1/***
2  This file is part of PulseAudio.
3
4  Copyright 2016 Arun Raghavan <mail@arunraghavan.net>
5
6  PulseAudio is free software; you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published
8  by the Free Software Foundation; either version 2.1 of the License,
9  or (at your option) any later version.
10
11  PulseAudio is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  General Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public License
17  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18***/
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24#include <check.h>
25
26#include <pulse/xmalloc.h>
27#include <pulsecore/core-util.h>
28#include <pulsecore/json.h>
29
30START_TEST (string_test) {
31    pa_json_object *o;
32    unsigned int i;
33    const char *strings_parse[] = {
34        "\"\"", "\"test\"", "\"test123\"", "\"123\"", "\"newline\\n\"", "\"  spaces \"",
35        "   \"lots of spaces\"     ", "\"esc\\nape\"", "\"escape a \\\" quote\"",
36    };
37    const char *strings_compare[] = {
38        "", "test", "test123", "123", "newline\n", "  spaces ",
39        "lots of spaces", "esc\nape", "escape a \" quote",
40    };
41
42    for (i = 0; i < PA_ELEMENTSOF(strings_parse); i++) {
43        o = pa_json_parse(strings_parse[i]);
44
45        fail_unless(o != NULL);
46        fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_STRING);
47        fail_unless(pa_streq(pa_json_object_get_string(o), strings_compare[i]));
48
49        pa_json_object_free(o);
50    }
51}
52END_TEST
53
54START_TEST (encoder_string_test) {
55    const char *test_strings[] = {
56        "", "test", "test123", "123", "newline\n", "  spaces ",
57        "lots of spaces", "esc\nape", "escape a \" quote",
58    };
59
60    pa_json_object *o;
61    unsigned int i;
62    pa_json_encoder *encoder;
63    const pa_json_object *v;
64    char *received;
65
66    encoder = pa_json_encoder_new();
67
68    pa_json_encoder_begin_element_array(encoder);
69
70    for (i = 0; i < PA_ELEMENTSOF(test_strings); i++) {
71        pa_json_encoder_add_element_string(encoder, test_strings[i]);
72    }
73
74    pa_json_encoder_end_array(encoder);
75
76    received = pa_json_encoder_to_string_free(encoder);
77    o = pa_json_parse(received);
78    pa_xfree(received);
79
80    fail_unless(o != NULL);
81    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
82    fail_unless(pa_json_object_get_array_length(o) == PA_ELEMENTSOF(test_strings));
83
84    for (i = 0; i < PA_ELEMENTSOF(test_strings); i++) {
85        v = pa_json_object_get_array_member(o, i);
86
87        fail_unless(v != NULL);
88        fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
89        fail_unless(pa_streq(pa_json_object_get_string(v), test_strings[i]));
90    }
91
92    pa_json_object_free(o);
93}
94END_TEST
95
96START_TEST(int_test) {
97    pa_json_object *o;
98    unsigned int i;
99    const char *ints_parse[] = { "1", "-1", "1234", "0" };
100    const int64_t ints_compare[] = { 1, -1, 1234, 0 };
101    char *uint64_max_str;
102
103    for (i = 0; i < PA_ELEMENTSOF(ints_parse); i++) {
104        o = pa_json_parse(ints_parse[i]);
105
106        fail_unless(o != NULL);
107        fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_INT);
108        fail_unless(pa_json_object_get_int(o) == ints_compare[i]);
109
110        pa_json_object_free(o);
111    }
112
113    /* test that parser would fail on integer overflow */
114    uint64_max_str = pa_sprintf_malloc("%"PRIu64, UINT64_MAX);
115    o = pa_json_parse(uint64_max_str);
116    fail_unless(o == NULL);
117    pa_xfree(uint64_max_str);
118}
119END_TEST
120
121START_TEST(encoder_int_test) {
122    const int64_t test_ints[] = { 1, -1, 1234, 0, LONG_MIN, LONG_MAX };
123
124    pa_json_object *o;
125    unsigned int i;
126    pa_json_encoder *encoder;
127    const pa_json_object *v;
128    char *received;
129
130    encoder = pa_json_encoder_new();
131
132    pa_json_encoder_begin_element_array(encoder);
133
134    for (i = 0; i < PA_ELEMENTSOF(test_ints); i++) {
135        pa_json_encoder_add_element_int(encoder, test_ints[i]);
136    }
137
138    pa_json_encoder_end_array(encoder);
139
140    received = pa_json_encoder_to_string_free(encoder);
141    o = pa_json_parse(received);
142    pa_xfree(received);
143
144    fail_unless(o != NULL);
145    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
146    fail_unless(pa_json_object_get_array_length(o) == PA_ELEMENTSOF(test_ints));
147
148    for (i = 0; i < PA_ELEMENTSOF(test_ints); i++) {
149        v = pa_json_object_get_array_member(o, i);
150
151        fail_unless(v != NULL);
152        fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_INT);
153        fail_unless(pa_json_object_get_int(v) == test_ints[i]);
154    }
155
156    pa_json_object_free(o);
157}
158END_TEST
159
160START_TEST(double_test) {
161    pa_json_object *o;
162    unsigned int i;
163    char *very_large_double_str;
164    const char *doubles_parse[] = {
165        "1.0", "-1.1", "1234e2", "1234e0", "0.1234", "-0.1234", "1234e-1", "1234.5e-1", "1234.5e+2",
166    };
167    const double doubles_compare[] = {
168        1.0, -1.1, 123400.0, 1234.0, 0.1234, -0.1234, 123.4, 123.45, 123450.0,
169    };
170
171    for (i = 0; i < PA_ELEMENTSOF(doubles_parse); i++) {
172        o = pa_json_parse(doubles_parse[i]);
173
174        fail_unless(o != NULL);
175        fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_DOUBLE);
176        fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(o), doubles_compare[i]));
177
178        pa_json_object_free(o);
179    }
180
181    /* test that parser would fail on double exponent overflow */
182    very_large_double_str = pa_sprintf_malloc("%"PRIu64"e%"PRIu64, UINT64_MAX, UINT64_MAX);
183    o = pa_json_parse(very_large_double_str);
184    fail_unless(o == NULL);
185    pa_xfree(very_large_double_str);
186}
187END_TEST
188
189START_TEST(encoder_double_test) {
190    const double test_doubles[] = {
191        1.0, -1.1, 123400.0, 1234.0, 0.1234, -0.1234, 123.4, 123.45, 123450.0,
192    };
193    pa_json_object *o;
194    unsigned int i;
195    pa_json_encoder *encoder;
196    const pa_json_object *v;
197    char *received;
198
199    encoder = pa_json_encoder_new();
200
201    pa_json_encoder_begin_element_array(encoder);
202
203    for (i = 0; i < PA_ELEMENTSOF(test_doubles); i++) {
204        pa_json_encoder_add_element_double(encoder, test_doubles[i], 6);
205    }
206
207    pa_json_encoder_end_array(encoder);
208
209    received = pa_json_encoder_to_string_free(encoder);
210    o = pa_json_parse(received);
211    pa_xfree(received);
212
213    fail_unless(o != NULL);
214    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
215    fail_unless(pa_json_object_get_array_length(o) == PA_ELEMENTSOF(test_doubles));
216
217    for (i = 0; i < PA_ELEMENTSOF(test_doubles); i++) {
218        v = pa_json_object_get_array_member(o, i);
219
220        fail_unless(v != NULL);
221        fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_DOUBLE);
222        fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(v), test_doubles[i]));
223    }
224
225    pa_json_object_free(o);
226}
227END_TEST
228
229START_TEST(null_test) {
230    pa_json_object *o;
231
232    o = pa_json_parse("null");
233
234    fail_unless(o != NULL);
235    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_NULL);
236
237    pa_json_object_free(o);
238}
239END_TEST
240
241START_TEST(encoder_null_test) {
242    pa_json_object *o;
243    pa_json_encoder *encoder;
244    char *received;
245
246    encoder = pa_json_encoder_new();
247    pa_json_encoder_add_element_null(encoder);
248
249    received = pa_json_encoder_to_string_free(encoder);
250    o = pa_json_parse(received);
251    pa_xfree(received);
252
253    fail_unless(o != NULL);
254    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_NULL);
255
256    pa_json_object_free(o);
257}
258END_TEST
259
260START_TEST(bool_test) {
261    pa_json_object *o;
262
263    o = pa_json_parse("true");
264
265    fail_unless(o != NULL);
266    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_BOOL);
267    fail_unless(pa_json_object_get_bool(o) == true);
268
269    pa_json_object_free(o);
270
271    o = pa_json_parse("false");
272
273    fail_unless(o != NULL);
274    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_BOOL);
275    fail_unless(pa_json_object_get_bool(o) == false);
276
277    pa_json_object_free(o);
278}
279END_TEST
280
281START_TEST(encoder_bool_test) {
282    const bool test_bools[] = {
283        true, false
284    };
285    pa_json_object *o;
286    unsigned int i;
287    pa_json_encoder *encoder;
288    const pa_json_object *v;
289    char *received;
290
291    encoder = pa_json_encoder_new();
292
293    pa_json_encoder_begin_element_array(encoder);
294
295    for (i = 0; i < PA_ELEMENTSOF(test_bools); i++) {
296        pa_json_encoder_add_element_bool(encoder, test_bools[i]);
297    }
298
299    pa_json_encoder_end_array(encoder);
300
301    received = pa_json_encoder_to_string_free(encoder);
302    o = pa_json_parse(received);
303    pa_xfree(received);
304
305    fail_unless(o != NULL);
306    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
307    fail_unless(pa_json_object_get_array_length(o) == PA_ELEMENTSOF(test_bools));
308
309    for (i = 0; i < PA_ELEMENTSOF(test_bools); i++) {
310        v = pa_json_object_get_array_member(o, i);
311
312        fail_unless(v != NULL);
313        fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_BOOL);
314        fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_bool(v), test_bools[i]));
315    }
316
317    pa_json_object_free(o);
318}
319END_TEST
320
321START_TEST(object_test) {
322    pa_json_object *o;
323    const pa_json_object *v;
324
325    o = pa_json_parse(" { \"name\" : \"A Person\" } ");
326
327    fail_unless(o != NULL);
328    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
329
330    v = pa_json_object_get_object_member(o, "name");
331    fail_unless(v != NULL);
332    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
333    fail_unless(pa_streq(pa_json_object_get_string(v), "A Person"));
334
335    pa_json_object_free(o);
336
337    o = pa_json_parse(" { \"age\" : -45.3e-0 } ");
338
339    fail_unless(o != NULL);
340    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
341
342    v = pa_json_object_get_object_member(o, "age");
343    fail_unless(v != NULL);
344    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_DOUBLE);
345    fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(v), -45.3));
346
347    pa_json_object_free(o);
348
349    o = pa_json_parse("{\"person\":true}");
350
351    fail_unless(o != NULL);
352    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
353
354    v = pa_json_object_get_object_member(o, "person");
355    fail_unless(v != NULL);
356    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_BOOL);
357    fail_unless(pa_json_object_get_bool(v) == true);
358
359    pa_json_object_free(o);
360
361    o = pa_json_parse("{ \"parent\": { \"child\": false } }");
362    fail_unless(o != NULL);
363    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
364
365    v = pa_json_object_get_object_member(o, "parent");
366    fail_unless(v != NULL);
367    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_OBJECT);
368    v = pa_json_object_get_object_member(v, "child");
369    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_BOOL);
370    fail_unless(pa_json_object_get_bool(v) == false);
371
372    pa_json_object_free(o);
373}
374END_TEST
375
376START_TEST(object_member_iterator_test) {
377    pa_json_object *o;
378    const pa_json_object *v;
379    const char *k;
380    void *state;
381    size_t i;
382
383    struct {
384        bool visited;
385        const char *key;
386        pa_json_type type;
387        union {
388            const char *str;
389            int64_t n;
390        } value;
391    } expected_entries[] = {
392            { .key = "name", .type = PA_JSON_TYPE_STRING, .value.str = "sample 1" },
393            { .key = "number", .type = PA_JSON_TYPE_INT, .value.n = 42 },
394    };
395
396    o = pa_json_parse(" { \"name\" : \"sample 1\", \"number\": 42 } ");
397
398    fail_unless(o != NULL);
399    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
400
401    PA_HASHMAP_FOREACH_KV(k, v, pa_json_object_get_object_member_hashmap(o), state) {
402        fail_unless(k != NULL);
403        fail_unless(v != NULL);
404        for (i = 0; i < PA_ELEMENTSOF(expected_entries); ++i) {
405            if (pa_streq(expected_entries[i].key, k)) {
406                fail_unless(!expected_entries[i].visited);
407                fail_unless(expected_entries[i].type == pa_json_object_get_type(v));
408                switch (expected_entries[i].type) {
409                    case PA_JSON_TYPE_STRING:
410                        fail_unless(pa_streq(expected_entries[i].value.str, pa_json_object_get_string(v)));
411                        break;
412                    case PA_JSON_TYPE_INT:
413                        fail_unless(expected_entries[i].value.n == pa_json_object_get_int(v));
414                        break;
415                    default:
416                        /* unreachable */
417                        fail_unless(false);
418                        break;
419                }
420                expected_entries[i].visited = true;
421            }
422        }
423    }
424
425    pa_json_object_free(o);
426}
427END_TEST
428
429START_TEST(encoder_object_test) {
430    pa_json_object *o;
431    const pa_json_object *v;
432    pa_json_encoder *encoder;
433    char *received;
434
435    /* { "name" : "A Person" } */
436
437    encoder = pa_json_encoder_new();
438    pa_json_encoder_begin_element_object(encoder);
439    pa_json_encoder_add_member_string(encoder, "name", "A Person");
440    pa_json_encoder_end_object(encoder);
441
442    received = pa_json_encoder_to_string_free(encoder);
443    o = pa_json_parse(received);
444    pa_xfree(received);
445
446    fail_unless(o != NULL);
447    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
448
449    v = pa_json_object_get_object_member(o, "name");
450    fail_unless(v != NULL);
451    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
452    fail_unless(pa_streq(pa_json_object_get_string(v), "A Person"));
453
454    pa_json_object_free(o);
455
456    /* { "age" : -45.3e-0 } */
457
458    encoder = pa_json_encoder_new();
459    pa_json_encoder_begin_element_object(encoder);
460    pa_json_encoder_add_member_double(encoder, "age", -45.3e-0, 2);
461    pa_json_encoder_end_object(encoder);
462
463    received = pa_json_encoder_to_string_free(encoder);
464    o = pa_json_parse(received);
465    pa_xfree(received);
466
467    fail_unless(o != NULL);
468    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
469
470    v = pa_json_object_get_object_member(o, "age");
471    fail_unless(v != NULL);
472    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_DOUBLE);
473    fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(v), -45.3));
474
475    pa_json_object_free(o);
476
477    /* {"person":true} */
478
479    encoder = pa_json_encoder_new();
480    pa_json_encoder_begin_element_object(encoder);
481    pa_json_encoder_add_member_bool(encoder, "person", true);
482    pa_json_encoder_end_object(encoder);
483
484    received = pa_json_encoder_to_string_free(encoder);
485    o = pa_json_parse(received);
486    pa_xfree(received);
487
488    fail_unless(o != NULL);
489    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
490
491    v = pa_json_object_get_object_member(o, "person");
492    fail_unless(v != NULL);
493    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_BOOL);
494    fail_unless(pa_json_object_get_bool(v) == true);
495
496    pa_json_object_free(o);
497}
498END_TEST
499
500START_TEST(encoder_member_object_test) {
501    pa_json_object *o;
502    const pa_json_object *v;
503    pa_json_encoder *encoder;
504    char *received;
505
506    /* { "parent": { "child": false } } */
507
508    encoder = pa_json_encoder_new();
509    pa_json_encoder_begin_element_object(encoder);
510
511    pa_json_encoder_begin_member_object(encoder, "parent");
512    pa_json_encoder_add_member_bool(encoder, "child", false);
513    pa_json_encoder_end_object(encoder);
514
515    pa_json_encoder_end_object(encoder);
516
517    received = pa_json_encoder_to_string_free(encoder);
518    o = pa_json_parse(received);
519    pa_xfree(received);
520
521    fail_unless(o != NULL);
522    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
523
524    v = pa_json_object_get_object_member(o, "parent");
525    fail_unless(v != NULL);
526    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_OBJECT);
527    v = pa_json_object_get_object_member(v, "child");
528    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_BOOL);
529    fail_unless(pa_json_object_get_bool(v) == false);
530
531    pa_json_object_free(o);
532}
533END_TEST
534
535START_TEST(array_test) {
536    pa_json_object *o;
537    const pa_json_object *v, *v2;
538
539    o = pa_json_parse(" [  ] ");
540
541    fail_unless(o != NULL);
542    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
543    fail_unless(pa_json_object_get_array_length(o) == 0);
544
545    pa_json_object_free(o);
546
547    o = pa_json_parse("[\"a member\"]");
548
549    fail_unless(o != NULL);
550    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
551    fail_unless(pa_json_object_get_array_length(o) == 1);
552
553    v = pa_json_object_get_array_member(o, 0);
554    fail_unless(v != NULL);
555    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
556    fail_unless(pa_streq(pa_json_object_get_string(v), "a member"));
557
558    pa_json_object_free(o);
559
560    o = pa_json_parse("[\"a member\", 1234.5, { \"another\": true } ]");
561
562    fail_unless(o != NULL);
563    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
564    fail_unless(pa_json_object_get_array_length(o) == 3);
565
566    v = pa_json_object_get_array_member(o, 0);
567    fail_unless(v != NULL);
568    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
569    fail_unless(pa_streq(pa_json_object_get_string(v), "a member"));
570    v = pa_json_object_get_array_member(o, 1);
571    fail_unless(v != NULL);
572    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_DOUBLE);
573    fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(v), 1234.5));
574    v = pa_json_object_get_array_member(o, 2);
575    fail_unless(v != NULL);
576    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_OBJECT);
577    v2 =pa_json_object_get_object_member(v, "another");
578    fail_unless(v2 != NULL);
579    fail_unless(pa_json_object_get_type(v2) == PA_JSON_TYPE_BOOL);
580    fail_unless(pa_json_object_get_bool(v2) == true);
581
582    pa_json_object_free(o);
583}
584END_TEST
585
586START_TEST(encoder_element_array_test) {
587    pa_json_object *o;
588    const pa_json_object *v, *v2;
589
590    pa_json_encoder *encoder;
591    char *received;
592    pa_json_encoder *subobject;
593    char *subobject_string;
594
595    /* [  ] */
596    encoder = pa_json_encoder_new();
597    pa_json_encoder_begin_element_array(encoder);
598    pa_json_encoder_end_array(encoder);
599
600    received = pa_json_encoder_to_string_free(encoder);
601    o = pa_json_parse(received);
602    pa_xfree(received);
603
604    fail_unless(o != NULL);
605    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
606    fail_unless(pa_json_object_get_array_length(o) == 0);
607
608    pa_json_object_free(o);
609
610    /* ["a member"] */
611
612    encoder = pa_json_encoder_new();
613    pa_json_encoder_begin_element_array(encoder);
614    pa_json_encoder_add_element_string(encoder, "a member");
615    pa_json_encoder_end_array(encoder);
616
617    received = pa_json_encoder_to_string_free(encoder);
618    o = pa_json_parse(received);
619    pa_xfree(received);
620
621    fail_unless(o != NULL);
622    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
623    fail_unless(pa_json_object_get_array_length(o) == 1);
624
625    v = pa_json_object_get_array_member(o, 0);
626    fail_unless(v != NULL);
627    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
628    fail_unless(pa_streq(pa_json_object_get_string(v), "a member"));
629
630    pa_json_object_free(o);
631
632    /* [\"a member\", 1234.5, { \"another\": true } ] */
633
634    subobject = pa_json_encoder_new();
635    pa_json_encoder_begin_element_object(subobject);
636    pa_json_encoder_add_member_bool(subobject, "another", true);
637    pa_json_encoder_end_object(subobject);
638    subobject_string = pa_json_encoder_to_string_free(subobject);
639
640    encoder = pa_json_encoder_new();
641    pa_json_encoder_begin_element_array(encoder);
642    pa_json_encoder_add_element_string(encoder, "a member");
643    pa_json_encoder_add_element_double(encoder, 1234.5, 1);
644    pa_json_encoder_add_element_raw_json(encoder, subobject_string);
645    pa_xfree(subobject_string);
646    pa_json_encoder_end_array(encoder);
647
648    received = pa_json_encoder_to_string_free(encoder);
649    o = pa_json_parse(received);
650    pa_xfree(received);
651
652    fail_unless(o != NULL);
653    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_ARRAY);
654    fail_unless(pa_json_object_get_array_length(o) == 3);
655
656    v = pa_json_object_get_array_member(o, 0);
657    fail_unless(v != NULL);
658    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_STRING);
659    fail_unless(pa_streq(pa_json_object_get_string(v), "a member"));
660    v = pa_json_object_get_array_member(o, 1);
661    fail_unless(v != NULL);
662    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_DOUBLE);
663    fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(v), 1234.5));
664    v = pa_json_object_get_array_member(o, 2);
665    fail_unless(v != NULL);
666    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_OBJECT);
667    v2 =pa_json_object_get_object_member(v, "another");
668    fail_unless(v2 != NULL);
669    fail_unless(pa_json_object_get_type(v2) == PA_JSON_TYPE_BOOL);
670    fail_unless(pa_json_object_get_bool(v2) == true);
671
672    pa_json_object_free(o);
673}
674END_TEST
675
676START_TEST(encoder_member_array_test) {
677    pa_json_object *o;
678    unsigned int i;
679    const pa_json_object *v;
680    const pa_json_object *e;
681    pa_json_encoder *encoder;
682    char *received;
683
684    const int64_t test_ints[] = { 1, -1, 1234, 0, LONG_MIN, LONG_MAX };
685
686    /* { "parameters": [ 1, -1, 1234, 0, -9223372036854775808, 9223372036854775807 ] } */
687
688
689    encoder = pa_json_encoder_new();
690    pa_json_encoder_begin_element_object(encoder);
691
692    pa_json_encoder_begin_member_array(encoder, "parameters");
693    for (i = 0; i < PA_ELEMENTSOF(test_ints); i++) {
694        pa_json_encoder_add_element_int(encoder, test_ints[i]);
695    }
696    pa_json_encoder_end_array(encoder);
697
698    pa_json_encoder_end_object(encoder);
699
700    received = pa_json_encoder_to_string_free(encoder);
701    o = pa_json_parse(received);
702    pa_xfree(received);
703
704    fail_unless(o != NULL);
705    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
706
707    v = pa_json_object_get_object_member(o, "parameters");
708    fail_unless(v != NULL);
709    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_ARRAY);
710    fail_unless(pa_json_object_get_array_length(v) == PA_ELEMENTSOF(test_ints));
711
712    for (i = 0; i < PA_ELEMENTSOF(test_ints); i++) {
713        e = pa_json_object_get_array_member(v, i);
714
715        fail_unless(e != NULL);
716        fail_unless(pa_json_object_get_type(e) == PA_JSON_TYPE_INT);
717        fail_unless(pa_json_object_get_int(e) == test_ints[i]);
718    }
719
720    pa_json_object_free(o);
721}
722END_TEST
723
724START_TEST(encoder_member_raw_json_test) {
725    pa_json_object *o;
726    const pa_json_object *v;
727    const pa_json_object *e;
728    pa_json_encoder *encoder;
729    char *received;
730    pa_json_encoder *subobject;
731    char *subobject_string;
732
733    /* { "parameters": [1, "a", 2.0] } */
734
735    subobject = pa_json_encoder_new();
736    pa_json_encoder_begin_element_array(subobject);
737    pa_json_encoder_add_element_int(subobject, 1);
738    pa_json_encoder_add_element_string(subobject, "a");
739    pa_json_encoder_add_element_double(subobject, 2.0, 6);
740    pa_json_encoder_end_array(subobject);
741    subobject_string = pa_json_encoder_to_string_free(subobject);
742
743    encoder = pa_json_encoder_new();
744    pa_json_encoder_begin_element_object(encoder);
745
746    pa_json_encoder_add_member_raw_json(encoder, "parameters", subobject_string);
747    pa_xfree(subobject_string);
748
749    pa_json_encoder_end_object(encoder);
750
751    received = pa_json_encoder_to_string_free(encoder);
752    o = pa_json_parse(received);
753    pa_xfree(received);
754
755    fail_unless(o != NULL);
756    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
757
758    v = pa_json_object_get_object_member(o, "parameters");
759    fail_unless(v != NULL);
760    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_ARRAY);
761    fail_unless(pa_json_object_get_array_length(v) == 3);
762    e = pa_json_object_get_array_member(v, 0);
763    fail_unless(e != NULL);
764    fail_unless(pa_json_object_get_type(e) == PA_JSON_TYPE_INT);
765    fail_unless(pa_json_object_get_int(e) == 1);
766    e = pa_json_object_get_array_member(v, 1);
767    fail_unless(e != NULL);
768    fail_unless(pa_json_object_get_type(e) == PA_JSON_TYPE_STRING);
769    fail_unless(pa_streq(pa_json_object_get_string(e), "a"));
770    e = pa_json_object_get_array_member(v, 2);
771    fail_unless(e != NULL);
772    fail_unless(pa_json_object_get_type(e) == PA_JSON_TYPE_DOUBLE);
773    fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(e), 2.0));
774
775    pa_json_object_free(o);
776
777    /* { "parent": { "child": false } } */
778
779    subobject = pa_json_encoder_new();
780    pa_json_encoder_begin_element_object(subobject);
781    pa_json_encoder_add_member_bool(subobject, "child", false);
782    pa_json_encoder_end_object(subobject);
783    subobject_string = pa_json_encoder_to_string_free(subobject);
784
785    encoder = pa_json_encoder_new();
786    pa_json_encoder_begin_element_object(encoder);
787
788    pa_json_encoder_add_member_raw_json(encoder, "parent", subobject_string);
789    pa_xfree(subobject_string);
790
791    pa_json_encoder_end_object(encoder);
792
793    received = pa_json_encoder_to_string_free(encoder);
794    o = pa_json_parse(received);
795    pa_xfree(received);
796
797    fail_unless(o != NULL);
798    fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_OBJECT);
799
800    v = pa_json_object_get_object_member(o, "parent");
801    fail_unless(v != NULL);
802    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_OBJECT);
803    v = pa_json_object_get_object_member(v, "child");
804    fail_unless(pa_json_object_get_type(v) == PA_JSON_TYPE_BOOL);
805    fail_unless(pa_json_object_get_bool(v) == false);
806
807    pa_json_object_free(o);
808}
809END_TEST
810
811START_TEST(bad_test) {
812    unsigned int i;
813    const char *bad_parse[] = {
814        "\"" /* Quote not closed */,
815        "123456789012345678901234567890" /* Overflow */,
816#if 0   /* TODO: check rounding the value is OK */
817        "0.123456789012345678901234567890" /* Overflow */,
818#endif
819        "1e123456789012345678901234567890" /* Overflow */,
820        "1e-10000" /* Underflow */,
821        "1e" /* Bad number string */,
822        "1." /* Bad number string */,
823        "1.e3" /* Bad number string */,
824        "-" /* Bad number string */,
825        "{ \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": {  \"a\": { } } } } } } } } } } } } } } } } } } } } } }" /* Nested too deep */,
826        "[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ { \"a\": \"b\" } ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]" /* Nested too deep */,
827        "asdf" /* Unquoted string */,
828        "{ a: true }" /* Unquoted key in object */,
829        "\"    \a\"" /* Alarm is not a valid character */
830    };
831
832    for (i = 0; i < PA_ELEMENTSOF(bad_parse); i++) {
833        pa_json_object *obj;
834
835        fail_unless((obj = pa_json_parse(bad_parse[i])) == NULL);
836        if (obj)
837            pa_json_object_free(obj);
838    }
839}
840END_TEST
841
842int main(int argc, char *argv[]) {
843    int failed = 0;
844    Suite *s;
845    TCase *tc;
846    SRunner *sr;
847
848    s = suite_create("JSON");
849    tc = tcase_create("json");
850    tcase_add_test(tc, string_test);
851    tcase_add_test(tc, encoder_string_test);
852    tcase_add_test(tc, int_test);
853    tcase_add_test(tc, encoder_int_test);
854    tcase_add_test(tc, double_test);
855    tcase_add_test(tc, encoder_double_test);
856    tcase_add_test(tc, null_test);
857    tcase_add_test(tc, encoder_null_test);
858    tcase_add_test(tc, bool_test);
859    tcase_add_test(tc, encoder_bool_test);
860    tcase_add_test(tc, object_test);
861    tcase_add_test(tc, encoder_member_object_test);
862    tcase_add_test(tc, object_member_iterator_test);
863    tcase_add_test(tc, encoder_object_test);
864    tcase_add_test(tc, array_test);
865    tcase_add_test(tc, encoder_element_array_test);
866    tcase_add_test(tc, encoder_member_array_test);
867    tcase_add_test(tc, encoder_member_raw_json_test);
868    tcase_add_test(tc, bad_test);
869    suite_add_tcase(s, tc);
870
871    sr = srunner_create(s);
872    srunner_run_all(sr, CK_NORMAL);
873    failed = srunner_ntests_failed(sr);
874    srunner_free(sr);
875
876    return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
877}
878