]>
git.proxmox.com Git - mirror_qemu.git/blob - tests/check-qjson.c
2 * Copyright IBM, Corp. 2009
3 * Copyright (c) 2013, 2015 Red Hat Inc.
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-common.h"
25 static QString
*from_json_str(const char *jstr
, bool single
, Error
**errp
)
27 char quote
= single
? '\'' : '"';
28 char *qjstr
= g_strdup_printf("%c%s%c", quote
, jstr
, quote
);
29 QString
*ret
= qobject_to(QString
, qobject_from_json(qjstr
, errp
));
35 static char *to_json_str(QString
*str
)
37 QString
*json
= qobject_to_json(QOBJECT(str
));
43 /* peel off double quotes */
44 jstr
= g_strndup(qstring_get_str(json
) + 1,
45 qstring_get_length(json
) - 2);
50 static void escaped_string(void)
53 /* Content of JSON string to parse with qobject_from_json() */
55 /* Expected parse output; to unparse with qobject_to_json() */
59 { "\\b\\f\\n\\r\\t\\\\\\\"", "\b\f\n\r\t\\\"" },
60 { "\\/\\'", "/'", .skip
= 1 },
61 { "single byte utf-8 \\u0020", "single byte utf-8 ", .skip
= 1 },
62 { "double byte utf-8 \\u00A2", "double byte utf-8 \xc2\xa2" },
63 { "triple byte utf-8 \\u20AC", "triple byte utf-8 \xe2\x82\xac" },
64 { "quadruple byte utf-8 \\uD834\\uDD1E", /* U+1D11E */
65 /* bug: want \xF0\x9D\x84\x9E */
66 "quadruple byte utf-8 \xED\xA0\xB4\xED\xB4\x9E", .skip
= 1 },
73 { "\\u12345", "\341\210\2645" },
74 { "\\u0000x", "x", .skip
= 1}, /* bug: want \xC0\x80x */
75 { "unpaired leading surrogate \\uD800",
76 /* bug: not rejected */
77 "unpaired leading surrogate \355\240\200", .skip
= 1 },
78 { "unpaired leading surrogate \\uD800\\uCAFE",
79 /* bug: not rejected */
80 "unpaired leading surrogate \355\240\200\354\253\276", .skip
= 1 },
81 { "unpaired leading surrogate \\uD800\\uD801\\uDC02",
82 /* bug: not rejected */
83 "unpaired leading surrogate \355\240\200\355\240\201\355\260\202",
85 { "unpaired trailing surrogate \\uDC00",
86 /* bug: not rejected */
87 "unpaired trailing surrogate \355\260\200", .skip
= 1},
88 { "backward surrogate pair \\uDC00\\uD800",
89 /* bug: not rejected */
90 "backward surrogate pair \355\260\200\355\240\200", .skip
= 1},
91 { "noncharacter U+FDD0 \\uFDD0",
92 /* bug: not rejected */
93 "noncharacter U+FDD0 \xEF\xB7\x90", .skip
= 1},
94 { "noncharacter U+FDEF \\uFDEF",
95 /* bug: not rejected */
96 "noncharacter U+FDEF \xEF\xB7\xAF", .skip
= 1},
97 { "noncharacter U+1FFFE \\uD87F\\uDFFE",
98 /* bug: not rejected */
99 "noncharacter U+1FFFE \xED\xA1\xBF\xED\xBF\xBE", .skip
= 1},
100 { "noncharacter U+10FFFF \\uDC3F\\uDFFF",
101 /* bug: not rejected */
102 "noncharacter U+10FFFF \xED\xB0\xBF\xED\xBF\xBF", .skip
= 1},
109 for (i
= 0; test_cases
[i
].json_in
; i
++) {
110 for (j
= 0; j
< 2; j
++) {
111 if (test_cases
[i
].utf8_out
) {
112 cstr
= from_json_str(test_cases
[i
].json_in
, j
, &error_abort
);
113 g_assert_cmpstr(qstring_get_try_str(cstr
),
114 ==, test_cases
[i
].utf8_out
);
115 if (!test_cases
[i
].skip
) {
116 jstr
= to_json_str(cstr
);
117 g_assert_cmpstr(jstr
, ==, test_cases
[i
].json_in
);
122 cstr
= from_json_str(test_cases
[i
].json_in
, j
, NULL
);
129 static void string_with_quotes(void)
131 const char *test_cases
[] = {
132 "\"the bee's knees\"",
140 for (i
= 0; test_cases
[i
]; i
++) {
141 str
= qobject_to(QString
,
142 qobject_from_json(test_cases
[i
], &error_abort
));
144 cstr
= g_strndup(test_cases
[i
] + 1, strlen(test_cases
[i
]) - 2);
145 g_assert_cmpstr(qstring_get_str(str
), ==, cstr
);
151 static void utf8_string(void)
154 * FIXME Current behavior for invalid UTF-8 sequences is
155 * incorrect. This test expects current, incorrect results.
156 * They're all marked "bug:" below, and are to be replaced by
157 * correct ones as the bugs get fixed.
159 * The JSON parser rejects some invalid sequences, but accepts
160 * others without correcting the problem.
162 * We should either reject all invalid sequences, or minimize
163 * overlong sequences and replace all other invalid sequences by a
164 * suitable replacement character. A common choice for
165 * replacement is U+FFFD.
167 * Problem: we can't easily deal with embedded U+0000. Parsing
168 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
169 * which gets misinterpreted as NUL-terminated "this ". We should
170 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
173 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
174 * capability and stress test at
175 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
177 static const struct {
178 /* Content of JSON string to parse with qobject_from_json() */
180 /* Expected parse output */
181 const char *utf8_out
;
182 /* Expected unparse output, defaults to @json_in */
183 const char *json_out
;
184 /* Expected parse output for @json_out, defaults to @utf8_out */
188 * Bug markers used here:
189 * - bug: not corrected
190 * JSON parser fails to correct invalid sequence(s)
192 * JSON parser rejects invalid sequence(s)
193 * We may choose to define this as feature
195 * JSON parser produces incorrect result, this is the
196 * correct one, assuming replacement character U+FFFF
197 * We may choose to reject instead of replace
200 /* 1 Some correct UTF-8 text */
202 /* a bit of German */
203 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
204 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
205 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
206 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
207 "Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
208 " jeden gr\\u00F6\\u00DFeren Zwerg.",
212 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
213 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
214 "\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5",
216 /* 2 Boundary condition test cases */
217 /* 2.1 First possible sequence of a certain length */
218 /* 2.1.1 1 byte U+0000 */
221 "", /* bug: want overlong "\xC0\x80" */
225 /* 2.1.2 2 bytes U+0080 */
231 /* 2.1.3 3 bytes U+0800 */
237 /* 2.1.4 4 bytes U+10000 */
243 /* 2.1.5 5 bytes U+200000 */
245 "\xF8\x88\x80\x80\x80",
246 NULL
, /* bug: rejected */
248 "\xF8\x88\x80\x80\x80",
250 /* 2.1.6 6 bytes U+4000000 */
252 "\xFC\x84\x80\x80\x80\x80",
253 NULL
, /* bug: rejected */
255 "\xFC\x84\x80\x80\x80\x80",
257 /* 2.2 Last possible sequence of a certain length */
258 /* 2.2.1 1 byte U+007F */
264 /* 2.2.2 2 bytes U+07FF */
271 * 2.2.3 3 bytes U+FFFC
272 * The last possible sequence is actually U+FFFF. But that's
273 * a noncharacter, and already covered by its own test case
274 * under 5.3. Same for U+FFFE. U+FFFD is the last character
275 * in the BMP, and covered under 2.3. Because of U+FFFD's
276 * special role as replacement character, it's worth testing
284 /* 2.2.4 4 bytes U+1FFFFF */
287 NULL
, /* bug: rejected */
291 /* 2.2.5 5 bytes U+3FFFFFF */
293 "\xFB\xBF\xBF\xBF\xBF",
294 NULL
, /* bug: rejected */
296 "\xFB\xBF\xBF\xBF\xBF",
298 /* 2.2.6 6 bytes U+7FFFFFFF */
300 "\xFD\xBF\xBF\xBF\xBF\xBF",
301 NULL
, /* bug: rejected */
303 "\xFD\xBF\xBF\xBF\xBF\xBF",
305 /* 2.3 Other boundary conditions */
307 /* last one before surrogate range: U+D7FF */
313 /* first one after surrogate range: U+E000 */
319 /* last one in BMP: U+FFFD */
325 /* last one in last plane: U+10FFFD */
331 /* first one beyond Unicode range: U+110000 */
336 /* 3 Malformed sequences */
337 /* 3.1 Unexpected continuation bytes */
338 /* 3.1.1 First continuation byte */
341 "\x80", /* bug: not corrected */
344 /* 3.1.2 Last continuation byte */
347 "\xBF", /* bug: not corrected */
350 /* 3.1.3 2 continuation bytes */
353 "\x80\xBF", /* bug: not corrected */
356 /* 3.1.4 3 continuation bytes */
359 "\x80\xBF\x80", /* bug: not corrected */
360 "\\uFFFD\\uFFFD\\uFFFD",
362 /* 3.1.5 4 continuation bytes */
365 "\x80\xBF\x80\xBF", /* bug: not corrected */
366 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
368 /* 3.1.6 5 continuation bytes */
370 "\x80\xBF\x80\xBF\x80",
371 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
372 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
374 /* 3.1.7 6 continuation bytes */
376 "\x80\xBF\x80\xBF\x80\xBF",
377 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
378 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
380 /* 3.1.8 7 continuation bytes */
382 "\x80\xBF\x80\xBF\x80\xBF\x80",
383 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
384 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
386 /* 3.1.9 Sequence of all 64 possible continuation bytes */
388 "\x80\x81\x82\x83\x84\x85\x86\x87"
389 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
390 "\x90\x91\x92\x93\x94\x95\x96\x97"
391 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
392 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
393 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
394 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
395 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
396 /* bug: not corrected */
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 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
406 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
407 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
408 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
409 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
410 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
411 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
412 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
414 /* 3.2 Lonely start characters */
415 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
417 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
418 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
419 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
420 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
421 NULL
, /* bug: rejected */
422 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
423 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
424 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
425 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
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 ",
431 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
433 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
434 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
435 /* bug: not corrected */
436 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
437 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
438 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
439 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
441 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
443 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
444 NULL
, /* bug: rejected */
445 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
446 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
448 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
450 "\xF8 \xF9 \xFA \xFB ",
451 NULL
, /* bug: rejected */
452 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
453 "\xF8 \xF9 \xFA \xFB ",
455 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
458 NULL
, /* bug: rejected */
462 /* 3.3 Sequences with last continuation byte missing */
463 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
466 NULL
, /* bug: rejected */
470 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
473 "\xE0\x80", /* bug: not corrected */
476 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
479 "\xF0\x80\x80", /* bug: not corrected */
482 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
485 NULL
, /* bug: rejected */
489 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
491 "\xFC\x80\x80\x80\x80",
492 NULL
, /* bug: rejected */
494 "\xFC\x80\x80\x80\x80",
496 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
499 "\xDF", /* bug: not corrected */
502 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
505 "\xEF\xBF", /* bug: not corrected */
508 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
511 NULL
, /* bug: rejected */
515 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
518 NULL
, /* bug: rejected */
522 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
524 "\xFD\xBF\xBF\xBF\xBF",
525 NULL
, /* bug: rejected */
527 "\xFD\xBF\xBF\xBF\xBF",
529 /* 3.4 Concatenation of incomplete sequences */
531 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
532 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
533 NULL
, /* bug: rejected */
534 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
535 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
536 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
537 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
539 /* 3.5 Impossible bytes */
542 NULL
, /* bug: rejected */
548 NULL
, /* bug: rejected */
554 NULL
, /* bug: rejected */
555 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
558 /* 4 Overlong sequences */
559 /* 4.1 Overlong '/' */
562 NULL
, /* bug: rejected */
568 "\xE0\x80\xAF", /* bug: not corrected */
573 "\xF0\x80\x80\xAF", /* bug: not corrected */
577 "\xF8\x80\x80\x80\xAF",
578 NULL
, /* bug: rejected */
580 "\xF8\x80\x80\x80\xAF",
583 "\xFC\x80\x80\x80\x80\xAF",
584 NULL
, /* bug: rejected */
586 "\xFC\x80\x80\x80\x80\xAF",
589 * 4.2 Maximum overlong sequences
590 * Highest Unicode value that is still resulting in an
591 * overlong sequence if represented with the given number of
592 * bytes. This is a boundary test for safe UTF-8 decoders.
597 NULL
, /* bug: rejected */
604 "\xE0\x9F\xBF", /* bug: not corrected */
610 * The actual maximum would be U+FFFF, but that's a
611 * noncharacter. Testing U+FFFC seems more useful. See
615 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
620 "\xF8\x87\xBF\xBF\xBF",
621 NULL
, /* bug: rejected */
623 "\xF8\x87\xBF\xBF\xBF",
627 "\xFC\x83\xBF\xBF\xBF\xBF",
628 NULL
, /* bug: rejected */
630 "\xFC\x83\xBF\xBF\xBF\xBF",
632 /* 4.3 Overlong representation of the NUL character */
636 NULL
, /* bug: rejected */
643 "\xE0\x80\x80", /* bug: not corrected */
649 "\xF0\x80\x80\x80", /* bug: not corrected */
654 "\xF8\x80\x80\x80\x80",
655 NULL
, /* bug: rejected */
657 "\xF8\x80\x80\x80\x80",
661 "\xFC\x80\x80\x80\x80\x80",
662 NULL
, /* bug: rejected */
664 "\xFC\x80\x80\x80\x80\x80",
666 /* 5 Illegal code positions */
667 /* 5.1 Single UTF-16 surrogates */
671 "\xED\xA0\x80", /* bug: not corrected */
677 "\xED\xAD\xBF", /* bug: not corrected */
683 "\xED\xAE\x80", /* bug: not corrected */
689 "\xED\xAF\xBF", /* bug: not corrected */
695 "\xED\xB0\x80", /* bug: not corrected */
701 "\xED\xBE\x80", /* bug: not corrected */
707 "\xED\xBF\xBF", /* bug: not corrected */
710 /* 5.2 Paired UTF-16 surrogates */
713 "\xED\xA0\x80\xED\xB0\x80",
714 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
719 "\xED\xA0\x80\xED\xBF\xBF",
720 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
725 "\xED\xAD\xBF\xED\xB0\x80",
726 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
731 "\xED\xAD\xBF\xED\xBF\xBF",
732 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
737 "\xED\xAE\x80\xED\xB0\x80",
738 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
743 "\xED\xAE\x80\xED\xBF\xBF",
744 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
749 "\xED\xAF\xBF\xED\xB0\x80",
750 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
755 "\xED\xAF\xBF\xED\xBF\xBF",
756 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
759 /* 5.3 Other illegal code positions */
760 /* BMP noncharacters */
764 "\xEF\xBF\xBE", /* bug: not corrected */
770 "\xEF\xBF\xBF", /* bug: not corrected */
776 "\xEF\xB7\x90", /* bug: not corrected */
782 "\xEF\xB7\xAF", /* bug: not corrected */
785 /* Plane 1 .. 16 noncharacters */
787 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
788 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
789 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
790 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
791 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
792 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
793 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
794 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
795 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
796 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
797 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
798 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
799 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
800 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
801 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
802 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
803 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
804 /* bug: not corrected */
805 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
806 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
807 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
808 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
809 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
810 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
811 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
812 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
813 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
814 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
815 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
816 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
817 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
818 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
819 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
820 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
821 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
822 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
823 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
824 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
830 const char *json_in
, *utf8_out
, *utf8_in
, *json_out
;
833 for (i
= 0; test_cases
[i
].json_in
; i
++) {
834 for (j
= 0; j
< 2; j
++) {
835 json_in
= test_cases
[i
].json_in
;
836 utf8_out
= test_cases
[i
].utf8_out
;
837 utf8_in
= test_cases
[i
].utf8_in
?: test_cases
[i
].utf8_out
;
838 json_out
= test_cases
[i
].json_out
?: test_cases
[i
].json_in
;
840 /* Parse @json_in, expect @utf8_out */
842 str
= from_json_str(json_in
, j
, &error_abort
);
843 g_assert_cmpstr(qstring_get_try_str(str
), ==, utf8_out
);
846 str
= from_json_str(json_in
, j
, NULL
);
850 /* Unparse @utf8_in, expect @json_out */
851 str
= qstring_from_str(utf8_in
);
852 jstr
= to_json_str(str
);
853 g_assert_cmpstr(jstr
, ==, json_out
);
858 * Parse @json_out right back
859 * Disabled, because qobject_from_json() is buggy, and I can't
860 * be bothered to add the expected incorrect results.
861 * FIXME Enable once these bugs have been fixed.
863 if (0 && json_out
!= json_in
) {
864 str
= from_json_str(json_out
, j
, &error_abort
);
865 g_assert_cmpstr(qstring_get_try_str(str
), ==, utf8_out
);
871 static void vararg_string(void)
878 { "the quick brown fox jumped over the fence" },
882 for (i
= 0; test_cases
[i
].decoded
; i
++) {
885 str
= qobject_to(QString
,
886 qobject_from_jsonf_nofail("%s",
887 test_cases
[i
].decoded
));
889 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
895 static void simple_number(void)
907 { "-0", 0, .skip
= 1 },
911 for (i
= 0; test_cases
[i
].encoded
; i
++) {
915 qnum
= qobject_to(QNum
,
916 qobject_from_json(test_cases
[i
].encoded
,
919 g_assert(qnum_get_try_int(qnum
, &val
));
920 g_assert_cmpint(val
, ==, test_cases
[i
].decoded
);
921 if (test_cases
[i
].skip
== 0) {
924 str
= qobject_to_json(QOBJECT(qnum
));
925 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
933 static void large_number(void)
935 const char *maxu64
= "18446744073709551615"; /* 2^64-1 */
936 const char *gtu64
= "18446744073709551616"; /* 2^64 */
937 const char *lti64
= "-9223372036854775809"; /* -2^63 - 1 */
943 qnum
= qobject_to(QNum
, qobject_from_json(maxu64
, &error_abort
));
945 g_assert_cmpuint(qnum_get_uint(qnum
), ==, 18446744073709551615U);
946 g_assert(!qnum_get_try_int(qnum
, &ival
));
948 str
= qobject_to_json(QOBJECT(qnum
));
949 g_assert_cmpstr(qstring_get_str(str
), ==, maxu64
);
953 qnum
= qobject_to(QNum
, qobject_from_json(gtu64
, &error_abort
));
955 g_assert_cmpfloat(qnum_get_double(qnum
), ==, 18446744073709552e3
);
956 g_assert(!qnum_get_try_uint(qnum
, &val
));
957 g_assert(!qnum_get_try_int(qnum
, &ival
));
959 str
= qobject_to_json(QOBJECT(qnum
));
960 g_assert_cmpstr(qstring_get_str(str
), ==, gtu64
);
964 qnum
= qobject_to(QNum
, qobject_from_json(lti64
, &error_abort
));
966 g_assert_cmpfloat(qnum_get_double(qnum
), ==, -92233720368547758e2
);
967 g_assert(!qnum_get_try_uint(qnum
, &val
));
968 g_assert(!qnum_get_try_int(qnum
, &ival
));
970 str
= qobject_to_json(QOBJECT(qnum
));
971 g_assert_cmpstr(qstring_get_str(str
), ==, "-9223372036854775808");
976 static void float_number(void)
986 { "-32.12313", -32.12313 },
987 { "-32.20e-10", -32.20e-10, .skip
= 1 },
991 for (i
= 0; test_cases
[i
].encoded
; i
++) {
995 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
996 qnum
= qobject_to(QNum
, obj
);
998 g_assert(qnum_get_double(qnum
) == test_cases
[i
].decoded
);
1000 if (test_cases
[i
].skip
== 0) {
1003 str
= qobject_to_json(obj
);
1004 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
1008 qobject_unref(qnum
);
1012 static void vararg_number(void)
1016 long long value_ll
= 0x2342342343LL
;
1017 double valuef
= 2.323423423;
1020 qnum
= qobject_to(QNum
, qobject_from_jsonf_nofail("%d", value
));
1021 g_assert(qnum_get_try_int(qnum
, &val
));
1022 g_assert_cmpint(val
, ==, value
);
1023 qobject_unref(qnum
);
1025 qnum
= qobject_to(QNum
, qobject_from_jsonf_nofail("%lld", value_ll
));
1026 g_assert(qnum_get_try_int(qnum
, &val
));
1027 g_assert_cmpint(val
, ==, value_ll
);
1028 qobject_unref(qnum
);
1030 qnum
= qobject_to(QNum
, qobject_from_jsonf_nofail("%f", valuef
));
1031 g_assert(qnum_get_double(qnum
) == valuef
);
1032 qobject_unref(qnum
);
1035 static void keyword_literal(void)
1042 obj
= qobject_from_json("true", &error_abort
);
1043 qbool
= qobject_to(QBool
, obj
);
1045 g_assert(qbool_get_bool(qbool
) == true);
1047 str
= qobject_to_json(obj
);
1048 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
1051 qobject_unref(qbool
);
1053 obj
= qobject_from_json("false", &error_abort
);
1054 qbool
= qobject_to(QBool
, obj
);
1056 g_assert(qbool_get_bool(qbool
) == false);
1058 str
= qobject_to_json(obj
);
1059 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
1062 qobject_unref(qbool
);
1064 qbool
= qobject_to(QBool
, qobject_from_jsonf_nofail("%i", false));
1066 g_assert(qbool_get_bool(qbool
) == false);
1067 qobject_unref(qbool
);
1069 /* Test that non-zero values other than 1 get collapsed to true */
1070 qbool
= qobject_to(QBool
, qobject_from_jsonf_nofail("%i", 2));
1072 g_assert(qbool_get_bool(qbool
) == true);
1073 qobject_unref(qbool
);
1075 obj
= qobject_from_json("null", &error_abort
);
1076 g_assert(obj
!= NULL
);
1077 g_assert(qobject_type(obj
) == QTYPE_QNULL
);
1080 g_assert(QOBJECT(null
) == obj
);
1083 qobject_unref(null
);
1086 static void simple_dict(void)
1090 const char *encoded
;
1094 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
1095 .decoded
= QLIT_QDICT(((QLitDictEntry
[]){
1096 { "foo", QLIT_QNUM(42) },
1097 { "bar", QLIT_QSTR("hello world") },
1102 .decoded
= QLIT_QDICT(((QLitDictEntry
[]){
1106 .encoded
= "{\"foo\": 43}",
1107 .decoded
= QLIT_QDICT(((QLitDictEntry
[]){
1108 { "foo", QLIT_QNUM(43) },
1115 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1119 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1120 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1122 str
= qobject_to_json(obj
);
1125 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1126 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1133 * this generates json of the form:
1134 * a(0,m) = [0, 1, ..., m-1]
1139 * 'key(n-1)': a(n-1,m)
1142 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1148 if (nest_level_max
== 0) {
1149 g_string_append(gstr
, "[");
1150 for (i
= 0; i
< elem_count
; i
++) {
1151 g_string_append_printf(gstr
, "%d", i
);
1152 if (i
< elem_count
- 1) {
1153 g_string_append_printf(gstr
, ", ");
1156 g_string_append(gstr
, "]");
1160 g_string_append(gstr
, "{");
1161 for (i
= 0; i
< nest_level_max
; i
++) {
1162 g_string_append_printf(gstr
, "'key%d': ", i
);
1163 gen_test_json(gstr
, i
, elem_count
);
1164 if (i
< nest_level_max
- 1) {
1165 g_string_append(gstr
, ",");
1168 g_string_append(gstr
, "}");
1171 static void large_dict(void)
1173 GString
*gstr
= g_string_new("");
1176 gen_test_json(gstr
, 10, 100);
1177 obj
= qobject_from_json(gstr
->str
, &error_abort
);
1178 g_assert(obj
!= NULL
);
1181 g_string_free(gstr
, true);
1184 static void simple_list(void)
1188 const char *encoded
;
1192 .encoded
= "[43,42]",
1193 .decoded
= QLIT_QLIST(((QLitObject
[]){
1201 .decoded
= QLIT_QLIST(((QLitObject
[]){
1208 .decoded
= QLIT_QLIST(((QLitObject
[]){
1214 .decoded
= QLIT_QLIST(((QLitObject
[]){
1215 QLIT_QDICT(((QLitDictEntry
[]){
1224 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1228 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1229 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1231 str
= qobject_to_json(obj
);
1234 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1235 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1241 static void simple_whitespace(void)
1245 const char *encoded
;
1249 .encoded
= " [ 43 , 42 ]",
1250 .decoded
= QLIT_QLIST(((QLitObject
[]){
1257 .encoded
= "\t[ 43 , { 'h' : 'b' },\r\n\t[ ], 42 ]\n",
1258 .decoded
= QLIT_QLIST(((QLitObject
[]){
1260 QLIT_QDICT(((QLitDictEntry
[]){
1261 { "h", QLIT_QSTR("b") },
1263 QLIT_QLIST(((QLitObject
[]){
1270 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1271 .decoded
= QLIT_QLIST(((QLitObject
[]){
1273 QLIT_QDICT(((QLitDictEntry
[]){
1274 { "h", QLIT_QSTR("b") },
1275 { "a", QLIT_QNUM(32) },
1277 QLIT_QLIST(((QLitObject
[]){
1286 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1290 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1291 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1293 str
= qobject_to_json(obj
);
1296 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1297 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1304 static void simple_varargs(void)
1306 QObject
*embedded_obj
;
1308 QLitObject decoded
= QLIT_QLIST(((QLitObject
[]){
1311 QLIT_QLIST(((QLitObject
[]){
1317 embedded_obj
= qobject_from_json("[32, 42]", &error_abort
);
1318 g_assert(embedded_obj
!= NULL
);
1320 obj
= qobject_from_jsonf_nofail("[%d, 2, %p]", 1, embedded_obj
);
1321 g_assert(qlit_equal_qobject(&decoded
, obj
));
1326 static void empty_input(void)
1328 QObject
*obj
= qobject_from_json("", &error_abort
);
1329 g_assert(obj
== NULL
);
1332 static void blank_input(void)
1334 QObject
*obj
= qobject_from_json("\n ", &error_abort
);
1335 g_assert(obj
== NULL
);
1338 static void junk_input(void)
1340 /* Note: junk within strings is covered elsewhere */
1344 obj
= qobject_from_json("@", &err
);
1345 g_assert(!err
); /* BUG */
1346 g_assert(obj
== NULL
);
1348 obj
= qobject_from_json("[0\xFF]", &err
);
1349 error_free_or_abort(&err
);
1350 g_assert(obj
== NULL
);
1352 obj
= qobject_from_json("00", &err
);
1353 g_assert(!err
); /* BUG */
1354 g_assert(obj
== NULL
);
1356 obj
= qobject_from_json("[1e", &err
);
1357 g_assert(!err
); /* BUG */
1358 g_assert(obj
== NULL
);
1360 obj
= qobject_from_json("truer", &err
);
1361 error_free_or_abort(&err
);
1362 g_assert(obj
== NULL
);
1365 static void unterminated_string(void)
1368 QObject
*obj
= qobject_from_json("\"abc", &err
);
1369 g_assert(!err
); /* BUG */
1370 g_assert(obj
== NULL
);
1373 static void unterminated_sq_string(void)
1376 QObject
*obj
= qobject_from_json("'abc", &err
);
1377 g_assert(!err
); /* BUG */
1378 g_assert(obj
== NULL
);
1381 static void unterminated_escape(void)
1384 QObject
*obj
= qobject_from_json("\"abc\\\"", &err
);
1385 g_assert(!err
); /* BUG */
1386 g_assert(obj
== NULL
);
1389 static void unterminated_array(void)
1392 QObject
*obj
= qobject_from_json("[32", &err
);
1393 g_assert(!err
); /* BUG */
1394 g_assert(obj
== NULL
);
1397 static void unterminated_array_comma(void)
1400 QObject
*obj
= qobject_from_json("[32,", &err
);
1401 g_assert(!err
); /* BUG */
1402 g_assert(obj
== NULL
);
1405 static void invalid_array_comma(void)
1408 QObject
*obj
= qobject_from_json("[32,}", &err
);
1409 error_free_or_abort(&err
);
1410 g_assert(obj
== NULL
);
1413 static void unterminated_dict(void)
1416 QObject
*obj
= qobject_from_json("{'abc':32", &err
);
1417 g_assert(!err
); /* BUG */
1418 g_assert(obj
== NULL
);
1421 static void unterminated_dict_comma(void)
1424 QObject
*obj
= qobject_from_json("{'abc':32,", &err
);
1425 g_assert(!err
); /* BUG */
1426 g_assert(obj
== NULL
);
1429 static void invalid_dict_comma(void)
1432 QObject
*obj
= qobject_from_json("{'abc':32,}", &err
);
1433 error_free_or_abort(&err
);
1434 g_assert(obj
== NULL
);
1437 static void unterminated_literal(void)
1440 QObject
*obj
= qobject_from_json("nul", &err
);
1441 error_free_or_abort(&err
);
1442 g_assert(obj
== NULL
);
1445 static char *make_nest(char *buf
, size_t cnt
)
1447 memset(buf
, '[', cnt
- 1);
1450 memset(buf
+ cnt
+ 1, ']', cnt
- 1);
1455 static void limits_nesting(void)
1458 enum { max_nesting
= 1024 }; /* see qobject/json-streamer.c */
1459 char buf
[2 * (max_nesting
+ 1) + 1];
1462 obj
= qobject_from_json(make_nest(buf
, max_nesting
), &error_abort
);
1463 g_assert(obj
!= NULL
);
1466 obj
= qobject_from_json(make_nest(buf
, max_nesting
+ 1), &err
);
1467 error_free_or_abort(&err
);
1468 g_assert(obj
== NULL
);
1471 static void multiple_values(void)
1476 /* BUG this leaks the syntax tree for "false" */
1477 obj
= qobject_from_json("false true", &err
);
1478 g_assert(qbool_get_bool(qobject_to(QBool
, obj
)));
1482 /* BUG simultaneously succeeds and fails */
1483 /* BUG calls json_parser_parse() with errp pointing to non-null */
1484 obj
= qobject_from_json("} true", &err
);
1485 g_assert(qbool_get_bool(qobject_to(QBool
, obj
)));
1486 error_free_or_abort(&err
);
1490 int main(int argc
, char **argv
)
1492 g_test_init(&argc
, &argv
, NULL
);
1494 g_test_add_func("/literals/string/escaped", escaped_string
);
1495 g_test_add_func("/literals/string/quotes", string_with_quotes
);
1496 g_test_add_func("/literals/string/utf8", utf8_string
);
1497 g_test_add_func("/literals/string/vararg", vararg_string
);
1499 g_test_add_func("/literals/number/simple", simple_number
);
1500 g_test_add_func("/literals/number/large", large_number
);
1501 g_test_add_func("/literals/number/float", float_number
);
1502 g_test_add_func("/literals/number/vararg", vararg_number
);
1504 g_test_add_func("/literals/keyword", keyword_literal
);
1506 g_test_add_func("/dicts/simple_dict", simple_dict
);
1507 g_test_add_func("/dicts/large_dict", large_dict
);
1508 g_test_add_func("/lists/simple_list", simple_list
);
1510 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1512 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1514 g_test_add_func("/errors/empty", empty_input
);
1515 g_test_add_func("/errors/blank", blank_input
);
1516 g_test_add_func("/errors/junk", junk_input
);
1517 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1518 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1519 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1520 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1521 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1522 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1523 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1524 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1525 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1526 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1527 g_test_add_func("/errors/limits/nesting", limits_nesting
);
1528 g_test_add_func("/errors/multiple_values", multiple_values
);
1530 return g_test_run();