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