s390x: remove double compat statement
[qemu.git] / tests / check-qjson.c
blob0b21a22e109933f77808d35b03f1f925c3d1a6ea
1 /*
2 * Copyright IBM, Corp. 2009
3 * Copyright (c) 2013, 2015 Red Hat Inc.
5 * Authors:
6 * Anthony Liguori <aliguori@us.ibm.com>
7 * Markus Armbruster <armbru@redhat.com>
9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 * See the COPYING.LIB file in the top-level directory.
13 #include "qemu/osdep.h"
15 #include "qapi/qmp/types.h"
16 #include "qapi/qmp/qjson.h"
17 #include "qemu-common.h"
19 static void escaped_string(void)
21 int i;
22 struct {
23 const char *encoded;
24 const char *decoded;
25 int skip;
26 } test_cases[] = {
27 { "\"\\b\"", "\b" },
28 { "\"\\f\"", "\f" },
29 { "\"\\n\"", "\n" },
30 { "\"\\r\"", "\r" },
31 { "\"\\t\"", "\t" },
32 { "\"/\"", "/" },
33 { "\"\\/\"", "/", .skip = 1 },
34 { "\"\\\\\"", "\\" },
35 { "\"\\\"\"", "\"" },
36 { "\"hello world \\\"embedded string\\\"\"",
37 "hello world \"embedded string\"" },
38 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
39 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
40 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
41 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
42 { "'\\b'", "\b", .skip = 1 },
43 { "'\\f'", "\f", .skip = 1 },
44 { "'\\n'", "\n", .skip = 1 },
45 { "'\\r'", "\r", .skip = 1 },
46 { "'\\t'", "\t", .skip = 1 },
47 { "'\\/'", "/", .skip = 1 },
48 { "'\\\\'", "\\", .skip = 1 },
52 for (i = 0; test_cases[i].encoded; i++) {
53 QObject *obj;
54 QString *str;
56 obj = qobject_from_json(test_cases[i].encoded);
58 g_assert(obj != NULL);
59 g_assert(qobject_type(obj) == QTYPE_QSTRING);
61 str = qobject_to_qstring(obj);
62 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
64 if (test_cases[i].skip == 0) {
65 str = qobject_to_json(obj);
66 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
67 qobject_decref(obj);
70 QDECREF(str);
74 static void simple_string(void)
76 int i;
77 struct {
78 const char *encoded;
79 const char *decoded;
80 } test_cases[] = {
81 { "\"hello world\"", "hello world" },
82 { "\"the quick brown fox jumped over the fence\"",
83 "the quick brown fox jumped over the fence" },
87 for (i = 0; test_cases[i].encoded; i++) {
88 QObject *obj;
89 QString *str;
91 obj = qobject_from_json(test_cases[i].encoded);
93 g_assert(obj != NULL);
94 g_assert(qobject_type(obj) == QTYPE_QSTRING);
96 str = qobject_to_qstring(obj);
97 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
99 str = qobject_to_json(obj);
100 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
102 qobject_decref(obj);
104 QDECREF(str);
108 static void single_quote_string(void)
110 int i;
111 struct {
112 const char *encoded;
113 const char *decoded;
114 } test_cases[] = {
115 { "'hello world'", "hello world" },
116 { "'the quick brown fox \\' jumped over the fence'",
117 "the quick brown fox ' jumped over the fence" },
121 for (i = 0; test_cases[i].encoded; i++) {
122 QObject *obj;
123 QString *str;
125 obj = qobject_from_json(test_cases[i].encoded);
127 g_assert(obj != NULL);
128 g_assert(qobject_type(obj) == QTYPE_QSTRING);
130 str = qobject_to_qstring(obj);
131 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
133 QDECREF(str);
137 static void utf8_string(void)
140 * FIXME Current behavior for invalid UTF-8 sequences is
141 * incorrect. This test expects current, incorrect results.
142 * They're all marked "bug:" below, and are to be replaced by
143 * correct ones as the bugs get fixed.
145 * The JSON parser rejects some invalid sequences, but accepts
146 * others without correcting the problem.
148 * We should either reject all invalid sequences, or minimize
149 * overlong sequences and replace all other invalid sequences by a
150 * suitable replacement character. A common choice for
151 * replacement is U+FFFD.
153 * Problem: we can't easily deal with embedded U+0000. Parsing
154 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
155 * which gets misinterpreted as NUL-terminated "this ". We should
156 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
157 * UTF-8").
159 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
160 * capability and stress test at
161 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
163 static const struct {
164 const char *json_in;
165 const char *utf8_out;
166 const char *json_out; /* defaults to @json_in */
167 const char *utf8_in; /* defaults to @utf8_out */
168 } test_cases[] = {
170 * Bug markers used here:
171 * - bug: not corrected
172 * JSON parser fails to correct invalid sequence(s)
173 * - bug: rejected
174 * JSON parser rejects invalid sequence(s)
175 * We may choose to define this as feature
176 * - bug: want "..."
177 * JSON parser produces incorrect result, this is the
178 * correct one, assuming replacement character U+FFFF
179 * We may choose to reject instead of replace
182 /* 1 Some correct UTF-8 text */
184 /* a bit of German */
185 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
186 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
187 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
188 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
189 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
190 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
193 /* a bit of Greek */
194 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
195 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
196 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
198 /* 2 Boundary condition test cases */
199 /* 2.1 First possible sequence of a certain length */
200 /* 2.1.1 1 byte U+0000 */
202 "\"\\u0000\"",
203 "", /* bug: want overlong "\xC0\x80" */
204 "\"\\u0000\"",
205 "\xC0\x80",
207 /* 2.1.2 2 bytes U+0080 */
209 "\"\xC2\x80\"",
210 "\xC2\x80",
211 "\"\\u0080\"",
213 /* 2.1.3 3 bytes U+0800 */
215 "\"\xE0\xA0\x80\"",
216 "\xE0\xA0\x80",
217 "\"\\u0800\"",
219 /* 2.1.4 4 bytes U+10000 */
221 "\"\xF0\x90\x80\x80\"",
222 "\xF0\x90\x80\x80",
223 "\"\\uD800\\uDC00\"",
225 /* 2.1.5 5 bytes U+200000 */
227 "\"\xF8\x88\x80\x80\x80\"",
228 NULL, /* bug: rejected */
229 "\"\\uFFFD\"",
230 "\xF8\x88\x80\x80\x80",
232 /* 2.1.6 6 bytes U+4000000 */
234 "\"\xFC\x84\x80\x80\x80\x80\"",
235 NULL, /* bug: rejected */
236 "\"\\uFFFD\"",
237 "\xFC\x84\x80\x80\x80\x80",
239 /* 2.2 Last possible sequence of a certain length */
240 /* 2.2.1 1 byte U+007F */
242 "\"\x7F\"",
243 "\x7F",
244 "\"\\u007F\"",
246 /* 2.2.2 2 bytes U+07FF */
248 "\"\xDF\xBF\"",
249 "\xDF\xBF",
250 "\"\\u07FF\"",
253 * 2.2.3 3 bytes U+FFFC
254 * The last possible sequence is actually U+FFFF. But that's
255 * a noncharacter, and already covered by its own test case
256 * under 5.3. Same for U+FFFE. U+FFFD is the last character
257 * in the BMP, and covered under 2.3. Because of U+FFFD's
258 * special role as replacement character, it's worth testing
259 * U+FFFC here.
262 "\"\xEF\xBF\xBC\"",
263 "\xEF\xBF\xBC",
264 "\"\\uFFFC\"",
266 /* 2.2.4 4 bytes U+1FFFFF */
268 "\"\xF7\xBF\xBF\xBF\"",
269 NULL, /* bug: rejected */
270 "\"\\uFFFD\"",
271 "\xF7\xBF\xBF\xBF",
273 /* 2.2.5 5 bytes U+3FFFFFF */
275 "\"\xFB\xBF\xBF\xBF\xBF\"",
276 NULL, /* bug: rejected */
277 "\"\\uFFFD\"",
278 "\xFB\xBF\xBF\xBF\xBF",
280 /* 2.2.6 6 bytes U+7FFFFFFF */
282 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
283 NULL, /* bug: rejected */
284 "\"\\uFFFD\"",
285 "\xFD\xBF\xBF\xBF\xBF\xBF",
287 /* 2.3 Other boundary conditions */
289 /* last one before surrogate range: U+D7FF */
290 "\"\xED\x9F\xBF\"",
291 "\xED\x9F\xBF",
292 "\"\\uD7FF\"",
295 /* first one after surrogate range: U+E000 */
296 "\"\xEE\x80\x80\"",
297 "\xEE\x80\x80",
298 "\"\\uE000\"",
301 /* last one in BMP: U+FFFD */
302 "\"\xEF\xBF\xBD\"",
303 "\xEF\xBF\xBD",
304 "\"\\uFFFD\"",
307 /* last one in last plane: U+10FFFD */
308 "\"\xF4\x8F\xBF\xBD\"",
309 "\xF4\x8F\xBF\xBD",
310 "\"\\uDBFF\\uDFFD\""
313 /* first one beyond Unicode range: U+110000 */
314 "\"\xF4\x90\x80\x80\"",
315 "\xF4\x90\x80\x80",
316 "\"\\uFFFD\"",
318 /* 3 Malformed sequences */
319 /* 3.1 Unexpected continuation bytes */
320 /* 3.1.1 First continuation byte */
322 "\"\x80\"",
323 "\x80", /* bug: not corrected */
324 "\"\\uFFFD\"",
326 /* 3.1.2 Last continuation byte */
328 "\"\xBF\"",
329 "\xBF", /* bug: not corrected */
330 "\"\\uFFFD\"",
332 /* 3.1.3 2 continuation bytes */
334 "\"\x80\xBF\"",
335 "\x80\xBF", /* bug: not corrected */
336 "\"\\uFFFD\\uFFFD\"",
338 /* 3.1.4 3 continuation bytes */
340 "\"\x80\xBF\x80\"",
341 "\x80\xBF\x80", /* bug: not corrected */
342 "\"\\uFFFD\\uFFFD\\uFFFD\"",
344 /* 3.1.5 4 continuation bytes */
346 "\"\x80\xBF\x80\xBF\"",
347 "\x80\xBF\x80\xBF", /* bug: not corrected */
348 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
350 /* 3.1.6 5 continuation bytes */
352 "\"\x80\xBF\x80\xBF\x80\"",
353 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
354 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
356 /* 3.1.7 6 continuation bytes */
358 "\"\x80\xBF\x80\xBF\x80\xBF\"",
359 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
360 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
362 /* 3.1.8 7 continuation bytes */
364 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
365 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
366 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
368 /* 3.1.9 Sequence of all 64 possible continuation bytes */
370 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
371 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
372 "\x90\x91\x92\x93\x94\x95\x96\x97"
373 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
374 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
375 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
376 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
377 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
378 /* bug: not corrected */
379 "\x80\x81\x82\x83\x84\x85\x86\x87"
380 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
381 "\x90\x91\x92\x93\x94\x95\x96\x97"
382 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
383 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
384 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
385 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
386 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
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"
394 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
396 /* 3.2 Lonely start characters */
397 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
399 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
400 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
401 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
402 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
403 NULL, /* bug: rejected */
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 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
408 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
409 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
410 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
411 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
413 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
415 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
416 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
417 /* bug: not corrected */
418 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
419 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
420 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
421 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
423 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
425 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
426 NULL, /* bug: rejected */
427 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
428 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
430 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
432 "\"\xF8 \xF9 \xFA \xFB \"",
433 NULL, /* bug: rejected */
434 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
435 "\xF8 \xF9 \xFA \xFB ",
437 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
439 "\"\xFC \xFD \"",
440 NULL, /* bug: rejected */
441 "\"\\uFFFD \\uFFFD \"",
442 "\xFC \xFD ",
444 /* 3.3 Sequences with last continuation byte missing */
445 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
447 "\"\xC0\"",
448 NULL, /* bug: rejected */
449 "\"\\uFFFD\"",
450 "\xC0",
452 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
454 "\"\xE0\x80\"",
455 "\xE0\x80", /* bug: not corrected */
456 "\"\\uFFFD\"",
458 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
460 "\"\xF0\x80\x80\"",
461 "\xF0\x80\x80", /* bug: not corrected */
462 "\"\\uFFFD\"",
464 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
466 "\"\xF8\x80\x80\x80\"",
467 NULL, /* bug: rejected */
468 "\"\\uFFFD\"",
469 "\xF8\x80\x80\x80",
471 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
473 "\"\xFC\x80\x80\x80\x80\"",
474 NULL, /* bug: rejected */
475 "\"\\uFFFD\"",
476 "\xFC\x80\x80\x80\x80",
478 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
480 "\"\xDF\"",
481 "\xDF", /* bug: not corrected */
482 "\"\\uFFFD\"",
484 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
486 "\"\xEF\xBF\"",
487 "\xEF\xBF", /* bug: not corrected */
488 "\"\\uFFFD\"",
490 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
492 "\"\xF7\xBF\xBF\"",
493 NULL, /* bug: rejected */
494 "\"\\uFFFD\"",
495 "\xF7\xBF\xBF",
497 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
499 "\"\xFB\xBF\xBF\xBF\"",
500 NULL, /* bug: rejected */
501 "\"\\uFFFD\"",
502 "\xFB\xBF\xBF\xBF",
504 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
506 "\"\xFD\xBF\xBF\xBF\xBF\"",
507 NULL, /* bug: rejected */
508 "\"\\uFFFD\"",
509 "\xFD\xBF\xBF\xBF\xBF",
511 /* 3.4 Concatenation of incomplete sequences */
513 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
514 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
515 NULL, /* bug: rejected */
516 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
517 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
518 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
519 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
521 /* 3.5 Impossible bytes */
523 "\"\xFE\"",
524 NULL, /* bug: rejected */
525 "\"\\uFFFD\"",
526 "\xFE",
529 "\"\xFF\"",
530 NULL, /* bug: rejected */
531 "\"\\uFFFD\"",
532 "\xFF",
535 "\"\xFE\xFE\xFF\xFF\"",
536 NULL, /* bug: rejected */
537 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
538 "\xFE\xFE\xFF\xFF",
540 /* 4 Overlong sequences */
541 /* 4.1 Overlong '/' */
543 "\"\xC0\xAF\"",
544 NULL, /* bug: rejected */
545 "\"\\uFFFD\"",
546 "\xC0\xAF",
549 "\"\xE0\x80\xAF\"",
550 "\xE0\x80\xAF", /* bug: not corrected */
551 "\"\\uFFFD\"",
554 "\"\xF0\x80\x80\xAF\"",
555 "\xF0\x80\x80\xAF", /* bug: not corrected */
556 "\"\\uFFFD\"",
559 "\"\xF8\x80\x80\x80\xAF\"",
560 NULL, /* bug: rejected */
561 "\"\\uFFFD\"",
562 "\xF8\x80\x80\x80\xAF",
565 "\"\xFC\x80\x80\x80\x80\xAF\"",
566 NULL, /* bug: rejected */
567 "\"\\uFFFD\"",
568 "\xFC\x80\x80\x80\x80\xAF",
571 * 4.2 Maximum overlong sequences
572 * Highest Unicode value that is still resulting in an
573 * overlong sequence if represented with the given number of
574 * bytes. This is a boundary test for safe UTF-8 decoders.
577 /* \U+007F */
578 "\"\xC1\xBF\"",
579 NULL, /* bug: rejected */
580 "\"\\uFFFD\"",
581 "\xC1\xBF",
584 /* \U+07FF */
585 "\"\xE0\x9F\xBF\"",
586 "\xE0\x9F\xBF", /* bug: not corrected */
587 "\"\\uFFFD\"",
591 * \U+FFFC
592 * The actual maximum would be U+FFFF, but that's a
593 * noncharacter. Testing U+FFFC seems more useful. See
594 * also 2.2.3
596 "\"\xF0\x8F\xBF\xBC\"",
597 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
598 "\"\\uFFFD\"",
601 /* \U+1FFFFF */
602 "\"\xF8\x87\xBF\xBF\xBF\"",
603 NULL, /* bug: rejected */
604 "\"\\uFFFD\"",
605 "\xF8\x87\xBF\xBF\xBF",
608 /* \U+3FFFFFF */
609 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
610 NULL, /* bug: rejected */
611 "\"\\uFFFD\"",
612 "\xFC\x83\xBF\xBF\xBF\xBF",
614 /* 4.3 Overlong representation of the NUL character */
616 /* \U+0000 */
617 "\"\xC0\x80\"",
618 NULL, /* bug: rejected */
619 "\"\\u0000\"",
620 "\xC0\x80",
623 /* \U+0000 */
624 "\"\xE0\x80\x80\"",
625 "\xE0\x80\x80", /* bug: not corrected */
626 "\"\\uFFFD\"",
629 /* \U+0000 */
630 "\"\xF0\x80\x80\x80\"",
631 "\xF0\x80\x80\x80", /* bug: not corrected */
632 "\"\\uFFFD\"",
635 /* \U+0000 */
636 "\"\xF8\x80\x80\x80\x80\"",
637 NULL, /* bug: rejected */
638 "\"\\uFFFD\"",
639 "\xF8\x80\x80\x80\x80",
642 /* \U+0000 */
643 "\"\xFC\x80\x80\x80\x80\x80\"",
644 NULL, /* bug: rejected */
645 "\"\\uFFFD\"",
646 "\xFC\x80\x80\x80\x80\x80",
648 /* 5 Illegal code positions */
649 /* 5.1 Single UTF-16 surrogates */
651 /* \U+D800 */
652 "\"\xED\xA0\x80\"",
653 "\xED\xA0\x80", /* bug: not corrected */
654 "\"\\uFFFD\"",
657 /* \U+DB7F */
658 "\"\xED\xAD\xBF\"",
659 "\xED\xAD\xBF", /* bug: not corrected */
660 "\"\\uFFFD\"",
663 /* \U+DB80 */
664 "\"\xED\xAE\x80\"",
665 "\xED\xAE\x80", /* bug: not corrected */
666 "\"\\uFFFD\"",
669 /* \U+DBFF */
670 "\"\xED\xAF\xBF\"",
671 "\xED\xAF\xBF", /* bug: not corrected */
672 "\"\\uFFFD\"",
675 /* \U+DC00 */
676 "\"\xED\xB0\x80\"",
677 "\xED\xB0\x80", /* bug: not corrected */
678 "\"\\uFFFD\"",
681 /* \U+DF80 */
682 "\"\xED\xBE\x80\"",
683 "\xED\xBE\x80", /* bug: not corrected */
684 "\"\\uFFFD\"",
687 /* \U+DFFF */
688 "\"\xED\xBF\xBF\"",
689 "\xED\xBF\xBF", /* bug: not corrected */
690 "\"\\uFFFD\"",
692 /* 5.2 Paired UTF-16 surrogates */
694 /* \U+D800\U+DC00 */
695 "\"\xED\xA0\x80\xED\xB0\x80\"",
696 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
697 "\"\\uFFFD\\uFFFD\"",
700 /* \U+D800\U+DFFF */
701 "\"\xED\xA0\x80\xED\xBF\xBF\"",
702 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
703 "\"\\uFFFD\\uFFFD\"",
706 /* \U+DB7F\U+DC00 */
707 "\"\xED\xAD\xBF\xED\xB0\x80\"",
708 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
709 "\"\\uFFFD\\uFFFD\"",
712 /* \U+DB7F\U+DFFF */
713 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
714 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
715 "\"\\uFFFD\\uFFFD\"",
718 /* \U+DB80\U+DC00 */
719 "\"\xED\xAE\x80\xED\xB0\x80\"",
720 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
721 "\"\\uFFFD\\uFFFD\"",
724 /* \U+DB80\U+DFFF */
725 "\"\xED\xAE\x80\xED\xBF\xBF\"",
726 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
727 "\"\\uFFFD\\uFFFD\"",
730 /* \U+DBFF\U+DC00 */
731 "\"\xED\xAF\xBF\xED\xB0\x80\"",
732 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
733 "\"\\uFFFD\\uFFFD\"",
736 /* \U+DBFF\U+DFFF */
737 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
738 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
739 "\"\\uFFFD\\uFFFD\"",
741 /* 5.3 Other illegal code positions */
742 /* BMP noncharacters */
744 /* \U+FFFE */
745 "\"\xEF\xBF\xBE\"",
746 "\xEF\xBF\xBE", /* bug: not corrected */
747 "\"\\uFFFD\"",
750 /* \U+FFFF */
751 "\"\xEF\xBF\xBF\"",
752 "\xEF\xBF\xBF", /* bug: not corrected */
753 "\"\\uFFFD\"",
756 /* U+FDD0 */
757 "\"\xEF\xB7\x90\"",
758 "\xEF\xB7\x90", /* bug: not corrected */
759 "\"\\uFFFD\"",
762 /* U+FDEF */
763 "\"\xEF\xB7\xAF\"",
764 "\xEF\xB7\xAF", /* bug: not corrected */
765 "\"\\uFFFD\"",
767 /* Plane 1 .. 16 noncharacters */
769 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
770 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
771 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
772 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
773 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
774 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
775 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
776 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
777 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
778 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
779 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
780 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
781 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
782 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
783 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
784 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
785 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
786 /* bug: not corrected */
787 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
788 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
789 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
790 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
791 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
792 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
793 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
794 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
795 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
796 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
797 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
798 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
799 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
800 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
801 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
802 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
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"
806 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
810 int i;
811 QObject *obj;
812 QString *str;
813 const char *json_in, *utf8_out, *utf8_in, *json_out;
815 for (i = 0; test_cases[i].json_in; i++) {
816 json_in = test_cases[i].json_in;
817 utf8_out = test_cases[i].utf8_out;
818 utf8_in = test_cases[i].utf8_in ?: test_cases[i].utf8_out;
819 json_out = test_cases[i].json_out ?: test_cases[i].json_in;
821 obj = qobject_from_json(json_in);
822 if (utf8_out) {
823 g_assert(obj);
824 g_assert(qobject_type(obj) == QTYPE_QSTRING);
825 str = qobject_to_qstring(obj);
826 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
827 } else {
828 g_assert(!obj);
830 qobject_decref(obj);
832 obj = QOBJECT(qstring_from_str(utf8_in));
833 str = qobject_to_json(obj);
834 if (json_out) {
835 g_assert(str);
836 g_assert_cmpstr(qstring_get_str(str), ==, json_out);
837 } else {
838 g_assert(!str);
840 QDECREF(str);
841 qobject_decref(obj);
844 * Disabled, because qobject_from_json() is buggy, and I can't
845 * be bothered to add the expected incorrect results.
846 * FIXME Enable once these bugs have been fixed.
848 if (0 && json_out != json_in) {
849 obj = qobject_from_json(json_out);
850 g_assert(obj);
851 g_assert(qobject_type(obj) == QTYPE_QSTRING);
852 str = qobject_to_qstring(obj);
853 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
858 static void vararg_string(void)
860 int i;
861 struct {
862 const char *decoded;
863 } test_cases[] = {
864 { "hello world" },
865 { "the quick brown fox jumped over the fence" },
869 for (i = 0; test_cases[i].decoded; i++) {
870 QObject *obj;
871 QString *str;
873 obj = qobject_from_jsonf("%s", test_cases[i].decoded);
875 g_assert(obj != NULL);
876 g_assert(qobject_type(obj) == QTYPE_QSTRING);
878 str = qobject_to_qstring(obj);
879 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
881 QDECREF(str);
885 static void simple_number(void)
887 int i;
888 struct {
889 const char *encoded;
890 int64_t decoded;
891 int skip;
892 } test_cases[] = {
893 { "0", 0 },
894 { "1234", 1234 },
895 { "1", 1 },
896 { "-32", -32 },
897 { "-0", 0, .skip = 1 },
898 { },
901 for (i = 0; test_cases[i].encoded; i++) {
902 QObject *obj;
903 QInt *qint;
905 obj = qobject_from_json(test_cases[i].encoded);
906 g_assert(obj != NULL);
907 g_assert(qobject_type(obj) == QTYPE_QINT);
909 qint = qobject_to_qint(obj);
910 g_assert(qint_get_int(qint) == test_cases[i].decoded);
911 if (test_cases[i].skip == 0) {
912 QString *str;
914 str = qobject_to_json(obj);
915 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
916 QDECREF(str);
919 QDECREF(qint);
923 static void float_number(void)
925 int i;
926 struct {
927 const char *encoded;
928 double decoded;
929 int skip;
930 } test_cases[] = {
931 { "32.43", 32.43 },
932 { "0.222", 0.222 },
933 { "-32.12313", -32.12313 },
934 { "-32.20e-10", -32.20e-10, .skip = 1 },
935 { },
938 for (i = 0; test_cases[i].encoded; i++) {
939 QObject *obj;
940 QFloat *qfloat;
942 obj = qobject_from_json(test_cases[i].encoded);
943 g_assert(obj != NULL);
944 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
946 qfloat = qobject_to_qfloat(obj);
947 g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
949 if (test_cases[i].skip == 0) {
950 QString *str;
952 str = qobject_to_json(obj);
953 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
954 QDECREF(str);
957 QDECREF(qfloat);
961 static void vararg_number(void)
963 QObject *obj;
964 QInt *qint;
965 QFloat *qfloat;
966 int value = 0x2342;
967 long long value_ll = 0x2342342343LL;
968 double valuef = 2.323423423;
970 obj = qobject_from_jsonf("%d", value);
971 g_assert(obj != NULL);
972 g_assert(qobject_type(obj) == QTYPE_QINT);
974 qint = qobject_to_qint(obj);
975 g_assert(qint_get_int(qint) == value);
977 QDECREF(qint);
979 obj = qobject_from_jsonf("%lld", value_ll);
980 g_assert(obj != NULL);
981 g_assert(qobject_type(obj) == QTYPE_QINT);
983 qint = qobject_to_qint(obj);
984 g_assert(qint_get_int(qint) == value_ll);
986 QDECREF(qint);
988 obj = qobject_from_jsonf("%f", valuef);
989 g_assert(obj != NULL);
990 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
992 qfloat = qobject_to_qfloat(obj);
993 g_assert(qfloat_get_double(qfloat) == valuef);
995 QDECREF(qfloat);
998 static void keyword_literal(void)
1000 QObject *obj;
1001 QBool *qbool;
1002 QObject *null;
1003 QString *str;
1005 obj = qobject_from_json("true");
1006 g_assert(obj != NULL);
1007 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1009 qbool = qobject_to_qbool(obj);
1010 g_assert(qbool_get_bool(qbool) == true);
1012 str = qobject_to_json(obj);
1013 g_assert(strcmp(qstring_get_str(str), "true") == 0);
1014 QDECREF(str);
1016 QDECREF(qbool);
1018 obj = qobject_from_json("false");
1019 g_assert(obj != NULL);
1020 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1022 qbool = qobject_to_qbool(obj);
1023 g_assert(qbool_get_bool(qbool) == false);
1025 str = qobject_to_json(obj);
1026 g_assert(strcmp(qstring_get_str(str), "false") == 0);
1027 QDECREF(str);
1029 QDECREF(qbool);
1031 obj = qobject_from_jsonf("%i", false);
1032 g_assert(obj != NULL);
1033 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1035 qbool = qobject_to_qbool(obj);
1036 g_assert(qbool_get_bool(qbool) == false);
1038 QDECREF(qbool);
1040 /* Test that non-zero values other than 1 get collapsed to true */
1041 obj = qobject_from_jsonf("%i", 2);
1042 g_assert(obj != NULL);
1043 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1045 qbool = qobject_to_qbool(obj);
1046 g_assert(qbool_get_bool(qbool) == true);
1048 QDECREF(qbool);
1050 obj = qobject_from_json("null");
1051 g_assert(obj != NULL);
1052 g_assert(qobject_type(obj) == QTYPE_QNULL);
1054 null = qnull();
1055 g_assert(null == obj);
1057 qobject_decref(obj);
1058 qobject_decref(null);
1061 typedef struct LiteralQDictEntry LiteralQDictEntry;
1062 typedef struct LiteralQObject LiteralQObject;
1064 struct LiteralQObject
1066 int type;
1067 union {
1068 int64_t qint;
1069 const char *qstr;
1070 LiteralQDictEntry *qdict;
1071 LiteralQObject *qlist;
1072 } value;
1075 struct LiteralQDictEntry
1077 const char *key;
1078 LiteralQObject value;
1081 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1082 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1083 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1084 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1086 typedef struct QListCompareHelper
1088 int index;
1089 LiteralQObject *objs;
1090 int result;
1091 } QListCompareHelper;
1093 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1095 static void compare_helper(QObject *obj, void *opaque)
1097 QListCompareHelper *helper = opaque;
1099 if (helper->result == 0) {
1100 return;
1103 if (helper->objs[helper->index].type == QTYPE_NONE) {
1104 helper->result = 0;
1105 return;
1108 helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1111 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1113 if (lhs->type != qobject_type(rhs)) {
1114 return 0;
1117 switch (lhs->type) {
1118 case QTYPE_QINT:
1119 return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
1120 case QTYPE_QSTRING:
1121 return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1122 case QTYPE_QDICT: {
1123 int i;
1125 for (i = 0; lhs->value.qdict[i].key; i++) {
1126 QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1128 if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1129 return 0;
1133 return 1;
1135 case QTYPE_QLIST: {
1136 QListCompareHelper helper;
1138 helper.index = 0;
1139 helper.objs = lhs->value.qlist;
1140 helper.result = 1;
1142 qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1144 return helper.result;
1146 default:
1147 break;
1150 return 0;
1153 static void simple_dict(void)
1155 int i;
1156 struct {
1157 const char *encoded;
1158 LiteralQObject decoded;
1159 } test_cases[] = {
1161 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1162 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1163 { "foo", QLIT_QINT(42) },
1164 { "bar", QLIT_QSTR("hello world") },
1166 })),
1167 }, {
1168 .encoded = "{}",
1169 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1171 })),
1172 }, {
1173 .encoded = "{\"foo\": 43}",
1174 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1175 { "foo", QLIT_QINT(43) },
1177 })),
1182 for (i = 0; test_cases[i].encoded; i++) {
1183 QObject *obj;
1184 QString *str;
1186 obj = qobject_from_json(test_cases[i].encoded);
1187 g_assert(obj != NULL);
1188 g_assert(qobject_type(obj) == QTYPE_QDICT);
1190 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1192 str = qobject_to_json(obj);
1193 qobject_decref(obj);
1195 obj = qobject_from_json(qstring_get_str(str));
1196 g_assert(obj != NULL);
1197 g_assert(qobject_type(obj) == QTYPE_QDICT);
1199 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1200 qobject_decref(obj);
1201 QDECREF(str);
1206 * this generates json of the form:
1207 * a(0,m) = [0, 1, ..., m-1]
1208 * a(n,m) = {
1209 * 'key0': a(0,m),
1210 * 'key1': a(1,m),
1211 * ...
1212 * 'key(n-1)': a(n-1,m)
1215 static void gen_test_json(GString *gstr, int nest_level_max,
1216 int elem_count)
1218 int i;
1220 g_assert(gstr);
1221 if (nest_level_max == 0) {
1222 g_string_append(gstr, "[");
1223 for (i = 0; i < elem_count; i++) {
1224 g_string_append_printf(gstr, "%d", i);
1225 if (i < elem_count - 1) {
1226 g_string_append_printf(gstr, ", ");
1229 g_string_append(gstr, "]");
1230 return;
1233 g_string_append(gstr, "{");
1234 for (i = 0; i < nest_level_max; i++) {
1235 g_string_append_printf(gstr, "'key%d': ", i);
1236 gen_test_json(gstr, i, elem_count);
1237 if (i < nest_level_max - 1) {
1238 g_string_append(gstr, ",");
1241 g_string_append(gstr, "}");
1244 static void large_dict(void)
1246 GString *gstr = g_string_new("");
1247 QObject *obj;
1249 gen_test_json(gstr, 10, 100);
1250 obj = qobject_from_json(gstr->str);
1251 g_assert(obj != NULL);
1253 qobject_decref(obj);
1254 g_string_free(gstr, true);
1257 static void simple_list(void)
1259 int i;
1260 struct {
1261 const char *encoded;
1262 LiteralQObject decoded;
1263 } test_cases[] = {
1265 .encoded = "[43,42]",
1266 .decoded = QLIT_QLIST(((LiteralQObject[]){
1267 QLIT_QINT(43),
1268 QLIT_QINT(42),
1270 })),
1273 .encoded = "[43]",
1274 .decoded = QLIT_QLIST(((LiteralQObject[]){
1275 QLIT_QINT(43),
1277 })),
1280 .encoded = "[]",
1281 .decoded = QLIT_QLIST(((LiteralQObject[]){
1283 })),
1286 .encoded = "[{}]",
1287 .decoded = QLIT_QLIST(((LiteralQObject[]){
1288 QLIT_QDICT(((LiteralQDictEntry[]){
1290 })),
1292 })),
1297 for (i = 0; test_cases[i].encoded; i++) {
1298 QObject *obj;
1299 QString *str;
1301 obj = qobject_from_json(test_cases[i].encoded);
1302 g_assert(obj != NULL);
1303 g_assert(qobject_type(obj) == QTYPE_QLIST);
1305 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1307 str = qobject_to_json(obj);
1308 qobject_decref(obj);
1310 obj = qobject_from_json(qstring_get_str(str));
1311 g_assert(obj != NULL);
1312 g_assert(qobject_type(obj) == QTYPE_QLIST);
1314 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1315 qobject_decref(obj);
1316 QDECREF(str);
1320 static void simple_whitespace(void)
1322 int i;
1323 struct {
1324 const char *encoded;
1325 LiteralQObject decoded;
1326 } test_cases[] = {
1328 .encoded = " [ 43 , 42 ]",
1329 .decoded = QLIT_QLIST(((LiteralQObject[]){
1330 QLIT_QINT(43),
1331 QLIT_QINT(42),
1333 })),
1336 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1337 .decoded = QLIT_QLIST(((LiteralQObject[]){
1338 QLIT_QINT(43),
1339 QLIT_QDICT(((LiteralQDictEntry[]){
1340 { "h", QLIT_QSTR("b") },
1341 { }})),
1342 QLIT_QLIST(((LiteralQObject[]){
1343 { }})),
1344 QLIT_QINT(42),
1346 })),
1349 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1350 .decoded = QLIT_QLIST(((LiteralQObject[]){
1351 QLIT_QINT(43),
1352 QLIT_QDICT(((LiteralQDictEntry[]){
1353 { "h", QLIT_QSTR("b") },
1354 { "a", QLIT_QINT(32) },
1355 { }})),
1356 QLIT_QLIST(((LiteralQObject[]){
1357 { }})),
1358 QLIT_QINT(42),
1360 })),
1365 for (i = 0; test_cases[i].encoded; i++) {
1366 QObject *obj;
1367 QString *str;
1369 obj = qobject_from_json(test_cases[i].encoded);
1370 g_assert(obj != NULL);
1371 g_assert(qobject_type(obj) == QTYPE_QLIST);
1373 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1375 str = qobject_to_json(obj);
1376 qobject_decref(obj);
1378 obj = qobject_from_json(qstring_get_str(str));
1379 g_assert(obj != NULL);
1380 g_assert(qobject_type(obj) == QTYPE_QLIST);
1382 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1384 qobject_decref(obj);
1385 QDECREF(str);
1389 static void simple_varargs(void)
1391 QObject *embedded_obj;
1392 QObject *obj;
1393 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1394 QLIT_QINT(1),
1395 QLIT_QINT(2),
1396 QLIT_QLIST(((LiteralQObject[]){
1397 QLIT_QINT(32),
1398 QLIT_QINT(42),
1399 {}})),
1400 {}}));
1402 embedded_obj = qobject_from_json("[32, 42]");
1403 g_assert(embedded_obj != NULL);
1405 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1406 g_assert(obj != NULL);
1408 g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1410 qobject_decref(obj);
1413 static void empty_input(void)
1415 const char *empty = "";
1417 QObject *obj = qobject_from_json(empty);
1418 g_assert(obj == NULL);
1421 static void unterminated_string(void)
1423 QObject *obj = qobject_from_json("\"abc");
1424 g_assert(obj == NULL);
1427 static void unterminated_sq_string(void)
1429 QObject *obj = qobject_from_json("'abc");
1430 g_assert(obj == NULL);
1433 static void unterminated_escape(void)
1435 QObject *obj = qobject_from_json("\"abc\\\"");
1436 g_assert(obj == NULL);
1439 static void unterminated_array(void)
1441 QObject *obj = qobject_from_json("[32");
1442 g_assert(obj == NULL);
1445 static void unterminated_array_comma(void)
1447 QObject *obj = qobject_from_json("[32,");
1448 g_assert(obj == NULL);
1451 static void invalid_array_comma(void)
1453 QObject *obj = qobject_from_json("[32,}");
1454 g_assert(obj == NULL);
1457 static void unterminated_dict(void)
1459 QObject *obj = qobject_from_json("{'abc':32");
1460 g_assert(obj == NULL);
1463 static void unterminated_dict_comma(void)
1465 QObject *obj = qobject_from_json("{'abc':32,");
1466 g_assert(obj == NULL);
1469 static void invalid_dict_comma(void)
1471 QObject *obj = qobject_from_json("{'abc':32,}");
1472 g_assert(obj == NULL);
1475 static void unterminated_literal(void)
1477 QObject *obj = qobject_from_json("nul");
1478 g_assert(obj == NULL);
1481 static char *make_nest(char *buf, size_t cnt)
1483 memset(buf, '[', cnt - 1);
1484 buf[cnt - 1] = '{';
1485 buf[cnt] = '}';
1486 memset(buf + cnt + 1, ']', cnt - 1);
1487 buf[2 * cnt] = 0;
1488 return buf;
1491 static void limits_nesting(void)
1493 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1494 char buf[2 * (max_nesting + 1) + 1];
1495 QObject *obj;
1497 obj = qobject_from_json(make_nest(buf, max_nesting));
1498 g_assert(obj != NULL);
1499 qobject_decref(obj);
1501 obj = qobject_from_json(make_nest(buf, max_nesting + 1));
1502 g_assert(obj == NULL);
1505 int main(int argc, char **argv)
1507 g_test_init(&argc, &argv, NULL);
1509 g_test_add_func("/literals/string/simple", simple_string);
1510 g_test_add_func("/literals/string/escaped", escaped_string);
1511 g_test_add_func("/literals/string/utf8", utf8_string);
1512 g_test_add_func("/literals/string/single_quote", single_quote_string);
1513 g_test_add_func("/literals/string/vararg", vararg_string);
1515 g_test_add_func("/literals/number/simple", simple_number);
1516 g_test_add_func("/literals/number/float", float_number);
1517 g_test_add_func("/literals/number/vararg", vararg_number);
1519 g_test_add_func("/literals/keyword", keyword_literal);
1521 g_test_add_func("/dicts/simple_dict", simple_dict);
1522 g_test_add_func("/dicts/large_dict", large_dict);
1523 g_test_add_func("/lists/simple_list", simple_list);
1525 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1527 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1529 g_test_add_func("/errors/empty_input", empty_input);
1530 g_test_add_func("/errors/unterminated/string", unterminated_string);
1531 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1532 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1533 g_test_add_func("/errors/unterminated/array", unterminated_array);
1534 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1535 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1536 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1537 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1538 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1539 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1540 g_test_add_func("/errors/limits/nesting", limits_nesting);
1542 return g_test_run();