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

App unit test. More...

#include "asterisk.h"
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/test.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
Include dependency graph for test_app.c:

Go to the source code of this file.

Macros

#define BASE_GROUP   "a group"
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (options_parsing)
 
 AST_TEST_DEFINE (app_group)
 
static int load_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "App unit tests" , .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

App unit test.

Author
Jeff Peeler jpeel.nosp@m.er@d.nosp@m.igium.nosp@m..com

Definition in file test_app.c.

Macro Definition Documentation

◆ BASE_GROUP

#define BASE_GROUP   "a group"

Definition at line 40 of file test_app.c.

Referenced by AST_TEST_DEFINE().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 238 of file test_app.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 238 of file test_app.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 238 of file test_app.c.

◆ AST_TEST_DEFINE() [1/2]

AST_TEST_DEFINE ( options_parsing  )

Definition at line 42 of file test_app.c.

References ARRAY_LEN, AST_APP_OPTION_ARG, AST_APP_OPTIONS, ast_app_parse_options(), ast_app_parse_options64(), ast_copy_string(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, sip_to_pjsip::info(), OPT_ARG_ARRAY_SIZE, options, parse(), string, TEST_EXECUTE, and TEST_INIT.

43 {
44  enum test_option_flags {
45  OPT_SIMPLE,
46  OPT_WITHQUOTES,
47  OPT_WITHBACKSLASH,
48  };
49  enum test_option_args {
50  OPT_ARG_SIMPLE,
51  OPT_ARG_WITHQUOTES,
52  OPT_ARG_WITHBACKSLASH,
54  };
56  AST_APP_OPTION_ARG('a', OPT_SIMPLE, OPT_ARG_SIMPLE),
57  AST_APP_OPTION_ARG('b', OPT_WITHQUOTES, OPT_ARG_WITHQUOTES),
58  AST_APP_OPTION_ARG('c', OPT_WITHBACKSLASH, OPT_ARG_WITHBACKSLASH),
59  });
60  struct ast_flags opts = { 0, };
61  struct ast_flags64 opts64 = { 0, };
62  char *opt_args[OPT_ARG_ARRAY_SIZE];
63  struct {
64  const char *string;
65  const char *parse[3];
66  } options[] = {
67  { "a(simple)b(\"quoted\")c(back\\slash)", { "simple", "quoted", "backslash", }, },
68  { "b(\"((())))\")a(simple)c(back\\)slash)", { "simple", "((())))", "back)slash", }, },
69  { "b(\"((\\\"\\)\\(\")a(simple)c(back\\\"\\)\\(\\\"slash)", { "simple", "((\"\\)\\(", "back\")(\"slash", }, },
70  };
71  int i, j, res = AST_TEST_PASS;
72  char buffer[256];
73 
74  switch (cmd) {
75  case TEST_INIT:
76  info->name = "options_parsing";
77  info->category = "/main/app/";
78  info->summary = "App options unit test";
79  info->description =
80  "This tests the options parsing code to ensure that it behaves as expected";
81  return AST_TEST_NOT_RUN;
82  case TEST_EXECUTE:
83  break;
84  }
85 
86  for (i = 0; i < ARRAY_LEN(options); i++) {
87  ast_copy_string(buffer, options[i].string, sizeof(buffer));
88 
89  if (ast_app_parse_options(test_options, &opts, opt_args, buffer)) {
90  ast_test_status_update(test, "ast_app_parse_options() of '%s' failed\n", options[i].string);
91  res = AST_TEST_FAIL;
92  } else {
93  /* Check arguments for success */
94  for (j = 0; j < 3; j++) {
95  if (strcmp(opt_args[j], options[i].parse[j])) {
96  ast_test_status_update(test, "Parse of option %c from '%s' produced '%s', "
97  "but it should have produced '%s'\n",
98  'a' + j, options[i].string, opt_args[j], options[i].parse[j]);
99  res = AST_TEST_FAIL;
100  }
101  }
102  }
103 
104  ast_copy_string(buffer, options[i].string, sizeof(buffer));
105  if (ast_app_parse_options64(test_options, &opts64, opt_args, buffer)) {
106  ast_test_status_update(test, "ast_app_parse_options64() of '%s' failed\n", options[i].string);
107  res = AST_TEST_FAIL;
108  } else {
109  /* Check arguments for success */
110  for (j = 0; j < 3; j++) {
111  if (strcmp(opt_args[j], options[i].parse[j])) {
112  ast_test_status_update(test, "Parse of option %c from '%s' produced '%s', "
113  "but it should have produced '%s'\n",
114  'a' + j, options[i].string, opt_args[j], options[i].parse[j]);
115  res = AST_TEST_FAIL;
116  }
117  }
118  }
119  }
120 
121  return res;
122 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
const char * string
Definition: presencestate.c:71
Structure used to handle a large number of boolean flags == used only in app_dial?
Definition: utils.h:204
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
int ast_app_parse_options64(const struct ast_app_option *options, struct ast_flags64 *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2911
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
def info(msg)
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
Structure used to handle boolean flags.
Definition: utils.h:199
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static struct test_options options

◆ AST_TEST_DEFINE() [2/2]

AST_TEST_DEFINE ( app_group  )

Definition at line 124 of file test_app.c.

References ARRAY_LEN, ast_app_group_match_get_count(), ast_app_group_set_channel(), ast_assert, ast_channel_alloc, ast_channel_unlock, ast_hangup(), AST_STATE_DOWN, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, BASE_GROUP, sip_to_pjsip::info(), NULL, TEST_EXECUTE, and TEST_INIT.

125 {
126  struct ast_channel *test_channel1 = NULL;
127  struct ast_channel *test_channel2 = NULL;
128  struct ast_channel *test_channel3 = NULL;
129  struct ast_channel *test_channel4 = NULL;
130 
131  static const char group1_full[] = BASE_GROUP "groupgroup";
132  static const char group2_full[] = BASE_GROUP "Groupgroup";
133  static const char regex1[] = "gr"; /* matches everything */
134  static const char regex2[] = "(group){2}$"; /* matches only group1_full */
135  static const char regex3[] = "[:ascii:]"; /* matches everything */
136  static const char regex4[] = "^(NOMATCH)"; /* matches nothing */
137  static const char category1_full[] = BASE_GROUP "@a_category"; /* categories shouldn't have spaces */
138  static const char category2_full[] = BASE_GROUP "@another!Category";
139  static const char regex5[] = "(gory)$"; /* matches both categories */
140  static const char regex6[] = "[A-Z]+"; /* matches only category2_full */
141  static const char regex7[] = "[["; /* not valid syntax, yes an expected warning will be displayed */
142  static enum ast_test_result_state res = AST_TEST_PASS;
143  static const struct group_test_params {
144  const char *groupmatch;
145  const char *category;
146  int expected;
147  } subtests[] = {
148  { regex1, "", 4 },
149  { regex2, "", 1 },
150  { regex3, "", 4 },
151  { regex4, "", 0 },
152  { BASE_GROUP, regex5, 2 },
153  { BASE_GROUP, regex6, 1 },
154  /* this test is expected to generate a warning message from the invalid regex */
155  { BASE_GROUP, regex7, 0 }
156  };
157  int i;
158  int returned_count;
159 
160  switch (cmd) {
161  case TEST_INIT:
162  info->name = "app_group";
163  info->category = "/main/app/";
164  info->summary = "App group unit test";
165  info->description =
166  "This tests various app group functionality";
167  return AST_TEST_NOT_RUN;
168  case TEST_EXECUTE:
169  break;
170  }
171 
172  ast_test_status_update(test, "Creating test channels with the following groups:\n"
173  "'%s', '%s', '%s', '%s'\n", group1_full, group2_full, category1_full, category2_full);
174 
175  if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
176  NULL, NULL, NULL, NULL, 0, "TestChannel1"))) {
177  goto exit_group_test;
178  }
179  ast_channel_unlock(test_channel1);
180  if (!(test_channel2 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
181  NULL, NULL, NULL, NULL, 0, "TestChannel2"))) {
182  goto exit_group_test;
183  }
184  ast_channel_unlock(test_channel2);
185  if (!(test_channel3 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
186  NULL, NULL, NULL, NULL, 0, "TestChannel3"))) {
187  goto exit_group_test;
188  }
189  ast_channel_unlock(test_channel3);
190  if (!(test_channel4 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
191  NULL, NULL, NULL, NULL, 0, "TestChannel4"))) {
192  goto exit_group_test;
193  }
194  ast_channel_unlock(test_channel4);
195 
196  ast_app_group_set_channel(test_channel1, group1_full);
197  ast_app_group_set_channel(test_channel2, group2_full);
198  ast_app_group_set_channel(test_channel3, category1_full);
199  ast_app_group_set_channel(test_channel4, category2_full);
200 
201  for (i = 0; i < ARRAY_LEN(subtests); i++) {
202  ast_assert(subtests[i].groupmatch != NULL || subtests[i].category != NULL);
203  returned_count = ast_app_group_match_get_count(subtests[i].groupmatch, subtests[i].category);
204 
205  if (subtests[i].expected != returned_count) {
206  ast_test_status_update(test, "(Subtest %d) Expected %d matches but found %d when examining group:'%s' category:'%s'\n",
207  i + 1, subtests[i].expected, returned_count, subtests[i].groupmatch, subtests[i].category);
208  res = AST_TEST_FAIL;
209  goto exit_group_test;
210  } else {
211  ast_test_status_update(test, "(Subtest %d) Found %d matches as expected when examining group:'%s' category:'%s'\n",
212  i + 1, subtests[i].expected, subtests[i].groupmatch, subtests[i].category);
213  }
214  }
215 
216 exit_group_test:
217  ast_hangup(test_channel1);
218  ast_hangup(test_channel2);
219  ast_hangup(test_channel3);
220  ast_hangup(test_channel4);
221  return res;
222 }
Main Channel structure associated with a channel.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define BASE_GROUP
Definition: test_app.c:40
def info(msg)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
int ast_app_group_match_get_count(const char *groupmatch, const char *category)
Get the current channel count of all groups that match the specified pattern and category.
Definition: main/app.c:2103
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
int ast_app_group_set_channel(struct ast_channel *chan, const char *data)
Set the group for a channel, splitting the provided data into group and category, if specified...
Definition: main/app.c:2036
ast_test_result_state
Definition: test.h:200

◆ load_module()

static int load_module ( void  )
static

Definition at line 231 of file test_app.c.

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

232 {
233  AST_TEST_REGISTER(app_group);
234  AST_TEST_REGISTER(options_parsing);
236 }
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 224 of file test_app.c.

References AST_TEST_UNREGISTER.

225 {
226  AST_TEST_UNREGISTER(app_group);
227  AST_TEST_UNREGISTER(options_parsing);
228  return 0;
229 }
#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 = "App unit tests" , .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 238 of file test_app.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 238 of file test_app.c.