Asterisk - The Open Source Telephony Project  18.5.0
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)
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (uri_encode_decode_test)
 
 AST_TEST_DEFINE (quoted_escape_test)
 
 AST_TEST_DEFINE (md5_test)
 
 AST_TEST_DEFINE (sha1_test)
 
 AST_TEST_DEFINE (base64_test)
 
 AST_TEST_DEFINE (crypto_loaded_test)
 
 AST_TEST_DEFINE (adsi_loaded_test)
 
 AST_TEST_DEFINE (agi_loaded_test)
 
 AST_TEST_DEFINE (safe_mkdir_test)
 
 AST_TEST_DEFINE (crypt_test)
 
 AST_TEST_DEFINE (quote_mutation)
 
 AST_TEST_DEFINE (quote_unescaping)
 
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 
)

Referenced by AST_TEST_DEFINE().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 660 of file test_utils.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 660 of file test_utils.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 660 of file test_utils.c.

◆ AST_TEST_DEFINE() [1/12]

AST_TEST_DEFINE ( uri_encode_decode_test  )

Definition at line 48 of file test_utils.c.

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(), out, TEST_EXECUTE, and TEST_INIT.

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 }
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition: main/utils.c:616
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * ast_uri_encode(const char *string, char *outbuf, int buflen, struct ast_flags spec)
Turn text string to URI-encoded XX version.
Definition: main/utils.c:577
static struct ast_codec none
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1584
FILE * in
Definition: utils/frame.c:33
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define INIT_ENCODE_TEST(s, buffer, in, out, dec_out)
const struct ast_flags ast_uri_http_legacy
Definition: main/utils.c:574
def info(msg)
Structure used to handle boolean flags.
Definition: utils.h:199
FILE * out
Definition: utils/frame.c:33
Definition: test.c:104
const struct ast_flags ast_uri_sip_user
Definition: main/utils.c:575
const struct ast_flags ast_uri_http
Definition: main/utils.c:573

◆ AST_TEST_DEFINE() [2/12]

AST_TEST_DEFINE ( quoted_escape_test  )

Definition at line 129 of file test_utils.c.

References ARRAY_LEN, ast_escape_quoted(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, buf, in, sip_to_pjsip::info(), out, TEST_EXECUTE, and TEST_INIT.

130 {
131  int res = AST_TEST_PASS;
132  const char *in = "a\"bcdefg\"hijkl\\mnopqrs tuv\twxyz";
133  char out[256] = { 0 };
134  char small[4] = { 0 };
135  int i;
136 
137  static struct {
138  char *buf;
139  const size_t buflen;
140 
141  const char *output;
142  } tests[] = {
143  {0, sizeof(out),
144  "a\\\"bcdefg\\\"hijkl\\\\mnopqrs tuv\twxyz"},
145  {0, sizeof(small),
146  "a\\\""},
147  };
148 
149  tests[0].buf = out;
150  tests[1].buf = small;
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  return res;
175 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
FILE * in
Definition: utils/frame.c:33
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
def info(msg)
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: main/utils.c:635
FILE * out
Definition: utils/frame.c:33
Definition: test.c:104

◆ AST_TEST_DEFINE() [3/12]

AST_TEST_DEFINE ( md5_test  )

Definition at line 177 of file test_utils.c.

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.

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

◆ AST_TEST_DEFINE() [4/12]

AST_TEST_DEFINE ( sha1_test  )

Definition at line 219 of file test_utils.c.

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.

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

◆ AST_TEST_DEFINE() [5/12]

AST_TEST_DEFINE ( base64_test  )

Definition at line 264 of file test_utils.c.

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().

265 {
266  static const struct {
267  const char *input;
268  const char *decoded;
269  } tests[] = {
270  { "giraffe",
271  "Z2lyYWZmZQ==" },
272  { "platypus",
273  "cGxhdHlwdXM=" },
274  { "ParastratiosphecomyiaStratiosphecomyioides",
275  "UGFyYXN0cmF0aW9zcGhlY29teWlhU3RyYXRpb3NwaGVjb215aW9pZGVz" },
276  };
277  int i;
279 
280  switch (cmd) {
281  case TEST_INIT:
282  info->name = "base64_test";
283  info->category = "/main/utils/";
284  info->summary = "base64 test";
285  info->description = "This test exercises the base64 conversions.";
286  return AST_TEST_NOT_RUN;
287  case TEST_EXECUTE:
288  break;
289  }
290 
291 
292  for (i = 0; i < ARRAY_LEN(tests); i++) {
293  char tmp[64];
294  ast_base64encode(tmp, (unsigned char *)tests[i].input, strlen(tests[i].input), sizeof(tmp));
295  if (strcasecmp(tmp, tests[i].decoded)) {
297  "input: '%s' base64 output: '%s' expected base64 output: '%s'\n",
298  tests[i].input, tmp, tests[i].decoded);
299  res = AST_TEST_FAIL;
300  }
301 
302  memset(tmp, 0, sizeof(tmp));
303  ast_base64decode((unsigned char *) tmp, tests[i].decoded, (sizeof(tmp) - 1));
304  if (strcasecmp(tmp, tests[i].input)) {
306  "base64 input: '%s' output: '%s' expected output: '%s'\n",
307  tests[i].decoded, tmp, tests[i].input);
308  res = AST_TEST_FAIL;
309  }
310  }
311 
312  return res;
313 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int tmp()
Definition: bt_open.c:389
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1584
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
Definition: main/utils.c:294
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition: main/utils.c:404
def info(msg)
Definition: test.c:104
ast_test_result_state
Definition: test.h:200

◆ AST_TEST_DEFINE() [6/12]

AST_TEST_DEFINE ( crypto_loaded_test  )

Definition at line 315 of file test_utils.c.

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

316 {
317  switch (cmd) {
318  case TEST_INIT:
319  info->name = "crypto_loaded_test";
320  info->category = "/res/crypto/";
321  info->summary = "Crypto loaded into memory";
322  info->description = "Verifies whether the crypto functions overrode the stubs";
323  return AST_TEST_NOT_RUN;
324  case TEST_EXECUTE:
325  break;
326  }
327 
329 }
int AST_OPTIONAL_API_NAME() ast_crypto_loaded(void)
Definition: res_crypto.c:461
def info(msg)

◆ AST_TEST_DEFINE() [7/12]

AST_TEST_DEFINE ( adsi_loaded_test  )

Definition at line 331 of file test_utils.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.

332 {
333  struct ast_channel *c;
334  int res;
335  switch (cmd) {
336  case TEST_INIT:
337  info->name = "adsi_loaded_test";
338  info->category = "/res/adsi/";
339  info->summary = "ADSI loaded into memory";
340  info->description = "Verifies whether the adsi functions overrode the stubs";
341  return AST_TEST_NOT_RUN;
342  case TEST_EXECUTE:
343  break;
344  }
345 
346  if (!ast_module_check("res_adsi.so")) {
347  ast_test_status_update(test, "This test skipped because deprecated module res_adsi.so is not built by default.\n");
348  return AST_TEST_PASS;
349  }
350 
351  if (!(c = ast_dummy_channel_alloc())) {
352  return AST_TEST_FAIL;
353  }
356  c = ast_channel_unref(c);
357  return res;
358 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
static struct test_val c
int ast_module_check(const char *name)
Check if module with the name given is loaded.
Definition: loader.c:2653
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
def info(msg)
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition: adsi.c:263

◆ AST_TEST_DEFINE() [8/12]

AST_TEST_DEFINE ( agi_loaded_test  )

Definition at line 366 of file test_utils.c.

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.

367 {
368  int res = AST_TEST_PASS;
369  struct agi_command noop_command =
370  { { "testnoop", NULL }, handle_noop, NULL, NULL, 0 };
371 
372  switch (cmd) {
373  case TEST_INIT:
374  info->name = "agi_loaded_test";
375  info->category = "/res/agi/";
376  info->summary = "AGI loaded into memory";
377  info->description = "Verifies whether the agi functions overrode the stubs";
378  return AST_TEST_NOT_RUN;
379  case TEST_EXECUTE:
380  break;
381  }
382 
384  ast_test_status_update(test, "Unable to register testnoop command, because res_agi is not loaded.\n");
385  return AST_TEST_FAIL;
386  }
387 
388 #ifndef HAVE_NULLSAFE_PRINTF
389  /* Test for condition without actually crashing Asterisk */
390  if (noop_command.usage == NULL) {
391  ast_test_status_update(test, "AGI testnoop usage was not updated properly.\n");
392  res = AST_TEST_FAIL;
393  }
394  if (noop_command.syntax == NULL) {
395  ast_test_status_update(test, "AGI testnoop syntax was not updated properly.\n");
396  res = AST_TEST_FAIL;
397  }
398 #endif
399 
400  ast_agi_unregister(&noop_command);
401  return res;
402 }
int AST_OPTIONAL_API_NAME() ast_agi_unregister(agi_command *cmd)
Definition: res_agi.c:3827
const char *const usage
Definition: agi.h:50
#define NULL
Definition: resample.c:96
struct ast_module * self
Definition: module.h:342
int AST_OPTIONAL_API_NAME() ast_agi_register(struct ast_module *mod, agi_command *cmd)
Definition: res_agi.c:3783
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_OPTIONAL_API_UNAVAILABLE
A common value for optional API stub functions to return.
Definition: optional_api.h:74
const char *const syntax
Definition: agi.h:54
def info(msg)
static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, const char *const argv[])
Definition: test_utils.c:360

◆ AST_TEST_DEFINE() [9/12]

AST_TEST_DEFINE ( safe_mkdir_test  )

Definition at line 404 of file test_utils.c.

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.

405 {
406  char base_path[] = "/tmp/safe_mkdir.XXXXXX";
407  char path[80] = {};
408  int res;
409  struct stat actual;
410 
411  switch (cmd) {
412  case TEST_INIT:
413  info->name = __func__;
414  info->category = "/main/utils/";
415  info->summary = "Safe mkdir test";
416  info->description =
417  "This test ensures that ast_safe_mkdir does what it is "
418  "supposed to";
419  return AST_TEST_NOT_RUN;
420  case TEST_EXECUTE:
421  break;
422  }
423 
424  if (mkdtemp(base_path) == NULL) {
425  ast_test_status_update(test, "Failed to create tmpdir for test\n");
426  return AST_TEST_FAIL;
427  }
428 
429  snprintf(path, sizeof(path), "%s/should_work", base_path);
430  res = ast_safe_mkdir(base_path, path, 0777);
431  ast_test_validate(test, 0 == res);
432  res = stat(path, &actual);
433  ast_test_validate(test, 0 == res);
434  ast_test_validate(test, S_ISDIR(actual.st_mode));
435 
436  snprintf(path, sizeof(path), "%s/should/also/work", base_path);
437  res = ast_safe_mkdir(base_path, path, 0777);
438  ast_test_validate(test, 0 == res);
439  res = stat(path, &actual);
440  ast_test_validate(test, 0 == res);
441  ast_test_validate(test, S_ISDIR(actual.st_mode));
442 
443  snprintf(path, sizeof(path), "%s/even/this/../should/work", base_path);
444  res = ast_safe_mkdir(base_path, path, 0777);
445  ast_test_validate(test, 0 == res);
446  snprintf(path, sizeof(path), "%s/even/should/work", base_path);
447  res = stat(path, &actual);
448  ast_test_validate(test, 0 == res);
449  ast_test_validate(test, S_ISDIR(actual.st_mode));
450 
451  snprintf(path, sizeof(path),
452  "%s/surprisingly/this/should//////////////////work", base_path);
453  res = ast_safe_mkdir(base_path, path, 0777);
454  ast_test_validate(test, 0 == res);
455  snprintf(path, sizeof(path),
456  "%s/surprisingly/this/should/work", base_path);
457  res = stat(path, &actual);
458  ast_test_validate(test, 0 == res);
459  ast_test_validate(test, S_ISDIR(actual.st_mode));
460 
461  snprintf(path, sizeof(path), "/should_not_work");
462  res = ast_safe_mkdir(base_path, path, 0777);
463  ast_test_validate(test, 0 != res);
464  ast_test_validate(test, EPERM == errno);
465  res = stat(path, &actual);
466  ast_test_validate(test, 0 != res);
467  ast_test_validate(test, ENOENT == errno);
468 
469  snprintf(path, sizeof(path), "%s/../nor_should_this", base_path);
470  res = ast_safe_mkdir(base_path, path, 0777);
471  ast_test_validate(test, 0 != res);
472  ast_test_validate(test, EPERM == errno);
473  strncpy(path, "/tmp/nor_should_this", sizeof(path));
474  res = stat(path, &actual);
475  ast_test_validate(test, 0 != res);
476  ast_test_validate(test, ENOENT == errno);
477 
478  snprintf(path, sizeof(path),
479  "%s/this/especially/should/not/../../../../../work", base_path);
480  res = ast_safe_mkdir(base_path, path, 0777);
481  ast_test_validate(test, 0 != res);
482  ast_test_validate(test, EPERM == errno);
483  strncpy(path, "/tmp/work", sizeof(path));
484  res = stat(path, &actual);
485  ast_test_validate(test, 0 != res);
486  ast_test_validate(test, ENOENT == errno);
487 
488  return AST_TEST_PASS;
489 }
#define NULL
Definition: resample.c:96
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
char * mkdtemp(char *template_s)
def info(msg)
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: main/utils.c:2336

◆ AST_TEST_DEFINE() [10/12]

AST_TEST_DEFINE ( crypt_test  )

Definition at line 491 of file test_utils.c.

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

492 {
493  RAII_VAR(char *, password_crypted, NULL, ast_free);
494  RAII_VAR(char *, blank_crypted, NULL, ast_free);
495  const char *password = "Passw0rd";
496  const char *not_a_password = "not-a-password";
497 
498  switch (cmd) {
499  case TEST_INIT:
500  info->name = "crypt_test";
501  info->category = "/main/utils/";
502  info->summary = "Test ast_crypt wrappers";
503  info->description = "Verifies that the ast_crypt wrappers work as expected.";
504  return AST_TEST_NOT_RUN;
505  case TEST_EXECUTE:
506  break;
507  }
508 
509  password_crypted = ast_crypt_encrypt(password);
510  ast_test_validate(test, NULL != password_crypted);
511  ast_test_validate(test, 0 != strcmp(password, password_crypted));
512  ast_test_validate(test, ast_crypt_validate(password, password_crypted));
513  ast_test_validate(test,
514  !ast_crypt_validate(not_a_password, password_crypted));
515 
516  blank_crypted = ast_crypt_encrypt("");
517  ast_test_validate(test, NULL != blank_crypted);
518  ast_test_validate(test, 0 != strcmp(blank_crypted, ""));
519  ast_test_validate(test, ast_crypt_validate("", blank_crypted));
520  ast_test_validate(test,
521  !ast_crypt_validate(not_a_password, blank_crypted));
522 
523  return AST_TEST_PASS;
524 }
#define NULL
Definition: resample.c:96
static struct ast_str * password
Definition: cdr_mysql.c:77
#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:911
def info(msg)
#define ast_free(a)
Definition: astmm.h:182
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

◆ AST_TEST_DEFINE() [11/12]

AST_TEST_DEFINE ( quote_mutation  )

Definition at line 532 of file test_utils.c.

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.

533 {
534  char escaped[64];
535  static const struct quote_set escape_sets[] = {
536  {"\"string\"", "\\\"string\\\""},
537  {"\"string", "\\\"string"},
538  {"string\"", "string\\\""},
539  {"string", "string"},
540  {"str\"ing", "str\\\"ing"},
541  {"\"", "\\\""},
542  {"\\\"", "\\\\\\\""},
543  };
544  int i;
545 
546  switch (cmd) {
547  case TEST_INIT:
548  info->name = "quote_mutation";
549  info->category = "/main/utils/";
550  info->summary = "Test mutation of quotes in strings";
551  info->description =
552  "This tests escaping and unescaping of quotes in strings to "
553  "verify that the original string is recovered.";
554  return AST_TEST_NOT_RUN;
555  case TEST_EXECUTE:
556  break;
557  }
558 
559  for (i = 0; i < ARRAY_LEN(escape_sets); i++) {
560  ast_escape_quoted(escape_sets[i].input, escaped, sizeof(escaped));
561 
562  if (strcmp(escaped, escape_sets[i].output)) {
564  "Expected escaped string '%s' instead of '%s'\n",
565  escape_sets[i].output, escaped);
566  return AST_TEST_FAIL;
567  }
568 
569  ast_unescape_quoted(escaped);
570  if (strcmp(escaped, escape_sets[i].input)) {
572  "Expected unescaped string '%s' instead of '%s'\n",
573  escape_sets[i].input, escaped);
574  return AST_TEST_FAIL;
575  }
576  }
577 
578  return AST_TEST_PASS;
579 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * output
Definition: test_utils.c:529
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1584
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
Definition: main/utils.c:696
def info(msg)
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: main/utils.c:635

◆ AST_TEST_DEFINE() [12/12]

AST_TEST_DEFINE ( quote_unescaping  )

Definition at line 581 of file test_utils.c.

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.

582 {
583  static const struct quote_set escape_sets[] = {
584  {"\"string\"", "\"string\""},
585  {"\\\"string\"", "\"string\""},
586  {"\"string\\\"", "\"string\""},
587  {"str\\ing", "string"},
588  {"string\\", "string"},
589  {"\\string", "string"},
590  };
591  int i;
592 
593  switch (cmd) {
594  case TEST_INIT:
595  info->name = "quote_unescaping";
596  info->category = "/main/utils/";
597  info->summary = "Test unescaping of off-nominal strings";
598  info->description =
599  "This tests unescaping of strings which contain a mix of "
600  "escaped and unescaped sequences.";
601  return AST_TEST_NOT_RUN;
602  case TEST_EXECUTE:
603  break;
604  }
605 
606  for (i = 0; i < ARRAY_LEN(escape_sets); i++) {
607  RAII_VAR(char *, escaped, ast_strdup(escape_sets[i].input), ast_free);
608 
609  ast_unescape_quoted(escaped);
610  if (strcmp(escaped, escape_sets[i].output)) {
612  "Expected unescaped string '%s' instead of '%s'\n",
613  escape_sets[i].output, escaped);
614  return AST_TEST_FAIL;
615  }
616  }
617 
618  return AST_TEST_PASS;
619 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * output
Definition: test_utils.c:529
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1584
#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:911
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
void ast_unescape_quoted(char *quote_str)
Unescape quotes in a string.
Definition: main/utils.c:696
def info(msg)
#define ast_free(a)
Definition: astmm.h:182

◆ handle_noop()

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

Definition at line 360 of file test_utils.c.

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

Referenced by AST_TEST_DEFINE().

361 {
362  ast_agi_send(agi->fd, chan, "200 result=0\n");
363  return RESULT_SUCCESS;
364 }
int fd
Definition: agi.h:35
int AST_OPTIONAL_API_NAME() ast_agi_send(int fd, struct ast_channel *chan, char *fmt,...)
Definition: res_agi.c:1486
#define RESULT_SUCCESS
Definition: cli.h:40

◆ load_module()

static int load_module ( void  )
static

Definition at line 638 of file test_utils.c.

References AST_MODFLAG_DEFAULT, AST_MODULE_INFO(), AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_CORE, AST_TEST_REGISTER, ASTERISK_GPL_KEY, and unload_module().

639 {
640  AST_TEST_REGISTER(uri_encode_decode_test);
641  AST_TEST_REGISTER(quoted_escape_test);
642  AST_TEST_REGISTER(md5_test);
643  AST_TEST_REGISTER(sha1_test);
644  AST_TEST_REGISTER(base64_test);
645  AST_TEST_REGISTER(crypto_loaded_test);
646  AST_TEST_REGISTER(adsi_loaded_test);
647  AST_TEST_REGISTER(agi_loaded_test);
648  AST_TEST_REGISTER(safe_mkdir_test);
649  AST_TEST_REGISTER(crypt_test);
650  AST_TEST_REGISTER(quote_mutation);
651  AST_TEST_REGISTER(quote_unescaping);
653 }
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 621 of file test_utils.c.

References AST_TEST_UNREGISTER.

Referenced by load_module().

622 {
623  AST_TEST_UNREGISTER(uri_encode_decode_test);
624  AST_TEST_UNREGISTER(quoted_escape_test);
625  AST_TEST_UNREGISTER(md5_test);
626  AST_TEST_UNREGISTER(sha1_test);
627  AST_TEST_UNREGISTER(base64_test);
628  AST_TEST_UNREGISTER(crypto_loaded_test);
629  AST_TEST_UNREGISTER(adsi_loaded_test);
630  AST_TEST_UNREGISTER(agi_loaded_test);
631  AST_TEST_UNREGISTER(safe_mkdir_test);
632  AST_TEST_UNREGISTER(crypt_test);
633  AST_TEST_UNREGISTER(quote_mutation);
634  AST_TEST_UNREGISTER(quote_unescaping);
635  return 0;
636 }
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

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 660 of file test_utils.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 660 of file test_utils.c.