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
);
58 g_assert(obj
!= NULL
);
59 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
61 str
= qobject_to_qstring(obj
);
62 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].decoded
);
64 if (test_cases
[i
].skip
== 0) {
65 str
= qobject_to_json(obj
);
66 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].encoded
);
74 static void simple_string(void)
81 { "\"hello world\"", "hello world" },
82 { "\"the quick brown fox jumped over the fence\"",
83 "the quick brown fox jumped over the fence" },
87 for (i
= 0; test_cases
[i
].encoded
; i
++) {
91 obj
= qobject_from_json(test_cases
[i
].encoded
);
93 g_assert(obj
!= NULL
);
94 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
96 str
= qobject_to_qstring(obj
);
97 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
99 str
= qobject_to_json(obj
);
100 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
108 static void single_quote_string(void)
115 { "'hello world'", "hello world" },
116 { "'the quick brown fox \\' jumped over the fence'",
117 "the quick brown fox ' jumped over the fence" },
121 for (i
= 0; test_cases
[i
].encoded
; i
++) {
125 obj
= qobject_from_json(test_cases
[i
].encoded
);
127 g_assert(obj
!= NULL
);
128 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
130 str
= qobject_to_qstring(obj
);
131 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
137 static void utf8_string(void)
140 * FIXME Current behavior for invalid UTF-8 sequences is
141 * incorrect. This test expects current, incorrect results.
142 * They're all marked "bug:" below, and are to be replaced by
143 * correct ones as the bugs get fixed.
145 * The JSON parser rejects some invalid sequences, but accepts
146 * others without correcting the problem.
148 * We should either reject all invalid sequences, or minimize
149 * overlong sequences and replace all other invalid sequences by a
150 * suitable replacement character. A common choice for
151 * replacement is U+FFFD.
153 * Problem: we can't easily deal with embedded U+0000. Parsing
154 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
155 * which gets misinterpreted as NUL-terminated "this ". We should
156 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
159 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
160 * capability and stress test at
161 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
163 static const struct {
165 const char *utf8_out
;
166 const char *json_out
; /* defaults to @json_in */
167 const char *utf8_in
; /* defaults to @utf8_out */
170 * Bug markers used here:
171 * - bug: not corrected
172 * JSON parser fails to correct invalid sequence(s)
174 * JSON parser rejects invalid sequence(s)
175 * We may choose to define this as feature
177 * JSON parser produces incorrect result, this is the
178 * correct one, assuming replacement character U+FFFF
179 * We may choose to reject instead of replace
182 /* 1 Some correct UTF-8 text */
184 /* a bit of German */
185 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
186 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
187 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
188 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
189 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
190 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
194 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
195 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
196 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
198 /* 2 Boundary condition test cases */
199 /* 2.1 First possible sequence of a certain length */
200 /* 2.1.1 1 byte U+0000 */
203 "", /* bug: want overlong "\xC0\x80" */
207 /* 2.1.2 2 bytes U+0080 */
213 /* 2.1.3 3 bytes U+0800 */
219 /* 2.1.4 4 bytes U+10000 */
221 "\"\xF0\x90\x80\x80\"",
223 "\"\\uD800\\uDC00\"",
225 /* 2.1.5 5 bytes U+200000 */
227 "\"\xF8\x88\x80\x80\x80\"",
228 NULL
, /* bug: rejected */
230 "\xF8\x88\x80\x80\x80",
232 /* 2.1.6 6 bytes U+4000000 */
234 "\"\xFC\x84\x80\x80\x80\x80\"",
235 NULL
, /* bug: rejected */
237 "\xFC\x84\x80\x80\x80\x80",
239 /* 2.2 Last possible sequence of a certain length */
240 /* 2.2.1 1 byte U+007F */
246 /* 2.2.2 2 bytes U+07FF */
253 * 2.2.3 3 bytes U+FFFC
254 * The last possible sequence is actually U+FFFF. But that's
255 * a noncharacter, and already covered by its own test case
256 * under 5.3. Same for U+FFFE. U+FFFD is the last character
257 * in the BMP, and covered under 2.3. Because of U+FFFD's
258 * special role as replacement character, it's worth testing
266 /* 2.2.4 4 bytes U+1FFFFF */
268 "\"\xF7\xBF\xBF\xBF\"",
269 NULL
, /* bug: rejected */
273 /* 2.2.5 5 bytes U+3FFFFFF */
275 "\"\xFB\xBF\xBF\xBF\xBF\"",
276 NULL
, /* bug: rejected */
278 "\xFB\xBF\xBF\xBF\xBF",
280 /* 2.2.6 6 bytes U+7FFFFFFF */
282 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
283 NULL
, /* bug: rejected */
285 "\xFD\xBF\xBF\xBF\xBF\xBF",
287 /* 2.3 Other boundary conditions */
289 /* last one before surrogate range: U+D7FF */
295 /* first one after surrogate range: U+E000 */
301 /* last one in BMP: U+FFFD */
307 /* last one in last plane: U+10FFFD */
308 "\"\xF4\x8F\xBF\xBD\"",
313 /* first one beyond Unicode range: U+110000 */
314 "\"\xF4\x90\x80\x80\"",
318 /* 3 Malformed sequences */
319 /* 3.1 Unexpected continuation bytes */
320 /* 3.1.1 First continuation byte */
323 "\x80", /* bug: not corrected */
326 /* 3.1.2 Last continuation byte */
329 "\xBF", /* bug: not corrected */
332 /* 3.1.3 2 continuation bytes */
335 "\x80\xBF", /* bug: not corrected */
336 "\"\\uFFFD\\uFFFD\"",
338 /* 3.1.4 3 continuation bytes */
341 "\x80\xBF\x80", /* bug: not corrected */
342 "\"\\uFFFD\\uFFFD\\uFFFD\"",
344 /* 3.1.5 4 continuation bytes */
346 "\"\x80\xBF\x80\xBF\"",
347 "\x80\xBF\x80\xBF", /* bug: not corrected */
348 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
350 /* 3.1.6 5 continuation bytes */
352 "\"\x80\xBF\x80\xBF\x80\"",
353 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
354 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
356 /* 3.1.7 6 continuation bytes */
358 "\"\x80\xBF\x80\xBF\x80\xBF\"",
359 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
360 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
362 /* 3.1.8 7 continuation bytes */
364 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
365 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
366 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
368 /* 3.1.9 Sequence of all 64 possible continuation bytes */
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 /* bug: not corrected */
379 "\x80\x81\x82\x83\x84\x85\x86\x87"
380 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
381 "\x90\x91\x92\x93\x94\x95\x96\x97"
382 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
383 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
384 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
385 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
386 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
387 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
388 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
389 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
390 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
391 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
392 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
393 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
394 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
396 /* 3.2 Lonely start characters */
397 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
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 \"",
403 NULL
, /* bug: rejected */
404 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
405 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
406 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
407 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
408 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
409 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
410 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
411 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
413 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
415 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
416 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
417 /* bug: not corrected */
418 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
419 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
420 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
421 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
423 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
425 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
426 NULL
, /* bug: rejected */
427 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
428 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
430 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
432 "\"\xF8 \xF9 \xFA \xFB \"",
433 NULL
, /* bug: rejected */
434 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
435 "\xF8 \xF9 \xFA \xFB ",
437 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
440 NULL
, /* bug: rejected */
441 "\"\\uFFFD \\uFFFD \"",
444 /* 3.3 Sequences with last continuation byte missing */
445 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
448 NULL
, /* bug: rejected */
452 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
455 "\xE0\x80", /* bug: not corrected */
458 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
461 "\xF0\x80\x80", /* bug: not corrected */
464 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
466 "\"\xF8\x80\x80\x80\"",
467 NULL
, /* bug: rejected */
471 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
473 "\"\xFC\x80\x80\x80\x80\"",
474 NULL
, /* bug: rejected */
476 "\xFC\x80\x80\x80\x80",
478 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
481 "\xDF", /* bug: not corrected */
484 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
487 "\xEF\xBF", /* bug: not corrected */
490 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
493 NULL
, /* bug: rejected */
497 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
499 "\"\xFB\xBF\xBF\xBF\"",
500 NULL
, /* bug: rejected */
504 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
506 "\"\xFD\xBF\xBF\xBF\xBF\"",
507 NULL
, /* bug: rejected */
509 "\xFD\xBF\xBF\xBF\xBF",
511 /* 3.4 Concatenation of incomplete sequences */
513 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
514 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
515 NULL
, /* bug: rejected */
516 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
517 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
518 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
519 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
521 /* 3.5 Impossible bytes */
524 NULL
, /* bug: rejected */
530 NULL
, /* bug: rejected */
535 "\"\xFE\xFE\xFF\xFF\"",
536 NULL
, /* bug: rejected */
537 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
540 /* 4 Overlong sequences */
541 /* 4.1 Overlong '/' */
544 NULL
, /* bug: rejected */
550 "\xE0\x80\xAF", /* bug: not corrected */
554 "\"\xF0\x80\x80\xAF\"",
555 "\xF0\x80\x80\xAF", /* bug: not corrected */
559 "\"\xF8\x80\x80\x80\xAF\"",
560 NULL
, /* bug: rejected */
562 "\xF8\x80\x80\x80\xAF",
565 "\"\xFC\x80\x80\x80\x80\xAF\"",
566 NULL
, /* bug: rejected */
568 "\xFC\x80\x80\x80\x80\xAF",
571 * 4.2 Maximum overlong sequences
572 * Highest Unicode value that is still resulting in an
573 * overlong sequence if represented with the given number of
574 * bytes. This is a boundary test for safe UTF-8 decoders.
579 NULL
, /* bug: rejected */
586 "\xE0\x9F\xBF", /* bug: not corrected */
592 * The actual maximum would be U+FFFF, but that's a
593 * noncharacter. Testing U+FFFC seems more useful. See
596 "\"\xF0\x8F\xBF\xBC\"",
597 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
602 "\"\xF8\x87\xBF\xBF\xBF\"",
603 NULL
, /* bug: rejected */
605 "\xF8\x87\xBF\xBF\xBF",
609 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
610 NULL
, /* bug: rejected */
612 "\xFC\x83\xBF\xBF\xBF\xBF",
614 /* 4.3 Overlong representation of the NUL character */
618 NULL
, /* bug: rejected */
625 "\xE0\x80\x80", /* bug: not corrected */
630 "\"\xF0\x80\x80\x80\"",
631 "\xF0\x80\x80\x80", /* bug: not corrected */
636 "\"\xF8\x80\x80\x80\x80\"",
637 NULL
, /* bug: rejected */
639 "\xF8\x80\x80\x80\x80",
643 "\"\xFC\x80\x80\x80\x80\x80\"",
644 NULL
, /* bug: rejected */
646 "\xFC\x80\x80\x80\x80\x80",
648 /* 5 Illegal code positions */
649 /* 5.1 Single UTF-16 surrogates */
653 "\xED\xA0\x80", /* bug: not corrected */
659 "\xED\xAD\xBF", /* bug: not corrected */
665 "\xED\xAE\x80", /* bug: not corrected */
671 "\xED\xAF\xBF", /* bug: not corrected */
677 "\xED\xB0\x80", /* bug: not corrected */
683 "\xED\xBE\x80", /* bug: not corrected */
689 "\xED\xBF\xBF", /* bug: not corrected */
692 /* 5.2 Paired UTF-16 surrogates */
695 "\"\xED\xA0\x80\xED\xB0\x80\"",
696 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
697 "\"\\uFFFD\\uFFFD\"",
701 "\"\xED\xA0\x80\xED\xBF\xBF\"",
702 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
703 "\"\\uFFFD\\uFFFD\"",
707 "\"\xED\xAD\xBF\xED\xB0\x80\"",
708 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
709 "\"\\uFFFD\\uFFFD\"",
713 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
714 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
715 "\"\\uFFFD\\uFFFD\"",
719 "\"\xED\xAE\x80\xED\xB0\x80\"",
720 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
721 "\"\\uFFFD\\uFFFD\"",
725 "\"\xED\xAE\x80\xED\xBF\xBF\"",
726 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
727 "\"\\uFFFD\\uFFFD\"",
731 "\"\xED\xAF\xBF\xED\xB0\x80\"",
732 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
733 "\"\\uFFFD\\uFFFD\"",
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 */
746 "\xEF\xBF\xBE", /* bug: not corrected */
752 "\xEF\xBF\xBF", /* bug: not corrected */
758 "\xEF\xB7\x90", /* bug: not corrected */
764 "\xEF\xB7\xAF", /* bug: not corrected */
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\"",
813 const char *json_in
, *utf8_out
, *utf8_in
, *json_out
;
815 for (i
= 0; test_cases
[i
].json_in
; i
++) {
816 json_in
= test_cases
[i
].json_in
;
817 utf8_out
= test_cases
[i
].utf8_out
;
818 utf8_in
= test_cases
[i
].utf8_in
?: test_cases
[i
].utf8_out
;
819 json_out
= test_cases
[i
].json_out
?: test_cases
[i
].json_in
;
821 obj
= qobject_from_json(json_in
);
824 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
825 str
= qobject_to_qstring(obj
);
826 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
832 obj
= QOBJECT(qstring_from_str(utf8_in
));
833 str
= qobject_to_json(obj
);
836 g_assert_cmpstr(qstring_get_str(str
), ==, json_out
);
844 * Disabled, because qobject_from_json() is buggy, and I can't
845 * be bothered to add the expected incorrect results.
846 * FIXME Enable once these bugs have been fixed.
848 if (0 && json_out
!= json_in
) {
849 obj
= qobject_from_json(json_out
);
851 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
852 str
= qobject_to_qstring(obj
);
853 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
858 static void vararg_string(void)
865 { "the quick brown fox jumped over the fence" },
869 for (i
= 0; test_cases
[i
].decoded
; i
++) {
873 obj
= qobject_from_jsonf("%s", test_cases
[i
].decoded
);
875 g_assert(obj
!= NULL
);
876 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
878 str
= qobject_to_qstring(obj
);
879 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
885 static void simple_number(void)
897 { "-0", 0, .skip
= 1 },
901 for (i
= 0; test_cases
[i
].encoded
; i
++) {
905 obj
= qobject_from_json(test_cases
[i
].encoded
);
906 g_assert(obj
!= NULL
);
907 g_assert(qobject_type(obj
) == QTYPE_QINT
);
909 qint
= qobject_to_qint(obj
);
910 g_assert(qint_get_int(qint
) == test_cases
[i
].decoded
);
911 if (test_cases
[i
].skip
== 0) {
914 str
= qobject_to_json(obj
);
915 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
923 static void float_number(void)
933 { "-32.12313", -32.12313 },
934 { "-32.20e-10", -32.20e-10, .skip
= 1 },
938 for (i
= 0; test_cases
[i
].encoded
; i
++) {
942 obj
= qobject_from_json(test_cases
[i
].encoded
);
943 g_assert(obj
!= NULL
);
944 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
946 qfloat
= qobject_to_qfloat(obj
);
947 g_assert(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
949 if (test_cases
[i
].skip
== 0) {
952 str
= qobject_to_json(obj
);
953 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
961 static void vararg_number(void)
967 long long value_ll
= 0x2342342343LL
;
968 double valuef
= 2.323423423;
970 obj
= qobject_from_jsonf("%d", value
);
971 g_assert(obj
!= NULL
);
972 g_assert(qobject_type(obj
) == QTYPE_QINT
);
974 qint
= qobject_to_qint(obj
);
975 g_assert(qint_get_int(qint
) == value
);
979 obj
= qobject_from_jsonf("%lld", value_ll
);
980 g_assert(obj
!= NULL
);
981 g_assert(qobject_type(obj
) == QTYPE_QINT
);
983 qint
= qobject_to_qint(obj
);
984 g_assert(qint_get_int(qint
) == value_ll
);
988 obj
= qobject_from_jsonf("%f", valuef
);
989 g_assert(obj
!= NULL
);
990 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
992 qfloat
= qobject_to_qfloat(obj
);
993 g_assert(qfloat_get_double(qfloat
) == valuef
);
998 static void keyword_literal(void)
1005 obj
= qobject_from_json("true");
1006 g_assert(obj
!= NULL
);
1007 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1009 qbool
= qobject_to_qbool(obj
);
1010 g_assert(qbool_get_bool(qbool
) == true);
1012 str
= qobject_to_json(obj
);
1013 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
1018 obj
= qobject_from_json("false");
1019 g_assert(obj
!= NULL
);
1020 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1022 qbool
= qobject_to_qbool(obj
);
1023 g_assert(qbool_get_bool(qbool
) == false);
1025 str
= qobject_to_json(obj
);
1026 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
1031 obj
= qobject_from_jsonf("%i", false);
1032 g_assert(obj
!= NULL
);
1033 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1035 qbool
= qobject_to_qbool(obj
);
1036 g_assert(qbool_get_bool(qbool
) == false);
1040 /* Test that non-zero values other than 1 get collapsed to true */
1041 obj
= qobject_from_jsonf("%i", 2);
1042 g_assert(obj
!= NULL
);
1043 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1045 qbool
= qobject_to_qbool(obj
);
1046 g_assert(qbool_get_bool(qbool
) == true);
1050 obj
= qobject_from_json("null");
1051 g_assert(obj
!= NULL
);
1052 g_assert(qobject_type(obj
) == QTYPE_QNULL
);
1055 g_assert(null
== obj
);
1057 qobject_decref(obj
);
1058 qobject_decref(null
);
1061 typedef struct LiteralQDictEntry LiteralQDictEntry
;
1062 typedef struct LiteralQObject LiteralQObject
;
1064 struct LiteralQObject
1070 LiteralQDictEntry
*qdict
;
1071 LiteralQObject
*qlist
;
1075 struct LiteralQDictEntry
1078 LiteralQObject value
;
1081 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1082 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1083 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1084 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1086 typedef struct QListCompareHelper
1089 LiteralQObject
*objs
;
1091 } QListCompareHelper
;
1093 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
1095 static void compare_helper(QObject
*obj
, void *opaque
)
1097 QListCompareHelper
*helper
= opaque
;
1099 if (helper
->result
== 0) {
1103 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
1108 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
1111 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
1113 if (!rhs
|| lhs
->type
!= qobject_type(rhs
)) {
1117 switch (lhs
->type
) {
1119 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
1121 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
1125 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
1126 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
1128 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
1136 QListCompareHelper helper
;
1139 helper
.objs
= lhs
->value
.qlist
;
1142 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
1144 return helper
.result
;
1153 static void simple_dict(void)
1157 const char *encoded
;
1158 LiteralQObject decoded
;
1161 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
1162 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1163 { "foo", QLIT_QINT(42) },
1164 { "bar", QLIT_QSTR("hello world") },
1169 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1173 .encoded
= "{\"foo\": 43}",
1174 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1175 { "foo", QLIT_QINT(43) },
1182 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1186 obj
= qobject_from_json(test_cases
[i
].encoded
);
1187 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1189 str
= qobject_to_json(obj
);
1190 qobject_decref(obj
);
1192 obj
= qobject_from_json(qstring_get_str(str
));
1193 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1194 qobject_decref(obj
);
1200 * this generates json of the form:
1201 * a(0,m) = [0, 1, ..., m-1]
1206 * 'key(n-1)': a(n-1,m)
1209 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1215 if (nest_level_max
== 0) {
1216 g_string_append(gstr
, "[");
1217 for (i
= 0; i
< elem_count
; i
++) {
1218 g_string_append_printf(gstr
, "%d", i
);
1219 if (i
< elem_count
- 1) {
1220 g_string_append_printf(gstr
, ", ");
1223 g_string_append(gstr
, "]");
1227 g_string_append(gstr
, "{");
1228 for (i
= 0; i
< nest_level_max
; i
++) {
1229 g_string_append_printf(gstr
, "'key%d': ", i
);
1230 gen_test_json(gstr
, i
, elem_count
);
1231 if (i
< nest_level_max
- 1) {
1232 g_string_append(gstr
, ",");
1235 g_string_append(gstr
, "}");
1238 static void large_dict(void)
1240 GString
*gstr
= g_string_new("");
1243 gen_test_json(gstr
, 10, 100);
1244 obj
= qobject_from_json(gstr
->str
);
1245 g_assert(obj
!= NULL
);
1247 qobject_decref(obj
);
1248 g_string_free(gstr
, true);
1251 static void simple_list(void)
1255 const char *encoded
;
1256 LiteralQObject decoded
;
1259 .encoded
= "[43,42]",
1260 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1268 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1275 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1281 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1282 QLIT_QDICT(((LiteralQDictEntry
[]){
1291 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1295 obj
= qobject_from_json(test_cases
[i
].encoded
);
1296 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1298 str
= qobject_to_json(obj
);
1299 qobject_decref(obj
);
1301 obj
= qobject_from_json(qstring_get_str(str
));
1302 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1303 qobject_decref(obj
);
1308 static void simple_whitespace(void)
1312 const char *encoded
;
1313 LiteralQObject decoded
;
1316 .encoded
= " [ 43 , 42 ]",
1317 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1324 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1325 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1327 QLIT_QDICT(((LiteralQDictEntry
[]){
1328 { "h", QLIT_QSTR("b") },
1330 QLIT_QLIST(((LiteralQObject
[]){
1337 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1338 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1340 QLIT_QDICT(((LiteralQDictEntry
[]){
1341 { "h", QLIT_QSTR("b") },
1342 { "a", QLIT_QINT(32) },
1344 QLIT_QLIST(((LiteralQObject
[]){
1353 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1357 obj
= qobject_from_json(test_cases
[i
].encoded
);
1358 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1360 str
= qobject_to_json(obj
);
1361 qobject_decref(obj
);
1363 obj
= qobject_from_json(qstring_get_str(str
));
1364 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1366 qobject_decref(obj
);
1371 static void simple_varargs(void)
1373 QObject
*embedded_obj
;
1375 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
1378 QLIT_QLIST(((LiteralQObject
[]){
1384 embedded_obj
= qobject_from_json("[32, 42]");
1385 g_assert(embedded_obj
!= NULL
);
1387 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
1388 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
1390 qobject_decref(obj
);
1393 static void empty_input(void)
1395 const char *empty
= "";
1397 QObject
*obj
= qobject_from_json(empty
);
1398 g_assert(obj
== NULL
);
1401 static void unterminated_string(void)
1403 QObject
*obj
= qobject_from_json("\"abc");
1404 g_assert(obj
== NULL
);
1407 static void unterminated_sq_string(void)
1409 QObject
*obj
= qobject_from_json("'abc");
1410 g_assert(obj
== NULL
);
1413 static void unterminated_escape(void)
1415 QObject
*obj
= qobject_from_json("\"abc\\\"");
1416 g_assert(obj
== NULL
);
1419 static void unterminated_array(void)
1421 QObject
*obj
= qobject_from_json("[32");
1422 g_assert(obj
== NULL
);
1425 static void unterminated_array_comma(void)
1427 QObject
*obj
= qobject_from_json("[32,");
1428 g_assert(obj
== NULL
);
1431 static void invalid_array_comma(void)
1433 QObject
*obj
= qobject_from_json("[32,}");
1434 g_assert(obj
== NULL
);
1437 static void unterminated_dict(void)
1439 QObject
*obj
= qobject_from_json("{'abc':32");
1440 g_assert(obj
== NULL
);
1443 static void unterminated_dict_comma(void)
1445 QObject
*obj
= qobject_from_json("{'abc':32,");
1446 g_assert(obj
== NULL
);
1449 static void invalid_dict_comma(void)
1451 QObject
*obj
= qobject_from_json("{'abc':32,}");
1452 g_assert(obj
== NULL
);
1455 static void unterminated_literal(void)
1457 QObject
*obj
= qobject_from_json("nul");
1458 g_assert(obj
== NULL
);
1461 static char *make_nest(char *buf
, size_t cnt
)
1463 memset(buf
, '[', cnt
- 1);
1466 memset(buf
+ cnt
+ 1, ']', cnt
- 1);
1471 static void limits_nesting(void)
1473 enum { max_nesting
= 1024 }; /* see qobject/json-streamer.c */
1474 char buf
[2 * (max_nesting
+ 1) + 1];
1477 obj
= qobject_from_json(make_nest(buf
, max_nesting
));
1478 g_assert(obj
!= NULL
);
1479 qobject_decref(obj
);
1481 obj
= qobject_from_json(make_nest(buf
, max_nesting
+ 1));
1482 g_assert(obj
== NULL
);
1485 int main(int argc
, char **argv
)
1487 g_test_init(&argc
, &argv
, NULL
);
1489 g_test_add_func("/literals/string/simple", simple_string
);
1490 g_test_add_func("/literals/string/escaped", escaped_string
);
1491 g_test_add_func("/literals/string/utf8", utf8_string
);
1492 g_test_add_func("/literals/string/single_quote", single_quote_string
);
1493 g_test_add_func("/literals/string/vararg", vararg_string
);
1495 g_test_add_func("/literals/number/simple", simple_number
);
1496 g_test_add_func("/literals/number/float", float_number
);
1497 g_test_add_func("/literals/number/vararg", vararg_number
);
1499 g_test_add_func("/literals/keyword", keyword_literal
);
1501 g_test_add_func("/dicts/simple_dict", simple_dict
);
1502 g_test_add_func("/dicts/large_dict", large_dict
);
1503 g_test_add_func("/lists/simple_list", simple_list
);
1505 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1507 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1509 g_test_add_func("/errors/empty_input", empty_input
);
1510 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1511 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1512 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1513 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1514 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1515 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1516 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1517 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1518 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1519 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1520 g_test_add_func("/errors/limits/nesting", limits_nesting
);
1522 return g_test_run();