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