Merged revisions 378915,378918 via svnmerge from
[asterisk/asterisk.git] / tests / test_json.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012 - 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 \brief Test JSON API.
21  *
22  * While some of these tests are actually testing our JSON library wrapper, the bulk of
23  * them are exploratory tests to determine what the behavior of the underlying JSON
24  * library is. This also gives us a good indicator if that behavior changes between
25  * Jansson revisions.
26  *
27  * \author\verbatim David M. Lee, II <dlee@digium.com> \endverbatim
28  *
29  * \ingroup tests
30  */
31
32 /*** MODULEINFO
33         <depend>TEST_FRAMEWORK</depend>
34         <depend>res_json</depend>
35         <support_level>core</support_level>
36  ***/
37
38 #include "asterisk.h"
39
40 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
41 #include "asterisk/json.h"
42 #include "asterisk/module.h"
43 #include "asterisk/test.h"
44
45 /*!
46  * Number of allocations from JSON library that have not yet been freed.
47  */
48 static size_t alloc_count;
49
50 /*!@{*/
51 /*!
52  * JSON library has its own reference counting, so we'll provide our own allocators to
53  * test that everything gets freed as expected.
54  */
55 static void *json_debug_malloc(size_t size)
56 {
57         void *p = ast_malloc(size);
58         if (p) {
59                 ++alloc_count;
60         }
61         return p;
62 }
63
64 static void json_debug_free(void *p)
65 {
66         if (p) {
67                 --alloc_count;
68         }
69         ast_free(p);
70 }
71
72 static void *json_test_init(struct ast_test *test)
73 {
74         ast_json_set_alloc_funcs(json_debug_malloc, json_debug_free);
75         alloc_count = 0;
76         return test;
77 }
78
79 static void json_test_finish(void *test)
80 {
81         struct ast_test *t = test;
82         ast_json_reset_alloc_funcs();
83         if (0 != alloc_count) {
84                 ast_test_status_update(t, "JSON test leaked %zd allocations!", alloc_count);
85         }
86 }
87
88 /*!@}*/
89
90 AST_TEST_DEFINE(json_test_false)
91 {
92         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
93         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
94
95         switch (cmd) {
96         case TEST_INIT:
97                 info->name = "false";
98                 info->category = "/main/json/";
99                 info->summary = "Testing fundamental JSON false value.";
100                 info->description = "Test JSON abstraction library.";
101                 return AST_TEST_NOT_RUN;
102         case TEST_EXECUTE:
103                 break;
104         }
105
106         uut = ast_json_false();
107         ast_test_validate(test, NULL != uut);
108         ast_test_validate(test, AST_JSON_FALSE == ast_json_typeof(uut));
109         ast_test_validate(test, !ast_json_is_null(uut));
110         ast_test_validate(test, !ast_json_is_true(uut));
111         ast_test_validate(test, ast_json_is_false(uut));
112
113         return AST_TEST_PASS;
114 }
115
116 AST_TEST_DEFINE(json_test_true)
117 {
118         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
119         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
120
121         switch (cmd) {
122         case TEST_INIT:
123                 info->name = "true";
124                 info->category = "/main/json/";
125                 info->summary = "Testing JSON true value.";
126                 info->description = "Test JSON abstraction library.";
127                 return AST_TEST_NOT_RUN;
128         case TEST_EXECUTE:
129                 break;
130         }
131
132         uut = ast_json_true();
133         ast_test_validate(test, NULL != uut);
134         ast_test_validate(test, AST_JSON_TRUE == ast_json_typeof(uut));
135         ast_test_validate(test, !ast_json_is_null(uut));
136         ast_test_validate(test, ast_json_is_true(uut));
137         ast_test_validate(test, !ast_json_is_false(uut));
138
139         return AST_TEST_PASS;
140 }
141
142 AST_TEST_DEFINE(json_test_bool0)
143 {
144         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
145         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
146
147         switch (cmd) {
148         case TEST_INIT:
149                 info->name = "bool0";
150                 info->category = "/main/json/";
151                 info->summary = "Testing JSON boolean function (false).";
152                 info->description = "Test JSON abstraction library.";
153                 return AST_TEST_NOT_RUN;
154         case TEST_EXECUTE:
155                 break;
156         }
157
158         uut = ast_json_boolean(0);
159         ast_test_validate(test, NULL != uut);
160         ast_test_validate(test, AST_JSON_FALSE == ast_json_typeof(uut));
161         ast_test_validate(test, !ast_json_is_null(uut));
162         ast_test_validate(test, !ast_json_is_true(uut));
163         ast_test_validate(test, ast_json_is_false(uut));
164         ast_test_validate(test, ast_json_equal(uut, ast_json_false()));
165         ast_test_validate(test, !ast_json_equal(uut, ast_json_true()));
166
167         return AST_TEST_PASS;
168 }
169
170 AST_TEST_DEFINE(json_test_bool1)
171 {
172         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
173         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
174
175         switch (cmd) {
176         case TEST_INIT:
177                 info->name = "bool1";
178                 info->category = "/main/json/";
179                 info->summary = "Testing JSON boolean function (true).";
180                 info->description = "Test JSON abstraction library.";
181                 return AST_TEST_NOT_RUN;
182         case TEST_EXECUTE:
183                 break;
184         }
185
186         uut = ast_json_boolean(1);
187         ast_test_validate(test, NULL != uut);
188         ast_test_validate(test, AST_JSON_TRUE == ast_json_typeof(uut));
189         ast_test_validate(test, !ast_json_is_null(uut));
190         ast_test_validate(test, ast_json_is_true(uut));
191         ast_test_validate(test, !ast_json_is_false(uut));
192         ast_test_validate(test, !ast_json_equal(uut, ast_json_false()));
193         ast_test_validate(test, ast_json_equal(uut, ast_json_true()));
194
195         return AST_TEST_PASS;
196 }
197
198 AST_TEST_DEFINE(json_test_null)
199 {
200         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
201         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
202
203         switch (cmd) {
204         case TEST_INIT:
205                 info->name = "null";
206                 info->category = "/main/json/";
207                 info->summary = "Testing JSON null value.";
208                 info->description = "Test JSON abstraction library.";
209                 return AST_TEST_NOT_RUN;
210         case TEST_EXECUTE:
211                 break;
212         }
213
214         uut = ast_json_null();
215         ast_test_validate(test, NULL != uut);
216         ast_test_validate(test, AST_JSON_NULL == ast_json_typeof(uut));
217         ast_test_validate(test, ast_json_is_null(uut));
218         ast_test_validate(test, !ast_json_is_true(uut));
219         ast_test_validate(test, !ast_json_is_false(uut));
220
221         return AST_TEST_PASS;
222 }
223
224 AST_TEST_DEFINE(json_test_null_val)
225 {
226         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
227         switch (cmd) {
228         case TEST_INIT:
229                 info->name = "null_val";
230                 info->category = "/main/json/";
231                 info->summary = "Testing JSON handling of NULL.";
232                 info->description = "Test JSON abstraction library.";
233                 return AST_TEST_NOT_RUN;
234         case TEST_EXECUTE:
235                 break;
236         }
237
238         /* NULL isn't null, true or false */
239         ast_test_validate(test, !ast_json_is_null(NULL));
240         ast_test_validate(test, !ast_json_is_false(NULL));
241         ast_test_validate(test, !ast_json_is_true(NULL));
242
243         /* ref and unref should be NULL safe */
244         ast_json_ref(NULL);
245         ast_json_unref(NULL);
246         /* no segfault; we're good. le sigh. */
247
248         return AST_TEST_PASS;
249 }
250
251 AST_TEST_DEFINE(json_test_string)
252 {
253         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
254         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
255         int uut_res;
256
257         switch (cmd) {
258         case TEST_INIT:
259                 info->name = "string";
260                 info->category = "/main/json/";
261                 info->summary = "Basic string tests.";
262                 info->description = "Test JSON abstraction library.";
263                 return AST_TEST_NOT_RUN;
264         case TEST_EXECUTE:
265                 break;
266         }
267
268         uut = ast_json_string_create("Hello, json");
269         ast_test_validate(test, NULL != uut);
270         ast_test_validate(test, AST_JSON_STRING == ast_json_typeof(uut));
271         ast_test_validate(test, 0 == strcmp("Hello, json", ast_json_string_get(uut)));
272
273         uut_res = ast_json_string_set(uut, NULL);
274         ast_test_validate(test, -1 == uut_res);
275         ast_test_validate(test, 0 == strcmp("Hello, json", ast_json_string_get(uut)));
276
277         uut_res = ast_json_string_set(uut, "Not UTF-8 - \xff");
278         ast_test_validate(test, -1 == uut_res);
279         ast_test_validate(test, 0 == strcmp("Hello, json", ast_json_string_get(uut)));
280
281         uut_res = ast_json_string_set(uut, "Is UTF-8 - \xE2\x98\xBA");
282         ast_test_validate(test, 0 == uut_res);
283         ast_test_validate(test, 0 == strcmp("Is UTF-8 - \xE2\x98\xBA", ast_json_string_get(uut)));
284
285         uut_res = ast_json_string_set(uut, "Goodbye, json");
286         ast_test_validate(test, 0 == uut_res);
287         ast_test_validate(test, 0 == strcmp("Goodbye, json", ast_json_string_get(uut)));
288
289         return AST_TEST_PASS;
290 }
291
292 AST_TEST_DEFINE(json_test_string_null)
293 {
294         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
295         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
296
297         switch (cmd) {
298         case TEST_INIT:
299                 info->name = "string_null";
300                 info->category = "/main/json/";
301                 info->summary = "JSON string NULL tests.";
302                 info->description = "Test JSON abstraction library.";
303                 return AST_TEST_NOT_RUN;
304         case TEST_EXECUTE:
305                 break;
306         }
307
308         /* NULL string */
309         uut = ast_json_string_create(NULL);
310         ast_test_validate(test, NULL == uut);
311
312         /* NULL JSON strings */
313         ast_test_validate(test, NULL == ast_json_string_create(NULL));
314         ast_test_validate(test, NULL == ast_json_string_get(NULL));
315         ast_test_validate(test, -1 == ast_json_string_set(NULL, "not null"));
316
317         /* string_value from non-string elements should return NULL */
318         ast_test_validate(test, NULL == ast_json_string_get(ast_json_null()));
319         ast_test_validate(test, NULL == ast_json_string_get(ast_json_false()));
320         ast_test_validate(test, NULL == ast_json_string_get(ast_json_true()));
321
322         return AST_TEST_PASS;
323 }
324
325 AST_TEST_DEFINE(json_test_stringf)
326 {
327         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
328         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
329         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
330
331         switch (cmd) {
332         case TEST_INIT:
333                 info->name = "stringf";
334                 info->category = "/main/json/";
335                 info->summary = "Basic string formatting tests.";
336                 info->description = "Test JSON abstraction library.";
337                 return AST_TEST_NOT_RUN;
338         case TEST_EXECUTE:
339                 break;
340         }
341
342         /* NULL format string */
343         uut = ast_json_stringf(NULL);
344         ast_test_validate(test, NULL == uut);
345
346         /* Non-UTF-8 strings are invalid */
347         uut = ast_json_stringf("Not UTF-8 - %s", "\xff");
348         ast_test_validate(test, NULL == uut);
349
350         /* formatted string */
351         uut = ast_json_stringf("Hello, %s", "json");
352         expected = ast_json_string_create("Hello, json");
353         ast_test_validate(test, NULL != uut);
354         ast_test_validate(test, ast_json_equal(expected, uut));
355
356         return AST_TEST_PASS;
357 }
358
359 AST_TEST_DEFINE(json_test_int)
360 {
361         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
362         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
363         int uut_res;
364
365         switch (cmd) {
366         case TEST_INIT:
367                 info->name = "int";
368                 info->category = "/main/json/";
369                 info->summary = "Basic JSON integer tests.";
370                 info->description = "Test JSON abstraction library.";
371                 return AST_TEST_NOT_RUN;
372         case TEST_EXECUTE:
373                 break;
374         }
375
376         /* Integer tests */
377         uut = ast_json_integer_create(0);
378         ast_test_validate(test, NULL != uut);
379         ast_test_validate(test, AST_JSON_INTEGER == ast_json_typeof(uut));
380         ast_test_validate(test, 0 == ast_json_integer_get(uut));
381
382         uut_res = ast_json_integer_set(uut, 1);
383         ast_test_validate(test, 0 == uut_res);
384         ast_test_validate(test, 1 == ast_json_integer_get(uut));
385
386         uut_res = ast_json_integer_set(uut, -1);
387         ast_test_validate(test, 0 == uut_res);
388         ast_test_validate(test, -1 == ast_json_integer_get(uut));
389
390         uut_res = ast_json_integer_set(uut, LLONG_MAX);
391         ast_test_validate(test, 0 == uut_res);
392         ast_test_validate(test, LLONG_MAX == ast_json_integer_get(uut));
393
394         uut_res = ast_json_integer_set(uut, LLONG_MIN);
395         ast_test_validate(test, 0 == uut_res);
396         ast_test_validate(test, LLONG_MIN == ast_json_integer_get(uut));
397
398         ast_json_unref(uut);
399
400         return AST_TEST_PASS;
401 }
402
403 AST_TEST_DEFINE(json_test_non_int)
404 {
405         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
406         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
407
408         switch (cmd) {
409         case TEST_INIT:
410                 info->name = "non_int";
411                 info->category = "/main/json/";
412                 info->summary = "Testing integer functions with non-integer types.";
413                 info->description = "Test JSON abstraction library.";
414                 return AST_TEST_NOT_RUN;
415         case TEST_EXECUTE:
416                 break;
417         }
418
419         /* Non-ints return 0 integer value */
420         ast_test_validate(test, 0 == ast_json_integer_get(ast_json_null()));
421         ast_test_validate(test, 0 == ast_json_integer_get(ast_json_true()));
422         ast_test_validate(test, 0 == ast_json_integer_get(ast_json_false()));
423
424         /* JSON NULL integers */
425         ast_test_validate(test, 0 == ast_json_integer_get(NULL));
426         ast_test_validate(test, -1 == ast_json_integer_set(NULL, 911));
427         ast_test_validate(test, 0 == ast_json_array_size(NULL));
428
429         /* No magical parsing of strings into ints */
430         uut = ast_json_string_create("314");
431         ast_test_validate(test, NULL != uut);
432         ast_test_validate(test, 0 == ast_json_integer_get(uut));
433
434         /* Or vice-versa */
435         ast_json_unref(uut);
436         uut = ast_json_integer_create(314);
437         ast_test_validate(test, NULL == ast_json_string_get(uut));
438
439         return AST_TEST_PASS;
440 }
441
442 AST_TEST_DEFINE(json_test_array_create)
443 {
444         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
445         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
446
447         switch (cmd) {
448         case TEST_INIT:
449                 info->name = "array_create";
450                 info->category = "/main/json/";
451                 info->summary = "Testing creating JSON arrays.";
452                 info->description = "Test JSON abstraction library.";
453                 return AST_TEST_NOT_RUN;
454         case TEST_EXECUTE:
455                 break;
456         }
457
458         /* array creation */
459         uut = ast_json_array_create();
460         ast_test_validate(test, NULL != uut);
461         ast_test_validate(test, AST_JSON_ARRAY == ast_json_typeof(uut));
462         ast_test_validate(test, 0 == ast_json_array_size(uut));
463
464         ast_json_unref(uut);
465
466         return AST_TEST_PASS;
467 }
468
469 AST_TEST_DEFINE(json_test_array_append)
470 {
471         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
472         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
473         int uut_res;
474
475         switch (cmd) {
476         case TEST_INIT:
477                 info->name = "array_append";
478                 info->category = "/main/json/";
479                 info->summary = "Testing appending to JSON arrays.";
480                 info->description = "Test JSON abstraction library.";
481                 return AST_TEST_NOT_RUN;
482         case TEST_EXECUTE:
483                 break;
484         }
485
486         /* array append */
487         uut = ast_json_array_create();
488         uut_res = ast_json_array_append(uut, ast_json_string_create("one"));
489         ast_test_validate(test, 0 == uut_res);
490         ast_test_validate(test, 1 == ast_json_array_size(uut));
491         ast_test_validate(test, 0 == strcmp("one", ast_json_string_get(ast_json_array_get(uut, 0))));
492         /* index out of range */
493         ast_test_validate(test, NULL == ast_json_array_get(uut, 1));
494         ast_test_validate(test, NULL == ast_json_array_get(uut, -1));
495
496         return AST_TEST_PASS;
497 }
498
499 AST_TEST_DEFINE(json_test_array_inset)
500 {
501         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
502         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
503         int uut_res;
504
505         switch (cmd) {
506         case TEST_INIT:
507                 info->name = "array_insert";
508                 info->category = "/main/json/";
509                 info->summary = "Testing inserting into JSON arrays.";
510                 info->description = "Test JSON abstraction library.";
511                 return AST_TEST_NOT_RUN;
512         case TEST_EXECUTE:
513                 break;
514         }
515
516         /* array insert */
517         uut = ast_json_pack("[s]", "one");
518         uut_res = ast_json_array_insert(uut, 0, ast_json_string_create("zero"));
519         ast_test_validate(test, 0 == uut_res);
520         ast_test_validate(test, 2 == ast_json_array_size(uut));
521         ast_test_validate(test, 0 == strcmp("zero", ast_json_string_get(ast_json_array_get(uut, 0))));
522         ast_test_validate(test, 0 == strcmp("one", ast_json_string_get(ast_json_array_get(uut, 1))));
523
524         return AST_TEST_PASS;
525 }
526
527 AST_TEST_DEFINE(json_test_array_set)
528 {
529         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
530         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
531         int uut_res;
532
533         switch (cmd) {
534         case TEST_INIT:
535                 info->name = "array_set";
536                 info->category = "/main/json/";
537                 info->summary = "Testing setting a value in JSON arrays.";
538                 info->description = "Test JSON abstraction library.";
539                 return AST_TEST_NOT_RUN;
540         case TEST_EXECUTE:
541                 break;
542         }
543
544         /* array set */
545         uut = ast_json_pack("[s, s]", "zero", "one");
546         uut_res = ast_json_array_set(uut, 1, ast_json_integer_create(1));
547         ast_test_validate(test, 0 == uut_res);
548         ast_test_validate(test, 2 == ast_json_array_size(uut));
549         ast_test_validate(test, 0 == strcmp("zero", ast_json_string_get(ast_json_array_get(uut, 0))));
550         ast_test_validate(test, 1 == ast_json_integer_get(ast_json_array_get(uut, 1)));
551
552         return AST_TEST_PASS;
553 }
554
555 AST_TEST_DEFINE(json_test_array_remove)
556 {
557         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
558         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
559         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
560         int uut_res;
561
562         switch (cmd) {
563         case TEST_INIT:
564                 info->name = "array_remove";
565                 info->category = "/main/json/";
566                 info->summary = "Testing removing a value from JSON arrays.";
567                 info->description = "Test JSON abstraction library.";
568                 return AST_TEST_NOT_RUN;
569         case TEST_EXECUTE:
570                 break;
571         }
572
573         /* array remove */
574         uut = ast_json_pack("[s, i]", "zero", 1);
575         expected = ast_json_pack("[i]", 1);
576         uut_res = ast_json_array_remove(uut, 0);
577         ast_test_validate(test, 0 == uut_res);
578         ast_test_validate(test, ast_json_equal(expected, uut));
579
580         return AST_TEST_PASS;
581 }
582
583 AST_TEST_DEFINE(json_test_array_clear)
584 {
585         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
586         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
587         int uut_res;
588
589         switch (cmd) {
590         case TEST_INIT:
591                 info->name = "array_clear";
592                 info->category = "/main/json/";
593                 info->summary = "Testing clearing JSON arrays.";
594                 info->description = "Test JSON abstraction library.";
595                 return AST_TEST_NOT_RUN;
596         case TEST_EXECUTE:
597                 break;
598         }
599
600         /* array clear */
601         uut = ast_json_pack("[s, s]", "zero", "one");
602         uut_res = ast_json_array_clear(uut);
603         ast_test_validate(test, 0 == uut_res);
604         ast_test_validate(test, 0 == ast_json_array_size(uut));
605
606         return AST_TEST_PASS;
607 }
608
609 AST_TEST_DEFINE(json_test_array_extend)
610 {
611         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
612         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
613         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
614         RAII_VAR(struct ast_json *, tail, NULL, ast_json_unref);
615         int uut_res;
616
617         switch (cmd) {
618         case TEST_INIT:
619                 info->name = "array_extend";
620                 info->category = "/main/json/";
621                 info->summary = "Testing extending JSON arrays.";
622                 info->description = "Test JSON abstraction library.";
623                 return AST_TEST_NOT_RUN;
624         case TEST_EXECUTE:
625                 break;
626         }
627
628         /* array extending */
629         expected = ast_json_array_create();
630         ast_json_array_append(expected, ast_json_string_create("a"));
631         ast_json_array_append(expected, ast_json_string_create("b"));
632         ast_json_array_append(expected, ast_json_string_create("c"));
633         ast_json_array_append(expected, ast_json_integer_create(1));
634         ast_json_array_append(expected, ast_json_integer_create(2));
635         ast_json_array_append(expected, ast_json_integer_create(3));
636
637         uut = ast_json_array_create();
638         ast_json_array_append(uut, ast_json_string_create("a"));
639         ast_json_array_append(uut, ast_json_string_create("b"));
640         ast_json_array_append(uut, ast_json_string_create("c"));
641
642         tail = ast_json_array_create();
643         ast_json_array_append(tail, ast_json_integer_create(1));
644         ast_json_array_append(tail, ast_json_integer_create(2));
645         ast_json_array_append(tail, ast_json_integer_create(3));
646
647         uut_res = ast_json_array_extend(uut, tail);
648         ast_test_validate(test, 0 == uut_res);
649         ast_test_validate(test, ast_json_equal(expected, uut));
650         /* tail is preserved */
651         ast_test_validate(test, 3 == ast_json_array_size(tail));
652
653         return AST_TEST_PASS;
654 }
655
656 AST_TEST_DEFINE(json_test_array_null)
657 {
658         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
659         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
660
661         switch (cmd) {
662         case TEST_INIT:
663                 info->name = "array_null";
664                 info->category = "/main/json/";
665                 info->summary = "Testing NULL conditions for JSON arrays.";
666                 info->description = "Test JSON abstraction library.";
667                 return AST_TEST_NOT_RUN;
668         case TEST_EXECUTE:
669                 break;
670         }
671
672         /* array NULL checks */
673         ast_test_validate(test, 0 == ast_json_array_size(NULL));
674         ast_test_validate(test, NULL == ast_json_array_get(NULL, 0));
675         ast_test_validate(test, -1 == ast_json_array_set(NULL, 0, ast_json_null()));
676         ast_test_validate(test, -1 == ast_json_array_append(NULL, ast_json_null()));
677         ast_test_validate(test, -1 == ast_json_array_insert(NULL, 0, ast_json_null()));
678         ast_test_validate(test, -1 == ast_json_array_remove(NULL, 0));
679         ast_test_validate(test, -1 == ast_json_array_clear(NULL));
680         uut = ast_json_array_create();
681         ast_test_validate(test, -1 == ast_json_array_extend(uut, NULL));
682         ast_test_validate(test, -1 == ast_json_array_extend(NULL, uut));
683         ast_test_validate(test, -1 == ast_json_array_extend(NULL, NULL));
684
685         return AST_TEST_PASS;
686 }
687
688 AST_TEST_DEFINE(json_test_object_alloc)
689 {
690         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
691         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
692
693         switch (cmd) {
694         case TEST_INIT:
695                 info->name = "object_alloc";
696                 info->category = "/main/json/";
697                 info->summary = "Testing creating JSON objects.";
698                 info->description = "Test JSON abstraction library.";
699                 return AST_TEST_NOT_RUN;
700         case TEST_EXECUTE:
701                 break;
702         }
703
704         /* object allocation */
705         uut = ast_json_object_create();
706         ast_test_validate(test, NULL != uut);
707         ast_test_validate(test, AST_JSON_OBJECT == ast_json_typeof(uut));
708         ast_test_validate(test, 0 == ast_json_object_size(uut));
709
710         return AST_TEST_PASS;
711 }
712
713 AST_TEST_DEFINE(json_test_object_set)
714 {
715         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
716         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
717         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
718         int uut_res;
719
720         switch (cmd) {
721         case TEST_INIT:
722                 info->name = "object_set";
723                 info->category = "/main/json/";
724                 info->summary = "Testing setting values in JSON objects.";
725                 info->description = "Test JSON abstraction library.";
726                 return AST_TEST_NOT_RUN;
727         case TEST_EXECUTE:
728                 break;
729         }
730
731         /* object set */
732         expected = ast_json_pack("{s: i, s: i, s: i}", "one", 1, "two", 2, "three", 3);
733         uut = ast_json_object_create();
734         uut_res = ast_json_object_set(uut, "one", ast_json_integer_create(1));
735         ast_test_validate(test, 0 == uut_res);
736         uut_res = ast_json_object_set(uut, "two", ast_json_integer_create(2));
737         ast_test_validate(test, 0 == uut_res);
738         uut_res = ast_json_object_set(uut, "three", ast_json_integer_create(3));
739         ast_test_validate(test, 0 == uut_res);
740         ast_test_validate(test, ast_json_equal(expected, uut));
741         ast_test_validate(test, NULL == ast_json_object_get(uut, "dne"));
742
743         return AST_TEST_PASS;
744 }
745
746 AST_TEST_DEFINE(json_test_object_set_overwrite)
747 {
748         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
749         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
750         int uut_res;
751
752         switch (cmd) {
753         case TEST_INIT:
754                 info->name = "object_set_overwriting";
755                 info->category = "/main/json/";
756                 info->summary = "Testing changing values in JSON objects.";
757                 info->description = "Test JSON abstraction library.";
758                 return AST_TEST_NOT_RUN;
759         case TEST_EXECUTE:
760                 break;
761         }
762
763         /* object set existing */
764         uut = ast_json_pack("{s: i, s: i, s: i}", "one", 1, "two", 2, "three", 3);
765         uut_res = ast_json_object_set(uut, "two", ast_json_integer_create(-2));
766         ast_test_validate(test, 0 == uut_res);
767         ast_test_validate(test, -2 == ast_json_integer_get(ast_json_object_get(uut, "two")));
768
769         return AST_TEST_PASS;
770 }
771
772 AST_TEST_DEFINE(json_test_object_get)
773 {
774         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
775         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
776
777         switch (cmd) {
778         case TEST_INIT:
779                 info->name = "object_get";
780                 info->category = "/main/json/";
781                 info->summary = "Testing getting values from JSON objects.";
782                 info->description = "Test JSON abstraction library.";
783                 return AST_TEST_NOT_RUN;
784         case TEST_EXECUTE:
785                 break;
786         }
787
788         /* object get */
789         uut = ast_json_pack("{s: i, s: i, s: i}", "one", 1, "two", 2, "three", 3);
790         ast_test_validate(test, 2 == ast_json_integer_get(ast_json_object_get(uut, "two")));
791         ast_test_validate(test, NULL == ast_json_object_get(uut, "dne"));
792         ast_test_validate(test, NULL == ast_json_object_get(uut, NULL));
793
794         return AST_TEST_PASS;
795 }
796
797 AST_TEST_DEFINE(json_test_object_del)
798 {
799         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
800         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
801         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
802         int uut_res;
803
804         switch (cmd) {
805         case TEST_INIT:
806                 info->name = "object_del";
807                 info->category = "/main/json/";
808                 info->summary = "Testing deleting values from JSON objects.";
809                 info->description = "Test JSON abstraction library.";
810                 return AST_TEST_NOT_RUN;
811         case TEST_EXECUTE:
812                 break;
813         }
814
815         /* object del */
816         expected = ast_json_object_create();
817         uut = ast_json_pack("{s: i}", "one", 1);
818         uut_res = ast_json_object_del(uut, "one");
819         ast_test_validate(test, 0 == uut_res);
820         ast_test_validate(test, ast_json_equal(expected, uut));
821         uut_res = ast_json_object_del(uut, "dne");
822         ast_test_validate(test, -1 == uut_res);
823
824         return AST_TEST_PASS;
825 }
826
827 AST_TEST_DEFINE(json_test_object_clear)
828 {
829         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
830         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
831         int uut_res;
832
833         switch (cmd) {
834         case TEST_INIT:
835                 info->name = "object_clear";
836                 info->category = "/main/json/";
837                 info->summary = "Testing clearing values from JSON objects.";
838                 info->description = "Test JSON abstraction library.";
839                 return AST_TEST_NOT_RUN;
840         case TEST_EXECUTE:
841                 break;
842         }
843
844         /* object clear */
845         uut = ast_json_object_create();
846         ast_json_object_set(uut, "one", ast_json_integer_create(1));
847         ast_json_object_set(uut, "two", ast_json_integer_create(2));
848         ast_json_object_set(uut, "three", ast_json_integer_create(3));
849         uut_res = ast_json_object_clear(uut);
850         ast_test_validate(test, 0 == uut_res);
851         ast_test_validate(test, 0 == ast_json_object_size(uut));
852
853         return AST_TEST_PASS;
854 }
855
856 AST_TEST_DEFINE(json_test_object_merge_all)
857 {
858         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
859         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
860         RAII_VAR(struct ast_json *, merge, NULL, ast_json_unref);
861         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
862         int uut_res;
863
864         switch (cmd) {
865         case TEST_INIT:
866                 info->name = "object_alloc";
867                 info->category = "/main/json/";
868                 info->summary = "Testing merging JSON objects.";
869                 info->description = "Test JSON abstraction library.";
870                 return AST_TEST_NOT_RUN;
871         case TEST_EXECUTE:
872                 break;
873         }
874
875         /* object merging - all */
876         uut = ast_json_object_create();
877         ast_json_object_set(uut, "one", ast_json_integer_create(1));
878         ast_json_object_set(uut, "two", ast_json_integer_create(2));
879         ast_json_object_set(uut, "three", ast_json_integer_create(3));
880
881         merge = ast_json_object_create();
882         ast_json_object_set(merge, "three", ast_json_integer_create(-3));
883         ast_json_object_set(merge, "four", ast_json_integer_create(-4));
884         ast_json_object_set(merge, "five", ast_json_integer_create(-5));
885
886         expected = ast_json_object_create();
887         ast_json_object_set(expected, "one", ast_json_integer_create(1));
888         ast_json_object_set(expected, "two", ast_json_integer_create(2));
889         ast_json_object_set(expected, "three", ast_json_integer_create(-3));
890         ast_json_object_set(expected, "four", ast_json_integer_create(-4));
891         ast_json_object_set(expected, "five", ast_json_integer_create(-5));
892
893         uut_res = ast_json_object_update(uut, merge);
894         ast_test_validate(test, 0 == uut_res);
895         ast_test_validate(test, ast_json_equal(expected, uut));
896         /* merge object is untouched */
897         ast_test_validate(test, 3 == ast_json_object_size(merge));
898
899         return AST_TEST_PASS;
900 }
901
902 AST_TEST_DEFINE(json_test_object_merge_existing)
903 {
904         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
905         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
906         RAII_VAR(struct ast_json *, merge, NULL, ast_json_unref);
907         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
908         int uut_res;
909
910         switch (cmd) {
911         case TEST_INIT:
912                 info->name = "object_alloc";
913                 info->category = "/main/json/";
914                 info->summary = "Testing merging JSON objects, updating only existing fields.";
915                 info->description = "Test JSON abstraction library.";
916                 return AST_TEST_NOT_RUN;
917         case TEST_EXECUTE:
918                 break;
919         }
920
921         /* object merging - existing */
922         uut = ast_json_object_create();
923         ast_json_object_set(uut, "one", ast_json_integer_create(1));
924         ast_json_object_set(uut, "two", ast_json_integer_create(2));
925         ast_json_object_set(uut, "three", ast_json_integer_create(3));
926
927         merge = ast_json_object_create();
928         ast_json_object_set(merge, "three", ast_json_integer_create(-3));
929         ast_json_object_set(merge, "four", ast_json_integer_create(-4));
930         ast_json_object_set(merge, "five", ast_json_integer_create(-5));
931
932         expected = ast_json_object_create();
933         ast_json_object_set(expected, "one", ast_json_integer_create(1));
934         ast_json_object_set(expected, "two", ast_json_integer_create(2));
935         ast_json_object_set(expected, "three", ast_json_integer_create(-3));
936
937         uut_res = ast_json_object_update_existing(uut, merge);
938         ast_test_validate(test, 0 == uut_res);
939         ast_test_validate(test, ast_json_equal(expected, uut));
940         /* merge object is untouched */
941         ast_test_validate(test, 3 == ast_json_object_size(merge));
942
943         return AST_TEST_PASS;
944 }
945
946 AST_TEST_DEFINE(json_test_object_merge_missing)
947 {
948         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
949         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
950         RAII_VAR(struct ast_json *, merge, NULL, ast_json_unref);
951         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
952         int uut_res;
953
954         switch (cmd) {
955         case TEST_INIT:
956                 info->name = "object_merge_missing";
957                 info->category = "/main/json/";
958                 info->summary = "Testing merging JSON objects, adding only missing fields.";
959                 info->description = "Test JSON abstraction library.";
960                 return AST_TEST_NOT_RUN;
961         case TEST_EXECUTE:
962                 break;
963         }
964
965         /* object merging - missing */
966         uut = ast_json_object_create();
967         ast_json_object_set(uut, "one", ast_json_integer_create(1));
968         ast_json_object_set(uut, "two", ast_json_integer_create(2));
969         ast_json_object_set(uut, "three", ast_json_integer_create(3));
970
971         merge = ast_json_object_create();
972         ast_json_object_set(merge, "three", ast_json_integer_create(-3));
973         ast_json_object_set(merge, "four", ast_json_integer_create(-4));
974         ast_json_object_set(merge, "five", ast_json_integer_create(-5));
975
976         expected = ast_json_object_create();
977         ast_json_object_set(expected, "one", ast_json_integer_create(1));
978         ast_json_object_set(expected, "two", ast_json_integer_create(2));
979         ast_json_object_set(expected, "three", ast_json_integer_create(3));
980         ast_json_object_set(expected, "four", ast_json_integer_create(-4));
981         ast_json_object_set(expected, "five", ast_json_integer_create(-5));
982
983         uut_res = ast_json_object_update_missing(uut, merge);
984         ast_test_validate(test, 0 == uut_res);
985         ast_test_validate(test, ast_json_equal(expected, uut));
986         /* merge object is untouched */
987         ast_test_validate(test, 3 == ast_json_object_size(merge));
988
989         return AST_TEST_PASS;
990 }
991
992 AST_TEST_DEFINE(json_test_object_null)
993 {
994         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
995         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
996
997         switch (cmd) {
998         case TEST_INIT:
999                 info->name = "object_null";
1000                 info->category = "/main/json/";
1001                 info->summary = "Testing JSON object NULL behavior.";
1002                 info->description = "Test JSON abstraction library.";
1003                 return AST_TEST_NOT_RUN;
1004         case TEST_EXECUTE:
1005                 break;
1006         }
1007
1008         /* Object NULL testing */
1009         ast_test_validate(test, 0 == ast_json_object_size(NULL));
1010         ast_test_validate(test, NULL == ast_json_object_get(NULL, "not null"));
1011         ast_test_validate(test, -1 == ast_json_object_set(NULL, "not null", ast_json_null()));
1012         ast_test_validate(test, -1 == ast_json_object_del(NULL, "not null"));
1013         ast_test_validate(test, -1 == ast_json_object_clear(NULL));
1014         uut = ast_json_object_create();
1015         ast_test_validate(test, -1 == ast_json_object_update(NULL, uut));
1016         ast_test_validate(test, -1 == ast_json_object_update(uut, NULL));
1017         ast_test_validate(test, -1 == ast_json_object_update(NULL, NULL));
1018         ast_test_validate(test, -1 == ast_json_object_update_existing(NULL, uut));
1019         ast_test_validate(test, -1 == ast_json_object_update_existing(uut, NULL));
1020         ast_test_validate(test, -1 == ast_json_object_update_existing(NULL, NULL));
1021         ast_test_validate(test, -1 == ast_json_object_update_missing(NULL, uut));
1022         ast_test_validate(test, -1 == ast_json_object_update_missing(uut, NULL));
1023         ast_test_validate(test, -1 == ast_json_object_update_missing(NULL, NULL));
1024
1025         return AST_TEST_PASS;
1026 }
1027
1028 AST_TEST_DEFINE(json_test_object_iter)
1029 {
1030         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1031         struct ast_json_iter *iter;
1032         int count;
1033         int uut_res;
1034         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1035
1036         switch (cmd) {
1037         case TEST_INIT:
1038                 info->name = "object_iter";
1039                 info->category = "/main/json/";
1040                 info->summary = "Testing iterating through JSON objects.";
1041                 info->description = "Test JSON abstraction library.";
1042                 return AST_TEST_NOT_RUN;
1043         case TEST_EXECUTE:
1044                 break;
1045         }
1046
1047         /* Object iterator testing */
1048         uut = ast_json_pack("{s: i, s: i, s: i, s: i, s: i}", "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
1049
1050         /* Iterate through the object; be aware that order isn't specified */
1051         iter = ast_json_object_iter(uut);
1052         ast_test_validate(test, NULL != iter);
1053         count = 0;
1054         while (NULL != iter) {
1055                 if (0 == strcmp("one", ast_json_object_iter_key(iter))) {
1056                         ast_test_validate(test, 1 == ast_json_integer_get(ast_json_object_iter_value(iter)));
1057                 } else if (0 == strcmp("two", ast_json_object_iter_key(iter))) {
1058                         ast_test_validate(test, 2 == ast_json_integer_get(ast_json_object_iter_value(iter)));
1059                 } else if (0 == strcmp("three", ast_json_object_iter_key(iter))) {
1060                         ast_test_validate(test, 3 == ast_json_integer_get(ast_json_object_iter_value(iter)));
1061                 } else if (0 == strcmp("four", ast_json_object_iter_key(iter))) {
1062                         ast_test_validate(test, 4 == ast_json_integer_get(ast_json_object_iter_value(iter)));
1063                 } else if (0 == strcmp("five", ast_json_object_iter_key(iter))) {
1064                         ast_test_validate(test, 5 == ast_json_integer_get(ast_json_object_iter_value(iter)));
1065                 } else {
1066                         /* Unexpected key */
1067                         ast_test_validate(test, 0);
1068                 }
1069                 iter = ast_json_object_iter_next(uut, iter);
1070                 ++count;
1071         }
1072         ast_test_validate(test, 5 == count);
1073
1074         /* iterator non-existing key */
1075         iter = ast_json_object_iter_at(uut, "dne");
1076         ast_test_validate(test, NULL == iter);
1077
1078         /* iterator specific key */
1079         iter = ast_json_object_iter_at(uut, "three");
1080         ast_test_validate(test, NULL != iter);
1081         ast_test_validate(test, 3 == ast_json_integer_get(ast_json_object_iter_value(iter)));
1082
1083         /* set via iter */
1084         iter = ast_json_object_iter_at(uut, "three");
1085         uut_res = ast_json_object_iter_set(uut, iter, ast_json_integer_create(-3));
1086         ast_test_validate(test, 0 == uut_res);
1087         ast_test_validate(test, -3 == ast_json_integer_get(ast_json_object_get(uut, "three")));
1088
1089         return AST_TEST_PASS;
1090 }
1091
1092 AST_TEST_DEFINE(json_test_object_iter_null)
1093 {
1094         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1095         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1096
1097         switch (cmd) {
1098         case TEST_INIT:
1099                 info->name = "object_iter_null";
1100                 info->category = "/main/json/";
1101                 info->summary = "Testing JSON object iterator NULL testings.";
1102                 info->description = "Test JSON abstraction library.";
1103                 return AST_TEST_NOT_RUN;
1104         case TEST_EXECUTE:
1105                 break;
1106         }
1107
1108         /* iterator NULL tests */
1109         uut = ast_json_object_create();
1110         ast_test_validate(test, NULL == ast_json_object_iter(NULL));
1111         ast_test_validate(test, NULL == ast_json_object_iter_at(NULL, "not null"));
1112         ast_test_validate(test, NULL == ast_json_object_iter_next(NULL, NULL));
1113         ast_test_validate(test, NULL == ast_json_object_iter_next(uut, NULL));
1114         ast_test_validate(test, NULL == ast_json_object_iter_key(NULL));
1115         ast_test_validate(test, NULL == ast_json_object_iter_value(NULL));
1116         ast_test_validate(test, -1 == ast_json_object_iter_set(NULL, NULL, ast_json_null()));
1117         ast_test_validate(test, -1 == ast_json_object_iter_set(uut, NULL, ast_json_null()));
1118
1119         return AST_TEST_PASS;
1120 }
1121
1122 AST_TEST_DEFINE(json_test_dump_load_string)
1123 {
1124         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1125         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1126         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
1127         RAII_VAR(char *, str, NULL, json_debug_free);
1128
1129         switch (cmd) {
1130         case TEST_INIT:
1131                 info->name = "dump_load_string";
1132                 info->category = "/main/json/";
1133                 info->summary = "Testing dumping strings from JSON.";
1134                 info->description = "Test JSON abstraction library.";
1135                 return AST_TEST_NOT_RUN;
1136         case TEST_EXECUTE:
1137                 break;
1138         }
1139         expected = ast_json_pack("{ s: i }", "one", 1);
1140         str = ast_json_dump_string(expected);
1141         ast_test_validate(test, NULL != str);
1142         uut = ast_json_load_string(str, NULL);
1143         ast_test_validate(test, NULL != uut);
1144         ast_test_validate(test, ast_json_equal(expected, uut));
1145
1146         /* dump_string NULL */
1147         ast_test_validate(test, NULL == ast_json_dump_string(NULL));
1148
1149         return AST_TEST_PASS;
1150 }
1151
1152 AST_TEST_DEFINE(json_test_dump_load_str)
1153 {
1154         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1155         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1156         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
1157         RAII_VAR(struct ast_str *, astr, NULL, ast_free);
1158         int uut_res;
1159
1160         switch (cmd) {
1161         case TEST_INIT:
1162                 info->name = "dump_load_str";
1163                 info->category = "/main/json/";
1164                 info->summary = "Testing dumping ast_str from JSON.";
1165                 info->description = "Test JSON abstraction library.";
1166                 return AST_TEST_NOT_RUN;
1167         case TEST_EXECUTE:
1168                 break;
1169         }
1170
1171         /* dump/load ast_str */
1172         expected = ast_json_pack("{ s: i }", "one", 1);
1173         astr = ast_str_create(1); /* should expand to hold output */
1174         uut_res = ast_json_dump_str(expected, &astr);
1175         ast_test_validate(test, 0 == uut_res);
1176         uut = ast_json_load_str(astr, NULL);
1177         ast_test_validate(test, NULL != uut);
1178         ast_test_validate(test, ast_json_equal(expected, uut));
1179
1180         return AST_TEST_PASS;
1181 }
1182
1183 AST_TEST_DEFINE(json_test_dump_str_fail)
1184 {
1185         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1186         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1187         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
1188         struct ast_str *astr;
1189         int uut_res;
1190
1191         switch (cmd) {
1192         case TEST_INIT:
1193                 info->name = "dump_str_fail";
1194                 info->category = "/main/json/";
1195                 info->summary = "Testing dumping to ast_str when it can't grow.";
1196                 info->description = "Test JSON abstraction library.";
1197                 return AST_TEST_NOT_RUN;
1198         case TEST_EXECUTE:
1199                 break;
1200         }
1201
1202         /* dump ast_str growth failure */
1203         expected = ast_json_pack("{ s: i }", "one", 1);
1204         astr = ast_str_alloca(1); /* cannot grow */
1205         uut_res = ast_json_dump_str(expected, &astr);
1206         ast_test_validate(test, 0 != uut_res);
1207
1208         return AST_TEST_PASS;
1209 }
1210
1211 AST_TEST_DEFINE(json_test_load_buffer)
1212 {
1213         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1214         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1215         const char *str;
1216
1217         switch (cmd) {
1218         case TEST_INIT:
1219                 info->name = "load_buffer";
1220                 info->category = "/main/json/";
1221                 info->summary = "Testing loading JSON from buffer.";
1222                 info->description = "Test JSON abstraction library.";
1223                 return AST_TEST_NOT_RUN;
1224         case TEST_EXECUTE:
1225                 break;
1226         }
1227
1228         /* load buffer */
1229         str = "{ \"one\": 1 } trailing garbage";
1230         uut = ast_json_load_string(str, NULL);
1231         ast_test_validate(test, NULL == uut);
1232         uut = ast_json_load_buf(str, strlen("{ \"one\": 1 }"), NULL);
1233         ast_test_validate(test, NULL != uut);
1234
1235         return AST_TEST_PASS;
1236 }
1237
1238 /*! \brief \a fclose isn't NULL safe. */
1239 static int safe_fclose(FILE *f)
1240 {
1241         if (f) {
1242                 return fclose(f);
1243         }
1244         return 0;
1245 }
1246
1247 AST_TEST_DEFINE(json_test_dump_load_file)
1248 {
1249         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1250         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1251         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
1252         RAII_VAR(char *, filename, NULL, free);
1253         RAII_VAR(FILE *, file, NULL, safe_fclose);
1254         int uut_res;
1255
1256         switch (cmd) {
1257         case TEST_INIT:
1258                 info->name = "dump_load_file";
1259                 info->category = "/main/json/";
1260                 info->summary = "Testing dumping/loading JSON to/from file by FILE *.";
1261                 info->description = "Test JSON abstraction library.";
1262                 return AST_TEST_NOT_RUN;
1263         case TEST_EXECUTE:
1264                 break;
1265         }
1266
1267         /* dump/load file */
1268         expected = ast_json_pack("{ s: i }", "one", 1);
1269         filename = tempnam(NULL, "ast-json");
1270         file = fopen(filename, "w");
1271         uut_res = ast_json_dump_file(expected, file);
1272         ast_test_validate(test, 0 == uut_res);
1273         fclose(file);
1274         file = fopen(filename, "r");
1275         uut = ast_json_load_file(file, NULL);
1276         ast_test_validate(test, ast_json_equal(expected, uut));
1277
1278         return AST_TEST_PASS;
1279 }
1280
1281 AST_TEST_DEFINE(json_test_dump_load_new_file)
1282 {
1283         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1284         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1285         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
1286         RAII_VAR(char *, filename, NULL, free);
1287         int uut_res;
1288
1289         switch (cmd) {
1290         case TEST_INIT:
1291                 info->name = "dump_load_new_file";
1292                 info->category = "/main/json/";
1293                 info->summary = "Testing dumping/load JSON to/from file by filename.";
1294                 info->description = "Test JSON abstraction library.";
1295                 return AST_TEST_NOT_RUN;
1296         case TEST_EXECUTE:
1297                 break;
1298         }
1299
1300         /* dump/load filename */
1301         expected = ast_json_pack("{ s: i }", "one", 1);
1302         filename = tempnam(NULL, "ast-json");
1303         uut_res = ast_json_dump_new_file(expected, filename);
1304         ast_test_validate(test, 0 == uut_res);
1305         uut = ast_json_load_new_file(filename, NULL);
1306         ast_test_validate(test, ast_json_equal(expected, uut));
1307
1308         return AST_TEST_PASS;
1309 }
1310
1311 AST_TEST_DEFINE(json_test_dump_load_null)
1312 {
1313         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1314         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1315         RAII_VAR(char *, filename, NULL, free);
1316         RAII_VAR(FILE *, file, NULL, safe_fclose);
1317
1318         switch (cmd) {
1319         case TEST_INIT:
1320                 info->name = "dump_load_null";
1321                 info->category = "/main/json/";
1322                 info->summary = "Testing NULL handling of dump/load functions.";
1323                 info->description = "Test JSON abstraction library.";
1324                 return AST_TEST_NOT_RUN;
1325         case TEST_EXECUTE:
1326                 break;
1327         }
1328
1329         /* dump/load NULL tests */
1330         uut = ast_json_load_string("{ \"one\": 1 }", NULL);
1331         ast_test_validate(test, NULL != uut);
1332         filename = tempnam(NULL, "ast-json");
1333         file = fopen(filename, "w");
1334         ast_test_validate(test, NULL == ast_json_dump_string(NULL));
1335         ast_test_validate(test, -1 == ast_json_dump_file(NULL, file));
1336         ast_test_validate(test, -1 == ast_json_dump_file(uut, NULL));
1337         ast_test_validate(test, -1 == ast_json_dump_file(NULL, NULL));
1338         ast_test_validate(test, -1 == ast_json_dump_new_file(uut, NULL));
1339         ast_test_validate(test, -1 == ast_json_dump_new_file(NULL, filename));
1340         ast_test_validate(test, -1 == ast_json_dump_new_file(NULL, NULL));
1341         ast_test_validate(test, NULL == ast_json_load_string(NULL, NULL));
1342         ast_test_validate(test, NULL == ast_json_load_buf(NULL, 0, NULL));
1343         ast_test_validate(test, NULL == ast_json_load_file(NULL, NULL));
1344         ast_test_validate(test, NULL == ast_json_load_new_file(NULL, NULL));
1345
1346         return AST_TEST_PASS;
1347 }
1348
1349 AST_TEST_DEFINE(json_test_parse_errors)
1350 {
1351         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1352         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1353
1354         switch (cmd) {
1355         case TEST_INIT:
1356                 info->name = "parse_errors";
1357                 info->category = "/main/json/";
1358                 info->summary = "Testing various parse errors.";
1359                 info->description = "Test JSON abstraction library.";
1360                 return AST_TEST_NOT_RUN;
1361         case TEST_EXECUTE:
1362                 break;
1363         }
1364
1365         /* parse errors */
1366         ast_test_validate(test, NULL == ast_json_load_string("'singleton'", NULL));
1367         ast_test_validate(test, NULL == ast_json_load_string("{ no value }", NULL));
1368         ast_test_validate(test, NULL == ast_json_load_string("{ 'no': 'curly' ", NULL));
1369         ast_test_validate(test, NULL == ast_json_load_string("[ 'no', 'square'", NULL));
1370         ast_test_validate(test, NULL == ast_json_load_string("{ 1: 'int key' }", NULL));
1371         ast_test_validate(test, NULL == ast_json_load_string("", NULL));
1372         ast_test_validate(test, NULL == ast_json_load_string("{ 'missing' 'colon' }", NULL));
1373         ast_test_validate(test, NULL == ast_json_load_string("[ 'missing' 'comma' ]", NULL));
1374
1375         return AST_TEST_PASS;
1376 }
1377
1378 AST_TEST_DEFINE(json_test_pack)
1379 {
1380         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1381         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1382         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
1383
1384         switch (cmd) {
1385         case TEST_INIT:
1386                 info->name = "pack";
1387                 info->category = "/main/json/";
1388                 info->summary = "Testing json_pack function.";
1389                 info->description = "Test JSON abstraction library.";
1390                 return AST_TEST_NOT_RUN;
1391         case TEST_EXECUTE:
1392                 break;
1393         }
1394
1395         /* pack test */
1396         expected = ast_json_array_create();
1397         ast_json_array_append(expected, ast_json_array_create());
1398         ast_json_array_append(expected, ast_json_object_create());
1399         ast_json_array_append(ast_json_array_get(expected, 0), ast_json_integer_create(1));
1400         ast_json_array_append(ast_json_array_get(expected, 0), ast_json_integer_create(2));
1401         ast_json_object_set(ast_json_array_get(expected, 1), "cool", ast_json_true());
1402         uut = ast_json_pack("[[i,i],{s:b}]", 1, 2, "cool", 1);
1403         ast_test_validate(test, NULL != uut);
1404         ast_test_validate(test, ast_json_equal(expected, uut));
1405
1406         return AST_TEST_PASS;
1407 }
1408
1409 AST_TEST_DEFINE(json_test_pack_errors)
1410 {
1411         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1412         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1413
1414         switch (cmd) {
1415         case TEST_INIT:
1416                 info->name = "object_alloc";
1417                 info->category = "/main/json/";
1418                 info->summary = "Testing json_pack failure conditions.";
1419                 info->description = "Test JSON abstraction library.";
1420                 return AST_TEST_NOT_RUN;
1421         case TEST_EXECUTE:
1422                 break;
1423         }
1424
1425         /* pack errors */
1426         ast_test_validate(test, NULL == ast_json_pack(NULL));
1427         ast_test_validate(test, NULL == ast_json_pack("{s:i", "no curly", 911));
1428         ast_test_validate(test, NULL == ast_json_pack("[s, s", "no", "square"));
1429
1430         return AST_TEST_PASS;
1431 }
1432
1433 AST_TEST_DEFINE(json_test_copy)
1434 {
1435         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1436         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1437         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
1438
1439         switch (cmd) {
1440         case TEST_INIT:
1441                 info->name = "copy";
1442                 info->category = "/main/json/";
1443                 info->summary = "Testing copying JSON.";
1444                 info->description = "Test JSON abstraction library.";
1445                 return AST_TEST_NOT_RUN;
1446         case TEST_EXECUTE:
1447                 break;
1448         }
1449
1450         /* copy test */
1451         expected = ast_json_pack("{s: {s: i}}", "outer", "inner", 8675309);
1452         uut = ast_json_copy(expected);
1453         ast_test_validate(test, NULL != uut);
1454         ast_test_validate(test, ast_json_equal(expected, uut));
1455         ast_test_validate(test, ast_json_object_get(expected, "outer") == ast_json_object_get(uut, "outer"));
1456
1457         return AST_TEST_PASS;
1458 }
1459
1460 AST_TEST_DEFINE(json_test_deep_copy)
1461 {
1462         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1463         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1464         RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
1465
1466         switch (cmd) {
1467         case TEST_INIT:
1468                 info->name = "deep_copy";
1469                 info->category = "/main/json/";
1470                 info->summary = "Testing deep copying of JSON.";
1471                 info->description = "Test JSON abstraction library.";
1472                 return AST_TEST_NOT_RUN;
1473         case TEST_EXECUTE:
1474                 break;
1475         }
1476
1477         /* deep copy test */
1478         expected = ast_json_pack("{s: {s: i}}", "outer", "inner", 8675309);
1479         uut = ast_json_deep_copy(expected);
1480         ast_test_validate(test, NULL != uut);
1481         ast_test_validate(test, ast_json_equal(expected, uut));
1482         ast_test_validate(test, ast_json_object_get(expected, "outer") != ast_json_object_get(uut, "outer"));
1483         /* Changing the inner value of one should not change the other */
1484         ast_json_integer_set(ast_json_object_get(ast_json_object_get(uut, "outer"), "inner"), 411);
1485         ast_test_validate(test, !ast_json_equal(expected, uut));
1486
1487         return AST_TEST_PASS;
1488 }
1489
1490 AST_TEST_DEFINE(json_test_copy_null)
1491 {
1492         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1493         switch (cmd) {
1494         case TEST_INIT:
1495                 info->name = "copy_null";
1496                 info->category = "/main/json/";
1497                 info->summary = "Testing NULL handling of copy functions.";
1498                 info->description = "Test JSON abstraction library.";
1499                 return AST_TEST_NOT_RUN;
1500         case TEST_EXECUTE:
1501                 break;
1502         }
1503
1504         /* copy NULL */
1505         ast_test_validate(test, NULL == ast_json_copy(NULL));
1506         ast_test_validate(test, NULL == ast_json_deep_copy(NULL));
1507
1508         return AST_TEST_PASS;
1509 }
1510
1511 AST_TEST_DEFINE(json_test_circular_object)
1512 {
1513         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1514         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1515         int uut_res;
1516
1517         switch (cmd) {
1518         case TEST_INIT:
1519                 info->name = "circular_object";
1520                 info->category = "/main/json/";
1521                 info->summary = "Object cannot be added to itself.";
1522                 info->description = "Test JSON abstraction library.";
1523                 return AST_TEST_NOT_RUN;
1524         case TEST_EXECUTE:
1525                 break;
1526         }
1527
1528         /* circular reference testing */
1529         /* Cannot add self */
1530         uut = ast_json_object_create();
1531         uut_res = ast_json_object_set(uut, "myself", uut);
1532         ast_test_validate(test, -1 == uut_res);
1533         ast_test_validate(test, 0 == ast_json_object_size(uut));
1534
1535         return AST_TEST_PASS;
1536 }
1537
1538 AST_TEST_DEFINE(json_test_circular_array)
1539 {
1540         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1541         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1542         int uut_res;
1543
1544         switch (cmd) {
1545         case TEST_INIT:
1546                 info->name = "circular_array";
1547                 info->category = "/main/json/";
1548                 info->summary = "Array cannot be added to itself.";
1549                 info->description = "Test JSON abstraction library.";
1550                 return AST_TEST_NOT_RUN;
1551         case TEST_EXECUTE:
1552                 break;
1553         }
1554
1555         uut = ast_json_array_create();
1556         uut_res = ast_json_object_set(uut, "myself", uut);
1557         ast_test_validate(test, -1 == uut_res);
1558         ast_test_validate(test, 0 == ast_json_array_size(uut));
1559
1560         return AST_TEST_PASS;
1561 }
1562
1563 AST_TEST_DEFINE(json_test_clever_circle)
1564 {
1565         RAII_VAR(void *, alloc_debug, json_test_init(test), json_test_finish);
1566         RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
1567         RAII_VAR(struct ast_json *, inner_child, NULL, ast_json_unref);
1568         RAII_VAR(char *, str, NULL, json_debug_free);
1569         int uut_res;
1570
1571         switch (cmd) {
1572         case TEST_INIT:
1573                 info->name = "clever_circle";
1574                 info->category = "/main/json/";
1575                 info->summary = "JSON with circular references cannot be encoded.";
1576                 info->description = "Test JSON abstraction library.";
1577                 return AST_TEST_NOT_RUN;
1578         case TEST_EXECUTE:
1579                 break;
1580         }
1581
1582         /* can add to self if you're clever enough, but it should not encode */
1583         uut = ast_json_object_create();
1584         inner_child = ast_json_object_create();
1585         uut_res = ast_json_object_set(uut, "inner_child", ast_json_ref(inner_child));   /* incref to keep a reference */
1586         ast_test_validate(test, 0 == uut_res);
1587         uut_res = ast_json_object_set(inner_child, "parent", ast_json_ref(uut));   /* incref to keep a reference */
1588         ast_test_validate(test, 0 == uut_res);
1589         str = ast_json_dump_string(uut);
1590         ast_test_validate(test, NULL == str);
1591         /* Circular refs screw up reference counting, so break the cycle */
1592         ast_json_object_clear(inner_child);
1593
1594         return AST_TEST_PASS;
1595 }
1596
1597 static int unload_module(void)
1598 {
1599         AST_TEST_UNREGISTER(json_test_false);
1600         AST_TEST_UNREGISTER(json_test_true);
1601         AST_TEST_UNREGISTER(json_test_bool0);
1602         AST_TEST_UNREGISTER(json_test_bool1);
1603         AST_TEST_UNREGISTER(json_test_null);
1604         AST_TEST_UNREGISTER(json_test_null_val);
1605         AST_TEST_UNREGISTER(json_test_string);
1606         AST_TEST_UNREGISTER(json_test_string_null);
1607         AST_TEST_UNREGISTER(json_test_stringf);
1608         AST_TEST_UNREGISTER(json_test_int);
1609         AST_TEST_UNREGISTER(json_test_non_int);
1610         AST_TEST_UNREGISTER(json_test_array_create);
1611         AST_TEST_UNREGISTER(json_test_array_append);
1612         AST_TEST_UNREGISTER(json_test_array_inset);
1613         AST_TEST_UNREGISTER(json_test_array_set);
1614         AST_TEST_UNREGISTER(json_test_array_remove);
1615         AST_TEST_UNREGISTER(json_test_array_clear);
1616         AST_TEST_UNREGISTER(json_test_array_extend);
1617         AST_TEST_UNREGISTER(json_test_array_null);
1618         AST_TEST_UNREGISTER(json_test_object_alloc);
1619         AST_TEST_UNREGISTER(json_test_object_set);
1620         AST_TEST_UNREGISTER(json_test_object_set_overwrite);
1621         AST_TEST_UNREGISTER(json_test_object_get);
1622         AST_TEST_UNREGISTER(json_test_object_del);
1623         AST_TEST_UNREGISTER(json_test_object_clear);
1624         AST_TEST_UNREGISTER(json_test_object_merge_all);
1625         AST_TEST_UNREGISTER(json_test_object_merge_existing);
1626         AST_TEST_UNREGISTER(json_test_object_merge_missing);
1627         AST_TEST_UNREGISTER(json_test_object_null);
1628         AST_TEST_UNREGISTER(json_test_object_iter);
1629         AST_TEST_UNREGISTER(json_test_object_iter_null);
1630         AST_TEST_UNREGISTER(json_test_dump_load_string);
1631         AST_TEST_UNREGISTER(json_test_dump_load_str);
1632         AST_TEST_UNREGISTER(json_test_dump_str_fail);
1633         AST_TEST_UNREGISTER(json_test_load_buffer);
1634         AST_TEST_UNREGISTER(json_test_dump_load_file);
1635         AST_TEST_UNREGISTER(json_test_dump_load_new_file);
1636         AST_TEST_UNREGISTER(json_test_dump_load_null);
1637         AST_TEST_UNREGISTER(json_test_parse_errors);
1638         AST_TEST_UNREGISTER(json_test_pack);
1639         AST_TEST_UNREGISTER(json_test_pack_errors);
1640         AST_TEST_UNREGISTER(json_test_copy);
1641         AST_TEST_UNREGISTER(json_test_deep_copy);
1642         AST_TEST_UNREGISTER(json_test_copy_null);
1643         AST_TEST_UNREGISTER(json_test_circular_object);
1644         AST_TEST_UNREGISTER(json_test_circular_array);
1645         AST_TEST_UNREGISTER(json_test_clever_circle);
1646         return 0;
1647 }
1648
1649 static int load_module(void)
1650 {
1651         AST_TEST_REGISTER(json_test_false);
1652         AST_TEST_REGISTER(json_test_true);
1653         AST_TEST_REGISTER(json_test_bool0);
1654         AST_TEST_REGISTER(json_test_bool1);
1655         AST_TEST_REGISTER(json_test_null);
1656         AST_TEST_REGISTER(json_test_null_val);
1657         AST_TEST_REGISTER(json_test_string);
1658         AST_TEST_REGISTER(json_test_string_null);
1659         AST_TEST_REGISTER(json_test_stringf);
1660         AST_TEST_REGISTER(json_test_int);
1661         AST_TEST_REGISTER(json_test_non_int);
1662         AST_TEST_REGISTER(json_test_array_create);
1663         AST_TEST_REGISTER(json_test_array_append);
1664         AST_TEST_REGISTER(json_test_array_inset);
1665         AST_TEST_REGISTER(json_test_array_set);
1666         AST_TEST_REGISTER(json_test_array_remove);
1667         AST_TEST_REGISTER(json_test_array_clear);
1668         AST_TEST_REGISTER(json_test_array_extend);
1669         AST_TEST_REGISTER(json_test_array_null);
1670         AST_TEST_REGISTER(json_test_object_alloc);
1671         AST_TEST_REGISTER(json_test_object_set);
1672         AST_TEST_REGISTER(json_test_object_set_overwrite);
1673         AST_TEST_REGISTER(json_test_object_get);
1674         AST_TEST_REGISTER(json_test_object_del);
1675         AST_TEST_REGISTER(json_test_object_clear);
1676         AST_TEST_REGISTER(json_test_object_merge_all);
1677         AST_TEST_REGISTER(json_test_object_merge_existing);
1678         AST_TEST_REGISTER(json_test_object_merge_missing);
1679         AST_TEST_REGISTER(json_test_object_null);
1680         AST_TEST_REGISTER(json_test_object_iter);
1681         AST_TEST_REGISTER(json_test_object_iter_null);
1682         AST_TEST_REGISTER(json_test_dump_load_string);
1683         AST_TEST_REGISTER(json_test_dump_load_str);
1684         AST_TEST_REGISTER(json_test_dump_str_fail);
1685         AST_TEST_REGISTER(json_test_load_buffer);
1686         AST_TEST_REGISTER(json_test_dump_load_file);
1687         AST_TEST_REGISTER(json_test_dump_load_new_file);
1688         AST_TEST_REGISTER(json_test_dump_load_null);
1689         AST_TEST_REGISTER(json_test_parse_errors);
1690         AST_TEST_REGISTER(json_test_pack);
1691         AST_TEST_REGISTER(json_test_pack_errors);
1692         AST_TEST_REGISTER(json_test_copy);
1693         AST_TEST_REGISTER(json_test_deep_copy);
1694         AST_TEST_REGISTER(json_test_copy_null);
1695         AST_TEST_REGISTER(json_test_circular_object);
1696         AST_TEST_REGISTER(json_test_circular_array);
1697         AST_TEST_REGISTER(json_test_clever_circle);
1698         return AST_MODULE_LOAD_SUCCESS;
1699 }
1700
1701 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "JSON testing.");