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.
13 #include "qemu/osdep.h"
15 #include "qapi/qmp/types.h"
16 #include "qapi/qmp/qjson.h"
17 #include "qemu-common.h"
19 static void escaped_string(void)
33 { "\"\\/\"", "/", .skip
= 1 },
36 { "\"hello world \\\"embedded string\\\"\"",
37 "hello world \"embedded string\"" },
38 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
39 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip
= 1 },
40 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
41 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
42 { "'\\b'", "\b", .skip
= 1 },
43 { "'\\f'", "\f", .skip
= 1 },
44 { "'\\n'", "\n", .skip
= 1 },
45 { "'\\r'", "\r", .skip
= 1 },
46 { "'\\t'", "\t", .skip
= 1 },
47 { "'\\/'", "/", .skip
= 1 },
48 { "'\\\\'", "\\", .skip
= 1 },
52 for (i
= 0; test_cases
[i
].encoded
; i
++) {
56 obj
= qobject_from_json(test_cases
[i
].encoded
);
57 str
= qobject_to_qstring(obj
);
59 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].decoded
);
61 if (test_cases
[i
].skip
== 0) {
62 str
= qobject_to_json(obj
);
63 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].encoded
);
71 static void simple_string(void)
78 { "\"hello world\"", "hello world" },
79 { "\"the quick brown fox jumped over the fence\"",
80 "the quick brown fox jumped over the fence" },
84 for (i
= 0; test_cases
[i
].encoded
; i
++) {
88 obj
= qobject_from_json(test_cases
[i
].encoded
);
89 str
= qobject_to_qstring(obj
);
91 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
93 str
= qobject_to_json(obj
);
94 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
102 static void single_quote_string(void)
109 { "'hello world'", "hello world" },
110 { "'the quick brown fox \\' jumped over the fence'",
111 "the quick brown fox ' jumped over the fence" },
115 for (i
= 0; test_cases
[i
].encoded
; i
++) {
119 obj
= qobject_from_json(test_cases
[i
].encoded
);
120 str
= qobject_to_qstring(obj
);
122 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
128 static void utf8_string(void)
131 * FIXME Current behavior for invalid UTF-8 sequences is
132 * incorrect. This test expects current, incorrect results.
133 * They're all marked "bug:" below, and are to be replaced by
134 * correct ones as the bugs get fixed.
136 * The JSON parser rejects some invalid sequences, but accepts
137 * others without correcting the problem.
139 * We should either reject all invalid sequences, or minimize
140 * overlong sequences and replace all other invalid sequences by a
141 * suitable replacement character. A common choice for
142 * replacement is U+FFFD.
144 * Problem: we can't easily deal with embedded U+0000. Parsing
145 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
146 * which gets misinterpreted as NUL-terminated "this ". We should
147 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
150 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
151 * capability and stress test at
152 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
154 static const struct {
156 const char *utf8_out
;
157 const char *json_out
; /* defaults to @json_in */
158 const char *utf8_in
; /* defaults to @utf8_out */
161 * Bug markers used here:
162 * - bug: not corrected
163 * JSON parser fails to correct invalid sequence(s)
165 * JSON parser rejects invalid sequence(s)
166 * We may choose to define this as feature
168 * JSON parser produces incorrect result, this is the
169 * correct one, assuming replacement character U+FFFF
170 * We may choose to reject instead of replace
173 /* 1 Some correct UTF-8 text */
175 /* a bit of German */
176 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
177 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
178 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
179 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
180 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
181 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
185 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
186 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
187 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
189 /* 2 Boundary condition test cases */
190 /* 2.1 First possible sequence of a certain length */
191 /* 2.1.1 1 byte U+0000 */
194 "", /* bug: want overlong "\xC0\x80" */
198 /* 2.1.2 2 bytes U+0080 */
204 /* 2.1.3 3 bytes U+0800 */
210 /* 2.1.4 4 bytes U+10000 */
212 "\"\xF0\x90\x80\x80\"",
214 "\"\\uD800\\uDC00\"",
216 /* 2.1.5 5 bytes U+200000 */
218 "\"\xF8\x88\x80\x80\x80\"",
219 NULL
, /* bug: rejected */
221 "\xF8\x88\x80\x80\x80",
223 /* 2.1.6 6 bytes U+4000000 */
225 "\"\xFC\x84\x80\x80\x80\x80\"",
226 NULL
, /* bug: rejected */
228 "\xFC\x84\x80\x80\x80\x80",
230 /* 2.2 Last possible sequence of a certain length */
231 /* 2.2.1 1 byte U+007F */
237 /* 2.2.2 2 bytes U+07FF */
244 * 2.2.3 3 bytes U+FFFC
245 * The last possible sequence is actually U+FFFF. But that's
246 * a noncharacter, and already covered by its own test case
247 * under 5.3. Same for U+FFFE. U+FFFD is the last character
248 * in the BMP, and covered under 2.3. Because of U+FFFD's
249 * special role as replacement character, it's worth testing
257 /* 2.2.4 4 bytes U+1FFFFF */
259 "\"\xF7\xBF\xBF\xBF\"",
260 NULL
, /* bug: rejected */
264 /* 2.2.5 5 bytes U+3FFFFFF */
266 "\"\xFB\xBF\xBF\xBF\xBF\"",
267 NULL
, /* bug: rejected */
269 "\xFB\xBF\xBF\xBF\xBF",
271 /* 2.2.6 6 bytes U+7FFFFFFF */
273 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
274 NULL
, /* bug: rejected */
276 "\xFD\xBF\xBF\xBF\xBF\xBF",
278 /* 2.3 Other boundary conditions */
280 /* last one before surrogate range: U+D7FF */
286 /* first one after surrogate range: U+E000 */
292 /* last one in BMP: U+FFFD */
298 /* last one in last plane: U+10FFFD */
299 "\"\xF4\x8F\xBF\xBD\"",
304 /* first one beyond Unicode range: U+110000 */
305 "\"\xF4\x90\x80\x80\"",
309 /* 3 Malformed sequences */
310 /* 3.1 Unexpected continuation bytes */
311 /* 3.1.1 First continuation byte */
314 "\x80", /* bug: not corrected */
317 /* 3.1.2 Last continuation byte */
320 "\xBF", /* bug: not corrected */
323 /* 3.1.3 2 continuation bytes */
326 "\x80\xBF", /* bug: not corrected */
327 "\"\\uFFFD\\uFFFD\"",
329 /* 3.1.4 3 continuation bytes */
332 "\x80\xBF\x80", /* bug: not corrected */
333 "\"\\uFFFD\\uFFFD\\uFFFD\"",
335 /* 3.1.5 4 continuation bytes */
337 "\"\x80\xBF\x80\xBF\"",
338 "\x80\xBF\x80\xBF", /* bug: not corrected */
339 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
341 /* 3.1.6 5 continuation bytes */
343 "\"\x80\xBF\x80\xBF\x80\"",
344 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
345 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
347 /* 3.1.7 6 continuation bytes */
349 "\"\x80\xBF\x80\xBF\x80\xBF\"",
350 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
351 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
353 /* 3.1.8 7 continuation bytes */
355 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
356 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
357 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
359 /* 3.1.9 Sequence of all 64 possible continuation bytes */
361 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
362 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
363 "\x90\x91\x92\x93\x94\x95\x96\x97"
364 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
365 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
366 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
367 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
368 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
369 /* bug: not corrected */
370 "\x80\x81\x82\x83\x84\x85\x86\x87"
371 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
372 "\x90\x91\x92\x93\x94\x95\x96\x97"
373 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
374 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
375 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
376 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
377 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
378 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
379 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
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\""
387 /* 3.2 Lonely start characters */
388 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
390 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
391 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
392 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
393 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
394 NULL
, /* bug: rejected */
395 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
396 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
397 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
398 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
399 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
400 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
401 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
402 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
404 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
406 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
407 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
408 /* bug: not corrected */
409 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
410 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
411 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
412 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
414 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
416 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
417 NULL
, /* bug: rejected */
418 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
419 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
421 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
423 "\"\xF8 \xF9 \xFA \xFB \"",
424 NULL
, /* bug: rejected */
425 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
426 "\xF8 \xF9 \xFA \xFB ",
428 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
431 NULL
, /* bug: rejected */
432 "\"\\uFFFD \\uFFFD \"",
435 /* 3.3 Sequences with last continuation byte missing */
436 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
439 NULL
, /* bug: rejected */
443 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
446 "\xE0\x80", /* bug: not corrected */
449 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
452 "\xF0\x80\x80", /* bug: not corrected */
455 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
457 "\"\xF8\x80\x80\x80\"",
458 NULL
, /* bug: rejected */
462 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
464 "\"\xFC\x80\x80\x80\x80\"",
465 NULL
, /* bug: rejected */
467 "\xFC\x80\x80\x80\x80",
469 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
472 "\xDF", /* bug: not corrected */
475 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
478 "\xEF\xBF", /* bug: not corrected */
481 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
484 NULL
, /* bug: rejected */
488 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
490 "\"\xFB\xBF\xBF\xBF\"",
491 NULL
, /* bug: rejected */
495 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
497 "\"\xFD\xBF\xBF\xBF\xBF\"",
498 NULL
, /* bug: rejected */
500 "\xFD\xBF\xBF\xBF\xBF",
502 /* 3.4 Concatenation of incomplete sequences */
504 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
505 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
506 NULL
, /* bug: rejected */
507 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
508 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
509 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
510 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
512 /* 3.5 Impossible bytes */
515 NULL
, /* bug: rejected */
521 NULL
, /* bug: rejected */
526 "\"\xFE\xFE\xFF\xFF\"",
527 NULL
, /* bug: rejected */
528 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
531 /* 4 Overlong sequences */
532 /* 4.1 Overlong '/' */
535 NULL
, /* bug: rejected */
541 "\xE0\x80\xAF", /* bug: not corrected */
545 "\"\xF0\x80\x80\xAF\"",
546 "\xF0\x80\x80\xAF", /* bug: not corrected */
550 "\"\xF8\x80\x80\x80\xAF\"",
551 NULL
, /* bug: rejected */
553 "\xF8\x80\x80\x80\xAF",
556 "\"\xFC\x80\x80\x80\x80\xAF\"",
557 NULL
, /* bug: rejected */
559 "\xFC\x80\x80\x80\x80\xAF",
562 * 4.2 Maximum overlong sequences
563 * Highest Unicode value that is still resulting in an
564 * overlong sequence if represented with the given number of
565 * bytes. This is a boundary test for safe UTF-8 decoders.
570 NULL
, /* bug: rejected */
577 "\xE0\x9F\xBF", /* bug: not corrected */
583 * The actual maximum would be U+FFFF, but that's a
584 * noncharacter. Testing U+FFFC seems more useful. See
587 "\"\xF0\x8F\xBF\xBC\"",
588 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
593 "\"\xF8\x87\xBF\xBF\xBF\"",
594 NULL
, /* bug: rejected */
596 "\xF8\x87\xBF\xBF\xBF",
600 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
601 NULL
, /* bug: rejected */
603 "\xFC\x83\xBF\xBF\xBF\xBF",
605 /* 4.3 Overlong representation of the NUL character */
609 NULL
, /* bug: rejected */
616 "\xE0\x80\x80", /* bug: not corrected */
621 "\"\xF0\x80\x80\x80\"",
622 "\xF0\x80\x80\x80", /* bug: not corrected */
627 "\"\xF8\x80\x80\x80\x80\"",
628 NULL
, /* bug: rejected */
630 "\xF8\x80\x80\x80\x80",
634 "\"\xFC\x80\x80\x80\x80\x80\"",
635 NULL
, /* bug: rejected */
637 "\xFC\x80\x80\x80\x80\x80",
639 /* 5 Illegal code positions */
640 /* 5.1 Single UTF-16 surrogates */
644 "\xED\xA0\x80", /* bug: not corrected */
650 "\xED\xAD\xBF", /* bug: not corrected */
656 "\xED\xAE\x80", /* bug: not corrected */
662 "\xED\xAF\xBF", /* bug: not corrected */
668 "\xED\xB0\x80", /* bug: not corrected */
674 "\xED\xBE\x80", /* bug: not corrected */
680 "\xED\xBF\xBF", /* bug: not corrected */
683 /* 5.2 Paired UTF-16 surrogates */
686 "\"\xED\xA0\x80\xED\xB0\x80\"",
687 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
688 "\"\\uFFFD\\uFFFD\"",
692 "\"\xED\xA0\x80\xED\xBF\xBF\"",
693 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
694 "\"\\uFFFD\\uFFFD\"",
698 "\"\xED\xAD\xBF\xED\xB0\x80\"",
699 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
700 "\"\\uFFFD\\uFFFD\"",
704 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
705 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
706 "\"\\uFFFD\\uFFFD\"",
710 "\"\xED\xAE\x80\xED\xB0\x80\"",
711 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
712 "\"\\uFFFD\\uFFFD\"",
716 "\"\xED\xAE\x80\xED\xBF\xBF\"",
717 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
718 "\"\\uFFFD\\uFFFD\"",
722 "\"\xED\xAF\xBF\xED\xB0\x80\"",
723 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
724 "\"\\uFFFD\\uFFFD\"",
728 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
729 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
730 "\"\\uFFFD\\uFFFD\"",
732 /* 5.3 Other illegal code positions */
733 /* BMP noncharacters */
737 "\xEF\xBF\xBE", /* bug: not corrected */
743 "\xEF\xBF\xBF", /* bug: not corrected */
749 "\xEF\xB7\x90", /* bug: not corrected */
755 "\xEF\xB7\xAF", /* bug: not corrected */
758 /* Plane 1 .. 16 noncharacters */
760 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
761 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
762 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
763 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
764 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
765 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
766 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
767 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
768 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
769 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
770 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
771 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
772 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
773 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
774 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
775 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
776 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
777 /* bug: not corrected */
778 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
779 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
780 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
781 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
782 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
783 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
784 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
785 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
786 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
787 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
788 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
789 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
790 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
791 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
792 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
793 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
794 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
795 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
796 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
797 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
804 const char *json_in
, *utf8_out
, *utf8_in
, *json_out
;
806 for (i
= 0; test_cases
[i
].json_in
; i
++) {
807 json_in
= test_cases
[i
].json_in
;
808 utf8_out
= test_cases
[i
].utf8_out
;
809 utf8_in
= test_cases
[i
].utf8_in
?: test_cases
[i
].utf8_out
;
810 json_out
= test_cases
[i
].json_out
?: test_cases
[i
].json_in
;
812 obj
= qobject_from_json(json_in
);
814 str
= qobject_to_qstring(obj
);
816 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
822 obj
= QOBJECT(qstring_from_str(utf8_in
));
823 str
= qobject_to_json(obj
);
826 g_assert_cmpstr(qstring_get_str(str
), ==, json_out
);
834 * Disabled, because qobject_from_json() is buggy, and I can't
835 * be bothered to add the expected incorrect results.
836 * FIXME Enable once these bugs have been fixed.
838 if (0 && json_out
!= json_in
) {
839 obj
= qobject_from_json(json_out
);
840 str
= qobject_to_qstring(obj
);
842 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
847 static void vararg_string(void)
854 { "the quick brown fox jumped over the fence" },
858 for (i
= 0; test_cases
[i
].decoded
; i
++) {
861 str
= qobject_to_qstring(qobject_from_jsonf("%s",
862 test_cases
[i
].decoded
));
864 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
870 static void simple_number(void)
882 { "-0", 0, .skip
= 1 },
886 for (i
= 0; test_cases
[i
].encoded
; i
++) {
889 qint
= qobject_to_qint(qobject_from_json(test_cases
[i
].encoded
));
891 g_assert(qint_get_int(qint
) == test_cases
[i
].decoded
);
892 if (test_cases
[i
].skip
== 0) {
895 str
= qobject_to_json(QOBJECT(qint
));
896 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
904 static void float_number(void)
914 { "-32.12313", -32.12313 },
915 { "-32.20e-10", -32.20e-10, .skip
= 1 },
919 for (i
= 0; test_cases
[i
].encoded
; i
++) {
923 obj
= qobject_from_json(test_cases
[i
].encoded
);
924 qfloat
= qobject_to_qfloat(obj
);
926 g_assert(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
928 if (test_cases
[i
].skip
== 0) {
931 str
= qobject_to_json(obj
);
932 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
940 static void vararg_number(void)
945 long long value_ll
= 0x2342342343LL
;
946 double valuef
= 2.323423423;
948 qint
= qobject_to_qint(qobject_from_jsonf("%d", value
));
949 g_assert(qint_get_int(qint
) == value
);
952 qint
= qobject_to_qint(qobject_from_jsonf("%lld", value_ll
));
953 g_assert(qint_get_int(qint
) == value_ll
);
956 qfloat
= qobject_to_qfloat(qobject_from_jsonf("%f", valuef
));
957 g_assert(qfloat_get_double(qfloat
) == valuef
);
961 static void keyword_literal(void)
968 obj
= qobject_from_json("true");
969 qbool
= qobject_to_qbool(obj
);
971 g_assert(qbool_get_bool(qbool
) == true);
973 str
= qobject_to_json(obj
);
974 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
979 obj
= qobject_from_json("false");
980 qbool
= qobject_to_qbool(obj
);
982 g_assert(qbool_get_bool(qbool
) == false);
984 str
= qobject_to_json(obj
);
985 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
990 qbool
= qobject_to_qbool(qobject_from_jsonf("%i", false));
992 g_assert(qbool_get_bool(qbool
) == false);
995 /* Test that non-zero values other than 1 get collapsed to true */
996 qbool
= qobject_to_qbool(qobject_from_jsonf("%i", 2));
998 g_assert(qbool_get_bool(qbool
) == true);
1001 obj
= qobject_from_json("null");
1002 g_assert(obj
!= NULL
);
1003 g_assert(qobject_type(obj
) == QTYPE_QNULL
);
1006 g_assert(null
== obj
);
1008 qobject_decref(obj
);
1009 qobject_decref(null
);
1012 typedef struct LiteralQDictEntry LiteralQDictEntry
;
1013 typedef struct LiteralQObject LiteralQObject
;
1015 struct LiteralQObject
1021 LiteralQDictEntry
*qdict
;
1022 LiteralQObject
*qlist
;
1026 struct LiteralQDictEntry
1029 LiteralQObject value
;
1032 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1033 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1034 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1035 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1037 typedef struct QListCompareHelper
1040 LiteralQObject
*objs
;
1042 } QListCompareHelper
;
1044 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
1046 static void compare_helper(QObject
*obj
, void *opaque
)
1048 QListCompareHelper
*helper
= opaque
;
1050 if (helper
->result
== 0) {
1054 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
1059 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
1062 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
1064 if (!rhs
|| lhs
->type
!= qobject_type(rhs
)) {
1068 switch (lhs
->type
) {
1070 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
1072 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
1076 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
1077 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
1079 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
1087 QListCompareHelper helper
;
1090 helper
.objs
= lhs
->value
.qlist
;
1093 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
1095 return helper
.result
;
1104 static void simple_dict(void)
1108 const char *encoded
;
1109 LiteralQObject decoded
;
1112 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
1113 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1114 { "foo", QLIT_QINT(42) },
1115 { "bar", QLIT_QSTR("hello world") },
1120 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1124 .encoded
= "{\"foo\": 43}",
1125 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1126 { "foo", QLIT_QINT(43) },
1133 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1137 obj
= qobject_from_json(test_cases
[i
].encoded
);
1138 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1140 str
= qobject_to_json(obj
);
1141 qobject_decref(obj
);
1143 obj
= qobject_from_json(qstring_get_str(str
));
1144 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1145 qobject_decref(obj
);
1151 * this generates json of the form:
1152 * a(0,m) = [0, 1, ..., m-1]
1157 * 'key(n-1)': a(n-1,m)
1160 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1166 if (nest_level_max
== 0) {
1167 g_string_append(gstr
, "[");
1168 for (i
= 0; i
< elem_count
; i
++) {
1169 g_string_append_printf(gstr
, "%d", i
);
1170 if (i
< elem_count
- 1) {
1171 g_string_append_printf(gstr
, ", ");
1174 g_string_append(gstr
, "]");
1178 g_string_append(gstr
, "{");
1179 for (i
= 0; i
< nest_level_max
; i
++) {
1180 g_string_append_printf(gstr
, "'key%d': ", i
);
1181 gen_test_json(gstr
, i
, elem_count
);
1182 if (i
< nest_level_max
- 1) {
1183 g_string_append(gstr
, ",");
1186 g_string_append(gstr
, "}");
1189 static void large_dict(void)
1191 GString
*gstr
= g_string_new("");
1194 gen_test_json(gstr
, 10, 100);
1195 obj
= qobject_from_json(gstr
->str
);
1196 g_assert(obj
!= NULL
);
1198 qobject_decref(obj
);
1199 g_string_free(gstr
, true);
1202 static void simple_list(void)
1206 const char *encoded
;
1207 LiteralQObject decoded
;
1210 .encoded
= "[43,42]",
1211 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1219 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1226 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1232 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1233 QLIT_QDICT(((LiteralQDictEntry
[]){
1242 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1246 obj
= qobject_from_json(test_cases
[i
].encoded
);
1247 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1249 str
= qobject_to_json(obj
);
1250 qobject_decref(obj
);
1252 obj
= qobject_from_json(qstring_get_str(str
));
1253 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1254 qobject_decref(obj
);
1259 static void simple_whitespace(void)
1263 const char *encoded
;
1264 LiteralQObject decoded
;
1267 .encoded
= " [ 43 , 42 ]",
1268 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1275 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1276 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1278 QLIT_QDICT(((LiteralQDictEntry
[]){
1279 { "h", QLIT_QSTR("b") },
1281 QLIT_QLIST(((LiteralQObject
[]){
1288 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1289 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1291 QLIT_QDICT(((LiteralQDictEntry
[]){
1292 { "h", QLIT_QSTR("b") },
1293 { "a", QLIT_QINT(32) },
1295 QLIT_QLIST(((LiteralQObject
[]){
1304 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1308 obj
= qobject_from_json(test_cases
[i
].encoded
);
1309 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1311 str
= qobject_to_json(obj
);
1312 qobject_decref(obj
);
1314 obj
= qobject_from_json(qstring_get_str(str
));
1315 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1317 qobject_decref(obj
);
1322 static void simple_varargs(void)
1324 QObject
*embedded_obj
;
1326 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
1329 QLIT_QLIST(((LiteralQObject
[]){
1335 embedded_obj
= qobject_from_json("[32, 42]");
1336 g_assert(embedded_obj
!= NULL
);
1338 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
1339 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
1341 qobject_decref(obj
);
1344 static void empty_input(void)
1346 const char *empty
= "";
1348 QObject
*obj
= qobject_from_json(empty
);
1349 g_assert(obj
== NULL
);
1352 static void unterminated_string(void)
1354 QObject
*obj
= qobject_from_json("\"abc");
1355 g_assert(obj
== NULL
);
1358 static void unterminated_sq_string(void)
1360 QObject
*obj
= qobject_from_json("'abc");
1361 g_assert(obj
== NULL
);
1364 static void unterminated_escape(void)
1366 QObject
*obj
= qobject_from_json("\"abc\\\"");
1367 g_assert(obj
== NULL
);
1370 static void unterminated_array(void)
1372 QObject
*obj
= qobject_from_json("[32");
1373 g_assert(obj
== NULL
);
1376 static void unterminated_array_comma(void)
1378 QObject
*obj
= qobject_from_json("[32,");
1379 g_assert(obj
== NULL
);
1382 static void invalid_array_comma(void)
1384 QObject
*obj
= qobject_from_json("[32,}");
1385 g_assert(obj
== NULL
);
1388 static void unterminated_dict(void)
1390 QObject
*obj
= qobject_from_json("{'abc':32");
1391 g_assert(obj
== NULL
);
1394 static void unterminated_dict_comma(void)
1396 QObject
*obj
= qobject_from_json("{'abc':32,");
1397 g_assert(obj
== NULL
);
1400 static void invalid_dict_comma(void)
1402 QObject
*obj
= qobject_from_json("{'abc':32,}");
1403 g_assert(obj
== NULL
);
1406 static void unterminated_literal(void)
1408 QObject
*obj
= qobject_from_json("nul");
1409 g_assert(obj
== NULL
);
1412 static char *make_nest(char *buf
, size_t cnt
)
1414 memset(buf
, '[', cnt
- 1);
1417 memset(buf
+ cnt
+ 1, ']', cnt
- 1);
1422 static void limits_nesting(void)
1424 enum { max_nesting
= 1024 }; /* see qobject/json-streamer.c */
1425 char buf
[2 * (max_nesting
+ 1) + 1];
1428 obj
= qobject_from_json(make_nest(buf
, max_nesting
));
1429 g_assert(obj
!= NULL
);
1430 qobject_decref(obj
);
1432 obj
= qobject_from_json(make_nest(buf
, max_nesting
+ 1));
1433 g_assert(obj
== NULL
);
1436 int main(int argc
, char **argv
)
1438 g_test_init(&argc
, &argv
, NULL
);
1440 g_test_add_func("/literals/string/simple", simple_string
);
1441 g_test_add_func("/literals/string/escaped", escaped_string
);
1442 g_test_add_func("/literals/string/utf8", utf8_string
);
1443 g_test_add_func("/literals/string/single_quote", single_quote_string
);
1444 g_test_add_func("/literals/string/vararg", vararg_string
);
1446 g_test_add_func("/literals/number/simple", simple_number
);
1447 g_test_add_func("/literals/number/float", float_number
);
1448 g_test_add_func("/literals/number/vararg", vararg_number
);
1450 g_test_add_func("/literals/keyword", keyword_literal
);
1452 g_test_add_func("/dicts/simple_dict", simple_dict
);
1453 g_test_add_func("/dicts/large_dict", large_dict
);
1454 g_test_add_func("/lists/simple_list", simple_list
);
1456 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1458 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1460 g_test_add_func("/errors/empty_input", empty_input
);
1461 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1462 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1463 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1464 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1465 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1466 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1467 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1468 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1469 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1470 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1471 g_test_add_func("/errors/limits/nesting", limits_nesting
);
1473 return g_test_run();