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
++) {
891 qint
= qobject_to_qint(qobject_from_json(test_cases
[i
].encoded
,
894 g_assert(qint_get_int(qint
) == test_cases
[i
].decoded
);
895 if (test_cases
[i
].skip
== 0) {
898 str
= qobject_to_json(QOBJECT(qint
));
899 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
907 static void float_number(void)
917 { "-32.12313", -32.12313 },
918 { "-32.20e-10", -32.20e-10, .skip
= 1 },
922 for (i
= 0; test_cases
[i
].encoded
; i
++) {
926 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
927 qfloat
= qobject_to_qfloat(obj
);
929 g_assert(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
931 if (test_cases
[i
].skip
== 0) {
934 str
= qobject_to_json(obj
);
935 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
943 static void vararg_number(void)
948 long long value_ll
= 0x2342342343LL
;
949 double valuef
= 2.323423423;
951 qint
= qobject_to_qint(qobject_from_jsonf("%d", value
));
952 g_assert(qint_get_int(qint
) == value
);
955 qint
= qobject_to_qint(qobject_from_jsonf("%lld", value_ll
));
956 g_assert(qint_get_int(qint
) == value_ll
);
959 qfloat
= qobject_to_qfloat(qobject_from_jsonf("%f", valuef
));
960 g_assert(qfloat_get_double(qfloat
) == valuef
);
964 static void keyword_literal(void)
971 obj
= qobject_from_json("true", &error_abort
);
972 qbool
= qobject_to_qbool(obj
);
974 g_assert(qbool_get_bool(qbool
) == true);
976 str
= qobject_to_json(obj
);
977 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
982 obj
= qobject_from_json("false", &error_abort
);
983 qbool
= qobject_to_qbool(obj
);
985 g_assert(qbool_get_bool(qbool
) == false);
987 str
= qobject_to_json(obj
);
988 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
993 qbool
= qobject_to_qbool(qobject_from_jsonf("%i", false));
995 g_assert(qbool_get_bool(qbool
) == false);
998 /* Test that non-zero values other than 1 get collapsed to true */
999 qbool
= qobject_to_qbool(qobject_from_jsonf("%i", 2));
1001 g_assert(qbool_get_bool(qbool
) == true);
1004 obj
= qobject_from_json("null", &error_abort
);
1005 g_assert(obj
!= NULL
);
1006 g_assert(qobject_type(obj
) == QTYPE_QNULL
);
1009 g_assert(null
== obj
);
1011 qobject_decref(obj
);
1012 qobject_decref(null
);
1015 typedef struct LiteralQDictEntry LiteralQDictEntry
;
1016 typedef struct LiteralQObject LiteralQObject
;
1018 struct LiteralQObject
1024 LiteralQDictEntry
*qdict
;
1025 LiteralQObject
*qlist
;
1029 struct LiteralQDictEntry
1032 LiteralQObject value
;
1035 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1036 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1037 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1038 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1040 typedef struct QListCompareHelper
1043 LiteralQObject
*objs
;
1045 } QListCompareHelper
;
1047 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
1049 static void compare_helper(QObject
*obj
, void *opaque
)
1051 QListCompareHelper
*helper
= opaque
;
1053 if (helper
->result
== 0) {
1057 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
1062 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
1065 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
1067 if (!rhs
|| lhs
->type
!= qobject_type(rhs
)) {
1071 switch (lhs
->type
) {
1073 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
1075 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
1079 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
1080 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
1082 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
1090 QListCompareHelper helper
;
1093 helper
.objs
= lhs
->value
.qlist
;
1096 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
1098 return helper
.result
;
1107 static void simple_dict(void)
1111 const char *encoded
;
1112 LiteralQObject decoded
;
1115 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
1116 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1117 { "foo", QLIT_QINT(42) },
1118 { "bar", QLIT_QSTR("hello world") },
1123 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1127 .encoded
= "{\"foo\": 43}",
1128 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
1129 { "foo", QLIT_QINT(43) },
1136 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1140 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1141 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1143 str
= qobject_to_json(obj
);
1144 qobject_decref(obj
);
1146 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1147 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1148 qobject_decref(obj
);
1154 * this generates json of the form:
1155 * a(0,m) = [0, 1, ..., m-1]
1160 * 'key(n-1)': a(n-1,m)
1163 static void gen_test_json(GString
*gstr
, int nest_level_max
,
1169 if (nest_level_max
== 0) {
1170 g_string_append(gstr
, "[");
1171 for (i
= 0; i
< elem_count
; i
++) {
1172 g_string_append_printf(gstr
, "%d", i
);
1173 if (i
< elem_count
- 1) {
1174 g_string_append_printf(gstr
, ", ");
1177 g_string_append(gstr
, "]");
1181 g_string_append(gstr
, "{");
1182 for (i
= 0; i
< nest_level_max
; i
++) {
1183 g_string_append_printf(gstr
, "'key%d': ", i
);
1184 gen_test_json(gstr
, i
, elem_count
);
1185 if (i
< nest_level_max
- 1) {
1186 g_string_append(gstr
, ",");
1189 g_string_append(gstr
, "}");
1192 static void large_dict(void)
1194 GString
*gstr
= g_string_new("");
1197 gen_test_json(gstr
, 10, 100);
1198 obj
= qobject_from_json(gstr
->str
, &error_abort
);
1199 g_assert(obj
!= NULL
);
1201 qobject_decref(obj
);
1202 g_string_free(gstr
, true);
1205 static void simple_list(void)
1209 const char *encoded
;
1210 LiteralQObject decoded
;
1213 .encoded
= "[43,42]",
1214 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1222 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1229 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1235 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1236 QLIT_QDICT(((LiteralQDictEntry
[]){
1245 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1249 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1250 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1252 str
= qobject_to_json(obj
);
1253 qobject_decref(obj
);
1255 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1256 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1257 qobject_decref(obj
);
1262 static void simple_whitespace(void)
1266 const char *encoded
;
1267 LiteralQObject decoded
;
1270 .encoded
= " [ 43 , 42 ]",
1271 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1278 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1279 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1281 QLIT_QDICT(((LiteralQDictEntry
[]){
1282 { "h", QLIT_QSTR("b") },
1284 QLIT_QLIST(((LiteralQObject
[]){
1291 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1292 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
1294 QLIT_QDICT(((LiteralQDictEntry
[]){
1295 { "h", QLIT_QSTR("b") },
1296 { "a", QLIT_QINT(32) },
1298 QLIT_QLIST(((LiteralQObject
[]){
1307 for (i
= 0; test_cases
[i
].encoded
; i
++) {
1311 obj
= qobject_from_json(test_cases
[i
].encoded
, &error_abort
);
1312 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1314 str
= qobject_to_json(obj
);
1315 qobject_decref(obj
);
1317 obj
= qobject_from_json(qstring_get_str(str
), &error_abort
);
1318 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
1320 qobject_decref(obj
);
1325 static void simple_varargs(void)
1327 QObject
*embedded_obj
;
1329 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
1332 QLIT_QLIST(((LiteralQObject
[]){
1338 embedded_obj
= qobject_from_json("[32, 42]", &error_abort
);
1339 g_assert(embedded_obj
!= NULL
);
1341 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
1342 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
1344 qobject_decref(obj
);
1347 static void empty_input(void)
1349 const char *empty
= "";
1350 QObject
*obj
= qobject_from_json(empty
, &error_abort
);
1351 g_assert(obj
== NULL
);
1354 static void unterminated_string(void)
1357 QObject
*obj
= qobject_from_json("\"abc", &err
);
1358 g_assert(!err
); /* BUG */
1359 g_assert(obj
== NULL
);
1362 static void unterminated_sq_string(void)
1365 QObject
*obj
= qobject_from_json("'abc", &err
);
1366 g_assert(!err
); /* BUG */
1367 g_assert(obj
== NULL
);
1370 static void unterminated_escape(void)
1373 QObject
*obj
= qobject_from_json("\"abc\\\"", &err
);
1374 g_assert(!err
); /* BUG */
1375 g_assert(obj
== NULL
);
1378 static void unterminated_array(void)
1381 QObject
*obj
= qobject_from_json("[32", &err
);
1382 g_assert(!err
); /* BUG */
1383 g_assert(obj
== NULL
);
1386 static void unterminated_array_comma(void)
1389 QObject
*obj
= qobject_from_json("[32,", &err
);
1390 g_assert(!err
); /* BUG */
1391 g_assert(obj
== NULL
);
1394 static void invalid_array_comma(void)
1397 QObject
*obj
= qobject_from_json("[32,}", &err
);
1398 error_free_or_abort(&err
);
1399 g_assert(obj
== NULL
);
1402 static void unterminated_dict(void)
1405 QObject
*obj
= qobject_from_json("{'abc':32", &err
);
1406 g_assert(!err
); /* BUG */
1407 g_assert(obj
== NULL
);
1410 static void unterminated_dict_comma(void)
1413 QObject
*obj
= qobject_from_json("{'abc':32,", &err
);
1414 g_assert(!err
); /* BUG */
1415 g_assert(obj
== NULL
);
1418 static void invalid_dict_comma(void)
1421 QObject
*obj
= qobject_from_json("{'abc':32,}", &err
);
1422 error_free_or_abort(&err
);
1423 g_assert(obj
== NULL
);
1426 static void unterminated_literal(void)
1429 QObject
*obj
= qobject_from_json("nul", &err
);
1430 error_free_or_abort(&err
);
1431 g_assert(obj
== NULL
);
1434 static char *make_nest(char *buf
, size_t cnt
)
1436 memset(buf
, '[', cnt
- 1);
1439 memset(buf
+ cnt
+ 1, ']', cnt
- 1);
1444 static void limits_nesting(void)
1447 enum { max_nesting
= 1024 }; /* see qobject/json-streamer.c */
1448 char buf
[2 * (max_nesting
+ 1) + 1];
1451 obj
= qobject_from_json(make_nest(buf
, max_nesting
), &error_abort
);
1452 g_assert(obj
!= NULL
);
1453 qobject_decref(obj
);
1455 obj
= qobject_from_json(make_nest(buf
, max_nesting
+ 1), &err
);
1456 error_free_or_abort(&err
);
1457 g_assert(obj
== NULL
);
1460 int main(int argc
, char **argv
)
1462 g_test_init(&argc
, &argv
, NULL
);
1464 g_test_add_func("/literals/string/simple", simple_string
);
1465 g_test_add_func("/literals/string/escaped", escaped_string
);
1466 g_test_add_func("/literals/string/utf8", utf8_string
);
1467 g_test_add_func("/literals/string/single_quote", single_quote_string
);
1468 g_test_add_func("/literals/string/vararg", vararg_string
);
1470 g_test_add_func("/literals/number/simple", simple_number
);
1471 g_test_add_func("/literals/number/float", float_number
);
1472 g_test_add_func("/literals/number/vararg", vararg_number
);
1474 g_test_add_func("/literals/keyword", keyword_literal
);
1476 g_test_add_func("/dicts/simple_dict", simple_dict
);
1477 g_test_add_func("/dicts/large_dict", large_dict
);
1478 g_test_add_func("/lists/simple_list", simple_list
);
1480 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
1482 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
1484 g_test_add_func("/errors/empty_input", empty_input
);
1485 g_test_add_func("/errors/unterminated/string", unterminated_string
);
1486 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
1487 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
1488 g_test_add_func("/errors/unterminated/array", unterminated_array
);
1489 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
1490 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
1491 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
1492 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
1493 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
1494 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);
1495 g_test_add_func("/errors/limits/nesting", limits_nesting
);
1497 return g_test_run();