test_utils.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2010, Digium, Inc.
  5. *
  6. * David Vossel <dvossel@digium.com>
  7. * Russell Bryant <russell@digium.com>
  8. *
  9. * See http://www.asterisk.org for more information about
  10. * the Asterisk project. Please do not directly contact
  11. * any of the maintainers of this project for assistance;
  12. * the project provides a web site, mailing lists and IRC
  13. * channels for your use.
  14. *
  15. * This program is free software, distributed under the terms of
  16. * the GNU General Public License Version 2. See the LICENSE file
  17. * at the top of the source tree.
  18. */
  19. /*!
  20. * \file
  21. * \brief Unit Tests for utils API
  22. *
  23. * \author David Vossel <dvossel@digium.com>
  24. * \author Russell Bryant <russell@digium.com>
  25. */
  26. /*** MODULEINFO
  27. <depend>TEST_FRAMEWORK</depend>
  28. <use type="module">res_agi</use>
  29. <use type="module">res_crypto</use>
  30. <use type="external">crypto</use>
  31. <support_level>core</support_level>
  32. ***/
  33. #include "asterisk.h"
  34. ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
  35. #include "asterisk/utils.h"
  36. #include "asterisk/test.h"
  37. #include "asterisk/crypto.h"
  38. #include "asterisk/adsi.h"
  39. #include "asterisk/agi.h"
  40. #include "asterisk/channel.h"
  41. #include "asterisk/module.h"
  42. #include <sys/stat.h>
  43. AST_TEST_DEFINE(uri_encode_decode_test)
  44. {
  45. int res = AST_TEST_PASS;
  46. const char *in = "abcdefghijklmnopurstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 ~`!@#$%^&*()_-+={[}]|\\:;\"'<,>.?/";
  47. char out[256] = { 0 };
  48. char small[4] = { 0 };
  49. const struct ast_flags none = {0};
  50. int i = 0;
  51. static struct {
  52. const char *spec_str;
  53. struct ast_flags spec;
  54. char *buf;
  55. size_t buflen;
  56. const char *input;
  57. const char *output;
  58. const char *decoded_output;
  59. } tests[5];
  60. #define INIT_ENCODE_TEST(s, buffer, in, out, dec_out) do { \
  61. if (i < ARRAY_LEN(tests)) { \
  62. tests[i].spec_str = #s; \
  63. tests[i].spec = s; \
  64. tests[i].buf = buffer; \
  65. tests[i].buflen = sizeof(buffer); \
  66. tests[i].input = in; \
  67. tests[i].output = out; \
  68. tests[i].decoded_output = dec_out; \
  69. i++; \
  70. } else { \
  71. ast_test_status_update(test, "error: 'tests' array too small\n"); \
  72. res = AST_TEST_FAIL; \
  73. } \
  74. } while (0)
  75. INIT_ENCODE_TEST(ast_uri_http, out, in,
  76. "abcdefghijklmnopurstuvwxyz%20ABCDEFGHIJKLMNOPQRSTUVWXYZ%201234567890%20~%60!%40%23%24%25%5E%26*()_-%2B%3D%7B%5B%7D%5D%7C%5C%3A%3B%22'%3C%2C%3E.%3F%2F", in);
  77. INIT_ENCODE_TEST(ast_uri_http_legacy, out, in,
  78. "abcdefghijklmnopurstuvwxyz+ABCDEFGHIJKLMNOPQRSTUVWXYZ+1234567890+~%60!%40%23%24%25%5E%26*()_-%2B%3D%7B%5B%7D%5D%7C%5C%3A%3B%22'%3C%2C%3E.%3F%2F", in);
  79. INIT_ENCODE_TEST(ast_uri_sip_user, out, in,
  80. "abcdefghijklmnopurstuvwxyz%20ABCDEFGHIJKLMNOPQRSTUVWXYZ%201234567890%20~%60!%40%23$%25%5E&*()_-+=%7B%5B%7D%5D%7C%5C%3A;%22'%3C,%3E.?/", in);
  81. INIT_ENCODE_TEST(none, small, in, "%61", "a");
  82. INIT_ENCODE_TEST(ast_uri_http, small, in, "abc", "abc");
  83. switch (cmd) {
  84. case TEST_INIT:
  85. info->name = "uri_encode_decode_test";
  86. info->category = "/main/utils/";
  87. info->summary = "encode and decode a hex escaped string";
  88. info->description = "encode a string, verify encoded string matches what we expect. Decode the encoded string, verify decoded string matches the original string.";
  89. return AST_TEST_NOT_RUN;
  90. case TEST_EXECUTE:
  91. break;
  92. }
  93. for (i = 0; i < ARRAY_LEN(tests); i++) {
  94. ast_uri_encode(tests[i].input, tests[i].buf, tests[i].buflen, tests[i].spec);
  95. if (strcmp(tests[i].output, tests[i].buf)) {
  96. ast_test_status_update(test, "encoding with %s did not match expected output, FAIL\n", tests[i].spec_str);
  97. ast_test_status_update(test, "original: %s\n", tests[i].input);
  98. ast_test_status_update(test, "expected: %s\n", tests[i].output);
  99. ast_test_status_update(test, "result: %s\n", tests[i].buf);
  100. res = AST_TEST_FAIL;
  101. continue;
  102. }
  103. ast_uri_decode(tests[i].buf, tests[i].spec);
  104. if (strcmp(tests[i].decoded_output, tests[i].buf)) {
  105. ast_test_status_update(test, "decoding with %s did not match the original input (or expected decoded output)\n", tests[i].spec_str);
  106. ast_test_status_update(test, "original: %s\n", tests[i].input);
  107. ast_test_status_update(test, "expected: %s\n", tests[i].decoded_output);
  108. ast_test_status_update(test, "decoded: %s\n", tests[i].buf);
  109. res = AST_TEST_FAIL;
  110. }
  111. }
  112. return res;
  113. }
  114. AST_TEST_DEFINE(quoted_escape_test)
  115. {
  116. int res = AST_TEST_PASS;
  117. const char *in = "a\"bcdefg\"hijkl\\mnopqrs tuv\twxyz";
  118. char out[256] = { 0 };
  119. char small[4] = { 0 };
  120. int i;
  121. static struct {
  122. char *buf;
  123. const size_t buflen;
  124. const char *output;
  125. } tests[] = {
  126. {0, sizeof(out),
  127. "a\\\"bcdefg\\\"hijkl\\\\mnopqrs tuv\twxyz"},
  128. {0, sizeof(small),
  129. "a\\\""},
  130. };
  131. tests[0].buf = out;
  132. tests[1].buf = small;
  133. switch (cmd) {
  134. case TEST_INIT:
  135. info->name = "quoted_escape_test";
  136. info->category = "/main/utils/";
  137. info->summary = "escape a quoted string";
  138. info->description = "Escape a string to be quoted and check the result.";
  139. return AST_TEST_NOT_RUN;
  140. case TEST_EXECUTE:
  141. break;
  142. }
  143. for (i = 0; i < ARRAY_LEN(tests); i++) {
  144. ast_escape_quoted(in, tests[i].buf, tests[i].buflen);
  145. if (strcmp(tests[i].output, tests[i].buf)) {
  146. ast_test_status_update(test, "ESCAPED DOES NOT MATCH EXPECTED, FAIL\n");
  147. ast_test_status_update(test, "original: %s\n", in);
  148. ast_test_status_update(test, "expected: %s\n", tests[i].output);
  149. ast_test_status_update(test, "result: %s\n", tests[i].buf);
  150. res = AST_TEST_FAIL;
  151. }
  152. }
  153. return res;
  154. }
  155. AST_TEST_DEFINE(md5_test)
  156. {
  157. static const struct {
  158. const char *input;
  159. const char *expected_output;
  160. } tests[] = {
  161. { "apples", "daeccf0ad3c1fc8c8015205c332f5b42" },
  162. { "bananas", "ec121ff80513ae58ed478d5c5787075b" },
  163. { "reallylongstringaboutgoatcheese", "0a2d9280d37e2e37545cfef6e7e4e890" },
  164. };
  165. enum ast_test_result_state res = AST_TEST_PASS;
  166. int i;
  167. switch (cmd) {
  168. case TEST_INIT:
  169. info->name = "md5_test";
  170. info->category = "/main/utils/";
  171. info->summary = "MD5 test";
  172. info->description =
  173. "This test exercises MD5 calculations."
  174. "";
  175. return AST_TEST_NOT_RUN;
  176. case TEST_EXECUTE:
  177. break;
  178. }
  179. ast_test_status_update(test, "Testing MD5 ...\n");
  180. for (i = 0; i < ARRAY_LEN(tests); i++) {
  181. char md5_hash[33];
  182. ast_md5_hash(md5_hash, tests[i].input);
  183. if (strcasecmp(md5_hash, tests[i].expected_output)) {
  184. ast_test_status_update(test,
  185. "input: '%s' hash: '%s' expected hash: '%s'\n",
  186. tests[i].input, md5_hash, tests[i].expected_output);
  187. res = AST_TEST_FAIL;
  188. }
  189. }
  190. return res;
  191. }
  192. AST_TEST_DEFINE(sha1_test)
  193. {
  194. static const struct {
  195. const char *input;
  196. const char *expected_output;
  197. } tests[] = {
  198. { "giraffe",
  199. "fac8f1a31d2998734d6a5253e49876b8e6a08239" },
  200. { "platypus",
  201. "1dfb21b7a4d35e90d943e3a16107ccbfabd064d5" },
  202. { "ParastratiosphecomyiaStratiosphecomyioides",
  203. "58af4e8438676f2bd3c4d8df9e00ee7fe06945bb" },
  204. };
  205. enum ast_test_result_state res = AST_TEST_PASS;
  206. int i;
  207. switch (cmd) {
  208. case TEST_INIT:
  209. info->name = "sha1_test";
  210. info->category = "/main/utils/";
  211. info->summary = "SHA1 test";
  212. info->description =
  213. "This test exercises SHA1 calculations."
  214. "";
  215. return AST_TEST_NOT_RUN;
  216. case TEST_EXECUTE:
  217. break;
  218. }
  219. ast_test_status_update(test, "Testing SHA1 ...\n");
  220. for (i = 0; i < ARRAY_LEN(tests); i++) {
  221. char sha1_hash[64];
  222. ast_sha1_hash(sha1_hash, tests[i].input);
  223. if (strcasecmp(sha1_hash, tests[i].expected_output)) {
  224. ast_test_status_update(test,
  225. "input: '%s' hash: '%s' expected hash: '%s'\n",
  226. tests[i].input, sha1_hash, tests[i].expected_output);
  227. res = AST_TEST_FAIL;
  228. }
  229. }
  230. return res;
  231. }
  232. AST_TEST_DEFINE(base64_test)
  233. {
  234. static const struct {
  235. const char *input;
  236. const char *decoded;
  237. } tests[] = {
  238. { "giraffe",
  239. "Z2lyYWZmZQ==" },
  240. { "platypus",
  241. "cGxhdHlwdXM=" },
  242. { "ParastratiosphecomyiaStratiosphecomyioides",
  243. "UGFyYXN0cmF0aW9zcGhlY29teWlhU3RyYXRpb3NwaGVjb215aW9pZGVz" },
  244. };
  245. int i;
  246. enum ast_test_result_state res = AST_TEST_PASS;
  247. switch (cmd) {
  248. case TEST_INIT:
  249. info->name = "base64_test";
  250. info->category = "/main/utils/";
  251. info->summary = "base64 test";
  252. info->description = "This test exercises the base64 conversions.";
  253. return AST_TEST_NOT_RUN;
  254. case TEST_EXECUTE:
  255. break;
  256. }
  257. for (i = 0; i < ARRAY_LEN(tests); i++) {
  258. char tmp[64];
  259. ast_base64encode(tmp, (unsigned char *)tests[i].input, strlen(tests[i].input), sizeof(tmp));
  260. if (strcasecmp(tmp, tests[i].decoded)) {
  261. ast_test_status_update(test,
  262. "input: '%s' base64 output: '%s' expected base64 output: '%s'\n",
  263. tests[i].input, tmp, tests[i].decoded);
  264. res = AST_TEST_FAIL;
  265. }
  266. memset(tmp, 0, sizeof(tmp));
  267. ast_base64decode((unsigned char *) tmp, tests[i].decoded, (sizeof(tmp) - 1));
  268. if (strcasecmp(tmp, tests[i].input)) {
  269. ast_test_status_update(test,
  270. "base64 input: '%s' output: '%s' expected output: '%s'\n",
  271. tests[i].decoded, tmp, tests[i].input);
  272. res = AST_TEST_FAIL;
  273. }
  274. }
  275. return res;
  276. }
  277. AST_TEST_DEFINE(crypto_loaded_test)
  278. {
  279. switch (cmd) {
  280. case TEST_INIT:
  281. info->name = "crypto_loaded_test";
  282. info->category = "/res/crypto/";
  283. info->summary = "Crypto loaded into memory";
  284. info->description = "Verifies whether the crypto functions overrode the stubs";
  285. return AST_TEST_NOT_RUN;
  286. case TEST_EXECUTE:
  287. break;
  288. }
  289. return ast_crypto_loaded() ? AST_TEST_PASS : AST_TEST_FAIL;
  290. }
  291. AST_TEST_DEFINE(adsi_loaded_test)
  292. {
  293. struct ast_channel *c;
  294. int res;
  295. switch (cmd) {
  296. case TEST_INIT:
  297. info->name = "adsi_loaded_test";
  298. info->category = "/res/adsi/";
  299. info->summary = "ADSI loaded into memory";
  300. info->description = "Verifies whether the adsi functions overrode the stubs";
  301. return AST_TEST_NOT_RUN;
  302. case TEST_EXECUTE:
  303. break;
  304. }
  305. if (!(c = ast_dummy_channel_alloc())) {
  306. return AST_TEST_FAIL;
  307. }
  308. ast_channel_adsicpe_set(c, AST_ADSI_AVAILABLE);
  309. res = ast_adsi_available(c) ? AST_TEST_PASS : AST_TEST_FAIL;
  310. c = ast_channel_unref(c);
  311. return res;
  312. }
  313. static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, const char * const argv[])
  314. {
  315. ast_agi_send(agi->fd, chan, "200 result=0\n");
  316. return RESULT_SUCCESS;
  317. }
  318. AST_TEST_DEFINE(agi_loaded_test)
  319. {
  320. int res = AST_TEST_PASS;
  321. struct agi_command noop_command =
  322. { { "testnoop", NULL }, handle_noop, NULL, NULL, 0 };
  323. switch (cmd) {
  324. case TEST_INIT:
  325. info->name = "agi_loaded_test";
  326. info->category = "/res/agi/";
  327. info->summary = "AGI loaded into memory";
  328. info->description = "Verifies whether the agi functions overrode the stubs";
  329. return AST_TEST_NOT_RUN;
  330. case TEST_EXECUTE:
  331. break;
  332. }
  333. if (ast_agi_register(ast_module_info->self, &noop_command) == AST_OPTIONAL_API_UNAVAILABLE) {
  334. ast_test_status_update(test, "Unable to register testnoop command, because res_agi is not loaded.\n");
  335. return AST_TEST_FAIL;
  336. }
  337. #ifndef HAVE_NULLSAFE_PRINTF
  338. /* Test for condition without actually crashing Asterisk */
  339. if (noop_command.usage == NULL) {
  340. ast_test_status_update(test, "AGI testnoop usage was not updated properly.\n");
  341. res = AST_TEST_FAIL;
  342. }
  343. if (noop_command.syntax == NULL) {
  344. ast_test_status_update(test, "AGI testnoop syntax was not updated properly.\n");
  345. res = AST_TEST_FAIL;
  346. }
  347. #endif
  348. ast_agi_unregister(ast_module_info->self, &noop_command);
  349. return res;
  350. }
  351. AST_TEST_DEFINE(safe_mkdir_test)
  352. {
  353. char base_path[] = "/tmp/safe_mkdir.XXXXXX";
  354. char path[80] = {};
  355. int res;
  356. struct stat actual;
  357. switch (cmd) {
  358. case TEST_INIT:
  359. info->name = __func__;
  360. info->category = "/main/utils/";
  361. info->summary = "Safe mkdir test";
  362. info->description =
  363. "This test ensures that ast_safe_mkdir does what it is "
  364. "supposed to";
  365. return AST_TEST_NOT_RUN;
  366. case TEST_EXECUTE:
  367. break;
  368. }
  369. if (mkdtemp(base_path) == NULL) {
  370. ast_test_status_update(test, "Failed to create tmpdir for test\n");
  371. return AST_TEST_FAIL;
  372. }
  373. snprintf(path, sizeof(path), "%s/should_work", base_path);
  374. res = ast_safe_mkdir(base_path, path, 0777);
  375. ast_test_validate(test, 0 == res);
  376. res = stat(path, &actual);
  377. ast_test_validate(test, 0 == res);
  378. ast_test_validate(test, S_ISDIR(actual.st_mode));
  379. snprintf(path, sizeof(path), "%s/should/also/work", base_path);
  380. res = ast_safe_mkdir(base_path, path, 0777);
  381. ast_test_validate(test, 0 == res);
  382. res = stat(path, &actual);
  383. ast_test_validate(test, 0 == res);
  384. ast_test_validate(test, S_ISDIR(actual.st_mode));
  385. snprintf(path, sizeof(path), "%s/even/this/../should/work", base_path);
  386. res = ast_safe_mkdir(base_path, path, 0777);
  387. ast_test_validate(test, 0 == res);
  388. snprintf(path, sizeof(path), "%s/even/should/work", base_path);
  389. res = stat(path, &actual);
  390. ast_test_validate(test, 0 == res);
  391. ast_test_validate(test, S_ISDIR(actual.st_mode));
  392. snprintf(path, sizeof(path),
  393. "%s/surprisingly/this/should//////////////////work", base_path);
  394. res = ast_safe_mkdir(base_path, path, 0777);
  395. ast_test_validate(test, 0 == res);
  396. snprintf(path, sizeof(path),
  397. "%s/surprisingly/this/should/work", base_path);
  398. res = stat(path, &actual);
  399. ast_test_validate(test, 0 == res);
  400. ast_test_validate(test, S_ISDIR(actual.st_mode));
  401. snprintf(path, sizeof(path), "/should_not_work");
  402. res = ast_safe_mkdir(base_path, path, 0777);
  403. ast_test_validate(test, 0 != res);
  404. ast_test_validate(test, EPERM == errno);
  405. res = stat(path, &actual);
  406. ast_test_validate(test, 0 != res);
  407. ast_test_validate(test, ENOENT == errno);
  408. snprintf(path, sizeof(path), "%s/../nor_should_this", base_path);
  409. res = ast_safe_mkdir(base_path, path, 0777);
  410. ast_test_validate(test, 0 != res);
  411. ast_test_validate(test, EPERM == errno);
  412. strncpy(path, "/tmp/nor_should_this", sizeof(path));
  413. res = stat(path, &actual);
  414. ast_test_validate(test, 0 != res);
  415. ast_test_validate(test, ENOENT == errno);
  416. snprintf(path, sizeof(path),
  417. "%s/this/especially/should/not/../../../../../work", base_path);
  418. res = ast_safe_mkdir(base_path, path, 0777);
  419. ast_test_validate(test, 0 != res);
  420. ast_test_validate(test, EPERM == errno);
  421. strncpy(path, "/tmp/work", sizeof(path));
  422. res = stat(path, &actual);
  423. ast_test_validate(test, 0 != res);
  424. ast_test_validate(test, ENOENT == errno);
  425. return AST_TEST_PASS;
  426. }
  427. AST_TEST_DEFINE(crypt_test)
  428. {
  429. RAII_VAR(char *, password_crypted, NULL, ast_free);
  430. RAII_VAR(char *, blank_crypted, NULL, ast_free);
  431. const char *password = "Passw0rd";
  432. const char *not_a_password = "not-a-password";
  433. switch (cmd) {
  434. case TEST_INIT:
  435. info->name = "crypt_test";
  436. info->category = "/main/utils/";
  437. info->summary = "Test ast_crypt wrappers";
  438. info->description = "Verifies that the ast_crypt wrappers work as expected.";
  439. return AST_TEST_NOT_RUN;
  440. case TEST_EXECUTE:
  441. break;
  442. }
  443. password_crypted = ast_crypt_encrypt(password);
  444. ast_test_validate(test, NULL != password_crypted);
  445. ast_test_validate(test, 0 != strcmp(password, password_crypted));
  446. ast_test_validate(test, ast_crypt_validate(password, password_crypted));
  447. ast_test_validate(test,
  448. !ast_crypt_validate(not_a_password, password_crypted));
  449. blank_crypted = ast_crypt_encrypt("");
  450. ast_test_validate(test, NULL != blank_crypted);
  451. ast_test_validate(test, 0 != strcmp(blank_crypted, ""));
  452. ast_test_validate(test, ast_crypt_validate("", blank_crypted));
  453. ast_test_validate(test,
  454. !ast_crypt_validate(not_a_password, blank_crypted));
  455. return AST_TEST_PASS;
  456. }
  457. struct quote_set {
  458. char *input;
  459. char *output;
  460. };
  461. AST_TEST_DEFINE(quote_mutation)
  462. {
  463. char escaped[64];
  464. static const struct quote_set escape_sets[] = {
  465. {"\"string\"", "\\\"string\\\""},
  466. {"\"string", "\\\"string"},
  467. {"string\"", "string\\\""},
  468. {"string", "string"},
  469. {"str\"ing", "str\\\"ing"},
  470. {"\"", "\\\""},
  471. {"\\\"", "\\\\\\\""},
  472. };
  473. int i;
  474. switch (cmd) {
  475. case TEST_INIT:
  476. info->name = "quote_mutation";
  477. info->category = "/main/utils/";
  478. info->summary = "Test mutation of quotes in strings";
  479. info->description =
  480. "This tests escaping and unescaping of quotes in strings to "
  481. "verify that the original string is recovered.";
  482. return AST_TEST_NOT_RUN;
  483. case TEST_EXECUTE:
  484. break;
  485. }
  486. for (i = 0; i < ARRAY_LEN(escape_sets); i++) {
  487. ast_escape_quoted(escape_sets[i].input, escaped, sizeof(escaped));
  488. if (strcmp(escaped, escape_sets[i].output)) {
  489. ast_test_status_update(test,
  490. "Expected escaped string '%s' instead of '%s'\n",
  491. escape_sets[i].output, escaped);
  492. return AST_TEST_FAIL;
  493. }
  494. ast_unescape_quoted(escaped);
  495. if (strcmp(escaped, escape_sets[i].input)) {
  496. ast_test_status_update(test,
  497. "Expected unescaped string '%s' instead of '%s'\n",
  498. escape_sets[i].input, escaped);
  499. return AST_TEST_FAIL;
  500. }
  501. }
  502. return AST_TEST_PASS;
  503. }
  504. AST_TEST_DEFINE(quote_unescaping)
  505. {
  506. static const struct quote_set escape_sets[] = {
  507. {"\"string\"", "\"string\""},
  508. {"\\\"string\"", "\"string\""},
  509. {"\"string\\\"", "\"string\""},
  510. {"str\\ing", "string"},
  511. {"string\\", "string"},
  512. {"\\string", "string"},
  513. };
  514. int i;
  515. switch (cmd) {
  516. case TEST_INIT:
  517. info->name = "quote_unescaping";
  518. info->category = "/main/utils/";
  519. info->summary = "Test unescaping of off-nominal strings";
  520. info->description =
  521. "This tests unescaping of strings which contain a mix of "
  522. "escaped and unescaped sequences.";
  523. return AST_TEST_NOT_RUN;
  524. case TEST_EXECUTE:
  525. break;
  526. }
  527. for (i = 0; i < ARRAY_LEN(escape_sets); i++) {
  528. RAII_VAR(char *, escaped, ast_strdup(escape_sets[i].input), ast_free);
  529. ast_unescape_quoted(escaped);
  530. if (strcmp(escaped, escape_sets[i].output)) {
  531. ast_test_status_update(test,
  532. "Expected unescaped string '%s' instead of '%s'\n",
  533. escape_sets[i].output, escaped);
  534. return AST_TEST_FAIL;
  535. }
  536. }
  537. return AST_TEST_PASS;
  538. }
  539. static int unload_module(void)
  540. {
  541. AST_TEST_UNREGISTER(uri_encode_decode_test);
  542. AST_TEST_UNREGISTER(quoted_escape_test);
  543. AST_TEST_UNREGISTER(md5_test);
  544. AST_TEST_UNREGISTER(sha1_test);
  545. AST_TEST_UNREGISTER(base64_test);
  546. AST_TEST_UNREGISTER(crypto_loaded_test);
  547. AST_TEST_UNREGISTER(adsi_loaded_test);
  548. AST_TEST_UNREGISTER(agi_loaded_test);
  549. AST_TEST_UNREGISTER(safe_mkdir_test);
  550. AST_TEST_UNREGISTER(crypt_test);
  551. AST_TEST_UNREGISTER(quote_mutation);
  552. AST_TEST_UNREGISTER(quote_unescaping);
  553. return 0;
  554. }
  555. static int load_module(void)
  556. {
  557. AST_TEST_REGISTER(uri_encode_decode_test);
  558. AST_TEST_REGISTER(quoted_escape_test);
  559. AST_TEST_REGISTER(md5_test);
  560. AST_TEST_REGISTER(sha1_test);
  561. AST_TEST_REGISTER(base64_test);
  562. AST_TEST_REGISTER(crypto_loaded_test);
  563. AST_TEST_REGISTER(adsi_loaded_test);
  564. AST_TEST_REGISTER(agi_loaded_test);
  565. AST_TEST_REGISTER(safe_mkdir_test);
  566. AST_TEST_REGISTER(crypt_test);
  567. AST_TEST_REGISTER(quote_mutation);
  568. AST_TEST_REGISTER(quote_unescaping);
  569. return AST_MODULE_LOAD_SUCCESS;
  570. }
  571. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Utils test module");