test_config.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  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. /*!
  202. * \brief Write the config file to disk
  203. *
  204. * This is necessary for testing config hooks since
  205. * they are only triggered when a config is read from
  206. * its intended storage medium
  207. */
  208. static int write_config_file(void)
  209. {
  210. int i;
  211. FILE *config_file;
  212. char filename[PATH_MAX];
  213. snprintf(filename, sizeof(filename), "%s/%s",
  214. ast_config_AST_CONFIG_DIR, CONFIG_FILE);
  215. config_file = fopen(filename, "w");
  216. if (!config_file) {
  217. return -1;
  218. }
  219. for (i = 0; i < ARRAY_LEN(categories); ++i) {
  220. int j;
  221. fprintf(config_file, "[%s]\n", categories[i].category);
  222. for (j = 0; j < ARRAY_LEN(categories[i].vars); ++j) {
  223. fprintf(config_file, "%s = %s\n",
  224. categories[i].vars[j].name,
  225. categories[i].vars[j].val);
  226. }
  227. }
  228. fclose(config_file);
  229. return 0;
  230. }
  231. /*!
  232. * \brief Delete config file created by write_config_file
  233. */
  234. static void delete_config_file(void)
  235. {
  236. char filename[PATH_MAX];
  237. snprintf(filename, sizeof(filename), "%s/%s",
  238. ast_config_AST_CONFIG_DIR, CONFIG_FILE);
  239. unlink(filename);
  240. }
  241. /*
  242. * Boolean to indicate if the config hook has run
  243. */
  244. static int hook_run;
  245. /*
  246. * Boolean to indicate if, when the hook runs, the
  247. * data passed to it is what is expected
  248. */
  249. static int hook_config_sane;
  250. static int hook_cb(struct ast_config *cfg)
  251. {
  252. hook_run = 1;
  253. if (test_config_validity(cfg) == 0) {
  254. hook_config_sane = 1;
  255. }
  256. ast_config_destroy(cfg);
  257. return 0;
  258. }
  259. AST_TEST_DEFINE(config_hook)
  260. {
  261. enum ast_test_result_state res = AST_TEST_FAIL;
  262. enum config_hook_flags hook_flags = { 0, };
  263. struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED };
  264. struct ast_config *cfg;
  265. switch (cmd) {
  266. case TEST_INIT:
  267. info->name = "config_hook";
  268. info->category = "/main/config/";
  269. info->summary = "Test config hooks";
  270. info->description =
  271. "Ensure that config hooks are called at approriate times,"
  272. "not called at inappropriate times, and that all information"
  273. "that should be present is present.";
  274. return AST_TEST_NOT_RUN;
  275. case TEST_EXECUTE:
  276. break;
  277. }
  278. write_config_file();
  279. /*
  280. * Register a config hook to run when CONFIG_FILE is loaded by this module
  281. */
  282. ast_config_hook_register("test_hook",
  283. CONFIG_FILE,
  284. AST_MODULE,
  285. hook_flags,
  286. hook_cb);
  287. /*
  288. * Try loading the config file. This should result in the hook
  289. * being called
  290. */
  291. cfg = ast_config_load(CONFIG_FILE, config_flags);
  292. ast_config_destroy(cfg);
  293. if (!hook_run || !hook_config_sane) {
  294. ast_test_status_update(test, "Config hook either did not run or was given bad data!\n");
  295. goto out;
  296. }
  297. /*
  298. * Now try loading the wrong config file but from the right module.
  299. * Hook should not run
  300. */
  301. hook_run = 0;
  302. cfg = ast_config_load("asterisk.conf", config_flags);
  303. ast_config_destroy(cfg);
  304. if (hook_run) {
  305. ast_test_status_update(test, "Config hook ran even though an incorrect file was specified.\n");
  306. goto out;
  307. }
  308. /*
  309. * Now try loading the correct config file but from the wrong module.
  310. * Hook should not run
  311. */
  312. hook_run = 0;
  313. cfg = ast_config_load2(CONFIG_FILE, "fake_module.so", config_flags);
  314. ast_config_destroy(cfg);
  315. if (hook_run) {
  316. ast_test_status_update(test, "Config hook ran even though an incorrect module was specified.\n");
  317. goto out;
  318. }
  319. /*
  320. * Now try loading the file correctly, but without any changes to the file.
  321. * Hook should not run
  322. */
  323. hook_run = 0;
  324. cfg = ast_config_load(CONFIG_FILE, config_flags);
  325. /* Only destroy this cfg conditionally. Otherwise a crash happens. */
  326. if (cfg != CONFIG_STATUS_FILEUNCHANGED) {
  327. ast_config_destroy(cfg);
  328. }
  329. if (hook_run) {
  330. ast_test_status_update(test, "Config hook ran even though file contents had not changed\n");
  331. goto out;
  332. }
  333. res = AST_TEST_PASS;
  334. out:
  335. delete_config_file();
  336. return res;
  337. }
  338. enum {
  339. EXPECT_FAIL = 0,
  340. EXPECT_SUCCEED,
  341. };
  342. #define TOOBIG_I32 "2147483649"
  343. #define TOOSMALL_I32 "-2147483649"
  344. #define TOOBIG_U32 "4294967297"
  345. #define TOOSMALL_U32 "-4294967297"
  346. #define DEFAULTVAL 42
  347. #define EPSILON 0.001
  348. #define TEST_PARSE(input, should_succeed, expected_result, flags, result, ...) do {\
  349. int __res = ast_parse_arg(input, (flags), result, ##__VA_ARGS__); \
  350. if (!__res == !should_succeed) { \
  351. ast_test_status_update(test, "ast_parse_arg failed on '%s'. %d/%d\n", input, __res, should_succeed); \
  352. ret = AST_TEST_FAIL; \
  353. } else { \
  354. if (((flags) & PARSE_TYPE) == PARSE_INT32) { \
  355. int32_t *r = (int32_t *) (void *) result; \
  356. int32_t e = (int32_t) expected_result; \
  357. if (*r != e) { \
  358. ast_test_status_update(test, "ast_parse_arg int32_t failed with %d != %d\n", *r, e); \
  359. ret = AST_TEST_FAIL; \
  360. } \
  361. } else if (((flags) & PARSE_TYPE) == PARSE_UINT32) { \
  362. uint32_t *r = (uint32_t *) (void *) result; \
  363. uint32_t e = (uint32_t) expected_result; \
  364. if (*r != e) { \
  365. ast_test_status_update(test, "ast_parse_arg uint32_t failed with %u != %u\n", *r, e); \
  366. ret = AST_TEST_FAIL; \
  367. } \
  368. } else if (((flags) & PARSE_TYPE) == PARSE_DOUBLE) { \
  369. double *r = (double *) (void *) result; \
  370. double e = (double) expected_result; \
  371. if (fabs(*r - e) > EPSILON) { \
  372. ast_test_status_update(test, "ast_parse_arg double failed with %f != %f\n", *r, e); \
  373. ret = AST_TEST_FAIL; \
  374. } \
  375. } \
  376. } \
  377. *(result) = DEFAULTVAL; \
  378. } while (0)
  379. AST_TEST_DEFINE(ast_parse_arg_test)
  380. {
  381. int ret = AST_TEST_PASS;
  382. int32_t int32_t_val = DEFAULTVAL;
  383. uint32_t uint32_t_val = DEFAULTVAL;
  384. double double_val = DEFAULTVAL;
  385. switch (cmd) {
  386. case TEST_INIT:
  387. info->name = "ast_parse_arg";
  388. info->category = "/config/";
  389. info->summary = "Test the output of ast_parse_arg";
  390. info->description =
  391. "Ensures that ast_parse_arg behaves as expected";
  392. return AST_TEST_NOT_RUN;
  393. case TEST_EXECUTE:
  394. break;
  395. }
  396. /* int32 testing */
  397. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32, &int32_t_val);
  398. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32, &int32_t_val);
  399. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32, &int32_t_val);
  400. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
  401. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
  402. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
  403. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32, &int32_t_val);
  404. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  405. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  406. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  407. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  408. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  409. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  410. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT, &int32_t_val, 7);
  411. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, 0, 200);
  412. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, -200, 100);
  413. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, -1, 0);
  414. TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, 0, 122);
  415. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, -122, 100);
  416. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, 1, 100);
  417. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  418. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  419. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  420. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_IN_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  421. TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, 0, 200);
  422. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, -200, 100);
  423. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, -1, 0);
  424. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, 0, 122);
  425. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, -122, 100);
  426. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, 1, 100);
  427. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  428. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  429. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  430. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_INT32 | PARSE_OUT_RANGE, &int32_t_val, INT_MIN, INT_MAX);
  431. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, 0, 200);
  432. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, -200, 100);
  433. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, -1, 0);
  434. TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, 0, 122);
  435. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, -122, 100);
  436. TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, 1, 100);
  437. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  438. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  439. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  440. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  441. TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, 0, 200);
  442. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, -200, 100);
  443. TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, -1, 0);
  444. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, 0, 122);
  445. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, -122, 100);
  446. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, 1, 100);
  447. TEST_PARSE(TOOBIG_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  448. TEST_PARSE(TOOSMALL_I32, EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  449. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  450. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_INT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &int32_t_val, 7, INT_MIN, INT_MAX);
  451. /* uuint32 testing */
  452. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32, &uint32_t_val);
  453. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  454. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32, &uint32_t_val);
  455. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  456. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  457. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  458. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  459. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  460. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  461. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  462. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  463. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  464. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  465. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT, &uint32_t_val, 7);
  466. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 200);
  467. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 200);
  468. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 1);
  469. TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 0, 122);
  470. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, 1, 100);
  471. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  472. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  473. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  474. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_IN_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  475. TEST_PARSE("123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 200);
  476. TEST_PARSE("-123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 200);
  477. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 1);
  478. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 0, 122);
  479. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, 1, 100);
  480. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  481. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  482. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  483. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32 | PARSE_OUT_RANGE, &uint32_t_val, INT_MIN, INT_MAX);
  484. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 200);
  485. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 200);
  486. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 1);
  487. TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 0, 122);
  488. TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, 1, 100);
  489. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  490. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  491. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  492. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_IN_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  493. TEST_PARSE("123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 200);
  494. TEST_PARSE("-123", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 100);
  495. TEST_PARSE("0", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 1);
  496. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 0, 122);
  497. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, 1, 100);
  498. TEST_PARSE(TOOBIG_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  499. TEST_PARSE(TOOSMALL_U32, EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  500. TEST_PARSE("not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  501. TEST_PARSE("7not a number", EXPECT_FAIL, 7, PARSE_UINT32 | PARSE_DEFAULT | PARSE_OUT_RANGE, &uint32_t_val, 7, INT_MIN, INT_MAX);
  502. TEST_PARSE(" -123", EXPECT_FAIL, DEFAULTVAL, PARSE_UINT32, &uint32_t_val);
  503. /* double testing */
  504. TEST_PARSE("123", EXPECT_SUCCEED, 123, PARSE_DOUBLE, &double_val);
  505. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE, &double_val);
  506. TEST_PARSE("-123", EXPECT_SUCCEED, -123, PARSE_DOUBLE, &double_val);
  507. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE, &double_val);
  508. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE, &double_val);
  509. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE, &double_val);
  510. TEST_PARSE("7.0not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE, &double_val);
  511. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  512. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  513. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  514. TEST_PARSE("not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  515. TEST_PARSE("7.0not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT, &double_val, 7.0);
  516. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, 0.0, 200.0);
  517. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -200.0, 100.0);
  518. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -1.0, 0.0);
  519. TEST_PARSE("123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, 0.0, 122.0);
  520. TEST_PARSE("-123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -122.0, 100.0);
  521. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, 1.0, 100.0);
  522. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
  523. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_IN_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
  524. TEST_PARSE("123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, 0.0, 200.0);
  525. TEST_PARSE("-123.123", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -200.0, 100.0);
  526. TEST_PARSE("0", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -1.0, 0.0);
  527. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, 0.0, 122.0);
  528. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -122.0, 100.0);
  529. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, 1.0, 100.0);
  530. TEST_PARSE("not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
  531. TEST_PARSE("7not a number", EXPECT_FAIL, DEFAULTVAL, PARSE_DOUBLE | PARSE_OUT_RANGE, &double_val, -HUGE_VAL, HUGE_VAL);
  532. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, 0.0, 200.0);
  533. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -200.0, 100.0);
  534. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -1.0, 0.0);
  535. TEST_PARSE("123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, 0.0, 122.0);
  536. TEST_PARSE("-123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -122.0, 100.0);
  537. TEST_PARSE("0", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, 1.0, 100.0);
  538. TEST_PARSE("not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
  539. TEST_PARSE("7not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_IN_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
  540. TEST_PARSE("123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, 0.0, 200.0);
  541. TEST_PARSE("-123.123", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -200.0, 100.0);
  542. TEST_PARSE("0", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -1.0, 0.0);
  543. TEST_PARSE("123.123", EXPECT_SUCCEED, 123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, 0.0, 122.0);
  544. TEST_PARSE("-123.123", EXPECT_SUCCEED, -123.123, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -122.0, 100.0);
  545. TEST_PARSE("0", EXPECT_SUCCEED, 0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, 1.0, 100.0);
  546. TEST_PARSE("not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
  547. TEST_PARSE("7not a number", EXPECT_FAIL, 7.0, PARSE_DOUBLE | PARSE_DEFAULT | PARSE_OUT_RANGE, &double_val, 7.0, -HUGE_VAL, HUGE_VAL);
  548. /* ast_sockaddr_parse is tested extensively in test_netsock2.c and PARSE_ADDR is a very simple wrapper */
  549. return ret;
  550. }
  551. struct test_item {
  552. AST_DECLARE_STRING_FIELDS(
  553. AST_STRING_FIELD(name);
  554. AST_STRING_FIELD(stropt);
  555. );
  556. int32_t intopt;
  557. uint32_t uintopt;
  558. unsigned int flags;
  559. double doubleopt;
  560. struct ast_sockaddr sockaddropt;
  561. int boolopt;
  562. struct ast_ha *aclopt;
  563. struct ast_codec_pref codecprefopt;
  564. struct ast_format_cap *codeccapopt;
  565. unsigned int customopt:1;
  566. };
  567. struct test_config {
  568. struct test_item *global;
  569. struct test_item *global_defaults;
  570. struct ao2_container *items;
  571. };
  572. static int test_item_hash(const void *obj, const int flags)
  573. {
  574. const struct test_item *item = obj;
  575. const char *name = (flags & OBJ_KEY) ? obj : item->name;
  576. return ast_str_case_hash(name);
  577. }
  578. static int test_item_cmp(void *obj, void *arg, int flags)
  579. {
  580. struct test_item *one = obj, *two = arg;
  581. const char *match = (flags & OBJ_KEY) ? arg : two->name;
  582. return strcasecmp(one->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
  583. }
  584. static void test_item_destructor(void *obj)
  585. {
  586. struct test_item *item = obj;
  587. ast_string_field_free_memory(item);
  588. if (item->codeccapopt) {
  589. ast_format_cap_destroy(item->codeccapopt);
  590. }
  591. if (item->aclopt) {
  592. ast_free_ha(item->aclopt);
  593. }
  594. return;
  595. }
  596. static void *test_item_alloc(const char *cat)
  597. {
  598. struct test_item *item;
  599. if (!(item = ao2_alloc(sizeof(*item), test_item_destructor))) {
  600. return NULL;
  601. }
  602. if (ast_string_field_init(item, 128)) {
  603. ao2_ref(item, -1);
  604. return NULL;
  605. }
  606. if (!(item->codeccapopt = ast_format_cap_alloc())) {
  607. ao2_ref(item, -1);
  608. return NULL;
  609. }
  610. ast_string_field_set(item, name, cat);
  611. return item;
  612. }
  613. static void test_config_destructor(void *obj)
  614. {
  615. struct test_config *cfg = obj;
  616. ao2_cleanup(cfg->global);
  617. ao2_cleanup(cfg->global_defaults);
  618. ao2_cleanup(cfg->items);
  619. }
  620. static void *test_config_alloc(void)
  621. {
  622. struct test_config *cfg;
  623. if (!(cfg = ao2_alloc(sizeof(*cfg), test_config_destructor))) {
  624. goto error;
  625. }
  626. if (!(cfg->global = test_item_alloc("global"))) {
  627. goto error;
  628. }
  629. if (!(cfg->global_defaults = test_item_alloc("global_defaults"))) {
  630. goto error;
  631. }
  632. if (!(cfg->items = ao2_container_alloc(1, test_item_hash, test_item_cmp))) {
  633. goto error;
  634. }
  635. return cfg;
  636. error:
  637. ao2_cleanup(cfg);
  638. return NULL;
  639. }
  640. static void *test_item_find(struct ao2_container *container, const char *cat)
  641. {
  642. return ao2_find(container, cat, OBJ_KEY);
  643. }
  644. static int customopt_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
  645. {
  646. struct test_item *item = obj;
  647. if (!strcasecmp(var->name, "customopt")) {
  648. item->customopt = ast_true(var->value);
  649. } else {
  650. return -1;
  651. }
  652. return 0;
  653. }
  654. static struct aco_type global = {
  655. .type = ACO_GLOBAL,
  656. .item_offset = offsetof(struct test_config, global),
  657. .category_match = ACO_WHITELIST,
  658. .category = "^global$",
  659. };
  660. static struct aco_type global_defaults = {
  661. .type = ACO_GLOBAL,
  662. .item_offset = offsetof(struct test_config, global_defaults),
  663. .category_match = ACO_WHITELIST,
  664. .category = "^global_defaults$",
  665. };
  666. static struct aco_type item = {
  667. .type = ACO_ITEM,
  668. .category_match = ACO_BLACKLIST,
  669. .category = "^(global|global_defaults)$",
  670. .item_alloc = test_item_alloc,
  671. .item_find = test_item_find,
  672. .item_offset = offsetof(struct test_config, items),
  673. };
  674. struct aco_file config_test_conf = {
  675. .filename = "config_test.conf",
  676. .types = ACO_TYPES(&global, &global_defaults, &item),
  677. };
  678. static AO2_GLOBAL_OBJ_STATIC(global_obj);
  679. CONFIG_INFO_STANDARD(cfg_info, global_obj, test_config_alloc,
  680. .files = ACO_FILES(&config_test_conf),
  681. );
  682. AST_TEST_DEFINE(config_options_test)
  683. {
  684. int res = AST_TEST_PASS, x, error;
  685. struct test_item defaults = { 0, }, configs = { 0, };
  686. struct test_item *arr[4];
  687. struct ast_sockaddr acl_allow = {{ 0, }}, acl_fail = {{ 0, }};
  688. RAII_VAR(struct test_config *, cfg, NULL, ao2_cleanup);
  689. RAII_VAR(struct test_item *, item, NULL, ao2_cleanup);
  690. RAII_VAR(struct test_item *, item_defaults, NULL, ao2_cleanup);
  691. switch (cmd) {
  692. case TEST_INIT:
  693. info->name = "config_options_test";
  694. info->category = "/config/";
  695. info->summary = "Config opptions unit test";
  696. info->description =
  697. "Tests the Config Options API";
  698. return AST_TEST_NOT_RUN;
  699. case TEST_EXECUTE:
  700. break;
  701. }
  702. #define INT_DEFAULT "-2"
  703. #define INT_CONFIG "-1"
  704. #define UINT_DEFAULT "2"
  705. #define UINT_CONFIG "1"
  706. #define DOUBLE_DEFAULT "1.1"
  707. #define DOUBLE_CONFIG "0.1"
  708. #define SOCKADDR_DEFAULT "4.3.2.1:4321"
  709. #define SOCKADDR_CONFIG "1.2.3.4:1234"
  710. #define BOOL_DEFAULT "false"
  711. #define BOOL_CONFIG "true"
  712. #define BOOLFLAG1_DEFAULT "false"
  713. #define BOOLFLAG1_CONFIG "true"
  714. #define BOOLFLAG2_DEFAULT "false"
  715. #define BOOLFLAG2_CONFIG "false"
  716. #define BOOLFLAG3_DEFAULT "false"
  717. #define BOOLFLAG3_CONFIG "true"
  718. #define ACL_DEFAULT NULL
  719. #define ACL_CONFIG_PERMIT "1.2.3.4/32"
  720. #define ACL_CONFIG_DENY "0.0.0.0/0"
  721. #define CODEC_DEFAULT "!all,alaw"
  722. #define CODEC_CONFIG "!all,ulaw,g729"
  723. #define STR_DEFAULT "default"
  724. #define STR_CONFIG "test"
  725. #define CUSTOM_DEFAULT "no"
  726. #define CUSTOM_CONFIG "yes"
  727. #define BOOLFLAG1 1 << 0
  728. #define BOOLFLAG2 1 << 1
  729. #define BOOLFLAG3 1 << 2
  730. if (aco_info_init(&cfg_info)) {
  731. ast_test_status_update(test, "Could not init cfg info\n");
  732. return AST_TEST_FAIL;
  733. }
  734. /* Register all options */
  735. aco_option_register(&cfg_info, "intopt", ACO_EXACT, config_test_conf.types, INT_DEFAULT, OPT_INT_T, 0, FLDSET(struct test_item, intopt));
  736. aco_option_register(&cfg_info, "uintopt", ACO_EXACT, config_test_conf.types, UINT_DEFAULT, OPT_UINT_T, 0, FLDSET(struct test_item, uintopt));
  737. aco_option_register(&cfg_info, "doubleopt", ACO_EXACT, config_test_conf.types, DOUBLE_DEFAULT, OPT_DOUBLE_T, 0, FLDSET(struct test_item, doubleopt));
  738. aco_option_register(&cfg_info, "sockaddropt", ACO_EXACT, config_test_conf.types, SOCKADDR_DEFAULT, OPT_SOCKADDR_T, 0, FLDSET(struct test_item, sockaddropt));
  739. aco_option_register(&cfg_info, "boolopt", ACO_EXACT, config_test_conf.types, BOOL_DEFAULT, OPT_BOOL_T, 1, FLDSET(struct test_item, boolopt));
  740. aco_option_register(&cfg_info, "boolflag1", ACO_EXACT, config_test_conf.types, BOOLFLAG1_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG1);
  741. aco_option_register(&cfg_info, "boolflag2", ACO_EXACT, config_test_conf.types, BOOLFLAG2_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG2);
  742. aco_option_register(&cfg_info, "boolflag3", ACO_EXACT, config_test_conf.types, BOOLFLAG3_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG3);
  743. aco_option_register(&cfg_info, "aclpermitopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 1, FLDSET(struct test_item, aclopt));
  744. aco_option_register(&cfg_info, "acldenyopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 0, FLDSET(struct test_item, aclopt));
  745. aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codecprefopt, codeccapopt));
  746. aco_option_register(&cfg_info, "stropt", ACO_EXACT, config_test_conf.types, STR_DEFAULT, OPT_STRINGFIELD_T, 0, STRFLDSET(struct test_item, stropt));
  747. aco_option_register_custom(&cfg_info, "customopt", ACO_EXACT, config_test_conf.types, CUSTOM_DEFAULT, customopt_handler, 0);
  748. aco_option_register_deprecated(&cfg_info, "permit", config_test_conf.types, "aclpermitopt");
  749. aco_option_register_deprecated(&cfg_info, "deny", config_test_conf.types, "acldenyopt");
  750. if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
  751. ast_test_status_update(test, "Could not parse config\n");
  752. return AST_TEST_FAIL;
  753. }
  754. ast_parse_arg(INT_DEFAULT, PARSE_INT32, &defaults.intopt);
  755. ast_parse_arg(INT_CONFIG, PARSE_INT32, &configs.intopt);
  756. ast_parse_arg(UINT_DEFAULT, PARSE_UINT32, &defaults.uintopt);
  757. ast_parse_arg(UINT_CONFIG, PARSE_UINT32, &configs.uintopt);
  758. ast_parse_arg(DOUBLE_DEFAULT, PARSE_DOUBLE, &defaults.doubleopt);
  759. ast_parse_arg(DOUBLE_CONFIG, PARSE_DOUBLE, &configs.doubleopt);
  760. ast_parse_arg(SOCKADDR_DEFAULT, PARSE_ADDR, &defaults.sockaddropt);
  761. ast_parse_arg(SOCKADDR_CONFIG, PARSE_ADDR, &configs.sockaddropt);
  762. defaults.boolopt = ast_true(BOOL_DEFAULT);
  763. configs.boolopt = ast_true(BOOL_CONFIG);
  764. ast_set2_flag(&defaults, ast_true(BOOLFLAG1_DEFAULT), BOOLFLAG1);
  765. ast_set2_flag(&defaults, ast_true(BOOLFLAG2_DEFAULT), BOOLFLAG2);
  766. ast_set2_flag(&defaults, ast_true(BOOLFLAG3_DEFAULT), BOOLFLAG3);
  767. ast_set2_flag(&configs, ast_true(BOOLFLAG1_CONFIG), BOOLFLAG1);
  768. ast_set2_flag(&configs, ast_true(BOOLFLAG2_CONFIG), BOOLFLAG2);
  769. ast_set2_flag(&configs, ast_true(BOOLFLAG3_CONFIG), BOOLFLAG3);
  770. defaults.aclopt = NULL;
  771. configs.aclopt = ast_append_ha("deny", ACL_CONFIG_DENY, configs.aclopt, &error);
  772. configs.aclopt = ast_append_ha("permit", ACL_CONFIG_PERMIT, configs.aclopt, &error);
  773. ast_sockaddr_parse(&acl_allow, "1.2.3.4", PARSE_PORT_FORBID);
  774. ast_sockaddr_parse(&acl_fail, "1.1.1.1", PARSE_PORT_FORBID);
  775. defaults.codeccapopt = ast_format_cap_alloc();
  776. ast_parse_allow_disallow(&defaults.codecprefopt, defaults.codeccapopt, CODEC_DEFAULT, 1);
  777. configs.codeccapopt = ast_format_cap_alloc();
  778. ast_parse_allow_disallow(&configs.codecprefopt, configs.codeccapopt, CODEC_CONFIG, 1);
  779. ast_string_field_init(&defaults, 128);
  780. ast_string_field_init(&configs, 128);
  781. ast_string_field_set(&defaults, stropt, STR_DEFAULT);
  782. ast_string_field_set(&configs, stropt, STR_CONFIG);
  783. defaults.customopt = ast_true(CUSTOM_DEFAULT);
  784. configs.customopt = ast_true(CUSTOM_CONFIG);
  785. cfg = ao2_global_obj_ref(global_obj);
  786. if (!(item = ao2_find(cfg->items, "item", OBJ_KEY))) {
  787. ast_test_status_update(test, "could not look up 'item'\n");
  788. return AST_TEST_FAIL;
  789. }
  790. if (!(item_defaults = ao2_find(cfg->items, "item_defaults", OBJ_KEY))) {
  791. ast_test_status_update(test, "could not look up 'item_defaults'\n");
  792. return AST_TEST_FAIL;
  793. }
  794. arr[0] = cfg->global;
  795. arr[1] = item;
  796. arr[2] = cfg->global_defaults;
  797. arr[3] = item_defaults;
  798. /* Test global and item against configs, global_defaults and item_defaults against defaults */
  799. #define NOT_EQUAL_FAIL(field, format) \
  800. if (arr[x]->field != control->field) { \
  801. ast_test_status_update(test, "%s did not match: " format " != " format " with x = %d\n", #field, arr[x]->field, control->field, x); \
  802. res = AST_TEST_FAIL; \
  803. }
  804. for (x = 0; x < 4; x++) {
  805. struct test_item *control = x < 2 ? &configs : &defaults;
  806. NOT_EQUAL_FAIL(intopt, "%d");
  807. NOT_EQUAL_FAIL(uintopt, "%u");
  808. NOT_EQUAL_FAIL(boolopt, "%d");
  809. NOT_EQUAL_FAIL(flags, "%u");
  810. NOT_EQUAL_FAIL(customopt, "%d");
  811. if (fabs(arr[x]->doubleopt - control->doubleopt) > 0.001) {
  812. ast_test_status_update(test, "doubleopt did not match: %f vs %f on loop %d\n", arr[x]->doubleopt, control->doubleopt, x);
  813. res = AST_TEST_FAIL;
  814. }
  815. if (ast_sockaddr_cmp(&arr[x]->sockaddropt, &control->sockaddropt)) {
  816. ast_test_status_update(test, "sockaddr did not match on loop %d\n", x);
  817. res = AST_TEST_FAIL;
  818. }
  819. if (!ast_format_cap_identical(arr[x]->codeccapopt, control->codeccapopt)) {
  820. char buf1[128], buf2[128];
  821. ast_getformatname_multiple(buf1, sizeof(buf1), arr[x]->codeccapopt);
  822. ast_getformatname_multiple(buf2, sizeof(buf2), control->codeccapopt);
  823. ast_test_status_update(test, "format did not match: '%s' vs '%s' on loop %d\n", buf1, buf2, x);
  824. res = AST_TEST_FAIL;
  825. }
  826. if (strcasecmp(arr[x]->stropt, control->stropt)) {
  827. ast_test_status_update(test, "stropt did not match: '%s' vs '%s' on loop %d\n", arr[x]->stropt, control->stropt, x);
  828. res = AST_TEST_FAIL;
  829. }
  830. if (arr[x]->aclopt != control->aclopt && (ast_apply_ha(arr[x]->aclopt, &acl_allow) != ast_apply_ha(control->aclopt, &acl_allow) ||
  831. ast_apply_ha(arr[x]->aclopt, &acl_fail) != ast_apply_ha(control->aclopt, &acl_fail))) {
  832. ast_test_status_update(test, "acl not match: on loop %d\n", x);
  833. res = AST_TEST_FAIL;
  834. }
  835. }
  836. ast_free_ha(configs.aclopt);
  837. ast_format_cap_destroy(defaults.codeccapopt);
  838. ast_format_cap_destroy(configs.codeccapopt);
  839. ast_string_field_free_memory(&defaults);
  840. ast_string_field_free_memory(&configs);
  841. return res;
  842. }
  843. static int unload_module(void)
  844. {
  845. AST_TEST_UNREGISTER(copy_config);
  846. AST_TEST_UNREGISTER(config_hook);
  847. AST_TEST_UNREGISTER(ast_parse_arg_test);
  848. AST_TEST_UNREGISTER(config_options_test);
  849. return 0;
  850. }
  851. static int load_module(void)
  852. {
  853. AST_TEST_REGISTER(copy_config);
  854. AST_TEST_REGISTER(config_hook);
  855. AST_TEST_REGISTER(ast_parse_arg_test);
  856. AST_TEST_REGISTER(config_options_test);
  857. return AST_MODULE_LOAD_SUCCESS;
  858. }
  859. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Config test module");