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" },
51 for (i
= 0; test_cases
[i
].encoded
; i
++) {
55 obj
= qobject_from_json(test_cases
[i
].encoded
);
57 g_assert(obj
!= NULL
);
58 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
60 str
= qobject_to_qstring(obj
);
61 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].decoded
);
63 if (test_cases
[i
].skip
== 0) {
64 str
= qobject_to_json(obj
);
65 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].encoded
);
73 static void simple_string(void)
80 { "\"hello world\"", "hello world" },
81 { "\"the quick brown fox jumped over the fence\"",
82 "the quick brown fox jumped over the fence" },
86 for (i
= 0; test_cases
[i
].encoded
; i
++) {
90 obj
= qobject_from_json(test_cases
[i
].encoded
);
92 g_assert(obj
!= NULL
);
93 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
95 str
= qobject_to_qstring(obj
);
96 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
98 str
= qobject_to_json(obj
);
99 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
107 static void single_quote_string(void)
114 { "'hello world'", "hello world" },
115 { "'the quick brown fox \\' jumped over the fence'",
116 "the quick brown fox ' jumped over the fence" },
120 for (i
= 0; test_cases
[i
].encoded
; i
++) {
124 obj
= qobject_from_json(test_cases
[i
].encoded
);
126 g_assert(obj
!= NULL
);
127 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
129 str
= qobject_to_qstring(obj
);
130 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
136 static void utf8_string(void)
139 * FIXME Current behavior for invalid UTF-8 sequences is
140 * incorrect. This test expects current, incorrect results.
141 * They're all marked "bug:" below, and are to be replaced by
142 * correct ones as the bugs get fixed.
144 * The JSON parser rejects some invalid sequences, but accepts
145 * others without correcting the problem.
147 * We should either reject all invalid sequences, or minimize
148 * overlong sequences and replace all other invalid sequences by a
149 * suitable replacement character. A common choice for
150 * replacement is U+FFFD.
152 * Problem: we can't easily deal with embedded U+0000. Parsing
153 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
154 * which gets misinterpreted as NUL-terminated "this ". We should
155 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
158 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
159 * capability and stress test at
160 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
162 static const struct {
164 const char *utf8_out
;
165 const char *json_out
; /* defaults to @json_in */
166 const char *utf8_in
; /* defaults to @utf8_out */
169 * Bug markers used here:
170 * - bug: not corrected
171 * JSON parser fails to correct invalid sequence(s)
173 * JSON parser rejects invalid sequence(s)
174 * We may choose to define this as feature
176 * JSON parser produces incorrect result, this is the
177 * correct one, assuming replacement character U+FFFF
178 * We may choose to reject instead of replace
181 /* 1 Some correct UTF-8 text */
183 /* a bit of German */
184 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
185 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
186 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
187 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
188 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
189 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
193 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
194 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
195 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
197 /* 2 Boundary condition test cases */
198 /* 2.1 First possible sequence of a certain length */
199 /* 2.1.1 1 byte U+0000 */
202 "", /* bug: want overlong "\xC0\x80" */
206 /* 2.1.2 2 bytes U+0080 */
212 /* 2.1.3 3 bytes U+0800 */
218 /* 2.1.4 4 bytes U+10000 */
220 "\"\xF0\x90\x80\x80\"",
222 "\"\\uD800\\uDC00\"",
224 /* 2.1.5 5 bytes U+200000 */
226 "\"\xF8\x88\x80\x80\x80\"",
227 NULL
, /* bug: rejected */
229 "\xF8\x88\x80\x80\x80",
231 /* 2.1.6 6 bytes U+4000000 */
233 "\"\xFC\x84\x80\x80\x80\x80\"",
234 NULL
, /* bug: rejected */
236 "\xFC\x84\x80\x80\x80\x80",
238 /* 2.2 Last possible sequence of a certain length */
239 /* 2.2.1 1 byte U+007F */
245 /* 2.2.2 2 bytes U+07FF */
252 * 2.2.3 3 bytes U+FFFC
253 * The last possible sequence is actually U+FFFF. But that's
254 * a noncharacter, and already covered by its own test case
255 * under 5.3. Same for U+FFFE. U+FFFD is the last character
256 * in the BMP, and covered under 2.3. Because of U+FFFD's
257 * special role as replacement character, it's worth testing
265 /* 2.2.4 4 bytes U+1FFFFF */
267 "\"\xF7\xBF\xBF\xBF\"",
268 NULL
, /* bug: rejected */
272 /* 2.2.5 5 bytes U+3FFFFFF */
274 "\"\xFB\xBF\xBF\xBF\xBF\"",
275 NULL
, /* bug: rejected */
277 "\xFB\xBF\xBF\xBF\xBF",
279 /* 2.2.6 6 bytes U+7FFFFFFF */
281 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
282 NULL
, /* bug: rejected */
284 "\xFD\xBF\xBF\xBF\xBF\xBF",
286 /* 2.3 Other boundary conditions */
288 /* last one before surrogate range: U+D7FF */
294 /* first one after surrogate range: U+E000 */
300 /* last one in BMP: U+FFFD */
306 /* last one in last plane: U+10FFFD */
307 "\"\xF4\x8F\xBF\xBD\"",
312 /* first one beyond Unicode range: U+110000 */
313 "\"\xF4\x90\x80\x80\"",
317 /* 3 Malformed sequences */
318 /* 3.1 Unexpected continuation bytes */
319 /* 3.1.1 First continuation byte */
322 "\x80", /* bug: not corrected */
325 /* 3.1.2 Last continuation byte */
328 "\xBF", /* bug: not corrected */
331 /* 3.1.3 2 continuation bytes */
334 "\x80\xBF", /* bug: not corrected */
335 "\"\\uFFFD\\uFFFD\"",
337 /* 3.1.4 3 continuation bytes */
340 "\x80\xBF\x80", /* bug: not corrected */
341 "\"\\uFFFD\\uFFFD\\uFFFD\"",
343 /* 3.1.5 4 continuation bytes */
345 "\"\x80\xBF\x80\xBF\"",
346 "\x80\xBF\x80\xBF", /* bug: not corrected */
347 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
349 /* 3.1.6 5 continuation bytes */
351 "\"\x80\xBF\x80\xBF\x80\"",
352 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
353 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
355 /* 3.1.7 6 continuation bytes */
357 "\"\x80\xBF\x80\xBF\x80\xBF\"",
358 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
359 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
361 /* 3.1.8 7 continuation bytes */
363 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
364 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
365 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
367 /* 3.1.9 Sequence of all 64 possible continuation bytes */
369 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
370 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
371 "\x90\x91\x92\x93\x94\x95\x96\x97"
372 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
373 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
374 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
375 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
376 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
377 /* bug: not corrected */
378 "\x80\x81\x82\x83\x84\x85\x86\x87"
379 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
380 "\x90\x91\x92\x93\x94\x95\x96\x97"
381 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
382 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
383 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
384 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
385 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
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"
392 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
393 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
395 /* 3.2 Lonely start characters */
396 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
398 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
399 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
400 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
401 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
402 NULL
, /* bug: rejected */
403 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
404 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
405 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
406 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
407 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
408 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
409 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
410 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
412 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
414 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
415 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
416 /* bug: not corrected */
417 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
418 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
419 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
420 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
422 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
424 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
425 NULL
, /* bug: rejected */
426 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
427 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
429 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
431 "\"\xF8 \xF9 \xFA \xFB \"",
432 NULL
, /* bug: rejected */
433 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
434 "\xF8 \xF9 \xFA \xFB ",
436 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
439 NULL
, /* bug: rejected */
440 "\"\\uFFFD \\uFFFD \"",
443 /* 3.3 Sequences with last continuation byte missing */
444 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
447 NULL
, /* bug: rejected */
451 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
454 "\xE0\x80", /* bug: not corrected */
457 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
460 "\xF0\x80\x80", /* bug: not corrected */
463 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
465 "\"\xF8\x80\x80\x80\"",
466 NULL
, /* bug: rejected */
470 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
472 "\"\xFC\x80\x80\x80\x80\"",
473 NULL
, /* bug: rejected */
475 "\xFC\x80\x80\x80\x80",
477 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
480 "\xDF", /* bug: not corrected */
483 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
486 "\xEF\xBF", /* bug: not corrected */
489 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
492 NULL
, /* bug: rejected */
496 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
498 "\"\xFB\xBF\xBF\xBF\"",
499 NULL
, /* bug: rejected */
503 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
505 "\"\xFD\xBF\xBF\xBF\xBF\"",
506 NULL
, /* bug: rejected */
508 "\xFD\xBF\xBF\xBF\xBF",
510 /* 3.4 Concatenation of incomplete sequences */
512 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
513 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
514 NULL
, /* bug: rejected */
515 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
516 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
517 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
518 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
520 /* 3.5 Impossible bytes */
523 NULL
, /* bug: rejected */
529 NULL
, /* bug: rejected */
534 "\"\xFE\xFE\xFF\xFF\"",
535 NULL
, /* bug: rejected */
536 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
539 /* 4 Overlong sequences */
540 /* 4.1 Overlong '/' */
543 NULL
, /* bug: rejected */
549 "\xE0\x80\xAF", /* bug: not corrected */
553 "\"\xF0\x80\x80\xAF\"",
554 "\xF0\x80\x80\xAF", /* bug: not corrected */
558 "\"\xF8\x80\x80\x80\xAF\"",
559 NULL
, /* bug: rejected */
561 "\xF8\x80\x80\x80\xAF",
564 "\"\xFC\x80\x80\x80\x80\xAF\"",
565 NULL
, /* bug: rejected */
567 "\xFC\x80\x80\x80\x80\xAF",
570 * 4.2 Maximum overlong sequences
571 * Highest Unicode value that is still resulting in an
572 * overlong sequence if represented with the given number of
573 * bytes. This is a boundary test for safe UTF-8 decoders.
578 NULL
, /* bug: rejected */
585 "\xE0\x9F\xBF", /* bug: not corrected */
591 * The actual maximum would be U+FFFF, but that's a
592 * noncharacter. Testing U+FFFC seems more useful. See
595 "\"\xF0\x8F\xBF\xBC\"",
596 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
601 "\"\xF8\x87\xBF\xBF\xBF\"",
602 NULL
, /* bug: rejected */
604 "\xF8\x87\xBF\xBF\xBF",
608 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
609 NULL
, /* bug: rejected */
611 "\xFC\x83\xBF\xBF\xBF\xBF",
613 /* 4.3 Overlong representation of the NUL character */
617 NULL
, /* bug: rejected */
624 "\xE0\x80\x80", /* bug: not corrected */
629 "\"\xF0\x80\x80\x80\"",
630 "\xF0\x80\x80\x80", /* bug: not corrected */
635 "\"\xF8\x80\x80\x80\x80\"",
636 NULL
, /* bug: rejected */
638 "\xF8\x80\x80\x80\x80",
642 "\"\xFC\x80\x80\x80\x80\x80\"",
643 NULL
, /* bug: rejected */
645 "\xFC\x80\x80\x80\x80\x80",
647 /* 5 Illegal code positions */
648 /* 5.1 Single UTF-16 surrogates */
652 "\xED\xA0\x80", /* bug: not corrected */
658 "\xED\xAD\xBF", /* bug: not corrected */
664 "\xED\xAE\x80", /* bug: not corrected */
670 "\xED\xAF\xBF", /* bug: not corrected */
676 "\xED\xB0\x80", /* bug: not corrected */
682 "\xED\xBE\x80", /* bug: not corrected */
688 "\xED\xBF\xBF", /* bug: not corrected */
691 /* 5.2 Paired UTF-16 surrogates */
694 "\"\xED\xA0\x80\xED\xB0\x80\"",
695 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
696 "\"\\uFFFD\\uFFFD\"",
700 "\"\xED\xA0\x80\xED\xBF\xBF\"",
701 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
702 "\"\\uFFFD\\uFFFD\"",
706 "\"\xED\xAD\xBF\xED\xB0\x80\"",
707 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
708 "\"\\uFFFD\\uFFFD\"",
712 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
713 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
714 "\"\\uFFFD\\uFFFD\"",
718 "\"\xED\xAE\x80\xED\xB0\x80\"",
719 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
720 "\"\\uFFFD\\uFFFD\"",
724 "\"\xED\xAE\x80\xED\xBF\xBF\"",
725 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
726 "\"\\uFFFD\\uFFFD\"",
730 "\"\xED\xAF\xBF\xED\xB0\x80\"",
731 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
732 "\"\\uFFFD\\uFFFD\"",
736 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
737 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
738 "\"\\uFFFD\\uFFFD\"",
740 /* 5.3 Other illegal code positions */
741 /* BMP noncharacters */
745 "\xEF\xBF\xBE", /* bug: not corrected */
751 "\xEF\xBF\xBF", /* bug: not corrected */
757 "\xEF\xB7\x90", /* bug: not corrected */
763 "\xEF\xB7\xAF", /* bug: not corrected */
766 /* Plane 1 .. 16 noncharacters */
768 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
769 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
770 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
771 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
772 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
773 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
774 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
775 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
776 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
777 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
778 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
779 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
780 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
781 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
782 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
783 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
784 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
785 /* bug: not corrected */
786 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
787 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
788 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
789 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
790 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
791 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
792 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
793 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
794 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
795 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
796 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
797 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
798 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
799 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
800 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
801 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
802 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
803 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
804 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
805 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
812 const char *json_in
, *utf8_out
, *utf8_in
, *json_out
;
814 for (i
= 0; test_cases
[i
].json_in
; i
++) {
815 json_in
= test_cases
[i
].json_in
;
816 utf8_out
= test_cases
[i
].utf8_out
;
817 utf8_in
= test_cases
[i
].utf8_in
?: test_cases
[i
].utf8_out
;
818 json_out
= test_cases
[i
].json_out
?: test_cases
[i
].json_in
;
820 obj
= qobject_from_json(json_in
);
823 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
824 str
= qobject_to_qstring(obj
);
825 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
831 obj
= QOBJECT(qstring_from_str(utf8_in
));
832 str
= qobject_to_json(obj
);
835 g_assert_cmpstr(qstring_get_str(str
), ==, json_out
);
843 * Disabled, because qobject_from_json() is buggy, and I can't
844 * be bothered to add the expected incorrect results.
845 * FIXME Enable once these bugs have been fixed.
847 if (0 && json_out
!= json_in
) {
848 obj
= qobject_from_json(json_out
);
850 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
851 str
= qobject_to_qstring(obj
);
852 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
857 static void vararg_string(void)
864 { "the quick brown fox jumped over the fence" },
868 for (i
= 0; test_cases
[i
].decoded
; i
++) {
872 obj
= qobject_from_jsonf("%s", test_cases
[i
].decoded
);
874 g_assert(obj
!= NULL
);
875 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
877 str
= qobject_to_qstring(obj
);
878 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
884 static void simple_number(void)
896 { "-0", 0, .skip
= 1 },
900 for (i
= 0; test_cases
[i
].encoded
; i
++) {
904 obj
= qobject_from_json(test_cases
[i
].encoded
);
905 g_assert(obj
!= NULL
);
906 g_assert(qobject_type(obj
) == QTYPE_QINT
);
908 qint
= qobject_to_qint(obj
);
909 g_assert(qint_get_int(qint
) == test_cases
[i
].decoded
);
910 if (test_cases
[i
].skip
== 0) {
913 str
= qobject_to_json(obj
);
914 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
922 static void float_number(void)
932 { "-32.12313", -32.12313 },
933 { "-32.20e-10", -32.20e-10, .skip
= 1 },
937 for (i
= 0; test_cases
[i
].encoded
; i
++) {
941 obj
= qobject_from_json(test_cases
[i
].encoded
);
942 g_assert(obj
!= NULL
);
943 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
945 qfloat
= qobject_to_qfloat(obj
);
946 g_assert(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
948 if (test_cases
[i
].skip
== 0) {
951 str
= qobject_to_json(obj
);
952 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
960 static void vararg_number(void)
966 int64_t value64
= 0x2342342343LL
;
967 double valuef
= 2.323423423;
969 obj
= qobject_from_jsonf("%d", value
);
970 g_assert(obj
!= NULL
);
971 g_assert(qobject_type(obj
) == QTYPE_QINT
);
973 qint
= qobject_to_qint(obj
);
974 g_assert(qint_get_int(qint
) == value
);
978 obj
= qobject_from_jsonf("%" PRId64
, value64
);
979 g_assert(obj
!= NULL
);
980 g_assert(qobject_type(obj
) == QTYPE_QINT
);
982 qint
= qobject_to_qint(obj
);
983 g_assert(qint_get_int(qint
) == value64
);
987 obj
= qobject_from_jsonf("%f", valuef
);
988 g_assert(obj
!= NULL
);
989 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
991 qfloat
= qobject_to_qfloat(obj
);
992 g_assert(qfloat_get_double(qfloat
) == valuef
);
997 static void keyword_literal(void)
1003 obj
= qobject_from_json("true");
1004 g_assert(obj
!= NULL
);
1005 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1007 qbool
= qobject_to_qbool(obj
);
1008 g_assert(qbool_get_int(qbool
) != 0);
1010 str
= qobject_to_json(obj
);
1011 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
1016 obj
= qobject_from_json("false");
1017 g_assert(obj
!= NULL
);
1018 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1020 qbool
= qobject_to_qbool(obj
);
1021 g_assert(qbool_get_int(qbool
) == 0);
1023 str
= qobject_to_json(obj
);
1024 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
1029 obj
= qobject_from_jsonf("%i", false);
1030 g_assert(obj
!= NULL
);
1031 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1033 qbool
= qobject_to_qbool(obj
);
1034 g_assert(qbool_get_int(qbool
) == 0);
1038 obj
= qobject_from_jsonf("%i", true);
1039 g_assert(obj
!= NULL
);
1040 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
1042 qbool
= qobject_to_qbool(obj
);
1043 g_assert(qbool_get_int(qbool
) != 0);
1048 typedef struct LiteralQDictEntry LiteralQDictEntry
;
1049 typedef struct LiteralQObject LiteralQObject
;
1051 struct LiteralQObject
1057 LiteralQDictEntry
*qdict
;
1058 LiteralQObject
*qlist
;
1062 struct LiteralQDictEntry
1065 LiteralQObject value
;
1068 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1069 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1070 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1071 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1073 typedef struct QListCompareHelper
1076 LiteralQObject
*objs
;
1078 } QListCompareHelper
;
1080 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
1082 static void compare_helper(QObject
*obj
, void *opaque
)
1084 QListCompareHelper
*helper
= opaque
;
1086 if (helper
->result
== 0) {
1090 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
1095 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
1098 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
1100 if (lhs
->type
!= qobject_type(rhs
)) {
1104 switch (lhs
->type
) {
1106 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
1108 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
1112 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
1113 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
1115 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
1123 QListCompareHelper helper
;
1126 helper
.objs
= lhs
->value
.qlist
;
1129 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
1131 return helper
.result
;
1140 static void simple_dict(void)
1144 const char *encoded
;
1145 LiteralQObject decoded
;
1148 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
1149 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1150 { "foo", QLIT_QINT(42) },
1151 { "bar", QLIT_QSTR("hello world") },
1156 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1160 .encoded
= "{\"foo\": 43}",
1161 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1162 { "foo", QLIT_QINT(43) },
1169 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1173 obj
= qobject_from_json(test_cases
[i
].encoded
);
1174 g_assert(obj
!= NULL
);
1175 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
1177 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1179 str
= qobject_to_json(obj
);
1180 qobject_decref(obj
);
1182 obj
= qobject_from_json(qstring_get_str(str
));
1183 g_assert(obj
!= NULL
);
1184 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
1186 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1187 qobject_decref(obj
);
1193 * this generates json of the form:
1194 * a(0,m) = [0, 1, ..., m-1]
1199 * 'key(n-1)': a(n-1,m)
1202 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1208 if (nest_level_max
== 0) {
1209 g_string_append(gstr
, "[");
1210 for (i
= 0; i
< elem_count
; i
++) {
1211 g_string_append_printf(gstr
, "%d", i
);
1212 if (i
< elem_count
- 1) {
1213 g_string_append_printf(gstr
, ", ");
1216 g_string_append(gstr
, "]");
1220 g_string_append(gstr
, "{");
1221 for (i
= 0; i
< nest_level_max
; i
++) {
1222 g_string_append_printf(gstr
, "'key%d': ", i
);
1223 gen_test_json(gstr
, i
, elem_count
);
1224 if (i
< nest_level_max
- 1) {
1225 g_string_append(gstr
, ",");
1228 g_string_append(gstr
, "}");
1231 static void large_dict(void)
1233 GString
*gstr
= g_string_new("");
1236 gen_test_json(gstr
, 10, 100);
1237 obj
= qobject_from_json(gstr
->str
);
1238 g_assert(obj
!= NULL
);
1240 qobject_decref(obj
);
1241 g_string_free(gstr
, true);
1244 static void simple_list(void)
1248 const char *encoded
;
1249 LiteralQObject decoded
;
1252 .encoded
= "[43,42]",
1253 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1261 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1268 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1274 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1275 QLIT_QDICT(((LiteralQDictEntry
[]){
1284 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1288 obj
= qobject_from_json(test_cases
[i
].encoded
);
1289 g_assert(obj
!= NULL
);
1290 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1292 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1294 str
= qobject_to_json(obj
);
1295 qobject_decref(obj
);
1297 obj
= qobject_from_json(qstring_get_str(str
));
1298 g_assert(obj
!= NULL
);
1299 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1301 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1302 qobject_decref(obj
);
1307 static void simple_whitespace(void)
1311 const char *encoded
;
1312 LiteralQObject decoded
;
1315 .encoded
= " [ 43 , 42 ]",
1316 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1323 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1324 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1326 QLIT_QDICT(((LiteralQDictEntry
[]){
1327 { "h", QLIT_QSTR("b") },
1329 QLIT_QLIST(((LiteralQObject
[]){
1336 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1337 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1339 QLIT_QDICT(((LiteralQDictEntry
[]){
1340 { "h", QLIT_QSTR("b") },
1341 { "a", QLIT_QINT(32) },
1343 QLIT_QLIST(((LiteralQObject
[]){
1352 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1356 obj
= qobject_from_json(test_cases
[i
].encoded
);
1357 g_assert(obj
!= NULL
);
1358 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1360 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1362 str
= qobject_to_json(obj
);
1363 qobject_decref(obj
);
1365 obj
= qobject_from_json(qstring_get_str(str
));
1366 g_assert(obj
!= NULL
);
1367 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
1369 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1371 qobject_decref(obj
);
1376 static void simple_varargs(void)
1378 QObject
*embedded_obj
;
1380 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
1383 QLIT_QLIST(((LiteralQObject
[]){
1389 embedded_obj
= qobject_from_json("[32, 42]");
1390 g_assert(embedded_obj
!= NULL
);
1392 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
1393 g_assert(obj
!= NULL
);
1395 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
1397 qobject_decref(obj
);
1400 static void empty_input(void)
1402 const char *empty
= "";
1404 QObject
*obj
= qobject_from_json(empty
);
1405 g_assert(obj
== NULL
);
1408 static void unterminated_string(void)
1410 QObject
*obj
= qobject_from_json("\"abc");
1411 g_assert(obj
== NULL
);
1414 static void unterminated_sq_string(void)
1416 QObject
*obj
= qobject_from_json("'abc");
1417 g_assert(obj
== NULL
);
1420 static void unterminated_escape(void)
1422 QObject
*obj
= qobject_from_json("\"abc\\\"");
1423 g_assert(obj
== NULL
);
1426 static void unterminated_array(void)
1428 QObject
*obj
= qobject_from_json("[32");
1429 g_assert(obj
== NULL
);
1432 static void unterminated_array_comma(void)
1434 QObject
*obj
= qobject_from_json("[32,");
1435 g_assert(obj
== NULL
);
1438 static void invalid_array_comma(void)
1440 QObject
*obj
= qobject_from_json("[32,}");
1441 g_assert(obj
== NULL
);
1444 static void unterminated_dict(void)
1446 QObject
*obj
= qobject_from_json("{'abc':32");
1447 g_assert(obj
== NULL
);
1450 static void unterminated_dict_comma(void)
1452 QObject
*obj
= qobject_from_json("{'abc':32,");
1453 g_assert(obj
== NULL
);
1456 static void invalid_dict_comma(void)
1458 QObject
*obj
= qobject_from_json("{'abc':32,}");
1459 g_assert(obj
== NULL
);
1462 static void unterminated_literal(void)
1464 QObject
*obj
= qobject_from_json("nul");
1465 g_assert(obj
== NULL
);
1468 int main(int argc
, char **argv
)
1470 g_test_init(&argc
, &argv
, NULL
);
1472 g_test_add_func("/literals/string/simple", simple_string
);
1473 g_test_add_func("/literals/string/escaped", escaped_string
);
1474 g_test_add_func("/literals/string/utf8", utf8_string
);
1475 g_test_add_func("/literals/string/single_quote", single_quote_string
);
1476 g_test_add_func("/literals/string/vararg", vararg_string
);
1478 g_test_add_func("/literals/number/simple", simple_number
);
1479 g_test_add_func("/literals/number/float", float_number
);
1480 g_test_add_func("/literals/number/vararg", vararg_number
);
1482 g_test_add_func("/literals/keyword", keyword_literal
);
1484 g_test_add_func("/dicts/simple_dict", simple_dict
);
1485 g_test_add_func("/dicts/large_dict", large_dict
);
1486 g_test_add_func("/lists/simple_list", simple_list
);
1488 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1490 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1492 g_test_add_func("/errors/empty_input", empty_input
);
1493 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1494 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1495 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1496 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1497 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1498 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1499 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1500 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1501 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1502 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1504 return g_test_run();