Asterisk - The Open Source Telephony Project GIT-master-d856a3e
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 <mmichelson@digium.com>
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 <mmichelson@digium.com>
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 */
68const char cat1[] = "Capitals";
69const char cat1varname1[] = "Germany";
70const char cat1varvalue1[] = "Berlin";
71const char cat1varname2[] = "China";
72const char cat1varvalue2[] = "Beijing";
73const char cat1varname3[] = "Canada";
74const char cat1varvalue3[] = "Ottawa";
75
76const char cat2[] = "Protagonists";
77const char cat2varname1[] = "1984";
78const char cat2varvalue1[] = "Winston Smith";
79const char cat2varname2[] = "Green Eggs And Ham";
80const char cat2varvalue2[] = "Sam I Am";
81const char cat2varname3[] = "The Kalevala";
82const char cat2varvalue3[] = "Vainamoinen";
83
84struct pair {
85 const char *name;
86 const char *val;
87};
88
90 const char *category;
91 struct pair vars[3];
92} categories [] = {
93 { cat1,
94 {
98 }
99 },
100 { cat2,
101 {
105 }
106 },
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 */
115static 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 }
147 }
148 }
149
150 return cfg;
151
152fail:
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 */
164static 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
192AST_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
226out:
229 return res;
230}
231
232AST_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 }
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 }
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 }
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
560out:
562 return res;
563}
564
565AST_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 */
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
702out:
704 return res;
705}
706
707AST_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
813out:
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 */
825static 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 */
856static 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 */
867static 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 */
874
875static int hook_cb(struct ast_config *cfg)
876{
877 hook_run = 1;
878 if (test_config_validity(cfg) == 0) {
880 }
882 return 0;
883}
884
885AST_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
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
948out:
950 unlink(config_filename);
951 unlink(include_filename);
952
953 return res;
954}
955
956AST_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",
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);
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
1041out:
1042 ast_config_hook_unregister("test_hook");
1044 return res;
1045}
1046
1047enum {
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
1098AST_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);
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);
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
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);
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);
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);
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);
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);
1282 TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_TIMELEN | PARSE_DEFAULT | PARSE_OUT_RANGE, &timelen_val, TIMELEN_MILLISECONDS, 7, -200, 100);
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}
1348 uint32_t uintopt;
1353 unsigned int flags;
1359 unsigned int customopt:1;
1360};
1365};
1366
1367static 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}
1373static 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}
1383static 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 }
1393 if (!(item->codeccapopt = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
1394 ao2_ref(item, -1);
1395 return NULL;
1396 }
1398 return item;
1399}
1400static void test_config_destructor(void *obj)
1401{
1402 struct test_config *cfg = obj;
1403 ao2_cleanup(cfg->global);
1405 ao2_cleanup(cfg->items);
1406}
1407static 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;
1424error:
1425 ao2_cleanup(cfg);
1426 return NULL;
1427}
1428static void *test_item_find(struct ao2_container *container, const char *cat)
1429{
1430 return ao2_find(container, cat, OBJ_KEY);
1431}
1432
1433static 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
1445static 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};
1451static 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};
1457static const char *item_blacklist[] = {
1458 "global",
1459 "global_defaults",
1460 NULL,
1461};
1462
1463static 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
1477static AO2_GLOBAL_OBJ_STATIC(global_obj);
1479 .files = ACO_FILES(&config_test_conf),
1480);
1481
1482AST_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 options 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));
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));
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));
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");
1642 NOT_EQUAL_FAIL(boolopt, "%d");
1643 NOT_EQUAL_FAIL(flags, "%u");
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;
1681 aco_info_destroy(&cfg_info);
1682 ao2_global_obj_release(global_obj);
1683 return res;
1684}
1685
1686AST_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
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
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
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
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
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
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
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
1828out:
1829 if (buf) {
1830 ast_free(buf);
1831 }
1833 return res;
1834}
1835
1836AST_TEST_DEFINE(variable_lists_match)
1837{
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);
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);
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);
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);
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
1896AST_TEST_DEFINE(variable_list_join_replace)
1897{
1899 RAII_VAR(struct ast_str *, str, NULL, ast_free);
1900 struct ast_variable *bbb;
1901 int rc;
1902
1903 switch (cmd) {
1904 case TEST_INIT:
1905 info->name = "variable_list_join_replace";
1906 info->category = "/main/config/";
1907 info->summary = "Test joining a variable list";
1908 info->description = info->summary;
1909 return AST_TEST_NOT_RUN;
1910 case TEST_EXECUTE:
1911 break;
1912 }
1913
1914 list = ast_variable_new("aaa", "111", "");
1915 bbb = ast_variable_new("bbb", "222", "");
1916 ast_variable_list_append(&list, bbb);
1917 ast_variable_list_append(&list, ast_variable_new("ccc", "33 33", ""));
1918
1919 str = ast_variable_list_join(list, ", ", " = ", "\"", &str);
1920 ast_test_validate(test, strcmp(ast_str_buffer(str), "aaa = \"111\", bbb = \"222\", ccc = \"33 33\"") == 0);
1921 ast_free(str);
1922
1924 str = ast_variable_list_join(list, ", ", " = ", "\"", &str);
1925 ast_test_validate(test, strcmp(ast_str_buffer(str), "aaa = \"111\", bbb = \"222\", ccc = \"33 33\"") == 0);
1926 ast_free(str);
1927
1928 str = ast_variable_list_join(list, ", ", " = ", "\"", NULL);
1929 ast_test_validate(test, strcmp(ast_str_buffer(str), "aaa = \"111\", bbb = \"222\", ccc = \"33 33\"") == 0);
1930 ast_free(str);
1931
1932 /* Replace the head item in the list */
1933 rc = ast_variable_list_replace_variable(&list, list, ast_variable_new("ddd", "444", ""));
1934 ast_test_validate(test, rc == 0);
1935 str = ast_variable_list_join(list, ", ", " = ", "\"", NULL);
1936 ast_test_validate(test, strcmp(ast_str_buffer(str), "ddd = \"444\", bbb = \"222\", ccc = \"33 33\"") == 0);
1937 ast_free(str);
1938
1939 rc = ast_variable_list_replace_variable(&list, bbb, ast_variable_new("eee", "555", ""));
1940 ast_test_validate(test, rc == 0);
1941 str = ast_variable_list_join(list, ", ", " = ", "\"", NULL);
1942 ast_test_validate(test, strcmp(ast_str_buffer(str), "ddd = \"444\", eee = \"555\", ccc = \"33 33\"") == 0);
1943
1944 return AST_TEST_PASS;
1945}
1946
1947AST_TEST_DEFINE(variable_list_from_string)
1948{
1950 RAII_VAR(struct ast_str *, str, NULL, ast_free);
1951 char *parse_string;
1952
1953 switch (cmd) {
1954 case TEST_INIT:
1955 info->name = "variable_list_from_quoted_string";
1956 info->category = "/main/config/";
1957 info->summary = "Test parsing a string into a variable list";
1958 info->description = info->summary;
1959 return AST_TEST_NOT_RUN;
1960 case TEST_EXECUTE:
1961 break;
1962 }
1963
1964 parse_string = "000= '', 111=, 222 = , 333 = ' ', abc = 'def', ghi = 'j,kl', mno='pq=r', stu = 'vwx=\"yz\", ABC = \"DEF\"'";
1965 list = ast_variable_list_from_quoted_string(parse_string, ",", "=", "'");
1966 ast_test_validate(test, list != NULL);
1967 str = ast_variable_list_join(list, "|", "^", "@", NULL);
1968
1969 ast_test_validate(test,
1970 strcmp(ast_str_buffer(str), "000^@@|111^@@|222^@@|333^@ @|abc^@def@|ghi^@j,kl@|mno^@pq=r@|stu^@vwx=\"yz\", ABC = \"DEF\"@") == 0);
1971
1972 return AST_TEST_PASS;
1973}
1974
1975static int unload_module(void)
1976{
1977 AST_TEST_UNREGISTER(config_save);
1978 AST_TEST_UNREGISTER(config_basic_ops);
1979 AST_TEST_UNREGISTER(config_filtered_ops);
1980 AST_TEST_UNREGISTER(config_template_ops);
1981 AST_TEST_UNREGISTER(copy_config);
1982 AST_TEST_UNREGISTER(config_hook);
1983 AST_TEST_UNREGISTER(ast_parse_arg_test);
1984 AST_TEST_UNREGISTER(config_options_test);
1985 AST_TEST_UNREGISTER(config_dialplan_function);
1986 AST_TEST_UNREGISTER(variable_lists_match);
1987 AST_TEST_UNREGISTER(variable_list_join_replace);
1988 AST_TEST_UNREGISTER(variable_list_from_string);
1989 return 0;
1990}
1991
1992static int load_module(void)
1993{
1994 AST_TEST_REGISTER(config_save);
1995 AST_TEST_REGISTER(config_basic_ops);
1996 AST_TEST_REGISTER(config_filtered_ops);
1997 AST_TEST_REGISTER(config_template_ops);
1998 AST_TEST_REGISTER(copy_config);
1999 AST_TEST_REGISTER(config_hook);
2000 AST_TEST_REGISTER(ast_parse_arg_test);
2001 AST_TEST_REGISTER(config_options_test);
2002 AST_TEST_REGISTER(config_dialplan_function);
2003 AST_TEST_REGISTER(variable_lists_match);
2004 AST_TEST_REGISTER(variable_list_join_replace);
2005 AST_TEST_REGISTER(variable_list_from_string);
2007}
2008
Access Control of various sorts.
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
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:807
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:712
#define AST_MODULE
const char * str
Definition: app_jack.c:147
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define PATH_MAX
Definition: asterisk.h:40
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define OBJ_KEY
Definition: astobj2.h:1151
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
static const char config_file[]
Definition: cdr_odbc.c:54
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:2362
#define AST_MAX_USER_FIELD
Definition: channel.h:176
Configuration option-handling.
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.
@ ACO_EXACT
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
@ ACO_PROCESS_ERROR
Their was an error and no changes were applied.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
#define ACO_FILES(...)
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_CODEC_T
Type for default option handler for format capabilities.
@ OPT_BOOL_T
Type for default option handler for bools (ast_true/ast_false)
@ OPT_BOOLFLAG_T
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag.
@ OPT_ACL_T
Type for default option handler for ACLs.
@ OPT_SOCKADDR_T
Type for default handler for ast_sockaddrs.
@ OPT_INT_T
Type for default option handler for signed integers.
@ OPT_TIMELEN_T
Type for default option handler for time length signed integers.
@ OPT_DOUBLE_T
Type for default option handler for doubles.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
@ ACO_ITEM
@ ACO_GLOBAL
@ ACO_WHITELIST_EXACT
@ ACO_WHITELIST
@ ACO_BLACKLIST_ARRAY
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.
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
int int32_t
Definition: db.h:60
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static char * config_filename
Definition: extconf.c:2120
Format Capabilities API.
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
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
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
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:734
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:687
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static const char name[]
Definition: format_mp3.c:68
static struct configs configs
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
@ TIMELEN_MILLISECONDS
@ TIMELEN_MINUTES
@ TIMELEN_SECONDS
@ TIMELEN_HOURS
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
struct ast_variable * ast_variable_list_from_quoted_string(const char *input, const char *item_separator, const char *name_value_separator, const char *quote_str)
Parse a string into an ast_variable list. The reverse of ast_variable_list_join.
Definition: main/config.c:727
const char * ast_category_get_name(const struct ast_category *category)
Return the name of the category.
Definition: main/config.c:1118
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:1085
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:3322
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
struct ast_category * ast_category_delete(struct ast_config *cfg, struct ast_category *cat)
Delete a category.
Definition: main/config.c:1568
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:932
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
void ast_config_hook_unregister(const char *name)
Unregister a config hook.
Definition: main/config.c:4275
int ast_category_insert(struct ast_config *config, struct ast_category *cat, const char *match)
Inserts new category.
Definition: main/config.c:1173
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:2702
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition: extconf.c:2833
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1177
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:1074
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:920
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
Definition: extconf.c:2788
#define ast_variable_new(name, value, filename)
int ast_variable_list_replace_variable(struct ast_variable **head, struct ast_variable *oldvar, struct ast_variable *newvar)
Replace a variable in the given list with a new variable.
Definition: main/config.c:684
#define ast_variable_list_append(head, new_var)
#define CONFIG_STATUS_FILEUNCHANGED
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
Definition: main/config.c:3828
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
int ast_category_empty(struct ast_category *category)
Removes and destroys all variables in a category.
Definition: main/config.c:1600
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:647
struct ast_str * ast_variable_list_join(const struct ast_variable *head, const char *item_separator, const char *name_value_separator, const char *quote_char, struct ast_str **str)
Join an ast_variable list with specified separators and quoted values.
Definition: main/config.c:701
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:784
void ast_variable_insert(struct ast_category *category, struct ast_variable *variable, const char *line)
Definition: main/config.c:500
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:862
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:4303
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
config_hook_flags
Flags that affect the behaviour of config hooks.
struct ast_config * ast_config_copy(const struct ast_config *orig)
Copies the contents of one ast_config into another.
Definition: main/config.c:3247
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
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:825
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:1112
@ CONFIG_FLAG_FILEUNCHANGED
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:1425
Asterisk internal frame definitions.
Support for logging to various files, console and syslog Configuration in file logger....
#define LOG_ERROR
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
Network socket handling.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151
Core PBX routines and definitions.
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
struct ao2_container * container
Definition: res_fax.c:501
#define NULL
Definition: resample.c:96
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:341
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:303
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
#define ast_str_alloca(init_len)
Definition: strings.h:848
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:693
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
The representation of a single configuration file to be processed.
struct aco_type * types[]
const char * filename
Type information about a category-level configurable object.
aco_type_item_find item_find
enum aco_type_t type
aco_type_item_alloc item_alloc
size_t item_offset
Generic container type.
const char * category
Definition: test_config.c:90
struct pair vars[3]
Definition: test_config.c:91
Structure used to handle boolean flags.
Definition: utils.h:199
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
internal representation of ACL entries In principle user applications would have no need for this,...
Definition: acl.h:51
Socket address structure.
Definition: netsock2.h:97
Support for dynamic strings.
Definition: strings.h:623
Structure for variables, used for configurations and for channel variables.
const char * val
Definition: test_config.c:86
const char * name
Definition: test_config.c:85
struct test_item * global
Definition: test_config.c:1362
struct ao2_container * items
Definition: test_config.c:1364
struct test_item * global_defaults
Definition: test_config.c:1363
uint32_t uintopt
Definition: test_config.c:1348
int timelenopt2
Definition: test_config.c:1350
int timelenopt4
Definition: test_config.c:1352
int timelenopt3
Definition: test_config.c:1351
struct ast_format_cap * codeccapopt
Definition: test_config.c:1358
int32_t intopt
Definition: test_config.c:1347
int timelenopt1
Definition: test_config.c:1349
struct ast_ha * aclopt
Definition: test_config.c:1357
const ast_string_field stropt
Definition: test_config.c:1346
struct ast_sockaddr sockaddropt
Definition: test_config.c:1355
unsigned int flags
Definition: test_config.c:1353
const ast_string_field name
Definition: test_config.c:1346
double doubleopt
Definition: test_config.c:1354
unsigned int customopt
Definition: test_config.c:1359
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
ast_test_result_state
Definition: test.h:193
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
#define CONFIG_INCLUDE_FILE
Definition: test_config.c:52
#define CODEC_DEFAULT
static struct ast_config * build_cfg(void)
Build ast_config struct from above definitions.
Definition: test_config.c:115
#define BOOLFLAG3_DEFAULT
#define TOOBIG_U32
Definition: test_config.c:1054
#define BOOLFLAG1_CONFIG
AST_TEST_DEFINE(copy_config)
Definition: test_config.c:192
static AO2_GLOBAL_OBJ_STATIC(global_obj)
static int hook_run
Definition: test_config.c:867
#define STR_DEFAULT
#define TIMELEN_CONFIG
#define TEST_PARSE(input, should_succeed, expected_result, flags, result,...)
Definition: test_config.c:1059
const char cat1varname1[]
Definition: test_config.c:69
const char cat1varname3[]
Definition: test_config.c:73
const char cat1[]
Definition: test_config.c:68
#define DEFAULTVAL
Definition: test_config.c:1056
const char cat1varvalue3[]
Definition: test_config.c:74
#define BOOL_CONFIG
#define ACL_DEFAULT
#define STR_CONFIG
#define TOOBIG_I32
Definition: test_config.c:1052
@ EXPECT_FAIL
Definition: test_config.c:1048
@ EXPECT_SUCCEED
Definition: test_config.c:1049
#define CONFIG_FILE
Definition: test_config.c:51
const char cat2varname1[]
Definition: test_config.c:77
#define BOOLFLAG2_DEFAULT
#define INT_CONFIG
#define ACL_CONFIG_PERMIT
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
const char cat2varvalue3[]
Definition: test_config.c:82
static void * test_item_find(struct ao2_container *container, const char *cat)
Definition: test_config.c:1428
static void * test_config_alloc(void)
Definition: test_config.c:1407
#define CODEC_CONFIG
#define BOOLFLAG2_CONFIG
#define UINT_DEFAULT
#define UINT_CONFIG
const char cat2varname2[]
Definition: test_config.c:79
static void test_item_destructor(void *obj)
Definition: test_config.c:1373
static struct aco_type global_defaults
Definition: test_config.c:1451
#define TOOSMALL_U32
Definition: test_config.c:1055
#define INT_DEFAULT
const char cat1varname2[]
Definition: test_config.c:71
static int test_item_cmp(void *obj, void *arg, int flags)
Definition: test_config.c:1367
static int hook_config_sane
Definition: test_config.c:873
const char cat2varvalue1[]
Definition: test_config.c:78
#define BOOLFLAG2
static const char * item_blacklist[]
Definition: test_config.c:1457
static int write_config_file(void)
Write the config file to disk.
Definition: test_config.c:825
static int hook_cb(struct ast_config *cfg)
Definition: test_config.c:875
static void delete_config_file(void)
Delete config file created by write_config_file.
Definition: test_config.c:856
static void test_config_destructor(void *obj)
Definition: test_config.c:1400
#define ACL_CONFIG_DENY
struct aco_file config_test_conf
Definition: test_config.c:1472
static void * test_item_alloc(const char *cat)
Definition: test_config.c:1383
const char cat1varvalue2[]
Definition: test_config.c:72
#define BOOLFLAG1
const char cat2[]
Definition: test_config.c:76
#define BOOLFLAG3_CONFIG
const char cat1varvalue1[]
Definition: test_config.c:70
#define BOOLFLAG3
const char cat2varvalue2[]
Definition: test_config.c:80
static struct aco_type global
Definition: test_config.c:1445
#define CUSTOM_CONFIG
#define NOT_EQUAL_FAIL(field, format)
static int load_module(void)
Definition: test_config.c:1992
static int customopt_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: test_config.c:1433
#define DOUBLE_DEFAULT
static int unload_module(void)
Definition: test_config.c:1975
#define BOOL_DEFAULT
#define TOOSMALL_I32
Definition: test_config.c:1053
struct association categories[]
#define CUSTOM_DEFAULT
#define TIMELEN_DEFAULT
#define SOCKADDR_CONFIG
#define BOOLFLAG1_DEFAULT
const char cat2varname3[]
Definition: test_config.c:81
#define DOUBLE_CONFIG
static struct aco_type item
Definition: test_config.c:1463
CONFIG_INFO_TEST(cfg_info, global_obj, test_config_alloc,.files=ACO_FILES(&config_test_conf),)
#define SOCKADDR_DEFAULT
FILE * out
Definition: utils/frame.c:33
int error(const char *format,...)
Definition: utils/frame.c:999
Utility functions.
#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:941
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ARRAY_LEN(a)
Definition: utils.h:666