json: Reject unescaped control characters
[qemu.git] / tests / check-qjson.c
blobf1405ad47acd9e0e09aa0f09eb51c66d27de8807
1 /*
2 * Copyright IBM, Corp. 2009
3 * Copyright (c) 2013, 2015 Red Hat Inc.
5 * Authors:
6 * Anthony Liguori <aliguori@us.ibm.com>
7 * Markus Armbruster <armbru@redhat.com>
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.
14 #include "qemu/osdep.h"
16 #include "qapi/error.h"
17 #include "qapi/qmp/qbool.h"
18 #include "qapi/qmp/qjson.h"
19 #include "qapi/qmp/qlit.h"
20 #include "qapi/qmp/qnull.h"
21 #include "qapi/qmp/qnum.h"
22 #include "qapi/qmp/qstring.h"
23 #include "qemu/unicode.h"
24 #include "qemu-common.h"
26 static QString *from_json_str(const char *jstr, bool single, Error **errp)
28 char quote = single ? '\'' : '"';
29 char *qjstr = g_strdup_printf("%c%s%c", quote, jstr, quote);
30 QString *ret = qobject_to(QString, qobject_from_json(qjstr, errp));
32 g_free(qjstr);
33 return ret;
36 static char *to_json_str(QString *str)
38 QString *json = qobject_to_json(QOBJECT(str));
39 char *jstr;
41 if (!json) {
42 return NULL;
44 /* peel off double quotes */
45 jstr = g_strndup(qstring_get_str(json) + 1,
46 qstring_get_length(json) - 2);
47 qobject_unref(json);
48 return jstr;
51 static void escaped_string(void)
53 struct {
54 /* Content of JSON string to parse with qobject_from_json() */
55 const char *json_in;
56 /* Expected parse output; to unparse with qobject_to_json() */
57 const char *utf8_out;
58 int skip;
59 } test_cases[] = {
60 { "\\b\\f\\n\\r\\t\\\\\\\"", "\b\f\n\r\t\\\"" },
61 { "\\/\\'", "/'", .skip = 1 },
62 { "single byte utf-8 \\u0020", "single byte utf-8 ", .skip = 1 },
63 { "double byte utf-8 \\u00A2", "double byte utf-8 \xc2\xa2" },
64 { "triple byte utf-8 \\u20AC", "triple byte utf-8 \xe2\x82\xac" },
65 { "quadruple byte utf-8 \\uD834\\uDD1E", /* U+1D11E */
66 /* bug: want \xF0\x9D\x84\x9E */
67 "quadruple byte utf-8 \xED\xA0\xB4\xED\xB4\x9E", .skip = 1 },
68 { "\\", NULL },
69 { "\\z", NULL },
70 { "\\ux", NULL },
71 { "\\u1x", NULL },
72 { "\\u12x", NULL },
73 { "\\u123x", NULL },
74 { "\\u12345", "\341\210\2645" },
75 { "\\u0000x", "x", .skip = 1}, /* bug: want \xC0\x80x */
76 { "unpaired leading surrogate \\uD800",
77 /* bug: not rejected */
78 "unpaired leading surrogate \355\240\200", .skip = 1 },
79 { "unpaired leading surrogate \\uD800\\uCAFE",
80 /* bug: not rejected */
81 "unpaired leading surrogate \355\240\200\354\253\276", .skip = 1 },
82 { "unpaired leading surrogate \\uD800\\uD801\\uDC02",
83 /* bug: not rejected */
84 "unpaired leading surrogate \355\240\200\355\240\201\355\260\202",
85 .skip = 1 },
86 { "unpaired trailing surrogate \\uDC00",
87 /* bug: not rejected */
88 "unpaired trailing surrogate \355\260\200", .skip = 1},
89 { "backward surrogate pair \\uDC00\\uD800",
90 /* bug: not rejected */
91 "backward surrogate pair \355\260\200\355\240\200", .skip = 1},
92 { "noncharacter U+FDD0 \\uFDD0",
93 /* bug: not rejected */
94 "noncharacter U+FDD0 \xEF\xB7\x90", .skip = 1},
95 { "noncharacter U+FDEF \\uFDEF",
96 /* bug: not rejected */
97 "noncharacter U+FDEF \xEF\xB7\xAF", .skip = 1},
98 { "noncharacter U+1FFFE \\uD87F\\uDFFE",
99 /* bug: not rejected */
100 "noncharacter U+1FFFE \xED\xA1\xBF\xED\xBF\xBE", .skip = 1},
101 { "noncharacter U+10FFFF \\uDC3F\\uDFFF",
102 /* bug: not rejected */
103 "noncharacter U+10FFFF \xED\xB0\xBF\xED\xBF\xBF", .skip = 1},
106 int i, j;
107 QString *cstr;
108 char *jstr;
110 for (i = 0; test_cases[i].json_in; i++) {
111 for (j = 0; j < 2; j++) {
112 if (test_cases[i].utf8_out) {
113 cstr = from_json_str(test_cases[i].json_in, j, &error_abort);
114 g_assert_cmpstr(qstring_get_try_str(cstr),
115 ==, test_cases[i].utf8_out);
116 if (!test_cases[i].skip) {
117 jstr = to_json_str(cstr);
118 g_assert_cmpstr(jstr, ==, test_cases[i].json_in);
119 g_free(jstr);
121 qobject_unref(cstr);
122 } else {
123 cstr = from_json_str(test_cases[i].json_in, j, NULL);
124 g_assert(!cstr);
130 static void string_with_quotes(void)
132 const char *test_cases[] = {
133 "\"the bee's knees\"",
134 "'double quote \"'",
135 NULL
137 int i;
138 QString *str;
139 char *cstr;
141 for (i = 0; test_cases[i]; i++) {
142 str = qobject_to(QString,
143 qobject_from_json(test_cases[i], &error_abort));
144 g_assert(str);
145 cstr = g_strndup(test_cases[i] + 1, strlen(test_cases[i]) - 2);
146 g_assert_cmpstr(qstring_get_str(str), ==, cstr);
147 g_free(cstr);
148 qobject_unref(str);
152 static void utf8_string(void)
155 * FIXME Current behavior for invalid UTF-8 sequences is
156 * incorrect. This test expects current, incorrect results.
157 * They're all marked "bug:" below, and are to be replaced by
158 * correct ones as the bugs get fixed.
160 * The JSON parser rejects some invalid sequences, but accepts
161 * others without correcting the problem.
163 * We should either reject all invalid sequences, or minimize
164 * overlong sequences and replace all other invalid sequences by a
165 * suitable replacement character. A common choice for
166 * replacement is U+FFFD.
168 * Problem: we can't easily deal with embedded U+0000. Parsing
169 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
170 * which gets misinterpreted as NUL-terminated "this ". We should
171 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
172 * UTF-8").
174 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
175 * capability and stress test at
176 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
178 static const struct {
179 /* Content of JSON string to parse with qobject_from_json() */
180 const char *json_in;
181 /* Expected parse output */
182 const char *utf8_out;
183 /* Expected unparse output, defaults to @json_in */
184 const char *json_out;
185 } test_cases[] = {
187 * Bug markers used here:
188 * - bug: not corrected
189 * JSON parser fails to correct invalid sequence(s)
190 * - bug: rejected
191 * JSON parser rejects invalid sequence(s)
192 * We may choose to define this as feature
195 /* 0 Control characters */
198 * Note: \x00 is impossible, other representations of
199 * U+0000 are covered under 4.3
201 "\x01\x02\x03\x04\x05\x06\x07"
202 "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
203 "\x10\x11\x12\x13\x14\x15\x16\x17"
204 "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
205 NULL,
206 "\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007"
207 "\\b\\t\\n\\u000B\\f\\r\\u000E\\u000F"
208 "\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017"
209 "\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F",
211 /* 1 Some correct UTF-8 text */
213 /* a bit of German */
214 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
215 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
216 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
217 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
218 "Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
219 " jeden gr\\u00F6\\u00DFeren Zwerg.",
222 /* a bit of Greek */
223 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
224 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
225 "\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5",
227 /* 2 Boundary condition test cases */
228 /* 2.1 First possible sequence of a certain length */
230 * 2.1.1 1 byte U+0020
231 * Control characters are already covered by their own test
232 * case under 0. Test the first 1 byte non-control character
233 * here.
236 " ",
237 " ",
239 /* 2.1.2 2 bytes U+0080 */
241 "\xC2\x80",
242 "\xC2\x80",
243 "\\u0080",
245 /* 2.1.3 3 bytes U+0800 */
247 "\xE0\xA0\x80",
248 "\xE0\xA0\x80",
249 "\\u0800",
251 /* 2.1.4 4 bytes U+10000 */
253 "\xF0\x90\x80\x80",
254 "\xF0\x90\x80\x80",
255 "\\uD800\\uDC00",
257 /* 2.1.5 5 bytes U+200000 */
259 "\xF8\x88\x80\x80\x80",
260 NULL, /* bug: rejected */
261 "\\uFFFD",
263 /* 2.1.6 6 bytes U+4000000 */
265 "\xFC\x84\x80\x80\x80\x80",
266 NULL, /* bug: rejected */
267 "\\uFFFD",
269 /* 2.2 Last possible sequence of a certain length */
270 /* 2.2.1 1 byte U+007F */
272 "\x7F",
273 "\x7F",
274 "\\u007F",
276 /* 2.2.2 2 bytes U+07FF */
278 "\xDF\xBF",
279 "\xDF\xBF",
280 "\\u07FF",
283 * 2.2.3 3 bytes U+FFFC
284 * The last possible sequence is actually U+FFFF. But that's
285 * a noncharacter, and already covered by its own test case
286 * under 5.3. Same for U+FFFE. U+FFFD is the last character
287 * in the BMP, and covered under 2.3. Because of U+FFFD's
288 * special role as replacement character, it's worth testing
289 * U+FFFC here.
292 "\xEF\xBF\xBC",
293 "\xEF\xBF\xBC",
294 "\\uFFFC",
296 /* 2.2.4 4 bytes U+1FFFFF */
298 "\xF7\xBF\xBF\xBF",
299 NULL, /* bug: rejected */
300 "\\uFFFD",
302 /* 2.2.5 5 bytes U+3FFFFFF */
304 "\xFB\xBF\xBF\xBF\xBF",
305 NULL, /* bug: rejected */
306 "\\uFFFD",
308 /* 2.2.6 6 bytes U+7FFFFFFF */
310 "\xFD\xBF\xBF\xBF\xBF\xBF",
311 NULL, /* bug: rejected */
312 "\\uFFFD",
314 /* 2.3 Other boundary conditions */
316 /* last one before surrogate range: U+D7FF */
317 "\xED\x9F\xBF",
318 "\xED\x9F\xBF",
319 "\\uD7FF",
322 /* first one after surrogate range: U+E000 */
323 "\xEE\x80\x80",
324 "\xEE\x80\x80",
325 "\\uE000",
328 /* last one in BMP: U+FFFD */
329 "\xEF\xBF\xBD",
330 "\xEF\xBF\xBD",
331 "\\uFFFD",
334 /* last one in last plane: U+10FFFD */
335 "\xF4\x8F\xBF\xBD",
336 "\xF4\x8F\xBF\xBD",
337 "\\uDBFF\\uDFFD"
340 /* first one beyond Unicode range: U+110000 */
341 "\xF4\x90\x80\x80",
342 "\xF4\x90\x80\x80",
343 "\\uFFFD",
345 /* 3 Malformed sequences */
346 /* 3.1 Unexpected continuation bytes */
347 /* 3.1.1 First continuation byte */
349 "\x80",
350 "\x80", /* bug: not corrected */
351 "\\uFFFD",
353 /* 3.1.2 Last continuation byte */
355 "\xBF",
356 "\xBF", /* bug: not corrected */
357 "\\uFFFD",
359 /* 3.1.3 2 continuation bytes */
361 "\x80\xBF",
362 "\x80\xBF", /* bug: not corrected */
363 "\\uFFFD\\uFFFD",
365 /* 3.1.4 3 continuation bytes */
367 "\x80\xBF\x80",
368 "\x80\xBF\x80", /* bug: not corrected */
369 "\\uFFFD\\uFFFD\\uFFFD",
371 /* 3.1.5 4 continuation bytes */
373 "\x80\xBF\x80\xBF",
374 "\x80\xBF\x80\xBF", /* bug: not corrected */
375 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
377 /* 3.1.6 5 continuation bytes */
379 "\x80\xBF\x80\xBF\x80",
380 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
381 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
383 /* 3.1.7 6 continuation bytes */
385 "\x80\xBF\x80\xBF\x80\xBF",
386 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
387 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
389 /* 3.1.8 7 continuation bytes */
391 "\x80\xBF\x80\xBF\x80\xBF\x80",
392 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
393 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
395 /* 3.1.9 Sequence of all 64 possible continuation bytes */
397 "\x80\x81\x82\x83\x84\x85\x86\x87"
398 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
399 "\x90\x91\x92\x93\x94\x95\x96\x97"
400 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
401 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
402 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
403 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
404 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
405 /* bug: not corrected */
406 "\x80\x81\x82\x83\x84\x85\x86\x87"
407 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
408 "\x90\x91\x92\x93\x94\x95\x96\x97"
409 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
410 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
411 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
412 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
413 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
414 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
415 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
416 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
417 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
418 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
419 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
420 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
421 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
423 /* 3.2 Lonely start characters */
424 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
426 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
427 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
428 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
429 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
430 NULL, /* bug: rejected (partly, see FIXME below) */
431 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
432 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
433 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
434 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
436 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
438 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
439 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
440 /* bug: not corrected */
441 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
442 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
443 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
444 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
446 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
448 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
449 NULL, /* bug: rejected (partly, see FIXME below) */
450 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
452 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
454 "\xF8 \xF9 \xFA \xFB ",
455 NULL, /* bug: rejected */
456 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
458 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
460 "\xFC \xFD ",
461 NULL, /* bug: rejected */
462 "\\uFFFD \\uFFFD ",
464 /* 3.3 Sequences with last continuation byte missing */
465 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
467 "\xC0",
468 NULL, /* bug: rejected */
469 "\\uFFFD",
471 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
473 "\xE0\x80",
474 "\xE0\x80", /* bug: not corrected */
475 "\\uFFFD",
477 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
479 "\xF0\x80\x80",
480 "\xF0\x80\x80", /* bug: not corrected */
481 "\\uFFFD",
483 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
485 "\xF8\x80\x80\x80",
486 NULL, /* bug: rejected */
487 "\\uFFFD",
489 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
491 "\xFC\x80\x80\x80\x80",
492 NULL, /* bug: rejected */
493 "\\uFFFD",
495 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
497 "\xDF",
498 "\xDF", /* bug: not corrected */
499 "\\uFFFD",
501 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
503 "\xEF\xBF",
504 "\xEF\xBF", /* bug: not corrected */
505 "\\uFFFD",
507 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
509 "\xF7\xBF\xBF",
510 NULL, /* bug: rejected */
511 "\\uFFFD",
513 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
515 "\xFB\xBF\xBF\xBF",
516 NULL, /* bug: rejected */
517 "\\uFFFD",
519 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
521 "\xFD\xBF\xBF\xBF\xBF",
522 NULL, /* bug: rejected */
523 "\\uFFFD",
525 /* 3.4 Concatenation of incomplete sequences */
527 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
528 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
529 NULL, /* bug: rejected (partly, see FIXME below) */
530 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
531 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
533 /* 3.5 Impossible bytes */
535 "\xFE",
536 NULL, /* bug: rejected */
537 "\\uFFFD",
540 "\xFF",
541 NULL, /* bug: rejected */
542 "\\uFFFD",
545 "\xFE\xFE\xFF\xFF",
546 NULL, /* bug: rejected */
547 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
549 /* 4 Overlong sequences */
550 /* 4.1 Overlong '/' */
552 "\xC0\xAF",
553 NULL, /* bug: rejected */
554 "\\uFFFD",
557 "\xE0\x80\xAF",
558 "\xE0\x80\xAF", /* bug: not corrected */
559 "\\uFFFD",
562 "\xF0\x80\x80\xAF",
563 "\xF0\x80\x80\xAF", /* bug: not corrected */
564 "\\uFFFD",
567 "\xF8\x80\x80\x80\xAF",
568 NULL, /* bug: rejected */
569 "\\uFFFD",
572 "\xFC\x80\x80\x80\x80\xAF",
573 NULL, /* bug: rejected */
574 "\\uFFFD",
577 * 4.2 Maximum overlong sequences
578 * Highest Unicode value that is still resulting in an
579 * overlong sequence if represented with the given number of
580 * bytes. This is a boundary test for safe UTF-8 decoders.
583 /* \U+007F */
584 "\xC1\xBF",
585 NULL, /* bug: rejected */
586 "\\uFFFD",
589 /* \U+07FF */
590 "\xE0\x9F\xBF",
591 "\xE0\x9F\xBF", /* bug: not corrected */
592 "\\uFFFD",
596 * \U+FFFC
597 * The actual maximum would be U+FFFF, but that's a
598 * noncharacter. Testing U+FFFC seems more useful. See
599 * also 2.2.3
601 "\xF0\x8F\xBF\xBC",
602 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
603 "\\uFFFD",
606 /* \U+1FFFFF */
607 "\xF8\x87\xBF\xBF\xBF",
608 NULL, /* bug: rejected */
609 "\\uFFFD",
612 /* \U+3FFFFFF */
613 "\xFC\x83\xBF\xBF\xBF\xBF",
614 NULL, /* bug: rejected */
615 "\\uFFFD",
617 /* 4.3 Overlong representation of the NUL character */
619 /* \U+0000 */
620 "\xC0\x80",
621 NULL, /* bug: rejected */
622 "\\u0000",
625 /* \U+0000 */
626 "\xE0\x80\x80",
627 "\xE0\x80\x80", /* bug: not corrected */
628 "\\uFFFD",
631 /* \U+0000 */
632 "\xF0\x80\x80\x80",
633 "\xF0\x80\x80\x80", /* bug: not corrected */
634 "\\uFFFD",
637 /* \U+0000 */
638 "\xF8\x80\x80\x80\x80",
639 NULL, /* bug: rejected */
640 "\\uFFFD",
643 /* \U+0000 */
644 "\xFC\x80\x80\x80\x80\x80",
645 NULL, /* bug: rejected */
646 "\\uFFFD",
648 /* 5 Illegal code positions */
649 /* 5.1 Single UTF-16 surrogates */
651 /* \U+D800 */
652 "\xED\xA0\x80",
653 "\xED\xA0\x80", /* bug: not corrected */
654 "\\uFFFD",
657 /* \U+DB7F */
658 "\xED\xAD\xBF",
659 "\xED\xAD\xBF", /* bug: not corrected */
660 "\\uFFFD",
663 /* \U+DB80 */
664 "\xED\xAE\x80",
665 "\xED\xAE\x80", /* bug: not corrected */
666 "\\uFFFD",
669 /* \U+DBFF */
670 "\xED\xAF\xBF",
671 "\xED\xAF\xBF", /* bug: not corrected */
672 "\\uFFFD",
675 /* \U+DC00 */
676 "\xED\xB0\x80",
677 "\xED\xB0\x80", /* bug: not corrected */
678 "\\uFFFD",
681 /* \U+DF80 */
682 "\xED\xBE\x80",
683 "\xED\xBE\x80", /* bug: not corrected */
684 "\\uFFFD",
687 /* \U+DFFF */
688 "\xED\xBF\xBF",
689 "\xED\xBF\xBF", /* bug: not corrected */
690 "\\uFFFD",
692 /* 5.2 Paired UTF-16 surrogates */
694 /* \U+D800\U+DC00 */
695 "\xED\xA0\x80\xED\xB0\x80",
696 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
697 "\\uFFFD\\uFFFD",
700 /* \U+D800\U+DFFF */
701 "\xED\xA0\x80\xED\xBF\xBF",
702 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
703 "\\uFFFD\\uFFFD",
706 /* \U+DB7F\U+DC00 */
707 "\xED\xAD\xBF\xED\xB0\x80",
708 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
709 "\\uFFFD\\uFFFD",
712 /* \U+DB7F\U+DFFF */
713 "\xED\xAD\xBF\xED\xBF\xBF",
714 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
715 "\\uFFFD\\uFFFD",
718 /* \U+DB80\U+DC00 */
719 "\xED\xAE\x80\xED\xB0\x80",
720 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
721 "\\uFFFD\\uFFFD",
724 /* \U+DB80\U+DFFF */
725 "\xED\xAE\x80\xED\xBF\xBF",
726 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
727 "\\uFFFD\\uFFFD",
730 /* \U+DBFF\U+DC00 */
731 "\xED\xAF\xBF\xED\xB0\x80",
732 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
733 "\\uFFFD\\uFFFD",
736 /* \U+DBFF\U+DFFF */
737 "\xED\xAF\xBF\xED\xBF\xBF",
738 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
739 "\\uFFFD\\uFFFD",
741 /* 5.3 Other illegal code positions */
742 /* BMP noncharacters */
744 /* \U+FFFE */
745 "\xEF\xBF\xBE",
746 "\xEF\xBF\xBE", /* bug: not corrected */
747 "\\uFFFD",
750 /* \U+FFFF */
751 "\xEF\xBF\xBF",
752 "\xEF\xBF\xBF", /* bug: not corrected */
753 "\\uFFFD",
756 /* U+FDD0 */
757 "\xEF\xB7\x90",
758 "\xEF\xB7\x90", /* bug: not corrected */
759 "\\uFFFD",
762 /* U+FDEF */
763 "\xEF\xB7\xAF",
764 "\xEF\xB7\xAF", /* bug: not corrected */
765 "\\uFFFD",
767 /* Plane 1 .. 16 noncharacters */
769 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
770 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
771 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
772 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
773 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
774 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
775 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
776 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
777 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
778 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
779 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
780 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
781 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
782 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
783 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
784 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
785 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
786 /* bug: not corrected */
787 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
788 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
789 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
790 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
791 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
792 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
793 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
794 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
795 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
796 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
797 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
798 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
799 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
800 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
801 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
802 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
803 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
804 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
805 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
806 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
810 int i, j;
811 QString *str;
812 const char *json_in, *utf8_out, *utf8_in, *json_out, *tail;
813 char *end, *in, *jstr;
815 for (i = 0; test_cases[i].json_in; i++) {
816 for (j = 0; j < 2; j++) {
817 json_in = test_cases[i].json_in;
818 utf8_out = test_cases[i].utf8_out;
819 utf8_in = test_cases[i].utf8_out ?: test_cases[i].json_in;
820 json_out = test_cases[i].json_out ?: test_cases[i].json_in;
822 /* Parse @json_in, expect @utf8_out */
823 if (utf8_out) {
824 str = from_json_str(json_in, j, &error_abort);
825 g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_out);
826 qobject_unref(str);
827 } else {
828 str = from_json_str(json_in, j, NULL);
829 g_assert(!str);
831 * Failure may be due to any sequence, but *all* sequences
832 * are expected to fail. Test each one in isolation.
834 for (tail = json_in; *tail; tail = end) {
835 mod_utf8_codepoint(tail, 6, &end);
836 if (*end == ' ') {
837 end++;
839 in = strndup(tail, end - tail);
840 str = from_json_str(in, j, NULL);
842 * FIXME JSON parser accepts invalid sequence
843 * starting with \xC2..\xF4
845 if (*in >= '\xC2' && *in <= '\xF4') {
846 g_free(str);
847 str = NULL;
849 g_assert(!str);
850 g_free(in);
854 /* Unparse @utf8_in, expect @json_out */
855 str = qstring_from_str(utf8_in);
856 jstr = to_json_str(str);
857 g_assert_cmpstr(jstr, ==, json_out);
858 qobject_unref(str);
859 g_free(jstr);
862 * Parse @json_out right back
863 * Disabled, because qobject_from_json() is buggy, and I can't
864 * be bothered to add the expected incorrect results.
865 * FIXME Enable once these bugs have been fixed.
867 if (0 && json_out != json_in) {
868 str = from_json_str(json_out, j, &error_abort);
869 g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_out);
875 static void simple_number(void)
877 int i;
878 struct {
879 const char *encoded;
880 int64_t decoded;
881 int skip;
882 } test_cases[] = {
883 { "0", 0 },
884 { "1234", 1234 },
885 { "1", 1 },
886 { "-32", -32 },
887 { "-0", 0, .skip = 1 },
888 { },
891 for (i = 0; test_cases[i].encoded; i++) {
892 QNum *qnum;
893 int64_t val;
895 qnum = qobject_to(QNum,
896 qobject_from_json(test_cases[i].encoded,
897 &error_abort));
898 g_assert(qnum);
899 g_assert(qnum_get_try_int(qnum, &val));
900 g_assert_cmpint(val, ==, test_cases[i].decoded);
901 if (test_cases[i].skip == 0) {
902 QString *str;
904 str = qobject_to_json(QOBJECT(qnum));
905 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
906 qobject_unref(str);
909 qobject_unref(qnum);
913 static void large_number(void)
915 const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
916 const char *gtu64 = "18446744073709551616"; /* 2^64 */
917 const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
918 QNum *qnum;
919 QString *str;
920 uint64_t val;
921 int64_t ival;
923 qnum = qobject_to(QNum, qobject_from_json(maxu64, &error_abort));
924 g_assert(qnum);
925 g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
926 g_assert(!qnum_get_try_int(qnum, &ival));
928 str = qobject_to_json(QOBJECT(qnum));
929 g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
930 qobject_unref(str);
931 qobject_unref(qnum);
933 qnum = qobject_to(QNum, qobject_from_json(gtu64, &error_abort));
934 g_assert(qnum);
935 g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
936 g_assert(!qnum_get_try_uint(qnum, &val));
937 g_assert(!qnum_get_try_int(qnum, &ival));
939 str = qobject_to_json(QOBJECT(qnum));
940 g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
941 qobject_unref(str);
942 qobject_unref(qnum);
944 qnum = qobject_to(QNum, qobject_from_json(lti64, &error_abort));
945 g_assert(qnum);
946 g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
947 g_assert(!qnum_get_try_uint(qnum, &val));
948 g_assert(!qnum_get_try_int(qnum, &ival));
950 str = qobject_to_json(QOBJECT(qnum));
951 g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
952 qobject_unref(str);
953 qobject_unref(qnum);
956 static void float_number(void)
958 int i;
959 struct {
960 const char *encoded;
961 double decoded;
962 int skip;
963 } test_cases[] = {
964 { "32.43", 32.43 },
965 { "0.222", 0.222 },
966 { "-32.12313", -32.12313 },
967 { "-32.20e-10", -32.20e-10, .skip = 1 },
968 { },
971 for (i = 0; test_cases[i].encoded; i++) {
972 QObject *obj;
973 QNum *qnum;
975 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
976 qnum = qobject_to(QNum, obj);
977 g_assert(qnum);
978 g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
980 if (test_cases[i].skip == 0) {
981 QString *str;
983 str = qobject_to_json(obj);
984 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
985 qobject_unref(str);
988 qobject_unref(qnum);
992 static void keyword_literal(void)
994 QObject *obj;
995 QBool *qbool;
996 QNull *null;
997 QString *str;
999 obj = qobject_from_json("true", &error_abort);
1000 qbool = qobject_to(QBool, obj);
1001 g_assert(qbool);
1002 g_assert(qbool_get_bool(qbool) == true);
1004 str = qobject_to_json(obj);
1005 g_assert(strcmp(qstring_get_str(str), "true") == 0);
1006 qobject_unref(str);
1008 qobject_unref(qbool);
1010 obj = qobject_from_json("false", &error_abort);
1011 qbool = qobject_to(QBool, obj);
1012 g_assert(qbool);
1013 g_assert(qbool_get_bool(qbool) == false);
1015 str = qobject_to_json(obj);
1016 g_assert(strcmp(qstring_get_str(str), "false") == 0);
1017 qobject_unref(str);
1019 qobject_unref(qbool);
1021 obj = qobject_from_json("null", &error_abort);
1022 g_assert(obj != NULL);
1023 g_assert(qobject_type(obj) == QTYPE_QNULL);
1025 null = qnull();
1026 g_assert(QOBJECT(null) == obj);
1028 qobject_unref(obj);
1029 qobject_unref(null);
1032 static void interpolation_valid(void)
1034 long long value_lld = 0x123456789abcdefLL;
1035 long value_ld = (long)value_lld;
1036 int value_d = (int)value_lld;
1037 unsigned long long value_llu = 0xfedcba9876543210ULL;
1038 unsigned long value_lu = (unsigned long)value_llu;
1039 unsigned value_u = (unsigned)value_llu;
1040 double value_f = 2.323423423;
1041 const char *value_s = "hello world";
1042 QObject *value_p = QOBJECT(qnull());
1043 QBool *qbool;
1044 QNum *qnum;
1045 QString *qstr;
1046 QObject *qobj;
1048 /* bool */
1050 qbool = qobject_to(QBool, qobject_from_jsonf_nofail("%i", false));
1051 g_assert(qbool);
1052 g_assert(qbool_get_bool(qbool) == false);
1053 qobject_unref(qbool);
1055 /* Test that non-zero values other than 1 get collapsed to true */
1056 qbool = qobject_to(QBool, qobject_from_jsonf_nofail("%i", 2));
1057 g_assert(qbool);
1058 g_assert(qbool_get_bool(qbool) == true);
1059 qobject_unref(qbool);
1061 /* number */
1063 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%d", value_d));
1064 g_assert_cmpint(qnum_get_int(qnum), ==, value_d);
1065 qobject_unref(qnum);
1067 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%ld", value_ld));
1068 g_assert_cmpint(qnum_get_int(qnum), ==, value_ld);
1069 qobject_unref(qnum);
1071 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%lld", value_lld));
1072 g_assert_cmpint(qnum_get_int(qnum), ==, value_lld);
1073 qobject_unref(qnum);
1075 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%u", value_u));
1076 g_assert_cmpuint(qnum_get_uint(qnum), ==, value_u);
1077 qobject_unref(qnum);
1079 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%lu", value_lu));
1080 g_assert_cmpuint(qnum_get_uint(qnum), ==, value_lu);
1081 qobject_unref(qnum);
1083 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%llu", value_llu));
1084 g_assert_cmpuint(qnum_get_uint(qnum), ==, value_llu);
1085 qobject_unref(qnum);
1087 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%f", value_f));
1088 g_assert(qnum_get_double(qnum) == value_f);
1089 qobject_unref(qnum);
1091 /* string */
1093 qstr = qobject_to(QString,
1094 qobject_from_jsonf_nofail("%s", value_s));
1095 g_assert_cmpstr(qstring_get_try_str(qstr), ==, value_s);
1096 qobject_unref(qstr);
1098 /* object */
1100 qobj = qobject_from_jsonf_nofail("%p", value_p);
1101 g_assert(qobj == value_p);
1104 static void interpolation_unknown(void)
1106 if (g_test_subprocess()) {
1107 qobject_from_jsonf_nofail("%x", 666);
1109 g_test_trap_subprocess(NULL, 0, 0);
1110 g_test_trap_assert_failed();
1113 static void interpolation_string(void)
1115 QLitObject decoded = QLIT_QLIST(((QLitObject[]){
1116 QLIT_QSTR("%s"),
1117 QLIT_QSTR("eins"),
1118 {}}));
1119 QObject *qobj;
1121 /* Dangerous misfeature: % is silently ignored in strings */
1122 qobj = qobject_from_jsonf_nofail("['%s', %s]", "eins", "zwei");
1123 g_assert(qlit_equal_qobject(&decoded, qobj));
1124 qobject_unref(qobj);
1127 static void simple_dict(void)
1129 int i;
1130 struct {
1131 const char *encoded;
1132 QLitObject decoded;
1133 } test_cases[] = {
1135 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1136 .decoded = QLIT_QDICT(((QLitDictEntry[]){
1137 { "foo", QLIT_QNUM(42) },
1138 { "bar", QLIT_QSTR("hello world") },
1140 })),
1141 }, {
1142 .encoded = "{}",
1143 .decoded = QLIT_QDICT(((QLitDictEntry[]){
1145 })),
1146 }, {
1147 .encoded = "{\"foo\": 43}",
1148 .decoded = QLIT_QDICT(((QLitDictEntry[]){
1149 { "foo", QLIT_QNUM(43) },
1151 })),
1156 for (i = 0; test_cases[i].encoded; i++) {
1157 QObject *obj;
1158 QString *str;
1160 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1161 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1163 str = qobject_to_json(obj);
1164 qobject_unref(obj);
1166 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1167 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1168 qobject_unref(obj);
1169 qobject_unref(str);
1174 * this generates json of the form:
1175 * a(0,m) = [0, 1, ..., m-1]
1176 * a(n,m) = {
1177 * 'key0': a(0,m),
1178 * 'key1': a(1,m),
1179 * ...
1180 * 'key(n-1)': a(n-1,m)
1183 static void gen_test_json(GString *gstr, int nest_level_max,
1184 int elem_count)
1186 int i;
1188 g_assert(gstr);
1189 if (nest_level_max == 0) {
1190 g_string_append(gstr, "[");
1191 for (i = 0; i < elem_count; i++) {
1192 g_string_append_printf(gstr, "%d", i);
1193 if (i < elem_count - 1) {
1194 g_string_append_printf(gstr, ", ");
1197 g_string_append(gstr, "]");
1198 return;
1201 g_string_append(gstr, "{");
1202 for (i = 0; i < nest_level_max; i++) {
1203 g_string_append_printf(gstr, "'key%d': ", i);
1204 gen_test_json(gstr, i, elem_count);
1205 if (i < nest_level_max - 1) {
1206 g_string_append(gstr, ",");
1209 g_string_append(gstr, "}");
1212 static void large_dict(void)
1214 GString *gstr = g_string_new("");
1215 QObject *obj;
1217 gen_test_json(gstr, 10, 100);
1218 obj = qobject_from_json(gstr->str, &error_abort);
1219 g_assert(obj != NULL);
1221 qobject_unref(obj);
1222 g_string_free(gstr, true);
1225 static void simple_list(void)
1227 int i;
1228 struct {
1229 const char *encoded;
1230 QLitObject decoded;
1231 } test_cases[] = {
1233 .encoded = "[43,42]",
1234 .decoded = QLIT_QLIST(((QLitObject[]){
1235 QLIT_QNUM(43),
1236 QLIT_QNUM(42),
1238 })),
1241 .encoded = "[43]",
1242 .decoded = QLIT_QLIST(((QLitObject[]){
1243 QLIT_QNUM(43),
1245 })),
1248 .encoded = "[]",
1249 .decoded = QLIT_QLIST(((QLitObject[]){
1251 })),
1254 .encoded = "[{}]",
1255 .decoded = QLIT_QLIST(((QLitObject[]){
1256 QLIT_QDICT(((QLitDictEntry[]){
1258 })),
1260 })),
1265 for (i = 0; test_cases[i].encoded; i++) {
1266 QObject *obj;
1267 QString *str;
1269 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1270 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1272 str = qobject_to_json(obj);
1273 qobject_unref(obj);
1275 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1276 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1277 qobject_unref(obj);
1278 qobject_unref(str);
1282 static void simple_whitespace(void)
1284 int i;
1285 struct {
1286 const char *encoded;
1287 QLitObject decoded;
1288 } test_cases[] = {
1290 .encoded = " [ 43 , 42 ]",
1291 .decoded = QLIT_QLIST(((QLitObject[]){
1292 QLIT_QNUM(43),
1293 QLIT_QNUM(42),
1295 })),
1298 .encoded = "\t[ 43 , { 'h' : 'b' },\r\n\t[ ], 42 ]\n",
1299 .decoded = QLIT_QLIST(((QLitObject[]){
1300 QLIT_QNUM(43),
1301 QLIT_QDICT(((QLitDictEntry[]){
1302 { "h", QLIT_QSTR("b") },
1303 { }})),
1304 QLIT_QLIST(((QLitObject[]){
1305 { }})),
1306 QLIT_QNUM(42),
1308 })),
1311 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1312 .decoded = QLIT_QLIST(((QLitObject[]){
1313 QLIT_QNUM(43),
1314 QLIT_QDICT(((QLitDictEntry[]){
1315 { "h", QLIT_QSTR("b") },
1316 { "a", QLIT_QNUM(32) },
1317 { }})),
1318 QLIT_QLIST(((QLitObject[]){
1319 { }})),
1320 QLIT_QNUM(42),
1322 })),
1327 for (i = 0; test_cases[i].encoded; i++) {
1328 QObject *obj;
1329 QString *str;
1331 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1332 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1334 str = qobject_to_json(obj);
1335 qobject_unref(obj);
1337 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1338 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1340 qobject_unref(obj);
1341 qobject_unref(str);
1345 static void simple_interpolation(void)
1347 QObject *embedded_obj;
1348 QObject *obj;
1349 QLitObject decoded = QLIT_QLIST(((QLitObject[]){
1350 QLIT_QNUM(1),
1351 QLIT_QNUM(2),
1352 QLIT_QLIST(((QLitObject[]){
1353 QLIT_QNUM(32),
1354 QLIT_QNUM(42),
1355 {}})),
1356 {}}));
1358 embedded_obj = qobject_from_json("[32, 42]", &error_abort);
1359 g_assert(embedded_obj != NULL);
1361 obj = qobject_from_jsonf_nofail("[%d, 2, %p]", 1, embedded_obj);
1362 g_assert(qlit_equal_qobject(&decoded, obj));
1364 qobject_unref(obj);
1367 static void empty_input(void)
1369 QObject *obj = qobject_from_json("", &error_abort);
1370 g_assert(obj == NULL);
1373 static void blank_input(void)
1375 QObject *obj = qobject_from_json("\n ", &error_abort);
1376 g_assert(obj == NULL);
1379 static void junk_input(void)
1381 /* Note: junk within strings is covered elsewhere */
1382 Error *err = NULL;
1383 QObject *obj;
1385 obj = qobject_from_json("@", &err);
1386 g_assert(!err); /* BUG */
1387 g_assert(obj == NULL);
1389 obj = qobject_from_json("{\x01", &err);
1390 g_assert(!err); /* BUG */
1391 g_assert(obj == NULL);
1393 obj = qobject_from_json("[0\xFF]", &err);
1394 error_free_or_abort(&err);
1395 g_assert(obj == NULL);
1397 obj = qobject_from_json("00", &err);
1398 g_assert(!err); /* BUG */
1399 g_assert(obj == NULL);
1401 obj = qobject_from_json("[1e", &err);
1402 g_assert(!err); /* BUG */
1403 g_assert(obj == NULL);
1405 obj = qobject_from_json("truer", &err);
1406 error_free_or_abort(&err);
1407 g_assert(obj == NULL);
1410 static void unterminated_string(void)
1412 Error *err = NULL;
1413 QObject *obj = qobject_from_json("\"abc", &err);
1414 g_assert(!err); /* BUG */
1415 g_assert(obj == NULL);
1418 static void unterminated_sq_string(void)
1420 Error *err = NULL;
1421 QObject *obj = qobject_from_json("'abc", &err);
1422 g_assert(!err); /* BUG */
1423 g_assert(obj == NULL);
1426 static void unterminated_escape(void)
1428 Error *err = NULL;
1429 QObject *obj = qobject_from_json("\"abc\\\"", &err);
1430 g_assert(!err); /* BUG */
1431 g_assert(obj == NULL);
1434 static void unterminated_array(void)
1436 Error *err = NULL;
1437 QObject *obj = qobject_from_json("[32", &err);
1438 g_assert(!err); /* BUG */
1439 g_assert(obj == NULL);
1442 static void unterminated_array_comma(void)
1444 Error *err = NULL;
1445 QObject *obj = qobject_from_json("[32,", &err);
1446 g_assert(!err); /* BUG */
1447 g_assert(obj == NULL);
1450 static void invalid_array_comma(void)
1452 Error *err = NULL;
1453 QObject *obj = qobject_from_json("[32,}", &err);
1454 error_free_or_abort(&err);
1455 g_assert(obj == NULL);
1458 static void unterminated_dict(void)
1460 Error *err = NULL;
1461 QObject *obj = qobject_from_json("{'abc':32", &err);
1462 g_assert(!err); /* BUG */
1463 g_assert(obj == NULL);
1466 static void unterminated_dict_comma(void)
1468 Error *err = NULL;
1469 QObject *obj = qobject_from_json("{'abc':32,", &err);
1470 g_assert(!err); /* BUG */
1471 g_assert(obj == NULL);
1474 static void invalid_dict_comma(void)
1476 Error *err = NULL;
1477 QObject *obj = qobject_from_json("{'abc':32,}", &err);
1478 error_free_or_abort(&err);
1479 g_assert(obj == NULL);
1482 static void unterminated_literal(void)
1484 Error *err = NULL;
1485 QObject *obj = qobject_from_json("nul", &err);
1486 error_free_or_abort(&err);
1487 g_assert(obj == NULL);
1490 static char *make_nest(char *buf, size_t cnt)
1492 memset(buf, '[', cnt - 1);
1493 buf[cnt - 1] = '{';
1494 buf[cnt] = '}';
1495 memset(buf + cnt + 1, ']', cnt - 1);
1496 buf[2 * cnt] = 0;
1497 return buf;
1500 static void limits_nesting(void)
1502 Error *err = NULL;
1503 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1504 char buf[2 * (max_nesting + 1) + 1];
1505 QObject *obj;
1507 obj = qobject_from_json(make_nest(buf, max_nesting), &error_abort);
1508 g_assert(obj != NULL);
1509 qobject_unref(obj);
1511 obj = qobject_from_json(make_nest(buf, max_nesting + 1), &err);
1512 error_free_or_abort(&err);
1513 g_assert(obj == NULL);
1516 static void multiple_values(void)
1518 Error *err = NULL;
1519 QObject *obj;
1521 /* BUG this leaks the syntax tree for "false" */
1522 obj = qobject_from_json("false true", &err);
1523 g_assert(qbool_get_bool(qobject_to(QBool, obj)));
1524 g_assert(!err);
1525 qobject_unref(obj);
1527 /* BUG simultaneously succeeds and fails */
1528 /* BUG calls json_parser_parse() with errp pointing to non-null */
1529 obj = qobject_from_json("} true", &err);
1530 g_assert(qbool_get_bool(qobject_to(QBool, obj)));
1531 error_free_or_abort(&err);
1532 qobject_unref(obj);
1535 int main(int argc, char **argv)
1537 g_test_init(&argc, &argv, NULL);
1539 g_test_add_func("/literals/string/escaped", escaped_string);
1540 g_test_add_func("/literals/string/quotes", string_with_quotes);
1541 g_test_add_func("/literals/string/utf8", utf8_string);
1543 g_test_add_func("/literals/number/simple", simple_number);
1544 g_test_add_func("/literals/number/large", large_number);
1545 g_test_add_func("/literals/number/float", float_number);
1547 g_test_add_func("/literals/keyword", keyword_literal);
1549 g_test_add_func("/literals/interpolation/valid", interpolation_valid);
1550 g_test_add_func("/literals/interpolation/unkown", interpolation_unknown);
1551 g_test_add_func("/literals/interpolation/string", interpolation_string);
1553 g_test_add_func("/dicts/simple_dict", simple_dict);
1554 g_test_add_func("/dicts/large_dict", large_dict);
1555 g_test_add_func("/lists/simple_list", simple_list);
1557 g_test_add_func("/mixed/simple_whitespace", simple_whitespace);
1558 g_test_add_func("/mixed/interpolation", simple_interpolation);
1560 g_test_add_func("/errors/empty", empty_input);
1561 g_test_add_func("/errors/blank", blank_input);
1562 g_test_add_func("/errors/junk", junk_input);
1563 g_test_add_func("/errors/unterminated/string", unterminated_string);
1564 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1565 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1566 g_test_add_func("/errors/unterminated/array", unterminated_array);
1567 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1568 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1569 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1570 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1571 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1572 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1573 g_test_add_func("/errors/limits/nesting", limits_nesting);
1574 g_test_add_func("/errors/multiple_values", multiple_values);
1576 return g_test_run();