test_ari_model.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * David M. Lee, II <dlee@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 Test the native ARI JSON validators.
  21. *
  22. * \author David M. Lee, II <dlee@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <depend>TEST_FRAMEWORK</depend>
  26. <depend>res_ari_model</depend>
  27. <support_level>core</support_level>
  28. ***/
  29. #include "asterisk.h"
  30. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  31. #include "asterisk/utils.h"
  32. #include "asterisk/module.h"
  33. #include "asterisk/test.h"
  34. #include "../res/ari/ari_model_validators.h"
  35. #if defined(TEST_FRAMEWORK)
  36. /*!
  37. * Wrapper of ast_test_validate_int() so an external function pointer is not used.
  38. *
  39. * \note Must do this because using an external function pointer
  40. * does not play nicely when loading with RTLD_LAZY.
  41. */
  42. static int wrap_ast_ari_validate_int(struct ast_json *json)
  43. {
  44. return ast_ari_validate_int(json);
  45. }
  46. #endif /* defined(TEST_FRAMEWORK) */
  47. #if defined(TEST_FRAMEWORK)
  48. /*!
  49. * Wrapper of ast_ari_validate_string() so an external function pointer is not used.
  50. *
  51. * \note Must do this because using an external function pointer
  52. * does not play nicely when loading with RTLD_LAZY.
  53. */
  54. static int wrap_ast_ari_validate_string(struct ast_json *json)
  55. {
  56. return ast_ari_validate_string(json);
  57. }
  58. #endif /* defined(TEST_FRAMEWORK) */
  59. AST_TEST_DEFINE(validate_byte)
  60. {
  61. RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
  62. RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
  63. int res;
  64. switch (cmd) {
  65. case TEST_INIT:
  66. info->name = __func__;
  67. info->category = "/ari/validators/";
  68. info->summary = "Test byte validation";
  69. info->description =
  70. "Test byte validation";
  71. return AST_TEST_NOT_RUN;
  72. case TEST_EXECUTE:
  73. break;
  74. }
  75. uut = ast_json_integer_create(-128);
  76. ast_test_validate(test, NULL != uut);
  77. ast_test_validate(test, ast_ari_validate_byte(uut));
  78. res = ast_json_integer_set(uut, 0);
  79. ast_test_validate(test, 0 == res);
  80. ast_test_validate(test, ast_ari_validate_byte(uut));
  81. res = ast_json_integer_set(uut, 255);
  82. ast_test_validate(test, 0 == res);
  83. ast_test_validate(test, ast_ari_validate_byte(uut));
  84. res = ast_json_integer_set(uut, -129);
  85. ast_test_validate(test, 0 == res);
  86. ast_test_validate(test, !ast_ari_validate_byte(uut));
  87. res = ast_json_integer_set(uut, 256);
  88. ast_test_validate(test, 0 == res);
  89. ast_test_validate(test, !ast_ari_validate_byte(uut));
  90. str = ast_json_string_create("not a byte");
  91. ast_test_validate(test, NULL != str);
  92. ast_test_validate(test, !ast_ari_validate_byte(str));
  93. /* Even if the string has an integral value */
  94. res = ast_json_string_set(str, "0");
  95. ast_test_validate(test, 0 == res);
  96. ast_test_validate(test, !ast_ari_validate_byte(str));
  97. ast_test_validate(test, !ast_ari_validate_byte(ast_json_null()));
  98. return AST_TEST_PASS;
  99. }
  100. AST_TEST_DEFINE(validate_boolean)
  101. {
  102. RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
  103. int res;
  104. switch (cmd) {
  105. case TEST_INIT:
  106. info->name = __func__;
  107. info->category = "/ari/validators/";
  108. info->summary = "Test byte validation";
  109. info->description =
  110. "Test byte validation";
  111. return AST_TEST_NOT_RUN;
  112. case TEST_EXECUTE:
  113. break;
  114. }
  115. ast_test_validate(test, ast_ari_validate_boolean(ast_json_true()));
  116. ast_test_validate(test, ast_ari_validate_boolean(ast_json_false()));
  117. str = ast_json_string_create("not a bool");
  118. ast_test_validate(test, NULL != str);
  119. ast_test_validate(test, !ast_ari_validate_boolean(str));
  120. /* Even if the string has a boolean value */
  121. res = ast_json_string_set(str, "true");
  122. ast_test_validate(test, 0 == res);
  123. ast_test_validate(test, !ast_ari_validate_boolean(str));
  124. /* Even if the string has a boolean text in it */
  125. res = ast_json_string_set(str, "true");
  126. ast_test_validate(test, 0 == res);
  127. ast_test_validate(test, !ast_ari_validate_boolean(str));
  128. ast_test_validate(test, !ast_ari_validate_boolean(ast_json_null()));
  129. return AST_TEST_PASS;
  130. }
  131. AST_TEST_DEFINE(validate_int)
  132. {
  133. RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
  134. RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
  135. int res;
  136. switch (cmd) {
  137. case TEST_INIT:
  138. info->name = __func__;
  139. info->category = "/ari/validators/";
  140. info->summary = "Test int validation";
  141. info->description =
  142. "Test int validation";
  143. return AST_TEST_NOT_RUN;
  144. case TEST_EXECUTE:
  145. break;
  146. }
  147. uut = ast_json_integer_create(-2147483648LL);
  148. ast_test_validate(test, NULL != uut);
  149. ast_test_validate(test, ast_ari_validate_int(uut));
  150. res = ast_json_integer_set(uut, 0);
  151. ast_test_validate(test, 0 == res);
  152. ast_test_validate(test, ast_ari_validate_int(uut));
  153. res = ast_json_integer_set(uut, 2147483647LL);
  154. ast_test_validate(test, 0 == res);
  155. ast_test_validate(test, ast_ari_validate_int(uut));
  156. res = ast_json_integer_set(uut, -2147483649LL);
  157. ast_test_validate(test, 0 == res);
  158. ast_test_validate(test, !ast_ari_validate_int(uut));
  159. res = ast_json_integer_set(uut, 2147483648LL);
  160. ast_test_validate(test, 0 == res);
  161. ast_test_validate(test, !ast_ari_validate_int(uut));
  162. str = ast_json_string_create("not a int");
  163. ast_test_validate(test, NULL != str);
  164. ast_test_validate(test, !ast_ari_validate_int(str));
  165. /* Even if the string has an integral value */
  166. res = ast_json_string_set(str, "0");
  167. ast_test_validate(test, 0 == res);
  168. ast_test_validate(test, !ast_ari_validate_int(str));
  169. ast_test_validate(test, !ast_ari_validate_int(ast_json_null()));
  170. return AST_TEST_PASS;
  171. }
  172. AST_TEST_DEFINE(validate_long)
  173. {
  174. RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
  175. RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
  176. int res;
  177. switch (cmd) {
  178. case TEST_INIT:
  179. info->name = __func__;
  180. info->category = "/ari/validators/";
  181. info->summary = "Test long validation";
  182. info->description =
  183. "Test long validation";
  184. return AST_TEST_NOT_RUN;
  185. case TEST_EXECUTE:
  186. break;
  187. }
  188. uut = ast_json_integer_create(0);
  189. ast_test_validate(test, NULL != uut);
  190. ast_test_validate(test, ast_ari_validate_long(uut));
  191. str = ast_json_string_create("not a long");
  192. ast_test_validate(test, NULL != str);
  193. ast_test_validate(test, !ast_ari_validate_long(str));
  194. /* Even if the string has an integral value */
  195. res = ast_json_string_set(str, "0");
  196. ast_test_validate(test, 0 == res);
  197. ast_test_validate(test, !ast_ari_validate_long(str));
  198. ast_test_validate(test, !ast_ari_validate_long(ast_json_null()));
  199. return AST_TEST_PASS;
  200. }
  201. AST_TEST_DEFINE(validate_string)
  202. {
  203. RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
  204. RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
  205. int res;
  206. switch (cmd) {
  207. case TEST_INIT:
  208. info->name = __func__;
  209. info->category = "/ari/validators/";
  210. info->summary = "Test string validation";
  211. info->description =
  212. "Test string validation";
  213. return AST_TEST_NOT_RUN;
  214. case TEST_EXECUTE:
  215. break;
  216. }
  217. uut = ast_json_string_create("text");
  218. ast_test_validate(test, NULL != uut);
  219. ast_test_validate(test, ast_ari_validate_string(uut));
  220. res = ast_json_string_set(uut, "");
  221. ast_test_validate(test, 0 == res);
  222. ast_test_validate(test, ast_ari_validate_string(uut));
  223. ast_test_validate(test, !ast_ari_validate_string(ast_json_null()));
  224. return AST_TEST_PASS;
  225. }
  226. AST_TEST_DEFINE(validate_date)
  227. {
  228. RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
  229. RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
  230. enum ast_test_result_state test_res;
  231. int res;
  232. int i;
  233. const char *valid_dates[] = {
  234. /* Time is optional */
  235. "2013-06-17",
  236. /* Seconds are optional */
  237. "2013-06-17T23:59Z",
  238. /* Subseconds are optional */
  239. "2013-06-17T23:59:59Z",
  240. /* Leap seconds are valid */
  241. "2013-06-30T23:59:61Z",
  242. /* Subseconds are allowed */
  243. "2013-06-17T23:59:59.999999Z",
  244. /* Now with -06:00 for the timezone */
  245. "2013-06-17T23:59-06:00",
  246. "2013-06-17T23:59:59-06:00",
  247. "2013-06-30T23:59:61-06:00",
  248. "2013-06-17T23:59:59.999999-06:00",
  249. /* Again, with +06:30 for the timezone */
  250. "2013-06-17T23:59+06:30",
  251. "2013-06-17T23:59:59+06:30",
  252. "2013-06-30T23:59:61+06:30",
  253. "2013-06-17T23:59:59.999999+06:30",
  254. /* So the colon in the timezone is optional */
  255. "2013-06-17T23:59-0600",
  256. "2013-06-17T23:59:59-0600",
  257. "2013-06-30T23:59:61-0600",
  258. "2013-06-17T23:59:59.999999-0600",
  259. /* Sure, why not */
  260. "2013-06-17T23:59+0630",
  261. "2013-06-17T23:59:59+0630",
  262. "2013-06-30T23:59:61+0630",
  263. "2013-06-17T23:59:59.999999+0630",
  264. "9999-12-31T23:59:61.999999Z",
  265. /* In fact, you don't even have to specify minutes */
  266. "2013-06-17T23:59-06",
  267. "2013-06-17T23:59:59-06",
  268. "2013-06-30T23:59:61-06",
  269. "2013-06-17T23:59:59.999999-06",
  270. };
  271. /* There are lots of invalid dates that the validator lets through.
  272. * Those would be strings properly formatted as a ridiculous date. Such
  273. * as 0000-00-00, or 9999-19-39. Those are harder to catch with a regex,
  274. * and actually aren't as important. So long as the valid dates pass the
  275. * validator, and poorly formatted dates are rejected, it's fine.
  276. * Catching the occasional ridiculous date is just bonus.
  277. */
  278. const char *invalid_dates[] = {
  279. "",
  280. "Not a date",
  281. "2013-06-17T", /* Missing time, but has T */
  282. "2013-06-17T23:59:59.Z", /* Missing subsecond, but has dot */
  283. "2013-06-17T23:59", /* Missing timezone, but has time */
  284. "2013-06-17T23:59:59.999999", /* Missing timezone */
  285. "9999-99-31T23:59:61.999999Z", /* Invalid month */
  286. "9999-12-99T23:59:61.999999Z", /* Invalid day */
  287. "9999-12-31T99:59:61.999999Z", /* Invalid hour */
  288. "9999-12-31T23:99:61.999999Z", /* Invalid minute */
  289. "9999-12-31T23:59:99.999999Z", /* Invalid second */
  290. "2013-06-17T23:59:59.999999-99:00", /* Invalid timezone */
  291. "2013-06-17T23:59:59.999999-06:99", /* Invalid timezone */
  292. "2013-06-17T23:59:59.999999-06:", /* Invalid timezone */
  293. "2013-06-17T23:59:59.999999-06:0", /* Invalid timezone */
  294. "2013-06-17T23:59:59.999999-060", /* Invalid timezone */
  295. };
  296. switch (cmd) {
  297. case TEST_INIT:
  298. info->name = __func__;
  299. info->category = "/ari/validators/";
  300. info->summary = "Test date validation";
  301. info->description =
  302. "Test date validation";
  303. return AST_TEST_NOT_RUN;
  304. case TEST_EXECUTE:
  305. break;
  306. }
  307. uut = ast_json_string_create("");
  308. ast_test_validate(test, NULL != uut);
  309. /* Instead of using ast_test_validate, we'll collect the results from
  310. * several test cases, since we have so many */
  311. test_res = AST_TEST_PASS;
  312. for (i = 0; i < ARRAY_LEN(valid_dates); ++i) {
  313. res = ast_json_string_set(uut, valid_dates[i]);
  314. ast_test_validate(test, 0 == res);
  315. if (!ast_ari_validate_date(uut)) {
  316. ast_test_status_update(test,
  317. "Expected '%s' to be a valid date\n",
  318. valid_dates[i]);
  319. test_res = AST_TEST_FAIL;
  320. }
  321. }
  322. for (i = 0; i < ARRAY_LEN(invalid_dates); ++i) {
  323. res = ast_json_string_set(uut, invalid_dates[i]);
  324. ast_test_validate(test, 0 == res);
  325. if (ast_ari_validate_date(uut)) {
  326. ast_test_status_update(test,
  327. "Expected '%s' to be an invalid date\n",
  328. invalid_dates[i]);
  329. test_res = AST_TEST_FAIL;
  330. }
  331. }
  332. ast_test_validate(test, !ast_ari_validate_string(ast_json_null()));
  333. return test_res;
  334. }
  335. AST_TEST_DEFINE(validate_list)
  336. {
  337. RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
  338. RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
  339. int res;
  340. switch (cmd) {
  341. case TEST_INIT:
  342. info->name = __func__;
  343. info->category = "/ari/validators/";
  344. info->summary = "Test list validation";
  345. info->description =
  346. "Test list validation";
  347. return AST_TEST_NOT_RUN;
  348. case TEST_EXECUTE:
  349. break;
  350. }
  351. uut = ast_json_array_create();
  352. ast_test_validate(test, NULL != uut);
  353. ast_test_validate(test, ast_ari_validate_list(uut, wrap_ast_ari_validate_string));
  354. ast_test_validate(test, ast_ari_validate_list(uut, wrap_ast_ari_validate_int));
  355. res = ast_json_array_append(uut, ast_json_string_create(""));
  356. ast_test_validate(test, 0 == res);
  357. ast_test_validate(test, ast_ari_validate_list(uut, wrap_ast_ari_validate_string));
  358. ast_test_validate(test, !ast_ari_validate_list(uut, wrap_ast_ari_validate_int));
  359. res = ast_json_array_append(uut, ast_json_integer_create(0));
  360. ast_test_validate(test, 0 == res);
  361. ast_test_validate(test, !ast_ari_validate_list(uut, wrap_ast_ari_validate_string));
  362. ast_test_validate(test, !ast_ari_validate_list(uut, wrap_ast_ari_validate_int));
  363. ast_test_validate(test,
  364. !ast_ari_validate_list(ast_json_null(), wrap_ast_ari_validate_string));
  365. return AST_TEST_PASS;
  366. }
  367. static int unload_module(void)
  368. {
  369. AST_TEST_UNREGISTER(validate_byte);
  370. AST_TEST_UNREGISTER(validate_boolean);
  371. AST_TEST_UNREGISTER(validate_int);
  372. AST_TEST_UNREGISTER(validate_long);
  373. AST_TEST_UNREGISTER(validate_string);
  374. AST_TEST_UNREGISTER(validate_date);
  375. AST_TEST_UNREGISTER(validate_list);
  376. return 0;
  377. }
  378. static int load_module(void)
  379. {
  380. AST_TEST_REGISTER(validate_byte);
  381. AST_TEST_REGISTER(validate_boolean);
  382. AST_TEST_REGISTER(validate_int);
  383. AST_TEST_REGISTER(validate_long);
  384. AST_TEST_REGISTER(validate_string);
  385. AST_TEST_REGISTER(validate_date);
  386. AST_TEST_REGISTER(validate_list);
  387. return AST_MODULE_LOAD_SUCCESS;
  388. }
  389. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Skeleton (sample) Test");