2 * Copyright IBM, Corp. 2009
3 * Copyright (c) 2013, 2015 Red Hat Inc.
6 * Anthony Liguori <aliguori@us.ibm.com>
7 * Markus Armbruster <armbru@redhat.com>
9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 * See the COPYING.LIB file in the top-level directory.
14 #include "qemu/osdep.h"
16 #include "qapi/error.h"
17 #include "qapi/qmp/types.h"
18 #include "qapi/qmp/qjson.h"
19 #include "qemu-common.h"
21 static void escaped_string(void)
35 { "\"\\/\"", "/", .skip
= 1 },
38 { "\"hello world \\\"embedded string\\\"\"",
39 "hello world \"embedded string\"" },
40 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
41 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip
= 1 },
42 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
43 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
44 { "'\\b'", "\b", .skip
= 1 },
45 { "'\\f'", "\f", .skip
= 1 },
46 { "'\\n'", "\n", .skip
= 1 },
47 { "'\\r'", "\r", .skip
= 1 },
48 { "'\\t'", "\t", .skip
= 1 },
49 { "'\\/'", "/", .skip
= 1 },
50 { "'\\\\'", "\\", .skip
= 1 },
54 for (i
= 0; test_cases
[i
].encoded
; i
++) {
58 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
59 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
, &error_abort
);
91 str
= qobject_to_qstring(obj
);
93 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
95 str
= qobject_to_json(obj
);
96 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
104 static void single_quote_string(void)
111 { "'hello world'", "hello world" },
112 { "'the quick brown fox \\' jumped over the fence'",
113 "the quick brown fox ' jumped over the fence" },
117 for (i
= 0; test_cases
[i
].encoded
; i
++) {
121 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
122 str
= qobject_to_qstring(obj
);
124 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
130 static void utf8_string(void)
133 * FIXME Current behavior for invalid UTF-8 sequences is
134 * incorrect. This test expects current, incorrect results.
135 * They're all marked "bug:" below, and are to be replaced by
136 * correct ones as the bugs get fixed.
138 * The JSON parser rejects some invalid sequences, but accepts
139 * others without correcting the problem.
141 * We should either reject all invalid sequences, or minimize
142 * overlong sequences and replace all other invalid sequences by a
143 * suitable replacement character. A common choice for
144 * replacement is U+FFFD.
146 * Problem: we can't easily deal with embedded U+0000. Parsing
147 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
148 * which gets misinterpreted as NUL-terminated "this ". We should
149 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
152 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
153 * capability and stress test at
154 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
156 static const struct {
158 const char *utf8_out
;
159 const char *json_out
; /* defaults to @json_in */
160 const char *utf8_in
; /* defaults to @utf8_out */
163 * Bug markers used here:
164 * - bug: not corrected
165 * JSON parser fails to correct invalid sequence(s)
167 * JSON parser rejects invalid sequence(s)
168 * We may choose to define this as feature
170 * JSON parser produces incorrect result, this is the
171 * correct one, assuming replacement character U+FFFF
172 * We may choose to reject instead of replace
175 /* 1 Some correct UTF-8 text */
177 /* a bit of German */
178 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
179 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
180 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
181 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
182 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
183 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
187 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
188 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
189 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
191 /* 2 Boundary condition test cases */
192 /* 2.1 First possible sequence of a certain length */
193 /* 2.1.1 1 byte U+0000 */
196 "", /* bug: want overlong "\xC0\x80" */
200 /* 2.1.2 2 bytes U+0080 */
206 /* 2.1.3 3 bytes U+0800 */
212 /* 2.1.4 4 bytes U+10000 */
214 "\"\xF0\x90\x80\x80\"",
216 "\"\\uD800\\uDC00\"",
218 /* 2.1.5 5 bytes U+200000 */
220 "\"\xF8\x88\x80\x80\x80\"",
221 NULL
, /* bug: rejected */
223 "\xF8\x88\x80\x80\x80",
225 /* 2.1.6 6 bytes U+4000000 */
227 "\"\xFC\x84\x80\x80\x80\x80\"",
228 NULL
, /* bug: rejected */
230 "\xFC\x84\x80\x80\x80\x80",
232 /* 2.2 Last possible sequence of a certain length */
233 /* 2.2.1 1 byte U+007F */
239 /* 2.2.2 2 bytes U+07FF */
246 * 2.2.3 3 bytes U+FFFC
247 * The last possible sequence is actually U+FFFF. But that's
248 * a noncharacter, and already covered by its own test case
249 * under 5.3. Same for U+FFFE. U+FFFD is the last character
250 * in the BMP, and covered under 2.3. Because of U+FFFD's
251 * special role as replacement character, it's worth testing
259 /* 2.2.4 4 bytes U+1FFFFF */
261 "\"\xF7\xBF\xBF\xBF\"",
262 NULL
, /* bug: rejected */
266 /* 2.2.5 5 bytes U+3FFFFFF */
268 "\"\xFB\xBF\xBF\xBF\xBF\"",
269 NULL
, /* bug: rejected */
271 "\xFB\xBF\xBF\xBF\xBF",
273 /* 2.2.6 6 bytes U+7FFFFFFF */
275 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
276 NULL
, /* bug: rejected */
278 "\xFD\xBF\xBF\xBF\xBF\xBF",
280 /* 2.3 Other boundary conditions */
282 /* last one before surrogate range: U+D7FF */
288 /* first one after surrogate range: U+E000 */
294 /* last one in BMP: U+FFFD */
300 /* last one in last plane: U+10FFFD */
301 "\"\xF4\x8F\xBF\xBD\"",
306 /* first one beyond Unicode range: U+110000 */
307 "\"\xF4\x90\x80\x80\"",
311 /* 3 Malformed sequences */
312 /* 3.1 Unexpected continuation bytes */
313 /* 3.1.1 First continuation byte */
316 "\x80", /* bug: not corrected */
319 /* 3.1.2 Last continuation byte */
322 "\xBF", /* bug: not corrected */
325 /* 3.1.3 2 continuation bytes */
328 "\x80\xBF", /* bug: not corrected */
329 "\"\\uFFFD\\uFFFD\"",
331 /* 3.1.4 3 continuation bytes */
334 "\x80\xBF\x80", /* bug: not corrected */
335 "\"\\uFFFD\\uFFFD\\uFFFD\"",
337 /* 3.1.5 4 continuation bytes */
339 "\"\x80\xBF\x80\xBF\"",
340 "\x80\xBF\x80\xBF", /* bug: not corrected */
341 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
343 /* 3.1.6 5 continuation bytes */
345 "\"\x80\xBF\x80\xBF\x80\"",
346 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
347 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
349 /* 3.1.7 6 continuation bytes */
351 "\"\x80\xBF\x80\xBF\x80\xBF\"",
352 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
353 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
355 /* 3.1.8 7 continuation bytes */
357 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
358 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
359 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
361 /* 3.1.9 Sequence of all 64 possible continuation bytes */
363 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
364 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
365 "\x90\x91\x92\x93\x94\x95\x96\x97"
366 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
367 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
368 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
369 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
370 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
371 /* bug: not corrected */
372 "\x80\x81\x82\x83\x84\x85\x86\x87"
373 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
374 "\x90\x91\x92\x93\x94\x95\x96\x97"
375 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
376 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
377 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
378 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
379 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
380 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
381 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
382 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
383 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
384 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
385 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
386 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
387 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
389 /* 3.2 Lonely start characters */
390 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
392 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
393 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
394 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
395 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
396 NULL
, /* bug: rejected */
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 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
402 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
403 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
404 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
406 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
408 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
409 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
410 /* bug: not corrected */
411 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
412 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
413 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
414 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
416 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
418 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
419 NULL
, /* bug: rejected */
420 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
421 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
423 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
425 "\"\xF8 \xF9 \xFA \xFB \"",
426 NULL
, /* bug: rejected */
427 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
428 "\xF8 \xF9 \xFA \xFB ",
430 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
433 NULL
, /* bug: rejected */
434 "\"\\uFFFD \\uFFFD \"",
437 /* 3.3 Sequences with last continuation byte missing */
438 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
441 NULL
, /* bug: rejected */
445 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
448 "\xE0\x80", /* bug: not corrected */
451 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
454 "\xF0\x80\x80", /* bug: not corrected */
457 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
459 "\"\xF8\x80\x80\x80\"",
460 NULL
, /* bug: rejected */
464 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
466 "\"\xFC\x80\x80\x80\x80\"",
467 NULL
, /* bug: rejected */
469 "\xFC\x80\x80\x80\x80",
471 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
474 "\xDF", /* bug: not corrected */
477 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
480 "\xEF\xBF", /* bug: not corrected */
483 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
486 NULL
, /* bug: rejected */
490 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
492 "\"\xFB\xBF\xBF\xBF\"",
493 NULL
, /* bug: rejected */
497 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
499 "\"\xFD\xBF\xBF\xBF\xBF\"",
500 NULL
, /* bug: rejected */
502 "\xFD\xBF\xBF\xBF\xBF",
504 /* 3.4 Concatenation of incomplete sequences */
506 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
507 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
508 NULL
, /* bug: rejected */
509 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
510 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
511 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
512 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
514 /* 3.5 Impossible bytes */
517 NULL
, /* bug: rejected */
523 NULL
, /* bug: rejected */
528 "\"\xFE\xFE\xFF\xFF\"",
529 NULL
, /* bug: rejected */
530 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
533 /* 4 Overlong sequences */
534 /* 4.1 Overlong '/' */
537 NULL
, /* bug: rejected */
543 "\xE0\x80\xAF", /* bug: not corrected */
547 "\"\xF0\x80\x80\xAF\"",
548 "\xF0\x80\x80\xAF", /* bug: not corrected */
552 "\"\xF8\x80\x80\x80\xAF\"",
553 NULL
, /* bug: rejected */
555 "\xF8\x80\x80\x80\xAF",
558 "\"\xFC\x80\x80\x80\x80\xAF\"",
559 NULL
, /* bug: rejected */
561 "\xFC\x80\x80\x80\x80\xAF",
564 * 4.2 Maximum overlong sequences
565 * Highest Unicode value that is still resulting in an
566 * overlong sequence if represented with the given number of
567 * bytes. This is a boundary test for safe UTF-8 decoders.
572 NULL
, /* bug: rejected */
579 "\xE0\x9F\xBF", /* bug: not corrected */
585 * The actual maximum would be U+FFFF, but that's a
586 * noncharacter. Testing U+FFFC seems more useful. See
589 "\"\xF0\x8F\xBF\xBC\"",
590 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
595 "\"\xF8\x87\xBF\xBF\xBF\"",
596 NULL
, /* bug: rejected */
598 "\xF8\x87\xBF\xBF\xBF",
602 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
603 NULL
, /* bug: rejected */
605 "\xFC\x83\xBF\xBF\xBF\xBF",
607 /* 4.3 Overlong representation of the NUL character */
611 NULL
, /* bug: rejected */
618 "\xE0\x80\x80", /* bug: not corrected */
623 "\"\xF0\x80\x80\x80\"",
624 "\xF0\x80\x80\x80", /* bug: not corrected */
629 "\"\xF8\x80\x80\x80\x80\"",
630 NULL
, /* bug: rejected */
632 "\xF8\x80\x80\x80\x80",
636 "\"\xFC\x80\x80\x80\x80\x80\"",
637 NULL
, /* bug: rejected */
639 "\xFC\x80\x80\x80\x80\x80",
641 /* 5 Illegal code positions */
642 /* 5.1 Single UTF-16 surrogates */
646 "\xED\xA0\x80", /* bug: not corrected */
652 "\xED\xAD\xBF", /* bug: not corrected */
658 "\xED\xAE\x80", /* bug: not corrected */
664 "\xED\xAF\xBF", /* bug: not corrected */
670 "\xED\xB0\x80", /* bug: not corrected */
676 "\xED\xBE\x80", /* bug: not corrected */
682 "\xED\xBF\xBF", /* bug: not corrected */
685 /* 5.2 Paired UTF-16 surrogates */
688 "\"\xED\xA0\x80\xED\xB0\x80\"",
689 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
690 "\"\\uFFFD\\uFFFD\"",
694 "\"\xED\xA0\x80\xED\xBF\xBF\"",
695 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
696 "\"\\uFFFD\\uFFFD\"",
700 "\"\xED\xAD\xBF\xED\xB0\x80\"",
701 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
702 "\"\\uFFFD\\uFFFD\"",
706 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
707 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
708 "\"\\uFFFD\\uFFFD\"",
712 "\"\xED\xAE\x80\xED\xB0\x80\"",
713 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
714 "\"\\uFFFD\\uFFFD\"",
718 "\"\xED\xAE\x80\xED\xBF\xBF\"",
719 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
720 "\"\\uFFFD\\uFFFD\"",
724 "\"\xED\xAF\xBF\xED\xB0\x80\"",
725 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
726 "\"\\uFFFD\\uFFFD\"",
730 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
731 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
732 "\"\\uFFFD\\uFFFD\"",
734 /* 5.3 Other illegal code positions */
735 /* BMP noncharacters */
739 "\xEF\xBF\xBE", /* bug: not corrected */
745 "\xEF\xBF\xBF", /* bug: not corrected */
751 "\xEF\xB7\x90", /* bug: not corrected */
757 "\xEF\xB7\xAF", /* bug: not corrected */
760 /* Plane 1 .. 16 noncharacters */
762 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
763 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
764 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
765 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
766 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
767 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
768 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
769 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
770 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
771 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
772 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
773 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
774 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
775 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
776 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
777 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
778 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
779 /* bug: not corrected */
780 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
781 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
782 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
783 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
784 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
785 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
786 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
787 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
788 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
789 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
790 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
791 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
792 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
793 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
794 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
795 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
796 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
797 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
798 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
799 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
806 const char *json_in
, *utf8_out
, *utf8_in
, *json_out
;
808 for (i
= 0; test_cases
[i
].json_in
; i
++) {
809 json_in
= test_cases
[i
].json_in
;
810 utf8_out
= test_cases
[i
].utf8_out
;
811 utf8_in
= test_cases
[i
].utf8_in
?: test_cases
[i
].utf8_out
;
812 json_out
= test_cases
[i
].json_out
?: test_cases
[i
].json_in
;
814 obj
= qobject_from_json(json_in
, utf8_out
? &error_abort
: NULL
);
816 str
= qobject_to_qstring(obj
);
818 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
824 obj
= QOBJECT(qstring_from_str(utf8_in
));
825 str
= qobject_to_json(obj
);
828 g_assert_cmpstr(qstring_get_str(str
), ==, json_out
);
836 * Disabled, because qobject_from_json() is buggy, and I can't
837 * be bothered to add the expected incorrect results.
838 * FIXME Enable once these bugs have been fixed.
840 if (0 && json_out
!= json_in
) {
841 obj
= qobject_from_json(json_out
, &error_abort
);
842 str
= qobject_to_qstring(obj
);
844 g_assert_cmpstr(qstring_get_str(str
), ==, utf8_out
);
849 static void vararg_string(void)
856 { "the quick brown fox jumped over the fence" },
860 for (i
= 0; test_cases
[i
].decoded
; i
++) {
863 str
= qobject_to_qstring(qobject_from_jsonf("%s",
864 test_cases
[i
].decoded
));
866 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
872 static void simple_number(void)
884 { "-0", 0, .skip
= 1 },
888 for (i
= 0; test_cases
[i
].encoded
; i
++) {
892 qnum
= qobject_to_qnum(qobject_from_json(test_cases
[i
].encoded
,
895 g_assert(qnum_get_try_int(qnum
, &val
));
896 g_assert_cmpint(val
, ==, test_cases
[i
].decoded
);
897 if (test_cases
[i
].skip
== 0) {
900 str
= qobject_to_json(QOBJECT(qnum
));
901 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
909 static void float_number(void)
919 { "-32.12313", -32.12313 },
920 { "-32.20e-10", -32.20e-10, .skip
= 1 },
924 for (i
= 0; test_cases
[i
].encoded
; i
++) {
928 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
929 qnum
= qobject_to_qnum(obj
);
931 g_assert(qnum_get_double(qnum
) == test_cases
[i
].decoded
);
933 if (test_cases
[i
].skip
== 0) {
936 str
= qobject_to_json(obj
);
937 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
945 static void vararg_number(void)
949 long long value_ll
= 0x2342342343LL
;
950 double valuef
= 2.323423423;
953 qnum
= qobject_to_qnum(qobject_from_jsonf("%d", value
));
954 g_assert(qnum_get_try_int(qnum
, &val
));
955 g_assert_cmpint(val
, ==, value
);
958 qnum
= qobject_to_qnum(qobject_from_jsonf("%lld", value_ll
));
959 g_assert(qnum_get_try_int(qnum
, &val
));
960 g_assert_cmpint(val
, ==, value_ll
);
963 qnum
= qobject_to_qnum(qobject_from_jsonf("%f", valuef
));
964 g_assert(qnum_get_double(qnum
) == valuef
);
968 static void keyword_literal(void)
975 obj
= qobject_from_json("true", &error_abort
);
976 qbool
= qobject_to_qbool(obj
);
978 g_assert(qbool_get_bool(qbool
) == true);
980 str
= qobject_to_json(obj
);
981 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
986 obj
= qobject_from_json("false", &error_abort
);
987 qbool
= qobject_to_qbool(obj
);
989 g_assert(qbool_get_bool(qbool
) == false);
991 str
= qobject_to_json(obj
);
992 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
997 qbool
= qobject_to_qbool(qobject_from_jsonf("%i", false));
999 g_assert(qbool_get_bool(qbool
) == false);
1002 /* Test that non-zero values other than 1 get collapsed to true */
1003 qbool
= qobject_to_qbool(qobject_from_jsonf("%i", 2));
1005 g_assert(qbool_get_bool(qbool
) == true);
1008 obj
= qobject_from_json("null", &error_abort
);
1009 g_assert(obj
!= NULL
);
1010 g_assert(qobject_type(obj
) == QTYPE_QNULL
);
1013 g_assert(null
== obj
);
1015 qobject_decref(obj
);
1016 qobject_decref(null
);
1019 typedef struct LiteralQDictEntry LiteralQDictEntry
;
1020 typedef struct LiteralQObject LiteralQObject
;
1022 struct LiteralQObject
1028 LiteralQDictEntry
*qdict
;
1029 LiteralQObject
*qlist
;
1033 struct LiteralQDictEntry
1036 LiteralQObject value
;
1039 #define QLIT_QNUM(val) (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
1040 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1041 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1042 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1044 typedef struct QListCompareHelper
1047 LiteralQObject
*objs
;
1049 } QListCompareHelper
;
1051 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
1053 static void compare_helper(QObject
*obj
, void *opaque
)
1055 QListCompareHelper
*helper
= opaque
;
1057 if (helper
->result
== 0) {
1061 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
1066 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
1069 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
1073 if (!rhs
|| lhs
->type
!= qobject_type(rhs
)) {
1077 switch (lhs
->type
) {
1079 g_assert(qnum_get_try_int(qobject_to_qnum(rhs
), &val
));
1080 return lhs
->value
.qnum
== val
;
1082 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
1086 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
1087 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
1089 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
1097 QListCompareHelper helper
;
1100 helper
.objs
= lhs
->value
.qlist
;
1103 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
1105 return helper
.result
;
1114 static void simple_dict(void)
1118 const char *encoded
;
1119 LiteralQObject decoded
;
1122 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
1123 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1124 { "foo", QLIT_QNUM(42) },
1125 { "bar", QLIT_QSTR("hello world") },
1130 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1134 .encoded
= "{\"foo\": 43}",
1135 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1136 { "foo", QLIT_QNUM(43) },
1143 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1147 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1148 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1150 str
= qobject_to_json(obj
);
1151 qobject_decref(obj
);
1153 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1154 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1155 qobject_decref(obj
);
1161 * this generates json of the form:
1162 * a(0,m) = [0, 1, ..., m-1]
1167 * 'key(n-1)': a(n-1,m)
1170 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1176 if (nest_level_max
== 0) {
1177 g_string_append(gstr
, "[");
1178 for (i
= 0; i
< elem_count
; i
++) {
1179 g_string_append_printf(gstr
, "%d", i
);
1180 if (i
< elem_count
- 1) {
1181 g_string_append_printf(gstr
, ", ");
1184 g_string_append(gstr
, "]");
1188 g_string_append(gstr
, "{");
1189 for (i
= 0; i
< nest_level_max
; i
++) {
1190 g_string_append_printf(gstr
, "'key%d': ", i
);
1191 gen_test_json(gstr
, i
, elem_count
);
1192 if (i
< nest_level_max
- 1) {
1193 g_string_append(gstr
, ",");
1196 g_string_append(gstr
, "}");
1199 static void large_dict(void)
1201 GString
*gstr
= g_string_new("");
1204 gen_test_json(gstr
, 10, 100);
1205 obj
= qobject_from_json(gstr
->str
, &error_abort
);
1206 g_assert(obj
!= NULL
);
1208 qobject_decref(obj
);
1209 g_string_free(gstr
, true);
1212 static void simple_list(void)
1216 const char *encoded
;
1217 LiteralQObject decoded
;
1220 .encoded
= "[43,42]",
1221 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1229 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1236 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1242 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1243 QLIT_QDICT(((LiteralQDictEntry
[]){
1252 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1256 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1257 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1259 str
= qobject_to_json(obj
);
1260 qobject_decref(obj
);
1262 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1263 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1264 qobject_decref(obj
);
1269 static void simple_whitespace(void)
1273 const char *encoded
;
1274 LiteralQObject decoded
;
1277 .encoded
= " [ 43 , 42 ]",
1278 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1285 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1286 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1288 QLIT_QDICT(((LiteralQDictEntry
[]){
1289 { "h", QLIT_QSTR("b") },
1291 QLIT_QLIST(((LiteralQObject
[]){
1298 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1299 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1301 QLIT_QDICT(((LiteralQDictEntry
[]){
1302 { "h", QLIT_QSTR("b") },
1303 { "a", QLIT_QNUM(32) },
1305 QLIT_QLIST(((LiteralQObject
[]){
1314 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1318 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1319 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1321 str
= qobject_to_json(obj
);
1322 qobject_decref(obj
);
1324 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1325 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1327 qobject_decref(obj
);
1332 static void simple_varargs(void)
1334 QObject
*embedded_obj
;
1336 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
1339 QLIT_QLIST(((LiteralQObject
[]){
1345 embedded_obj
= qobject_from_json("[32, 42]", &error_abort
);
1346 g_assert(embedded_obj
!= NULL
);
1348 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
1349 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
1351 qobject_decref(obj
);
1354 static void empty_input(void)
1356 const char *empty
= "";
1357 QObject
*obj
= qobject_from_json(empty
, &error_abort
);
1358 g_assert(obj
== NULL
);
1361 static void unterminated_string(void)
1364 QObject
*obj
= qobject_from_json("\"abc", &err
);
1365 g_assert(!err
); /* BUG */
1366 g_assert(obj
== NULL
);
1369 static void unterminated_sq_string(void)
1372 QObject
*obj
= qobject_from_json("'abc", &err
);
1373 g_assert(!err
); /* BUG */
1374 g_assert(obj
== NULL
);
1377 static void unterminated_escape(void)
1380 QObject
*obj
= qobject_from_json("\"abc\\\"", &err
);
1381 g_assert(!err
); /* BUG */
1382 g_assert(obj
== NULL
);
1385 static void unterminated_array(void)
1388 QObject
*obj
= qobject_from_json("[32", &err
);
1389 g_assert(!err
); /* BUG */
1390 g_assert(obj
== NULL
);
1393 static void unterminated_array_comma(void)
1396 QObject
*obj
= qobject_from_json("[32,", &err
);
1397 g_assert(!err
); /* BUG */
1398 g_assert(obj
== NULL
);
1401 static void invalid_array_comma(void)
1404 QObject
*obj
= qobject_from_json("[32,}", &err
);
1405 error_free_or_abort(&err
);
1406 g_assert(obj
== NULL
);
1409 static void unterminated_dict(void)
1412 QObject
*obj
= qobject_from_json("{'abc':32", &err
);
1413 g_assert(!err
); /* BUG */
1414 g_assert(obj
== NULL
);
1417 static void unterminated_dict_comma(void)
1420 QObject
*obj
= qobject_from_json("{'abc':32,", &err
);
1421 g_assert(!err
); /* BUG */
1422 g_assert(obj
== NULL
);
1425 static void invalid_dict_comma(void)
1428 QObject
*obj
= qobject_from_json("{'abc':32,}", &err
);
1429 error_free_or_abort(&err
);
1430 g_assert(obj
== NULL
);
1433 static void unterminated_literal(void)
1436 QObject
*obj
= qobject_from_json("nul", &err
);
1437 error_free_or_abort(&err
);
1438 g_assert(obj
== NULL
);
1441 static char *make_nest(char *buf
, size_t cnt
)
1443 memset(buf
, '[', cnt
- 1);
1446 memset(buf
+ cnt
+ 1, ']', cnt
- 1);
1451 static void limits_nesting(void)
1454 enum { max_nesting
= 1024 }; /* see qobject/json-streamer.c */
1455 char buf
[2 * (max_nesting
+ 1) + 1];
1458 obj
= qobject_from_json(make_nest(buf
, max_nesting
), &error_abort
);
1459 g_assert(obj
!= NULL
);
1460 qobject_decref(obj
);
1462 obj
= qobject_from_json(make_nest(buf
, max_nesting
+ 1), &err
);
1463 error_free_or_abort(&err
);
1464 g_assert(obj
== NULL
);
1467 int main(int argc
, char **argv
)
1469 g_test_init(&argc
, &argv
, NULL
);
1471 g_test_add_func("/literals/string/simple", simple_string
);
1472 g_test_add_func("/literals/string/escaped", escaped_string
);
1473 g_test_add_func("/literals/string/utf8", utf8_string
);
1474 g_test_add_func("/literals/string/single_quote", single_quote_string
);
1475 g_test_add_func("/literals/string/vararg", vararg_string
);
1477 g_test_add_func("/literals/number/simple", simple_number
);
1478 g_test_add_func("/literals/number/float", float_number
);
1479 g_test_add_func("/literals/number/vararg", vararg_number
);
1481 g_test_add_func("/literals/keyword", keyword_literal
);
1483 g_test_add_func("/dicts/simple_dict", simple_dict
);
1484 g_test_add_func("/dicts/large_dict", large_dict
);
1485 g_test_add_func("/lists/simple_list", simple_list
);
1487 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1489 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1491 g_test_add_func("/errors/empty_input", empty_input
);
1492 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1493 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1494 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1495 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1496 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1497 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1498 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1499 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1500 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1501 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1502 g_test_add_func("/errors/limits/nesting", limits_nesting
);
1504 return g_test_run();