Asterisk - The Open Source Telephony Project  18.5.0
test_config.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * Mark Michelson <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief Configuration unit tests
22  *
23  * \author Mark Michelson <[email protected]>
24  *
25  */
26 
27 /*** MODULEINFO
28  <depend>TEST_FRAMEWORK</depend>
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #include <math.h> /* HUGE_VAL */
35 #include <sys/stat.h>
36 
37 #include "asterisk/config.h"
38 #include "asterisk/module.h"
39 #include "asterisk/test.h"
40 #include "asterisk/paths.h"
42 #include "asterisk/netsock2.h"
43 #include "asterisk/acl.h"
44 #include "asterisk/app.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/frame.h"
47 #include "asterisk/utils.h"
48 #include "asterisk/logger.h"
49 #include "asterisk/format_cap.h"
50 
51 #define CONFIG_FILE "test_config.conf"
52 #define CONFIG_INCLUDE_FILE "test_config_include.conf"
53 
54 /*
55  * This builds the folowing config:
56  * [Capitals]
57  * Germany = Berlin
58  * China = Beijing
59  * Canada = Ottawa
60  *
61  * [Protagonists]
62  * 1984 = Winston Smith
63  * Green Eggs And Ham = Sam I Am
64  * The Kalevala = Vainamoinen
65  *
66  * This config is used for all tests below.
67  */
68 const char cat1[] = "Capitals";
69 const char cat1varname1[] = "Germany";
70 const char cat1varvalue1[] = "Berlin";
71 const char cat1varname2[] = "China";
72 const char cat1varvalue2[] = "Beijing";
73 const char cat1varname3[] = "Canada";
74 const char cat1varvalue3[] = "Ottawa";
75 
76 const char cat2[] = "Protagonists";
77 const char cat2varname1[] = "1984";
78 const char cat2varvalue1[] = "Winston Smith";
79 const char cat2varname2[] = "Green Eggs And Ham";
80 const char cat2varvalue2[] = "Sam I Am";
81 const char cat2varname3[] = "The Kalevala";
82 const char cat2varvalue3[] = "Vainamoinen";
83 
84 struct pair {
85  const char *name;
86  const char *val;
87 };
88 
89 struct association {
90  const char *category;
91  struct pair vars[3];
92 } categories [] = {
93  { cat1,
94  {
98  }
99  },
100  { cat2,
101  {
105  }
106  },
107 };
108 
109 /*!
110  * \brief Build ast_config struct from above definitions
111  *
112  * \retval NULL Failed to build the config
113  * \retval non-NULL An ast_config struct populated with data
114  */
115 static struct ast_config *build_cfg(void)
116 {
117  struct ast_config *cfg;
118  struct association *cat_iter;
119  struct pair *var_iter;
120  size_t i;
121  size_t j;
122 
123  cfg = ast_config_new();
124  if (!cfg) {
125  goto fail;
126  }
127 
128  for (i = 0; i < ARRAY_LEN(categories); ++i) {
129  struct ast_category *cat;
130  cat_iter = &categories[i];
131 
132  cat = ast_category_new(cat_iter->category, "", 999999);
133  if (!cat) {
134  goto fail;
135  }
136  ast_category_append(cfg, cat);
137 
138  for (j = 0; j < ARRAY_LEN(cat_iter->vars); ++j) {
139  struct ast_variable *var;
140  var_iter = &cat_iter->vars[j];
141 
142  var = ast_variable_new(var_iter->name, var_iter->val, "");
143  if (!var) {
144  goto fail;
145  }
146  ast_variable_append(cat, var);
147  }
148  }
149 
150  return cfg;
151 
152 fail:
153  ast_config_destroy(cfg);
154  return NULL;
155 }
156 
157 /*!
158  * \brief Tests that the contents of an ast_config is what is expected
159  *
160  * \param cfg Config to test
161  * \retval -1 Failed to pass a test
162  * \retval 0 Config passes checks
163  */
164 static int test_config_validity(struct ast_config *cfg)
165 {
166  int i;
167  const char *cat_iter = NULL;
168  /* Okay, let's see if the correct content is there */
169  for (i = 0; i < ARRAY_LEN(categories); ++i) {
170  struct ast_variable *var = NULL;
171  size_t j;
172  cat_iter = ast_category_browse(cfg, cat_iter);
173  if (strcmp(cat_iter, categories[i].category)) {
174  ast_log(LOG_ERROR, "Category name mismatch, %s does not match %s\n", cat_iter, categories[i].category);
175  return -1;
176  }
177  for (j = 0; j < ARRAY_LEN(categories[i].vars); ++j) {
178  var = var ? var->next : ast_variable_browse(cfg, cat_iter);
179  if (strcmp(var->name, categories[i].vars[j].name)) {
180  ast_log(LOG_ERROR, "Variable name mismatch, %s does not match %s\n", var->name, categories[i].vars[j].name);
181  return -1;
182  }
183  if (strcmp(var->value, categories[i].vars[j].val)) {
184  ast_log(LOG_ERROR, "Variable value mismatch, %s does not match %s\n", var->value, categories[i].vars[j].val);
185  return -1;
186  }
187  }
188  }
189  return 0;
190 }
191 
192 AST_TEST_DEFINE(copy_config)
193 {
195  struct ast_config *cfg = NULL;
196  struct ast_config *copy = NULL;
197 
198  switch (cmd) {
199  case TEST_INIT:
200  info->name = "copy_config";
201  info->category = "/main/config/";
202  info->summary = "Test copying configuration";
203  info->description =
204  "Ensure that variables and categories are copied correctly";
205  return AST_TEST_NOT_RUN;
206  case TEST_EXECUTE:
207  break;
208  }
209 
210  cfg = build_cfg();
211  if (!cfg) {
212  goto out;
213  }
214 
215  copy = ast_config_copy(cfg);
216  if (!copy) {
217  goto out;
218  }
219 
220  if (test_config_validity(copy) != 0) {
221  goto out;
222  }
223 
224  res = AST_TEST_PASS;
225 
226 out:
227  ast_config_destroy(cfg);
228  ast_config_destroy(copy);
229  return res;
230 }
231 
232 AST_TEST_DEFINE(config_basic_ops)
233 {
235  struct ast_config *cfg = NULL;
236  struct ast_category *cat = NULL;
237  struct ast_variable *var;
238  struct ast_variable *varlist;
239  char temp[32];
240  const char *cat_name;
241  const char *var_value;
242  int i;
243 
244  switch (cmd) {
245  case TEST_INIT:
246  info->name = "config_basic_ops";
247  info->category = "/main/config/";
248  info->summary = "Test basic config ops";
249  info->description = "Test basic config ops";
250  return AST_TEST_NOT_RUN;
251  case TEST_EXECUTE:
252  break;
253  }
254 
255  cfg = ast_config_new();
256  if (!cfg) {
257  return res;
258  }
259 
260  /* load the config */
261  for(i = 0; i < 5; i++) {
262  snprintf(temp, sizeof(temp), "test%d", i);
263  ast_category_append(cfg, ast_category_new(temp, "dummy", -1));
264  }
265 
266  /* test0 test1 test2 test3 test4 */
267  /* check the config has 5 elements */
268  i = 0;
269  cat = NULL;
270  while ((cat = ast_category_browse_filtered(cfg, NULL, cat, NULL))) {
271  snprintf(temp, sizeof(temp), "test%d", i);
272  if (strcmp(ast_category_get_name(cat), temp)) {
273  ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
274  goto out;
275  }
276  i++;
277  }
278  if (i != 5) {
279  ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
280  goto out;
281  }
282 
283  /* search for test2 */
284  cat = ast_category_get(cfg, "test2", NULL);
285  if (!cat || strcmp(ast_category_get_name(cat), "test2")) {
286  ast_test_status_update(test, "Get failed %s != %s\n", ast_category_get_name(cat), "test2");
287  goto out;
288  }
289 
290  /* delete test2 */
291  cat = ast_category_delete(cfg, cat);
292 
293  /* Now: test0 test1 test3 test4 */
294  /* make sure the curr category is test1 */
295  if (!cat || strcmp(ast_category_get_name(cat), "test1")) {
296  ast_test_status_update(test, "Delete failed %s != %s\n", ast_category_get_name(cat), "test1");
297  goto out;
298  }
299 
300  /* Now: test0 test1 test3 test4 */
301  /* make sure the test2 is not found */
302  cat = ast_category_get(cfg, "test2", NULL);
303  if (cat) {
304  ast_test_status_update(test, "Should not have found test2\n");
305  goto out;
306  }
307 
308  /* Now: test0 test1 test3 test4 */
309  /* make sure the sequence is correctly missing test2 */
310  i = 0;
311  cat = NULL;
312  while ((cat = ast_category_browse_filtered(cfg, NULL, cat, NULL))) {
313  snprintf(temp, sizeof(temp), "test%d", i);
314  if (strcmp(ast_category_get_name(cat), temp)) {
315  ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
316  goto out;
317  }
318  i++;
319  if (i == 2) {
320  i++;
321  }
322  }
323  if (i != 5) {
324  ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
325  goto out;
326  }
327 
328  /* insert test2 back in before test3 */
329  ast_category_insert(cfg, ast_category_new("test2", "dummy", -1), "test3");
330 
331  /* Now: test0 test1 test2 test3 test4 */
332  /* make sure the sequence is correct again */
333  i = 0;
334  cat = NULL;
335  while ((cat = ast_category_browse_filtered(cfg, NULL, cat, NULL))) {
336  snprintf(temp, sizeof(temp), "test%d", i);
337  if (strcmp(ast_category_get_name(cat), temp)) {
338  ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
339  goto out;
340  }
341  i++;
342  }
343  if (i != 5) {
344  ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
345  goto out;
346  }
347 
348  /* Now: test0 test1 test2 test3 test4 */
349  /* make sure non filtered browse still works */
350  i = 0;
351  cat_name = NULL;
352  while ((cat_name = ast_category_browse(cfg, cat_name))) {
353  snprintf(temp, sizeof(temp), "test%d", i);
354  if (strcmp(cat_name, temp)) {
355  ast_test_status_update(test, "%s != %s\n", cat_name, temp);
356  goto out;
357  }
358  i++;
359  }
360  if (i != 5) {
361  ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
362  goto out;
363  }
364 
365  /* append another test2 */
366  ast_category_append(cfg, ast_category_new("test2", "dummy", -1));
367  /* Now: test0 test1 test2 test3 test4 test2*/
368  /* make sure only test2's are returned */
369  i = 0;
370  cat = NULL;
371  while ((cat = ast_category_browse_filtered(cfg, "test2", cat, NULL))) {
372  if (strcmp(ast_category_get_name(cat), "test2")) {
373  ast_test_status_update(test, "Should have returned test2 instead of %s\n", ast_category_get_name(cat));
374  goto out;
375  }
376  i++;
377  }
378  /* make sure 2 test2's were found */
379  if (i != 2) {
380  ast_test_status_update(test, "Should have found 2 test2's %d\n", i);
381  goto out;
382  }
383 
384  /* Test in-flight deletion using ast_category_browse_filtered */
385  /* Now: test0 test1 test2 test3 test4 test2 */
386  /* Delete the middle test2 and continue */
387  cat = NULL;
388  for(i = 0; i < 5; i++) {
389  snprintf(temp, sizeof(temp), "test%d", i);
390  cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
391  cat_name = ast_category_get_name(cat);
392  if (strcmp(cat_name, temp)) {
393  ast_test_status_update(test, "Should have returned %s instead of %s: %d\n", temp, cat_name, i);
394  goto out;
395  }
396  if (i == 2) {
397  cat = ast_category_delete(cfg, cat);
398  }
399  }
400 
401  /* Now: test0 test3 test4 test2 */
402  /* delete the head item */
404  cat_name = ast_category_get_name(cat);
405  if (strcmp(cat_name, "test0")) {
406  ast_test_status_update(test, "Should have returned test0 instead of %s\n", cat_name);
407  goto out;
408  }
409  ast_category_delete(cfg, cat);
410  /* Now: test3 test4 test2 */
411 
412  /* make sure head got updated to the new first element */
414  cat_name = ast_category_get_name(cat);
415  if (strcmp(cat_name, "test1")) {
416  ast_test_status_update(test, "Should have returned test3 instead of %s\n", cat_name);
417  goto out;
418  }
419 
420  /* delete the tail item */
421  cat = ast_category_get(cfg, "test2", NULL);
422  cat_name = ast_category_get_name(cat);
423  if (strcmp(cat_name, "test2")) {
424  ast_test_status_update(test, "Should have returned test2 instead of %s\n", cat_name);
425  goto out;
426  }
427  ast_category_delete(cfg, cat);
428  /* Now: test3 test4 */
429 
430  /* There should now only be 2 elements in the list */
431  cat = NULL;
432  cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
433  cat_name = ast_category_get_name(cat);
434  if (strcmp(cat_name, "test1")) {
435  ast_test_status_update(test, "Should have returned test1 instead of %s\n", cat_name);
436  goto out;
437  }
438 
439  cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
440  cat_name = ast_category_get_name(cat);
441  if (strcmp(cat_name, "test3")) {
442  ast_test_status_update(test, "Should have returned test3 instead of %s\n", cat_name);
443  goto out;
444  }
445 
446  cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
447  cat_name = ast_category_get_name(cat);
448  if (strcmp(cat_name, "test4")) {
449  ast_test_status_update(test, "Should have returned test4 instead of %s\n", cat_name);
450  goto out;
451  }
452 
453  /* There should be nothing more */
454  cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
455  if (cat) {
456  ast_test_status_update(test, "Should not have returned anything\n");
457  goto out;
458  }
459 
460  /* Test ast_variable retrieve.
461  * Get the second category.
462  */
464  cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
465  cat_name = ast_category_get_name(cat);
466  var = ast_variable_new("aaa", "bbb0", "dummy");
467  if (!var) {
468  ast_test_status_update(test, "Couldn't allocate variable.\n");
469  goto out;
470  }
471  ast_variable_append(cat, var);
472 
473  /* Make sure we can retrieve with specific category name */
474  var_value = ast_variable_retrieve(cfg, cat_name, "aaa");
475  if (!var_value || strcmp(var_value, "bbb0")) {
476  ast_test_status_update(test, "Variable not found or wrong value.\n");
477  goto out;
478  }
479 
480  /* Make sure we can retrieve with NULL category name */
481  var_value = ast_variable_retrieve(cfg, NULL, "aaa");
482  if (!var_value || strcmp(var_value, "bbb0")) {
483  ast_test_status_update(test, "Variable not found or wrong value.\n");
484  goto out;
485  }
486 
487  /* Now test variable retrieve inside a browse loop
488  * with multiple categories of the same name
489  */
490  cat = ast_category_new("test3", "dummy", -1);
491  if (!cat) {
492  ast_test_status_update(test, "Couldn't allocate category.\n");
493  goto out;
494  }
495  var = ast_variable_new("aaa", "bbb1", "dummy");
496  if (!var) {
497  ast_test_status_update(test, "Couldn't allocate variable.\n");
498  goto out;
499  }
500  ast_variable_append(cat, var);
501  ast_category_append(cfg, cat);
502 
503  cat = ast_category_new("test3", "dummy", -1);
504  if (!cat) {
505  ast_test_status_update(test, "Couldn't allocate category.\n");
506  goto out;
507  }
508  var = ast_variable_new("aaa", "bbb2", "dummy");
509  if (!var) {
510  ast_test_status_update(test, "Couldn't allocate variable.\n");
511  goto out;
512  }
513  ast_variable_append(cat, var);
514  ast_category_append(cfg, cat);
515 
516  cat_name = NULL;
517  i = 0;
518  while ((cat_name = ast_category_browse(cfg, cat_name))) {
519  if (!strcmp(cat_name, "test3")) {
520  snprintf(temp, sizeof(temp), "bbb%d", i);
521 
522  var_value = ast_variable_retrieve(cfg, cat_name, "aaa");
523  if (!var_value || strcmp(var_value, temp)) {
524  ast_test_status_update(test, "Variable not found or wrong value %s.\n", var_value);
525  goto out;
526  }
527 
528  var = ast_variable_browse(cfg, cat_name);
529  if (!var->value || strcmp(var->value, temp)) {
530  ast_test_status_update(test, "Variable not found or wrong value %s.\n", var->value);
531  goto out;
532  }
533 
534  i++;
535  }
536  }
537  if (i != 3) {
538  ast_test_status_update(test, "There should have been 3 matches instead of %d.\n", i);
539  goto out;
540  }
541 
542  varlist = ast_variable_new("name1", "value1", "");
543  ast_variable_list_append_hint(&varlist, NULL, ast_variable_new("name1", "value2", ""));
544  ast_variable_list_append_hint(&varlist, NULL, ast_variable_new("name1", "value3", ""));
545 
546  var_value = ast_variable_find_in_list(varlist, "name1");
547  if (strcmp(var_value, "value1") != 0) {
548  ast_test_status_update(test, "Wrong variable retrieved %s.\n", var_value);
549  goto out;
550  }
551 
552  var_value = ast_variable_find_last_in_list(varlist, "name1");
553  if (strcmp(var_value, "value3") != 0) {
554  ast_test_status_update(test, "Wrong variable retrieved %s.\n", var_value);
555  goto out;
556  }
557 
558  res = AST_TEST_PASS;
559 
560 out:
561  ast_config_destroy(cfg);
562  return res;
563 }
564 
565 AST_TEST_DEFINE(config_filtered_ops)
566 {
568  struct ast_config *cfg = NULL;
569  struct ast_category *cat = NULL;
570  char temp[32];
571  const char *value;
572  int i;
573 
574  switch (cmd) {
575  case TEST_INIT:
576  info->name = "config_filtered_ops";
577  info->category = "/main/config/";
578  info->summary = "Test filtered config ops";
579  info->description = "Test filtered config ops";
580  return AST_TEST_NOT_RUN;
581  case TEST_EXECUTE:
582  break;
583  }
584 
585  cfg = ast_config_new();
586  if (!cfg) {
587  return res;
588  }
589 
590  /* load the config */
591  for(i = 0; i < 5; i++) {
592  snprintf(temp, sizeof(temp), "test%d", i);
593  cat = ast_category_new(temp, "dummy", -1);
594  ast_variable_insert(cat, ast_variable_new("type", "a", "dummy"), "0");
595  ast_category_append(cfg, cat);
596  }
597 
598  for(i = 0; i < 5; i++) {
599  snprintf(temp, sizeof(temp), "test%d", i);
600  cat = ast_category_new(temp, "dummy", -1);
601  ast_variable_insert(cat, ast_variable_new("type", "b", "dummy"), "0");
602  ast_category_append(cfg, cat);
603  }
604 
605  /* check the config has 5 elements for each type*/
606  i = 0;
607  cat = NULL;
608  while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "type=a"))) {
609  snprintf(temp, sizeof(temp), "test%d", i);
610  if (strcmp(ast_category_get_name(cat), temp)) {
611  ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
612  goto out;
613  }
614  value = ast_variable_find(cat, "type");
615  if (!value || strcmp(value, "a")) {
616  ast_test_status_update(test, "Type %s != %s\n", "a", value);
617  goto out;
618  }
619  i++;
620  }
621  if (i != 5) {
622  ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
623  goto out;
624  }
625 
626  i = 0;
627  cat = NULL;
628  while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "type=b"))) {
629  snprintf(temp, sizeof(temp), "test%d", i);
630  if (!cat || strcmp(ast_category_get_name(cat), temp)) {
631  ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
632  goto out;
633  }
634  value = ast_variable_find(cat, "type");
635  if (!value || strcmp(value, "b")) {
636  ast_test_status_update(test, "Type %s != %s\n", "b", value);
637  goto out;
638  }
639  i++;
640  }
641  if (i != 5) {
642  ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
643  goto out;
644  }
645 
646  /* Delete b3 and make sure it's gone and a3 is still there.
647  * Really this is a test of get since delete takes a specific category structure.
648  */
649  cat = ast_category_get(cfg, "test3", "type=b");
650  value = ast_variable_find(cat, "type");
651  if (strcmp(value, "b")) {
652  ast_test_status_update(test, "Type %s != %s\n", "b", value);
653  goto out;
654  }
655  ast_category_delete(cfg, cat);
656 
657  cat = ast_category_get(cfg, "test3", "type=b");
658  if (cat) {
659  ast_test_status_update(test, "Category b was not deleted.\n");
660  goto out;
661  }
662 
663  cat = ast_category_get(cfg, "test3", "type=a");
664  if (!cat) {
665  ast_test_status_update(test, "Category a was deleted.\n");
666  goto out;
667  }
668 
669  value = ast_variable_find(cat, "type");
670  if (strcmp(value, "a")) {
671  ast_test_status_update(test, "Type %s != %s\n", value, "a");
672  goto out;
673  }
674 
675  /* Basic regex stuff is handled by regcomp/regexec so not testing here.
676  * Still need to test multiple name/value pairs though.
677  */
678  ast_category_empty(cat);
679  ast_variable_insert(cat, ast_variable_new("type", "bx", "dummy"), "0");
680  ast_variable_insert(cat, ast_variable_new("e", "z", "dummy"), "0");
681 
682  cat = ast_category_get(cfg, "test3", "type=.,e=z");
683  if (!cat) {
684  ast_test_status_update(test, "Category not found.\n");
685  goto out;
686  }
687 
688  cat = ast_category_get(cfg, "test3", "type=.,e=zX");
689  if (cat) {
690  ast_test_status_update(test, "Category found.\n");
691  goto out;
692  }
693 
694  cat = ast_category_get(cfg, "test3", "TEMPLATE=restrict,type=.,e=z");
695  if (cat) {
696  ast_test_status_update(test, "Category found.\n");
697  goto out;
698  }
699 
700  res = AST_TEST_PASS;
701 
702 out:
703  ast_config_destroy(cfg);
704  return res;
705 }
706 
707 AST_TEST_DEFINE(config_template_ops)
708 {
710  struct ast_config *cfg = NULL;
711  struct ast_category *cat = NULL;
712  char temp[32];
713  const char *value;
714  int i;
715 
716  switch (cmd) {
717  case TEST_INIT:
718  info->name = "config_template_ops";
719  info->category = "/main/config/";
720  info->summary = "Test template config ops";
721  info->description = "Test template config ops";
722  return AST_TEST_NOT_RUN;
723  case TEST_EXECUTE:
724  break;
725  }
726 
727  cfg = ast_config_new();
728  if (!cfg) {
729  return res;
730  }
731 
732  /* load the config with 5 templates and 5 regular */
733  for(i = 0; i < 5; i++) {
734  snprintf(temp, sizeof(temp), "test%d", i);
735  cat = ast_category_new_template(temp, "dummy", -1);
736  ast_variable_insert(cat, ast_variable_new("type", "a", "dummy"), "0");
737  ast_category_append(cfg, cat);
738  }
739 
740  for(i = 0; i < 5; i++) {
741  snprintf(temp, sizeof(temp), "test%d", i);
742  cat = ast_category_new(temp, "dummy", -1);
743  ast_variable_insert(cat, ast_variable_new("type", "b", "dummy"), "0");
744  ast_category_append(cfg, cat);
745  }
746 
747  /* check the config has 5 template elements of type a */
748  i = 0;
749  cat = NULL;
750  while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "TEMPLATES=restrict,type=a"))) {
751  snprintf(temp, sizeof(temp), "test%d", i);
752  if (strcmp(ast_category_get_name(cat), temp)) {
753  ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
754  goto out;
755  }
756  value = ast_variable_find(cat, "type");
757  if (!value || strcmp(value, "a")) {
758  ast_test_status_update(test, "Type %s != %s\n", value, "a");
759  goto out;
760  }
761  i++;
762  }
763  if (i != 5) {
764  ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
765  goto out;
766  }
767 
768  /* Test again with 'include'. There should still only be 5 (type a) */
769  i = 0;
770  cat = NULL;
771  while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "TEMPLATES=include,type=a"))) {
772  snprintf(temp, sizeof(temp), "test%d", i);
773  if (strcmp(ast_category_get_name(cat), temp)) {
774  ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
775  goto out;
776  }
777  value = ast_variable_find(cat, "type");
778  if (!value || strcmp(value, "a")) {
779  ast_test_status_update(test, "Type %s != %s\n", value, "a");
780  goto out;
781  }
782  i++;
783  }
784  if (i != 5) {
785  ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
786  goto out;
787  }
788 
789  /* Test again with 'include' but no type. There should now be 10 (type a and type b) */
790  i = 0;
791  cat = NULL;
792  while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "TEMPLATES=include"))) {
793  i++;
794  }
795  if (i != 10) {
796  ast_test_status_update(test, "There were %d matches instead of 10.\n", i);
797  goto out;
798  }
799 
800  /* Test again with 'restrict' and type b. There should 0 */
801  i = 0;
802  cat = NULL;
803  while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "TEMPLATES=restrict,type=b"))) {
804  i++;
805  }
806  if (i != 0) {
807  ast_test_status_update(test, "There were %d matches instead of 0.\n", i);
808  goto out;
809  }
810 
811  res = AST_TEST_PASS;
812 
813 out:
814  ast_config_destroy(cfg);
815  return res;
816 }
817 
818 /*!
819  * \brief Write the config file to disk
820  *
821  * This is necessary for testing config hooks since
822  * they are only triggered when a config is read from
823  * its intended storage medium
824  */
825 static int write_config_file(void)
826 {
827  int i;
828  FILE *config_file;
829  char filename[PATH_MAX];
830 
831  snprintf(filename, sizeof(filename), "%s/%s",
833  config_file = fopen(filename, "w");
834 
835  if (!config_file) {
836  return -1;
837  }
838 
839  for (i = 0; i < ARRAY_LEN(categories); ++i) {
840  int j;
841  fprintf(config_file, "[%s]\n", categories[i].category);
842  for (j = 0; j < ARRAY_LEN(categories[i].vars); ++j) {
843  fprintf(config_file, "%s = %s\n",
844  categories[i].vars[j].name,
845  categories[i].vars[j].val);
846  }
847  }
848 
849  fclose(config_file);
850  return 0;
851 }
852 
853 /*!
854  * \brief Delete config file created by write_config_file
855  */
856 static void delete_config_file(void)
857 {
858  char filename[PATH_MAX];
859  snprintf(filename, sizeof(filename), "%s/%s",
861  unlink(filename);
862 }
863 
864 /*
865  * Boolean to indicate if the config hook has run
866  */
867 static int hook_run;
868 
869 /*
870  * Boolean to indicate if, when the hook runs, the
871  * data passed to it is what is expected
872  */
873 static int hook_config_sane;
874 
875 static int hook_cb(struct ast_config *cfg)
876 {
877  hook_run = 1;
878  if (test_config_validity(cfg) == 0) {
879  hook_config_sane = 1;
880  }
881  ast_config_destroy(cfg);
882  return 0;
883 }
884 
885 AST_TEST_DEFINE(config_save)
886 {
888  struct ast_flags config_flags = { 0 };
889  struct ast_config *cfg;
891  char include_filename[PATH_MAX];
892  struct stat config_stat;
893  off_t before_save;
894 
895  switch (cmd) {
896  case TEST_INIT:
897  info->name = "config_save";
898  info->category = "/main/config/";
899  info->summary = "Test config save";
900  info->description =
901  "Test configuration save.";
902  return AST_TEST_NOT_RUN;
903  case TEST_EXECUTE:
904  break;
905  }
906 
907  if (write_config_file()) {
908  ast_test_status_update(test, "Could not write initial config files\n");
909  return res;
910  }
911 
912  snprintf(config_filename, PATH_MAX, "%s/%s", ast_config_AST_CONFIG_DIR, CONFIG_FILE);
913  snprintf(include_filename, PATH_MAX, "%s/%s", ast_config_AST_CONFIG_DIR, CONFIG_INCLUDE_FILE);
914 
915  cfg = ast_config_load(CONFIG_FILE, config_flags);
916  if (!cfg) {
917  ast_test_status_update(test, "Could not load config\n");
918  goto out;
919  }
920 
921  /* We need to re-save to get the generator header */
922  if (ast_config_text_file_save(CONFIG_FILE, cfg, "TEST")) {
923  ast_test_status_update(test, "Unable to write files\n");
924  goto out;
925  }
926 
927  stat(config_filename, &config_stat);
928  before_save = config_stat.st_size;
929 
930  if (!ast_include_new(cfg, CONFIG_FILE, CONFIG_INCLUDE_FILE, 0, NULL, 4, include_filename, PATH_MAX)) {
931  ast_test_status_update(test, "Could not create include\n");
932  goto out;
933  }
934 
935  if (ast_config_text_file_save(CONFIG_FILE, cfg, "TEST")) {
936  ast_test_status_update(test, "Unable to write files\n");
937  goto out;
938  }
939 
940  stat(config_filename, &config_stat);
941  if (config_stat.st_size <= before_save) {
942  ast_test_status_update(test, "Did not save config file with #include\n");
943  goto out;
944  }
945 
946  res = AST_TEST_PASS;
947 
948 out:
949  ast_config_destroy(cfg);
950  unlink(config_filename);
951  unlink(include_filename);
952 
953  return res;
954 }
955 
956 AST_TEST_DEFINE(config_hook)
957 {
959  enum config_hook_flags hook_flags = { 0, };
960  struct ast_flags config_flags = { 0 };
961  struct ast_flags reload_flags = { CONFIG_FLAG_FILEUNCHANGED };
962  struct ast_config *cfg;
963 
964  switch (cmd) {
965  case TEST_INIT:
966  info->name = "config_hook";
967  info->category = "/main/config/";
968  info->summary = "Test config hooks";
969  info->description =
970  "Ensure that config hooks are called at approriate times,"
971  "not called at inappropriate times, and that all information"
972  "that should be present is present.";
973  return AST_TEST_NOT_RUN;
974  case TEST_EXECUTE:
975  break;
976  }
977 
979 
980  /*
981  * Register a config hook to run when CONFIG_FILE is loaded by this module
982  */
983  ast_config_hook_register("test_hook",
984  CONFIG_FILE,
985  AST_MODULE,
986  hook_flags,
987  hook_cb);
988 
989  /*
990  * Try loading the config file. This should result in the hook
991  * being called
992  */
993  cfg = ast_config_load(CONFIG_FILE, config_flags);
994  ast_config_destroy(cfg);
995  if (!hook_run || !hook_config_sane) {
996  ast_test_status_update(test, "Config hook either did not run or was given bad data!\n");
997  goto out;
998  }
999 
1000  /*
1001  * Now try loading the wrong config file but from the right module.
1002  * Hook should not run
1003  */
1004  hook_run = 0;
1005  cfg = ast_config_load("asterisk.conf", config_flags);
1006  ast_config_destroy(cfg);
1007  if (hook_run) {
1008  ast_test_status_update(test, "Config hook ran even though an incorrect file was specified.\n");
1009  goto out;
1010  }
1011 
1012  /*
1013  * Now try loading the correct config file but from the wrong module.
1014  * Hook should not run
1015  */
1016  hook_run = 0;
1017  cfg = ast_config_load2(CONFIG_FILE, "fake_module.so", config_flags);
1018  ast_config_destroy(cfg);
1019  if (hook_run) {
1020  ast_test_status_update(test, "Config hook ran even though an incorrect module was specified.\n");
1021  goto out;
1022  }
1023 
1024  /*
1025  * Now try loading the file correctly, but without any changes to the file.
1026  * Hook should not run
1027  */
1028  hook_run = 0;
1029  cfg = ast_config_load(CONFIG_FILE, reload_flags);
1030  /* Only destroy this cfg conditionally. Otherwise a crash happens. */
1031  if (cfg != CONFIG_STATUS_FILEUNCHANGED) {
1032  ast_config_destroy(cfg);
1033  }
1034  if (hook_run) {
1035  ast_test_status_update(test, "Config hook ran even though file contents had not changed\n");
1036  goto out;
1037  }
1038 
1039  res = AST_TEST_PASS;
1040 
1041 out:
1042  ast_config_hook_unregister("test_hook");
1044  return res;
1045 }
1046 
1047 enum {
1050 };
1051 
1052 #define TOOBIG_I32 "2147483649"
1053 #define TOOSMALL_I32 "-2147483649"
1054 #define TOOBIG_U32 "4294967297"
1055 #define TOOSMALL_U32 "-4294967297"
1056 #define DEFAULTVAL 42
1057 #define EPSILON 0.001
1058 
1059 #define TEST_PARSE(input, should_succeed, expected_result, flags, result, ...) do {\
1060  int __res = ast_parse_arg(input, (flags), result, ##__VA_ARGS__); \
1061  if (!__res == !should_succeed) { \
1062  ast_test_status_update(test, "ast_parse_arg failed on '%s'. %d/%d\n", input, __res, should_succeed); \
1063  ret = AST_TEST_FAIL; \
1064  } else { \
1065  if (((flags) & PARSE_TYPE) == PARSE_INT32) { \
1066  int32_t *r = (int32_t *) (void *) result; \
1067  int32_t e = (int32_t) expected_result; \
1068  if (*r != e) { \
1069  ast_test_status_update(test, "ast_parse_arg int32_t failed with %d != %d\n", *r, e); \
1070  ret = AST_TEST_FAIL; \
1071  } \
1072  } else if (((flags) & PARSE_TYPE) == PARSE_UINT32) { \
1073  uint32_t *r = (uint32_t *) (void *) result; \
1074  uint32_t e = (uint32_t) expected_result; \
1075  if (*r != e) { \
1076  ast_test_status_update(test, "ast_parse_arg uint32_t failed with %u != %u\n", *r, e); \
1077  ret = AST_TEST_FAIL; \
1078  } \
1079  } else if (((flags) & PARSE_TYPE) == PARSE_DOUBLE) { \
1080  double *r = (double *) (void *) result; \
1081  double e = (double) expected_result; \
1082  if (fabs(*r - e) > EPSILON) { \
1083  ast_test_status_update(test, "ast_parse_arg double failed with %f != %f\n", *r, e); \
1084  ret = AST_TEST_FAIL; \
1085  } \
1086  } else if (((flags) & PARSE_TYPE) == PARSE_TIMELEN) { \
1087  int *r = (int *) (void *) result; \
1088  int e = (int) expected_result; \
1089  if (*r != e) { \
1090  ast_test_status_update(test, "ast_parse_arg timelen failed with %d != %d\n", *r, e); \
1091  ret = AST_TEST_FAIL; \
1092  } \
1093  } \
1094  } \
1095  *(result) = DEFAULTVAL; \
1096 } while (0)
1097 
1098 AST_TEST_DEFINE(ast_parse_arg_test)
1099 {
1100  int ret = AST_TEST_PASS;
1101  int32_t int32_t_val = DEFAULTVAL;
1102  uint32_t uint32_t_val = DEFAULTVAL;
1103  int timelen_val = DEFAULTVAL;
1104  double double_val = DEFAULTVAL;
1105 
1106  switch (cmd) {
1107  case TEST_INIT:
1108  info->name = "ast_parse_arg";
1109  info->category = "/config/";
1110  info->summary = "Test the output of ast_parse_arg";
1111  info->description =
1112  "Ensures that ast_parse_arg behaves as expected";
1113  return AST_TEST_NOT_RUN;
1114  case TEST_EXECUTE:
1115  break;
1116  }
1117 
1118  /* int32 testing */
1119  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32, &int32_t_val);
1120  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32, &int32_t_val);
1121  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32, &int32_t_val);
1124  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
1125  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
1126  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
1127  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
1128  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
1129  TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
1130  TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
1131  TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
1132  TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
1133 
1134  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, 0, 200);
1135  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, -200, 100);
1136  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, -1, 0);
1137  TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, 0, 122);
1138  TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, -122, 100);
1139  TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, 1, 100);
1140  TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
1141  TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
1142  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
1143  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
1144  TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, 0, 200);
1145  TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, -200, 100);
1146  TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, -1, 0);
1147  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, 0, 122);
1148  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, -122, 100);
1149  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, 1, 100);
1150  TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
1151  TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
1152  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
1153  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
1154 
1155  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, 0, 200);
1156  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, -200, 100);
1157  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, -1, 0);
1158  TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, 0, 122);
1159  TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, -122, 100);
1160  TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, 1, 100);
1161  TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
1162  TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
1163  TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
1164  TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
1165  TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, 0, 200);
1166  TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, -200, 100);
1167  TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, -1, 0);
1168  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, 0, 122);
1169  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, -122, 100);
1170  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, 1, 100);
1171  TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
1172  TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
1173  TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
1174  TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
1175 
1176  /* uuint32 testing */
1177  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32, &uint32_t_val);
1178  TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
1179  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32, &uint32_t_val);
1182  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
1183  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
1184 
1185  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
1186  TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
1187  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
1188  TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
1189  TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
1190  TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
1191  TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
1192 
1193  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 200);
1194  TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 200);
1195  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 1);
1196 
1197  TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 122);
1198  TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 1, 100);
1199  TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
1200  TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
1201  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
1202  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
1203 
1204  TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 200);
1205  TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 200);
1206  TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 1);
1207 
1208  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 122);
1209  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 1, 100);
1210  TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
1211  TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
1212  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
1213  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
1214 
1215  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 200);
1216  TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 200);
1217  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 1);
1218  TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 122);
1219  TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 1, 100);
1220  TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
1221  TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
1222  TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
1223  TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
1224  TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 200);
1225  TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 100);
1226  TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 1);
1227  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 122);
1228  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 1, 100);
1229  TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
1230  TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
1231  TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
1232  TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
1233 
1234  TEST_PARSE(" -123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
1235 
1236  /* timelen testing */
1237  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_TIMELEN, &timelen_val, TIMELEN_MILLISECONDS);
1238  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_TIMELEN, &timelen_val, TIMELEN_MILLISECONDS);
1240  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_TIMELEN, &timelen_val, TIMELEN_MILLISECONDS);
1241  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_TIMELEN, &timelen_val, TIMELEN_MILLISECONDS);
1242 
1243  TEST_PARSE("123s", EXPECT_SUCCEED, 123000, PARSE_TIMELEN, &timelen_val, TIMELEN_MILLISECONDS);
1244  TEST_PARSE("-123s", EXPECT_SUCCEED, -123000, PARSE_TIMELEN, &timelen_val, TIMELEN_MILLISECONDS);
1245  TEST_PARSE("1m", EXPECT_SUCCEED, 60000, PARSE_TIMELEN, &timelen_val, TIMELEN_MILLISECONDS);
1246  TEST_PARSE("1", EXPECT_SUCCEED, 60000, PARSE_TIMELEN, &timelen_val, TIMELEN_MINUTES);
1247  TEST_PARSE("1h", EXPECT_SUCCEED, 3600000, PARSE_TIMELEN, &timelen_val, TIMELEN_MILLISECONDS);
1248  TEST_PARSE("1", EXPECT_SUCCEED, 3600000, PARSE_TIMELEN, &timelen_val, TIMELEN_HOURS);
1249 
1250  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_TIMELEN | PARSE_DEFAULT, &timelen_val, TIMELEN_MILLISECONDS, 7);
1251  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_TIMELEN | PARSE_DEFAULT, &timelen_val, TIMELEN_MILLISECONDS, 7);
1253  TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT, &timelen_val, TIMELEN_MILLISECONDS, 7);
1254  TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT, &timelen_val, TIMELEN_MILLISECONDS, 7);
1255 
1256  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_TIMELEN | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 0, 200);
1257  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_TIMELEN | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, -200, 100);
1260  TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_TIMELEN | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, -122, 100);
1262  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_TIMELEN | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, INT_MIN, INT_MAX);
1263  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_TIMELEN | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, INT_MIN, INT_MAX);
1265  TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_TIMELEN | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, -200, 100);
1267  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_TIMELEN | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 0, 122);
1268  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_TIMELEN | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, -122, 100);
1269  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_TIMELEN | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 1, 100);
1270  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_TIMELEN | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, INT_MIN, INT_MAX);
1271  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_TIMELEN | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, INT_MIN, INT_MAX);
1272 
1273  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, 0, 200);
1274  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, -200, 100);
1276  TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, 0, 122);
1277  TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, -122, 100);
1278  TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, 1, 100);
1279  TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, INT_MIN, INT_MAX);
1280  TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_IN_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, INT_MIN, INT_MAX);
1281  TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, 0, 200);
1282  TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, -200, 100);
1284  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, 0, 122);
1285  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, -122, 100);
1287  TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, INT_MIN, INT_MAX);
1288  TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, INT_MIN, INT_MAX);
1289 
1290  /* double testing */
1291  TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_DOUBLE, &double_val);
1292  TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE, &double_val);
1293  TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_DOUBLE, &double_val);
1294  TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE, &double_val);
1295  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE, &double_val);
1296  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE, &double_val);
1297  TEST_PARSE("7.0not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE, &double_val);
1298  TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
1299  TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
1300  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
1301  TEST_PARSE("not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
1302  TEST_PARSE("7.0not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
1303 
1304  TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, 0.0, 200.0);
1305  TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -200.0, 100.0);
1306  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -1.0, 0.0);
1307  TEST_PARSE("123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, 0.0, 122.0);
1308  TEST_PARSE("-123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -122.0, 100.0);
1309  TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, 1.0, 100.0);
1310  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
1311  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
1312  TEST_PARSE("123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, 0.0, 200.0);
1313  TEST_PARSE("-123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -200.0, 100.0);
1314  TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -1.0, 0.0);
1315  TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, 0.0, 122.0);
1316  TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -122.0, 100.0);
1317  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, 1.0, 100.0);
1318  TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
1319  TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
1320 
1321  TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, 0.0, 200.0);
1322  TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -200.0, 100.0);
1323  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -1.0, 0.0);
1324  TEST_PARSE("123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, 0.0, 122.0);
1325  TEST_PARSE("-123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -122.0, 100.0);
1326  TEST_PARSE("0", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, 1.0, 100.0);
1327  TEST_PARSE("not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
1328  TEST_PARSE("7not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
1329  TEST_PARSE("123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, 0.0, 200.0);
1330  TEST_PARSE("-123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -200.0, 100.0);
1331  TEST_PARSE("0", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -1.0, 0.0);
1332  TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, 0.0, 122.0);
1333  TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -122.0, 100.0);
1334  TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, 1.0, 100.0);
1335  TEST_PARSE("not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
1336  TEST_PARSE("7not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
1337 
1338  /* ast_sockaddr_parse is tested extensively in test_netsock2.c and PARSE_ADDR is a very simple wrapper */
1339 
1340  return ret;
1341 }
1342 struct test_item {
1345  AST_STRING_FIELD(stropt);
1346  );
1348  uint32_t uintopt;
1353  unsigned int flags;
1354  double doubleopt;
1355  struct ast_sockaddr sockaddropt;
1356  int boolopt;
1357  struct ast_ha *aclopt;
1359  unsigned int customopt:1;
1360 };
1361 struct test_config {
1365 };
1366 
1367 static int test_item_cmp(void *obj, void *arg, int flags)
1368 {
1369  struct test_item *one = obj, *two = arg;
1370  const char *match = (flags & OBJ_KEY) ? arg : two->name;
1371  return strcasecmp(one->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
1372 }
1373 static void test_item_destructor(void *obj)
1374 {
1375  struct test_item *item = obj;
1377  ao2_cleanup(item->codeccapopt);
1378  if (item->aclopt) {
1379  ast_free_ha(item->aclopt);
1380  }
1381  return;
1382 }
1383 static void *test_item_alloc(const char *cat)
1384 {
1385  struct test_item *item;
1386  if (!(item = ao2_alloc(sizeof(*item), test_item_destructor))) {
1387  return NULL;
1388  }
1389  if (ast_string_field_init(item, 128)) {
1390  ao2_ref(item, -1);
1391  return NULL;
1392  }
1394  ao2_ref(item, -1);
1395  return NULL;
1396  }
1397  ast_string_field_set(item, name, cat);
1398  return item;
1399 }
1400 static void test_config_destructor(void *obj)
1401 {
1402  struct test_config *cfg = obj;
1403  ao2_cleanup(cfg->global);
1405  ao2_cleanup(cfg->items);
1406 }
1407 static void *test_config_alloc(void)
1408 {
1409  struct test_config *cfg;
1410  if (!(cfg = ao2_alloc(sizeof(*cfg), test_config_destructor))) {
1411  goto error;
1412  }
1413  if (!(cfg->global = test_item_alloc("global"))) {
1414  goto error;
1415  }
1416  if (!(cfg->global_defaults = test_item_alloc("global_defaults"))) {
1417  goto error;
1418  }
1420  if (!cfg->items) {
1421  goto error;
1422  }
1423  return cfg;
1424 error:
1425  ao2_cleanup(cfg);
1426  return NULL;
1427 }
1428 static void *test_item_find(struct ao2_container *container, const char *cat)
1429 {
1430  return ao2_find(container, cat, OBJ_KEY);
1431 }
1432 
1433 static int customopt_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1434 {
1435  struct test_item *item = obj;
1436  if (!strcasecmp(var->name, "customopt")) {
1437  item->customopt = ast_true(var->value);
1438  } else {
1439  return -1;
1440  }
1441 
1442  return 0;
1443 }
1444 
1445 static struct aco_type global = {
1446  .type = ACO_GLOBAL,
1447  .item_offset = offsetof(struct test_config, global),
1448  .category_match = ACO_WHITELIST,
1449  .category = "^global$",
1450 };
1451 static struct aco_type global_defaults = {
1452  .type = ACO_GLOBAL,
1453  .item_offset = offsetof(struct test_config, global_defaults),
1454  .category_match = ACO_WHITELIST_EXACT,
1455  .category = "global_defaults",
1456 };
1457 static const char *item_blacklist[] = {
1458  "global",
1459  "global_defaults",
1460  NULL,
1461 };
1462 
1463 static struct aco_type item = {
1464  .type = ACO_ITEM,
1465  .category_match = ACO_BLACKLIST_ARRAY,
1466  .category = (const char *)item_blacklist,
1469  .item_offset = offsetof(struct test_config, items),
1470 };
1471 
1473  .filename = "config_test.conf",
1474  .types = ACO_TYPES(&global, &global_defaults, &item),
1475 };
1476 
1477 static AO2_GLOBAL_OBJ_STATIC(global_obj);
1478 CONFIG_INFO_TEST(cfg_info, global_obj, test_config_alloc,
1479  .files = ACO_FILES(&config_test_conf),
1480 );
1481 
1482 AST_TEST_DEFINE(config_options_test)
1483 {
1484  int res = AST_TEST_PASS, x, error;
1485  struct test_item defaults = { 0, }, configs = { 0, };
1486  struct test_item *arr[4];
1487  struct ast_sockaddr acl_allow = {{ 0, }}, acl_fail = {{ 0, }};
1488  RAII_VAR(struct test_config *, cfg, NULL, ao2_cleanup);
1489  RAII_VAR(struct test_item *, item, NULL, ao2_cleanup);
1490  RAII_VAR(struct test_item *, item_defaults, NULL, ao2_cleanup);
1491 
1492  switch (cmd) {
1493  case TEST_INIT:
1494  info->name = "config_options_test";
1495  info->category = "/config/";
1496  info->summary = "Config opptions unit test";
1497  info->description =
1498  "Tests the Config Options API";
1499  return AST_TEST_NOT_RUN;
1500  case TEST_EXECUTE:
1501  break;
1502  }
1503 
1504 #define INT_DEFAULT "-2"
1505 #define INT_CONFIG "-1"
1506 #define UINT_DEFAULT "2"
1507 #define UINT_CONFIG "1"
1508 #define TIMELEN_DEFAULT "2"
1509 #define TIMELEN_CONFIG "1"
1510 #define DOUBLE_DEFAULT "1.1"
1511 #define DOUBLE_CONFIG "0.1"
1512 #define SOCKADDR_DEFAULT "4.3.2.1:4321"
1513 #define SOCKADDR_CONFIG "1.2.3.4:1234"
1514 #define BOOL_DEFAULT "false"
1515 #define BOOL_CONFIG "true"
1516 #define BOOLFLAG1_DEFAULT "false"
1517 #define BOOLFLAG1_CONFIG "true"
1518 #define BOOLFLAG2_DEFAULT "false"
1519 #define BOOLFLAG2_CONFIG "false"
1520 #define BOOLFLAG3_DEFAULT "false"
1521 #define BOOLFLAG3_CONFIG "true"
1522 #define ACL_DEFAULT NULL
1523 #define ACL_CONFIG_PERMIT "1.2.3.4/32"
1524 #define ACL_CONFIG_DENY "0.0.0.0/0"
1525 #define CODEC_DEFAULT "!all,alaw"
1526 #define CODEC_CONFIG "!all,ulaw,g729"
1527 #define STR_DEFAULT "default"
1528 #define STR_CONFIG "test"
1529 #define CUSTOM_DEFAULT "no"
1530 #define CUSTOM_CONFIG "yes"
1531 
1532 #define BOOLFLAG1 1 << 0
1533 #define BOOLFLAG2 1 << 1
1534 #define BOOLFLAG3 1 << 2
1535 
1536  if (aco_info_init(&cfg_info)) {
1537  ast_test_status_update(test, "Could not init cfg info\n");
1538  return AST_TEST_FAIL;
1539  }
1540 
1541  /* Register all options */
1542  aco_option_register(&cfg_info, "intopt", ACO_EXACT, config_test_conf.types, INT_DEFAULT, OPT_INT_T, 0, FLDSET(struct test_item, intopt));
1543  aco_option_register(&cfg_info, "uintopt", ACO_EXACT, config_test_conf.types, UINT_DEFAULT, OPT_UINT_T, 0, FLDSET(struct test_item, uintopt));
1544  aco_option_register(&cfg_info, "timelenopt1", ACO_EXACT, config_test_conf.types, TIMELEN_DEFAULT, OPT_TIMELEN_T, 0, FLDSET(struct test_item, timelenopt1), TIMELEN_MILLISECONDS);
1545  aco_option_register(&cfg_info, "timelenopt2", ACO_EXACT, config_test_conf.types, TIMELEN_DEFAULT, OPT_TIMELEN_T, 0, FLDSET(struct test_item, timelenopt2), TIMELEN_SECONDS);
1546  aco_option_register(&cfg_info, "timelenopt3", ACO_EXACT, config_test_conf.types, TIMELEN_DEFAULT, OPT_TIMELEN_T, 0, FLDSET(struct test_item, timelenopt3), TIMELEN_MINUTES);
1547  aco_option_register(&cfg_info, "timelenopt4", ACO_EXACT, config_test_conf.types, TIMELEN_DEFAULT, OPT_TIMELEN_T, 0, FLDSET(struct test_item, timelenopt4), TIMELEN_HOURS);
1548  aco_option_register(&cfg_info, "doubleopt", ACO_EXACT, config_test_conf.types, DOUBLE_DEFAULT, OPT_DOUBLE_T, 0, FLDSET(struct test_item, doubleopt));
1549  aco_option_register(&cfg_info, "sockaddropt", ACO_EXACT, config_test_conf.types, SOCKADDR_DEFAULT, OPT_SOCKADDR_T, 0, FLDSET(struct test_item, sockaddropt));
1550  aco_option_register(&cfg_info, "boolopt", ACO_EXACT, config_test_conf.types, BOOL_DEFAULT, OPT_BOOL_T, 1, FLDSET(struct test_item, boolopt));
1551  aco_option_register(&cfg_info, "boolflag1", ACO_EXACT, config_test_conf.types, BOOLFLAG1_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG1);
1552  aco_option_register(&cfg_info, "boolflag2", ACO_EXACT, config_test_conf.types, BOOLFLAG2_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG2);
1553  aco_option_register(&cfg_info, "boolflag3", ACO_EXACT, config_test_conf.types, BOOLFLAG3_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG3);
1554  aco_option_register(&cfg_info, "aclpermitopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 1, FLDSET(struct test_item, aclopt));
1555  aco_option_register(&cfg_info, "acldenyopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 0, FLDSET(struct test_item, aclopt));
1556  aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codeccapopt));
1557  aco_option_register(&cfg_info, "stropt", ACO_EXACT, config_test_conf.types, STR_DEFAULT, OPT_STRINGFIELD_T, 0, STRFLDSET(struct test_item, stropt));
1558  aco_option_register_custom(&cfg_info, "customopt", ACO_EXACT, config_test_conf.types, CUSTOM_DEFAULT, customopt_handler, 0);
1559  aco_option_register_deprecated(&cfg_info, "permit", config_test_conf.types, "aclpermitopt");
1560  aco_option_register_deprecated(&cfg_info, "deny", config_test_conf.types, "acldenyopt");
1561 
1562  if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
1563  ast_test_status_update(test, "Could not parse config\n");
1564  return AST_TEST_FAIL;
1565  }
1566 
1583  defaults.boolopt = ast_true(BOOL_DEFAULT);
1584  configs.boolopt = ast_true(BOOL_CONFIG);
1591 
1592  defaults.aclopt = NULL;
1593  configs.aclopt = ast_append_ha("deny", ACL_CONFIG_DENY, configs.aclopt, &error);
1594  configs.aclopt = ast_append_ha("permit", ACL_CONFIG_PERMIT, configs.aclopt, &error);
1595  ast_sockaddr_parse(&acl_allow, "1.2.3.4", PARSE_PORT_FORBID);
1596  ast_sockaddr_parse(&acl_fail, "1.1.1.1", PARSE_PORT_FORBID);
1597 
1600 
1603 
1604  ast_string_field_init(&defaults, 128);
1606  ast_string_field_set(&defaults, stropt, STR_DEFAULT);
1608 
1609  defaults.customopt = ast_true(CUSTOM_DEFAULT);
1610  configs.customopt = ast_true(CUSTOM_CONFIG);
1611 
1612 
1613  cfg = ao2_global_obj_ref(global_obj);
1614  if (!(item = ao2_find(cfg->items, "item", OBJ_KEY))) {
1615  ast_test_status_update(test, "could not look up 'item'\n");
1616  return AST_TEST_FAIL;
1617  }
1618  if (!(item_defaults = ao2_find(cfg->items, "item_defaults", OBJ_KEY))) {
1619  ast_test_status_update(test, "could not look up 'item_defaults'\n");
1620  return AST_TEST_FAIL;
1621  }
1622  arr[0] = cfg->global;
1623  arr[1] = item;
1624  arr[2] = cfg->global_defaults;
1625  arr[3] = item_defaults;
1626  /* Test global and item against configs, global_defaults and item_defaults against defaults */
1627 
1628 #define NOT_EQUAL_FAIL(field, format) \
1629  if (arr[x]->field != control->field) { \
1630  ast_test_status_update(test, "%s did not match: " format " != " format " with x = %d\n", #field, arr[x]->field, control->field, x); \
1631  res = AST_TEST_FAIL; \
1632  }
1633  for (x = 0; x < 4; x++) {
1634  struct test_item *control = x < 2 ? &configs : &defaults;
1635 
1636  NOT_EQUAL_FAIL(intopt, "%d");
1637  NOT_EQUAL_FAIL(uintopt, "%u");
1638  NOT_EQUAL_FAIL(timelenopt1, "%d");
1639  NOT_EQUAL_FAIL(timelenopt2, "%d");
1640  NOT_EQUAL_FAIL(timelenopt3, "%d");
1641  NOT_EQUAL_FAIL(timelenopt4, "%d");
1642  NOT_EQUAL_FAIL(boolopt, "%d");
1643  NOT_EQUAL_FAIL(flags, "%u");
1644  NOT_EQUAL_FAIL(customopt, "%d");
1645  if (fabs(arr[x]->doubleopt - control->doubleopt) > 0.001) {
1646  ast_test_status_update(test, "doubleopt did not match: %f vs %f on loop %d\n", arr[x]->doubleopt, control->doubleopt, x);
1647  res = AST_TEST_FAIL;
1648  }
1649  if (ast_sockaddr_cmp(&arr[x]->sockaddropt, &control->sockaddropt)) {
1650  ast_test_status_update(test, "sockaddr did not match on loop %d\n", x);
1651  res = AST_TEST_FAIL;
1652  }
1653  if (!ast_format_cap_identical(arr[x]->codeccapopt, control->codeccapopt)) {
1654  struct ast_str *codec_buf1 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1655  struct ast_str *codec_buf2 = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1656 
1657  ast_test_status_update(test, "format did not match: '%s' vs '%s' on loop %d\n",
1658  ast_format_cap_get_names(arr[x]->codeccapopt, &codec_buf1),
1659  ast_format_cap_get_names(control->codeccapopt, &codec_buf2),
1660  x);
1661  res = AST_TEST_FAIL;
1662  }
1663  if (strcasecmp(arr[x]->stropt, control->stropt)) {
1664  ast_test_status_update(test, "stropt did not match: '%s' vs '%s' on loop %d\n", arr[x]->stropt, control->stropt, x);
1665  res = AST_TEST_FAIL;
1666  }
1667  if (arr[x]->aclopt != control->aclopt && (ast_apply_ha(arr[x]->aclopt, &acl_allow) != ast_apply_ha(control->aclopt, &acl_allow) ||
1668  ast_apply_ha(arr[x]->aclopt, &acl_fail) != ast_apply_ha(control->aclopt, &acl_fail))) {
1669  ast_test_status_update(test, "acl not match: on loop %d\n", x);
1670  res = AST_TEST_FAIL;
1671  }
1672  }
1673 
1674  ast_free_ha(configs.aclopt);
1675  ao2_cleanup(defaults.codeccapopt);
1676  defaults.codeccapopt = NULL;
1677  ao2_cleanup(configs.codeccapopt);
1678  configs.codeccapopt = NULL;
1679  ast_string_field_free_memory(&defaults);
1681  aco_info_destroy(&cfg_info);
1682  ao2_global_obj_release(global_obj);
1683  return res;
1684 }
1685 
1686 AST_TEST_DEFINE(config_dialplan_function)
1687 {
1689  FILE *config_file;
1690  char filename[PATH_MAX];
1691  struct ast_str *buf;
1692 
1693  switch (cmd) {
1694  case TEST_INIT:
1695  info->name = "config_dialplan_function";
1696  info->category = "/main/config/";
1697  info->summary = "Test AST_CONFIG dialplan function";
1698  info->description = "Test AST_CONFIG dialplan function";
1699  return AST_TEST_NOT_RUN;
1700  case TEST_EXECUTE:
1701  break;
1702  }
1703 
1704  snprintf(filename, sizeof(filename), "%s/%s",
1706  config_file = fopen(filename, "w");
1707 
1708  if (!config_file) {
1709  return AST_TEST_FAIL;
1710  }
1711 
1712  fputs(
1713  "[c1t](!)\n"
1714  "var1=val1\n"
1715  "var1=val2\n"
1716  "var2=val21\n"
1717  "\n"
1718  "[c1](c1t)\n"
1719  "var1=val3\n"
1720  "var1=val4\n"
1721  , config_file);
1722 
1723  fclose(config_file);
1724 
1725  if (!(buf = ast_str_create(32))) {
1726  ast_test_status_update(test, "Failed to allocate return buffer\n");
1727  res = AST_TEST_FAIL;
1728  goto out;
1729  }
1730 
1731  if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1)", &buf, 32)) {
1732  ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
1733  res = AST_TEST_FAIL;
1734  goto out;
1735  }
1736  if (strcmp(ast_str_buffer(buf), "val1")) {
1737  ast_test_status_update(test, "Got '%s', should be '%s'\n",
1738  ast_str_buffer(buf), "val1");
1739  res = AST_TEST_FAIL;
1740  goto out;
1741  }
1742 
1743  ast_str_reset(buf);
1744  if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,0)", &buf, 32)) {
1745  ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
1746  res = AST_TEST_FAIL;
1747  goto out;
1748  }
1749  if (strcmp(ast_str_buffer(buf), "val1")) {
1750  ast_test_status_update(test, "Got '%s', should be '%s'\n",
1751  ast_str_buffer(buf), "val1");
1752  res = AST_TEST_FAIL;
1753  goto out;
1754  }
1755 
1756  ast_str_reset(buf);
1757  if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,1)", &buf, 32)) {
1758  ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
1759  res = AST_TEST_FAIL;
1760  goto out;
1761  }
1762  if (strcmp(ast_str_buffer(buf), "val2")) {
1763  ast_test_status_update(test, "Got '%s', should be '%s'\n",
1764  ast_str_buffer(buf), "val2");
1765  res = AST_TEST_FAIL;
1766  goto out;
1767  }
1768 
1769  ast_str_reset(buf);
1770  if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,2)", &buf, 32)) {
1771  ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
1772  res = AST_TEST_FAIL;
1773  goto out;
1774  }
1775  if (strcmp(ast_str_buffer(buf), "val3")) {
1776  ast_test_status_update(test, "Got '%s', should be '%s'\n",
1777  ast_str_buffer(buf), "val3");
1778  res = AST_TEST_FAIL;
1779  goto out;
1780  }
1781 
1782  ast_str_reset(buf);
1783  if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,3)", &buf, 32)) {
1784  ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
1785  res = AST_TEST_FAIL;
1786  goto out;
1787  }
1788  if (strcmp(ast_str_buffer(buf), "val4")) {
1789  ast_test_status_update(test, "Got '%s', should be '%s'\n",
1790  ast_str_buffer(buf), "val4");
1791  res = AST_TEST_FAIL;
1792  goto out;
1793  }
1794 
1795  ast_str_reset(buf);
1796  if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,-1)", &buf, 32)) {
1797  ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
1798  res = AST_TEST_FAIL;
1799  goto out;
1800  }
1801  if (strcmp(ast_str_buffer(buf), "val4")) {
1802  ast_test_status_update(test, "Got '%s', should be '%s'\n",
1803  ast_str_buffer(buf), "val4");
1804  res = AST_TEST_FAIL;
1805  goto out;
1806  }
1807 
1808  ast_str_reset(buf);
1809  if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var2,-1)", &buf, 32)) {
1810  ast_test_status_update(test, "Failed to retrieve field 'var2'\n");
1811  res = AST_TEST_FAIL;
1812  goto out;
1813  }
1814  if (strcmp(ast_str_buffer(buf), "val21")) {
1815  ast_test_status_update(test, "Got '%s', should be '%s'\n",
1816  ast_str_buffer(buf), "val21");
1817  res = AST_TEST_FAIL;
1818  goto out;
1819  }
1820 
1821  ast_str_reset(buf);
1822  if (!ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,5)", &buf, 32)) {
1823  ast_test_status_update(test, "Should not have retrieved a value\n");
1824  res = AST_TEST_FAIL;
1825  goto out;
1826  }
1827 
1828 out:
1829  if (buf) {
1830  ast_free(buf);
1831  }
1833  return res;
1834 }
1835 
1836 AST_TEST_DEFINE(variable_lists_match)
1837 {
1838  RAII_VAR(struct ast_variable *, left, NULL, ast_variables_destroy);
1839  RAII_VAR(struct ast_variable *, right, NULL, ast_variables_destroy);
1840  struct ast_variable *var;
1841 
1842  switch (cmd) {
1843  case TEST_INIT:
1844  info->name = "variable_lists_match";
1845  info->category = "/main/config/";
1846  info->summary = "Test ast_variable_lists_match";
1847  info->description = "Test ast_variable_lists_match";
1848  return AST_TEST_NOT_RUN;
1849  case TEST_EXECUTE:
1850  break;
1851  }
1852 
1853  var = ast_variable_new("aaa", "111", "");
1854  ast_test_validate(test, var);
1855  left = var;
1856  var = ast_variable_new("bbb", "222", "");
1857  ast_test_validate(test, var);
1858  ast_variable_list_append(&left, var);
1859 
1860  var = ast_variable_new("aaa", "111", "");
1861  ast_test_validate(test, var);
1862  right = var;
1863 
1864  ast_test_validate(test, ast_variable_lists_match(left, right, 0));
1865  ast_test_validate(test, !ast_variable_lists_match(left, right, 1));
1866 
1867  var = ast_variable_new("bbb", "222", "");
1868  ast_test_validate(test, var);
1869  ast_variable_list_append(&right, var);
1870 
1871  ast_test_validate(test, ast_variable_lists_match(left, right, 0));
1872  ast_test_validate(test, ast_variable_lists_match(left, right, 1));
1873 
1874  var = ast_variable_new("ccc >", "333", "");
1875  ast_test_validate(test, var);
1876  ast_variable_list_append(&right, var);
1877 
1878  ast_test_validate(test, !ast_variable_lists_match(left, right, 0));
1879  ast_test_validate(test, !ast_variable_lists_match(left, right, 1));
1880 
1881  var = ast_variable_new("ccc", "444", "");
1882  ast_test_validate(test, var);
1883  ast_variable_list_append(&left, var);
1884 
1885  ast_test_validate(test, ast_variable_lists_match(left, right, 0));
1886  ast_test_validate(test, !ast_variable_lists_match(left, right, 1));
1887 
1888  ast_test_validate(test, !ast_variable_lists_match(left, NULL, 0));
1889  ast_test_validate(test, ast_variable_lists_match(NULL, NULL, 0));
1890  ast_test_validate(test, !ast_variable_lists_match(NULL, right, 0));
1891  ast_test_validate(test, ast_variable_lists_match(left, left, 0));
1892 
1893  return AST_TEST_PASS;
1894 }
1895 
1896 static int unload_module(void)
1897 {
1898  AST_TEST_UNREGISTER(config_save);
1899  AST_TEST_UNREGISTER(config_basic_ops);
1900  AST_TEST_UNREGISTER(config_filtered_ops);
1901  AST_TEST_UNREGISTER(config_template_ops);
1902  AST_TEST_UNREGISTER(copy_config);
1903  AST_TEST_UNREGISTER(config_hook);
1904  AST_TEST_UNREGISTER(ast_parse_arg_test);
1905  AST_TEST_UNREGISTER(config_options_test);
1906  AST_TEST_UNREGISTER(config_dialplan_function);
1907  AST_TEST_UNREGISTER(variable_lists_match);
1908  return 0;
1909 }
1910 
1911 static int load_module(void)
1912 {
1913  AST_TEST_REGISTER(config_save);
1914  AST_TEST_REGISTER(config_basic_ops);
1915  AST_TEST_REGISTER(config_filtered_ops);
1916  AST_TEST_REGISTER(config_template_ops);
1917  AST_TEST_REGISTER(copy_config);
1918  AST_TEST_REGISTER(config_hook);
1919  AST_TEST_REGISTER(ast_parse_arg_test);
1920  AST_TEST_REGISTER(config_options_test);
1921  AST_TEST_REGISTER(config_dialplan_function);
1922  AST_TEST_REGISTER(variable_lists_match);
1923  return AST_MODULE_LOAD_SUCCESS;
1924 }
1925 
Type for default handler for ast_sockaddrs.
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
Definition: extconf.c:2790
struct ast_variable * next
Type for default option handler for format capabilities.
const char cat2varvalue3[]
Definition: test_config.c:82
static int unload_module(void)
Definition: test_config.c:1896
struct aco_file config_test_conf
Definition: test_config.c:1472
#define BOOLFLAG2_DEFAULT
const char * val
Definition: test_config.c:86
#define CODEC_DEFAULT
aco_type_item_find item_find
struct ast_config_include * ast_include_new(struct ast_config *conf, const char *from_file, const char *included_file, int is_exec, const char *exec_file, int from_lineno, char *real_included_file_name, int real_included_file_name_size)
Definition: extconf.c:1075
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
int ast_config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator)
Save a config text file preserving the pre 13.2 behavior.
Definition: main/config.c:2531
int timelenopt3
Definition: test_config.c:1351
const ast_string_field name
Definition: test_config.c:1346
Asterisk main include file. File version handling, generic pbx functions.
static const char config_file[]
Definition: cdr_odbc.c:57
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define STR_DEFAULT
void ast_variable_insert(struct ast_category *category, struct ast_variable *variable, const char *line)
Definition: main/config.c:501
#define ACL_CONFIG_PERMIT
static struct aco_type global
Definition: test_config.c:1445
const char cat1[]
Definition: test_config.c:68
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
Definition: ast_expr2.c:325
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
const char cat2varvalue1[]
Definition: test_config.c:78
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
const char * category
Definition: test_config.c:90
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define OBJ_KEY
Definition: astobj2.h:1155
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
executes a read operation on a function
static AO2_GLOBAL_OBJ_STATIC(global_obj)
struct ast_category * ast_category_delete(struct ast_config *cfg, struct ast_category *category)
Delete a category.
Definition: main/config.c:1478
#define INT_CONFIG
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:326
const char cat2varvalue2[]
Definition: test_config.c:80
const char cat1varname2[]
Definition: test_config.c:71
int timelenopt4
Definition: test_config.c:1352
static int hook_config_sane
Definition: test_config.c:873
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
double doubleopt
Definition: test_config.c:1354
#define BOOLFLAG2
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1335
CONFIG_INFO_TEST(cfg_info, global_obj, test_config_alloc,.files=ACO_FILES(&config_test_conf),)
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3154
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
Test Framework API.
struct ao2_container * items
Definition: test_config.c:1364
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define DOUBLE_DEFAULT
enum ast_acl_sense ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr)
Apply a set of rules to a given IP address.
Definition: acl.c:808
const char cat1varvalue2[]
Definition: test_config.c:72
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
static struct aco_type item
Definition: test_config.c:1463
static int hook_run
Definition: test_config.c:867
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:337
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2315
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
#define ast_str_alloca(init_len)
Definition: strings.h:800
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
The representation of a single configuration file to be processed.
int value
Definition: syslog.c:37
#define BOOLFLAG3
const char * ast_variable_find_last_in_list(const struct ast_variable *list, const char *variable)
Gets the value of the LAST occurrence of a variable from a variable list.
Definition: main/config.c:842
enum aco_type_t type
Socket address structure.
Definition: netsock2.h:97
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
#define CONFIG_INCLUDE_FILE
Definition: test_config.c:52
struct ast_category * ast_category_browse_filtered(struct ast_config *config, const char *category_name, struct ast_category *prev, const char *filter)
Browse categories with filters.
Definition: main/config.c:1335
#define UINT_DEFAULT
struct test_item * global
Definition: test_config.c:1362
Utility functions.
#define SOCKADDR_CONFIG
#define TOOBIG_I32
Definition: test_config.c:1052
static void * test_item_find(struct ao2_container *container, const char *cat)
Definition: test_config.c:1428
#define CODEC_CONFIG
#define DOUBLE_CONFIG
int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing)
Parse an "allow" or "deny" list and modify a format capabilities structure accordingly.
Definition: format_cap.c:320
static void * test_config_alloc(void)
Definition: test_config.c:1407
internal representation of ACL entries In principle user applications would have no need for this...
Definition: acl.h:51
struct ast_format_cap * codeccapopt
Definition: test_config.c:1358
#define BOOLFLAG2_CONFIG
Configuration File Parser.
void ast_config_hook_unregister(const char *name)
Unregister a config hook.
Definition: main/config.c:4104
#define ast_log
Definition: astobj2.c:42
#define STR_CONFIG
#define ast_config_load(filename, flags)
Load a config file.
static char * config_filename
Definition: extconf.c:2121
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
const char cat1varname1[]
Definition: test_config.c:69
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define ACL_DEFAULT
Asterisk file paths, configured in asterisk.conf.
#define BOOL_DEFAULT
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
Type for default option handler for unsigned integers.
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
int ast_config_hook_register(const char *name, const char *filename, const char *module, enum config_hook_flags flags, config_hook_cb hook)
Register a config hook for a particular file and module.
Definition: main/config.c:4132
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
struct ast_ha * aclopt
Definition: test_config.c:1357
Access Control of various sorts.
unsigned int customopt
Definition: test_config.c:1359
const char cat1varvalue1[]
Definition: test_config.c:70
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:299
#define INT_DEFAULT
Asterisk internal frame definitions.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int write_config_file(void)
Write the config file to disk.
Definition: test_config.c:825
const char cat2varname1[]
Definition: test_config.c:77
int timelenopt2
Definition: test_config.c:1350
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define BOOL_CONFIG
const char * ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
Gets the value of a variable from a variable list by name.
Definition: main/config.c:830
aco_type_item_alloc item_alloc
struct ao2_container * container
Definition: res_fax.c:502
const char cat2varname2[]
Definition: test_config.c:79
#define ast_variable_new(name, value, filename)
int aco_option_register_deprecated(struct aco_info *info, const char *name, struct aco_type **types, const char *aliased_to)
Register a deprecated (and aliased) config option.
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3276
struct ast_variable * ast_variable_list_append_hint(struct ast_variable **head, struct ast_variable *search_hint, struct ast_variable *new_var)
Appends a variable list to the end of another list.
Definition: main/config.c:648
Network socket handling.
Core PBX routines and definitions.
static void * test_item_alloc(const char *cat)
Definition: test_config.c:1383
#define CONFIG_STATUS_FILEUNCHANGED
Format Capabilities API.
Their was an error and no changes were applied.
struct ast_sockaddr sockaddropt
Definition: test_config.c:1355
Configuration option-handling.
#define LOG_ERROR
Definition: logger.h:285
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define TIMELEN_DEFAULT
struct association categories[]
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865
Type for default option handler for bools (ast_true/ast_false)
def info(msg)
int ast_category_insert(struct ast_config *config, struct ast_category *cat, const char *match)
Inserts new category.
Definition: main/config.c:1083
static int load_module(void)
Definition: test_config.c:1911
AST_TEST_DEFINE(copy_config)
Definition: test_config.c:192
#define BOOLFLAG3_CONFIG
#define BOOLFLAG3_DEFAULT
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define TEST_PARSE(input, should_succeed, expected_result, flags, result,...)
Definition: test_config.c:1059
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:736
#define TOOSMALL_U32
Definition: test_config.c:1055
const char cat1varname3[]
Definition: test_config.c:73
struct ast_config * ast_config_copy(const struct ast_config *orig)
Copies the contents of one ast_config into another.
Definition: main/config.c:3079
#define BOOLFLAG1_DEFAULT
#define TIMELEN_CONFIG
#define ast_free(a)
Definition: astmm.h:182
const char cat1varvalue3[]
Definition: test_config.c:74
Type for default option handler for ACLs.
const ast_string_field stropt
Definition: test_config.c:1346
int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if two capabilities structures are identical.
Definition: format_cap.c:689
Type for default option handler for doubles.
#define CONFIG_FILE
Definition: test_config.c:51
#define TOOBIG_U32
Definition: test_config.c:1054
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *result,...)
The argument parsing routine.
Definition: main/config.c:3657
uint32_t uintopt
Definition: test_config.c:1348
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
const char * ast_variable_find(const struct ast_category *category, const char *variable)
Gets a variable value from a specific category structure by name.
Definition: main/config.c:735
#define TOOSMALL_I32
Definition: test_config.c:1053
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char cat2varname3[]
Definition: test_config.c:81
struct pair vars[3]
Definition: test_config.c:91
#define SOCKADDR_DEFAULT
struct test_item * global_defaults
Definition: test_config.c:1363
static void test_item_destructor(void *obj)
Definition: test_config.c:1373
Structure used to handle boolean flags.
Definition: utils.h:199
static struct aco_type global_defaults
Definition: test_config.c:1451
Support for logging to various files, console and syslog Configuration in file logger.conf.
config_hook_flags
Flags that affect the behaviour of config hooks.
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1178
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Appends a category to a config.
Definition: extconf.c:2835
static const char * item_blacklist[]
Definition: test_config.c:1457
struct ast_category * ast_category_new_template(const char *name, const char *in_file, int lineno)
Create a category making it a template.
Definition: main/config.c:995
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
static void delete_config_file(void)
Delete config file created by write_config_file.
Definition: test_config.c:856
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define ACO_FILES(...)
int ast_category_empty(struct ast_category *category)
Removes and destroys all variables in a category.
Definition: main/config.c:1510
#define CUSTOM_DEFAULT
#define NOT_EQUAL_FAIL(field, format)
FILE * out
Definition: utils/frame.c:33
int ast_variable_lists_match(const struct ast_variable *left, const struct ast_variable *right, int exact_match)
Tests 2 variable lists to see if they match.
Definition: main/config.c:772
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Type for default option handler for time length signed integers.
int timelenopt1
Definition: test_config.c:1349
Type information about a category-level configurable object.
#define AST_MODULE
size_t item_offset
const char * filename
const char cat2[]
Definition: test_config.c:76
static struct configs configs
Type for default option handler for stringfields.
const char * name
Definition: test_config.c:85
unsigned int flags
Definition: test_config.c:1353
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
Definition: acl.c:713
int error(const char *format,...)
Definition: utils/frame.c:999
int32_t intopt
Definition: test_config.c:1347
#define UINT_CONFIG
#define PATH_MAX
Definition: asterisk.h:40
int int32_t
Definition: db.h:60
Generic container type.
#define ACL_CONFIG_DENY
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
Definition: main/config.c:1022
static struct ast_config * build_cfg(void)
Build ast_config struct from above definitions.
Definition: test_config.c:115
#define BOOLFLAG1
struct aco_type * types[]
Type for default option handler for signed integers.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
#define DEFAULTVAL
Definition: test_config.c:1056
static int hook_cb(struct ast_config *cfg)
Definition: test_config.c:875
Asterisk module definitions.
static void test_config_destructor(void *obj)
Definition: test_config.c:1400
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static int test_config_validity(struct ast_config *cfg)
Tests that the contents of an ast_config is what is expected.
Definition: test_config.c:164
static int test_item_cmp(void *obj, void *arg, int flags)
Definition: test_config.c:1367
#define ast_variable_list_append(head, new_var)
const char * ast_category_get_name(const struct ast_category *category)
Return the name of the category.
Definition: main/config.c:1028
ast_test_result_state
Definition: test.h:200
#define BOOLFLAG1_CONFIG
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
static int customopt_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: test_config.c:1433
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
#define CUSTOM_CONFIG