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