Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
test_pbx.c File Reference

PBX Tests. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/test.h"
#include <signal.h>
Include dependency graph for test_pbx.c:

Go to the source code of this file.

Data Structures

struct  exten_info
 an extension to add to our context More...
 
struct  pbx_test_pattern
 

Macros

#define MAX_PRIORITIES   10
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (pattern_match_test)
 
 AST_TEST_DEFINE (segv)
 
 AST_TEST_DEFINE (call_assert)
 
 AST_TEST_DEFINE (call_backtrace)
 
static int load_module (void)
 
static int test_exten (const struct pbx_test_pattern *test_pattern, struct ast_test *test, int new_engine)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PBX test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

PBX Tests.

Author
Mark Michelson mmich.nosp@m.elso.nosp@m.n@dig.nosp@m.ium..nosp@m.com

This module will run some PBX tests.

Definition in file test_pbx.c.

Macro Definition Documentation

◆ MAX_PRIORITIES

#define MAX_PRIORITIES   10

If we determine that we really need to be able to register more than 10 priorities for a single extension, then fine, we can do that later.

Definition at line 48 of file test_pbx.c.

Referenced by AST_TEST_DEFINE().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 404 of file test_pbx.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 404 of file test_pbx.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 404 of file test_pbx.c.

◆ AST_TEST_DEFINE() [1/4]

AST_TEST_DEFINE ( pattern_match_test  )

Definition at line 188 of file test_pbx.c.

References ARRAY_LEN, ast_add_extension(), ast_context_add_include(), ast_context_destroy(), ast_context_find_or_create(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, exten_info::cid, cleanup(), exten_info::context, contexts, exten_info::exten, sip_to_pjsip::info(), MAX_PRIORITIES, NULL, exten_info::num_priorities, pbx_set_extenpatternmatchnew(), exten_info::priorities, priority, registrar, TEST_EXECUTE, test_exten(), and TEST_INIT.

189 {
190  static const char registrar[] = "test_pbx";
192  static const char TEST_PATTERN[] = "test_pattern";
193  static const char TEST_PATTERN_INCLUDE[] = "test_pattern_include";
194  int i, j;
195 
196  /* The array of contexts to register for our test.
197  * To add more contexts, just add more rows to this array.
198  */
199  struct {
200  const char * context_string;
201  } contexts[] = {
202  { TEST_PATTERN, },
203  { TEST_PATTERN_INCLUDE, },
204  };
205 
206  /*
207  * Map to indicate which contexts should be included inside
208  * other contexts. The first context listed will include
209  * the second context listed.
210  *
211  * To add more inclusions, add new rows to this array.
212  */
213  const struct {
214  const char *outer_context;
215  const char *inner_context;
216  } context_includes[] = {
217  { TEST_PATTERN, TEST_PATTERN_INCLUDE },
218  };
219 
220  /* The array of extensions to add to our test context.
221  * For more information about the individual fields, see
222  * the doxygen for struct exten_info.
223  *
224  * To add new extensions to the test, simply add new rows
225  * to this array. All extensions will automatically be
226  * added when the test is run.
227  */
228  const struct exten_info extens[] = {
229  [0] = { TEST_PATTERN, "_2.", NULL, 1, { 1 } },
230  [1] = { TEST_PATTERN, "2000", NULL, 1, { 1 } },
231  [2] = { TEST_PATTERN_INCLUDE, "2000", NULL, 1, { 2 } },
232  };
233 
234  /* This array contains our test material. See the doxygen
235  * for struct pbx_test_pattern for more information on each
236  * component.
237  *
238  * To add more test cases, add more lines to this array. Each
239  * case will be tested automatically when the test is run.
240  */
241  const struct pbx_test_pattern tests[] = {
242  { TEST_PATTERN, "200", NULL, 1, &extens[0] },
243  { TEST_PATTERN, "2000", NULL, 1, &extens[1] },
244  { TEST_PATTERN, "2000", NULL, 2, &extens[2] },
245  { TEST_PATTERN_INCLUDE, "2000", NULL, 2, &extens[2] },
246  };
247 
248  switch (cmd) {
249  case TEST_INIT:
250  info->name = "pattern_match_test";
251  info->category = "/main/pbx/";
252  info->summary = "Test pattern matching";
253  info->description = "Create a context with a bunch of extensions within. Then attempt\n"
254  "to match some strings to the extensions.";
255  return AST_TEST_NOT_RUN;
256  case TEST_EXECUTE:
257  break;
258  }
259 
260  /* Step one is to build the dialplan.
261  *
262  * We iterate first through the contexts array to build
263  * all the contexts we'll need. Then, we iterate over the
264  * extens array to add all the extensions to the appropriate
265  * contexts.
266  */
267 
268  for (i = 0; i < ARRAY_LEN(contexts); ++i) {
269  if (!ast_context_find_or_create(NULL, NULL, contexts[i].context_string, registrar)) {
270  ast_test_status_update(test, "Failed to create context %s\n", contexts[i].context_string);
271  res = AST_TEST_FAIL;
272  goto cleanup;
273  }
274  }
275 
276  for (i = 0; i < ARRAY_LEN(context_includes); ++i) {
277  if (ast_context_add_include(context_includes[i].outer_context,
278  context_includes[i].inner_context, registrar)) {
279  ast_test_status_update(test, "Failed to include context %s inside context %s\n",
280  context_includes[i].inner_context, context_includes[i].outer_context);
281  res = AST_TEST_FAIL;
282  goto cleanup;
283  }
284  }
285 
286  for (i = 0; i < ARRAY_LEN(extens); ++i) {
287  int priority;
288  if (extens[i].num_priorities > MAX_PRIORITIES) {
289  ast_test_status_update(test, "Invalid number of priorities specified for extension %s."
290  "Max is %d, but we requested %d. Test failed\n",
291  extens[i].exten, MAX_PRIORITIES, extens[i].num_priorities);
292  res = AST_TEST_FAIL;
293  goto cleanup;
294  }
295  for (priority = 0; priority < extens[i].num_priorities; ++priority) {
296  if (ast_add_extension(extens[i].context, 0, extens[i].exten, extens[i].priorities[priority],
297  NULL, extens[i].cid, "Noop", (void *) extens[i].exten, NULL, registrar)) {
298  ast_test_status_update(test, "Failed to add extension %s, priority %d, to context %s."
299  "Test failed\n", extens[i].exten, extens[i].priorities[priority], extens[i].context);
300  res = AST_TEST_FAIL;
301  goto cleanup;
302  }
303  }
304  }
305 
306  /* At this stage, the dialplan is built. Now we iterate over
307  * the tests array to attempt to find each of the specified
308  * extensions with the old and new pattern matching engines.
309  */
310  for (j = 0; j < 2; j++) {
312  for (i = 0; i < ARRAY_LEN(tests); ++i) {
313  if (test_exten(&tests[i], test, j)) {
314  res = AST_TEST_FAIL;
315  break;
316  }
317  }
318  }
319 
320 cleanup:
321  ast_context_destroy(NULL, registrar);
322 
323  return res;
324 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define NULL
Definition: resample.c:96
static int priority
int ast_context_add_include(const char *context, const char *include, const char *registrar)
Add a context include.
Definition: pbx.c:6706
#define MAX_PRIORITIES
Definition: test_pbx.c:48
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
int pbx_set_extenpatternmatchnew(int newval)
Definition: pbx.c:4781
def info(msg)
struct ast_context * contexts
Definition: extconf.c:4483
const int num_priorities
Number of priorities.
Definition: test_pbx.c:95
static char * registrar
Definition: pbx_ael.c:78
int extens
Definition: ael_main.c:93
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
an extension to add to our context
Definition: test_pbx.c:53
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:6970
Definition: test.c:104
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: conf2ael.c:625
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6198
static int test_exten(const struct pbx_test_pattern *test_pattern, struct ast_test *test, int new_engine)
Definition: test_pbx.c:156
ast_test_result_state
Definition: test.h:200

◆ AST_TEST_DEFINE() [2/4]

AST_TEST_DEFINE ( segv  )

Definition at line 326 of file test_pbx.c.

References AST_TEST_FAIL, AST_TEST_NOT_RUN, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

327 {
328  switch (cmd) {
329  case TEST_INIT:
330  info->name = "RAISE_SEGV";
331  info->category = "/DO_NOT_RUN/";
332  info->summary = "RAISES SEGV!!! (will only be run if explicitly called)";
333  info->description = "RAISES SEGV!!! (will only be run if explicitly called). "
334  "This test is mainly used for testing CI and tool failure scenarios.";
335  info->explicit_only = 1;
336  return AST_TEST_NOT_RUN;
337  case TEST_EXECUTE:
338  break;
339  }
340 
341  raise(SIGSEGV);
342 
343  return AST_TEST_FAIL;
344 }
def info(msg)

◆ AST_TEST_DEFINE() [3/4]

AST_TEST_DEFINE ( call_assert  )

Definition at line 346 of file test_pbx.c.

References ast_assert, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

347 {
348  switch (cmd) {
349  case TEST_INIT:
350  info->name = "CALL_ASSERT";
351  info->category = "/DO_NOT_RUN/";
352  info->summary = "Calls ast_asert()!!! (will only be run if explicitly called)";
353  info->description = "Calls ast_asert()!!! (will only be run if explicitly called). "
354  "This test is mainly used for testing CI and tool failure scenarios.";
355  info->explicit_only = 1;
356  return AST_TEST_NOT_RUN;
357  case TEST_EXECUTE:
358  break;
359  }
360 
361  ast_assert(0);
362 
363  return AST_TEST_PASS;
364 }
#define ast_assert(a)
Definition: utils.h:695
def info(msg)

◆ AST_TEST_DEFINE() [4/4]

AST_TEST_DEFINE ( call_backtrace  )

Definition at line 366 of file test_pbx.c.

References ast_log_backtrace(), AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

367 {
368  switch (cmd) {
369  case TEST_INIT:
370  info->name = "CALL_BACKTRACE";
371  info->category = "/DO_NOT_RUN/";
372  info->summary = "Calls ast_log_backtrace()!!! (will only be run if explicitly called)";
373  info->description = "Calls ast_log_backtrace()!!! (will only be run if explicitly called). "
374  "This test is mainly used for testing CI and tool failure scenarios.";
375  info->explicit_only = 1;
376  return AST_TEST_NOT_RUN;
377  case TEST_EXECUTE:
378  break;
379  }
380 
382 
383  return AST_TEST_PASS;
384 }
void ast_log_backtrace(void)
Log a backtrace of the current thread&#39;s execution stack to the Asterisk log.
Definition: logger.c:2158
def info(msg)

◆ load_module()

static int load_module ( void  )
static

Definition at line 395 of file test_pbx.c.

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

396 {
397  AST_TEST_REGISTER(pattern_match_test);
398  AST_TEST_REGISTER(segv);
399  AST_TEST_REGISTER(call_assert);
400  AST_TEST_REGISTER(call_backtrace);
402 }
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

◆ test_exten()

static int test_exten ( const struct pbx_test_pattern test_pattern,
struct ast_test test,
int  new_engine 
)
static

Definition at line 156 of file test_pbx.c.

References ast_canmatch_extension(), ast_get_extension_cidmatch(), ast_get_extension_name(), ast_test_status_update, exten_info::cid, pbx_test_pattern::context, E_MATCH, exten_info::exten, pbx_test_pattern::exten, NULL, pbx_find_extension(), pbx_test_pattern::priority, pbx_test_pattern::test_cid, and pbx_test_pattern::test_exten.

Referenced by AST_TEST_DEFINE().

157 {
158  struct pbx_find_info pfi = { { 0 }, };
159  struct ast_exten *exten;
160  if (!(exten = pbx_find_extension(NULL, NULL, &pfi, test_pattern->context,
161  test_pattern->test_exten, test_pattern->priority, NULL,
162  test_pattern->test_cid, E_MATCH))) {
163  ast_test_status_update(test, "Cannot find extension %s in context %s with the %s pattern match engine. "
164  "Test failed.\n", test_pattern->test_exten, test_pattern->context, (new_engine ? "new" : "old"));
165  return -1;
166  }
167  if (strcmp(ast_get_extension_name(exten), test_pattern->exten->exten)) {
168  ast_test_status_update(test, "Expected extension %s but got extension %s instead with the %s pattern match engine. "
169  "Test failed.\n", test_pattern->exten->exten, ast_get_extension_name(exten), (new_engine ? "new" : "old"));
170  return -1;
171  }
172  if (test_pattern->test_cid && strcmp(ast_get_extension_cidmatch(exten), test_pattern->test_cid)) {
173  ast_test_status_update(test, "Expected CID match %s but got CID match %s instead with the %s pattern match engine. "
174  "Test failed.\n", test_pattern->exten->cid, ast_get_extension_cidmatch(exten), (new_engine ? "new" : "old"));
175  return -1;
176  }
177  if (!ast_canmatch_extension(NULL, test_pattern->context, test_pattern->test_exten,
178  test_pattern->priority, test_pattern->test_cid)) {
179  ast_test_status_update(test, "Partial match failed for extension %s in context %s with the %s pattern match engine. "
180  "Test failed.\n", test_pattern->test_exten, test_pattern->context, (new_engine ? "new" : "old"));
181  return -1;
182  }
183  ast_test_status_update(test, "Successfully matched %s to exten %s in context %s with the %s pattern match engine\n",
184  test_pattern->test_exten, test_pattern->exten->exten, test_pattern->context, (new_engine ? "new" : "old"));
185  return 0;
186 }
const struct exten_info * exten
Expected extension match.
Definition: test_pbx.c:153
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:237
const char * cid
CID match.
Definition: test_pbx.c:85
const char * test_cid
Test CID match.
Definition: test_pbx.c:138
#define NULL
Definition: resample.c:96
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4194
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
const char * ast_get_extension_cidmatch(struct ast_exten *e)
Definition: pbx.c:8591
const char * test_exten
Test extension number.
Definition: test_pbx.c:128
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8548
const char * context
Test context.
Definition: test_pbx.c:118
const char * exten
Extension pattern.
Definition: test_pbx.c:73
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: ael_main.c:152
const int priority
The priority to find.
Definition: test_pbx.c:142

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 386 of file test_pbx.c.

References AST_TEST_UNREGISTER.

387 {
388  AST_TEST_UNREGISTER(call_backtrace);
389  AST_TEST_UNREGISTER(call_assert);
390  AST_TEST_UNREGISTER(segv);
391  AST_TEST_UNREGISTER(pattern_match_test);
392  return 0;
393 }
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PBX test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 404 of file test_pbx.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 404 of file test_pbx.c.