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