test_config.c 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530
  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. * \file
  20. * \brief Configuration unit tests
  21. *
  22. * \author Mark Michelson <mmichelson@digium.com>
  23. *
  24. */
  25. /*** MODULEINFO
  26. <depend>TEST_FRAMEWORK</depend>
  27. <support_level>core</support_level>
  28. ***/
  29. #include "asterisk.h"
  30. ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
  31. #include <math.h> /* HUGE_VAL */
  32. #include "asterisk/config.h"
  33. #include "asterisk/module.h"
  34. #include "asterisk/test.h"
  35. #include "asterisk/paths.h"
  36. #include "asterisk/config_options.h"
  37. #include "asterisk/netsock2.h"
  38. #include "asterisk/acl.h"
  39. #include "asterisk/frame.h"
  40. #include "asterisk/utils.h"
  41. #include "asterisk/logger.h"
  42. #define CONFIG_FILE "test_config.conf"
  43. /*
  44. * This builds the folowing config:
  45. * [Capitals]
  46. * Germany = Berlin
  47. * China = Beijing
  48. * Canada = Ottawa
  49. *
  50. * [Protagonists]
  51. * 1984 = Winston Smith
  52. * Green Eggs And Ham = Sam I Am
  53. * The Kalevala = Vainamoinen
  54. *
  55. * This config is used for all tests below.
  56. */
  57. const char cat1[] = "Capitals";
  58. const char cat1varname1[] = "Germany";
  59. const char cat1varvalue1[] = "Berlin";
  60. const char cat1varname2[] = "China";
  61. const char cat1varvalue2[] = "Beijing";
  62. const char cat1varname3[] = "Canada";
  63. const char cat1varvalue3[] = "Ottawa";
  64. const char cat2[] = "Protagonists";
  65. const char cat2varname1[] = "1984";
  66. const char cat2varvalue1[] = "Winston Smith";
  67. const char cat2varname2[] = "Green Eggs And Ham";
  68. const char cat2varvalue2[] = "Sam I Am";
  69. const char cat2varname3[] = "The Kalevala";
  70. const char cat2varvalue3[] = "Vainamoinen";
  71. struct pair {
  72. const char *name;
  73. const char *val;
  74. };
  75. struct association {
  76. const char *category;
  77. struct pair vars[3];
  78. } categories [] = {
  79. { cat1,
  80. {
  81. { cat1varname1, cat1varvalue1 },
  82. { cat1varname2, cat1varvalue2 },
  83. { cat1varname3, cat1varvalue3 },
  84. }
  85. },
  86. { cat2,
  87. {
  88. { cat2varname1, cat2varvalue1 },
  89. { cat2varname2, cat2varvalue2 },
  90. { cat2varname3, cat2varvalue3 },
  91. }
  92. },
  93. };
  94. /*!
  95. * \brief Build ast_config struct from above definitions
  96. *
  97. * \retval NULL Failed to build the config
  98. * \retval non-NULL An ast_config struct populated with data
  99. */
  100. static struct ast_config *build_cfg(void)
  101. {
  102. struct ast_config *cfg;
  103. struct association *cat_iter;
  104. struct pair *var_iter;
  105. size_t i;
  106. size_t j;
  107. cfg = ast_config_new();
  108. if (!cfg) {
  109. goto fail;
  110. }
  111. for (i = 0; i < ARRAY_LEN(categories); ++i) {
  112. struct ast_category *cat;
  113. cat_iter = &categories[i];
  114. cat = ast_category_new(cat_iter->category, "", 999999);
  115. if (!cat) {
  116. goto fail;
  117. }
  118. ast_category_append(cfg, cat);
  119. for (j = 0; j < ARRAY_LEN(cat_iter->vars); ++j) {
  120. struct ast_variable *var;
  121. var_iter = &cat_iter->vars[j];
  122. var = ast_variable_new(var_iter->name, var_iter->val, "");
  123. if (!var) {
  124. goto fail;
  125. }
  126. ast_variable_append(cat, var);
  127. }
  128. }
  129. return cfg;
  130. fail:
  131. ast_config_destroy(cfg);
  132. return NULL;
  133. }
  134. /*!
  135. * \brief Tests that the contents of an ast_config is what is expected
  136. *
  137. * \param cfg Config to test
  138. * \retval -1 Failed to pass a test
  139. * \retval 0 Config passes checks
  140. */
  141. static int test_config_validity(struct ast_config *cfg)
  142. {
  143. int i;
  144. const char *cat_iter = NULL;
  145. /* Okay, let's see if the correct content is there */
  146. for (i = 0; i < ARRAY_LEN(categories); ++i) {
  147. struct ast_variable *var = NULL;
  148. size_t j;
  149. cat_iter = ast_category_browse(cfg, cat_iter);
  150. if (strcmp(cat_iter, categories[i].category)) {
  151. ast_log(LOG_ERROR, "Category name mismatch, %s does not match %s\n", cat_iter, categories[i].category);
  152. return -1;
  153. }
  154. for (j = 0; j < ARRAY_LEN(categories[i].vars); ++j) {
  155. var = var ? var->next : ast_variable_browse(cfg, cat_iter);
  156. if (strcmp(var->name, categories[i].vars[j].name)) {
  157. ast_log(LOG_ERROR, "Variable name mismatch, %s does not match %s\n", var->name, categories[i].vars[j].name);
  158. return -1;
  159. }
  160. if (strcmp(var->value, categories[i].vars[j].val)) {
  161. ast_log(LOG_ERROR, "Variable value mismatch, %s does not match %s\n", var->value, categories[i].vars[j].val);
  162. return -1;
  163. }
  164. }
  165. }
  166. return 0;
  167. }
  168. AST_TEST_DEFINE(copy_config)
  169. {
  170. enum ast_test_result_state res = AST_TEST_FAIL;
  171. struct ast_config *cfg = NULL;
  172. struct ast_config *copy = NULL;
  173. switch (cmd) {
  174. case TEST_INIT:
  175. info->name = "copy_config";
  176. info->category = "/main/config/";
  177. info->summary = "Test copying configuration";
  178. info->description =
  179. "Ensure that variables and categories are copied correctly";
  180. return AST_TEST_NOT_RUN;
  181. case TEST_EXECUTE:
  182. break;
  183. }
  184. cfg = build_cfg();
  185. if (!cfg) {
  186. goto out;
  187. }
  188. copy = ast_config_copy(cfg);
  189. if (!copy) {
  190. goto out;
  191. }
  192. if (test_config_validity(copy) != 0) {
  193. goto out;
  194. }
  195. res = AST_TEST_PASS;
  196. out:
  197. ast_config_destroy(cfg);
  198. ast_config_destroy(copy);
  199. return res;
  200. }
  201. AST_TEST_DEFINE(config_basic_ops)
  202. {
  203. enum ast_test_result_state res = AST_TEST_FAIL;
  204. struct ast_config *cfg = NULL;
  205. struct ast_category *cat = NULL;
  206. struct ast_variable *var;
  207. char temp[32];
  208. const char *cat_name;
  209. const char *var_value;
  210. int i;
  211. switch (cmd) {
  212. case TEST_INIT:
  213. info->name = "config_basic_ops";
  214. info->category = "/main/config/";
  215. info->summary = "Test basic config ops";
  216. info->description = "Test basic config ops";
  217. return AST_TEST_NOT_RUN;
  218. case TEST_EXECUTE:
  219. break;
  220. }
  221. cfg = ast_config_new();
  222. if (!cfg) {
  223. return res;
  224. }
  225. /* load the config */
  226. for(i = 0; i < 5; i++) {
  227. snprintf(temp, sizeof(temp), "test%d", i);
  228. ast_category_append(cfg, ast_category_new(temp, "dummy", -1));
  229. }
  230. /* test0 test1 test2 test3 test4 */
  231. /* check the config has 5 elements */
  232. i = 0;
  233. cat = NULL;
  234. while ((cat = ast_category_browse_filtered(cfg, NULL, cat, NULL))) {
  235. snprintf(temp, sizeof(temp), "test%d", i);
  236. if (strcmp(ast_category_get_name(cat), temp)) {
  237. ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
  238. goto out;
  239. }
  240. i++;
  241. }
  242. if (i != 5) {
  243. ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
  244. goto out;
  245. }
  246. /* search for test2 */
  247. cat = ast_category_get(cfg, "test2", NULL);
  248. if (!cat || strcmp(ast_category_get_name(cat), "test2")) {
  249. ast_test_status_update(test, "Get failed %s != %s\n", ast_category_get_name(cat), "test2");
  250. goto out;
  251. }
  252. /* delete test2 */
  253. cat = ast_category_delete(cfg, cat);
  254. /* Now: test0 test1 test3 test4 */
  255. /* make sure the curr category is test1 */
  256. if (!cat || strcmp(ast_category_get_name(cat), "test1")) {
  257. ast_test_status_update(test, "Delete failed %s != %s\n", ast_category_get_name(cat), "test1");
  258. goto out;
  259. }
  260. /* Now: test0 test1 test3 test4 */
  261. /* make sure the test2 is not found */
  262. cat = ast_category_get(cfg, "test2", NULL);
  263. if (cat) {
  264. ast_test_status_update(test, "Should not have found test2\n");
  265. goto out;
  266. }
  267. /* Now: test0 test1 test3 test4 */
  268. /* make sure the sequence is correctly missing test2 */
  269. i = 0;
  270. cat = NULL;
  271. while ((cat = ast_category_browse_filtered(cfg, NULL, cat, NULL))) {
  272. snprintf(temp, sizeof(temp), "test%d", i);
  273. if (strcmp(ast_category_get_name(cat), temp)) {
  274. ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
  275. goto out;
  276. }
  277. i++;
  278. if (i == 2) {
  279. i++;
  280. }
  281. }
  282. if (i != 5) {
  283. ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
  284. goto out;
  285. }
  286. /* insert test2 back in before test3 */
  287. ast_category_insert(cfg, ast_category_new("test2", "dummy", -1), "test3");
  288. /* Now: test0 test1 test2 test3 test4 */
  289. /* make sure the sequence is correct again */
  290. i = 0;
  291. cat = NULL;
  292. while ((cat = ast_category_browse_filtered(cfg, NULL, cat, NULL))) {
  293. snprintf(temp, sizeof(temp), "test%d", i);
  294. if (strcmp(ast_category_get_name(cat), temp)) {
  295. ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
  296. goto out;
  297. }
  298. i++;
  299. }
  300. if (i != 5) {
  301. ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
  302. goto out;
  303. }
  304. /* Now: test0 test1 test2 test3 test4 */
  305. /* make sure non filtered browse still works */
  306. i = 0;
  307. cat_name = NULL;
  308. while ((cat_name = ast_category_browse(cfg, cat_name))) {
  309. snprintf(temp, sizeof(temp), "test%d", i);
  310. if (strcmp(cat_name, temp)) {
  311. ast_test_status_update(test, "%s != %s\n", cat_name, temp);
  312. goto out;
  313. }
  314. i++;
  315. }
  316. if (i != 5) {
  317. ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
  318. goto out;
  319. }
  320. /* append another test2 */
  321. ast_category_append(cfg, ast_category_new("test2", "dummy", -1));
  322. /* Now: test0 test1 test2 test3 test4 test2*/
  323. /* make sure only test2's are returned */
  324. i = 0;
  325. cat = NULL;
  326. while ((cat = ast_category_browse_filtered(cfg, "test2", cat, NULL))) {
  327. if (strcmp(ast_category_get_name(cat), "test2")) {
  328. ast_test_status_update(test, "Should have returned test2 instead of %s\n", ast_category_get_name(cat));
  329. goto out;
  330. }
  331. i++;
  332. }
  333. /* make sure 2 test2's were found */
  334. if (i != 2) {
  335. ast_test_status_update(test, "Should have found 2 test2's %d\n", i);
  336. goto out;
  337. }
  338. /* Test in-flight deletion using ast_category_browse_filtered */
  339. /* Now: test0 test1 test2 test3 test4 test2 */
  340. /* Delete the middle test2 and continue */
  341. cat = NULL;
  342. for(i = 0; i < 5; i++) {
  343. snprintf(temp, sizeof(temp), "test%d", i);
  344. cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
  345. cat_name = ast_category_get_name(cat);
  346. if (strcmp(cat_name, temp)) {
  347. ast_test_status_update(test, "Should have returned %s instead of %s: %d\n", temp, cat_name, i);
  348. goto out;
  349. }
  350. if (i == 2) {
  351. cat = ast_category_delete(cfg, cat);
  352. }
  353. }
  354. /* Now: test0 test3 test4 test2 */
  355. /* delete the head item */
  356. cat = ast_category_browse_filtered(cfg, NULL, NULL, NULL);
  357. cat_name = ast_category_get_name(cat);
  358. if (strcmp(cat_name, "test0")) {
  359. ast_test_status_update(test, "Should have returned test0 instead of %s\n", cat_name);
  360. goto out;
  361. }
  362. ast_category_delete(cfg, cat);
  363. /* Now: test3 test4 test2 */
  364. /* make sure head got updated to the new first element */
  365. cat = ast_category_browse_filtered(cfg, NULL, NULL, NULL);
  366. cat_name = ast_category_get_name(cat);
  367. if (strcmp(cat_name, "test1")) {
  368. ast_test_status_update(test, "Should have returned test3 instead of %s\n", cat_name);
  369. goto out;
  370. }
  371. /* delete the tail item */
  372. cat = ast_category_get(cfg, "test2", NULL);
  373. cat_name = ast_category_get_name(cat);
  374. if (strcmp(cat_name, "test2")) {
  375. ast_test_status_update(test, "Should have returned test2 instead of %s\n", cat_name);
  376. goto out;
  377. }
  378. ast_category_delete(cfg, cat);
  379. /* Now: test3 test4 */
  380. /* There should now only be 2 elements in the list */
  381. cat = NULL;
  382. cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
  383. cat_name = ast_category_get_name(cat);
  384. if (strcmp(cat_name, "test1")) {
  385. ast_test_status_update(test, "Should have returned test1 instead of %s\n", cat_name);
  386. goto out;
  387. }
  388. cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
  389. cat_name = ast_category_get_name(cat);
  390. if (strcmp(cat_name, "test3")) {
  391. ast_test_status_update(test, "Should have returned test3 instead of %s\n", cat_name);
  392. goto out;
  393. }
  394. cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
  395. cat_name = ast_category_get_name(cat);
  396. if (strcmp(cat_name, "test4")) {
  397. ast_test_status_update(test, "Should have returned test4 instead of %s\n", cat_name);
  398. goto out;
  399. }
  400. /* There should be nothing more */
  401. cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
  402. if (cat) {
  403. ast_test_status_update(test, "Should not have returned anything\n");
  404. goto out;
  405. }
  406. /* Test ast_variable retrieve.
  407. * Get the second category.
  408. */
  409. cat = ast_category_browse_filtered(cfg, NULL, NULL, NULL);
  410. cat = ast_category_browse_filtered(cfg, NULL, cat, NULL);
  411. cat_name = ast_category_get_name(cat);
  412. var = ast_variable_new("aaa", "bbb0", "dummy");
  413. if (!var) {
  414. ast_test_status_update(test, "Couldn't allocate variable.\n");
  415. goto out;
  416. }
  417. ast_variable_append(cat, var);
  418. /* Make sure we can retrieve with specific category name */
  419. var_value = ast_variable_retrieve(cfg, cat_name, "aaa");
  420. if (!var_value || strcmp(var_value, "bbb0")) {
  421. ast_test_status_update(test, "Variable not found or wrong value.\n");
  422. goto out;
  423. }
  424. /* Make sure we can retrieve with NULL category name */
  425. var_value = ast_variable_retrieve(cfg, NULL, "aaa");
  426. if (!var_value || strcmp(var_value, "bbb0")) {
  427. ast_test_status_update(test, "Variable not found or wrong value.\n");
  428. goto out;
  429. }
  430. /* Now test variable retrieve inside a browse loop
  431. * with multiple categories of the same name
  432. */
  433. cat = ast_category_new("test3", "dummy", -1);
  434. if (!cat) {
  435. ast_test_status_update(test, "Couldn't allocate category.\n");
  436. goto out;
  437. }
  438. var = ast_variable_new("aaa", "bbb1", "dummy");
  439. if (!var) {
  440. ast_test_status_update(test, "Couldn't allocate variable.\n");
  441. goto out;
  442. }
  443. ast_variable_append(cat, var);
  444. ast_category_append(cfg, cat);
  445. cat = ast_category_new("test3", "dummy", -1);
  446. if (!cat) {
  447. ast_test_status_update(test, "Couldn't allocate category.\n");
  448. goto out;
  449. }
  450. var = ast_variable_new("aaa", "bbb2", "dummy");
  451. if (!var) {
  452. ast_test_status_update(test, "Couldn't allocate variable.\n");
  453. goto out;
  454. }
  455. ast_variable_append(cat, var);
  456. ast_category_append(cfg, cat);
  457. cat_name = NULL;
  458. i = 0;
  459. while ((cat_name = ast_category_browse(cfg, cat_name))) {
  460. if (!strcmp(cat_name, "test3")) {
  461. snprintf(temp, sizeof(temp), "bbb%d", i);
  462. var_value = ast_variable_retrieve(cfg, cat_name, "aaa");
  463. if (!var_value || strcmp(var_value, temp)) {
  464. ast_test_status_update(test, "Variable not found or wrong value %s.\n", var_value);
  465. goto out;
  466. }
  467. var = ast_variable_browse(cfg, cat_name);
  468. if (!var->value || strcmp(var->value, temp)) {
  469. ast_test_status_update(test, "Variable not found or wrong value %s.\n", var->value);
  470. goto out;
  471. }
  472. i++;
  473. }
  474. }
  475. if (i != 3) {
  476. ast_test_status_update(test, "There should have been 3 matches instead of %d.\n", i);
  477. goto out;
  478. }
  479. res = AST_TEST_PASS;
  480. out:
  481. ast_config_destroy(cfg);
  482. return res;
  483. }
  484. AST_TEST_DEFINE(config_filtered_ops)
  485. {
  486. enum ast_test_result_state res = AST_TEST_FAIL;
  487. struct ast_config *cfg = NULL;
  488. struct ast_category *cat = NULL;
  489. char temp[32];
  490. const char *value;
  491. int i;
  492. switch (cmd) {
  493. case TEST_INIT:
  494. info->name = "config_filtered_ops";
  495. info->category = "/main/config/";
  496. info->summary = "Test filtered config ops";
  497. info->description = "Test filtered config ops";
  498. return AST_TEST_NOT_RUN;
  499. case TEST_EXECUTE:
  500. break;
  501. }
  502. cfg = ast_config_new();
  503. if (!cfg) {
  504. return res;
  505. }
  506. /* load the config */
  507. for(i = 0; i < 5; i++) {
  508. snprintf(temp, sizeof(temp), "test%d", i);
  509. cat = ast_category_new(temp, "dummy", -1);
  510. ast_variable_insert(cat, ast_variable_new("type", "a", "dummy"), "0");
  511. ast_category_append(cfg, cat);
  512. }
  513. for(i = 0; i < 5; i++) {
  514. snprintf(temp, sizeof(temp), "test%d", i);
  515. cat = ast_category_new(temp, "dummy", -1);
  516. ast_variable_insert(cat, ast_variable_new("type", "b", "dummy"), "0");
  517. ast_category_append(cfg, cat);
  518. }
  519. /* check the config has 5 elements for each type*/
  520. i = 0;
  521. cat = NULL;
  522. while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "type=a"))) {
  523. snprintf(temp, sizeof(temp), "test%d", i);
  524. if (strcmp(ast_category_get_name(cat), temp)) {
  525. ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
  526. goto out;
  527. }
  528. value = ast_variable_find(cat, "type");
  529. if (!value || strcmp(value, "a")) {
  530. ast_test_status_update(test, "Type %s != %s\n", "a", value);
  531. goto out;
  532. }
  533. i++;
  534. }
  535. if (i != 5) {
  536. ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
  537. goto out;
  538. }
  539. i = 0;
  540. cat = NULL;
  541. while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "type=b"))) {
  542. snprintf(temp, sizeof(temp), "test%d", i);
  543. if (!cat || strcmp(ast_category_get_name(cat), temp)) {
  544. ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
  545. goto out;
  546. }
  547. value = ast_variable_find(cat, "type");
  548. if (!value || strcmp(value, "b")) {
  549. ast_test_status_update(test, "Type %s != %s\n", "b", value);
  550. goto out;
  551. }
  552. i++;
  553. }
  554. if (i != 5) {
  555. ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
  556. goto out;
  557. }
  558. /* Delete b3 and make sure it's gone and a3 is still there.
  559. * Really this is a test of get since delete takes a specific category structure.
  560. */
  561. cat = ast_category_get(cfg, "test3", "type=b");
  562. value = ast_variable_find(cat, "type");
  563. if (strcmp(value, "b")) {
  564. ast_test_status_update(test, "Type %s != %s\n", "b", value);
  565. goto out;
  566. }
  567. ast_category_delete(cfg, cat);
  568. cat = ast_category_get(cfg, "test3", "type=b");
  569. if (cat) {
  570. ast_test_status_update(test, "Category b was not deleted.\n");
  571. goto out;
  572. }
  573. cat = ast_category_get(cfg, "test3", "type=a");
  574. if (!cat) {
  575. ast_test_status_update(test, "Category a was deleted.\n");
  576. goto out;
  577. }
  578. value = ast_variable_find(cat, "type");
  579. if (strcmp(value, "a")) {
  580. ast_test_status_update(test, "Type %s != %s\n", value, "a");
  581. goto out;
  582. }
  583. /* Basic regex stuff is handled by regcomp/regexec so not testing here.
  584. * Still need to test multiple name/value pairs though.
  585. */
  586. ast_category_empty(cat);
  587. ast_variable_insert(cat, ast_variable_new("type", "bx", "dummy"), "0");
  588. ast_variable_insert(cat, ast_variable_new("e", "z", "dummy"), "0");
  589. cat = ast_category_get(cfg, "test3", "type=.,e=z");
  590. if (!cat) {
  591. ast_test_status_update(test, "Category not found.\n");
  592. goto out;
  593. }
  594. cat = ast_category_get(cfg, "test3", "type=.,e=zX");
  595. if (cat) {
  596. ast_test_status_update(test, "Category found.\n");
  597. goto out;
  598. }
  599. cat = ast_category_get(cfg, "test3", "TEMPLATE=restrict,type=.,e=z");
  600. if (cat) {
  601. ast_test_status_update(test, "Category found.\n");
  602. goto out;
  603. }
  604. res = AST_TEST_PASS;
  605. out:
  606. ast_config_destroy(cfg);
  607. return res;
  608. }
  609. AST_TEST_DEFINE(config_template_ops)
  610. {
  611. enum ast_test_result_state res = AST_TEST_FAIL;
  612. struct ast_config *cfg = NULL;
  613. struct ast_category *cat = NULL;
  614. char temp[32];
  615. const char *value;
  616. int i;
  617. switch (cmd) {
  618. case TEST_INIT:
  619. info->name = "config_template_ops";
  620. info->category = "/main/config/";
  621. info->summary = "Test template config ops";
  622. info->description = "Test template config ops";
  623. return AST_TEST_NOT_RUN;
  624. case TEST_EXECUTE:
  625. break;
  626. }
  627. cfg = ast_config_new();
  628. if (!cfg) {
  629. return res;
  630. }
  631. /* load the config with 5 templates and 5 regular */
  632. for(i = 0; i < 5; i++) {
  633. snprintf(temp, sizeof(temp), "test%d", i);
  634. cat = ast_category_new_template(temp, "dummy", -1);
  635. ast_variable_insert(cat, ast_variable_new("type", "a", "dummy"), "0");
  636. ast_category_append(cfg, cat);
  637. }
  638. for(i = 0; i < 5; i++) {
  639. snprintf(temp, sizeof(temp), "test%d", i);
  640. cat = ast_category_new(temp, "dummy", -1);
  641. ast_variable_insert(cat, ast_variable_new("type", "b", "dummy"), "0");
  642. ast_category_append(cfg, cat);
  643. }
  644. /* check the config has 5 template elements of type a */
  645. i = 0;
  646. cat = NULL;
  647. while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "TEMPLATES=restrict,type=a"))) {
  648. snprintf(temp, sizeof(temp), "test%d", i);
  649. if (strcmp(ast_category_get_name(cat), temp)) {
  650. ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
  651. goto out;
  652. }
  653. value = ast_variable_find(cat, "type");
  654. if (!value || strcmp(value, "a")) {
  655. ast_test_status_update(test, "Type %s != %s\n", value, "a");
  656. goto out;
  657. }
  658. i++;
  659. }
  660. if (i != 5) {
  661. ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
  662. goto out;
  663. }
  664. /* Test again with 'include'. There should still only be 5 (type a) */
  665. i = 0;
  666. cat = NULL;
  667. while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "TEMPLATES=include,type=a"))) {
  668. snprintf(temp, sizeof(temp), "test%d", i);
  669. if (strcmp(ast_category_get_name(cat), temp)) {
  670. ast_test_status_update(test, "%s != %s\n", ast_category_get_name(cat), temp);
  671. goto out;
  672. }
  673. value = ast_variable_find(cat, "type");
  674. if (!value || strcmp(value, "a")) {
  675. ast_test_status_update(test, "Type %s != %s\n", value, "a");
  676. goto out;
  677. }
  678. i++;
  679. }
  680. if (i != 5) {
  681. ast_test_status_update(test, "There were %d matches instead of 5.\n", i);
  682. goto out;
  683. }
  684. /* Test again with 'include' but no type. There should now be 10 (type a and type b) */
  685. i = 0;
  686. cat = NULL;
  687. while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "TEMPLATES=include"))) {
  688. i++;
  689. }
  690. if (i != 10) {
  691. ast_test_status_update(test, "There were %d matches instead of 10.\n", i);
  692. goto out;
  693. }
  694. /* Test again with 'restrict' and type b. There should 0 */
  695. i = 0;
  696. cat = NULL;
  697. while ((cat = ast_category_browse_filtered(cfg, NULL, cat, "TEMPLATES=restrict,type=b"))) {
  698. i++;
  699. }
  700. if (i != 0) {
  701. ast_test_status_update(test, "There were %d matches instead of 0.\n", i);
  702. goto out;
  703. }
  704. res = AST_TEST_PASS;
  705. out:
  706. ast_config_destroy(cfg);
  707. return res;
  708. }
  709. /*!
  710. * \brief Write the config file to disk
  711. *
  712. * This is necessary for testing config hooks since
  713. * they are only triggered when a config is read from
  714. * its intended storage medium
  715. */
  716. static int write_config_file(void)
  717. {
  718. int i;
  719. FILE *config_file;
  720. char filename[PATH_MAX];
  721. snprintf(filename, sizeof(filename), "%s/%s",
  722. ast_config_AST_CONFIG_DIR, CONFIG_FILE);
  723. config_file = fopen(filename, "w");
  724. if (!config_file) {
  725. return -1;
  726. }
  727. for (i = 0; i < ARRAY_LEN(categories); ++i) {
  728. int j;
  729. fprintf(config_file, "[%s]\n", categories[i].category);
  730. for (j = 0; j < ARRAY_LEN(categories[i].vars); ++j) {
  731. fprintf(config_file, "%s = %s\n",
  732. categories[i].vars[j].name,
  733. categories[i].vars[j].val);
  734. }
  735. }
  736. fclose(config_file);
  737. return 0;
  738. }
  739. /*!
  740. * \brief Delete config file created by write_config_file
  741. */
  742. static void delete_config_file(void)
  743. {
  744. char filename[PATH_MAX];
  745. snprintf(filename, sizeof(filename), "%s/%s",
  746. ast_config_AST_CONFIG_DIR, CONFIG_FILE);
  747. unlink(filename);
  748. }
  749. /*
  750. * Boolean to indicate if the config hook has run
  751. */
  752. static int hook_run;
  753. /*
  754. * Boolean to indicate if, when the hook runs, the
  755. * data passed to it is what is expected
  756. */
  757. static int hook_config_sane;
  758. static int hook_cb(struct ast_config *cfg)
  759. {
  760. hook_run = 1;
  761. if (test_config_validity(cfg) == 0) {
  762. hook_config_sane = 1;
  763. }
  764. ast_config_destroy(cfg);
  765. return 0;
  766. }
  767. AST_TEST_DEFINE(config_hook)
  768. {
  769. enum ast_test_result_state res = AST_TEST_FAIL;
  770. enum config_hook_flags hook_flags = { 0, };
  771. struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED };
  772. struct ast_config *cfg;
  773. switch (cmd) {
  774. case TEST_INIT:
  775. info->name = "config_hook";
  776. info->category = "/main/config/";
  777. info->summary = "Test config hooks";
  778. info->description =
  779. "Ensure that config hooks are called at approriate times,"
  780. "not called at inappropriate times, and that all information"
  781. "that should be present is present.";
  782. return AST_TEST_NOT_RUN;
  783. case TEST_EXECUTE:
  784. break;
  785. }
  786. write_config_file();
  787. /*
  788. * Register a config hook to run when CONFIG_FILE is loaded by this module
  789. */
  790. ast_config_hook_register("test_hook",
  791. CONFIG_FILE,
  792. AST_MODULE,
  793. hook_flags,
  794. hook_cb);
  795. /*
  796. * Try loading the config file. This should result in the hook
  797. * being called
  798. */
  799. cfg = ast_config_load(CONFIG_FILE, config_flags);
  800. ast_config_destroy(cfg);
  801. if (!hook_run || !hook_config_sane) {
  802. ast_test_status_update(test, "Config hook either did not run or was given bad data!\n");
  803. goto out;
  804. }
  805. /*
  806. * Now try loading the wrong config file but from the right module.
  807. * Hook should not run
  808. */
  809. hook_run = 0;
  810. cfg = ast_config_load("asterisk.conf", config_flags);
  811. ast_config_destroy(cfg);
  812. if (hook_run) {
  813. ast_test_status_update(test, "Config hook ran even though an incorrect file was specified.\n");
  814. goto out;
  815. }
  816. /*
  817. * Now try loading the correct config file but from the wrong module.
  818. * Hook should not run
  819. */
  820. hook_run = 0;
  821. cfg = ast_config_load2(CONFIG_FILE, "fake_module.so", config_flags);
  822. ast_config_destroy(cfg);
  823. if (hook_run) {
  824. ast_test_status_update(test, "Config hook ran even though an incorrect module was specified.\n");
  825. goto out;
  826. }
  827. /*
  828. * Now try loading the file correctly, but without any changes to the file.
  829. * Hook should not run
  830. */
  831. hook_run = 0;
  832. cfg = ast_config_load(CONFIG_FILE, config_flags);
  833. /* Only destroy this cfg conditionally. Otherwise a crash happens. */
  834. if (cfg != CONFIG_STATUS_FILEUNCHANGED) {
  835. ast_config_destroy(cfg);
  836. }
  837. if (hook_run) {
  838. ast_test_status_update(test, "Config hook ran even though file contents had not changed\n");
  839. goto out;
  840. }
  841. res = AST_TEST_PASS;
  842. out:
  843. delete_config_file();
  844. return res;
  845. }
  846. enum {
  847. EXPECT_FAIL = 0,
  848. EXPECT_SUCCEED,
  849. };
  850. #define TOOBIG_I32 "2147483649"
  851. #define TOOSMALL_I32 "-2147483649"
  852. #define TOOBIG_U32 "4294967297"
  853. #define TOOSMALL_U32 "-4294967297"
  854. #define DEFAULTVAL 42
  855. #define EPSILON 0.001
  856. #define TEST_PARSE(input, should_succeed, expected_result, flags, result, ...) do {\
  857. int __res = ast_parse_arg(input, (flags), result, ##__VA_ARGS__); \
  858. if (!__res == !should_succeed) { \
  859. ast_test_status_update(test, "ast_parse_arg failed on '%s'. %d/%d\n", input, __res, should_succeed); \
  860. ret = AST_TEST_FAIL; \
  861. } else { \
  862. if (((flags) & PARSE_TYPE) == PARSE_INT32) { \
  863. int32_t *r = (int32_t *) (void *) result; \
  864. int32_t e = (int32_t) expected_result; \
  865. if (*r != e) { \
  866. ast_test_status_update(test, "ast_parse_arg int32_t failed with %d != %d\n", *r, e); \
  867. ret = AST_TEST_FAIL; \
  868. } \
  869. } else if (((flags) & PARSE_TYPE) == PARSE_UINT32) { \
  870. uint32_t *r = (uint32_t *) (void *) result; \
  871. uint32_t e = (uint32_t) expected_result; \
  872. if (*r != e) { \
  873. ast_test_status_update(test, "ast_parse_arg uint32_t failed with %u != %u\n", *r, e); \
  874. ret = AST_TEST_FAIL; \
  875. } \
  876. } else if (((flags) & PARSE_TYPE) == PARSE_DOUBLE) { \
  877. double *r = (double *) (void *) result; \
  878. double e = (double) expected_result; \
  879. if (fabs(*r - e) > EPSILON) { \
  880. ast_test_status_update(test, "ast_parse_arg double failed with %f != %f\n", *r, e); \
  881. ret = AST_TEST_FAIL; \
  882. } \
  883. } \
  884. } \
  885. *(result) = DEFAULTVAL; \
  886. } while (0)
  887. AST_TEST_DEFINE(ast_parse_arg_test)
  888. {
  889. int ret = AST_TEST_PASS;
  890. int32_t int32_t_val = DEFAULTVAL;
  891. uint32_t uint32_t_val = DEFAULTVAL;
  892. double double_val = DEFAULTVAL;
  893. switch (cmd) {
  894. case TEST_INIT:
  895. info->name = "ast_parse_arg";
  896. info->category = "/config/";
  897. info->summary = "Test the output of ast_parse_arg";
  898. info->description =
  899. "Ensures that ast_parse_arg behaves as expected";
  900. return AST_TEST_NOT_RUN;
  901. case TEST_EXECUTE:
  902. break;
  903. }
  904. /* int32 testing */
  905. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32, &int32_t_val);
  906. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32, &int32_t_val);
  907. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32, &int32_t_val);
  908. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
  909. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
  910. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
  911. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
  912. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  913. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  914. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  915. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  916. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  917. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  918. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  919. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, 0, 200);
  920. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, -200, 100);
  921. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, -1, 0);
  922. TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, 0, 122);
  923. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, -122, 100);
  924. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, 1, 100);
  925. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  926. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  927. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  928. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  929. TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, 0, 200);
  930. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, -200, 100);
  931. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, -1, 0);
  932. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, 0, 122);
  933. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, -122, 100);
  934. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, 1, 100);
  935. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  936. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  937. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  938. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  939. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, 0, 200);
  940. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, -200, 100);
  941. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, -1, 0);
  942. TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, 0, 122);
  943. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, -122, 100);
  944. TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, 1, 100);
  945. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  946. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  947. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  948. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  949. TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, 0, 200);
  950. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, -200, 100);
  951. TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, -1, 0);
  952. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, 0, 122);
  953. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, -122, 100);
  954. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, 1, 100);
  955. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  956. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  957. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  958. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  959. /* uuint32 testing */
  960. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32, &uint32_t_val);
  961. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  962. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32, &uint32_t_val);
  963. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  964. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  965. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  966. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  967. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  968. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  969. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  970. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  971. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  972. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  973. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  974. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 200);
  975. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 200);
  976. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 1);
  977. TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 122);
  978. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 1, 100);
  979. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  980. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  981. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  982. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  983. TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 200);
  984. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 200);
  985. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 1);
  986. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 122);
  987. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 1, 100);
  988. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  989. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  990. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  991. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  992. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 200);
  993. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 200);
  994. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 1);
  995. TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 122);
  996. TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 1, 100);
  997. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  998. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  999. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  1000. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  1001. TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 200);
  1002. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 100);
  1003. TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 1);
  1004. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 122);
  1005. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 1, 100);
  1006. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  1007. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  1008. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  1009. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  1010. TEST_PARSE(" -123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  1011. /* double testing */
  1012. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_DOUBLE, &double_val);
  1013. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE, &double_val);
  1014. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_DOUBLE, &double_val);
  1015. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE, &double_val);
  1016. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE, &double_val);
  1017. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE, &double_val);
  1018. TEST_PARSE("7.0not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE, &double_val);
  1019. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  1020. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  1021. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  1022. TEST_PARSE("not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  1023. TEST_PARSE("7.0not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  1024. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, 0.0, 200.0);
  1025. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -200.0, 100.0);
  1026. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -1.0, 0.0);
  1027. TEST_PARSE("123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, 0.0, 122.0);
  1028. TEST_PARSE("-123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -122.0, 100.0);
  1029. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, 1.0, 100.0);
  1030. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
  1031. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
  1032. TEST_PARSE("123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, 0.0, 200.0);
  1033. TEST_PARSE("-123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -200.0, 100.0);
  1034. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -1.0, 0.0);
  1035. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, 0.0, 122.0);
  1036. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -122.0, 100.0);
  1037. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, 1.0, 100.0);
  1038. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
  1039. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
  1040. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, 0.0, 200.0);
  1041. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -200.0, 100.0);
  1042. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -1.0, 0.0);
  1043. TEST_PARSE("123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, 0.0, 122.0);
  1044. TEST_PARSE("-123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -122.0, 100.0);
  1045. TEST_PARSE("0", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, 1.0, 100.0);
  1046. TEST_PARSE("not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
  1047. TEST_PARSE("7not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
  1048. TEST_PARSE("123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, 0.0, 200.0);
  1049. TEST_PARSE("-123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -200.0, 100.0);
  1050. TEST_PARSE("0", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -1.0, 0.0);
  1051. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, 0.0, 122.0);
  1052. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -122.0, 100.0);
  1053. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, 1.0, 100.0);
  1054. TEST_PARSE("not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
  1055. TEST_PARSE("7not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
  1056. /* ast_sockaddr_parse is tested extensively in test_netsock2.c and PARSE_ADDR is a very simple wrapper */
  1057. return ret;
  1058. }
  1059. struct test_item {
  1060. AST_DECLARE_STRING_FIELDS(
  1061. AST_STRING_FIELD(name);
  1062. AST_STRING_FIELD(stropt);
  1063. );
  1064. int32_t intopt;
  1065. uint32_t uintopt;
  1066. unsigned int flags;
  1067. double doubleopt;
  1068. struct ast_sockaddr sockaddropt;
  1069. int boolopt;
  1070. struct ast_ha *aclopt;
  1071. struct ast_codec_pref codecprefopt;
  1072. struct ast_format_cap *codeccapopt;
  1073. unsigned int customopt:1;
  1074. };
  1075. struct test_config {
  1076. struct test_item *global;
  1077. struct test_item *global_defaults;
  1078. struct ao2_container *items;
  1079. };
  1080. static int test_item_hash(const void *obj, const int flags)
  1081. {
  1082. const struct test_item *item = obj;
  1083. const char *name = (flags & OBJ_KEY) ? obj : item->name;
  1084. return ast_str_case_hash(name);
  1085. }
  1086. static int test_item_cmp(void *obj, void *arg, int flags)
  1087. {
  1088. struct test_item *one = obj, *two = arg;
  1089. const char *match = (flags & OBJ_KEY) ? arg : two->name;
  1090. return strcasecmp(one->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
  1091. }
  1092. static void test_item_destructor(void *obj)
  1093. {
  1094. struct test_item *item = obj;
  1095. ast_string_field_free_memory(item);
  1096. if (item->codeccapopt) {
  1097. ast_format_cap_destroy(item->codeccapopt);
  1098. }
  1099. if (item->aclopt) {
  1100. ast_free_ha(item->aclopt);
  1101. }
  1102. return;
  1103. }
  1104. static void *test_item_alloc(const char *cat)
  1105. {
  1106. struct test_item *item;
  1107. if (!(item = ao2_alloc(sizeof(*item), test_item_destructor))) {
  1108. return NULL;
  1109. }
  1110. if (ast_string_field_init(item, 128)) {
  1111. ao2_ref(item, -1);
  1112. return NULL;
  1113. }
  1114. if (!(item->codeccapopt = ast_format_cap_alloc(0))) {
  1115. ao2_ref(item, -1);
  1116. return NULL;
  1117. }
  1118. ast_string_field_set(item, name, cat);
  1119. return item;
  1120. }
  1121. static void test_config_destructor(void *obj)
  1122. {
  1123. struct test_config *cfg = obj;
  1124. ao2_cleanup(cfg->global);
  1125. ao2_cleanup(cfg->global_defaults);
  1126. ao2_cleanup(cfg->items);
  1127. }
  1128. static void *test_config_alloc(void)
  1129. {
  1130. struct test_config *cfg;
  1131. if (!(cfg = ao2_alloc(sizeof(*cfg), test_config_destructor))) {
  1132. goto error;
  1133. }
  1134. if (!(cfg->global = test_item_alloc("global"))) {
  1135. goto error;
  1136. }
  1137. if (!(cfg->global_defaults = test_item_alloc("global_defaults"))) {
  1138. goto error;
  1139. }
  1140. if (!(cfg->items = ao2_container_alloc(1, test_item_hash, test_item_cmp))) {
  1141. goto error;
  1142. }
  1143. return cfg;
  1144. error:
  1145. ao2_cleanup(cfg);
  1146. return NULL;
  1147. }
  1148. static void *test_item_find(struct ao2_container *container, const char *cat)
  1149. {
  1150. return ao2_find(container, cat, OBJ_KEY);
  1151. }
  1152. static int customopt_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  1153. {
  1154. struct test_item *item = obj;
  1155. if (!strcasecmp(var->name, "customopt")) {
  1156. item->customopt = ast_true(var->value);
  1157. } else {
  1158. return -1;
  1159. }
  1160. return 0;
  1161. }
  1162. static struct aco_type global = {
  1163. .type = ACO_GLOBAL,
  1164. .item_offset = offsetof(struct test_config, global),
  1165. .category_match = ACO_WHITELIST,
  1166. .category = "^global$",
  1167. };
  1168. static struct aco_type global_defaults = {
  1169. .type = ACO_GLOBAL,
  1170. .item_offset = offsetof(struct test_config, global_defaults),
  1171. .category_match = ACO_WHITELIST,
  1172. .category = "^global_defaults$",
  1173. };
  1174. static struct aco_type item = {
  1175. .type = ACO_ITEM,
  1176. .category_match = ACO_BLACKLIST,
  1177. .category = "^(global|global_defaults)$",
  1178. .item_alloc = test_item_alloc,
  1179. .item_find = test_item_find,
  1180. .item_offset = offsetof(struct test_config, items),
  1181. };
  1182. struct aco_file config_test_conf = {
  1183. .filename = "config_test.conf",
  1184. .types = ACO_TYPES(&global, &global_defaults, &item),
  1185. };
  1186. static AO2_GLOBAL_OBJ_STATIC(global_obj);
  1187. CONFIG_INFO_TEST(cfg_info, global_obj, test_config_alloc,
  1188. .files = ACO_FILES(&config_test_conf),
  1189. );
  1190. AST_TEST_DEFINE(config_options_test)
  1191. {
  1192. int res = AST_TEST_PASS, x, error;
  1193. struct test_item defaults = { 0, }, configs = { 0, };
  1194. struct test_item *arr[4];
  1195. struct ast_sockaddr acl_allow = {{ 0, }}, acl_fail = {{ 0, }};
  1196. RAII_VAR(struct test_config *, cfg, NULL, ao2_cleanup);
  1197. RAII_VAR(struct test_item *, item, NULL, ao2_cleanup);
  1198. RAII_VAR(struct test_item *, item_defaults, NULL, ao2_cleanup);
  1199. switch (cmd) {
  1200. case TEST_INIT:
  1201. info->name = "config_options_test";
  1202. info->category = "/config/";
  1203. info->summary = "Config opptions unit test";
  1204. info->description =
  1205. "Tests the Config Options API";
  1206. return AST_TEST_NOT_RUN;
  1207. case TEST_EXECUTE:
  1208. break;
  1209. }
  1210. #define INT_DEFAULT "-2"
  1211. #define INT_CONFIG "-1"
  1212. #define UINT_DEFAULT "2"
  1213. #define UINT_CONFIG "1"
  1214. #define DOUBLE_DEFAULT "1.1"
  1215. #define DOUBLE_CONFIG "0.1"
  1216. #define SOCKADDR_DEFAULT "4.3.2.1:4321"
  1217. #define SOCKADDR_CONFIG "1.2.3.4:1234"
  1218. #define BOOL_DEFAULT "false"
  1219. #define BOOL_CONFIG "true"
  1220. #define BOOLFLAG1_DEFAULT "false"
  1221. #define BOOLFLAG1_CONFIG "true"
  1222. #define BOOLFLAG2_DEFAULT "false"
  1223. #define BOOLFLAG2_CONFIG "false"
  1224. #define BOOLFLAG3_DEFAULT "false"
  1225. #define BOOLFLAG3_CONFIG "true"
  1226. #define ACL_DEFAULT NULL
  1227. #define ACL_CONFIG_PERMIT "1.2.3.4/32"
  1228. #define ACL_CONFIG_DENY "0.0.0.0/0"
  1229. #define CODEC_DEFAULT "!all,alaw"
  1230. #define CODEC_CONFIG "!all,ulaw,g729"
  1231. #define STR_DEFAULT "default"
  1232. #define STR_CONFIG "test"
  1233. #define CUSTOM_DEFAULT "no"
  1234. #define CUSTOM_CONFIG "yes"
  1235. #define BOOLFLAG1 1 << 0
  1236. #define BOOLFLAG2 1 << 1
  1237. #define BOOLFLAG3 1 << 2
  1238. if (aco_info_init(&cfg_info)) {
  1239. ast_test_status_update(test, "Could not init cfg info\n");
  1240. return AST_TEST_FAIL;
  1241. }
  1242. /* Register all options */
  1243. aco_option_register(&cfg_info, "intopt", ACO_EXACT, config_test_conf.types, INT_DEFAULT, OPT_INT_T, 0, FLDSET(struct test_item, intopt));
  1244. aco_option_register(&cfg_info, "uintopt", ACO_EXACT, config_test_conf.types, UINT_DEFAULT, OPT_UINT_T, 0, FLDSET(struct test_item, uintopt));
  1245. aco_option_register(&cfg_info, "doubleopt", ACO_EXACT, config_test_conf.types, DOUBLE_DEFAULT, OPT_DOUBLE_T, 0, FLDSET(struct test_item, doubleopt));
  1246. aco_option_register(&cfg_info, "sockaddropt", ACO_EXACT, config_test_conf.types, SOCKADDR_DEFAULT, OPT_SOCKADDR_T, 0, FLDSET(struct test_item, sockaddropt));
  1247. aco_option_register(&cfg_info, "boolopt", ACO_EXACT, config_test_conf.types, BOOL_DEFAULT, OPT_BOOL_T, 1, FLDSET(struct test_item, boolopt));
  1248. aco_option_register(&cfg_info, "boolflag1", ACO_EXACT, config_test_conf.types, BOOLFLAG1_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG1);
  1249. aco_option_register(&cfg_info, "boolflag2", ACO_EXACT, config_test_conf.types, BOOLFLAG2_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG2);
  1250. aco_option_register(&cfg_info, "boolflag3", ACO_EXACT, config_test_conf.types, BOOLFLAG3_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG3);
  1251. aco_option_register(&cfg_info, "aclpermitopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 1, FLDSET(struct test_item, aclopt));
  1252. aco_option_register(&cfg_info, "acldenyopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 0, FLDSET(struct test_item, aclopt));
  1253. aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codecprefopt, codeccapopt));
  1254. aco_option_register(&cfg_info, "stropt", ACO_EXACT, config_test_conf.types, STR_DEFAULT, OPT_STRINGFIELD_T, 0, STRFLDSET(struct test_item, stropt));
  1255. aco_option_register_custom(&cfg_info, "customopt", ACO_EXACT, config_test_conf.types, CUSTOM_DEFAULT, customopt_handler, 0);
  1256. aco_option_register_deprecated(&cfg_info, "permit", config_test_conf.types, "aclpermitopt");
  1257. aco_option_register_deprecated(&cfg_info, "deny", config_test_conf.types, "acldenyopt");
  1258. if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
  1259. ast_test_status_update(test, "Could not parse config\n");
  1260. return AST_TEST_FAIL;
  1261. }
  1262. ast_parse_arg(INT_DEFAULT, PARSE_INT32, &defaults.intopt);
  1263. ast_parse_arg(INT_CONFIG, PARSE_INT32, &configs.intopt);
  1264. ast_parse_arg(UINT_DEFAULT, PARSE_UINT32, &defaults.uintopt);
  1265. ast_parse_arg(UINT_CONFIG, PARSE_UINT32, &configs.uintopt);
  1266. ast_parse_arg(DOUBLE_DEFAULT, PARSE_DOUBLE, &defaults.doubleopt);
  1267. ast_parse_arg(DOUBLE_CONFIG, PARSE_DOUBLE, &configs.doubleopt);
  1268. ast_parse_arg(SOCKADDR_DEFAULT, PARSE_ADDR, &defaults.sockaddropt);
  1269. ast_parse_arg(SOCKADDR_CONFIG, PARSE_ADDR, &configs.sockaddropt);
  1270. defaults.boolopt = ast_true(BOOL_DEFAULT);
  1271. configs.boolopt = ast_true(BOOL_CONFIG);
  1272. ast_set2_flag(&defaults, ast_true(BOOLFLAG1_DEFAULT), BOOLFLAG1);
  1273. ast_set2_flag(&defaults, ast_true(BOOLFLAG2_DEFAULT), BOOLFLAG2);
  1274. ast_set2_flag(&defaults, ast_true(BOOLFLAG3_DEFAULT), BOOLFLAG3);
  1275. ast_set2_flag(&configs, ast_true(BOOLFLAG1_CONFIG), BOOLFLAG1);
  1276. ast_set2_flag(&configs, ast_true(BOOLFLAG2_CONFIG), BOOLFLAG2);
  1277. ast_set2_flag(&configs, ast_true(BOOLFLAG3_CONFIG), BOOLFLAG3);
  1278. defaults.aclopt = NULL;
  1279. configs.aclopt = ast_append_ha("deny", ACL_CONFIG_DENY, configs.aclopt, &error);
  1280. configs.aclopt = ast_append_ha("permit", ACL_CONFIG_PERMIT, configs.aclopt, &error);
  1281. ast_sockaddr_parse(&acl_allow, "1.2.3.4", PARSE_PORT_FORBID);
  1282. ast_sockaddr_parse(&acl_fail, "1.1.1.1", PARSE_PORT_FORBID);
  1283. defaults.codeccapopt = ast_format_cap_alloc(0);
  1284. ast_parse_allow_disallow(&defaults.codecprefopt, defaults.codeccapopt, CODEC_DEFAULT, 1);
  1285. configs.codeccapopt = ast_format_cap_alloc(0);
  1286. ast_parse_allow_disallow(&configs.codecprefopt, configs.codeccapopt, CODEC_CONFIG, 1);
  1287. ast_string_field_init(&defaults, 128);
  1288. ast_string_field_init(&configs, 128);
  1289. ast_string_field_set(&defaults, stropt, STR_DEFAULT);
  1290. ast_string_field_set(&configs, stropt, STR_CONFIG);
  1291. defaults.customopt = ast_true(CUSTOM_DEFAULT);
  1292. configs.customopt = ast_true(CUSTOM_CONFIG);
  1293. cfg = ao2_global_obj_ref(global_obj);
  1294. if (!(item = ao2_find(cfg->items, "item", OBJ_KEY))) {
  1295. ast_test_status_update(test, "could not look up 'item'\n");
  1296. return AST_TEST_FAIL;
  1297. }
  1298. if (!(item_defaults = ao2_find(cfg->items, "item_defaults", OBJ_KEY))) {
  1299. ast_test_status_update(test, "could not look up 'item_defaults'\n");
  1300. return AST_TEST_FAIL;
  1301. }
  1302. arr[0] = cfg->global;
  1303. arr[1] = item;
  1304. arr[2] = cfg->global_defaults;
  1305. arr[3] = item_defaults;
  1306. /* Test global and item against configs, global_defaults and item_defaults against defaults */
  1307. #define NOT_EQUAL_FAIL(field, format) \
  1308. if (arr[x]->field != control->field) { \
  1309. ast_test_status_update(test, "%s did not match: " format " != " format " with x = %d\n", #field, arr[x]->field, control->field, x); \
  1310. res = AST_TEST_FAIL; \
  1311. }
  1312. for (x = 0; x < 4; x++) {
  1313. struct test_item *control = x < 2 ? &configs : &defaults;
  1314. NOT_EQUAL_FAIL(intopt, "%d");
  1315. NOT_EQUAL_FAIL(uintopt, "%u");
  1316. NOT_EQUAL_FAIL(boolopt, "%d");
  1317. NOT_EQUAL_FAIL(flags, "%u");
  1318. NOT_EQUAL_FAIL(customopt, "%d");
  1319. if (fabs(arr[x]->doubleopt - control->doubleopt) > 0.001) {
  1320. ast_test_status_update(test, "doubleopt did not match: %f vs %f on loop %d\n", arr[x]->doubleopt, control->doubleopt, x);
  1321. res = AST_TEST_FAIL;
  1322. }
  1323. if (ast_sockaddr_cmp(&arr[x]->sockaddropt, &control->sockaddropt)) {
  1324. ast_test_status_update(test, "sockaddr did not match on loop %d\n", x);
  1325. res = AST_TEST_FAIL;
  1326. }
  1327. if (!ast_format_cap_identical(arr[x]->codeccapopt, control->codeccapopt)) {
  1328. char buf1[128], buf2[128];
  1329. ast_getformatname_multiple(buf1, sizeof(buf1), arr[x]->codeccapopt);
  1330. ast_getformatname_multiple(buf2, sizeof(buf2), control->codeccapopt);
  1331. ast_test_status_update(test, "format did not match: '%s' vs '%s' on loop %d\n", buf1, buf2, x);
  1332. res = AST_TEST_FAIL;
  1333. }
  1334. if (strcasecmp(arr[x]->stropt, control->stropt)) {
  1335. ast_test_status_update(test, "stropt did not match: '%s' vs '%s' on loop %d\n", arr[x]->stropt, control->stropt, x);
  1336. res = AST_TEST_FAIL;
  1337. }
  1338. if (arr[x]->aclopt != control->aclopt && (ast_apply_ha(arr[x]->aclopt, &acl_allow) != ast_apply_ha(control->aclopt, &acl_allow) ||
  1339. ast_apply_ha(arr[x]->aclopt, &acl_fail) != ast_apply_ha(control->aclopt, &acl_fail))) {
  1340. ast_test_status_update(test, "acl not match: on loop %d\n", x);
  1341. res = AST_TEST_FAIL;
  1342. }
  1343. }
  1344. ast_free_ha(configs.aclopt);
  1345. ast_format_cap_destroy(defaults.codeccapopt);
  1346. ast_format_cap_destroy(configs.codeccapopt);
  1347. ast_string_field_free_memory(&defaults);
  1348. ast_string_field_free_memory(&configs);
  1349. return res;
  1350. }
  1351. static int unload_module(void)
  1352. {
  1353. AST_TEST_UNREGISTER(config_basic_ops);
  1354. AST_TEST_UNREGISTER(config_filtered_ops);
  1355. AST_TEST_UNREGISTER(config_template_ops);
  1356. AST_TEST_UNREGISTER(copy_config);
  1357. AST_TEST_UNREGISTER(config_hook);
  1358. AST_TEST_UNREGISTER(ast_parse_arg_test);
  1359. AST_TEST_UNREGISTER(config_options_test);
  1360. return 0;
  1361. }
  1362. static int load_module(void)
  1363. {
  1364. AST_TEST_REGISTER(config_basic_ops);
  1365. AST_TEST_REGISTER(config_filtered_ops);
  1366. AST_TEST_REGISTER(config_template_ops);
  1367. AST_TEST_REGISTER(copy_config);
  1368. AST_TEST_REGISTER(config_hook);
  1369. AST_TEST_REGISTER(ast_parse_arg_test);
  1370. AST_TEST_REGISTER(config_options_test);
  1371. return AST_MODULE_LOAD_SUCCESS;
  1372. }
  1373. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Config test module");