2 * Copyright IBM, Corp. 2009
3 * Copyright (c) 2013, 2015 Red Hat Inc.
6 * Anthony Liguori <aliguori@us.ibm.com>
7 * Markus Armbruster <armbru@redhat.com>
9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 * See the COPYING.LIB file in the top-level directory.
14 #include "qemu/osdep.h"
16 #include "qapi/error.h"
17 #include "qapi/qmp/qbool.h"
18 #include "qapi/qmp/qjson.h"
19 #include "qapi/qmp/qlit.h"
20 #include "qapi/qmp/qnull.h"
21 #include "qapi/qmp/qnum.h"
22 #include "qapi/qmp/qstring.h"
23 #include "qemu-common.h"
25 static void escaped_string(void)
39 { "\"\\/\"", "/", .skip
= 1 },
42 { "\"hello world \\\"embedded string\\\"\"",
43 "hello world \"embedded string\"" },
44 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
45 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip
= 1 },
46 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
47 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
48 { "'\\b'", "\b", .skip
= 1 },
49 { "'\\f'", "\f", .skip
= 1 },
50 { "'\\n'", "\n", .skip
= 1 },
51 { "'\\r'", "\r", .skip
= 1 },
52 { "'\\t'", "\t", .skip
= 1 },
53 { "'\\/'", "/", .skip
= 1 },
54 { "'\\\\'", "\\", .skip
= 1 },
58 for (i
= 0; test_cases
[i
].encoded
; i
++) {
62 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
63 str
= qobject_to(QString
, obj
);
65 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].decoded
);
67 if (test_cases
[i
].skip
== 0) {
68 str
= qobject_to_json(obj
);
69 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].encoded
);
77 static void simple_string(void)
84 { "\"hello world\"", "hello world" },
85 { "\"the quick brown fox jumped over the fence\"",
86 "the quick brown fox jumped over the fence" },
90 for (i
= 0; test_cases
[i
].encoded
; i
++) {
94 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
95 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
, &error_abort
);
126 str
= qobject_to(QString
, obj
);
128 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
134 static void utf8_string(void)
137 * FIXME Current behavior for invalid UTF-8 sequences is
138 * incorrect. This test expects current, incorrect results.
139 * They're all marked "bug:" below, and are to be replaced by
140 * correct ones as the bugs get fixed.
142 * The JSON parser rejects some invalid sequences, but accepts
143 * others without correcting the problem.
145 * We should either reject all invalid sequences, or minimize
146 * overlong sequences and replace all other invalid sequences by a
147 * suitable replacement character. A common choice for
148 * replacement is U+FFFD.
150 * Problem: we can't easily deal with embedded U+0000. Parsing
151 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
152 * which gets misinterpreted as NUL-terminated "this ". We should
153 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
156 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
157 * capability and stress test at
158 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
160 static const struct {
162 const char *utf8_out
;
163 const char *json_out
; /* defaults to @json_in */
164 const char *utf8_in
; /* defaults to @utf8_out */
167 * Bug markers used here:
168 * - bug: not corrected
169 * JSON parser fails to correct invalid sequence(s)
171 * JSON parser rejects invalid sequence(s)
172 * We may choose to define this as feature
174 * JSON parser produces incorrect result, this is the
175 * correct one, assuming replacement character U+FFFF
176 * We may choose to reject instead of replace
179 /* 1 Some correct UTF-8 text */
181 /* a bit of German */
182 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
183 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
184 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
185 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
186 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
187 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
191 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
192 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
193 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
195 /* 2 Boundary condition test cases */
196 /* 2.1 First possible sequence of a certain length */
197 /* 2.1.1 1 byte U+0000 */
200 "", /* bug: want overlong "\xC0\x80" */
204 /* 2.1.2 2 bytes U+0080 */
210 /* 2.1.3 3 bytes U+0800 */
216 /* 2.1.4 4 bytes U+10000 */
218 "\"\xF0\x90\x80\x80\"",
220 "\"\\uD800\\uDC00\"",
222 /* 2.1.5 5 bytes U+200000 */
224 "\"\xF8\x88\x80\x80\x80\"",
225 NULL
, /* bug: rejected */
227 "\xF8\x88\x80\x80\x80",
229 /* 2.1.6 6 bytes U+4000000 */
231 "\"\xFC\x84\x80\x80\x80\x80\"",
232 NULL
, /* bug: rejected */
234 "\xFC\x84\x80\x80\x80\x80",
236 /* 2.2 Last possible sequence of a certain length */
237 /* 2.2.1 1 byte U+007F */
243 /* 2.2.2 2 bytes U+07FF */
250 * 2.2.3 3 bytes U+FFFC
251 * The last possible sequence is actually U+FFFF. But that's
252 * a noncharacter, and already covered by its own test case
253 * under 5.3. Same for U+FFFE. U+FFFD is the last character
254 * in the BMP, and covered under 2.3. Because of U+FFFD's
255 * special role as replacement character, it's worth testing
263 /* 2.2.4 4 bytes U+1FFFFF */
265 "\"\xF7\xBF\xBF\xBF\"",
266 NULL
, /* bug: rejected */
270 /* 2.2.5 5 bytes U+3FFFFFF */
272 "\"\xFB\xBF\xBF\xBF\xBF\"",
273 NULL
, /* bug: rejected */
275 "\xFB\xBF\xBF\xBF\xBF",
277 /* 2.2.6 6 bytes U+7FFFFFFF */
279 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
280 NULL
, /* bug: rejected */
282 "\xFD\xBF\xBF\xBF\xBF\xBF",
284 /* 2.3 Other boundary conditions */
286 /* last one before surrogate range: U+D7FF */
292 /* first one after surrogate range: U+E000 */
298 /* last one in BMP: U+FFFD */
304 /* last one in last plane: U+10FFFD */
305 "\"\xF4\x8F\xBF\xBD\"",
310 /* first one beyond Unicode range: U+110000 */
311 "\"\xF4\x90\x80\x80\"",
315 /* 3 Malformed sequences */
316 /* 3.1 Unexpected continuation bytes */
317 /* 3.1.1 First continuation byte */
320 "\x80", /* bug: not corrected */
323 /* 3.1.2 Last continuation byte */
326 "\xBF", /* bug: not corrected */
329 /* 3.1.3 2 continuation bytes */
332 "\x80\xBF", /* bug: not corrected */
333 "\"\\uFFFD\\uFFFD\"",
335 /* 3.1.4 3 continuation bytes */
338 "\x80\xBF\x80", /* bug: not corrected */
339 "\"\\uFFFD\\uFFFD\\uFFFD\"",
341 /* 3.1.5 4 continuation bytes */
343 "\"\x80\xBF\x80\xBF\"",
344 "\x80\xBF\x80\xBF", /* bug: not corrected */
345 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
347 /* 3.1.6 5 continuation bytes */
349 "\"\x80\xBF\x80\xBF\x80\"",
350 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
351 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
353 /* 3.1.7 6 continuation bytes */
355 "\"\x80\xBF\x80\xBF\x80\xBF\"",
356 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
357 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
359 /* 3.1.8 7 continuation bytes */
361 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
362 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
363 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
365 /* 3.1.9 Sequence of all 64 possible continuation bytes */
367 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
368 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
369 "\x90\x91\x92\x93\x94\x95\x96\x97"
370 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
371 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
372 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
373 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
374 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
375 /* bug: not corrected */
376 "\x80\x81\x82\x83\x84\x85\x86\x87"
377 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
378 "\x90\x91\x92\x93\x94\x95\x96\x97"
379 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
380 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
381 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
382 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
383 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
384 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
385 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
386 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
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\""
393 /* 3.2 Lonely start characters */
394 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
396 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
397 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
398 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
399 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
400 NULL
, /* bug: rejected */
401 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
402 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
403 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
404 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
405 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
406 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
407 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
408 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
410 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
412 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
413 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
414 /* bug: not corrected */
415 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
416 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
417 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
418 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
420 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
422 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
423 NULL
, /* bug: rejected */
424 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
425 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
427 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
429 "\"\xF8 \xF9 \xFA \xFB \"",
430 NULL
, /* bug: rejected */
431 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
432 "\xF8 \xF9 \xFA \xFB ",
434 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
437 NULL
, /* bug: rejected */
438 "\"\\uFFFD \\uFFFD \"",
441 /* 3.3 Sequences with last continuation byte missing */
442 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
445 NULL
, /* bug: rejected */
449 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
452 "\xE0\x80", /* bug: not corrected */
455 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
458 "\xF0\x80\x80", /* bug: not corrected */
461 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
463 "\"\xF8\x80\x80\x80\"",
464 NULL
, /* bug: rejected */
468 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
470 "\"\xFC\x80\x80\x80\x80\"",
471 NULL
, /* bug: rejected */
473 "\xFC\x80\x80\x80\x80",
475 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
478 "\xDF", /* bug: not corrected */
481 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
484 "\xEF\xBF", /* bug: not corrected */
487 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
490 NULL
, /* bug: rejected */
494 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
496 "\"\xFB\xBF\xBF\xBF\"",
497 NULL
, /* bug: rejected */
501 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
503 "\"\xFD\xBF\xBF\xBF\xBF\"",
504 NULL
, /* bug: rejected */
506 "\xFD\xBF\xBF\xBF\xBF",
508 /* 3.4 Concatenation of incomplete sequences */
510 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
511 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
512 NULL
, /* bug: rejected */
513 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
514 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
515 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
516 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
518 /* 3.5 Impossible bytes */
521 NULL
, /* bug: rejected */
527 NULL
, /* bug: rejected */
532 "\"\xFE\xFE\xFF\xFF\"",
533 NULL
, /* bug: rejected */
534 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
537 /* 4 Overlong sequences */
538 /* 4.1 Overlong '/' */
541 NULL
, /* bug: rejected */
547 "\xE0\x80\xAF", /* bug: not corrected */
551 "\"\xF0\x80\x80\xAF\"",
552 "\xF0\x80\x80\xAF", /* bug: not corrected */
556 "\"\xF8\x80\x80\x80\xAF\"",
557 NULL
, /* bug: rejected */
559 "\xF8\x80\x80\x80\xAF",
562 "\"\xFC\x80\x80\x80\x80\xAF\"",
563 NULL
, /* bug: rejected */
565 "\xFC\x80\x80\x80\x80\xAF",
568 * 4.2 Maximum overlong sequences
569 * Highest Unicode value that is still resulting in an
570 * overlong sequence if represented with the given number of
571 * bytes. This is a boundary test for safe UTF-8 decoders.
576 NULL
, /* bug: rejected */
583 "\xE0\x9F\xBF", /* bug: not corrected */
589 * The actual maximum would be U+FFFF, but that's a
590 * noncharacter. Testing U+FFFC seems more useful. See
593 "\"\xF0\x8F\xBF\xBC\"",
594 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
599 "\"\xF8\x87\xBF\xBF\xBF\"",
600 NULL
, /* bug: rejected */
602 "\xF8\x87\xBF\xBF\xBF",
606 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
607 NULL
, /* bug: rejected */
609 "\xFC\x83\xBF\xBF\xBF\xBF",
611 /* 4.3 Overlong representation of the NUL character */
615 NULL
, /* bug: rejected */
622 "\xE0\x80\x80", /* bug: not corrected */
627 "\"\xF0\x80\x80\x80\"",
628 "\xF0\x80\x80\x80", /* bug: not corrected */
633 "\"\xF8\x80\x80\x80\x80\"",
634 NULL
, /* bug: rejected */
636 "\xF8\x80\x80\x80\x80",
640 "\"\xFC\x80\x80\x80\x80\x80\"",
641 NULL
, /* bug: rejected */
643 "\xFC\x80\x80\x80\x80\x80",
645 /* 5 Illegal code positions */
646 /* 5.1 Single UTF-16 surrogates */
650 "\xED\xA0\x80", /* bug: not corrected */
656 "\xED\xAD\xBF", /* bug: not corrected */
662 "\xED\xAE\x80", /* bug: not corrected */
668 "\xED\xAF\xBF", /* bug: not corrected */
674 "\xED\xB0\x80", /* bug: not corrected */
680 "\xED\xBE\x80", /* bug: not corrected */
686 "\xED\xBF\xBF", /* bug: not corrected */
689 /* 5.2 Paired UTF-16 surrogates */
692 "\"\xED\xA0\x80\xED\xB0\x80\"",
693 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
694 "\"\\uFFFD\\uFFFD\"",
698 "\"\xED\xA0\x80\xED\xBF\xBF\"",
699 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
700 "\"\\uFFFD\\uFFFD\"",
704 "\"\xED\xAD\xBF\xED\xB0\x80\"",
705 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
706 "\"\\uFFFD\\uFFFD\"",
710 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
711 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
712 "\"\\uFFFD\\uFFFD\"",
716 "\"\xED\xAE\x80\xED\xB0\x80\"",
717 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
718 "\"\\uFFFD\\uFFFD\"",
722 "\"\xED\xAE\x80\xED\xBF\xBF\"",
723 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
724 "\"\\uFFFD\\uFFFD\"",
728 "\"\xED\xAF\xBF\xED\xB0\x80\"",
729 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
730 "\"\\uFFFD\\uFFFD\"",
734 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
735 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
736 "\"\\uFFFD\\uFFFD\"",
738 /* 5.3 Other illegal code positions */
739 /* BMP noncharacters */
743 "\xEF\xBF\xBE", /* bug: not corrected */
749 "\xEF\xBF\xBF", /* bug: not corrected */
755 "\xEF\xB7\x90", /* bug: not corrected */
761 "\xEF\xB7\xAF", /* bug: not corrected */
764 /* Plane 1 .. 16 noncharacters */
766 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
767 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
768 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
769 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
770 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
771 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
772 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
773 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
774 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
775 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
776 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
777 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
778 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
779 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
780 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
781 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
782 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
783 /* bug: not corrected */
784 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
785 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
786 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
787 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
788 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
789 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
790 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
791 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
792 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
793 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
794 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
795 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
796 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
797 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
798 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
799 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
800 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
801 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
802 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
803 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
810 const char *json_in
, *utf8_out
, *utf8_in
, *json_out
;
812 for (i
= 0; test_cases
[i
].json_in
; i
++) {
813 json_in
= test_cases
[i
].json_in
;
814 utf8_out
= test_cases
[i
].utf8_out
;
815 utf8_in
= test_cases
[i
].utf8_in
?: test_cases
[i
].utf8_out
;
816 json_out
= test_cases
[i
].json_out
?: test_cases
[i
].json_in
;
818 obj
= qobject_from_json(json_in
, utf8_out
? &error_abort
: NULL
);
820 str
= qobject_to(QString
, obj
);
822 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
828 obj
= QOBJECT(qstring_from_str(utf8_in
));
829 str
= qobject_to_json(obj
);
832 g_assert_cmpstr(qstring_get_str(str
), ==, json_out
);
840 * Disabled, because qobject_from_json() is buggy, and I can't
841 * be bothered to add the expected incorrect results.
842 * FIXME Enable once these bugs have been fixed.
844 if (0 && json_out
!= json_in
) {
845 obj
= qobject_from_json(json_out
, &error_abort
);
846 str
= qobject_to(QString
, obj
);
848 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
853 static void vararg_string(void)
860 { "the quick brown fox jumped over the fence" },
864 for (i
= 0; test_cases
[i
].decoded
; i
++) {
867 str
= qobject_to(QString
,
868 qobject_from_jsonf("%s", test_cases
[i
].decoded
));
870 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
876 static void simple_number(void)
888 { "-0", 0, .skip
= 1 },
892 for (i
= 0; test_cases
[i
].encoded
; i
++) {
896 qnum
= qobject_to(QNum
,
897 qobject_from_json(test_cases
[i
].encoded
,
900 g_assert(qnum_get_try_int(qnum
, &val
));
901 g_assert_cmpint(val
, ==, test_cases
[i
].decoded
);
902 if (test_cases
[i
].skip
== 0) {
905 str
= qobject_to_json(QOBJECT(qnum
));
906 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
914 static void large_number(void)
916 const char *maxu64
= "18446744073709551615"; /* 2^64-1 */
917 const char *gtu64
= "18446744073709551616"; /* 2^64 */
918 const char *lti64
= "-9223372036854775809"; /* -2^63 - 1 */
924 qnum
= qobject_to(QNum
, qobject_from_json(maxu64
, &error_abort
));
926 g_assert_cmpuint(qnum_get_uint(qnum
), ==, 18446744073709551615U);
927 g_assert(!qnum_get_try_int(qnum
, &ival
));
929 str
= qobject_to_json(QOBJECT(qnum
));
930 g_assert_cmpstr(qstring_get_str(str
), ==, maxu64
);
934 qnum
= qobject_to(QNum
, qobject_from_json(gtu64
, &error_abort
));
936 g_assert_cmpfloat(qnum_get_double(qnum
), ==, 18446744073709552e3
);
937 g_assert(!qnum_get_try_uint(qnum
, &val
));
938 g_assert(!qnum_get_try_int(qnum
, &ival
));
940 str
= qobject_to_json(QOBJECT(qnum
));
941 g_assert_cmpstr(qstring_get_str(str
), ==, gtu64
);
945 qnum
= qobject_to(QNum
, qobject_from_json(lti64
, &error_abort
));
947 g_assert_cmpfloat(qnum_get_double(qnum
), ==, -92233720368547758e2
);
948 g_assert(!qnum_get_try_uint(qnum
, &val
));
949 g_assert(!qnum_get_try_int(qnum
, &ival
));
951 str
= qobject_to_json(QOBJECT(qnum
));
952 g_assert_cmpstr(qstring_get_str(str
), ==, "-9223372036854775808");
957 static void float_number(void)
967 { "-32.12313", -32.12313 },
968 { "-32.20e-10", -32.20e-10, .skip
= 1 },
972 for (i
= 0; test_cases
[i
].encoded
; i
++) {
976 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
977 qnum
= qobject_to(QNum
, obj
);
979 g_assert(qnum_get_double(qnum
) == test_cases
[i
].decoded
);
981 if (test_cases
[i
].skip
== 0) {
984 str
= qobject_to_json(obj
);
985 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
993 static void vararg_number(void)
997 long long value_ll
= 0x2342342343LL
;
998 double valuef
= 2.323423423;
1001 qnum
= qobject_to(QNum
, qobject_from_jsonf("%d", value
));
1002 g_assert(qnum_get_try_int(qnum
, &val
));
1003 g_assert_cmpint(val
, ==, value
);
1006 qnum
= qobject_to(QNum
, qobject_from_jsonf("%lld", value_ll
));
1007 g_assert(qnum_get_try_int(qnum
, &val
));
1008 g_assert_cmpint(val
, ==, value_ll
);
1011 qnum
= qobject_to(QNum
, qobject_from_jsonf("%f", valuef
));
1012 g_assert(qnum_get_double(qnum
) == valuef
);
1016 static void keyword_literal(void)
1023 obj
= qobject_from_json("true", &error_abort
);
1024 qbool
= qobject_to(QBool
, obj
);
1026 g_assert(qbool_get_bool(qbool
) == true);
1028 str
= qobject_to_json(obj
);
1029 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
1034 obj
= qobject_from_json("false", &error_abort
);
1035 qbool
= qobject_to(QBool
, obj
);
1037 g_assert(qbool_get_bool(qbool
) == false);
1039 str
= qobject_to_json(obj
);
1040 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
1045 qbool
= qobject_to(QBool
, qobject_from_jsonf("%i", false));
1047 g_assert(qbool_get_bool(qbool
) == false);
1050 /* Test that non-zero values other than 1 get collapsed to true */
1051 qbool
= qobject_to(QBool
, qobject_from_jsonf("%i", 2));
1053 g_assert(qbool_get_bool(qbool
) == true);
1056 obj
= qobject_from_json("null", &error_abort
);
1057 g_assert(obj
!= NULL
);
1058 g_assert(qobject_type(obj
) == QTYPE_QNULL
);
1061 g_assert(QOBJECT(null
) == obj
);
1063 qobject_decref(obj
);
1067 static void simple_dict(void)
1071 const char *encoded
;
1075 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
1076 .decoded
= QLIT_QDICT(((QLitDictEntry
[]){
1077 { "foo", QLIT_QNUM(42) },
1078 { "bar", QLIT_QSTR("hello world") },
1083 .decoded
= QLIT_QDICT(((QLitDictEntry
[]){
1087 .encoded
= "{\"foo\": 43}",
1088 .decoded
= QLIT_QDICT(((QLitDictEntry
[]){
1089 { "foo", QLIT_QNUM(43) },
1096 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1100 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1101 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1103 str
= qobject_to_json(obj
);
1104 qobject_decref(obj
);
1106 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1107 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1108 qobject_decref(obj
);
1114 * this generates json of the form:
1115 * a(0,m) = [0, 1, ..., m-1]
1120 * 'key(n-1)': a(n-1,m)
1123 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1129 if (nest_level_max
== 0) {
1130 g_string_append(gstr
, "[");
1131 for (i
= 0; i
< elem_count
; i
++) {
1132 g_string_append_printf(gstr
, "%d", i
);
1133 if (i
< elem_count
- 1) {
1134 g_string_append_printf(gstr
, ", ");
1137 g_string_append(gstr
, "]");
1141 g_string_append(gstr
, "{");
1142 for (i
= 0; i
< nest_level_max
; i
++) {
1143 g_string_append_printf(gstr
, "'key%d': ", i
);
1144 gen_test_json(gstr
, i
, elem_count
);
1145 if (i
< nest_level_max
- 1) {
1146 g_string_append(gstr
, ",");
1149 g_string_append(gstr
, "}");
1152 static void large_dict(void)
1154 GString
*gstr
= g_string_new("");
1157 gen_test_json(gstr
, 10, 100);
1158 obj
= qobject_from_json(gstr
->str
, &error_abort
);
1159 g_assert(obj
!= NULL
);
1161 qobject_decref(obj
);
1162 g_string_free(gstr
, true);
1165 static void simple_list(void)
1169 const char *encoded
;
1173 .encoded
= "[43,42]",
1174 .decoded
= QLIT_QLIST(((QLitObject
[]){
1182 .decoded
= QLIT_QLIST(((QLitObject
[]){
1189 .decoded
= QLIT_QLIST(((QLitObject
[]){
1195 .decoded
= QLIT_QLIST(((QLitObject
[]){
1196 QLIT_QDICT(((QLitDictEntry
[]){
1205 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1209 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1210 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1212 str
= qobject_to_json(obj
);
1213 qobject_decref(obj
);
1215 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1216 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1217 qobject_decref(obj
);
1222 static void simple_whitespace(void)
1226 const char *encoded
;
1230 .encoded
= " [ 43 , 42 ]",
1231 .decoded
= QLIT_QLIST(((QLitObject
[]){
1238 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1239 .decoded
= QLIT_QLIST(((QLitObject
[]){
1241 QLIT_QDICT(((QLitDictEntry
[]){
1242 { "h", QLIT_QSTR("b") },
1244 QLIT_QLIST(((QLitObject
[]){
1251 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1252 .decoded
= QLIT_QLIST(((QLitObject
[]){
1254 QLIT_QDICT(((QLitDictEntry
[]){
1255 { "h", QLIT_QSTR("b") },
1256 { "a", QLIT_QNUM(32) },
1258 QLIT_QLIST(((QLitObject
[]){
1267 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1271 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1272 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1274 str
= qobject_to_json(obj
);
1275 qobject_decref(obj
);
1277 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1278 g_assert(qlit_equal_qobject(&test_cases
[i
].decoded
, obj
));
1280 qobject_decref(obj
);
1285 static void simple_varargs(void)
1287 QObject
*embedded_obj
;
1289 QLitObject decoded
= QLIT_QLIST(((QLitObject
[]){
1292 QLIT_QLIST(((QLitObject
[]){
1298 embedded_obj
= qobject_from_json("[32, 42]", &error_abort
);
1299 g_assert(embedded_obj
!= NULL
);
1301 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
1302 g_assert(qlit_equal_qobject(&decoded
, obj
));
1304 qobject_decref(obj
);
1307 static void empty_input(void)
1309 const char *empty
= "";
1310 QObject
*obj
= qobject_from_json(empty
, &error_abort
);
1311 g_assert(obj
== NULL
);
1314 static void unterminated_string(void)
1317 QObject
*obj
= qobject_from_json("\"abc", &err
);
1318 g_assert(!err
); /* BUG */
1319 g_assert(obj
== NULL
);
1322 static void unterminated_sq_string(void)
1325 QObject
*obj
= qobject_from_json("'abc", &err
);
1326 g_assert(!err
); /* BUG */
1327 g_assert(obj
== NULL
);
1330 static void unterminated_escape(void)
1333 QObject
*obj
= qobject_from_json("\"abc\\\"", &err
);
1334 g_assert(!err
); /* BUG */
1335 g_assert(obj
== NULL
);
1338 static void unterminated_array(void)
1341 QObject
*obj
= qobject_from_json("[32", &err
);
1342 g_assert(!err
); /* BUG */
1343 g_assert(obj
== NULL
);
1346 static void unterminated_array_comma(void)
1349 QObject
*obj
= qobject_from_json("[32,", &err
);
1350 g_assert(!err
); /* BUG */
1351 g_assert(obj
== NULL
);
1354 static void invalid_array_comma(void)
1357 QObject
*obj
= qobject_from_json("[32,}", &err
);
1358 error_free_or_abort(&err
);
1359 g_assert(obj
== NULL
);
1362 static void unterminated_dict(void)
1365 QObject
*obj
= qobject_from_json("{'abc':32", &err
);
1366 g_assert(!err
); /* BUG */
1367 g_assert(obj
== NULL
);
1370 static void unterminated_dict_comma(void)
1373 QObject
*obj
= qobject_from_json("{'abc':32,", &err
);
1374 g_assert(!err
); /* BUG */
1375 g_assert(obj
== NULL
);
1378 static void invalid_dict_comma(void)
1381 QObject
*obj
= qobject_from_json("{'abc':32,}", &err
);
1382 error_free_or_abort(&err
);
1383 g_assert(obj
== NULL
);
1386 static void unterminated_literal(void)
1389 QObject
*obj
= qobject_from_json("nul", &err
);
1390 error_free_or_abort(&err
);
1391 g_assert(obj
== NULL
);
1394 static char *make_nest(char *buf
, size_t cnt
)
1396 memset(buf
, '[', cnt
- 1);
1399 memset(buf
+ cnt
+ 1, ']', cnt
- 1);
1404 static void limits_nesting(void)
1407 enum { max_nesting
= 1024 }; /* see qobject/json-streamer.c */
1408 char buf
[2 * (max_nesting
+ 1) + 1];
1411 obj
= qobject_from_json(make_nest(buf
, max_nesting
), &error_abort
);
1412 g_assert(obj
!= NULL
);
1413 qobject_decref(obj
);
1415 obj
= qobject_from_json(make_nest(buf
, max_nesting
+ 1), &err
);
1416 error_free_or_abort(&err
);
1417 g_assert(obj
== NULL
);
1420 int main(int argc
, char **argv
)
1422 g_test_init(&argc
, &argv
, NULL
);
1424 g_test_add_func("/literals/string/simple", simple_string
);
1425 g_test_add_func("/literals/string/escaped", escaped_string
);
1426 g_test_add_func("/literals/string/utf8", utf8_string
);
1427 g_test_add_func("/literals/string/single_quote", single_quote_string
);
1428 g_test_add_func("/literals/string/vararg", vararg_string
);
1430 g_test_add_func("/literals/number/simple", simple_number
);
1431 g_test_add_func("/literals/number/large", large_number
);
1432 g_test_add_func("/literals/number/float", float_number
);
1433 g_test_add_func("/literals/number/vararg", vararg_number
);
1435 g_test_add_func("/literals/keyword", keyword_literal
);
1437 g_test_add_func("/dicts/simple_dict", simple_dict
);
1438 g_test_add_func("/dicts/large_dict", large_dict
);
1439 g_test_add_func("/lists/simple_list", simple_list
);
1441 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1443 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1445 g_test_add_func("/errors/empty_input", empty_input
);
1446 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1447 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1448 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1449 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1450 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1451 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1452 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1453 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1454 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1455 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1456 g_test_add_func("/errors/limits/nesting", limits_nesting
);
1458 return g_test_run();