]> rtime.felk.cvut.cz Git - lisovros/qemu_apohw.git/blob - tests/check-qjson.c
Support for Humusoft MF624 data acquisition card.
[lisovros/qemu_apohw.git] / tests / check-qjson.c
1 /*
2  * Copyright IBM, Corp. 2009
3  * Copyright (c) 2013 Red Hat Inc.
4  *
5  * Authors:
6  *  Anthony Liguori   <aliguori@us.ibm.com>
7  *  Markus Armbruster <armbru@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10  * See the COPYING.LIB file in the top-level directory.
11  *
12  */
13 #include <glib.h>
14
15 #include "qapi/qmp/qstring.h"
16 #include "qapi/qmp/qint.h"
17 #include "qapi/qmp/qdict.h"
18 #include "qapi/qmp/qlist.h"
19 #include "qapi/qmp/qfloat.h"
20 #include "qapi/qmp/qbool.h"
21 #include "qapi/qmp/qjson.h"
22
23 #include "qemu-common.h"
24
25 static void escaped_string(void)
26 {
27     int i;
28     struct {
29         const char *encoded;
30         const char *decoded;
31         int skip;
32     } test_cases[] = {
33         { "\"\\b\"", "\b" },
34         { "\"\\f\"", "\f" },
35         { "\"\\n\"", "\n" },
36         { "\"\\r\"", "\r" },
37         { "\"\\t\"", "\t" },
38         { "\"/\"", "/" },
39         { "\"\\/\"", "/", .skip = 1 },
40         { "\"\\\\\"", "\\" },
41         { "\"\\\"\"", "\"" },
42         { "\"hello world \\\"embedded string\\\"\"",
43           "hello world \"embedded string\"" },
44         { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
45         { "\"single byte utf-8 \\u0020\"", "single byte utf-8  ", .skip = 1 },
46         { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
47         { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
48         { "'\\b'", "\b", .skip = 1 },
49         { "'\\f'", "\f", .skip = 1 },
50         { "'\\n'", "\n", .skip = 1 },
51         { "'\\r'", "\r", .skip = 1 },
52         { "'\\t'", "\t", .skip = 1 },
53         { "'\\/'", "/", .skip = 1 },
54         { "'\\\\'", "\\", .skip = 1 },
55         {}
56     };
57
58     for (i = 0; test_cases[i].encoded; i++) {
59         QObject *obj;
60         QString *str;
61
62         obj = qobject_from_json(test_cases[i].encoded);
63
64         g_assert(obj != NULL);
65         g_assert(qobject_type(obj) == QTYPE_QSTRING);
66         
67         str = qobject_to_qstring(obj);
68         g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
69
70         if (test_cases[i].skip == 0) {
71             str = qobject_to_json(obj);
72             g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
73             qobject_decref(obj);
74         }
75
76         QDECREF(str);
77     }
78 }
79
80 static void simple_string(void)
81 {
82     int i;
83     struct {
84         const char *encoded;
85         const char *decoded;
86     } test_cases[] = {
87         { "\"hello world\"", "hello world" },
88         { "\"the quick brown fox jumped over the fence\"",
89           "the quick brown fox jumped over the fence" },
90         {}
91     };
92
93     for (i = 0; test_cases[i].encoded; i++) {
94         QObject *obj;
95         QString *str;
96
97         obj = qobject_from_json(test_cases[i].encoded);
98
99         g_assert(obj != NULL);
100         g_assert(qobject_type(obj) == QTYPE_QSTRING);
101         
102         str = qobject_to_qstring(obj);
103         g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
104
105         str = qobject_to_json(obj);
106         g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
107
108         qobject_decref(obj);
109         
110         QDECREF(str);
111     }
112 }
113
114 static void single_quote_string(void)
115 {
116     int i;
117     struct {
118         const char *encoded;
119         const char *decoded;
120     } test_cases[] = {
121         { "'hello world'", "hello world" },
122         { "'the quick brown fox \\' jumped over the fence'",
123           "the quick brown fox ' jumped over the fence" },
124         {}
125     };
126
127     for (i = 0; test_cases[i].encoded; i++) {
128         QObject *obj;
129         QString *str;
130
131         obj = qobject_from_json(test_cases[i].encoded);
132
133         g_assert(obj != NULL);
134         g_assert(qobject_type(obj) == QTYPE_QSTRING);
135         
136         str = qobject_to_qstring(obj);
137         g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
138
139         QDECREF(str);
140     }
141 }
142
143 static void utf8_string(void)
144 {
145     /*
146      * FIXME Current behavior for invalid UTF-8 sequences is
147      * incorrect.  This test expects current, incorrect results.
148      * They're all marked "bug:" below, and are to be replaced by
149      * correct ones as the bugs get fixed.
150      *
151      * The JSON parser rejects some invalid sequences, but accepts
152      * others without correcting the problem.
153      *
154      * We should either reject all invalid sequences, or minimize
155      * overlong sequences and replace all other invalid sequences by a
156      * suitable replacement character.  A common choice for
157      * replacement is U+FFFD.
158      *
159      * Problem: we can't easily deal with embedded U+0000.  Parsing
160      * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
161      * which gets misinterpreted as NUL-terminated "this ".  We should
162      * consider using overlong encoding \xC0\x80 for U+0000 ("modified
163      * UTF-8").
164      *
165      * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
166      * capability and stress test at
167      * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
168      */
169     static const struct {
170         const char *json_in;
171         const char *utf8_out;
172         const char *json_out;   /* defaults to @json_in */
173         const char *utf8_in;    /* defaults to @utf8_out */
174     } test_cases[] = {
175         /*
176          * Bug markers used here:
177          * - bug: not corrected
178          *   JSON parser fails to correct invalid sequence(s)
179          * - bug: rejected
180          *   JSON parser rejects invalid sequence(s)
181          *   We may choose to define this as feature
182          * - bug: want "..."
183          *   JSON parser produces incorrect result, this is the
184          *   correct one, assuming replacement character U+FFFF
185          *   We may choose to reject instead of replace
186          */
187
188         /* 1  Some correct UTF-8 text */
189         {
190             /* a bit of German */
191             "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
192             " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
193             "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
194             " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
195             "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
196             " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
197         },
198         {
199             /* a bit of Greek */
200             "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
201             "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
202             "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
203         },
204         /* 2  Boundary condition test cases */
205         /* 2.1  First possible sequence of a certain length */
206         /* 2.1.1  1 byte U+0000 */
207         {
208             "\"\\u0000\"",
209             "",                 /* bug: want overlong "\xC0\x80" */
210             "\"\\u0000\"",
211             "\xC0\x80",
212         },
213         /* 2.1.2  2 bytes U+0080 */
214         {
215             "\"\xC2\x80\"",
216             "\xC2\x80",
217             "\"\\u0080\"",
218         },
219         /* 2.1.3  3 bytes U+0800 */
220         {
221             "\"\xE0\xA0\x80\"",
222             "\xE0\xA0\x80",
223             "\"\\u0800\"",
224         },
225         /* 2.1.4  4 bytes U+10000 */
226         {
227             "\"\xF0\x90\x80\x80\"",
228             "\xF0\x90\x80\x80",
229             "\"\\uD800\\uDC00\"",
230         },
231         /* 2.1.5  5 bytes U+200000 */
232         {
233             "\"\xF8\x88\x80\x80\x80\"",
234             NULL,               /* bug: rejected */
235             "\"\\uFFFD\"",
236             "\xF8\x88\x80\x80\x80",
237         },
238         /* 2.1.6  6 bytes U+4000000 */
239         {
240             "\"\xFC\x84\x80\x80\x80\x80\"",
241             NULL,               /* bug: rejected */
242             "\"\\uFFFD\"",
243             "\xFC\x84\x80\x80\x80\x80",
244         },
245         /* 2.2  Last possible sequence of a certain length */
246         /* 2.2.1  1 byte U+007F */
247         {
248             "\"\x7F\"",
249             "\x7F",
250             "\"\\u007F\"",
251         },
252         /* 2.2.2  2 bytes U+07FF */
253         {
254             "\"\xDF\xBF\"",
255             "\xDF\xBF",
256             "\"\\u07FF\"",
257         },
258         /*
259          * 2.2.3  3 bytes U+FFFC
260          * The last possible sequence is actually U+FFFF.  But that's
261          * a noncharacter, and already covered by its own test case
262          * under 5.3.  Same for U+FFFE.  U+FFFD is the last character
263          * in the BMP, and covered under 2.3.  Because of U+FFFD's
264          * special role as replacement character, it's worth testing
265          * U+FFFC here.
266          */
267         {
268             "\"\xEF\xBF\xBC\"",
269             "\xEF\xBF\xBC",
270             "\"\\uFFFC\"",
271         },
272         /* 2.2.4  4 bytes U+1FFFFF */
273         {
274             "\"\xF7\xBF\xBF\xBF\"",
275             NULL,               /* bug: rejected */
276             "\"\\uFFFD\"",
277             "\xF7\xBF\xBF\xBF",
278         },
279         /* 2.2.5  5 bytes U+3FFFFFF */
280         {
281             "\"\xFB\xBF\xBF\xBF\xBF\"",
282             NULL,               /* bug: rejected */
283             "\"\\uFFFD\"",
284             "\xFB\xBF\xBF\xBF\xBF",
285         },
286         /* 2.2.6  6 bytes U+7FFFFFFF */
287         {
288             "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
289             NULL,               /* bug: rejected */
290             "\"\\uFFFD\"",
291             "\xFD\xBF\xBF\xBF\xBF\xBF",
292         },
293         /* 2.3  Other boundary conditions */
294         {
295             /* last one before surrogate range: U+D7FF */
296             "\"\xED\x9F\xBF\"",
297             "\xED\x9F\xBF",
298             "\"\\uD7FF\"",
299         },
300         {
301             /* first one after surrogate range: U+E000 */
302             "\"\xEE\x80\x80\"",
303             "\xEE\x80\x80",
304             "\"\\uE000\"",
305         },
306         {
307             /* last one in BMP: U+FFFD */
308             "\"\xEF\xBF\xBD\"",
309             "\xEF\xBF\xBD",
310             "\"\\uFFFD\"",
311         },
312         {
313             /* last one in last plane: U+10FFFD */
314             "\"\xF4\x8F\xBF\xBD\"",
315             "\xF4\x8F\xBF\xBD",
316             "\"\\uDBFF\\uDFFD\""
317         },
318         {
319             /* first one beyond Unicode range: U+110000 */
320             "\"\xF4\x90\x80\x80\"",
321             "\xF4\x90\x80\x80",
322             "\"\\uFFFD\"",
323         },
324         /* 3  Malformed sequences */
325         /* 3.1  Unexpected continuation bytes */
326         /* 3.1.1  First continuation byte */
327         {
328             "\"\x80\"",
329             "\x80",             /* bug: not corrected */
330             "\"\\uFFFD\"",
331         },
332         /* 3.1.2  Last continuation byte */
333         {
334             "\"\xBF\"",
335             "\xBF",             /* bug: not corrected */
336             "\"\\uFFFD\"",
337         },
338         /* 3.1.3  2 continuation bytes */
339         {
340             "\"\x80\xBF\"",
341             "\x80\xBF",         /* bug: not corrected */
342             "\"\\uFFFD\\uFFFD\"",
343         },
344         /* 3.1.4  3 continuation bytes */
345         {
346             "\"\x80\xBF\x80\"",
347             "\x80\xBF\x80",     /* bug: not corrected */
348             "\"\\uFFFD\\uFFFD\\uFFFD\"",
349         },
350         /* 3.1.5  4 continuation bytes */
351         {
352             "\"\x80\xBF\x80\xBF\"",
353             "\x80\xBF\x80\xBF", /* bug: not corrected */
354             "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
355         },
356         /* 3.1.6  5 continuation bytes */
357         {
358             "\"\x80\xBF\x80\xBF\x80\"",
359             "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
360             "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
361         },
362         /* 3.1.7  6 continuation bytes */
363         {
364             "\"\x80\xBF\x80\xBF\x80\xBF\"",
365             "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
366             "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
367         },
368         /* 3.1.8  7 continuation bytes */
369         {
370             "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
371             "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
372             "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
373         },
374         /* 3.1.9  Sequence of all 64 possible continuation bytes */
375         {
376             "\"\x80\x81\x82\x83\x84\x85\x86\x87"
377             "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
378             "\x90\x91\x92\x93\x94\x95\x96\x97"
379             "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
380             "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
381             "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
382             "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
383             "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
384              /* bug: not corrected */
385             "\x80\x81\x82\x83\x84\x85\x86\x87"
386             "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
387             "\x90\x91\x92\x93\x94\x95\x96\x97"
388             "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
389             "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
390             "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
391             "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
392             "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
393             "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
394             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
395             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
396             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
397             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
398             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
399             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
400             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
401         },
402         /* 3.2  Lonely start characters */
403         /* 3.2.1  All 32 first bytes of 2-byte sequences, followed by space */
404         {
405             "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
406             "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
407             "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
408             "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
409             NULL,               /* bug: rejected */
410             "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
411             "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
412             "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
413             "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
414             "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
415             "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
416             "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
417             "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
418         },
419         /* 3.2.2  All 16 first bytes of 3-byte sequences, followed by space */
420         {
421             "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
422             "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
423             /* bug: not corrected */
424             "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
425             "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
426             "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
427             "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
428         },
429         /* 3.2.3  All 8 first bytes of 4-byte sequences, followed by space */
430         {
431             "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
432             NULL,               /* bug: rejected */
433             "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
434             "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
435         },
436         /* 3.2.4  All 4 first bytes of 5-byte sequences, followed by space */
437         {
438             "\"\xF8 \xF9 \xFA \xFB \"",
439             NULL,               /* bug: rejected */
440             "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
441             "\xF8 \xF9 \xFA \xFB ",
442         },
443         /* 3.2.5  All 2 first bytes of 6-byte sequences, followed by space */
444         {
445             "\"\xFC \xFD \"",
446             NULL,               /* bug: rejected */
447             "\"\\uFFFD \\uFFFD \"",
448             "\xFC \xFD ",
449         },
450         /* 3.3  Sequences with last continuation byte missing */
451         /* 3.3.1  2-byte sequence with last byte missing (U+0000) */
452         {
453             "\"\xC0\"",
454             NULL,               /* bug: rejected */
455             "\"\\uFFFD\"",
456             "\xC0",
457         },
458         /* 3.3.2  3-byte sequence with last byte missing (U+0000) */
459         {
460             "\"\xE0\x80\"",
461             "\xE0\x80",           /* bug: not corrected */
462             "\"\\uFFFD\"",
463         },
464         /* 3.3.3  4-byte sequence with last byte missing (U+0000) */
465         {
466             "\"\xF0\x80\x80\"",
467             "\xF0\x80\x80",     /* bug: not corrected */
468             "\"\\uFFFD\"",
469         },
470         /* 3.3.4  5-byte sequence with last byte missing (U+0000) */
471         {
472             "\"\xF8\x80\x80\x80\"",
473             NULL,                   /* bug: rejected */
474             "\"\\uFFFD\"",
475             "\xF8\x80\x80\x80",
476         },
477         /* 3.3.5  6-byte sequence with last byte missing (U+0000) */
478         {
479             "\"\xFC\x80\x80\x80\x80\"",
480             NULL,                        /* bug: rejected */
481             "\"\\uFFFD\"",
482             "\xFC\x80\x80\x80\x80",
483         },
484         /* 3.3.6  2-byte sequence with last byte missing (U+07FF) */
485         {
486             "\"\xDF\"",
487             "\xDF",             /* bug: not corrected */
488             "\"\\uFFFD\"",
489         },
490         /* 3.3.7  3-byte sequence with last byte missing (U+FFFF) */
491         {
492             "\"\xEF\xBF\"",
493             "\xEF\xBF",           /* bug: not corrected */
494             "\"\\uFFFD\"",
495         },
496         /* 3.3.8  4-byte sequence with last byte missing (U+1FFFFF) */
497         {
498             "\"\xF7\xBF\xBF\"",
499             NULL,               /* bug: rejected */
500             "\"\\uFFFD\"",
501             "\xF7\xBF\xBF",
502         },
503         /* 3.3.9  5-byte sequence with last byte missing (U+3FFFFFF) */
504         {
505             "\"\xFB\xBF\xBF\xBF\"",
506             NULL,                 /* bug: rejected */
507             "\"\\uFFFD\"",
508             "\xFB\xBF\xBF\xBF",
509         },
510         /* 3.3.10  6-byte sequence with last byte missing (U+7FFFFFFF) */
511         {
512             "\"\xFD\xBF\xBF\xBF\xBF\"",
513             NULL,                        /* bug: rejected */
514             "\"\\uFFFD\"",
515             "\xFD\xBF\xBF\xBF\xBF",
516         },
517         /* 3.4  Concatenation of incomplete sequences */
518         {
519             "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
520             "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
521             NULL,               /* bug: rejected */
522             "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
523             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
524             "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
525             "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
526         },
527         /* 3.5  Impossible bytes */
528         {
529             "\"\xFE\"",
530             NULL,               /* bug: rejected */
531             "\"\\uFFFD\"",
532             "\xFE",
533         },
534         {
535             "\"\xFF\"",
536             NULL,               /* bug: rejected */
537             "\"\\uFFFD\"",
538             "\xFF",
539         },
540         {
541             "\"\xFE\xFE\xFF\xFF\"",
542             NULL,                 /* bug: rejected */
543             "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
544             "\xFE\xFE\xFF\xFF",
545         },
546         /* 4  Overlong sequences */
547         /* 4.1  Overlong '/' */
548         {
549             "\"\xC0\xAF\"",
550             NULL,               /* bug: rejected */
551             "\"\\uFFFD\"",
552             "\xC0\xAF",
553         },
554         {
555             "\"\xE0\x80\xAF\"",
556             "\xE0\x80\xAF",     /* bug: not corrected */
557             "\"\\uFFFD\"",
558         },
559         {
560             "\"\xF0\x80\x80\xAF\"",
561             "\xF0\x80\x80\xAF",  /* bug: not corrected */
562             "\"\\uFFFD\"",
563         },
564         {
565             "\"\xF8\x80\x80\x80\xAF\"",
566             NULL,                        /* bug: rejected */
567             "\"\\uFFFD\"",
568             "\xF8\x80\x80\x80\xAF",
569         },
570         {
571             "\"\xFC\x80\x80\x80\x80\xAF\"",
572             NULL,                               /* bug: rejected */
573             "\"\\uFFFD\"",
574             "\xFC\x80\x80\x80\x80\xAF",
575         },
576         /*
577          * 4.2  Maximum overlong sequences
578          * Highest Unicode value that is still resulting in an
579          * overlong sequence if represented with the given number of
580          * bytes.  This is a boundary test for safe UTF-8 decoders.
581          */
582         {
583             /* \U+007F */
584             "\"\xC1\xBF\"",
585             NULL,               /* bug: rejected */
586             "\"\\uFFFD\"",
587             "\xC1\xBF",
588         },
589         {
590             /* \U+07FF */
591             "\"\xE0\x9F\xBF\"",
592             "\xE0\x9F\xBF",     /* bug: not corrected */
593             "\"\\uFFFD\"",
594         },
595         {
596             /*
597              * \U+FFFC
598              * The actual maximum would be U+FFFF, but that's a
599              * noncharacter.  Testing U+FFFC seems more useful.  See
600              * also 2.2.3
601              */
602             "\"\xF0\x8F\xBF\xBC\"",
603             "\xF0\x8F\xBF\xBC",   /* bug: not corrected */
604             "\"\\uFFFD\"",
605         },
606         {
607             /* \U+1FFFFF */
608             "\"\xF8\x87\xBF\xBF\xBF\"",
609             NULL,                        /* bug: rejected */
610             "\"\\uFFFD\"",
611             "\xF8\x87\xBF\xBF\xBF",
612         },
613         {
614             /* \U+3FFFFFF */
615             "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
616             NULL,                               /* bug: rejected */
617             "\"\\uFFFD\"",
618             "\xFC\x83\xBF\xBF\xBF\xBF",
619         },
620         /* 4.3  Overlong representation of the NUL character */
621         {
622             /* \U+0000 */
623             "\"\xC0\x80\"",
624             NULL,               /* bug: rejected */
625             "\"\\u0000\"",
626             "\xC0\x80",
627         },
628         {
629             /* \U+0000 */
630             "\"\xE0\x80\x80\"",
631             "\xE0\x80\x80",     /* bug: not corrected */
632             "\"\\uFFFD\"",
633         },
634         {
635             /* \U+0000 */
636             "\"\xF0\x80\x80\x80\"",
637             "\xF0\x80\x80\x80",   /* bug: not corrected */
638             "\"\\uFFFD\"",
639         },
640         {
641             /* \U+0000 */
642             "\"\xF8\x80\x80\x80\x80\"",
643             NULL,                        /* bug: rejected */
644             "\"\\uFFFD\"",
645             "\xF8\x80\x80\x80\x80",
646         },
647         {
648             /* \U+0000 */
649             "\"\xFC\x80\x80\x80\x80\x80\"",
650             NULL,                               /* bug: rejected */
651             "\"\\uFFFD\"",
652             "\xFC\x80\x80\x80\x80\x80",
653         },
654         /* 5  Illegal code positions */
655         /* 5.1  Single UTF-16 surrogates */
656         {
657             /* \U+D800 */
658             "\"\xED\xA0\x80\"",
659             "\xED\xA0\x80",     /* bug: not corrected */
660             "\"\\uFFFD\"",
661         },
662         {
663             /* \U+DB7F */
664             "\"\xED\xAD\xBF\"",
665             "\xED\xAD\xBF",     /* bug: not corrected */
666             "\"\\uFFFD\"",
667         },
668         {
669             /* \U+DB80 */
670             "\"\xED\xAE\x80\"",
671             "\xED\xAE\x80",     /* bug: not corrected */
672             "\"\\uFFFD\"",
673         },
674         {
675             /* \U+DBFF */
676             "\"\xED\xAF\xBF\"",
677             "\xED\xAF\xBF",     /* bug: not corrected */
678             "\"\\uFFFD\"",
679         },
680         {
681             /* \U+DC00 */
682             "\"\xED\xB0\x80\"",
683             "\xED\xB0\x80",     /* bug: not corrected */
684             "\"\\uFFFD\"",
685         },
686         {
687             /* \U+DF80 */
688             "\"\xED\xBE\x80\"",
689             "\xED\xBE\x80",     /* bug: not corrected */
690             "\"\\uFFFD\"",
691         },
692         {
693             /* \U+DFFF */
694             "\"\xED\xBF\xBF\"",
695             "\xED\xBF\xBF",     /* bug: not corrected */
696             "\"\\uFFFD\"",
697         },
698         /* 5.2  Paired UTF-16 surrogates */
699         {
700             /* \U+D800\U+DC00 */
701             "\"\xED\xA0\x80\xED\xB0\x80\"",
702             "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
703             "\"\\uFFFD\\uFFFD\"",
704         },
705         {
706             /* \U+D800\U+DFFF */
707             "\"\xED\xA0\x80\xED\xBF\xBF\"",
708             "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
709             "\"\\uFFFD\\uFFFD\"",
710         },
711         {
712             /* \U+DB7F\U+DC00 */
713             "\"\xED\xAD\xBF\xED\xB0\x80\"",
714             "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
715             "\"\\uFFFD\\uFFFD\"",
716         },
717         {
718             /* \U+DB7F\U+DFFF */
719             "\"\xED\xAD\xBF\xED\xBF\xBF\"",
720             "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
721             "\"\\uFFFD\\uFFFD\"",
722         },
723         {
724             /* \U+DB80\U+DC00 */
725             "\"\xED\xAE\x80\xED\xB0\x80\"",
726             "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
727             "\"\\uFFFD\\uFFFD\"",
728         },
729         {
730             /* \U+DB80\U+DFFF */
731             "\"\xED\xAE\x80\xED\xBF\xBF\"",
732             "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
733             "\"\\uFFFD\\uFFFD\"",
734         },
735         {
736             /* \U+DBFF\U+DC00 */
737             "\"\xED\xAF\xBF\xED\xB0\x80\"",
738             "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
739             "\"\\uFFFD\\uFFFD\"",
740         },
741         {
742             /* \U+DBFF\U+DFFF */
743             "\"\xED\xAF\xBF\xED\xBF\xBF\"",
744             "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
745             "\"\\uFFFD\\uFFFD\"",
746         },
747         /* 5.3  Other illegal code positions */
748         /* BMP noncharacters */
749         {
750             /* \U+FFFE */
751             "\"\xEF\xBF\xBE\"",
752             "\xEF\xBF\xBE",     /* bug: not corrected */
753             "\"\\uFFFD\"",
754         },
755         {
756             /* \U+FFFF */
757             "\"\xEF\xBF\xBF\"",
758             "\xEF\xBF\xBF",     /* bug: not corrected */
759             "\"\\uFFFD\"",
760         },
761         {
762             /* U+FDD0 */
763             "\"\xEF\xB7\x90\"",
764             "\xEF\xB7\x90",     /* bug: not corrected */
765             "\"\\uFFFD\"",
766         },
767         {
768             /* U+FDEF */
769             "\"\xEF\xB7\xAF\"",
770             "\xEF\xB7\xAF",     /* bug: not corrected */
771             "\"\\uFFFD\"",
772         },
773         /* Plane 1 .. 16 noncharacters */
774         {
775             /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
776             "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
777             "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
778             "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
779             "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
780             "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
781             "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
782             "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
783             "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
784             "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
785             "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
786             "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
787             "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
788             "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
789             "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
790             "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
791             "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
792             /* bug: not corrected */
793             "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
794             "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
795             "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
796             "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
797             "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
798             "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
799             "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
800             "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
801             "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
802             "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
803             "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
804             "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
805             "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
806             "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
807             "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
808             "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
809             "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
810             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
811             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
812             "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
813         },
814         {}
815     };
816     int i;
817     QObject *obj;
818     QString *str;
819     const char *json_in, *utf8_out, *utf8_in, *json_out;
820
821     for (i = 0; test_cases[i].json_in; i++) {
822         json_in = test_cases[i].json_in;
823         utf8_out = test_cases[i].utf8_out;
824         utf8_in = test_cases[i].utf8_in ?: test_cases[i].utf8_out;
825         json_out = test_cases[i].json_out ?: test_cases[i].json_in;
826
827         obj = qobject_from_json(json_in);
828         if (utf8_out) {
829             g_assert(obj);
830             g_assert(qobject_type(obj) == QTYPE_QSTRING);
831             str = qobject_to_qstring(obj);
832             g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
833         } else {
834             g_assert(!obj);
835         }
836         qobject_decref(obj);
837
838         obj = QOBJECT(qstring_from_str(utf8_in));
839         str = qobject_to_json(obj);
840         if (json_out) {
841             g_assert(str);
842             g_assert_cmpstr(qstring_get_str(str), ==, json_out);
843         } else {
844             g_assert(!str);
845         }
846         QDECREF(str);
847         qobject_decref(obj);
848
849         /*
850          * Disabled, because qobject_from_json() is buggy, and I can't
851          * be bothered to add the expected incorrect results.
852          * FIXME Enable once these bugs have been fixed.
853          */
854         if (0 && json_out != json_in) {
855             obj = qobject_from_json(json_out);
856             g_assert(obj);
857             g_assert(qobject_type(obj) == QTYPE_QSTRING);
858             str = qobject_to_qstring(obj);
859             g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
860         }
861     }
862 }
863
864 static void vararg_string(void)
865 {
866     int i;
867     struct {
868         const char *decoded;
869     } test_cases[] = {
870         { "hello world" },
871         { "the quick brown fox jumped over the fence" },
872         {}
873     };
874
875     for (i = 0; test_cases[i].decoded; i++) {
876         QObject *obj;
877         QString *str;
878
879         obj = qobject_from_jsonf("%s", test_cases[i].decoded);
880
881         g_assert(obj != NULL);
882         g_assert(qobject_type(obj) == QTYPE_QSTRING);
883         
884         str = qobject_to_qstring(obj);
885         g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
886
887         QDECREF(str);
888     }
889 }
890
891 static void simple_number(void)
892 {
893     int i;
894     struct {
895         const char *encoded;
896         int64_t decoded;
897         int skip;
898     } test_cases[] = {
899         { "0", 0 },
900         { "1234", 1234 },
901         { "1", 1 },
902         { "-32", -32 },
903         { "-0", 0, .skip = 1 },
904         { },
905     };
906
907     for (i = 0; test_cases[i].encoded; i++) {
908         QObject *obj;
909         QInt *qint;
910
911         obj = qobject_from_json(test_cases[i].encoded);
912         g_assert(obj != NULL);
913         g_assert(qobject_type(obj) == QTYPE_QINT);
914
915         qint = qobject_to_qint(obj);
916         g_assert(qint_get_int(qint) == test_cases[i].decoded);
917         if (test_cases[i].skip == 0) {
918             QString *str;
919
920             str = qobject_to_json(obj);
921             g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
922             QDECREF(str);
923         }
924
925         QDECREF(qint);
926     }
927 }
928
929 static void float_number(void)
930 {
931     int i;
932     struct {
933         const char *encoded;
934         double decoded;
935         int skip;
936     } test_cases[] = {
937         { "32.43", 32.43 },
938         { "0.222", 0.222 },
939         { "-32.12313", -32.12313 },
940         { "-32.20e-10", -32.20e-10, .skip = 1 },
941         { },
942     };
943
944     for (i = 0; test_cases[i].encoded; i++) {
945         QObject *obj;
946         QFloat *qfloat;
947
948         obj = qobject_from_json(test_cases[i].encoded);
949         g_assert(obj != NULL);
950         g_assert(qobject_type(obj) == QTYPE_QFLOAT);
951
952         qfloat = qobject_to_qfloat(obj);
953         g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
954
955         if (test_cases[i].skip == 0) {
956             QString *str;
957
958             str = qobject_to_json(obj);
959             g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
960             QDECREF(str);
961         }
962
963         QDECREF(qfloat);
964     }
965 }
966
967 static void vararg_number(void)
968 {
969     QObject *obj;
970     QInt *qint;
971     QFloat *qfloat;
972     int value = 0x2342;
973     int64_t value64 = 0x2342342343LL;
974     double valuef = 2.323423423;
975
976     obj = qobject_from_jsonf("%d", value);
977     g_assert(obj != NULL);
978     g_assert(qobject_type(obj) == QTYPE_QINT);
979
980     qint = qobject_to_qint(obj);
981     g_assert(qint_get_int(qint) == value);
982
983     QDECREF(qint);
984
985     obj = qobject_from_jsonf("%" PRId64, value64);
986     g_assert(obj != NULL);
987     g_assert(qobject_type(obj) == QTYPE_QINT);
988
989     qint = qobject_to_qint(obj);
990     g_assert(qint_get_int(qint) == value64);
991
992     QDECREF(qint);
993
994     obj = qobject_from_jsonf("%f", valuef);
995     g_assert(obj != NULL);
996     g_assert(qobject_type(obj) == QTYPE_QFLOAT);
997
998     qfloat = qobject_to_qfloat(obj);
999     g_assert(qfloat_get_double(qfloat) == valuef);
1000
1001     QDECREF(qfloat);
1002 }
1003
1004 static void keyword_literal(void)
1005 {
1006     QObject *obj;
1007     QBool *qbool;
1008     QString *str;
1009
1010     obj = qobject_from_json("true");
1011     g_assert(obj != NULL);
1012     g_assert(qobject_type(obj) == QTYPE_QBOOL);
1013
1014     qbool = qobject_to_qbool(obj);
1015     g_assert(qbool_get_int(qbool) != 0);
1016
1017     str = qobject_to_json(obj);
1018     g_assert(strcmp(qstring_get_str(str), "true") == 0);
1019     QDECREF(str);
1020
1021     QDECREF(qbool);
1022
1023     obj = qobject_from_json("false");
1024     g_assert(obj != NULL);
1025     g_assert(qobject_type(obj) == QTYPE_QBOOL);
1026
1027     qbool = qobject_to_qbool(obj);
1028     g_assert(qbool_get_int(qbool) == 0);
1029
1030     str = qobject_to_json(obj);
1031     g_assert(strcmp(qstring_get_str(str), "false") == 0);
1032     QDECREF(str);
1033
1034     QDECREF(qbool);
1035
1036     obj = qobject_from_jsonf("%i", false);
1037     g_assert(obj != NULL);
1038     g_assert(qobject_type(obj) == QTYPE_QBOOL);
1039
1040     qbool = qobject_to_qbool(obj);
1041     g_assert(qbool_get_int(qbool) == 0);
1042
1043     QDECREF(qbool);
1044     
1045     obj = qobject_from_jsonf("%i", true);
1046     g_assert(obj != NULL);
1047     g_assert(qobject_type(obj) == QTYPE_QBOOL);
1048
1049     qbool = qobject_to_qbool(obj);
1050     g_assert(qbool_get_int(qbool) != 0);
1051
1052     QDECREF(qbool);
1053 }
1054
1055 typedef struct LiteralQDictEntry LiteralQDictEntry;
1056 typedef struct LiteralQObject LiteralQObject;
1057
1058 struct LiteralQObject
1059 {
1060     int type;
1061     union {
1062         int64_t qint;
1063         const char *qstr;
1064         LiteralQDictEntry *qdict;
1065         LiteralQObject *qlist;
1066     } value;
1067 };
1068
1069 struct LiteralQDictEntry
1070 {
1071     const char *key;
1072     LiteralQObject value;
1073 };
1074
1075 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1076 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1077 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1078 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1079
1080 typedef struct QListCompareHelper
1081 {
1082     int index;
1083     LiteralQObject *objs;
1084     int result;
1085 } QListCompareHelper;
1086
1087 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1088
1089 static void compare_helper(QObject *obj, void *opaque)
1090 {
1091     QListCompareHelper *helper = opaque;
1092
1093     if (helper->result == 0) {
1094         return;
1095     }
1096
1097     if (helper->objs[helper->index].type == QTYPE_NONE) {
1098         helper->result = 0;
1099         return;
1100     }
1101
1102     helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1103 }
1104
1105 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1106 {
1107     if (lhs->type != qobject_type(rhs)) {
1108         return 0;
1109     }
1110
1111     switch (lhs->type) {
1112     case QTYPE_QINT:
1113         return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
1114     case QTYPE_QSTRING:
1115         return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1116     case QTYPE_QDICT: {
1117         int i;
1118
1119         for (i = 0; lhs->value.qdict[i].key; i++) {
1120             QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1121
1122             if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1123                 return 0;
1124             }
1125         }
1126
1127         return 1;
1128     }
1129     case QTYPE_QLIST: {
1130         QListCompareHelper helper;
1131
1132         helper.index = 0;
1133         helper.objs = lhs->value.qlist;
1134         helper.result = 1;
1135         
1136         qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1137
1138         return helper.result;
1139     }
1140     default:
1141         break;
1142     }
1143
1144     return 0;
1145 }
1146
1147 static void simple_dict(void)
1148 {
1149     int i;
1150     struct {
1151         const char *encoded;
1152         LiteralQObject decoded;
1153     } test_cases[] = {
1154         {
1155             .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1156             .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1157                         { "foo", QLIT_QINT(42) },
1158                         { "bar", QLIT_QSTR("hello world") },
1159                         { }
1160                     })),
1161         }, {
1162             .encoded = "{}",
1163             .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1164                         { }
1165                     })),
1166         }, {
1167             .encoded = "{\"foo\": 43}",
1168             .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1169                         { "foo", QLIT_QINT(43) },
1170                         { }
1171                     })),
1172         },
1173         { }
1174     };
1175
1176     for (i = 0; test_cases[i].encoded; i++) {
1177         QObject *obj;
1178         QString *str;
1179
1180         obj = qobject_from_json(test_cases[i].encoded);
1181         g_assert(obj != NULL);
1182         g_assert(qobject_type(obj) == QTYPE_QDICT);
1183
1184         g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1185
1186         str = qobject_to_json(obj);
1187         qobject_decref(obj);
1188
1189         obj = qobject_from_json(qstring_get_str(str));
1190         g_assert(obj != NULL);
1191         g_assert(qobject_type(obj) == QTYPE_QDICT);
1192
1193         g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1194         qobject_decref(obj);
1195         QDECREF(str);
1196     }
1197 }
1198
1199 /*
1200  * this generates json of the form:
1201  * a(0,m) = [0, 1, ..., m-1]
1202  * a(n,m) = {
1203  *            'key0': a(0,m),
1204  *            'key1': a(1,m),
1205  *            ...
1206  *            'key(n-1)': a(n-1,m)
1207  *          }
1208  */
1209 static void gen_test_json(GString *gstr, int nest_level_max,
1210                           int elem_count)
1211 {
1212     int i;
1213
1214     g_assert(gstr);
1215     if (nest_level_max == 0) {
1216         g_string_append(gstr, "[");
1217         for (i = 0; i < elem_count; i++) {
1218             g_string_append_printf(gstr, "%d", i);
1219             if (i < elem_count - 1) {
1220                 g_string_append_printf(gstr, ", ");
1221             }
1222         }
1223         g_string_append(gstr, "]");
1224         return;
1225     }
1226
1227     g_string_append(gstr, "{");
1228     for (i = 0; i < nest_level_max; i++) {
1229         g_string_append_printf(gstr, "'key%d': ", i);
1230         gen_test_json(gstr, i, elem_count);
1231         if (i < nest_level_max - 1) {
1232             g_string_append(gstr, ",");
1233         }
1234     }
1235     g_string_append(gstr, "}");
1236 }
1237
1238 static void large_dict(void)
1239 {
1240     GString *gstr = g_string_new("");
1241     QObject *obj;
1242
1243     gen_test_json(gstr, 10, 100);
1244     obj = qobject_from_json(gstr->str);
1245     g_assert(obj != NULL);
1246
1247     qobject_decref(obj);
1248     g_string_free(gstr, true);
1249 }
1250
1251 static void simple_list(void)
1252 {
1253     int i;
1254     struct {
1255         const char *encoded;
1256         LiteralQObject decoded;
1257     } test_cases[] = {
1258         {
1259             .encoded = "[43,42]",
1260             .decoded = QLIT_QLIST(((LiteralQObject[]){
1261                         QLIT_QINT(43),
1262                         QLIT_QINT(42),
1263                         { }
1264                     })),
1265         },
1266         {
1267             .encoded = "[43]",
1268             .decoded = QLIT_QLIST(((LiteralQObject[]){
1269                         QLIT_QINT(43),
1270                         { }
1271                     })),
1272         },
1273         {
1274             .encoded = "[]",
1275             .decoded = QLIT_QLIST(((LiteralQObject[]){
1276                         { }
1277                     })),
1278         },
1279         {
1280             .encoded = "[{}]",
1281             .decoded = QLIT_QLIST(((LiteralQObject[]){
1282                         QLIT_QDICT(((LiteralQDictEntry[]){
1283                                     {},
1284                                         })),
1285                         {},
1286                             })),
1287         },
1288         { }
1289     };
1290
1291     for (i = 0; test_cases[i].encoded; i++) {
1292         QObject *obj;
1293         QString *str;
1294
1295         obj = qobject_from_json(test_cases[i].encoded);
1296         g_assert(obj != NULL);
1297         g_assert(qobject_type(obj) == QTYPE_QLIST);
1298
1299         g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1300
1301         str = qobject_to_json(obj);
1302         qobject_decref(obj);
1303
1304         obj = qobject_from_json(qstring_get_str(str));
1305         g_assert(obj != NULL);
1306         g_assert(qobject_type(obj) == QTYPE_QLIST);
1307
1308         g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1309         qobject_decref(obj);
1310         QDECREF(str);
1311     }
1312 }
1313
1314 static void simple_whitespace(void)
1315 {
1316     int i;
1317     struct {
1318         const char *encoded;
1319         LiteralQObject decoded;
1320     } test_cases[] = {
1321         {
1322             .encoded = " [ 43 , 42 ]",
1323             .decoded = QLIT_QLIST(((LiteralQObject[]){
1324                         QLIT_QINT(43),
1325                         QLIT_QINT(42),
1326                         { }
1327                     })),
1328         },
1329         {
1330             .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1331             .decoded = QLIT_QLIST(((LiteralQObject[]){
1332                         QLIT_QINT(43),
1333                         QLIT_QDICT(((LiteralQDictEntry[]){
1334                                     { "h", QLIT_QSTR("b") },
1335                                     { }})),
1336                         QLIT_QLIST(((LiteralQObject[]){
1337                                     { }})),
1338                         QLIT_QINT(42),
1339                         { }
1340                     })),
1341         },
1342         {
1343             .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1344             .decoded = QLIT_QLIST(((LiteralQObject[]){
1345                         QLIT_QINT(43),
1346                         QLIT_QDICT(((LiteralQDictEntry[]){
1347                                     { "h", QLIT_QSTR("b") },
1348                                     { "a", QLIT_QINT(32) },
1349                                     { }})),
1350                         QLIT_QLIST(((LiteralQObject[]){
1351                                     { }})),
1352                         QLIT_QINT(42),
1353                         { }
1354                     })),
1355         },
1356         { }
1357     };
1358
1359     for (i = 0; test_cases[i].encoded; i++) {
1360         QObject *obj;
1361         QString *str;
1362
1363         obj = qobject_from_json(test_cases[i].encoded);
1364         g_assert(obj != NULL);
1365         g_assert(qobject_type(obj) == QTYPE_QLIST);
1366
1367         g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1368
1369         str = qobject_to_json(obj);
1370         qobject_decref(obj);
1371
1372         obj = qobject_from_json(qstring_get_str(str));
1373         g_assert(obj != NULL);
1374         g_assert(qobject_type(obj) == QTYPE_QLIST);
1375
1376         g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1377
1378         qobject_decref(obj);
1379         QDECREF(str);
1380     }
1381 }
1382
1383 static void simple_varargs(void)
1384 {
1385     QObject *embedded_obj;
1386     QObject *obj;
1387     LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1388             QLIT_QINT(1),
1389             QLIT_QINT(2),
1390             QLIT_QLIST(((LiteralQObject[]){
1391                         QLIT_QINT(32),
1392                         QLIT_QINT(42),
1393                         {}})),
1394             {}}));
1395
1396     embedded_obj = qobject_from_json("[32, 42]");
1397     g_assert(embedded_obj != NULL);
1398
1399     obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1400     g_assert(obj != NULL);
1401
1402     g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1403
1404     qobject_decref(obj);
1405 }
1406
1407 static void empty_input(void)
1408 {
1409     const char *empty = "";
1410
1411     QObject *obj = qobject_from_json(empty);
1412     g_assert(obj == NULL);
1413 }
1414
1415 static void unterminated_string(void)
1416 {
1417     QObject *obj = qobject_from_json("\"abc");
1418     g_assert(obj == NULL);
1419 }
1420
1421 static void unterminated_sq_string(void)
1422 {
1423     QObject *obj = qobject_from_json("'abc");
1424     g_assert(obj == NULL);
1425 }
1426
1427 static void unterminated_escape(void)
1428 {
1429     QObject *obj = qobject_from_json("\"abc\\\"");
1430     g_assert(obj == NULL);
1431 }
1432
1433 static void unterminated_array(void)
1434 {
1435     QObject *obj = qobject_from_json("[32");
1436     g_assert(obj == NULL);
1437 }
1438
1439 static void unterminated_array_comma(void)
1440 {
1441     QObject *obj = qobject_from_json("[32,");
1442     g_assert(obj == NULL);
1443 }
1444
1445 static void invalid_array_comma(void)
1446 {
1447     QObject *obj = qobject_from_json("[32,}");
1448     g_assert(obj == NULL);
1449 }
1450
1451 static void unterminated_dict(void)
1452 {
1453     QObject *obj = qobject_from_json("{'abc':32");
1454     g_assert(obj == NULL);
1455 }
1456
1457 static void unterminated_dict_comma(void)
1458 {
1459     QObject *obj = qobject_from_json("{'abc':32,");
1460     g_assert(obj == NULL);
1461 }
1462
1463 static void invalid_dict_comma(void)
1464 {
1465     QObject *obj = qobject_from_json("{'abc':32,}");
1466     g_assert(obj == NULL);
1467 }
1468
1469 static void unterminated_literal(void)
1470 {
1471     QObject *obj = qobject_from_json("nul");
1472     g_assert(obj == NULL);
1473 }
1474
1475 int main(int argc, char **argv)
1476 {
1477     g_test_init(&argc, &argv, NULL);
1478
1479     g_test_add_func("/literals/string/simple", simple_string);
1480     g_test_add_func("/literals/string/escaped", escaped_string);
1481     g_test_add_func("/literals/string/utf8", utf8_string);
1482     g_test_add_func("/literals/string/single_quote", single_quote_string);
1483     g_test_add_func("/literals/string/vararg", vararg_string);
1484
1485     g_test_add_func("/literals/number/simple", simple_number);
1486     g_test_add_func("/literals/number/float", float_number);
1487     g_test_add_func("/literals/number/vararg", vararg_number);
1488
1489     g_test_add_func("/literals/keyword", keyword_literal);
1490
1491     g_test_add_func("/dicts/simple_dict", simple_dict);
1492     g_test_add_func("/dicts/large_dict", large_dict);
1493     g_test_add_func("/lists/simple_list", simple_list);
1494
1495     g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1496
1497     g_test_add_func("/varargs/simple_varargs", simple_varargs);
1498
1499     g_test_add_func("/errors/empty_input", empty_input);
1500     g_test_add_func("/errors/unterminated/string", unterminated_string);
1501     g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1502     g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1503     g_test_add_func("/errors/unterminated/array", unterminated_array);
1504     g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1505     g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1506     g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1507     g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1508     g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1509     g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1510
1511     return g_test_run();
1512 }