2 * Copyright IBM, Corp. 2009
3 * Copyright (c) 2013 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.
15 #include "qapi/qmp/qstring.h"
16 #include "qapi/qmp/qint.h"
17 #include "qapi/qmp/qdict.h"
18 #include "qapi/qmp/qlist.h"
19 #include "qapi/qmp/qfloat.h"
20 #include "qapi/qmp/qbool.h"
21 #include "qapi/qmp/qjson.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
);
64 g_assert(obj
!= NULL
);
65 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
67 str
= qobject_to_qstring(obj
);
68 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].decoded
);
70 if (test_cases
[i
].skip
== 0) {
71 str
= qobject_to_json(obj
);
72 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].encoded
);
80 static void simple_string(void)
87 { "\"hello world\"", "hello world" },
88 { "\"the quick brown fox jumped over the fence\"",
89 "the quick brown fox jumped over the fence" },
93 for (i
= 0; test_cases
[i
].encoded
; i
++) {
97 obj
= qobject_from_json(test_cases
[i
].encoded
);
99 g_assert(obj
!= NULL
);
100 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
102 str
= qobject_to_qstring(obj
);
103 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
105 str
= qobject_to_json(obj
);
106 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
114 static void single_quote_string(void)
121 { "'hello world'", "hello world" },
122 { "'the quick brown fox \\' jumped over the fence'",
123 "the quick brown fox ' jumped over the fence" },
127 for (i
= 0; test_cases
[i
].encoded
; i
++) {
131 obj
= qobject_from_json(test_cases
[i
].encoded
);
133 g_assert(obj
!= NULL
);
134 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
136 str
= qobject_to_qstring(obj
);
137 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
143 static void utf8_string(void)
146 * FIXME Current behavior for invalid UTF-8 sequences is
147 * incorrect. This test expects current, incorrect results.
148 * They're all marked "bug:" below, and are to be replaced by
149 * correct ones as the bugs get fixed.
151 * The JSON parser rejects some invalid sequences, but accepts
152 * others without correcting the problem.
154 * We should either reject all invalid sequences, or minimize
155 * overlong sequences and replace all other invalid sequences by a
156 * suitable replacement character. A common choice for
157 * replacement is U+FFFD.
159 * Problem: we can't easily deal with embedded U+0000. Parsing
160 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
161 * which gets misinterpreted as NUL-terminated "this ". We should
162 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
165 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
166 * capability and stress test at
167 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
169 static const struct {
171 const char *utf8_out
;
172 const char *json_out
; /* defaults to @json_in */
173 const char *utf8_in
; /* defaults to @utf8_out */
176 * Bug markers used here:
177 * - bug: not corrected
178 * JSON parser fails to correct invalid sequence(s)
180 * JSON parser rejects invalid sequence(s)
181 * We may choose to define this as feature
183 * JSON parser produces incorrect result, this is the
184 * correct one, assuming replacement character U+FFFF
185 * We may choose to reject instead of replace
188 /* 1 Some correct UTF-8 text */
190 /* a bit of German */
191 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
192 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
193 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
194 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
195 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
196 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
200 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
201 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
202 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
204 /* 2 Boundary condition test cases */
205 /* 2.1 First possible sequence of a certain length */
206 /* 2.1.1 1 byte U+0000 */
209 "", /* bug: want overlong "\xC0\x80" */
213 /* 2.1.2 2 bytes U+0080 */
219 /* 2.1.3 3 bytes U+0800 */
225 /* 2.1.4 4 bytes U+10000 */
227 "\"\xF0\x90\x80\x80\"",
229 "\"\\uD800\\uDC00\"",
231 /* 2.1.5 5 bytes U+200000 */
233 "\"\xF8\x88\x80\x80\x80\"",
234 NULL
, /* bug: rejected */
236 "\xF8\x88\x80\x80\x80",
238 /* 2.1.6 6 bytes U+4000000 */
240 "\"\xFC\x84\x80\x80\x80\x80\"",
241 NULL
, /* bug: rejected */
243 "\xFC\x84\x80\x80\x80\x80",
245 /* 2.2 Last possible sequence of a certain length */
246 /* 2.2.1 1 byte U+007F */
252 /* 2.2.2 2 bytes U+07FF */
259 * 2.2.3 3 bytes U+FFFC
260 * The last possible sequence is actually U+FFFF. But that's
261 * a noncharacter, and already covered by its own test case
262 * under 5.3. Same for U+FFFE. U+FFFD is the last character
263 * in the BMP, and covered under 2.3. Because of U+FFFD's
264 * special role as replacement character, it's worth testing
272 /* 2.2.4 4 bytes U+1FFFFF */
274 "\"\xF7\xBF\xBF\xBF\"",
275 NULL
, /* bug: rejected */
279 /* 2.2.5 5 bytes U+3FFFFFF */
281 "\"\xFB\xBF\xBF\xBF\xBF\"",
282 NULL
, /* bug: rejected */
284 "\xFB\xBF\xBF\xBF\xBF",
286 /* 2.2.6 6 bytes U+7FFFFFFF */
288 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
289 NULL
, /* bug: rejected */
291 "\xFD\xBF\xBF\xBF\xBF\xBF",
293 /* 2.3 Other boundary conditions */
295 /* last one before surrogate range: U+D7FF */
301 /* first one after surrogate range: U+E000 */
307 /* last one in BMP: U+FFFD */
313 /* last one in last plane: U+10FFFD */
314 "\"\xF4\x8F\xBF\xBD\"",
319 /* first one beyond Unicode range: U+110000 */
320 "\"\xF4\x90\x80\x80\"",
324 /* 3 Malformed sequences */
325 /* 3.1 Unexpected continuation bytes */
326 /* 3.1.1 First continuation byte */
329 "\x80", /* bug: not corrected */
332 /* 3.1.2 Last continuation byte */
335 "\xBF", /* bug: not corrected */
338 /* 3.1.3 2 continuation bytes */
341 "\x80\xBF", /* bug: not corrected */
342 "\"\\uFFFD\\uFFFD\"",
344 /* 3.1.4 3 continuation bytes */
347 "\x80\xBF\x80", /* bug: not corrected */
348 "\"\\uFFFD\\uFFFD\\uFFFD\"",
350 /* 3.1.5 4 continuation bytes */
352 "\"\x80\xBF\x80\xBF\"",
353 "\x80\xBF\x80\xBF", /* bug: not corrected */
354 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
356 /* 3.1.6 5 continuation bytes */
358 "\"\x80\xBF\x80\xBF\x80\"",
359 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
360 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
362 /* 3.1.7 6 continuation bytes */
364 "\"\x80\xBF\x80\xBF\x80\xBF\"",
365 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
366 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
368 /* 3.1.8 7 continuation bytes */
370 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
371 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
372 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
374 /* 3.1.9 Sequence of all 64 possible continuation bytes */
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 /* bug: not corrected */
385 "\x80\x81\x82\x83\x84\x85\x86\x87"
386 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
387 "\x90\x91\x92\x93\x94\x95\x96\x97"
388 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
389 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
390 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
391 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
392 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
393 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
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\""
402 /* 3.2 Lonely start characters */
403 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
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 \"",
409 NULL
, /* bug: rejected */
410 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
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 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
415 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
416 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
417 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
419 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
421 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
422 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
423 /* bug: not corrected */
424 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
425 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
426 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
427 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
429 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
431 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
432 NULL
, /* bug: rejected */
433 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
434 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
436 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
438 "\"\xF8 \xF9 \xFA \xFB \"",
439 NULL
, /* bug: rejected */
440 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
441 "\xF8 \xF9 \xFA \xFB ",
443 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
446 NULL
, /* bug: rejected */
447 "\"\\uFFFD \\uFFFD \"",
450 /* 3.3 Sequences with last continuation byte missing */
451 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
454 NULL
, /* bug: rejected */
458 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
461 "\xE0\x80", /* bug: not corrected */
464 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
467 "\xF0\x80\x80", /* bug: not corrected */
470 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
472 "\"\xF8\x80\x80\x80\"",
473 NULL
, /* bug: rejected */
477 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
479 "\"\xFC\x80\x80\x80\x80\"",
480 NULL
, /* bug: rejected */
482 "\xFC\x80\x80\x80\x80",
484 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
487 "\xDF", /* bug: not corrected */
490 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
493 "\xEF\xBF", /* bug: not corrected */
496 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
499 NULL
, /* bug: rejected */
503 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
505 "\"\xFB\xBF\xBF\xBF\"",
506 NULL
, /* bug: rejected */
510 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
512 "\"\xFD\xBF\xBF\xBF\xBF\"",
513 NULL
, /* bug: rejected */
515 "\xFD\xBF\xBF\xBF\xBF",
517 /* 3.4 Concatenation of incomplete sequences */
519 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
520 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
521 NULL
, /* bug: rejected */
522 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
523 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
524 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
525 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
527 /* 3.5 Impossible bytes */
530 NULL
, /* bug: rejected */
536 NULL
, /* bug: rejected */
541 "\"\xFE\xFE\xFF\xFF\"",
542 NULL
, /* bug: rejected */
543 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
546 /* 4 Overlong sequences */
547 /* 4.1 Overlong '/' */
550 NULL
, /* bug: rejected */
556 "\xE0\x80\xAF", /* bug: not corrected */
560 "\"\xF0\x80\x80\xAF\"",
561 "\xF0\x80\x80\xAF", /* bug: not corrected */
565 "\"\xF8\x80\x80\x80\xAF\"",
566 NULL
, /* bug: rejected */
568 "\xF8\x80\x80\x80\xAF",
571 "\"\xFC\x80\x80\x80\x80\xAF\"",
572 NULL
, /* bug: rejected */
574 "\xFC\x80\x80\x80\x80\xAF",
577 * 4.2 Maximum overlong sequences
578 * Highest Unicode value that is still resulting in an
579 * overlong sequence if represented with the given number of
580 * bytes. This is a boundary test for safe UTF-8 decoders.
585 NULL
, /* bug: rejected */
592 "\xE0\x9F\xBF", /* bug: not corrected */
598 * The actual maximum would be U+FFFF, but that's a
599 * noncharacter. Testing U+FFFC seems more useful. See
602 "\"\xF0\x8F\xBF\xBC\"",
603 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
608 "\"\xF8\x87\xBF\xBF\xBF\"",
609 NULL
, /* bug: rejected */
611 "\xF8\x87\xBF\xBF\xBF",
615 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
616 NULL
, /* bug: rejected */
618 "\xFC\x83\xBF\xBF\xBF\xBF",
620 /* 4.3 Overlong representation of the NUL character */
624 NULL
, /* bug: rejected */
631 "\xE0\x80\x80", /* bug: not corrected */
636 "\"\xF0\x80\x80\x80\"",
637 "\xF0\x80\x80\x80", /* bug: not corrected */
642 "\"\xF8\x80\x80\x80\x80\"",
643 NULL
, /* bug: rejected */
645 "\xF8\x80\x80\x80\x80",
649 "\"\xFC\x80\x80\x80\x80\x80\"",
650 NULL
, /* bug: rejected */
652 "\xFC\x80\x80\x80\x80\x80",
654 /* 5 Illegal code positions */
655 /* 5.1 Single UTF-16 surrogates */
659 "\xED\xA0\x80", /* bug: not corrected */
665 "\xED\xAD\xBF", /* bug: not corrected */
671 "\xED\xAE\x80", /* bug: not corrected */
677 "\xED\xAF\xBF", /* bug: not corrected */
683 "\xED\xB0\x80", /* bug: not corrected */
689 "\xED\xBE\x80", /* bug: not corrected */
695 "\xED\xBF\xBF", /* bug: not corrected */
698 /* 5.2 Paired UTF-16 surrogates */
701 "\"\xED\xA0\x80\xED\xB0\x80\"",
702 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
703 "\"\\uFFFD\\uFFFD\"",
707 "\"\xED\xA0\x80\xED\xBF\xBF\"",
708 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
709 "\"\\uFFFD\\uFFFD\"",
713 "\"\xED\xAD\xBF\xED\xB0\x80\"",
714 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
715 "\"\\uFFFD\\uFFFD\"",
719 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
720 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
721 "\"\\uFFFD\\uFFFD\"",
725 "\"\xED\xAE\x80\xED\xB0\x80\"",
726 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
727 "\"\\uFFFD\\uFFFD\"",
731 "\"\xED\xAE\x80\xED\xBF\xBF\"",
732 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
733 "\"\\uFFFD\\uFFFD\"",
737 "\"\xED\xAF\xBF\xED\xB0\x80\"",
738 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
739 "\"\\uFFFD\\uFFFD\"",
743 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
744 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
745 "\"\\uFFFD\\uFFFD\"",
747 /* 5.3 Other illegal code positions */
748 /* BMP noncharacters */
752 "\xEF\xBF\xBE", /* bug: not corrected */
758 "\xEF\xBF\xBF", /* bug: not corrected */
764 "\xEF\xB7\x90", /* bug: not corrected */
770 "\xEF\xB7\xAF", /* bug: not corrected */
773 /* Plane 1 .. 16 noncharacters */
775 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
776 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
777 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
778 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
779 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
780 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
781 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
782 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
783 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
784 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
785 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
786 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
787 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
788 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
789 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
790 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
791 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
792 /* bug: not corrected */
793 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
794 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
795 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
796 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
797 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
798 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
799 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
800 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
801 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
802 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
803 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
804 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
805 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
806 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
807 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
808 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
809 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
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\"",
819 const char *json_in
, *utf8_out
, *utf8_in
, *json_out
;
821 for (i
= 0; test_cases
[i
].json_in
; i
++) {
822 json_in
= test_cases
[i
].json_in
;
823 utf8_out
= test_cases
[i
].utf8_out
;
824 utf8_in
= test_cases
[i
].utf8_in
?: test_cases
[i
].utf8_out
;
825 json_out
= test_cases
[i
].json_out
?: test_cases
[i
].json_in
;
827 obj
= qobject_from_json(json_in
);
830 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
831 str
= qobject_to_qstring(obj
);
832 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
838 obj
= QOBJECT(qstring_from_str(utf8_in
));
839 str
= qobject_to_json(obj
);
842 g_assert_cmpstr(qstring_get_str(str
), ==, json_out
);
850 * Disabled, because qobject_from_json() is buggy, and I can't
851 * be bothered to add the expected incorrect results.
852 * FIXME Enable once these bugs have been fixed.
854 if (0 && json_out
!= json_in
) {
855 obj
= qobject_from_json(json_out
);
857 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
858 str
= qobject_to_qstring(obj
);
859 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
864 static void vararg_string(void)
871 { "the quick brown fox jumped over the fence" },
875 for (i
= 0; test_cases
[i
].decoded
; i
++) {
879 obj
= qobject_from_jsonf("%s", test_cases
[i
].decoded
);
881 g_assert(obj
!= NULL
);
882 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
884 str
= qobject_to_qstring(obj
);
885 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
891 static void simple_number(void)
903 { "-0", 0, .skip
= 1 },
907 for (i
= 0; test_cases
[i
].encoded
; i
++) {
911 obj
= qobject_from_json(test_cases
[i
].encoded
);
912 g_assert(obj
!= NULL
);
913 g_assert(qobject_type(obj
) == QTYPE_QINT
);
915 qint
= qobject_to_qint(obj
);
916 g_assert(qint_get_int(qint
) == test_cases
[i
].decoded
);
917 if (test_cases
[i
].skip
== 0) {
920 str
= qobject_to_json(obj
);
921 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
929 static void float_number(void)
939 { "-32.12313", -32.12313 },
940 { "-32.20e-10", -32.20e-10, .skip
= 1 },
944 for (i
= 0; test_cases
[i
].encoded
; i
++) {
948 obj
= qobject_from_json(test_cases
[i
].encoded
);
949 g_assert(obj
!= NULL
);
950 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
952 qfloat
= qobject_to_qfloat(obj
);
953 g_assert(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
955 if (test_cases
[i
].skip
== 0) {
958 str
= qobject_to_json(obj
);
959 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
967 static void vararg_number(void)
973 int64_t value64
= 0x2342342343LL
;
974 double valuef
= 2.323423423;
976 obj
= qobject_from_jsonf("%d", value
);
977 g_assert(obj
!= NULL
);
978 g_assert(qobject_type(obj
) == QTYPE_QINT
);
980 qint
= qobject_to_qint(obj
);
981 g_assert(qint_get_int(qint
) == value
);
985 obj
= qobject_from_jsonf("%" PRId64
, value64
);
986 g_assert(obj
!= NULL
);
987 g_assert(qobject_type(obj
) == QTYPE_QINT
);
989 qint
= qobject_to_qint(obj
);
990 g_assert(qint_get_int(qint
) == value64
);
994 obj
= qobject_from_jsonf("%f", valuef
);
995 g_assert(obj
!= NULL
);
996 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
998 qfloat
= qobject_to_qfloat(obj
);
999 g_assert(qfloat_get_double(qfloat
) == valuef
);
1004 static void keyword_literal(void)
1010 obj
= qobject_from_json("true");
1011 g_assert(obj
!= NULL
);
1012 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1014 qbool
= qobject_to_qbool(obj
);
1015 g_assert(qbool_get_int(qbool
) != 0);
1017 str
= qobject_to_json(obj
);
1018 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
1023 obj
= qobject_from_json("false");
1024 g_assert(obj
!= NULL
);
1025 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1027 qbool
= qobject_to_qbool(obj
);
1028 g_assert(qbool_get_int(qbool
) == 0);
1030 str
= qobject_to_json(obj
);
1031 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
1036 obj
= qobject_from_jsonf("%i", false);
1037 g_assert(obj
!= NULL
);
1038 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1040 qbool
= qobject_to_qbool(obj
);
1041 g_assert(qbool_get_int(qbool
) == 0);
1045 obj
= qobject_from_jsonf("%i", true);
1046 g_assert(obj
!= NULL
);
1047 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1049 qbool
= qobject_to_qbool(obj
);
1050 g_assert(qbool_get_int(qbool
) != 0);
1055 typedef struct LiteralQDictEntry LiteralQDictEntry
;
1056 typedef struct LiteralQObject LiteralQObject
;
1058 struct LiteralQObject
1064 LiteralQDictEntry
*qdict
;
1065 LiteralQObject
*qlist
;
1069 struct LiteralQDictEntry
1072 LiteralQObject value
;
1075 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1076 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1077 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1078 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1080 typedef struct QListCompareHelper
1083 LiteralQObject
*objs
;
1085 } QListCompareHelper
;
1087 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
1089 static void compare_helper(QObject
*obj
, void *opaque
)
1091 QListCompareHelper
*helper
= opaque
;
1093 if (helper
->result
== 0) {
1097 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
1102 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
1105 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
1107 if (lhs
->type
!= qobject_type(rhs
)) {
1111 switch (lhs
->type
) {
1113 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
1115 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
1119 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
1120 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
1122 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
1130 QListCompareHelper helper
;
1133 helper
.objs
= lhs
->value
.qlist
;
1136 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
1138 return helper
.result
;
1147 static void simple_dict(void)
1151 const char *encoded
;
1152 LiteralQObject decoded
;
1155 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
1156 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1157 { "foo", QLIT_QINT(42) },
1158 { "bar", QLIT_QSTR("hello world") },
1163 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1167 .encoded
= "{\"foo\": 43}",
1168 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1169 { "foo", QLIT_QINT(43) },
1176 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1180 obj
= qobject_from_json(test_cases
[i
].encoded
);
1181 g_assert(obj
!= NULL
);
1182 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
1184 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1186 str
= qobject_to_json(obj
);
1187 qobject_decref(obj
);
1189 obj
= qobject_from_json(qstring_get_str(str
));
1190 g_assert(obj
!= NULL
);
1191 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
1193 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1194 qobject_decref(obj
);
1200 * this generates json of the form:
1201 * a(0,m) = [0, 1, ..., m-1]
1206 * 'key(n-1)': a(n-1,m)
1209 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1215 if (nest_level_max
== 0) {
1216 g_string_append(gstr
, "[");
1217 for (i
= 0; i
< elem_count
; i
++) {
1218 g_string_append_printf(gstr
, "%d", i
);
1219 if (i
< elem_count
- 1) {
1220 g_string_append_printf(gstr
, ", ");
1223 g_string_append(gstr
, "]");
1227 g_string_append(gstr
, "{");
1228 for (i
= 0; i
< nest_level_max
; i
++) {
1229 g_string_append_printf(gstr
, "'key%d': ", i
);
1230 gen_test_json(gstr
, i
, elem_count
);
1231 if (i
< nest_level_max
- 1) {
1232 g_string_append(gstr
, ",");
1235 g_string_append(gstr
, "}");
1238 static void large_dict(void)
1240 GString
*gstr
= g_string_new("");
1243 gen_test_json(gstr
, 10, 100);
1244 obj
= qobject_from_json(gstr
->str
);
1245 g_assert(obj
!= NULL
);
1247 qobject_decref(obj
);
1248 g_string_free(gstr
, true);
1251 static void simple_list(void)
1255 const char *encoded
;
1256 LiteralQObject decoded
;
1259 .encoded
= "[43,42]",
1260 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1268 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1275 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1281 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1282 QLIT_QDICT(((LiteralQDictEntry
[]){
1291 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1295 obj
= qobject_from_json(test_cases
[i
].encoded
);
1296 g_assert(obj
!= NULL
);
1297 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1299 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1301 str
= qobject_to_json(obj
);
1302 qobject_decref(obj
);
1304 obj
= qobject_from_json(qstring_get_str(str
));
1305 g_assert(obj
!= NULL
);
1306 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1308 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1309 qobject_decref(obj
);
1314 static void simple_whitespace(void)
1318 const char *encoded
;
1319 LiteralQObject decoded
;
1322 .encoded
= " [ 43 , 42 ]",
1323 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1330 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1331 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1333 QLIT_QDICT(((LiteralQDictEntry
[]){
1334 { "h", QLIT_QSTR("b") },
1336 QLIT_QLIST(((LiteralQObject
[]){
1343 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1344 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1346 QLIT_QDICT(((LiteralQDictEntry
[]){
1347 { "h", QLIT_QSTR("b") },
1348 { "a", QLIT_QINT(32) },
1350 QLIT_QLIST(((LiteralQObject
[]){
1359 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1363 obj
= qobject_from_json(test_cases
[i
].encoded
);
1364 g_assert(obj
!= NULL
);
1365 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1367 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1369 str
= qobject_to_json(obj
);
1370 qobject_decref(obj
);
1372 obj
= qobject_from_json(qstring_get_str(str
));
1373 g_assert(obj
!= NULL
);
1374 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1376 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1378 qobject_decref(obj
);
1383 static void simple_varargs(void)
1385 QObject
*embedded_obj
;
1387 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
1390 QLIT_QLIST(((LiteralQObject
[]){
1396 embedded_obj
= qobject_from_json("[32, 42]");
1397 g_assert(embedded_obj
!= NULL
);
1399 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
1400 g_assert(obj
!= NULL
);
1402 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
1404 qobject_decref(obj
);
1407 static void empty_input(void)
1409 const char *empty
= "";
1411 QObject
*obj
= qobject_from_json(empty
);
1412 g_assert(obj
== NULL
);
1415 static void unterminated_string(void)
1417 QObject
*obj
= qobject_from_json("\"abc");
1418 g_assert(obj
== NULL
);
1421 static void unterminated_sq_string(void)
1423 QObject
*obj
= qobject_from_json("'abc");
1424 g_assert(obj
== NULL
);
1427 static void unterminated_escape(void)
1429 QObject
*obj
= qobject_from_json("\"abc\\\"");
1430 g_assert(obj
== NULL
);
1433 static void unterminated_array(void)
1435 QObject
*obj
= qobject_from_json("[32");
1436 g_assert(obj
== NULL
);
1439 static void unterminated_array_comma(void)
1441 QObject
*obj
= qobject_from_json("[32,");
1442 g_assert(obj
== NULL
);
1445 static void invalid_array_comma(void)
1447 QObject
*obj
= qobject_from_json("[32,}");
1448 g_assert(obj
== NULL
);
1451 static void unterminated_dict(void)
1453 QObject
*obj
= qobject_from_json("{'abc':32");
1454 g_assert(obj
== NULL
);
1457 static void unterminated_dict_comma(void)
1459 QObject
*obj
= qobject_from_json("{'abc':32,");
1460 g_assert(obj
== NULL
);
1463 static void invalid_dict_comma(void)
1465 QObject
*obj
= qobject_from_json("{'abc':32,}");
1466 g_assert(obj
== NULL
);
1469 static void unterminated_literal(void)
1471 QObject
*obj
= qobject_from_json("nul");
1472 g_assert(obj
== NULL
);
1475 int main(int argc
, char **argv
)
1477 g_test_init(&argc
, &argv
, NULL
);
1479 g_test_add_func("/literals/string/simple", simple_string
);
1480 g_test_add_func("/literals/string/escaped", escaped_string
);
1481 g_test_add_func("/literals/string/utf8", utf8_string
);
1482 g_test_add_func("/literals/string/single_quote", single_quote_string
);
1483 g_test_add_func("/literals/string/vararg", vararg_string
);
1485 g_test_add_func("/literals/number/simple", simple_number
);
1486 g_test_add_func("/literals/number/float", float_number
);
1487 g_test_add_func("/literals/number/vararg", vararg_number
);
1489 g_test_add_func("/literals/keyword", keyword_literal
);
1491 g_test_add_func("/dicts/simple_dict", simple_dict
);
1492 g_test_add_func("/dicts/large_dict", large_dict
);
1493 g_test_add_func("/lists/simple_list", simple_list
);
1495 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1497 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1499 g_test_add_func("/errors/empty_input", empty_input
);
1500 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1501 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1502 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1503 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1504 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1505 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1506 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1507 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1508 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1509 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1511 return g_test_run();