Update events to use Swagger 1.3 subtyping, and related aftermath
[asterisk/asterisk.git] / tests / test_ari_model.c
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 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35
36 #include "asterisk/utils.h"
37 #include "asterisk/module.h"
38 #include "asterisk/test.h"
39 #include "../res/stasis_http/ari_model_validators.h"
40
41 AST_TEST_DEFINE(validate_byte)
42 {
43         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
44         RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
45         int res;
46
47         switch (cmd) {
48         case TEST_INIT:
49                 info->name = __func__;
50                 info->category = "/ari/validators/";
51                 info->summary = "Test byte validation";
52                 info->description =
53                         "Test byte validation";
54                 return AST_TEST_NOT_RUN;
55         case TEST_EXECUTE:
56                 break;
57         }
58
59         uut = ast_json_integer_create(-128);
60         ast_test_validate(test, NULL != uut);
61         ast_test_validate(test, ari_validate_byte(uut));
62
63         res = ast_json_integer_set(uut, 0);
64         ast_test_validate(test, 0 == res);
65         ast_test_validate(test, ari_validate_byte(uut));
66
67         res = ast_json_integer_set(uut, 255);
68         ast_test_validate(test, 0 == res);
69         ast_test_validate(test, ari_validate_byte(uut));
70
71         res = ast_json_integer_set(uut, -129);
72         ast_test_validate(test, 0 == res);
73         ast_test_validate(test, !ari_validate_byte(uut));
74
75         res = ast_json_integer_set(uut, 256);
76         ast_test_validate(test, 0 == res);
77         ast_test_validate(test, !ari_validate_byte(uut));
78
79         str = ast_json_string_create("not a byte");
80         ast_test_validate(test, NULL != str);
81         ast_test_validate(test, !ari_validate_byte(str));
82
83         /* Even if the string has an integral value */
84         res = ast_json_string_set(str, "0");
85         ast_test_validate(test, 0 == res);
86         ast_test_validate(test, !ari_validate_byte(str));
87
88         ast_test_validate(test, !ari_validate_byte(ast_json_null()));
89
90         return AST_TEST_PASS;
91 }
92
93 AST_TEST_DEFINE(validate_boolean)
94 {
95         RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
96         int res;
97
98         switch (cmd) {
99         case TEST_INIT:
100                 info->name = __func__;
101                 info->category = "/ari/validators/";
102                 info->summary = "Test byte validation";
103                 info->description =
104                         "Test byte validation";
105                 return AST_TEST_NOT_RUN;
106         case TEST_EXECUTE:
107                 break;
108         }
109
110         ast_test_validate(test, ari_validate_boolean(ast_json_true()));
111         ast_test_validate(test, ari_validate_boolean(ast_json_false()));
112
113         str = ast_json_string_create("not a bool");
114         ast_test_validate(test, NULL != str);
115         ast_test_validate(test, !ari_validate_boolean(str));
116
117         /* Even if the string has a boolean value */
118         res = ast_json_string_set(str, "true");
119         ast_test_validate(test, 0 == res);
120         ast_test_validate(test, !ari_validate_boolean(str));
121
122         /* Even if the string has a boolean text in it */
123         res = ast_json_string_set(str, "true");
124         ast_test_validate(test, 0 == res);
125         ast_test_validate(test, !ari_validate_boolean(str));
126
127         ast_test_validate(test, !ari_validate_boolean(ast_json_null()));
128
129         return AST_TEST_PASS;
130 }
131
132 AST_TEST_DEFINE(validate_int)
133 {
134         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
135         RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
136         int res;
137
138         switch (cmd) {
139         case TEST_INIT:
140                 info->name = __func__;
141                 info->category = "/ari/validators/";
142                 info->summary = "Test int validation";
143                 info->description =
144                         "Test int validation";
145                 return AST_TEST_NOT_RUN;
146         case TEST_EXECUTE:
147                 break;
148         }
149
150         uut = ast_json_integer_create(-2147483648);
151         ast_test_validate(test, NULL != uut);
152         ast_test_validate(test, ari_validate_int(uut));
153
154         res = ast_json_integer_set(uut, 0);
155         ast_test_validate(test, 0 == res);
156         ast_test_validate(test, ari_validate_int(uut));
157
158         res = ast_json_integer_set(uut, 2147483647);
159         ast_test_validate(test, 0 == res);
160         ast_test_validate(test, ari_validate_int(uut));
161
162         res = ast_json_integer_set(uut, -2147483649LL);
163         ast_test_validate(test, 0 == res);
164         ast_test_validate(test, !ari_validate_int(uut));
165
166         res = ast_json_integer_set(uut, 2147483648LL);
167         ast_test_validate(test, 0 == res);
168         ast_test_validate(test, !ari_validate_int(uut));
169
170         str = ast_json_string_create("not a int");
171         ast_test_validate(test, NULL != str);
172         ast_test_validate(test, !ari_validate_int(str));
173
174         /* Even if the string has an integral value */
175         res = ast_json_string_set(str, "0");
176         ast_test_validate(test, 0 == res);
177         ast_test_validate(test, !ari_validate_int(str));
178
179         ast_test_validate(test, !ari_validate_int(ast_json_null()));
180
181         return AST_TEST_PASS;
182 }
183
184 AST_TEST_DEFINE(validate_long)
185 {
186         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
187         RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
188         int res;
189
190         switch (cmd) {
191         case TEST_INIT:
192                 info->name = __func__;
193                 info->category = "/ari/validators/";
194                 info->summary = "Test long validation";
195                 info->description =
196                         "Test long validation";
197                 return AST_TEST_NOT_RUN;
198         case TEST_EXECUTE:
199                 break;
200         }
201
202         uut = ast_json_integer_create(0);
203         ast_test_validate(test, NULL != uut);
204         ast_test_validate(test, ari_validate_long(uut));
205
206         str = ast_json_string_create("not a long");
207         ast_test_validate(test, NULL != str);
208         ast_test_validate(test, !ari_validate_long(str));
209
210         /* Even if the string has an integral value */
211         res = ast_json_string_set(str, "0");
212         ast_test_validate(test, 0 == res);
213         ast_test_validate(test, !ari_validate_long(str));
214
215         ast_test_validate(test, !ari_validate_long(ast_json_null()));
216
217         return AST_TEST_PASS;
218 }
219
220 AST_TEST_DEFINE(validate_string)
221 {
222         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
223         RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
224         int res;
225
226         switch (cmd) {
227         case TEST_INIT:
228                 info->name = __func__;
229                 info->category = "/ari/validators/";
230                 info->summary = "Test string validation";
231                 info->description =
232                         "Test string validation";
233                 return AST_TEST_NOT_RUN;
234         case TEST_EXECUTE:
235                 break;
236         }
237
238         uut = ast_json_string_create("text");
239         ast_test_validate(test, NULL != uut);
240         ast_test_validate(test, ari_validate_string(uut));
241
242         res = ast_json_string_set(uut, "");
243         ast_test_validate(test, 0 == res);
244         ast_test_validate(test, ari_validate_string(uut));
245
246         ast_test_validate(test, !ari_validate_string(ast_json_null()));
247
248         return AST_TEST_PASS;
249 }
250
251 AST_TEST_DEFINE(validate_date)
252 {
253         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
254         RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
255         enum ast_test_result_state test_res;
256         int res;
257         int i;
258         const char *valid_dates[] = {
259                 /* Time is optional */
260                 "2013-06-17",
261                 /* Seconds are optional */
262                 "2013-06-17T23:59Z",
263                 /* Subseconds are optional */
264                 "2013-06-17T23:59:59Z",
265                 /* Leap seconds are valid */
266                 "2013-06-30T23:59:61Z",
267                 /* Subseconds are allowed */
268                 "2013-06-17T23:59:59.999999Z",
269                 /* Now with -06:00 for the timezone */
270                 "2013-06-17T23:59-06:00",
271                 "2013-06-17T23:59:59-06:00",
272                 "2013-06-30T23:59:61-06:00",
273                 "2013-06-17T23:59:59.999999-06:00",
274                 /* Again, with +06:30 for the timezone */
275                 "2013-06-17T23:59+06:30",
276                 "2013-06-17T23:59:59+06:30",
277                 "2013-06-30T23:59:61+06:30",
278                 "2013-06-17T23:59:59.999999+06:30",
279                 /* So the colon in the timezone is optional */
280                 "2013-06-17T23:59-0600",
281                 "2013-06-17T23:59:59-0600",
282                 "2013-06-30T23:59:61-0600",
283                 "2013-06-17T23:59:59.999999-0600",
284                 /* Sure, why not */
285                 "2013-06-17T23:59+0630",
286                 "2013-06-17T23:59:59+0630",
287                 "2013-06-30T23:59:61+0630",
288                 "2013-06-17T23:59:59.999999+0630",
289                 "9999-12-31T23:59:61.999999Z",
290                 /* In fact, you don't even have to specify minutes */
291                 "2013-06-17T23:59-06",
292                 "2013-06-17T23:59:59-06",
293                 "2013-06-30T23:59:61-06",
294                 "2013-06-17T23:59:59.999999-06",
295         };
296
297         /* There are lots of invalid dates that the validator lets through.
298          * Those would be strings properly formatted as a ridiculous date. Such
299          * as 0000-00-00, or 9999-19-39. Those are harder to catch with a regex,
300          * and actually aren't as important. So long as the valid dates pass the
301          * validator, and poorly formatted dates are rejected, it's fine.
302          * Catching the occasional ridiculous date is just bonus.
303          */
304         const char *invalid_dates[] = {
305                 "",
306                 "Not a date",
307                 "2013-06-17T", /* Missing time, but has T */
308                 "2013-06-17T23:59:59.Z", /* Missing subsecond, but has dot */
309                 "2013-06-17T23:59", /* Missing timezone, but has time */
310                 "2013-06-17T23:59:59.999999", /* Missing timezone */
311                 "9999-99-31T23:59:61.999999Z", /* Invalid month */
312                 "9999-12-99T23:59:61.999999Z", /* Invalid day */
313                 "9999-12-31T99:59:61.999999Z", /* Invalid hour */
314                 "9999-12-31T23:99:61.999999Z", /* Invalid minute */
315                 "9999-12-31T23:59:99.999999Z", /* Invalid second */
316                 "2013-06-17T23:59:59.999999-99:00", /* Invalid timezone */
317                 "2013-06-17T23:59:59.999999-06:99", /* Invalid timezone */
318                 "2013-06-17T23:59:59.999999-06:", /* Invalid timezone */
319                 "2013-06-17T23:59:59.999999-06:0", /* Invalid timezone */
320                 "2013-06-17T23:59:59.999999-060", /* Invalid timezone */
321         };
322
323         switch (cmd) {
324         case TEST_INIT:
325                 info->name = __func__;
326                 info->category = "/ari/validators/";
327                 info->summary = "Test date validation";
328                 info->description =
329                         "Test date validation";
330                 return AST_TEST_NOT_RUN;
331         case TEST_EXECUTE:
332                 break;
333         }
334
335         uut = ast_json_string_create("");
336         ast_test_validate(test, NULL != uut);
337
338         /* Instead of using ast_test_validate, we'll collect the results from
339          * several test cases, since we have so many */
340         test_res = AST_TEST_PASS;
341         for (i = 0; i < ARRAY_LEN(valid_dates); ++i) {
342                 res = ast_json_string_set(uut, valid_dates[i]);
343                 ast_test_validate(test, 0 == res);
344                 if (!ari_validate_date(uut)) {
345                         ast_test_status_update(test,
346                                 "Expected '%s' to be a valid date\n",
347                                 valid_dates[i]);
348                         test_res = AST_TEST_FAIL;
349                 }
350         }
351
352         for (i = 0; i < ARRAY_LEN(invalid_dates); ++i) {
353                 res = ast_json_string_set(uut, invalid_dates[i]);
354                 ast_test_validate(test, 0 == res);
355                 if (ari_validate_date(uut)) {
356                         ast_test_status_update(test,
357                                 "Expected '%s' to be an invalid date\n",
358                                 invalid_dates[i]);
359                         test_res = AST_TEST_FAIL;
360                 }
361         }
362
363         ast_test_validate(test, !ari_validate_string(ast_json_null()));
364
365         return test_res;
366 }
367
368 AST_TEST_DEFINE(validate_list)
369 {
370         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
371         RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
372         int res;
373
374         switch (cmd) {
375         case TEST_INIT:
376                 info->name = __func__;
377                 info->category = "/ari/validators/";
378                 info->summary = "Test list validation";
379                 info->description =
380                         "Test list validation";
381                 return AST_TEST_NOT_RUN;
382         case TEST_EXECUTE:
383                 break;
384         }
385
386         uut = ast_json_array_create();
387         ast_test_validate(test, NULL != uut);
388         ast_test_validate(test, ari_validate_list(uut, ari_validate_string));
389         ast_test_validate(test, ari_validate_list(uut, ari_validate_int));
390
391         res = ast_json_array_append(uut, ast_json_string_create(""));
392         ast_test_validate(test, 0 == res);
393         ast_test_validate(test, ari_validate_list(uut, ari_validate_string));
394         ast_test_validate(test, !ari_validate_list(uut, ari_validate_int));
395
396         res = ast_json_array_append(uut, ast_json_integer_create(0));
397         ast_test_validate(test, 0 == res);
398         ast_test_validate(test, !ari_validate_list(uut, ari_validate_string));
399         ast_test_validate(test, !ari_validate_list(uut, ari_validate_int));
400
401         ast_test_validate(test,
402                 !ari_validate_list(ast_json_null(), ari_validate_string));
403
404         return AST_TEST_PASS;
405 }
406
407 static int unload_module(void)
408 {
409         AST_TEST_UNREGISTER(validate_byte);
410         AST_TEST_UNREGISTER(validate_boolean);
411         AST_TEST_UNREGISTER(validate_int);
412         AST_TEST_UNREGISTER(validate_long);
413         AST_TEST_UNREGISTER(validate_string);
414         AST_TEST_UNREGISTER(validate_date);
415         AST_TEST_UNREGISTER(validate_list);
416         return 0;
417 }
418
419 static int load_module(void)
420 {
421         AST_TEST_REGISTER(validate_byte);
422         AST_TEST_REGISTER(validate_boolean);
423         AST_TEST_REGISTER(validate_int);
424         AST_TEST_REGISTER(validate_long);
425         AST_TEST_REGISTER(validate_string);
426         AST_TEST_REGISTER(validate_date);
427         AST_TEST_REGISTER(validate_list);
428         return AST_MODULE_LOAD_SUCCESS;
429 }
430
431 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Skeleton (sample) Test");