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 (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(obj
!= NULL
);
1188 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
1190 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1192 str
= qobject_to_json(obj
);
1193 qobject_decref(obj
);
1195 obj
= qobject_from_json(qstring_get_str(str
));
1196 g_assert(obj
!= NULL
);
1197 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
1199 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1200 qobject_decref(obj
);
1206 * this generates json of the form:
1207 * a(0,m) = [0, 1, ..., m-1]
1212 * 'key(n-1)': a(n-1,m)
1215 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1221 if (nest_level_max
== 0) {
1222 g_string_append(gstr
, "[");
1223 for (i
= 0; i
< elem_count
; i
++) {
1224 g_string_append_printf(gstr
, "%d", i
);
1225 if (i
< elem_count
- 1) {
1226 g_string_append_printf(gstr
, ", ");
1229 g_string_append(gstr
, "]");
1233 g_string_append(gstr
, "{");
1234 for (i
= 0; i
< nest_level_max
; i
++) {
1235 g_string_append_printf(gstr
, "'key%d': ", i
);
1236 gen_test_json(gstr
, i
, elem_count
);
1237 if (i
< nest_level_max
- 1) {
1238 g_string_append(gstr
, ",");
1241 g_string_append(gstr
, "}");
1244 static void large_dict(void)
1246 GString
*gstr
= g_string_new("");
1249 gen_test_json(gstr
, 10, 100);
1250 obj
= qobject_from_json(gstr
->str
);
1251 g_assert(obj
!= NULL
);
1253 qobject_decref(obj
);
1254 g_string_free(gstr
, true);
1257 static void simple_list(void)
1261 const char *encoded
;
1262 LiteralQObject decoded
;
1265 .encoded
= "[43,42]",
1266 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1274 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1281 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1287 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1288 QLIT_QDICT(((LiteralQDictEntry
[]){
1297 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1301 obj
= qobject_from_json(test_cases
[i
].encoded
);
1302 g_assert(obj
!= NULL
);
1303 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1305 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1307 str
= qobject_to_json(obj
);
1308 qobject_decref(obj
);
1310 obj
= qobject_from_json(qstring_get_str(str
));
1311 g_assert(obj
!= NULL
);
1312 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1314 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1315 qobject_decref(obj
);
1320 static void simple_whitespace(void)
1324 const char *encoded
;
1325 LiteralQObject decoded
;
1328 .encoded
= " [ 43 , 42 ]",
1329 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1336 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1337 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1339 QLIT_QDICT(((LiteralQDictEntry
[]){
1340 { "h", QLIT_QSTR("b") },
1342 QLIT_QLIST(((LiteralQObject
[]){
1349 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1350 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1352 QLIT_QDICT(((LiteralQDictEntry
[]){
1353 { "h", QLIT_QSTR("b") },
1354 { "a", QLIT_QINT(32) },
1356 QLIT_QLIST(((LiteralQObject
[]){
1365 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1369 obj
= qobject_from_json(test_cases
[i
].encoded
);
1370 g_assert(obj
!= NULL
);
1371 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1373 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1375 str
= qobject_to_json(obj
);
1376 qobject_decref(obj
);
1378 obj
= qobject_from_json(qstring_get_str(str
));
1379 g_assert(obj
!= NULL
);
1380 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1382 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1384 qobject_decref(obj
);
1389 static void simple_varargs(void)
1391 QObject
*embedded_obj
;
1393 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
1396 QLIT_QLIST(((LiteralQObject
[]){
1402 embedded_obj
= qobject_from_json("[32, 42]");
1403 g_assert(embedded_obj
!= NULL
);
1405 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
1406 g_assert(obj
!= NULL
);
1408 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
1410 qobject_decref(obj
);
1413 static void empty_input(void)
1415 const char *empty
= "";
1417 QObject
*obj
= qobject_from_json(empty
);
1418 g_assert(obj
== NULL
);
1421 static void unterminated_string(void)
1423 QObject
*obj
= qobject_from_json("\"abc");
1424 g_assert(obj
== NULL
);
1427 static void unterminated_sq_string(void)
1429 QObject
*obj
= qobject_from_json("'abc");
1430 g_assert(obj
== NULL
);
1433 static void unterminated_escape(void)
1435 QObject
*obj
= qobject_from_json("\"abc\\\"");
1436 g_assert(obj
== NULL
);
1439 static void unterminated_array(void)
1441 QObject
*obj
= qobject_from_json("[32");
1442 g_assert(obj
== NULL
);
1445 static void unterminated_array_comma(void)
1447 QObject
*obj
= qobject_from_json("[32,");
1448 g_assert(obj
== NULL
);
1451 static void invalid_array_comma(void)
1453 QObject
*obj
= qobject_from_json("[32,}");
1454 g_assert(obj
== NULL
);
1457 static void unterminated_dict(void)
1459 QObject
*obj
= qobject_from_json("{'abc':32");
1460 g_assert(obj
== NULL
);
1463 static void unterminated_dict_comma(void)
1465 QObject
*obj
= qobject_from_json("{'abc':32,");
1466 g_assert(obj
== NULL
);
1469 static void invalid_dict_comma(void)
1471 QObject
*obj
= qobject_from_json("{'abc':32,}");
1472 g_assert(obj
== NULL
);
1475 static void unterminated_literal(void)
1477 QObject
*obj
= qobject_from_json("nul");
1478 g_assert(obj
== NULL
);
1481 static char *make_nest(char *buf
, size_t cnt
)
1483 memset(buf
, '[', cnt
- 1);
1486 memset(buf
+ cnt
+ 1, ']', cnt
- 1);
1491 static void limits_nesting(void)
1493 enum { max_nesting
= 1024 }; /* see qobject/json-streamer.c */
1494 char buf
[2 * (max_nesting
+ 1) + 1];
1497 obj
= qobject_from_json(make_nest(buf
, max_nesting
));
1498 g_assert(obj
!= NULL
);
1499 qobject_decref(obj
);
1501 obj
= qobject_from_json(make_nest(buf
, max_nesting
+ 1));
1502 g_assert(obj
== NULL
);
1505 int main(int argc
, char **argv
)
1507 g_test_init(&argc
, &argv
, NULL
);
1509 g_test_add_func("/literals/string/simple", simple_string
);
1510 g_test_add_func("/literals/string/escaped", escaped_string
);
1511 g_test_add_func("/literals/string/utf8", utf8_string
);
1512 g_test_add_func("/literals/string/single_quote", single_quote_string
);
1513 g_test_add_func("/literals/string/vararg", vararg_string
);
1515 g_test_add_func("/literals/number/simple", simple_number
);
1516 g_test_add_func("/literals/number/float", float_number
);
1517 g_test_add_func("/literals/number/vararg", vararg_number
);
1519 g_test_add_func("/literals/keyword", keyword_literal
);
1521 g_test_add_func("/dicts/simple_dict", simple_dict
);
1522 g_test_add_func("/dicts/large_dict", large_dict
);
1523 g_test_add_func("/lists/simple_list", simple_list
);
1525 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1527 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1529 g_test_add_func("/errors/empty_input", empty_input
);
1530 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1531 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1532 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1533 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1534 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1535 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1536 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1537 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1538 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1539 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1540 g_test_add_func("/errors/limits/nesting", limits_nesting
);
1542 return g_test_run();