]> Git Repo - qemu.git/blob - tests/check-qjson.c
qapi: Replace qobject_to_X(o) by qobject_to(X, o)
[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,
868                          qobject_from_jsonf("%s", 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,
897                           qobject_from_json(test_cases[i].encoded,
898                                             &error_abort));
899         g_assert(qnum);
900         g_assert(qnum_get_try_int(qnum, &val));
901         g_assert_cmpint(val, ==, test_cases[i].decoded);
902         if (test_cases[i].skip == 0) {
903             QString *str;
904
905             str = qobject_to_json(QOBJECT(qnum));
906             g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
907             QDECREF(str);
908         }
909
910         QDECREF(qnum);
911     }
912 }
913
914 static void large_number(void)
915 {
916     const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
917     const char *gtu64 = "18446744073709551616"; /* 2^64 */
918     const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
919     QNum *qnum;
920     QString *str;
921     uint64_t val;
922     int64_t ival;
923
924     qnum = qobject_to(QNum, qobject_from_json(maxu64, &error_abort));
925     g_assert(qnum);
926     g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
927     g_assert(!qnum_get_try_int(qnum, &ival));
928
929     str = qobject_to_json(QOBJECT(qnum));
930     g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
931     QDECREF(str);
932     QDECREF(qnum);
933
934     qnum = qobject_to(QNum, qobject_from_json(gtu64, &error_abort));
935     g_assert(qnum);
936     g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
937     g_assert(!qnum_get_try_uint(qnum, &val));
938     g_assert(!qnum_get_try_int(qnum, &ival));
939
940     str = qobject_to_json(QOBJECT(qnum));
941     g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
942     QDECREF(str);
943     QDECREF(qnum);
944
945     qnum = qobject_to(QNum, qobject_from_json(lti64, &error_abort));
946     g_assert(qnum);
947     g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
948     g_assert(!qnum_get_try_uint(qnum, &val));
949     g_assert(!qnum_get_try_int(qnum, &ival));
950
951     str = qobject_to_json(QOBJECT(qnum));
952     g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
953     QDECREF(str);
954     QDECREF(qnum);
955 }
956
957 static void float_number(void)
958 {
959     int i;
960     struct {
961         const char *encoded;
962         double decoded;
963         int skip;
964     } test_cases[] = {
965         { "32.43", 32.43 },
966         { "0.222", 0.222 },
967         { "-32.12313", -32.12313 },
968         { "-32.20e-10", -32.20e-10, .skip = 1 },
969         { },
970     };
971
972     for (i = 0; test_cases[i].encoded; i++) {
973         QObject *obj;
974         QNum *qnum;
975
976         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
977         qnum = qobject_to(QNum, obj);
978         g_assert(qnum);
979         g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
980
981         if (test_cases[i].skip == 0) {
982             QString *str;
983
984             str = qobject_to_json(obj);
985             g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
986             QDECREF(str);
987         }
988
989         QDECREF(qnum);
990     }
991 }
992
993 static void vararg_number(void)
994 {
995     QNum *qnum;
996     int value = 0x2342;
997     long long value_ll = 0x2342342343LL;
998     double valuef = 2.323423423;
999     int64_t val;
1000
1001     qnum = qobject_to(QNum, qobject_from_jsonf("%d", value));
1002     g_assert(qnum_get_try_int(qnum, &val));
1003     g_assert_cmpint(val, ==, value);
1004     QDECREF(qnum);
1005
1006     qnum = qobject_to(QNum, qobject_from_jsonf("%lld", value_ll));
1007     g_assert(qnum_get_try_int(qnum, &val));
1008     g_assert_cmpint(val, ==, value_ll);
1009     QDECREF(qnum);
1010
1011     qnum = qobject_to(QNum, qobject_from_jsonf("%f", valuef));
1012     g_assert(qnum_get_double(qnum) == valuef);
1013     QDECREF(qnum);
1014 }
1015
1016 static void keyword_literal(void)
1017 {
1018     QObject *obj;
1019     QBool *qbool;
1020     QNull *null;
1021     QString *str;
1022
1023     obj = qobject_from_json("true", &error_abort);
1024     qbool = qobject_to(QBool, obj);
1025     g_assert(qbool);
1026     g_assert(qbool_get_bool(qbool) == true);
1027
1028     str = qobject_to_json(obj);
1029     g_assert(strcmp(qstring_get_str(str), "true") == 0);
1030     QDECREF(str);
1031
1032     QDECREF(qbool);
1033
1034     obj = qobject_from_json("false", &error_abort);
1035     qbool = qobject_to(QBool, obj);
1036     g_assert(qbool);
1037     g_assert(qbool_get_bool(qbool) == false);
1038
1039     str = qobject_to_json(obj);
1040     g_assert(strcmp(qstring_get_str(str), "false") == 0);
1041     QDECREF(str);
1042
1043     QDECREF(qbool);
1044
1045     qbool = qobject_to(QBool, qobject_from_jsonf("%i", false));
1046     g_assert(qbool);
1047     g_assert(qbool_get_bool(qbool) == false);
1048     QDECREF(qbool);
1049
1050     /* Test that non-zero values other than 1 get collapsed to true */
1051     qbool = qobject_to(QBool, qobject_from_jsonf("%i", 2));
1052     g_assert(qbool);
1053     g_assert(qbool_get_bool(qbool) == true);
1054     QDECREF(qbool);
1055
1056     obj = qobject_from_json("null", &error_abort);
1057     g_assert(obj != NULL);
1058     g_assert(qobject_type(obj) == QTYPE_QNULL);
1059
1060     null = qnull();
1061     g_assert(QOBJECT(null) == obj);
1062
1063     qobject_decref(obj);
1064     QDECREF(null);
1065 }
1066
1067 static void simple_dict(void)
1068 {
1069     int i;
1070     struct {
1071         const char *encoded;
1072         QLitObject decoded;
1073     } test_cases[] = {
1074         {
1075             .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1076             .decoded = QLIT_QDICT(((QLitDictEntry[]){
1077                         { "foo", QLIT_QNUM(42) },
1078                         { "bar", QLIT_QSTR("hello world") },
1079                         { }
1080                     })),
1081         }, {
1082             .encoded = "{}",
1083             .decoded = QLIT_QDICT(((QLitDictEntry[]){
1084                         { }
1085                     })),
1086         }, {
1087             .encoded = "{\"foo\": 43}",
1088             .decoded = QLIT_QDICT(((QLitDictEntry[]){
1089                         { "foo", QLIT_QNUM(43) },
1090                         { }
1091                     })),
1092         },
1093         { }
1094     };
1095
1096     for (i = 0; test_cases[i].encoded; i++) {
1097         QObject *obj;
1098         QString *str;
1099
1100         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1101         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1102
1103         str = qobject_to_json(obj);
1104         qobject_decref(obj);
1105
1106         obj = qobject_from_json(qstring_get_str(str), &error_abort);
1107         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1108         qobject_decref(obj);
1109         QDECREF(str);
1110     }
1111 }
1112
1113 /*
1114  * this generates json of the form:
1115  * a(0,m) = [0, 1, ..., m-1]
1116  * a(n,m) = {
1117  *            'key0': a(0,m),
1118  *            'key1': a(1,m),
1119  *            ...
1120  *            'key(n-1)': a(n-1,m)
1121  *          }
1122  */
1123 static void gen_test_json(GString *gstr, int nest_level_max,
1124                           int elem_count)
1125 {
1126     int i;
1127
1128     g_assert(gstr);
1129     if (nest_level_max == 0) {
1130         g_string_append(gstr, "[");
1131         for (i = 0; i < elem_count; i++) {
1132             g_string_append_printf(gstr, "%d", i);
1133             if (i < elem_count - 1) {
1134                 g_string_append_printf(gstr, ", ");
1135             }
1136         }
1137         g_string_append(gstr, "]");
1138         return;
1139     }
1140
1141     g_string_append(gstr, "{");
1142     for (i = 0; i < nest_level_max; i++) {
1143         g_string_append_printf(gstr, "'key%d': ", i);
1144         gen_test_json(gstr, i, elem_count);
1145         if (i < nest_level_max - 1) {
1146             g_string_append(gstr, ",");
1147         }
1148     }
1149     g_string_append(gstr, "}");
1150 }
1151
1152 static void large_dict(void)
1153 {
1154     GString *gstr = g_string_new("");
1155     QObject *obj;
1156
1157     gen_test_json(gstr, 10, 100);
1158     obj = qobject_from_json(gstr->str, &error_abort);
1159     g_assert(obj != NULL);
1160
1161     qobject_decref(obj);
1162     g_string_free(gstr, true);
1163 }
1164
1165 static void simple_list(void)
1166 {
1167     int i;
1168     struct {
1169         const char *encoded;
1170         QLitObject decoded;
1171     } test_cases[] = {
1172         {
1173             .encoded = "[43,42]",
1174             .decoded = QLIT_QLIST(((QLitObject[]){
1175                         QLIT_QNUM(43),
1176                         QLIT_QNUM(42),
1177                         { }
1178                     })),
1179         },
1180         {
1181             .encoded = "[43]",
1182             .decoded = QLIT_QLIST(((QLitObject[]){
1183                         QLIT_QNUM(43),
1184                         { }
1185                     })),
1186         },
1187         {
1188             .encoded = "[]",
1189             .decoded = QLIT_QLIST(((QLitObject[]){
1190                         { }
1191                     })),
1192         },
1193         {
1194             .encoded = "[{}]",
1195             .decoded = QLIT_QLIST(((QLitObject[]){
1196                         QLIT_QDICT(((QLitDictEntry[]){
1197                                     {},
1198                                         })),
1199                         {},
1200                             })),
1201         },
1202         { }
1203     };
1204
1205     for (i = 0; test_cases[i].encoded; i++) {
1206         QObject *obj;
1207         QString *str;
1208
1209         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1210         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1211
1212         str = qobject_to_json(obj);
1213         qobject_decref(obj);
1214
1215         obj = qobject_from_json(qstring_get_str(str), &error_abort);
1216         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1217         qobject_decref(obj);
1218         QDECREF(str);
1219     }
1220 }
1221
1222 static void simple_whitespace(void)
1223 {
1224     int i;
1225     struct {
1226         const char *encoded;
1227         QLitObject decoded;
1228     } test_cases[] = {
1229         {
1230             .encoded = " [ 43 , 42 ]",
1231             .decoded = QLIT_QLIST(((QLitObject[]){
1232                         QLIT_QNUM(43),
1233                         QLIT_QNUM(42),
1234                         { }
1235                     })),
1236         },
1237         {
1238             .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1239             .decoded = QLIT_QLIST(((QLitObject[]){
1240                         QLIT_QNUM(43),
1241                         QLIT_QDICT(((QLitDictEntry[]){
1242                                     { "h", QLIT_QSTR("b") },
1243                                     { }})),
1244                         QLIT_QLIST(((QLitObject[]){
1245                                     { }})),
1246                         QLIT_QNUM(42),
1247                         { }
1248                     })),
1249         },
1250         {
1251             .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1252             .decoded = QLIT_QLIST(((QLitObject[]){
1253                         QLIT_QNUM(43),
1254                         QLIT_QDICT(((QLitDictEntry[]){
1255                                     { "h", QLIT_QSTR("b") },
1256                                     { "a", QLIT_QNUM(32) },
1257                                     { }})),
1258                         QLIT_QLIST(((QLitObject[]){
1259                                     { }})),
1260                         QLIT_QNUM(42),
1261                         { }
1262                     })),
1263         },
1264         { }
1265     };
1266
1267     for (i = 0; test_cases[i].encoded; i++) {
1268         QObject *obj;
1269         QString *str;
1270
1271         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1272         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1273
1274         str = qobject_to_json(obj);
1275         qobject_decref(obj);
1276
1277         obj = qobject_from_json(qstring_get_str(str), &error_abort);
1278         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1279
1280         qobject_decref(obj);
1281         QDECREF(str);
1282     }
1283 }
1284
1285 static void simple_varargs(void)
1286 {
1287     QObject *embedded_obj;
1288     QObject *obj;
1289     QLitObject decoded = QLIT_QLIST(((QLitObject[]){
1290             QLIT_QNUM(1),
1291             QLIT_QNUM(2),
1292             QLIT_QLIST(((QLitObject[]){
1293                         QLIT_QNUM(32),
1294                         QLIT_QNUM(42),
1295                         {}})),
1296             {}}));
1297
1298     embedded_obj = qobject_from_json("[32, 42]", &error_abort);
1299     g_assert(embedded_obj != NULL);
1300
1301     obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1302     g_assert(qlit_equal_qobject(&decoded, obj));
1303
1304     qobject_decref(obj);
1305 }
1306
1307 static void empty_input(void)
1308 {
1309     const char *empty = "";
1310     QObject *obj = qobject_from_json(empty, &error_abort);
1311     g_assert(obj == NULL);
1312 }
1313
1314 static void unterminated_string(void)
1315 {
1316     Error *err = NULL;
1317     QObject *obj = qobject_from_json("\"abc", &err);
1318     g_assert(!err);             /* BUG */
1319     g_assert(obj == NULL);
1320 }
1321
1322 static void unterminated_sq_string(void)
1323 {
1324     Error *err = NULL;
1325     QObject *obj = qobject_from_json("'abc", &err);
1326     g_assert(!err);             /* BUG */
1327     g_assert(obj == NULL);
1328 }
1329
1330 static void unterminated_escape(void)
1331 {
1332     Error *err = NULL;
1333     QObject *obj = qobject_from_json("\"abc\\\"", &err);
1334     g_assert(!err);             /* BUG */
1335     g_assert(obj == NULL);
1336 }
1337
1338 static void unterminated_array(void)
1339 {
1340     Error *err = NULL;
1341     QObject *obj = qobject_from_json("[32", &err);
1342     g_assert(!err);             /* BUG */
1343     g_assert(obj == NULL);
1344 }
1345
1346 static void unterminated_array_comma(void)
1347 {
1348     Error *err = NULL;
1349     QObject *obj = qobject_from_json("[32,", &err);
1350     g_assert(!err);             /* BUG */
1351     g_assert(obj == NULL);
1352 }
1353
1354 static void invalid_array_comma(void)
1355 {
1356     Error *err = NULL;
1357     QObject *obj = qobject_from_json("[32,}", &err);
1358     error_free_or_abort(&err);
1359     g_assert(obj == NULL);
1360 }
1361
1362 static void unterminated_dict(void)
1363 {
1364     Error *err = NULL;
1365     QObject *obj = qobject_from_json("{'abc':32", &err);
1366     g_assert(!err);             /* BUG */
1367     g_assert(obj == NULL);
1368 }
1369
1370 static void unterminated_dict_comma(void)
1371 {
1372     Error *err = NULL;
1373     QObject *obj = qobject_from_json("{'abc':32,", &err);
1374     g_assert(!err);             /* BUG */
1375     g_assert(obj == NULL);
1376 }
1377
1378 static void invalid_dict_comma(void)
1379 {
1380     Error *err = NULL;
1381     QObject *obj = qobject_from_json("{'abc':32,}", &err);
1382     error_free_or_abort(&err);
1383     g_assert(obj == NULL);
1384 }
1385
1386 static void unterminated_literal(void)
1387 {
1388     Error *err = NULL;
1389     QObject *obj = qobject_from_json("nul", &err);
1390     error_free_or_abort(&err);
1391     g_assert(obj == NULL);
1392 }
1393
1394 static char *make_nest(char *buf, size_t cnt)
1395 {
1396     memset(buf, '[', cnt - 1);
1397     buf[cnt - 1] = '{';
1398     buf[cnt] = '}';
1399     memset(buf + cnt + 1, ']', cnt - 1);
1400     buf[2 * cnt] = 0;
1401     return buf;
1402 }
1403
1404 static void limits_nesting(void)
1405 {
1406     Error *err = NULL;
1407     enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1408     char buf[2 * (max_nesting + 1) + 1];
1409     QObject *obj;
1410
1411     obj = qobject_from_json(make_nest(buf, max_nesting), &error_abort);
1412     g_assert(obj != NULL);
1413     qobject_decref(obj);
1414
1415     obj = qobject_from_json(make_nest(buf, max_nesting + 1), &err);
1416     error_free_or_abort(&err);
1417     g_assert(obj == NULL);
1418 }
1419
1420 int main(int argc, char **argv)
1421 {
1422     g_test_init(&argc, &argv, NULL);
1423
1424     g_test_add_func("/literals/string/simple", simple_string);
1425     g_test_add_func("/literals/string/escaped", escaped_string);
1426     g_test_add_func("/literals/string/utf8", utf8_string);
1427     g_test_add_func("/literals/string/single_quote", single_quote_string);
1428     g_test_add_func("/literals/string/vararg", vararg_string);
1429
1430     g_test_add_func("/literals/number/simple", simple_number);
1431     g_test_add_func("/literals/number/large", large_number);
1432     g_test_add_func("/literals/number/float", float_number);
1433     g_test_add_func("/literals/number/vararg", vararg_number);
1434
1435     g_test_add_func("/literals/keyword", keyword_literal);
1436
1437     g_test_add_func("/dicts/simple_dict", simple_dict);
1438     g_test_add_func("/dicts/large_dict", large_dict);
1439     g_test_add_func("/lists/simple_list", simple_list);
1440
1441     g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1442
1443     g_test_add_func("/varargs/simple_varargs", simple_varargs);
1444
1445     g_test_add_func("/errors/empty_input", empty_input);
1446     g_test_add_func("/errors/unterminated/string", unterminated_string);
1447     g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1448     g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1449     g_test_add_func("/errors/unterminated/array", unterminated_array);
1450     g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1451     g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1452     g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1453     g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1454     g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1455     g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1456     g_test_add_func("/errors/limits/nesting", limits_nesting);
1457
1458     return g_test_run();
1459 }
This page took 0.108063 seconds and 4 git commands to generate.