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