Asterisk - The Open Source Telephony Project  18.5.0
test_ari_model.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * David M. Lee, II <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief Test the native ARI JSON validators.
22  *
23  * \author David M. Lee, II <[email protected]>
24  */
25 
26 /*** MODULEINFO
27  <depend>TEST_FRAMEWORK</depend>
28  <depend>res_ari_model</depend>
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #include "asterisk/utils.h"
35 #include "asterisk/module.h"
36 #include "asterisk/test.h"
37 #include "../res/ari/ari_model_validators.h"
38 
39 #if defined(TEST_FRAMEWORK)
40 /*!
41  * Wrapper of ast_test_validate_int() so an external function pointer is not used.
42  *
43  * \note We do this because using an external function pointer
44  * did not play nicely when we loaded with RTLD_LAZY.
45  */
46 static int wrap_ast_ari_validate_int(struct ast_json *json)
47 {
48  return ast_ari_validate_int(json);
49 }
50 #endif /* defined(TEST_FRAMEWORK) */
51 
52 #if defined(TEST_FRAMEWORK)
53 /*!
54  * Wrapper of ast_ari_validate_string() so an external function pointer is not used.
55  *
56  * \note We do this because using an external function pointer
57  * did not play nicely when we loaded with RTLD_LAZY.
58  */
59 static int wrap_ast_ari_validate_string(struct ast_json *json)
60 {
61  return ast_ari_validate_string(json);
62 }
63 #endif /* defined(TEST_FRAMEWORK) */
64 
65 AST_TEST_DEFINE(validate_byte)
66 {
67  RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
69  int res;
70 
71  switch (cmd) {
72  case TEST_INIT:
73  info->name = __func__;
74  info->category = "/ari/validators/";
75  info->summary = "Test byte validation";
76  info->description =
77  "Test byte validation";
78  return AST_TEST_NOT_RUN;
79  case TEST_EXECUTE:
80  break;
81  }
82 
83  uut = ast_json_integer_create(-128);
84  ast_test_validate(test, NULL != uut);
85  ast_test_validate(test, ast_ari_validate_byte(uut));
86 
87  res = ast_json_integer_set(uut, 0);
88  ast_test_validate(test, 0 == res);
89  ast_test_validate(test, ast_ari_validate_byte(uut));
90 
91  res = ast_json_integer_set(uut, 255);
92  ast_test_validate(test, 0 == res);
93  ast_test_validate(test, ast_ari_validate_byte(uut));
94 
95  res = ast_json_integer_set(uut, -129);
96  ast_test_validate(test, 0 == res);
97  ast_test_validate(test, !ast_ari_validate_byte(uut));
98 
99  res = ast_json_integer_set(uut, 256);
100  ast_test_validate(test, 0 == res);
101  ast_test_validate(test, !ast_ari_validate_byte(uut));
102 
103  str = ast_json_string_create("not a byte");
104  ast_test_validate(test, NULL != str);
105  ast_test_validate(test, !ast_ari_validate_byte(str));
106 
107  /* Even if the string has an integral value */
108  res = ast_json_string_set(str, "0");
109  ast_test_validate(test, 0 == res);
110  ast_test_validate(test, !ast_ari_validate_byte(str));
111 
112  ast_test_validate(test, !ast_ari_validate_byte(ast_json_null()));
113 
114  return AST_TEST_PASS;
115 }
116 
117 AST_TEST_DEFINE(validate_boolean)
118 {
119  RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
120  int res;
121 
122  switch (cmd) {
123  case TEST_INIT:
124  info->name = __func__;
125  info->category = "/ari/validators/";
126  info->summary = "Test byte validation";
127  info->description =
128  "Test byte validation";
129  return AST_TEST_NOT_RUN;
130  case TEST_EXECUTE:
131  break;
132  }
133 
134  ast_test_validate(test, ast_ari_validate_boolean(ast_json_true()));
135  ast_test_validate(test, ast_ari_validate_boolean(ast_json_false()));
136 
137  str = ast_json_string_create("not a bool");
138  ast_test_validate(test, NULL != str);
139  ast_test_validate(test, !ast_ari_validate_boolean(str));
140 
141  /* Even if the string has a boolean value */
142  res = ast_json_string_set(str, "true");
143  ast_test_validate(test, 0 == res);
144  ast_test_validate(test, !ast_ari_validate_boolean(str));
145 
146  /* Even if the string has a boolean text in it */
147  res = ast_json_string_set(str, "true");
148  ast_test_validate(test, 0 == res);
149  ast_test_validate(test, !ast_ari_validate_boolean(str));
150 
151  ast_test_validate(test, !ast_ari_validate_boolean(ast_json_null()));
152 
153  return AST_TEST_PASS;
154 }
155 
156 AST_TEST_DEFINE(validate_int)
157 {
158  RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
159  RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
160  int res;
161 
162  switch (cmd) {
163  case TEST_INIT:
164  info->name = __func__;
165  info->category = "/ari/validators/";
166  info->summary = "Test int validation";
167  info->description =
168  "Test int validation";
169  return AST_TEST_NOT_RUN;
170  case TEST_EXECUTE:
171  break;
172  }
173 
174  uut = ast_json_integer_create(-2147483648LL);
175  ast_test_validate(test, NULL != uut);
176  ast_test_validate(test, ast_ari_validate_int(uut));
177 
178  res = ast_json_integer_set(uut, 0);
179  ast_test_validate(test, 0 == res);
180  ast_test_validate(test, ast_ari_validate_int(uut));
181 
182  res = ast_json_integer_set(uut, 2147483647LL);
183  ast_test_validate(test, 0 == res);
184  ast_test_validate(test, ast_ari_validate_int(uut));
185 
186  res = ast_json_integer_set(uut, -2147483649LL);
187  ast_test_validate(test, 0 == res);
188  ast_test_validate(test, !ast_ari_validate_int(uut));
189 
190  res = ast_json_integer_set(uut, 2147483648LL);
191  ast_test_validate(test, 0 == res);
192  ast_test_validate(test, !ast_ari_validate_int(uut));
193 
194  str = ast_json_string_create("not a int");
195  ast_test_validate(test, NULL != str);
196  ast_test_validate(test, !ast_ari_validate_int(str));
197 
198  /* Even if the string has an integral value */
199  res = ast_json_string_set(str, "0");
200  ast_test_validate(test, 0 == res);
201  ast_test_validate(test, !ast_ari_validate_int(str));
202 
203  ast_test_validate(test, !ast_ari_validate_int(ast_json_null()));
204 
205  return AST_TEST_PASS;
206 }
207 
208 AST_TEST_DEFINE(validate_long)
209 {
210  RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
211  RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
212  int res;
213 
214  switch (cmd) {
215  case TEST_INIT:
216  info->name = __func__;
217  info->category = "/ari/validators/";
218  info->summary = "Test long validation";
219  info->description =
220  "Test long validation";
221  return AST_TEST_NOT_RUN;
222  case TEST_EXECUTE:
223  break;
224  }
225 
226  uut = ast_json_integer_create(0);
227  ast_test_validate(test, NULL != uut);
228  ast_test_validate(test, ast_ari_validate_long(uut));
229 
230  str = ast_json_string_create("not a long");
231  ast_test_validate(test, NULL != str);
232  ast_test_validate(test, !ast_ari_validate_long(str));
233 
234  /* Even if the string has an integral value */
235  res = ast_json_string_set(str, "0");
236  ast_test_validate(test, 0 == res);
237  ast_test_validate(test, !ast_ari_validate_long(str));
238 
239  ast_test_validate(test, !ast_ari_validate_long(ast_json_null()));
240 
241  return AST_TEST_PASS;
242 }
243 
244 AST_TEST_DEFINE(validate_string)
245 {
246  RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
247  RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
248  int res;
249 
250  switch (cmd) {
251  case TEST_INIT:
252  info->name = __func__;
253  info->category = "/ari/validators/";
254  info->summary = "Test string validation";
255  info->description =
256  "Test string validation";
257  return AST_TEST_NOT_RUN;
258  case TEST_EXECUTE:
259  break;
260  }
261 
262  uut = ast_json_string_create("text");
263  ast_test_validate(test, NULL != uut);
264  ast_test_validate(test, ast_ari_validate_string(uut));
265 
266  res = ast_json_string_set(uut, "");
267  ast_test_validate(test, 0 == res);
268  ast_test_validate(test, ast_ari_validate_string(uut));
269 
270  ast_test_validate(test, !ast_ari_validate_string(ast_json_null()));
271 
272  return AST_TEST_PASS;
273 }
274 
275 AST_TEST_DEFINE(validate_date)
276 {
277  RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
278  RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
280  int res;
281  int i;
282  const char *valid_dates[] = {
283  /* Time is optional */
284  "2013-06-17",
285  /* Seconds are optional */
286  "2013-06-17T23:59Z",
287  /* Subseconds are optional */
288  "2013-06-17T23:59:59Z",
289  /* Leap seconds are valid */
290  "2013-06-30T23:59:61Z",
291  /* Subseconds are allowed */
292  "2013-06-17T23:59:59.999999Z",
293  /* Now with -06:00 for the timezone */
294  "2013-06-17T23:59-06:00",
295  "2013-06-17T23:59:59-06:00",
296  "2013-06-30T23:59:61-06:00",
297  "2013-06-17T23:59:59.999999-06:00",
298  /* Again, with +06:30 for the timezone */
299  "2013-06-17T23:59+06:30",
300  "2013-06-17T23:59:59+06:30",
301  "2013-06-30T23:59:61+06:30",
302  "2013-06-17T23:59:59.999999+06:30",
303  /* So the colon in the timezone is optional */
304  "2013-06-17T23:59-0600",
305  "2013-06-17T23:59:59-0600",
306  "2013-06-30T23:59:61-0600",
307  "2013-06-17T23:59:59.999999-0600",
308  /* Sure, why not */
309  "2013-06-17T23:59+0630",
310  "2013-06-17T23:59:59+0630",
311  "2013-06-30T23:59:61+0630",
312  "2013-06-17T23:59:59.999999+0630",
313  "9999-12-31T23:59:61.999999Z",
314  /* In fact, you don't even have to specify minutes */
315  "2013-06-17T23:59-06",
316  "2013-06-17T23:59:59-06",
317  "2013-06-30T23:59:61-06",
318  "2013-06-17T23:59:59.999999-06",
319  };
320 
321  /* There are lots of invalid dates that the validator lets through.
322  * Those would be strings properly formatted as a ridiculous date. Such
323  * as 0000-00-00, or 9999-19-39. Those are harder to catch with a regex,
324  * and actually aren't as important. So long as the valid dates pass the
325  * validator, and poorly formatted dates are rejected, it's fine.
326  * Catching the occasional ridiculous date is just bonus.
327  */
328  const char *invalid_dates[] = {
329  "",
330  "Not a date",
331  "2013-06-17T", /* Missing time, but has T */
332  "2013-06-17T23:59:59.Z", /* Missing subsecond, but has dot */
333  "2013-06-17T23:59", /* Missing timezone, but has time */
334  "2013-06-17T23:59:59.999999", /* Missing timezone */
335  "9999-99-31T23:59:61.999999Z", /* Invalid month */
336  "9999-12-99T23:59:61.999999Z", /* Invalid day */
337  "9999-12-31T99:59:61.999999Z", /* Invalid hour */
338  "9999-12-31T23:99:61.999999Z", /* Invalid minute */
339  "9999-12-31T23:59:99.999999Z", /* Invalid second */
340  "2013-06-17T23:59:59.999999-99:00", /* Invalid timezone */
341  "2013-06-17T23:59:59.999999-06:99", /* Invalid timezone */
342  "2013-06-17T23:59:59.999999-06:", /* Invalid timezone */
343  "2013-06-17T23:59:59.999999-06:0", /* Invalid timezone */
344  "2013-06-17T23:59:59.999999-060", /* Invalid timezone */
345  };
346 
347  switch (cmd) {
348  case TEST_INIT:
349  info->name = __func__;
350  info->category = "/ari/validators/";
351  info->summary = "Test date validation";
352  info->description =
353  "Test date validation";
354  return AST_TEST_NOT_RUN;
355  case TEST_EXECUTE:
356  break;
357  }
358 
359  uut = ast_json_string_create("");
360  ast_test_validate(test, NULL != uut);
361 
362  /* Instead of using ast_test_validate, we'll collect the results from
363  * several test cases, since we have so many */
364  test_res = AST_TEST_PASS;
365  for (i = 0; i < ARRAY_LEN(valid_dates); ++i) {
366  res = ast_json_string_set(uut, valid_dates[i]);
367  ast_test_validate(test, 0 == res);
368  if (!ast_ari_validate_date(uut)) {
370  "Expected '%s' to be a valid date\n",
371  valid_dates[i]);
372  test_res = AST_TEST_FAIL;
373  }
374  }
375 
376  for (i = 0; i < ARRAY_LEN(invalid_dates); ++i) {
377  res = ast_json_string_set(uut, invalid_dates[i]);
378  ast_test_validate(test, 0 == res);
379  if (ast_ari_validate_date(uut)) {
381  "Expected '%s' to be an invalid date\n",
382  invalid_dates[i]);
383  test_res = AST_TEST_FAIL;
384  }
385  }
386 
387  ast_test_validate(test, !ast_ari_validate_string(ast_json_null()));
388 
389  return test_res;
390 }
391 
392 AST_TEST_DEFINE(validate_list)
393 {
394  RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
395  RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
396  int res;
397 
398  switch (cmd) {
399  case TEST_INIT:
400  info->name = __func__;
401  info->category = "/ari/validators/";
402  info->summary = "Test list validation";
403  info->description =
404  "Test list validation";
405  return AST_TEST_NOT_RUN;
406  case TEST_EXECUTE:
407  break;
408  }
409 
410  uut = ast_json_array_create();
411  ast_test_validate(test, NULL != uut);
412  ast_test_validate(test, ast_ari_validate_list(uut, wrap_ast_ari_validate_string));
413  ast_test_validate(test, ast_ari_validate_list(uut, wrap_ast_ari_validate_int));
414 
416  ast_test_validate(test, 0 == res);
417  ast_test_validate(test, ast_ari_validate_list(uut, wrap_ast_ari_validate_string));
418  ast_test_validate(test, !ast_ari_validate_list(uut, wrap_ast_ari_validate_int));
419 
421  ast_test_validate(test, 0 == res);
422  ast_test_validate(test, !ast_ari_validate_list(uut, wrap_ast_ari_validate_string));
423  ast_test_validate(test, !ast_ari_validate_list(uut, wrap_ast_ari_validate_int));
424 
425  ast_test_validate(test,
427 
428  return AST_TEST_PASS;
429 }
430 
431 static int unload_module(void)
432 {
433  AST_TEST_UNREGISTER(validate_byte);
434  AST_TEST_UNREGISTER(validate_boolean);
435  AST_TEST_UNREGISTER(validate_int);
436  AST_TEST_UNREGISTER(validate_long);
437  AST_TEST_UNREGISTER(validate_string);
438  AST_TEST_UNREGISTER(validate_date);
439  AST_TEST_UNREGISTER(validate_list);
440  return 0;
441 }
442 
443 static int load_module(void)
444 {
445  AST_TEST_REGISTER(validate_byte);
446  AST_TEST_REGISTER(validate_boolean);
447  AST_TEST_REGISTER(validate_int);
448  AST_TEST_REGISTER(validate_long);
449  AST_TEST_REGISTER(validate_string);
450  AST_TEST_REGISTER(validate_date);
451  AST_TEST_REGISTER(validate_list);
453 }
454 
455 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Skeleton (sample) Test",
456  .support_level = AST_MODULE_SUPPORT_CORE,
457  .load = load_module,
458  .unload = unload_module,
459  .requires = "res_ari_model",
460 );
static int wrap_ast_ari_validate_string(struct ast_json *json)
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int unload_module(void)
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
Test Framework API.
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
int ast_ari_validate_boolean(struct ast_json *json)
Validator for native Swagger boolean.
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
Utility functions.
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
int ast_ari_validate_date(struct ast_json *json)
Validator for native Swagger date.
#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
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:352
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:368
int ast_ari_validate_long(struct ast_json *json)
Validator for native Swagger long.
int ast_json_integer_set(struct ast_json *integer, intmax_t value)
Set the value of a JSON integer.
Definition: json.c:327
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
static enum ast_test_result_state test_res
def info(msg)
static int load_module(void)
int ast_ari_validate_int(struct ast_json *json)
Validator for native Swagger int.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
int ast_ari_validate_byte(struct ast_json *json)
Validator for native Swagger byte.
struct ast_json * ast_json_false(void)
Get the JSON false value.
Definition: json.c:238
int ast_ari_validate_string(struct ast_json *json)
Validator for native Swagger string.
Abstract JSON element (object, array, string, int, ...).
int ast_ari_validate_list(struct ast_json *json, int(*fn)(struct ast_json *))
Validator for a Swagger List[]/JSON array.
int ast_json_string_set(struct ast_json *string, const char *value)
Change the value of a JSON string.
Definition: json.c:278
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
AST_TEST_DEFINE(validate_byte)
Asterisk module definitions.
ast_test_result_state
Definition: test.h:200
struct ast_json * ast_json_true(void)
Get the JSON true value.
Definition: json.c:233
static int wrap_ast_ari_validate_int(struct ast_json *json)
struct ast_json * ast_json_integer_create(intmax_t value)
Create a JSON integer.
Definition: json.c:317