Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Macros | Functions | Variables
test_utils.c File Reference

Unit Tests for utils API. More...

#include "asterisk.h"
#include "asterisk/utils.h"
#include "asterisk/test.h"
#include "asterisk/crypto.h"
#include "asterisk/adsi.h"
#include "asterisk/agi.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include <sys/stat.h>
Include dependency graph for test_utils.c:

Go to the source code of this file.

Data Structures

struct  quote_set
 

Macros

#define INIT_ENCODE_TEST(s, buffer, in, out, dec_out)
 
#define LONG_SIZE   256
 
#define SHORT_SIZE   4
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (adsi_loaded_test)
 
 AST_TEST_DEFINE (agi_loaded_test)
 
 AST_TEST_DEFINE (base64_test)
 
 AST_TEST_DEFINE (crypt_test)
 
 AST_TEST_DEFINE (crypto_loaded_test)
 
 AST_TEST_DEFINE (md5_test)
 
 AST_TEST_DEFINE (quote_mutation)
 
 AST_TEST_DEFINE (quote_unescaping)
 
 AST_TEST_DEFINE (quoted_escape_test)
 
 AST_TEST_DEFINE (safe_mkdir_test)
 
 AST_TEST_DEFINE (sha1_test)
 
 AST_TEST_DEFINE (uri_encode_decode_test)
 
static int handle_noop (struct ast_channel *chan, AGI *agi, int arg, const char *const argv[])
 
static int load_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Utils test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "res_agi,res_crypto", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

Unit Tests for utils API.

Author
David Vossel dvoss.nosp@m.el@d.nosp@m.igium.nosp@m..com
Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com

Definition in file test_utils.c.

Macro Definition Documentation

◆ INIT_ENCODE_TEST

#define INIT_ENCODE_TEST (   s,
  buffer,
  in,
  out,
  dec_out 
)

◆ LONG_SIZE

#define LONG_SIZE   256

◆ SHORT_SIZE

#define SHORT_SIZE   4

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 662 of file test_utils.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 662 of file test_utils.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 662 of file test_utils.c.

◆ AST_TEST_DEFINE() [1/12]

AST_TEST_DEFINE ( adsi_loaded_test  )

Definition at line 333 of file test_utils.c.

334{
335 struct ast_channel *c;
336 int res;
337 switch (cmd) {
338 case TEST_INIT:
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;
344 case TEST_EXECUTE:
345 break;
346 }
347
348 if (!ast_module_check("res_adsi.so")) {
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;
351 }
352
353 if (!(c = ast_dummy_channel_alloc())) {
354 return AST_TEST_FAIL;
355 }
359 return res;
360}
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263
@ AST_ADSI_AVAILABLE
Definition: channel.h:870
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1282
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
int ast_module_check(const char *name)
Check if module with the name given is loaded.
Definition: loader.c:2669
def info(msg)
Main Channel structure associated with a channel.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
static struct test_val c

References ast_adsi_available(), AST_ADSI_AVAILABLE, ast_channel_adsicpe_set(), ast_channel_unref, ast_dummy_channel_alloc, ast_module_check(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, c, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [2/12]

AST_TEST_DEFINE ( agi_loaded_test  )

Definition at line 368 of file test_utils.c.

369{
370 int res = AST_TEST_PASS;
371 struct agi_command noop_command =
372 { { "testnoop", NULL }, handle_noop, NULL, NULL, 0 };
373
374 switch (cmd) {
375 case TEST_INIT:
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;
381 case TEST_EXECUTE:
382 break;
383 }
384
386 ast_test_status_update(test, "Unable to register testnoop command, because res_agi is not loaded.\n");
387 return AST_TEST_FAIL;
388 }
389
390#ifndef HAVE_NULLSAFE_PRINTF
391 /* Test for condition without actually crashing Asterisk */
392 if (noop_command.usage == NULL) {
393 ast_test_status_update(test, "AGI testnoop usage was not updated properly.\n");
394 res = AST_TEST_FAIL;
395 }
396 if (noop_command.syntax == NULL) {
397 ast_test_status_update(test, "AGI testnoop syntax was not updated properly.\n");
398 res = AST_TEST_FAIL;
399 }
400#endif
401
402 ast_agi_unregister(&noop_command);
403 return res;
404}
int ast_agi_register(struct ast_module *mod, agi_command *cmd)
Registers an AGI command.
Definition: res_agi.c:3815
int ast_agi_unregister(agi_command *cmd)
Unregisters an AGI command.
Definition: res_agi.c:3859
#define AST_OPTIONAL_API_UNAVAILABLE
A common value for optional API stub functions to return.
Definition: optional_api.h:74
#define NULL
Definition: resample.c:96
const char *const usage
Definition: agi.h:50
const char *const syntax
Definition: agi.h:54
struct ast_module * self
Definition: module.h:342
static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, const char *const argv[])
Definition: test_utils.c:362

References ast_agi_register(), ast_agi_unregister(), AST_OPTIONAL_API_UNAVAILABLE, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, handle_noop(), sip_to_pjsip::info(), NULL, ast_module_info::self, agi_command::syntax, TEST_EXECUTE, TEST_INIT, and agi_command::usage.

◆ AST_TEST_DEFINE() [3/12]

AST_TEST_DEFINE ( base64_test  )

Definition at line 266 of file test_utils.c.

267{
268 static const struct {
269 const char *input;
270 const char *decoded;
271 } tests[] = {
272 { "giraffe",
273 "Z2lyYWZmZQ==" },
274 { "platypus",
275 "cGxhdHlwdXM=" },
276 { "ParastratiosphecomyiaStratiosphecomyioides",
277 "UGFyYXN0cmF0aW9zcGhlY29teWlhU3RyYXRpb3NwaGVjb215aW9pZGVz" },
278 };
279 int i;
281
282 switch (cmd) {
283 case TEST_INIT:
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;
289 case TEST_EXECUTE:
290 break;
291 }
292
293
294 for (i = 0; i < ARRAY_LEN(tests); i++) {
295 char tmp[64];
296 ast_base64encode(tmp, (unsigned char *)tests[i].input, strlen(tests[i].input), sizeof(tmp));
297 if (strcasecmp(tmp, tests[i].decoded)) {
299 "input: '%s' base64 output: '%s' expected base64 output: '%s'\n",
300 tests[i].input, tmp, tests[i].decoded);
301 res = AST_TEST_FAIL;
302 }
303
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)) {
308 "base64 input: '%s' output: '%s' expected output: '%s'\n",
309 tests[i].decoded, tmp, tests[i].input);
310 res = AST_TEST_FAIL;
311 }
312 }
313
314 return res;
315}
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1570
static int tmp()
Definition: bt_open.c:389
ast_test_result_state
Definition: test.h:193
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
Definition: utils.c:296
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: utils.c:406
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_base64decode(), ast_base64encode(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, sip_to_pjsip::info(), input(), TEST_EXECUTE, TEST_INIT, and tmp().

◆ AST_TEST_DEFINE() [4/12]

AST_TEST_DEFINE ( crypt_test  )

Definition at line 493 of file test_utils.c.

494{
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";
499
500 switch (cmd) {
501 case TEST_INIT:
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;
507 case TEST_EXECUTE:
508 break;
509 }
510
511 password_crypted = ast_crypt_encrypt(password);
512 ast_test_validate(test, NULL != password_crypted);
513 ast_test_validate(test, 0 != strcmp(password, password_crypted));
514 ast_test_validate(test, ast_crypt_validate(password, password_crypted));
515 ast_test_validate(test,
516 !ast_crypt_validate(not_a_password, password_crypted));
517
518 blank_crypted = ast_crypt_encrypt("");
519 ast_test_validate(test, NULL != blank_crypted);
520 ast_test_validate(test, 0 != strcmp(blank_crypted, ""));
521 ast_test_validate(test, ast_crypt_validate("", blank_crypted));
522 ast_test_validate(test,
523 !ast_crypt_validate(not_a_password, blank_crypted));
524
525 return AST_TEST_PASS;
526}
#define ast_free(a)
Definition: astmm.h:180
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
int ast_crypt_validate(const char *key, const char *expected)
Asterisk wrapper around crypt(3) for validating passwords.
Definition: crypt.c:136
char * ast_crypt_encrypt(const char *key)
Asterisk wrapper around crypt(3) for encrypting passwords.
Definition: crypt.c:190

References ast_crypt_encrypt(), ast_crypt_validate(), ast_free, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), NULL, RAII_VAR, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [5/12]

AST_TEST_DEFINE ( crypto_loaded_test  )

Definition at line 317 of file test_utils.c.

318{
319 switch (cmd) {
320 case TEST_INIT:
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;
326 case TEST_EXECUTE:
327 break;
328 }
329
331}
int ast_crypto_loaded(void)
Definition: res_crypto.c:689

References ast_crypto_loaded(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [6/12]

AST_TEST_DEFINE ( md5_test  )

Definition at line 179 of file test_utils.c.

180{
181 static const struct {
182 const char *input;
183 const char *expected_output;
184 } tests[] = {
185 { "apples", "daeccf0ad3c1fc8c8015205c332f5b42" },
186 { "bananas", "ec121ff80513ae58ed478d5c5787075b" },
187 { "reallylongstringaboutgoatcheese", "0a2d9280d37e2e37545cfef6e7e4e890" },
188 };
190 int i;
191
192 switch (cmd) {
193 case TEST_INIT:
194 info->name = "md5_test";
195 info->category = "/main/utils/";
196 info->summary = "MD5 test";
197 info->description =
198 "This test exercises MD5 calculations."
199 "";
200 return AST_TEST_NOT_RUN;
201 case TEST_EXECUTE:
202 break;
203 }
204
205 ast_test_status_update(test, "Testing MD5 ...\n");
206
207 for (i = 0; i < ARRAY_LEN(tests); i++) {
208 char md5_hash[33];
209 ast_md5_hash(md5_hash, tests[i].input);
210 if (strcasecmp(md5_hash, tests[i].expected_output)) {
212 "input: '%s' hash: '%s' expected hash: '%s'\n",
213 tests[i].input, md5_hash, tests[i].expected_output);
214 res = AST_TEST_FAIL;
215 }
216 }
217
218 return res;
219}
void ast_md5_hash(char *output, const char *input)
Produces MD5 hash based on input string.
Definition: utils.c:250

References ARRAY_LEN, ast_md5_hash(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, sip_to_pjsip::info(), input(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [7/12]

AST_TEST_DEFINE ( quote_mutation  )

Definition at line 534 of file test_utils.c.

535{
536 char escaped[64];
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"},
543 {"\"", "\\\""},
544 {"\\\"", "\\\\\\\""},
545 };
546 int i;
547
548 switch (cmd) {
549 case TEST_INIT:
550 info->name = "quote_mutation";
551 info->category = "/main/utils/";
552 info->summary = "Test mutation of quotes in strings";
553 info->description =
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;
557 case TEST_EXECUTE:
558 break;
559 }
560
561 for (i = 0; i < ARRAY_LEN(escape_sets); i++) {
562 ast_escape_quoted(escape_sets[i].input, escaped, sizeof(escaped));
563
564 if (strcmp(escaped, escape_sets[i].output)) {
566 "Expected escaped string '%s' instead of '%s'\n",
567 escape_sets[i].output, escaped);
568 return AST_TEST_FAIL;
569 }
570
571 ast_unescape_quoted(escaped);
572 if (strcmp(escaped, escape_sets[i].input)) {
574 "Expected unescaped string '%s' instead of '%s'\n",
575 escape_sets[i].input, escaped);
576 return AST_TEST_FAIL;
577 }
578 }
579
580 return AST_TEST_PASS;
581}
char * output
Definition: test_utils.c:531
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
Definition: utils.c:842
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: utils.c:781

References ARRAY_LEN, ast_escape_quoted(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_unescape_quoted(), sip_to_pjsip::info(), input(), quote_set::output, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [8/12]

AST_TEST_DEFINE ( quote_unescaping  )

Definition at line 583 of file test_utils.c.

584{
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"},
592 };
593 int i;
594
595 switch (cmd) {
596 case TEST_INIT:
597 info->name = "quote_unescaping";
598 info->category = "/main/utils/";
599 info->summary = "Test unescaping of off-nominal strings";
600 info->description =
601 "This tests unescaping of strings which contain a mix of "
602 "escaped and unescaped sequences.";
603 return AST_TEST_NOT_RUN;
604 case TEST_EXECUTE:
605 break;
606 }
607
608 for (i = 0; i < ARRAY_LEN(escape_sets); i++) {
609 RAII_VAR(char *, escaped, ast_strdup(escape_sets[i].input), ast_free);
610
611 ast_unescape_quoted(escaped);
612 if (strcmp(escaped, escape_sets[i].output)) {
614 "Expected unescaped string '%s' instead of '%s'\n",
615 escape_sets[i].output, escaped);
616 return AST_TEST_FAIL;
617 }
618 }
619
620 return AST_TEST_PASS;
621}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241

References ARRAY_LEN, ast_free, ast_strdup, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_unescape_quoted(), sip_to_pjsip::info(), input(), quote_set::output, RAII_VAR, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [9/12]

AST_TEST_DEFINE ( quoted_escape_test  )

Definition at line 129 of file test_utils.c.

130{
131 int res = AST_TEST_PASS;
132 const char *in = "a\"bcdefg\"hijkl\\mnopqrs tuv\twxyz";
133 int i;
134#define LONG_SIZE 256
135#define SHORT_SIZE 4
136
137 static struct {
138 char *buf;
139 const size_t buflen;
140
141 const char *output;
142 } tests[] = {
143 {NULL, LONG_SIZE,
144 "a\\\"bcdefg\\\"hijkl\\\\mnopqrs tuv\twxyz"},
146 "a\\\""},
147 };
148
149 tests[0].buf = ast_alloca(LONG_SIZE);
150 tests[1].buf = ast_alloca(SHORT_SIZE);
151
152 switch (cmd) {
153 case TEST_INIT:
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;
159 case TEST_EXECUTE:
160 break;
161 }
162
163 for (i = 0; i < ARRAY_LEN(tests); i++) {
164 ast_escape_quoted(in, tests[i].buf, tests[i].buflen);
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);
170 res = AST_TEST_FAIL;
171 }
172 }
173
174#undef LONG_SIZE
175#undef SHORT_SIZE
176 return res;
177}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define SHORT_SIZE
#define LONG_SIZE
FILE * in
Definition: utils/frame.c:33

References ARRAY_LEN, ast_alloca, ast_escape_quoted(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, buf, in, sip_to_pjsip::info(), LONG_SIZE, NULL, SHORT_SIZE, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [10/12]

AST_TEST_DEFINE ( safe_mkdir_test  )

Definition at line 406 of file test_utils.c.

407{
408 char base_path[] = "/tmp/safe_mkdir.XXXXXX";
409 char path[80] = {};
410 int res;
411 struct stat actual;
412
413 switch (cmd) {
414 case TEST_INIT:
415 info->name = __func__;
416 info->category = "/main/utils/";
417 info->summary = "Safe mkdir test";
418 info->description =
419 "This test ensures that ast_safe_mkdir does what it is "
420 "supposed to";
421 return AST_TEST_NOT_RUN;
422 case TEST_EXECUTE:
423 break;
424 }
425
426 if (mkdtemp(base_path) == NULL) {
427 ast_test_status_update(test, "Failed to create tmpdir for test\n");
428 return AST_TEST_FAIL;
429 }
430
431 snprintf(path, sizeof(path), "%s/should_work", base_path);
432 res = ast_safe_mkdir(base_path, path, 0777);
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));
437
438 snprintf(path, sizeof(path), "%s/should/also/work", base_path);
439 res = ast_safe_mkdir(base_path, path, 0777);
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));
444
445 snprintf(path, sizeof(path), "%s/even/this/../should/work", base_path);
446 res = ast_safe_mkdir(base_path, path, 0777);
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));
452
453 snprintf(path, sizeof(path),
454 "%s/surprisingly/this/should//////////////////work", base_path);
455 res = ast_safe_mkdir(base_path, path, 0777);
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));
462
463 snprintf(path, sizeof(path), "/should_not_work");
464 res = ast_safe_mkdir(base_path, path, 0777);
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);
470
471 snprintf(path, sizeof(path), "%s/../nor_should_this", base_path);
472 res = ast_safe_mkdir(base_path, path, 0777);
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);
479
480 snprintf(path, sizeof(path),
481 "%s/this/especially/should/not/../../../../../work", base_path);
482 res = ast_safe_mkdir(base_path, path, 0777);
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);
489
490 return AST_TEST_PASS;
491}
char * mkdtemp(char *template_s)
int errno
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.
Definition: utils.c:2584

References ast_safe_mkdir(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, errno, sip_to_pjsip::info(), mkdtemp(), NULL, TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [11/12]

AST_TEST_DEFINE ( sha1_test  )

Definition at line 221 of file test_utils.c.

222{
223 static const struct {
224 const char *input;
225 const char *expected_output;
226 } tests[] = {
227 { "giraffe",
228 "fac8f1a31d2998734d6a5253e49876b8e6a08239" },
229 { "platypus",
230 "1dfb21b7a4d35e90d943e3a16107ccbfabd064d5" },
231 { "ParastratiosphecomyiaStratiosphecomyioides",
232 "58af4e8438676f2bd3c4d8df9e00ee7fe06945bb" },
233 };
235 int i;
236
237 switch (cmd) {
238 case TEST_INIT:
239 info->name = "sha1_test";
240 info->category = "/main/utils/";
241 info->summary = "SHA1 test";
242 info->description =
243 "This test exercises SHA1 calculations."
244 "";
245 return AST_TEST_NOT_RUN;
246 case TEST_EXECUTE:
247 break;
248 }
249
250 ast_test_status_update(test, "Testing SHA1 ...\n");
251
252 for (i = 0; i < ARRAY_LEN(tests); i++) {
253 char sha1_hash[64];
254 ast_sha1_hash(sha1_hash, tests[i].input);
255 if (strcasecmp(sha1_hash, tests[i].expected_output)) {
257 "input: '%s' hash: '%s' expected hash: '%s'\n",
258 tests[i].input, sha1_hash, tests[i].expected_output);
259 res = AST_TEST_FAIL;
260 }
261 }
262
263 return res;
264}
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
Definition: utils.c:266

References ARRAY_LEN, ast_sha1_hash(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, sip_to_pjsip::info(), input(), TEST_EXECUTE, and TEST_INIT.

◆ AST_TEST_DEFINE() [12/12]

AST_TEST_DEFINE ( uri_encode_decode_test  )

Definition at line 48 of file test_utils.c.

49{
50 int res = AST_TEST_PASS;
51 const char *in = "abcdefghijklmnopurstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 ~`!@#$%^&*()_-+={[}]|\\:;\"'<,>.?/";
52 char out[256] = { 0 };
53 char small[4] = { 0 };
54 const struct ast_flags none = {0};
55 int i = 0;
56
57 static struct {
58 const char *spec_str;
59 struct ast_flags spec;
60
61 char *buf;
62 size_t buflen;
63
64 const char *input;
65 const char *output;
66 const char *decoded_output;
67 } tests[5];
68
69#define INIT_ENCODE_TEST(s, buffer, in, out, dec_out) do { \
70 if (i < ARRAY_LEN(tests)) { \
71 tests[i].spec_str = #s; \
72 tests[i].spec = 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; \
78 i++; \
79 } else { \
80 ast_test_status_update(test, "error: 'tests' array too small\n"); \
81 res = AST_TEST_FAIL; \
82 } \
83 } while (0)
84
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);
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);
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");
93
94 switch (cmd) {
95 case TEST_INIT:
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;
101 case TEST_EXECUTE:
102 break;
103 }
104
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);
112 res = AST_TEST_FAIL;
113 continue;
114 }
115
116 ast_uri_decode(tests[i].buf, tests[i].spec);
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);
122 res = AST_TEST_FAIL;
123 }
124 }
125
126 return res;
127}
static struct ast_codec none
Structure used to handle boolean flags.
Definition: utils.h:199
#define INIT_ENCODE_TEST(s, buffer, in, out, dec_out)
FILE * out
Definition: utils/frame.c:33
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
Definition: utils.c:723
const struct ast_flags ast_uri_http
Definition: utils.c:719
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition: utils.c:762
const struct ast_flags ast_uri_sip_user
Definition: utils.c:721
const struct ast_flags ast_uri_http_legacy
Definition: utils.c:720

References ARRAY_LEN, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_uri_decode(), ast_uri_encode(), ast_uri_http, ast_uri_http_legacy, ast_uri_sip_user, buf, in, sip_to_pjsip::info(), INIT_ENCODE_TEST, input(), none, out, TEST_EXECUTE, and TEST_INIT.

◆ handle_noop()

static int handle_noop ( struct ast_channel chan,
AGI agi,
int  arg,
const char *const  argv[] 
)
static

Definition at line 362 of file test_utils.c.

363{
364 ast_agi_send(agi->fd, chan, "200 result=0\n");
365 return RESULT_SUCCESS;
366}
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Sends a string of text to an application connected via AGI.
Definition: res_agi.c:1481
#define RESULT_SUCCESS
Definition: cli.h:40
int fd
Definition: agi.h:35

References ast_agi_send(), agi_state::fd, and RESULT_SUCCESS.

Referenced by AST_TEST_DEFINE().

◆ load_module()

static int load_module ( void  )
static

Definition at line 640 of file test_utils.c.

641{
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);
655}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 623 of file test_utils.c.

624{
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);
637 return 0;
638}
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References AST_TEST_UNREGISTER.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Utils test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "res_agi,res_crypto", }
static

Definition at line 662 of file test_utils.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 662 of file test_utils.c.