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"
16 #include "qapi/qmp/qstring.h"
17 #include "qapi/qmp/qint.h"
18 #include "qapi/qmp/qdict.h"
19 #include "qapi/qmp/qlist.h"
20 #include "qapi/qmp/qfloat.h"
21 #include "qapi/qmp/qbool.h"
22 #include "qapi/qmp/qjson.h"
24 #include "qemu-common.h"
26 static void escaped_string(void)
40 { "\"\\/\"", "/", .skip
= 1 },
43 { "\"hello world \\\"embedded string\\\"\"",
44 "hello world \"embedded string\"" },
45 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
46 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip
= 1 },
47 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
48 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
49 { "'\\b'", "\b", .skip
= 1 },
50 { "'\\f'", "\f", .skip
= 1 },
51 { "'\\n'", "\n", .skip
= 1 },
52 { "'\\r'", "\r", .skip
= 1 },
53 { "'\\t'", "\t", .skip
= 1 },
54 { "'\\/'", "/", .skip
= 1 },
55 { "'\\\\'", "\\", .skip
= 1 },
59 for (i
= 0; test_cases
[i
].encoded
; i
++) {
63 obj
= qobject_from_json(test_cases
[i
].encoded
);
65 g_assert(obj
!= NULL
);
66 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
68 str
= qobject_to_qstring(obj
);
69 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].decoded
);
71 if (test_cases
[i
].skip
== 0) {
72 str
= qobject_to_json(obj
);
73 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].encoded
);
81 static void simple_string(void)
88 { "\"hello world\"", "hello world" },
89 { "\"the quick brown fox jumped over the fence\"",
90 "the quick brown fox jumped over the fence" },
94 for (i
= 0; test_cases
[i
].encoded
; i
++) {
98 obj
= qobject_from_json(test_cases
[i
].encoded
);
100 g_assert(obj
!= NULL
);
101 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
103 str
= qobject_to_qstring(obj
);
104 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
106 str
= qobject_to_json(obj
);
107 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
115 static void single_quote_string(void)
122 { "'hello world'", "hello world" },
123 { "'the quick brown fox \\' jumped over the fence'",
124 "the quick brown fox ' jumped over the fence" },
128 for (i
= 0; test_cases
[i
].encoded
; i
++) {
132 obj
= qobject_from_json(test_cases
[i
].encoded
);
134 g_assert(obj
!= NULL
);
135 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
137 str
= qobject_to_qstring(obj
);
138 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
144 static void utf8_string(void)
147 * FIXME Current behavior for invalid UTF-8 sequences is
148 * incorrect. This test expects current, incorrect results.
149 * They're all marked "bug:" below, and are to be replaced by
150 * correct ones as the bugs get fixed.
152 * The JSON parser rejects some invalid sequences, but accepts
153 * others without correcting the problem.
155 * We should either reject all invalid sequences, or minimize
156 * overlong sequences and replace all other invalid sequences by a
157 * suitable replacement character. A common choice for
158 * replacement is U+FFFD.
160 * Problem: we can't easily deal with embedded U+0000. Parsing
161 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
162 * which gets misinterpreted as NUL-terminated "this ". We should
163 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
166 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
167 * capability and stress test at
168 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
170 static const struct {
172 const char *utf8_out
;
173 const char *json_out
; /* defaults to @json_in */
174 const char *utf8_in
; /* defaults to @utf8_out */
177 * Bug markers used here:
178 * - bug: not corrected
179 * JSON parser fails to correct invalid sequence(s)
181 * JSON parser rejects invalid sequence(s)
182 * We may choose to define this as feature
184 * JSON parser produces incorrect result, this is the
185 * correct one, assuming replacement character U+FFFF
186 * We may choose to reject instead of replace
189 /* 1 Some correct UTF-8 text */
191 /* a bit of German */
192 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
193 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
194 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
195 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
196 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
197 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
201 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
202 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
203 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
205 /* 2 Boundary condition test cases */
206 /* 2.1 First possible sequence of a certain length */
207 /* 2.1.1 1 byte U+0000 */
210 "", /* bug: want overlong "\xC0\x80" */
214 /* 2.1.2 2 bytes U+0080 */
220 /* 2.1.3 3 bytes U+0800 */
226 /* 2.1.4 4 bytes U+10000 */
228 "\"\xF0\x90\x80\x80\"",
230 "\"\\uD800\\uDC00\"",
232 /* 2.1.5 5 bytes U+200000 */
234 "\"\xF8\x88\x80\x80\x80\"",
235 NULL
, /* bug: rejected */
237 "\xF8\x88\x80\x80\x80",
239 /* 2.1.6 6 bytes U+4000000 */
241 "\"\xFC\x84\x80\x80\x80\x80\"",
242 NULL
, /* bug: rejected */
244 "\xFC\x84\x80\x80\x80\x80",
246 /* 2.2 Last possible sequence of a certain length */
247 /* 2.2.1 1 byte U+007F */
253 /* 2.2.2 2 bytes U+07FF */
260 * 2.2.3 3 bytes U+FFFC
261 * The last possible sequence is actually U+FFFF. But that's
262 * a noncharacter, and already covered by its own test case
263 * under 5.3. Same for U+FFFE. U+FFFD is the last character
264 * in the BMP, and covered under 2.3. Because of U+FFFD's
265 * special role as replacement character, it's worth testing
273 /* 2.2.4 4 bytes U+1FFFFF */
275 "\"\xF7\xBF\xBF\xBF\"",
276 NULL
, /* bug: rejected */
280 /* 2.2.5 5 bytes U+3FFFFFF */
282 "\"\xFB\xBF\xBF\xBF\xBF\"",
283 NULL
, /* bug: rejected */
285 "\xFB\xBF\xBF\xBF\xBF",
287 /* 2.2.6 6 bytes U+7FFFFFFF */
289 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
290 NULL
, /* bug: rejected */
292 "\xFD\xBF\xBF\xBF\xBF\xBF",
294 /* 2.3 Other boundary conditions */
296 /* last one before surrogate range: U+D7FF */
302 /* first one after surrogate range: U+E000 */
308 /* last one in BMP: U+FFFD */
314 /* last one in last plane: U+10FFFD */
315 "\"\xF4\x8F\xBF\xBD\"",
320 /* first one beyond Unicode range: U+110000 */
321 "\"\xF4\x90\x80\x80\"",
325 /* 3 Malformed sequences */
326 /* 3.1 Unexpected continuation bytes */
327 /* 3.1.1 First continuation byte */
330 "\x80", /* bug: not corrected */
333 /* 3.1.2 Last continuation byte */
336 "\xBF", /* bug: not corrected */
339 /* 3.1.3 2 continuation bytes */
342 "\x80\xBF", /* bug: not corrected */
343 "\"\\uFFFD\\uFFFD\"",
345 /* 3.1.4 3 continuation bytes */
348 "\x80\xBF\x80", /* bug: not corrected */
349 "\"\\uFFFD\\uFFFD\\uFFFD\"",
351 /* 3.1.5 4 continuation bytes */
353 "\"\x80\xBF\x80\xBF\"",
354 "\x80\xBF\x80\xBF", /* bug: not corrected */
355 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
357 /* 3.1.6 5 continuation bytes */
359 "\"\x80\xBF\x80\xBF\x80\"",
360 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
361 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
363 /* 3.1.7 6 continuation bytes */
365 "\"\x80\xBF\x80\xBF\x80\xBF\"",
366 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
367 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
369 /* 3.1.8 7 continuation bytes */
371 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
372 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
373 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
375 /* 3.1.9 Sequence of all 64 possible continuation bytes */
377 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
378 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
379 "\x90\x91\x92\x93\x94\x95\x96\x97"
380 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
381 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
382 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
383 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
384 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
385 /* bug: not corrected */
386 "\x80\x81\x82\x83\x84\x85\x86\x87"
387 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
388 "\x90\x91\x92\x93\x94\x95\x96\x97"
389 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
390 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
391 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
392 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
393 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
394 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
395 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
396 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
397 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
398 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
399 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
400 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
401 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
403 /* 3.2 Lonely start characters */
404 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
406 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
407 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
408 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
409 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
410 NULL
, /* bug: rejected */
411 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
412 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
413 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
414 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
415 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
416 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
417 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
418 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
420 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
422 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
423 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
424 /* bug: not corrected */
425 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
426 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
427 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
428 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
430 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
432 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
433 NULL
, /* bug: rejected */
434 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
435 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
437 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
439 "\"\xF8 \xF9 \xFA \xFB \"",
440 NULL
, /* bug: rejected */
441 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
442 "\xF8 \xF9 \xFA \xFB ",
444 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
447 NULL
, /* bug: rejected */
448 "\"\\uFFFD \\uFFFD \"",
451 /* 3.3 Sequences with last continuation byte missing */
452 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
455 NULL
, /* bug: rejected */
459 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
462 "\xE0\x80", /* bug: not corrected */
465 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
468 "\xF0\x80\x80", /* bug: not corrected */
471 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
473 "\"\xF8\x80\x80\x80\"",
474 NULL
, /* bug: rejected */
478 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
480 "\"\xFC\x80\x80\x80\x80\"",
481 NULL
, /* bug: rejected */
483 "\xFC\x80\x80\x80\x80",
485 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
488 "\xDF", /* bug: not corrected */
491 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
494 "\xEF\xBF", /* bug: not corrected */
497 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
500 NULL
, /* bug: rejected */
504 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
506 "\"\xFB\xBF\xBF\xBF\"",
507 NULL
, /* bug: rejected */
511 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
513 "\"\xFD\xBF\xBF\xBF\xBF\"",
514 NULL
, /* bug: rejected */
516 "\xFD\xBF\xBF\xBF\xBF",
518 /* 3.4 Concatenation of incomplete sequences */
520 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
521 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
522 NULL
, /* bug: rejected */
523 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
524 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
525 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
526 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
528 /* 3.5 Impossible bytes */
531 NULL
, /* bug: rejected */
537 NULL
, /* bug: rejected */
542 "\"\xFE\xFE\xFF\xFF\"",
543 NULL
, /* bug: rejected */
544 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
547 /* 4 Overlong sequences */
548 /* 4.1 Overlong '/' */
551 NULL
, /* bug: rejected */
557 "\xE0\x80\xAF", /* bug: not corrected */
561 "\"\xF0\x80\x80\xAF\"",
562 "\xF0\x80\x80\xAF", /* bug: not corrected */
566 "\"\xF8\x80\x80\x80\xAF\"",
567 NULL
, /* bug: rejected */
569 "\xF8\x80\x80\x80\xAF",
572 "\"\xFC\x80\x80\x80\x80\xAF\"",
573 NULL
, /* bug: rejected */
575 "\xFC\x80\x80\x80\x80\xAF",
578 * 4.2 Maximum overlong sequences
579 * Highest Unicode value that is still resulting in an
580 * overlong sequence if represented with the given number of
581 * bytes. This is a boundary test for safe UTF-8 decoders.
586 NULL
, /* bug: rejected */
593 "\xE0\x9F\xBF", /* bug: not corrected */
599 * The actual maximum would be U+FFFF, but that's a
600 * noncharacter. Testing U+FFFC seems more useful. See
603 "\"\xF0\x8F\xBF\xBC\"",
604 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
609 "\"\xF8\x87\xBF\xBF\xBF\"",
610 NULL
, /* bug: rejected */
612 "\xF8\x87\xBF\xBF\xBF",
616 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
617 NULL
, /* bug: rejected */
619 "\xFC\x83\xBF\xBF\xBF\xBF",
621 /* 4.3 Overlong representation of the NUL character */
625 NULL
, /* bug: rejected */
632 "\xE0\x80\x80", /* bug: not corrected */
637 "\"\xF0\x80\x80\x80\"",
638 "\xF0\x80\x80\x80", /* bug: not corrected */
643 "\"\xF8\x80\x80\x80\x80\"",
644 NULL
, /* bug: rejected */
646 "\xF8\x80\x80\x80\x80",
650 "\"\xFC\x80\x80\x80\x80\x80\"",
651 NULL
, /* bug: rejected */
653 "\xFC\x80\x80\x80\x80\x80",
655 /* 5 Illegal code positions */
656 /* 5.1 Single UTF-16 surrogates */
660 "\xED\xA0\x80", /* bug: not corrected */
666 "\xED\xAD\xBF", /* bug: not corrected */
672 "\xED\xAE\x80", /* bug: not corrected */
678 "\xED\xAF\xBF", /* bug: not corrected */
684 "\xED\xB0\x80", /* bug: not corrected */
690 "\xED\xBE\x80", /* bug: not corrected */
696 "\xED\xBF\xBF", /* bug: not corrected */
699 /* 5.2 Paired UTF-16 surrogates */
702 "\"\xED\xA0\x80\xED\xB0\x80\"",
703 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
704 "\"\\uFFFD\\uFFFD\"",
708 "\"\xED\xA0\x80\xED\xBF\xBF\"",
709 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
710 "\"\\uFFFD\\uFFFD\"",
714 "\"\xED\xAD\xBF\xED\xB0\x80\"",
715 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
716 "\"\\uFFFD\\uFFFD\"",
720 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
721 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
722 "\"\\uFFFD\\uFFFD\"",
726 "\"\xED\xAE\x80\xED\xB0\x80\"",
727 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
728 "\"\\uFFFD\\uFFFD\"",
732 "\"\xED\xAE\x80\xED\xBF\xBF\"",
733 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
734 "\"\\uFFFD\\uFFFD\"",
738 "\"\xED\xAF\xBF\xED\xB0\x80\"",
739 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
740 "\"\\uFFFD\\uFFFD\"",
744 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
745 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
746 "\"\\uFFFD\\uFFFD\"",
748 /* 5.3 Other illegal code positions */
749 /* BMP noncharacters */
753 "\xEF\xBF\xBE", /* bug: not corrected */
759 "\xEF\xBF\xBF", /* bug: not corrected */
765 "\xEF\xB7\x90", /* bug: not corrected */
771 "\xEF\xB7\xAF", /* bug: not corrected */
774 /* Plane 1 .. 16 noncharacters */
776 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
777 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
778 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
779 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
780 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
781 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
782 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
783 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
784 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
785 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
786 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
787 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
788 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
789 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
790 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
791 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
792 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
793 /* bug: not corrected */
794 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
795 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
796 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
797 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
798 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
799 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
800 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
801 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
802 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
803 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
804 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
805 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
806 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
807 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
808 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
809 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
810 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
811 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
812 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
813 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
820 const char *json_in
, *utf8_out
, *utf8_in
, *json_out
;
822 for (i
= 0; test_cases
[i
].json_in
; i
++) {
823 json_in
= test_cases
[i
].json_in
;
824 utf8_out
= test_cases
[i
].utf8_out
;
825 utf8_in
= test_cases
[i
].utf8_in
?: test_cases
[i
].utf8_out
;
826 json_out
= test_cases
[i
].json_out
?: test_cases
[i
].json_in
;
828 obj
= qobject_from_json(json_in
);
831 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
832 str
= qobject_to_qstring(obj
);
833 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
839 obj
= QOBJECT(qstring_from_str(utf8_in
));
840 str
= qobject_to_json(obj
);
843 g_assert_cmpstr(qstring_get_str(str
), ==, json_out
);
851 * Disabled, because qobject_from_json() is buggy, and I can't
852 * be bothered to add the expected incorrect results.
853 * FIXME Enable once these bugs have been fixed.
855 if (0 && json_out
!= json_in
) {
856 obj
= qobject_from_json(json_out
);
858 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
859 str
= qobject_to_qstring(obj
);
860 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
865 static void vararg_string(void)
872 { "the quick brown fox jumped over the fence" },
876 for (i
= 0; test_cases
[i
].decoded
; i
++) {
880 obj
= qobject_from_jsonf("%s", test_cases
[i
].decoded
);
882 g_assert(obj
!= NULL
);
883 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
885 str
= qobject_to_qstring(obj
);
886 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
892 static void simple_number(void)
904 { "-0", 0, .skip
= 1 },
908 for (i
= 0; test_cases
[i
].encoded
; i
++) {
912 obj
= qobject_from_json(test_cases
[i
].encoded
);
913 g_assert(obj
!= NULL
);
914 g_assert(qobject_type(obj
) == QTYPE_QINT
);
916 qint
= qobject_to_qint(obj
);
917 g_assert(qint_get_int(qint
) == test_cases
[i
].decoded
);
918 if (test_cases
[i
].skip
== 0) {
921 str
= qobject_to_json(obj
);
922 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
930 static void float_number(void)
940 { "-32.12313", -32.12313 },
941 { "-32.20e-10", -32.20e-10, .skip
= 1 },
945 for (i
= 0; test_cases
[i
].encoded
; i
++) {
949 obj
= qobject_from_json(test_cases
[i
].encoded
);
950 g_assert(obj
!= NULL
);
951 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
953 qfloat
= qobject_to_qfloat(obj
);
954 g_assert(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
956 if (test_cases
[i
].skip
== 0) {
959 str
= qobject_to_json(obj
);
960 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
968 static void vararg_number(void)
974 int64_t value64
= 0x2342342343LL
;
975 double valuef
= 2.323423423;
977 obj
= qobject_from_jsonf("%d", value
);
978 g_assert(obj
!= NULL
);
979 g_assert(qobject_type(obj
) == QTYPE_QINT
);
981 qint
= qobject_to_qint(obj
);
982 g_assert(qint_get_int(qint
) == value
);
986 obj
= qobject_from_jsonf("%" PRId64
, value64
);
987 g_assert(obj
!= NULL
);
988 g_assert(qobject_type(obj
) == QTYPE_QINT
);
990 qint
= qobject_to_qint(obj
);
991 g_assert(qint_get_int(qint
) == value64
);
995 obj
= qobject_from_jsonf("%f", valuef
);
996 g_assert(obj
!= NULL
);
997 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
999 qfloat
= qobject_to_qfloat(obj
);
1000 g_assert(qfloat_get_double(qfloat
) == valuef
);
1005 static void keyword_literal(void)
1012 obj
= qobject_from_json("true");
1013 g_assert(obj
!= NULL
);
1014 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1016 qbool
= qobject_to_qbool(obj
);
1017 g_assert(qbool_get_bool(qbool
) == true);
1019 str
= qobject_to_json(obj
);
1020 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
1025 obj
= qobject_from_json("false");
1026 g_assert(obj
!= NULL
);
1027 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1029 qbool
= qobject_to_qbool(obj
);
1030 g_assert(qbool_get_bool(qbool
) == false);
1032 str
= qobject_to_json(obj
);
1033 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
1038 obj
= qobject_from_jsonf("%i", false);
1039 g_assert(obj
!= NULL
);
1040 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1042 qbool
= qobject_to_qbool(obj
);
1043 g_assert(qbool_get_bool(qbool
) == false);
1047 /* Test that non-zero values other than 1 get collapsed to true */
1048 obj
= qobject_from_jsonf("%i", 2);
1049 g_assert(obj
!= NULL
);
1050 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1052 qbool
= qobject_to_qbool(obj
);
1053 g_assert(qbool_get_bool(qbool
) == true);
1057 obj
= qobject_from_json("null");
1058 g_assert(obj
!= NULL
);
1059 g_assert(qobject_type(obj
) == QTYPE_QNULL
);
1062 g_assert(null
== obj
);
1064 qobject_decref(obj
);
1065 qobject_decref(null
);
1068 typedef struct LiteralQDictEntry LiteralQDictEntry
;
1069 typedef struct LiteralQObject LiteralQObject
;
1071 struct LiteralQObject
1077 LiteralQDictEntry
*qdict
;
1078 LiteralQObject
*qlist
;
1082 struct LiteralQDictEntry
1085 LiteralQObject value
;
1088 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1089 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1090 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1091 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1093 typedef struct QListCompareHelper
1096 LiteralQObject
*objs
;
1098 } QListCompareHelper
;
1100 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
1102 static void compare_helper(QObject
*obj
, void *opaque
)
1104 QListCompareHelper
*helper
= opaque
;
1106 if (helper
->result
== 0) {
1110 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
1115 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
1118 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
1120 if (lhs
->type
!= qobject_type(rhs
)) {
1124 switch (lhs
->type
) {
1126 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
1128 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
1132 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
1133 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
1135 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
1143 QListCompareHelper helper
;
1146 helper
.objs
= lhs
->value
.qlist
;
1149 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
1151 return helper
.result
;
1160 static void simple_dict(void)
1164 const char *encoded
;
1165 LiteralQObject decoded
;
1168 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
1169 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1170 { "foo", QLIT_QINT(42) },
1171 { "bar", QLIT_QSTR("hello world") },
1176 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1180 .encoded
= "{\"foo\": 43}",
1181 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1182 { "foo", QLIT_QINT(43) },
1189 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1193 obj
= qobject_from_json(test_cases
[i
].encoded
);
1194 g_assert(obj
!= NULL
);
1195 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
1197 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1199 str
= qobject_to_json(obj
);
1200 qobject_decref(obj
);
1202 obj
= qobject_from_json(qstring_get_str(str
));
1203 g_assert(obj
!= NULL
);
1204 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
1206 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1207 qobject_decref(obj
);
1213 * this generates json of the form:
1214 * a(0,m) = [0, 1, ..., m-1]
1219 * 'key(n-1)': a(n-1,m)
1222 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1228 if (nest_level_max
== 0) {
1229 g_string_append(gstr
, "[");
1230 for (i
= 0; i
< elem_count
; i
++) {
1231 g_string_append_printf(gstr
, "%d", i
);
1232 if (i
< elem_count
- 1) {
1233 g_string_append_printf(gstr
, ", ");
1236 g_string_append(gstr
, "]");
1240 g_string_append(gstr
, "{");
1241 for (i
= 0; i
< nest_level_max
; i
++) {
1242 g_string_append_printf(gstr
, "'key%d': ", i
);
1243 gen_test_json(gstr
, i
, elem_count
);
1244 if (i
< nest_level_max
- 1) {
1245 g_string_append(gstr
, ",");
1248 g_string_append(gstr
, "}");
1251 static void large_dict(void)
1253 GString
*gstr
= g_string_new("");
1256 gen_test_json(gstr
, 10, 100);
1257 obj
= qobject_from_json(gstr
->str
);
1258 g_assert(obj
!= NULL
);
1260 qobject_decref(obj
);
1261 g_string_free(gstr
, true);
1264 static void simple_list(void)
1268 const char *encoded
;
1269 LiteralQObject decoded
;
1272 .encoded
= "[43,42]",
1273 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1281 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1288 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1294 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1295 QLIT_QDICT(((LiteralQDictEntry
[]){
1304 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1308 obj
= qobject_from_json(test_cases
[i
].encoded
);
1309 g_assert(obj
!= NULL
);
1310 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1312 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1314 str
= qobject_to_json(obj
);
1315 qobject_decref(obj
);
1317 obj
= qobject_from_json(qstring_get_str(str
));
1318 g_assert(obj
!= NULL
);
1319 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1321 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1322 qobject_decref(obj
);
1327 static void simple_whitespace(void)
1331 const char *encoded
;
1332 LiteralQObject decoded
;
1335 .encoded
= " [ 43 , 42 ]",
1336 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1343 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1344 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1346 QLIT_QDICT(((LiteralQDictEntry
[]){
1347 { "h", QLIT_QSTR("b") },
1349 QLIT_QLIST(((LiteralQObject
[]){
1356 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1357 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1359 QLIT_QDICT(((LiteralQDictEntry
[]){
1360 { "h", QLIT_QSTR("b") },
1361 { "a", QLIT_QINT(32) },
1363 QLIT_QLIST(((LiteralQObject
[]){
1372 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1376 obj
= qobject_from_json(test_cases
[i
].encoded
);
1377 g_assert(obj
!= NULL
);
1378 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1380 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1382 str
= qobject_to_json(obj
);
1383 qobject_decref(obj
);
1385 obj
= qobject_from_json(qstring_get_str(str
));
1386 g_assert(obj
!= NULL
);
1387 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1389 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1391 qobject_decref(obj
);
1396 static void simple_varargs(void)
1398 QObject
*embedded_obj
;
1400 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
1403 QLIT_QLIST(((LiteralQObject
[]){
1409 embedded_obj
= qobject_from_json("[32, 42]");
1410 g_assert(embedded_obj
!= NULL
);
1412 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
1413 g_assert(obj
!= NULL
);
1415 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
1417 qobject_decref(obj
);
1420 static void empty_input(void)
1422 const char *empty
= "";
1424 QObject
*obj
= qobject_from_json(empty
);
1425 g_assert(obj
== NULL
);
1428 static void unterminated_string(void)
1430 QObject
*obj
= qobject_from_json("\"abc");
1431 g_assert(obj
== NULL
);
1434 static void unterminated_sq_string(void)
1436 QObject
*obj
= qobject_from_json("'abc");
1437 g_assert(obj
== NULL
);
1440 static void unterminated_escape(void)
1442 QObject
*obj
= qobject_from_json("\"abc\\\"");
1443 g_assert(obj
== NULL
);
1446 static void unterminated_array(void)
1448 QObject
*obj
= qobject_from_json("[32");
1449 g_assert(obj
== NULL
);
1452 static void unterminated_array_comma(void)
1454 QObject
*obj
= qobject_from_json("[32,");
1455 g_assert(obj
== NULL
);
1458 static void invalid_array_comma(void)
1460 QObject
*obj
= qobject_from_json("[32,}");
1461 g_assert(obj
== NULL
);
1464 static void unterminated_dict(void)
1466 QObject
*obj
= qobject_from_json("{'abc':32");
1467 g_assert(obj
== NULL
);
1470 static void unterminated_dict_comma(void)
1472 QObject
*obj
= qobject_from_json("{'abc':32,");
1473 g_assert(obj
== NULL
);
1476 static void invalid_dict_comma(void)
1478 QObject
*obj
= qobject_from_json("{'abc':32,}");
1479 g_assert(obj
== NULL
);
1482 static void unterminated_literal(void)
1484 QObject
*obj
= qobject_from_json("nul");
1485 g_assert(obj
== NULL
);
1488 static char *make_nest(char *buf
, size_t cnt
)
1490 memset(buf
, '[', cnt
- 1);
1493 memset(buf
+ cnt
+ 1, ']', cnt
- 1);
1498 static void limits_nesting(void)
1500 enum { max_nesting
= 1024 }; /* see qobject/json-streamer.c */
1501 char buf
[2 * (max_nesting
+ 1) + 1];
1504 obj
= qobject_from_json(make_nest(buf
, max_nesting
));
1505 g_assert(obj
!= NULL
);
1506 qobject_decref(obj
);
1508 obj
= qobject_from_json(make_nest(buf
, max_nesting
+ 1));
1509 g_assert(obj
== NULL
);
1512 int main(int argc
, char **argv
)
1514 g_test_init(&argc
, &argv
, NULL
);
1516 g_test_add_func("/literals/string/simple", simple_string
);
1517 g_test_add_func("/literals/string/escaped", escaped_string
);
1518 g_test_add_func("/literals/string/utf8", utf8_string
);
1519 g_test_add_func("/literals/string/single_quote", single_quote_string
);
1520 g_test_add_func("/literals/string/vararg", vararg_string
);
1522 g_test_add_func("/literals/number/simple", simple_number
);
1523 g_test_add_func("/literals/number/float", float_number
);
1524 g_test_add_func("/literals/number/vararg", vararg_number
);
1526 g_test_add_func("/literals/keyword", keyword_literal
);
1528 g_test_add_func("/dicts/simple_dict", simple_dict
);
1529 g_test_add_func("/dicts/large_dict", large_dict
);
1530 g_test_add_func("/lists/simple_list", simple_list
);
1532 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1534 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1536 g_test_add_func("/errors/empty_input", empty_input
);
1537 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1538 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1539 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1540 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1541 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1542 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1543 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1544 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1545 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1546 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1547 g_test_add_func("/errors/limits/nesting", limits_nesting
);
1549 return g_test_run();