50 int res = AST_TEST_PASS;
51 const char *in =
"abcdefghijklmnopurstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 ~`!@#$%^&*()_-+={[}]|\\:;\"'<,>.?/";
52 char out[256] = { 0 };
53 char small[4] = { 0 };
66 const char *decoded_output;
69 #define INIT_ENCODE_TEST(s, buffer, in, out, dec_out) do { \
70 if (i < ARRAY_LEN(tests)) { \
71 tests[i].spec_str = #s; \
73 tests[i].buf = buffer; \
74 tests[i].buflen = sizeof(buffer); \
75 tests[i].input = in; \
76 tests[i].output = out; \
77 tests[i].decoded_output = dec_out; \
80 ast_test_status_update(test, "error: 'tests' array too small\n"); \
81 res = AST_TEST_FAIL; \
85 INIT_ENCODE_TEST(ast_uri_http, out, in,
86 "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);
87 INIT_ENCODE_TEST(ast_uri_http_legacy, out, in,
88 "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);
89 INIT_ENCODE_TEST(ast_uri_sip_user, out, in,
90 "abcdefghijklmnopurstuvwxyz%20ABCDEFGHIJKLMNOPQRSTUVWXYZ%201234567890%20~%60!%40%23$%25%5E&*()_-+=%7B%5B%7D%5D%7C%5C%3A;%22'%3C,%3E.?/", in);
91 INIT_ENCODE_TEST(none, small, in,
"%61",
"a");
92 INIT_ENCODE_TEST(ast_uri_http, small, in,
"abc",
"abc");
96 info->name =
"uri_encode_decode_test";
97 info->category =
"/main/utils/";
98 info->summary =
"encode and decode a hex escaped string";
99 info->description =
"encode a string, verify encoded string matches what we expect. Decode the encoded string, verify decoded string matches the original string.";
100 return AST_TEST_NOT_RUN;
105 for (i = 0; i < ARRAY_LEN(tests); i++) {
106 ast_uri_encode(tests[i].input, tests[i].buf, tests[i].buflen, tests[i].spec);
107 if (strcmp(tests[i].output, tests[i].buf)) {
108 ast_test_status_update(
test,
"encoding with %s did not match expected output, FAIL\n", tests[i].spec_str);
109 ast_test_status_update(
test,
"original: %s\n", tests[i].input);
110 ast_test_status_update(
test,
"expected: %s\n", tests[i].output);
111 ast_test_status_update(
test,
"result: %s\n", tests[i].buf);
117 if (strcmp(tests[i].decoded_output, tests[i].buf)) {
118 ast_test_status_update(
test,
"decoding with %s did not match the original input (or expected decoded output)\n", tests[i].spec_str);
119 ast_test_status_update(
test,
"original: %s\n", tests[i].input);
120 ast_test_status_update(
test,
"expected: %s\n", tests[i].decoded_output);
121 ast_test_status_update(
test,
"decoded: %s\n", tests[i].buf);
131 int res = AST_TEST_PASS;
132 const char *in =
"a\"bcdefg\"hijkl\\mnopqrs tuv\twxyz";
134 #define LONG_SIZE 256
144 "a\\\"bcdefg\\\"hijkl\\\\mnopqrs tuv\twxyz"},
154 info->name =
"quoted_escape_test";
155 info->category =
"/main/utils/";
156 info->summary =
"escape a quoted string";
157 info->description =
"Escape a string to be quoted and check the result.";
158 return AST_TEST_NOT_RUN;
163 for (i = 0; i < ARRAY_LEN(tests); i++) {
165 if (strcmp(tests[i].output, tests[i].buf)) {
166 ast_test_status_update(
test,
"ESCAPED DOES NOT MATCH EXPECTED, FAIL\n");
167 ast_test_status_update(
test,
"original: %s\n", in);
168 ast_test_status_update(
test,
"expected: %s\n", tests[i].output);
169 ast_test_status_update(
test,
"result: %s\n", tests[i].buf);
181 static const struct {
183 const char *expected_output;
185 {
"apples",
"daeccf0ad3c1fc8c8015205c332f5b42" },
186 {
"bananas",
"ec121ff80513ae58ed478d5c5787075b" },
187 {
"reallylongstringaboutgoatcheese",
"0a2d9280d37e2e37545cfef6e7e4e890" },
189 enum ast_test_result_state res = AST_TEST_PASS;
194 info->name =
"md5_test";
195 info->category =
"/main/utils/";
196 info->summary =
"MD5 test";
198 "This test exercises MD5 calculations."
200 return AST_TEST_NOT_RUN;
205 ast_test_status_update(
test,
"Testing MD5 ...\n");
207 for (i = 0; i < ARRAY_LEN(tests); i++) {
210 if (strcasecmp(md5_hash, tests[i].expected_output)) {
211 ast_test_status_update(
test,
212 "input: '%s' hash: '%s' expected hash: '%s'\n",
213 tests[i].input, md5_hash, tests[i].expected_output);
223 static const struct {
225 const char *expected_output;
228 "fac8f1a31d2998734d6a5253e49876b8e6a08239" },
230 "1dfb21b7a4d35e90d943e3a16107ccbfabd064d5" },
231 {
"ParastratiosphecomyiaStratiosphecomyioides",
232 "58af4e8438676f2bd3c4d8df9e00ee7fe06945bb" },
234 enum ast_test_result_state res = AST_TEST_PASS;
239 info->name =
"sha1_test";
240 info->category =
"/main/utils/";
241 info->summary =
"SHA1 test";
243 "This test exercises SHA1 calculations."
245 return AST_TEST_NOT_RUN;
250 ast_test_status_update(
test,
"Testing SHA1 ...\n");
252 for (i = 0; i < ARRAY_LEN(tests); i++) {
255 if (strcasecmp(sha1_hash, tests[i].expected_output)) {
256 ast_test_status_update(
test,
257 "input: '%s' hash: '%s' expected hash: '%s'\n",
258 tests[i].input, sha1_hash, tests[i].expected_output);
268 static const struct {
276 {
"ParastratiosphecomyiaStratiosphecomyioides",
277 "UGFyYXN0cmF0aW9zcGhlY29teWlhU3RyYXRpb3NwaGVjb215aW9pZGVz" },
280 enum ast_test_result_state res = AST_TEST_PASS;
284 info->name =
"base64_test";
285 info->category =
"/main/utils/";
286 info->summary =
"base64 test";
287 info->description =
"This test exercises the base64 conversions.";
288 return AST_TEST_NOT_RUN;
294 for (i = 0; i < ARRAY_LEN(tests); i++) {
296 ast_base64encode(tmp, (
unsigned char *)tests[i].input, strlen(tests[i].input),
sizeof(tmp));
297 if (strcasecmp(tmp, tests[i].decoded)) {
298 ast_test_status_update(
test,
299 "input: '%s' base64 output: '%s' expected base64 output: '%s'\n",
300 tests[i].input, tmp, tests[i].decoded);
304 memset(tmp, 0,
sizeof(tmp));
305 ast_base64decode((
unsigned char *) tmp, tests[i].decoded, (
sizeof(tmp) - 1));
306 if (strcasecmp(tmp, tests[i].input)) {
307 ast_test_status_update(
test,
308 "base64 input: '%s' output: '%s' expected output: '%s'\n",
309 tests[i].decoded, tmp, tests[i].input);
321 info->name =
"crypto_loaded_test";
322 info->category =
"/res/crypto/";
323 info->summary =
"Crypto loaded into memory";
324 info->description =
"Verifies whether the crypto functions overrode the stubs";
325 return AST_TEST_NOT_RUN;
330 return ast_crypto_loaded() ? AST_TEST_PASS : AST_TEST_FAIL;
339 info->name =
"adsi_loaded_test";
340 info->category =
"/res/adsi/";
341 info->summary =
"ADSI loaded into memory";
342 info->description =
"Verifies whether the adsi functions overrode the stubs";
343 return AST_TEST_NOT_RUN;
349 ast_test_status_update(
test,
"This test skipped because deprecated module res_adsi.so is not built by default.\n");
350 return AST_TEST_PASS;
354 return AST_TEST_FAIL;
356 ast_channel_adsicpe_set(c, AST_ADSI_AVAILABLE);
362 static int handle_noop(
struct ast_channel *chan,
AGI *agi,
int arg,
const char *
const argv[])
364 ast_agi_send(agi->
fd, chan,
"200 result=0\n");
365 return RESULT_SUCCESS;
370 int res = AST_TEST_PASS;
372 { {
"testnoop", NULL }, handle_noop, NULL, NULL, 0 };
376 info->name =
"agi_loaded_test";
377 info->category =
"/res/agi/";
378 info->summary =
"AGI loaded into memory";
379 info->description =
"Verifies whether the agi functions overrode the stubs";
380 return AST_TEST_NOT_RUN;
386 ast_test_status_update(
test,
"Unable to register testnoop command, because res_agi is not loaded.\n");
387 return AST_TEST_FAIL;
390 #ifndef HAVE_NULLSAFE_PRINTF
392 if (noop_command.
usage == NULL) {
393 ast_test_status_update(
test,
"AGI testnoop usage was not updated properly.\n");
396 if (noop_command.
syntax == NULL) {
397 ast_test_status_update(
test,
"AGI testnoop syntax was not updated properly.\n");
402 ast_agi_unregister(&noop_command);
408 char base_path[] =
"/tmp/safe_mkdir.XXXXXX";
415 info->name = __func__;
416 info->category =
"/main/utils/";
417 info->summary =
"Safe mkdir test";
419 "This test ensures that ast_safe_mkdir does what it is "
421 return AST_TEST_NOT_RUN;
426 if (mkdtemp(base_path) == NULL) {
427 ast_test_status_update(
test,
"Failed to create tmpdir for test\n");
428 return AST_TEST_FAIL;
431 snprintf(path,
sizeof(path),
"%s/should_work", base_path);
433 ast_test_validate(
test, 0 == res);
434 res = stat(path, &actual);
435 ast_test_validate(
test, 0 == res);
436 ast_test_validate(
test, S_ISDIR(actual.st_mode));
438 snprintf(path,
sizeof(path),
"%s/should/also/work", base_path);
440 ast_test_validate(
test, 0 == res);
441 res = stat(path, &actual);
442 ast_test_validate(
test, 0 == res);
443 ast_test_validate(
test, S_ISDIR(actual.st_mode));
445 snprintf(path,
sizeof(path),
"%s/even/this/../should/work", base_path);
447 ast_test_validate(
test, 0 == res);
448 snprintf(path,
sizeof(path),
"%s/even/should/work", base_path);
449 res = stat(path, &actual);
450 ast_test_validate(
test, 0 == res);
451 ast_test_validate(
test, S_ISDIR(actual.st_mode));
453 snprintf(path,
sizeof(path),
454 "%s/surprisingly/this/should//////////////////work", base_path);
456 ast_test_validate(
test, 0 == res);
457 snprintf(path,
sizeof(path),
458 "%s/surprisingly/this/should/work", base_path);
459 res = stat(path, &actual);
460 ast_test_validate(
test, 0 == res);
461 ast_test_validate(
test, S_ISDIR(actual.st_mode));
463 snprintf(path,
sizeof(path),
"/should_not_work");
465 ast_test_validate(
test, 0 != res);
466 ast_test_validate(
test, EPERM == errno);
467 res = stat(path, &actual);
468 ast_test_validate(
test, 0 != res);
469 ast_test_validate(
test, ENOENT == errno);
471 snprintf(path,
sizeof(path),
"%s/../nor_should_this", base_path);
473 ast_test_validate(
test, 0 != res);
474 ast_test_validate(
test, EPERM == errno);
475 strncpy(path,
"/tmp/nor_should_this",
sizeof(path));
476 res = stat(path, &actual);
477 ast_test_validate(
test, 0 != res);
478 ast_test_validate(
test, ENOENT == errno);
480 snprintf(path,
sizeof(path),
481 "%s/this/especially/should/not/../../../../../work", base_path);
483 ast_test_validate(
test, 0 != res);
484 ast_test_validate(
test, EPERM == errno);
485 strncpy(path,
"/tmp/work",
sizeof(path));
486 res = stat(path, &actual);
487 ast_test_validate(
test, 0 != res);
488 ast_test_validate(
test, ENOENT == errno);
490 return AST_TEST_PASS;
495 RAII_VAR(
char *, password_crypted, NULL, ast_free);
496 RAII_VAR(
char *, blank_crypted, NULL, ast_free);
497 const char *password =
"Passw0rd";
498 const char *not_a_password =
"not-a-password";
502 info->name =
"crypt_test";
503 info->category =
"/main/utils/";
504 info->summary =
"Test ast_crypt wrappers";
505 info->description =
"Verifies that the ast_crypt wrappers work as expected.";
506 return AST_TEST_NOT_RUN;
512 ast_test_validate(
test, NULL != password_crypted);
513 ast_test_validate(
test, 0 != strcmp(password, password_crypted));
515 ast_test_validate(
test,
519 ast_test_validate(
test, NULL != blank_crypted);
520 ast_test_validate(
test, 0 != strcmp(blank_crypted,
""));
522 ast_test_validate(
test,
525 return AST_TEST_PASS;
537 static const struct quote_set escape_sets[] = {
538 {
"\"string\"",
"\\\"string\\\""},
539 {
"\"string",
"\\\"string"},
540 {
"string\"",
"string\\\""},
541 {
"string",
"string"},
542 {
"str\"ing",
"str\\\"ing"},
544 {
"\\\"",
"\\\\\\\""},
550 info->name =
"quote_mutation";
551 info->category =
"/main/utils/";
552 info->summary =
"Test mutation of quotes in strings";
554 "This tests escaping and unescaping of quotes in strings to "
555 "verify that the original string is recovered.";
556 return AST_TEST_NOT_RUN;
561 for (i = 0; i < ARRAY_LEN(escape_sets); i++) {
564 if (strcmp(escaped, escape_sets[i].output)) {
565 ast_test_status_update(
test,
566 "Expected escaped string '%s' instead of '%s'\n",
567 escape_sets[i].output, escaped);
568 return AST_TEST_FAIL;
572 if (strcmp(escaped, escape_sets[i].input)) {
573 ast_test_status_update(
test,
574 "Expected unescaped string '%s' instead of '%s'\n",
575 escape_sets[i].input, escaped);
576 return AST_TEST_FAIL;
580 return AST_TEST_PASS;
585 static const struct quote_set escape_sets[] = {
586 {
"\"string\"",
"\"string\""},
587 {
"\\\"string\"",
"\"string\""},
588 {
"\"string\\\"",
"\"string\""},
589 {
"str\\ing",
"string"},
590 {
"string\\",
"string"},
591 {
"\\string",
"string"},
597 info->name =
"quote_unescaping";
598 info->category =
"/main/utils/";
599 info->summary =
"Test unescaping of off-nominal strings";
601 "This tests unescaping of strings which contain a mix of "
602 "escaped and unescaped sequences.";
603 return AST_TEST_NOT_RUN;
608 for (i = 0; i < ARRAY_LEN(escape_sets); i++) {
612 if (strcmp(escaped, escape_sets[i].output)) {
613 ast_test_status_update(
test,
614 "Expected unescaped string '%s' instead of '%s'\n",
615 escape_sets[i].output, escaped);
616 return AST_TEST_FAIL;
620 return AST_TEST_PASS;
623 static int unload_module(
void)
625 AST_TEST_UNREGISTER(uri_encode_decode_test);
626 AST_TEST_UNREGISTER(quoted_escape_test);
627 AST_TEST_UNREGISTER(md5_test);
628 AST_TEST_UNREGISTER(sha1_test);
629 AST_TEST_UNREGISTER(base64_test);
630 AST_TEST_UNREGISTER(crypto_loaded_test);
631 AST_TEST_UNREGISTER(adsi_loaded_test);
632 AST_TEST_UNREGISTER(agi_loaded_test);
633 AST_TEST_UNREGISTER(safe_mkdir_test);
634 AST_TEST_UNREGISTER(crypt_test);
635 AST_TEST_UNREGISTER(quote_mutation);
636 AST_TEST_UNREGISTER(quote_unescaping);
640 static int load_module(
void)
642 AST_TEST_REGISTER(uri_encode_decode_test);
643 AST_TEST_REGISTER(quoted_escape_test);
644 AST_TEST_REGISTER(md5_test);
645 AST_TEST_REGISTER(sha1_test);
646 AST_TEST_REGISTER(base64_test);
647 AST_TEST_REGISTER(crypto_loaded_test);
648 AST_TEST_REGISTER(adsi_loaded_test);
649 AST_TEST_REGISTER(agi_loaded_test);
650 AST_TEST_REGISTER(safe_mkdir_test);
651 AST_TEST_REGISTER(crypt_test);
652 AST_TEST_REGISTER(quote_mutation);
653 AST_TEST_REGISTER(quote_unescaping);
658 .support_level = AST_MODULE_SUPPORT_CORE,
660 .unload = unload_module,
661 .requires =
"res_agi,res_crypto",
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_channel_unref(c)
Decrease channel reference count.
AGI Extension interfaces - Asterisk Gateway Interface.
Provide cryptographic signature routines.
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
#define ast_strdup(str)
A wrapper for strdup()
ADSI Support (built upon Caller*ID)
int ast_module_check(const char *name)
Check if module with the name given is loaded.
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
General Asterisk PBX channel definitions.
#define ast_dummy_channel_alloc()
Create a fake channel structure.
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
#define AST_OPTIONAL_API_UNAVAILABLE
A common value for optional API stub functions to return.
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
int ast_safe_mkdir(const char *base_path, const char *path, int mode)
Recursively create directory path, but only if it resolves within the given base_path.
Structure used to handle boolean flags.
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
int ast_crypt_validate(const char *key, const char *expected)
Asterisk wrapper around crypt(3) for validating passwords.
#define AST_TEST_DEFINE(hdr)
void ast_md5_hash(char *output, const char *input)
Produces MD5 hash based on input string.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
char * ast_crypt_encrypt(const char *key)
Asterisk wrapper around crypt(3) for encrypting passwords.