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