Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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 <dlee@digium.com>
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 <dlee@digium.com>
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 */
46static 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 */
59static 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
65AST_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
117AST_TEST_DEFINE(validate_boolean)
118{
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
156AST_TEST_DEFINE(validate_int)
157{
158 RAII_VAR(struct ast_json *, uut, 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
208AST_TEST_DEFINE(validate_long)
209{
210 RAII_VAR(struct ast_json *, uut, 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
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
244AST_TEST_DEFINE(validate_string)
245{
246 RAII_VAR(struct ast_json *, uut, 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
275AST_TEST_DEFINE(validate_date)
276{
277 RAII_VAR(struct ast_json *, uut, 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 */
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]);
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]);
384 }
385 }
386
387 ast_test_validate(test, !ast_ari_validate_string(ast_json_null()));
388
389 return test_res;
390}
391
392AST_TEST_DEFINE(validate_list)
393{
394 RAII_VAR(struct ast_json *, uut, 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,
426 !ast_ari_validate_list(ast_json_null(), wrap_ast_ari_validate_string));
427
428 return AST_TEST_PASS;
429}
430
431static 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
443static 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
455AST_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",
const char * str
Definition: app_jack.c:147
int ast_ari_validate_int(struct ast_json *json)
Validator for native Swagger int.
int ast_ari_validate_long(struct ast_json *json)
Validator for native Swagger long.
int ast_ari_validate_byte(struct ast_json *json)
Validator for native Swagger byte.
int ast_ari_validate_string(struct ast_json *json)
Validator for native Swagger string.
int ast_ari_validate_boolean(struct ast_json *json)
Validator for native Swagger boolean.
int ast_ari_validate_date(struct ast_json *json)
Validator for native Swagger date.
int ast_ari_validate_list(struct ast_json *json, int(*fn)(struct ast_json *))
Validator for a Swagger List[]/JSON array.
Asterisk main include file. File version handling, generic pbx functions.
struct ast_json * ast_json_false(void)
Get the JSON false value.
Definition: json.c:238
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:278
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:378
int ast_json_integer_set(struct ast_json *integer, intmax_t value)
Set the value of a JSON integer.
Definition: json.c:337
struct ast_json * ast_json_integer_create(intmax_t value)
Create a JSON integer.
Definition: json.c:327
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:362
struct ast_json * ast_json_true(void)
Get the JSON true value.
Definition: json.c:233
int ast_json_string_set(struct ast_json *string, const char *value)
Change the value of a JSON string.
Definition: json.c:288
Asterisk module definitions.
@ AST_MODFLAG_DEFAULT
Definition: module.h:315
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
#define NULL
Definition: resample.c:96
Abstract JSON element (object, array, string, int, ...).
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
ast_test_result_state
Definition: test.h:193
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
AST_TEST_DEFINE(validate_byte)
static int load_module(void)
static int unload_module(void)
static enum ast_test_result_state test_res
Utility functions.
#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
#define ARRAY_LEN(a)
Definition: utils.h:666