qdev: allow both pre- and post-order vists in qdev walking functions
[qemu/armbru.git] / tests / check-qjson.c
blob4e745481094d14b0b11b0adb7407c02bb88cebd9
1 /*
2 * Copyright IBM, Corp. 2009
3 * Copyright (c) 2013 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 <glib.h>
15 #include "qapi/qmp/qstring.h"
16 #include "qapi/qmp/qint.h"
17 #include "qapi/qmp/qdict.h"
18 #include "qapi/qmp/qlist.h"
19 #include "qapi/qmp/qfloat.h"
20 #include "qapi/qmp/qbool.h"
21 #include "qapi/qmp/qjson.h"
23 #include "qemu-common.h"
25 static void escaped_string(void)
27 int i;
28 struct {
29 const char *encoded;
30 const char *decoded;
31 int skip;
32 } test_cases[] = {
33 { "\"\\b\"", "\b" },
34 { "\"\\f\"", "\f" },
35 { "\"\\n\"", "\n" },
36 { "\"\\r\"", "\r" },
37 { "\"\\t\"", "\t" },
38 { "\"/\"", "/" },
39 { "\"\\/\"", "/", .skip = 1 },
40 { "\"\\\\\"", "\\" },
41 { "\"\\\"\"", "\"" },
42 { "\"hello world \\\"embedded string\\\"\"",
43 "hello world \"embedded string\"" },
44 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
45 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
46 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
47 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
51 for (i = 0; test_cases[i].encoded; i++) {
52 QObject *obj;
53 QString *str;
55 obj = qobject_from_json(test_cases[i].encoded);
57 g_assert(obj != NULL);
58 g_assert(qobject_type(obj) == QTYPE_QSTRING);
60 str = qobject_to_qstring(obj);
61 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
63 if (test_cases[i].skip == 0) {
64 str = qobject_to_json(obj);
65 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
66 qobject_decref(obj);
69 QDECREF(str);
73 static void simple_string(void)
75 int i;
76 struct {
77 const char *encoded;
78 const char *decoded;
79 } test_cases[] = {
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++) {
87 QObject *obj;
88 QString *str;
90 obj = qobject_from_json(test_cases[i].encoded);
92 g_assert(obj != NULL);
93 g_assert(qobject_type(obj) == QTYPE_QSTRING);
95 str = qobject_to_qstring(obj);
96 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
98 str = qobject_to_json(obj);
99 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
101 qobject_decref(obj);
103 QDECREF(str);
107 static void single_quote_string(void)
109 int i;
110 struct {
111 const char *encoded;
112 const char *decoded;
113 } test_cases[] = {
114 { "'hello world'", "hello world" },
115 { "'the quick brown fox \\' jumped over the fence'",
116 "the quick brown fox ' jumped over the fence" },
120 for (i = 0; test_cases[i].encoded; i++) {
121 QObject *obj;
122 QString *str;
124 obj = qobject_from_json(test_cases[i].encoded);
126 g_assert(obj != NULL);
127 g_assert(qobject_type(obj) == QTYPE_QSTRING);
129 str = qobject_to_qstring(obj);
130 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
132 QDECREF(str);
136 static void utf8_string(void)
139 * FIXME Current behavior for invalid UTF-8 sequences is
140 * incorrect. This test expects current, incorrect results.
141 * They're all marked "bug:" below, and are to be replaced by
142 * correct ones as the bugs get fixed.
144 * The JSON parser rejects some invalid sequences, but accepts
145 * others without correcting the problem.
147 * We should either reject all invalid sequences, or minimize
148 * overlong sequences and replace all other invalid sequences by a
149 * suitable replacement character. A common choice for
150 * replacement is U+FFFD.
152 * Problem: we can't easily deal with embedded U+0000. Parsing
153 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
154 * which gets misinterpreted as NUL-terminated "this ". We should
155 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
156 * UTF-8").
158 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
159 * capability and stress test at
160 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
162 static const struct {
163 const char *json_in;
164 const char *utf8_out;
165 const char *json_out; /* defaults to @json_in */
166 const char *utf8_in; /* defaults to @utf8_out */
167 } test_cases[] = {
169 * Bug markers used here:
170 * - bug: not corrected
171 * JSON parser fails to correct invalid sequence(s)
172 * - bug: rejected
173 * JSON parser rejects invalid sequence(s)
174 * We may choose to define this as feature
175 * - bug: want "..."
176 * JSON parser produces incorrect result, this is the
177 * correct one, assuming replacement character U+FFFF
178 * We may choose to reject instead of replace
181 /* 1 Some correct UTF-8 text */
183 /* a bit of German */
184 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
185 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
186 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
187 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
188 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
189 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
192 /* a bit of Greek */
193 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
194 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
195 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
197 /* 2 Boundary condition test cases */
198 /* 2.1 First possible sequence of a certain length */
199 /* 2.1.1 1 byte U+0000 */
201 "\"\\u0000\"",
202 "", /* bug: want overlong "\xC0\x80" */
203 "\"\\u0000\"",
204 "\xC0\x80",
206 /* 2.1.2 2 bytes U+0080 */
208 "\"\xC2\x80\"",
209 "\xC2\x80",
210 "\"\\u0080\"",
212 /* 2.1.3 3 bytes U+0800 */
214 "\"\xE0\xA0\x80\"",
215 "\xE0\xA0\x80",
216 "\"\\u0800\"",
218 /* 2.1.4 4 bytes U+10000 */
220 "\"\xF0\x90\x80\x80\"",
221 "\xF0\x90\x80\x80",
222 "\"\\uD800\\uDC00\"",
224 /* 2.1.5 5 bytes U+200000 */
226 "\"\xF8\x88\x80\x80\x80\"",
227 NULL, /* bug: rejected */
228 "\"\\uFFFD\"",
229 "\xF8\x88\x80\x80\x80",
231 /* 2.1.6 6 bytes U+4000000 */
233 "\"\xFC\x84\x80\x80\x80\x80\"",
234 NULL, /* bug: rejected */
235 "\"\\uFFFD\"",
236 "\xFC\x84\x80\x80\x80\x80",
238 /* 2.2 Last possible sequence of a certain length */
239 /* 2.2.1 1 byte U+007F */
241 "\"\x7F\"",
242 "\x7F",
243 "\"\\u007F\"",
245 /* 2.2.2 2 bytes U+07FF */
247 "\"\xDF\xBF\"",
248 "\xDF\xBF",
249 "\"\\u07FF\"",
252 * 2.2.3 3 bytes U+FFFC
253 * The last possible sequence is actually U+FFFF. But that's
254 * a noncharacter, and already covered by its own test case
255 * under 5.3. Same for U+FFFE. U+FFFD is the last character
256 * in the BMP, and covered under 2.3. Because of U+FFFD's
257 * special role as replacement character, it's worth testing
258 * U+FFFC here.
261 "\"\xEF\xBF\xBC\"",
262 "\xEF\xBF\xBC",
263 "\"\\uFFFC\"",
265 /* 2.2.4 4 bytes U+1FFFFF */
267 "\"\xF7\xBF\xBF\xBF\"",
268 NULL, /* bug: rejected */
269 "\"\\uFFFD\"",
270 "\xF7\xBF\xBF\xBF",
272 /* 2.2.5 5 bytes U+3FFFFFF */
274 "\"\xFB\xBF\xBF\xBF\xBF\"",
275 NULL, /* bug: rejected */
276 "\"\\uFFFD\"",
277 "\xFB\xBF\xBF\xBF\xBF",
279 /* 2.2.6 6 bytes U+7FFFFFFF */
281 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
282 NULL, /* bug: rejected */
283 "\"\\uFFFD\"",
284 "\xFD\xBF\xBF\xBF\xBF\xBF",
286 /* 2.3 Other boundary conditions */
288 /* last one before surrogate range: U+D7FF */
289 "\"\xED\x9F\xBF\"",
290 "\xED\x9F\xBF",
291 "\"\\uD7FF\"",
294 /* first one after surrogate range: U+E000 */
295 "\"\xEE\x80\x80\"",
296 "\xEE\x80\x80",
297 "\"\\uE000\"",
300 /* last one in BMP: U+FFFD */
301 "\"\xEF\xBF\xBD\"",
302 "\xEF\xBF\xBD",
303 "\"\\uFFFD\"",
306 /* last one in last plane: U+10FFFD */
307 "\"\xF4\x8F\xBF\xBD\"",
308 "\xF4\x8F\xBF\xBD",
309 "\"\\uDBFF\\uDFFD\""
312 /* first one beyond Unicode range: U+110000 */
313 "\"\xF4\x90\x80\x80\"",
314 "\xF4\x90\x80\x80",
315 "\"\\uFFFD\"",
317 /* 3 Malformed sequences */
318 /* 3.1 Unexpected continuation bytes */
319 /* 3.1.1 First continuation byte */
321 "\"\x80\"",
322 "\x80", /* bug: not corrected */
323 "\"\\uFFFD\"",
325 /* 3.1.2 Last continuation byte */
327 "\"\xBF\"",
328 "\xBF", /* bug: not corrected */
329 "\"\\uFFFD\"",
331 /* 3.1.3 2 continuation bytes */
333 "\"\x80\xBF\"",
334 "\x80\xBF", /* bug: not corrected */
335 "\"\\uFFFD\\uFFFD\"",
337 /* 3.1.4 3 continuation bytes */
339 "\"\x80\xBF\x80\"",
340 "\x80\xBF\x80", /* bug: not corrected */
341 "\"\\uFFFD\\uFFFD\\uFFFD\"",
343 /* 3.1.5 4 continuation bytes */
345 "\"\x80\xBF\x80\xBF\"",
346 "\x80\xBF\x80\xBF", /* bug: not corrected */
347 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
349 /* 3.1.6 5 continuation bytes */
351 "\"\x80\xBF\x80\xBF\x80\"",
352 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
353 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
355 /* 3.1.7 6 continuation bytes */
357 "\"\x80\xBF\x80\xBF\x80\xBF\"",
358 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
359 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
361 /* 3.1.8 7 continuation bytes */
363 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
364 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
365 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
367 /* 3.1.9 Sequence of all 64 possible continuation bytes */
369 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
370 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
371 "\x90\x91\x92\x93\x94\x95\x96\x97"
372 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
373 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
374 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
375 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
376 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
377 /* bug: not corrected */
378 "\x80\x81\x82\x83\x84\x85\x86\x87"
379 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
380 "\x90\x91\x92\x93\x94\x95\x96\x97"
381 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
382 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
383 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
384 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
385 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
386 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
387 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
388 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
389 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
390 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
391 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
392 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
393 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
395 /* 3.2 Lonely start characters */
396 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
398 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
399 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
400 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
401 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
402 NULL, /* bug: rejected */
403 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
404 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
405 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
406 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
407 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
408 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
409 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
410 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
412 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
414 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
415 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
416 /* bug: not corrected */
417 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
418 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
419 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
420 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
422 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
424 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
425 NULL, /* bug: rejected */
426 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
427 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
429 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
431 "\"\xF8 \xF9 \xFA \xFB \"",
432 NULL, /* bug: rejected */
433 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
434 "\xF8 \xF9 \xFA \xFB ",
436 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
438 "\"\xFC \xFD \"",
439 NULL, /* bug: rejected */
440 "\"\\uFFFD \\uFFFD \"",
441 "\xFC \xFD ",
443 /* 3.3 Sequences with last continuation byte missing */
444 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
446 "\"\xC0\"",
447 NULL, /* bug: rejected */
448 "\"\\uFFFD\"",
449 "\xC0",
451 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
453 "\"\xE0\x80\"",
454 "\xE0\x80", /* bug: not corrected */
455 "\"\\uFFFD\"",
457 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
459 "\"\xF0\x80\x80\"",
460 "\xF0\x80\x80", /* bug: not corrected */
461 "\"\\uFFFD\"",
463 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
465 "\"\xF8\x80\x80\x80\"",
466 NULL, /* bug: rejected */
467 "\"\\uFFFD\"",
468 "\xF8\x80\x80\x80",
470 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
472 "\"\xFC\x80\x80\x80\x80\"",
473 NULL, /* bug: rejected */
474 "\"\\uFFFD\"",
475 "\xFC\x80\x80\x80\x80",
477 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
479 "\"\xDF\"",
480 "\xDF", /* bug: not corrected */
481 "\"\\uFFFD\"",
483 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
485 "\"\xEF\xBF\"",
486 "\xEF\xBF", /* bug: not corrected */
487 "\"\\uFFFD\"",
489 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
491 "\"\xF7\xBF\xBF\"",
492 NULL, /* bug: rejected */
493 "\"\\uFFFD\"",
494 "\xF7\xBF\xBF",
496 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
498 "\"\xFB\xBF\xBF\xBF\"",
499 NULL, /* bug: rejected */
500 "\"\\uFFFD\"",
501 "\xFB\xBF\xBF\xBF",
503 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
505 "\"\xFD\xBF\xBF\xBF\xBF\"",
506 NULL, /* bug: rejected */
507 "\"\\uFFFD\"",
508 "\xFD\xBF\xBF\xBF\xBF",
510 /* 3.4 Concatenation of incomplete sequences */
512 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
513 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
514 NULL, /* bug: rejected */
515 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
516 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
517 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
518 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
520 /* 3.5 Impossible bytes */
522 "\"\xFE\"",
523 NULL, /* bug: rejected */
524 "\"\\uFFFD\"",
525 "\xFE",
528 "\"\xFF\"",
529 NULL, /* bug: rejected */
530 "\"\\uFFFD\"",
531 "\xFF",
534 "\"\xFE\xFE\xFF\xFF\"",
535 NULL, /* bug: rejected */
536 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
537 "\xFE\xFE\xFF\xFF",
539 /* 4 Overlong sequences */
540 /* 4.1 Overlong '/' */
542 "\"\xC0\xAF\"",
543 NULL, /* bug: rejected */
544 "\"\\uFFFD\"",
545 "\xC0\xAF",
548 "\"\xE0\x80\xAF\"",
549 "\xE0\x80\xAF", /* bug: not corrected */
550 "\"\\uFFFD\"",
553 "\"\xF0\x80\x80\xAF\"",
554 "\xF0\x80\x80\xAF", /* bug: not corrected */
555 "\"\\uFFFD\"",
558 "\"\xF8\x80\x80\x80\xAF\"",
559 NULL, /* bug: rejected */
560 "\"\\uFFFD\"",
561 "\xF8\x80\x80\x80\xAF",
564 "\"\xFC\x80\x80\x80\x80\xAF\"",
565 NULL, /* bug: rejected */
566 "\"\\uFFFD\"",
567 "\xFC\x80\x80\x80\x80\xAF",
570 * 4.2 Maximum overlong sequences
571 * Highest Unicode value that is still resulting in an
572 * overlong sequence if represented with the given number of
573 * bytes. This is a boundary test for safe UTF-8 decoders.
576 /* \U+007F */
577 "\"\xC1\xBF\"",
578 NULL, /* bug: rejected */
579 "\"\\uFFFD\"",
580 "\xC1\xBF",
583 /* \U+07FF */
584 "\"\xE0\x9F\xBF\"",
585 "\xE0\x9F\xBF", /* bug: not corrected */
586 "\"\\uFFFD\"",
590 * \U+FFFC
591 * The actual maximum would be U+FFFF, but that's a
592 * noncharacter. Testing U+FFFC seems more useful. See
593 * also 2.2.3
595 "\"\xF0\x8F\xBF\xBC\"",
596 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
597 "\"\\uFFFD\"",
600 /* \U+1FFFFF */
601 "\"\xF8\x87\xBF\xBF\xBF\"",
602 NULL, /* bug: rejected */
603 "\"\\uFFFD\"",
604 "\xF8\x87\xBF\xBF\xBF",
607 /* \U+3FFFFFF */
608 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
609 NULL, /* bug: rejected */
610 "\"\\uFFFD\"",
611 "\xFC\x83\xBF\xBF\xBF\xBF",
613 /* 4.3 Overlong representation of the NUL character */
615 /* \U+0000 */
616 "\"\xC0\x80\"",
617 NULL, /* bug: rejected */
618 "\"\\u0000\"",
619 "\xC0\x80",
622 /* \U+0000 */
623 "\"\xE0\x80\x80\"",
624 "\xE0\x80\x80", /* bug: not corrected */
625 "\"\\uFFFD\"",
628 /* \U+0000 */
629 "\"\xF0\x80\x80\x80\"",
630 "\xF0\x80\x80\x80", /* bug: not corrected */
631 "\"\\uFFFD\"",
634 /* \U+0000 */
635 "\"\xF8\x80\x80\x80\x80\"",
636 NULL, /* bug: rejected */
637 "\"\\uFFFD\"",
638 "\xF8\x80\x80\x80\x80",
641 /* \U+0000 */
642 "\"\xFC\x80\x80\x80\x80\x80\"",
643 NULL, /* bug: rejected */
644 "\"\\uFFFD\"",
645 "\xFC\x80\x80\x80\x80\x80",
647 /* 5 Illegal code positions */
648 /* 5.1 Single UTF-16 surrogates */
650 /* \U+D800 */
651 "\"\xED\xA0\x80\"",
652 "\xED\xA0\x80", /* bug: not corrected */
653 "\"\\uFFFD\"",
656 /* \U+DB7F */
657 "\"\xED\xAD\xBF\"",
658 "\xED\xAD\xBF", /* bug: not corrected */
659 "\"\\uFFFD\"",
662 /* \U+DB80 */
663 "\"\xED\xAE\x80\"",
664 "\xED\xAE\x80", /* bug: not corrected */
665 "\"\\uFFFD\"",
668 /* \U+DBFF */
669 "\"\xED\xAF\xBF\"",
670 "\xED\xAF\xBF", /* bug: not corrected */
671 "\"\\uFFFD\"",
674 /* \U+DC00 */
675 "\"\xED\xB0\x80\"",
676 "\xED\xB0\x80", /* bug: not corrected */
677 "\"\\uFFFD\"",
680 /* \U+DF80 */
681 "\"\xED\xBE\x80\"",
682 "\xED\xBE\x80", /* bug: not corrected */
683 "\"\\uFFFD\"",
686 /* \U+DFFF */
687 "\"\xED\xBF\xBF\"",
688 "\xED\xBF\xBF", /* bug: not corrected */
689 "\"\\uFFFD\"",
691 /* 5.2 Paired UTF-16 surrogates */
693 /* \U+D800\U+DC00 */
694 "\"\xED\xA0\x80\xED\xB0\x80\"",
695 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
696 "\"\\uFFFD\\uFFFD\"",
699 /* \U+D800\U+DFFF */
700 "\"\xED\xA0\x80\xED\xBF\xBF\"",
701 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
702 "\"\\uFFFD\\uFFFD\"",
705 /* \U+DB7F\U+DC00 */
706 "\"\xED\xAD\xBF\xED\xB0\x80\"",
707 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
708 "\"\\uFFFD\\uFFFD\"",
711 /* \U+DB7F\U+DFFF */
712 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
713 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
714 "\"\\uFFFD\\uFFFD\"",
717 /* \U+DB80\U+DC00 */
718 "\"\xED\xAE\x80\xED\xB0\x80\"",
719 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
720 "\"\\uFFFD\\uFFFD\"",
723 /* \U+DB80\U+DFFF */
724 "\"\xED\xAE\x80\xED\xBF\xBF\"",
725 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
726 "\"\\uFFFD\\uFFFD\"",
729 /* \U+DBFF\U+DC00 */
730 "\"\xED\xAF\xBF\xED\xB0\x80\"",
731 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
732 "\"\\uFFFD\\uFFFD\"",
735 /* \U+DBFF\U+DFFF */
736 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
737 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
738 "\"\\uFFFD\\uFFFD\"",
740 /* 5.3 Other illegal code positions */
741 /* BMP noncharacters */
743 /* \U+FFFE */
744 "\"\xEF\xBF\xBE\"",
745 "\xEF\xBF\xBE", /* bug: not corrected */
746 "\"\\uFFFD\"",
749 /* \U+FFFF */
750 "\"\xEF\xBF\xBF\"",
751 "\xEF\xBF\xBF", /* bug: not corrected */
752 "\"\\uFFFD\"",
755 /* U+FDD0 */
756 "\"\xEF\xB7\x90\"",
757 "\xEF\xB7\x90", /* bug: not corrected */
758 "\"\\uFFFD\"",
761 /* U+FDEF */
762 "\"\xEF\xB7\xAF\"",
763 "\xEF\xB7\xAF", /* bug: not corrected */
764 "\"\\uFFFD\"",
766 /* Plane 1 .. 16 noncharacters */
768 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
769 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
770 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
771 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
772 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
773 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
774 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
775 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
776 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
777 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
778 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
779 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
780 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
781 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
782 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
783 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
784 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
785 /* bug: not corrected */
786 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
787 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
788 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
789 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
790 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
791 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
792 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
793 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
794 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
795 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
796 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
797 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
798 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
799 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
800 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
801 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
802 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
803 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
804 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
805 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
809 int i;
810 QObject *obj;
811 QString *str;
812 const char *json_in, *utf8_out, *utf8_in, *json_out;
814 for (i = 0; test_cases[i].json_in; i++) {
815 json_in = test_cases[i].json_in;
816 utf8_out = test_cases[i].utf8_out;
817 utf8_in = test_cases[i].utf8_in ?: test_cases[i].utf8_out;
818 json_out = test_cases[i].json_out ?: test_cases[i].json_in;
820 obj = qobject_from_json(json_in);
821 if (utf8_out) {
822 g_assert(obj);
823 g_assert(qobject_type(obj) == QTYPE_QSTRING);
824 str = qobject_to_qstring(obj);
825 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
826 } else {
827 g_assert(!obj);
829 qobject_decref(obj);
831 obj = QOBJECT(qstring_from_str(utf8_in));
832 str = qobject_to_json(obj);
833 if (json_out) {
834 g_assert(str);
835 g_assert_cmpstr(qstring_get_str(str), ==, json_out);
836 } else {
837 g_assert(!str);
839 QDECREF(str);
840 qobject_decref(obj);
843 * Disabled, because qobject_from_json() is buggy, and I can't
844 * be bothered to add the expected incorrect results.
845 * FIXME Enable once these bugs have been fixed.
847 if (0 && json_out != json_in) {
848 obj = qobject_from_json(json_out);
849 g_assert(obj);
850 g_assert(qobject_type(obj) == QTYPE_QSTRING);
851 str = qobject_to_qstring(obj);
852 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
857 static void vararg_string(void)
859 int i;
860 struct {
861 const char *decoded;
862 } test_cases[] = {
863 { "hello world" },
864 { "the quick brown fox jumped over the fence" },
868 for (i = 0; test_cases[i].decoded; i++) {
869 QObject *obj;
870 QString *str;
872 obj = qobject_from_jsonf("%s", test_cases[i].decoded);
874 g_assert(obj != NULL);
875 g_assert(qobject_type(obj) == QTYPE_QSTRING);
877 str = qobject_to_qstring(obj);
878 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
880 QDECREF(str);
884 static void simple_number(void)
886 int i;
887 struct {
888 const char *encoded;
889 int64_t decoded;
890 int skip;
891 } test_cases[] = {
892 { "0", 0 },
893 { "1234", 1234 },
894 { "1", 1 },
895 { "-32", -32 },
896 { "-0", 0, .skip = 1 },
897 { },
900 for (i = 0; test_cases[i].encoded; i++) {
901 QObject *obj;
902 QInt *qint;
904 obj = qobject_from_json(test_cases[i].encoded);
905 g_assert(obj != NULL);
906 g_assert(qobject_type(obj) == QTYPE_QINT);
908 qint = qobject_to_qint(obj);
909 g_assert(qint_get_int(qint) == test_cases[i].decoded);
910 if (test_cases[i].skip == 0) {
911 QString *str;
913 str = qobject_to_json(obj);
914 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
915 QDECREF(str);
918 QDECREF(qint);
922 static void float_number(void)
924 int i;
925 struct {
926 const char *encoded;
927 double decoded;
928 int skip;
929 } test_cases[] = {
930 { "32.43", 32.43 },
931 { "0.222", 0.222 },
932 { "-32.12313", -32.12313 },
933 { "-32.20e-10", -32.20e-10, .skip = 1 },
934 { },
937 for (i = 0; test_cases[i].encoded; i++) {
938 QObject *obj;
939 QFloat *qfloat;
941 obj = qobject_from_json(test_cases[i].encoded);
942 g_assert(obj != NULL);
943 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
945 qfloat = qobject_to_qfloat(obj);
946 g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
948 if (test_cases[i].skip == 0) {
949 QString *str;
951 str = qobject_to_json(obj);
952 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
953 QDECREF(str);
956 QDECREF(qfloat);
960 static void vararg_number(void)
962 QObject *obj;
963 QInt *qint;
964 QFloat *qfloat;
965 int value = 0x2342;
966 int64_t value64 = 0x2342342343LL;
967 double valuef = 2.323423423;
969 obj = qobject_from_jsonf("%d", value);
970 g_assert(obj != NULL);
971 g_assert(qobject_type(obj) == QTYPE_QINT);
973 qint = qobject_to_qint(obj);
974 g_assert(qint_get_int(qint) == value);
976 QDECREF(qint);
978 obj = qobject_from_jsonf("%" PRId64, value64);
979 g_assert(obj != NULL);
980 g_assert(qobject_type(obj) == QTYPE_QINT);
982 qint = qobject_to_qint(obj);
983 g_assert(qint_get_int(qint) == value64);
985 QDECREF(qint);
987 obj = qobject_from_jsonf("%f", valuef);
988 g_assert(obj != NULL);
989 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
991 qfloat = qobject_to_qfloat(obj);
992 g_assert(qfloat_get_double(qfloat) == valuef);
994 QDECREF(qfloat);
997 static void keyword_literal(void)
999 QObject *obj;
1000 QBool *qbool;
1001 QString *str;
1003 obj = qobject_from_json("true");
1004 g_assert(obj != NULL);
1005 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1007 qbool = qobject_to_qbool(obj);
1008 g_assert(qbool_get_int(qbool) != 0);
1010 str = qobject_to_json(obj);
1011 g_assert(strcmp(qstring_get_str(str), "true") == 0);
1012 QDECREF(str);
1014 QDECREF(qbool);
1016 obj = qobject_from_json("false");
1017 g_assert(obj != NULL);
1018 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1020 qbool = qobject_to_qbool(obj);
1021 g_assert(qbool_get_int(qbool) == 0);
1023 str = qobject_to_json(obj);
1024 g_assert(strcmp(qstring_get_str(str), "false") == 0);
1025 QDECREF(str);
1027 QDECREF(qbool);
1029 obj = qobject_from_jsonf("%i", false);
1030 g_assert(obj != NULL);
1031 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1033 qbool = qobject_to_qbool(obj);
1034 g_assert(qbool_get_int(qbool) == 0);
1036 QDECREF(qbool);
1038 obj = qobject_from_jsonf("%i", true);
1039 g_assert(obj != NULL);
1040 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1042 qbool = qobject_to_qbool(obj);
1043 g_assert(qbool_get_int(qbool) != 0);
1045 QDECREF(qbool);
1048 typedef struct LiteralQDictEntry LiteralQDictEntry;
1049 typedef struct LiteralQObject LiteralQObject;
1051 struct LiteralQObject
1053 int type;
1054 union {
1055 int64_t qint;
1056 const char *qstr;
1057 LiteralQDictEntry *qdict;
1058 LiteralQObject *qlist;
1059 } value;
1062 struct LiteralQDictEntry
1064 const char *key;
1065 LiteralQObject value;
1068 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1069 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1070 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1071 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1073 typedef struct QListCompareHelper
1075 int index;
1076 LiteralQObject *objs;
1077 int result;
1078 } QListCompareHelper;
1080 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1082 static void compare_helper(QObject *obj, void *opaque)
1084 QListCompareHelper *helper = opaque;
1086 if (helper->result == 0) {
1087 return;
1090 if (helper->objs[helper->index].type == QTYPE_NONE) {
1091 helper->result = 0;
1092 return;
1095 helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1098 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1100 if (lhs->type != qobject_type(rhs)) {
1101 return 0;
1104 switch (lhs->type) {
1105 case QTYPE_QINT:
1106 return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
1107 case QTYPE_QSTRING:
1108 return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1109 case QTYPE_QDICT: {
1110 int i;
1112 for (i = 0; lhs->value.qdict[i].key; i++) {
1113 QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1115 if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1116 return 0;
1120 return 1;
1122 case QTYPE_QLIST: {
1123 QListCompareHelper helper;
1125 helper.index = 0;
1126 helper.objs = lhs->value.qlist;
1127 helper.result = 1;
1129 qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1131 return helper.result;
1133 default:
1134 break;
1137 return 0;
1140 static void simple_dict(void)
1142 int i;
1143 struct {
1144 const char *encoded;
1145 LiteralQObject decoded;
1146 } test_cases[] = {
1148 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1149 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1150 { "foo", QLIT_QINT(42) },
1151 { "bar", QLIT_QSTR("hello world") },
1153 })),
1154 }, {
1155 .encoded = "{}",
1156 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1158 })),
1159 }, {
1160 .encoded = "{\"foo\": 43}",
1161 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1162 { "foo", QLIT_QINT(43) },
1164 })),
1169 for (i = 0; test_cases[i].encoded; i++) {
1170 QObject *obj;
1171 QString *str;
1173 obj = qobject_from_json(test_cases[i].encoded);
1174 g_assert(obj != NULL);
1175 g_assert(qobject_type(obj) == QTYPE_QDICT);
1177 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1179 str = qobject_to_json(obj);
1180 qobject_decref(obj);
1182 obj = qobject_from_json(qstring_get_str(str));
1183 g_assert(obj != NULL);
1184 g_assert(qobject_type(obj) == QTYPE_QDICT);
1186 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1187 qobject_decref(obj);
1188 QDECREF(str);
1193 * this generates json of the form:
1194 * a(0,m) = [0, 1, ..., m-1]
1195 * a(n,m) = {
1196 * 'key0': a(0,m),
1197 * 'key1': a(1,m),
1198 * ...
1199 * 'key(n-1)': a(n-1,m)
1202 static void gen_test_json(GString *gstr, int nest_level_max,
1203 int elem_count)
1205 int i;
1207 g_assert(gstr);
1208 if (nest_level_max == 0) {
1209 g_string_append(gstr, "[");
1210 for (i = 0; i < elem_count; i++) {
1211 g_string_append_printf(gstr, "%d", i);
1212 if (i < elem_count - 1) {
1213 g_string_append_printf(gstr, ", ");
1216 g_string_append(gstr, "]");
1217 return;
1220 g_string_append(gstr, "{");
1221 for (i = 0; i < nest_level_max; i++) {
1222 g_string_append_printf(gstr, "'key%d': ", i);
1223 gen_test_json(gstr, i, elem_count);
1224 if (i < nest_level_max - 1) {
1225 g_string_append(gstr, ",");
1228 g_string_append(gstr, "}");
1231 static void large_dict(void)
1233 GString *gstr = g_string_new("");
1234 QObject *obj;
1236 gen_test_json(gstr, 10, 100);
1237 obj = qobject_from_json(gstr->str);
1238 g_assert(obj != NULL);
1240 qobject_decref(obj);
1241 g_string_free(gstr, true);
1244 static void simple_list(void)
1246 int i;
1247 struct {
1248 const char *encoded;
1249 LiteralQObject decoded;
1250 } test_cases[] = {
1252 .encoded = "[43,42]",
1253 .decoded = QLIT_QLIST(((LiteralQObject[]){
1254 QLIT_QINT(43),
1255 QLIT_QINT(42),
1257 })),
1260 .encoded = "[43]",
1261 .decoded = QLIT_QLIST(((LiteralQObject[]){
1262 QLIT_QINT(43),
1264 })),
1267 .encoded = "[]",
1268 .decoded = QLIT_QLIST(((LiteralQObject[]){
1270 })),
1273 .encoded = "[{}]",
1274 .decoded = QLIT_QLIST(((LiteralQObject[]){
1275 QLIT_QDICT(((LiteralQDictEntry[]){
1277 })),
1279 })),
1284 for (i = 0; test_cases[i].encoded; i++) {
1285 QObject *obj;
1286 QString *str;
1288 obj = qobject_from_json(test_cases[i].encoded);
1289 g_assert(obj != NULL);
1290 g_assert(qobject_type(obj) == QTYPE_QLIST);
1292 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1294 str = qobject_to_json(obj);
1295 qobject_decref(obj);
1297 obj = qobject_from_json(qstring_get_str(str));
1298 g_assert(obj != NULL);
1299 g_assert(qobject_type(obj) == QTYPE_QLIST);
1301 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1302 qobject_decref(obj);
1303 QDECREF(str);
1307 static void simple_whitespace(void)
1309 int i;
1310 struct {
1311 const char *encoded;
1312 LiteralQObject decoded;
1313 } test_cases[] = {
1315 .encoded = " [ 43 , 42 ]",
1316 .decoded = QLIT_QLIST(((LiteralQObject[]){
1317 QLIT_QINT(43),
1318 QLIT_QINT(42),
1320 })),
1323 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1324 .decoded = QLIT_QLIST(((LiteralQObject[]){
1325 QLIT_QINT(43),
1326 QLIT_QDICT(((LiteralQDictEntry[]){
1327 { "h", QLIT_QSTR("b") },
1328 { }})),
1329 QLIT_QLIST(((LiteralQObject[]){
1330 { }})),
1331 QLIT_QINT(42),
1333 })),
1336 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1337 .decoded = QLIT_QLIST(((LiteralQObject[]){
1338 QLIT_QINT(43),
1339 QLIT_QDICT(((LiteralQDictEntry[]){
1340 { "h", QLIT_QSTR("b") },
1341 { "a", QLIT_QINT(32) },
1342 { }})),
1343 QLIT_QLIST(((LiteralQObject[]){
1344 { }})),
1345 QLIT_QINT(42),
1347 })),
1352 for (i = 0; test_cases[i].encoded; i++) {
1353 QObject *obj;
1354 QString *str;
1356 obj = qobject_from_json(test_cases[i].encoded);
1357 g_assert(obj != NULL);
1358 g_assert(qobject_type(obj) == QTYPE_QLIST);
1360 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1362 str = qobject_to_json(obj);
1363 qobject_decref(obj);
1365 obj = qobject_from_json(qstring_get_str(str));
1366 g_assert(obj != NULL);
1367 g_assert(qobject_type(obj) == QTYPE_QLIST);
1369 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1371 qobject_decref(obj);
1372 QDECREF(str);
1376 static void simple_varargs(void)
1378 QObject *embedded_obj;
1379 QObject *obj;
1380 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1381 QLIT_QINT(1),
1382 QLIT_QINT(2),
1383 QLIT_QLIST(((LiteralQObject[]){
1384 QLIT_QINT(32),
1385 QLIT_QINT(42),
1386 {}})),
1387 {}}));
1389 embedded_obj = qobject_from_json("[32, 42]");
1390 g_assert(embedded_obj != NULL);
1392 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1393 g_assert(obj != NULL);
1395 g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1397 qobject_decref(obj);
1400 static void empty_input(void)
1402 const char *empty = "";
1404 QObject *obj = qobject_from_json(empty);
1405 g_assert(obj == NULL);
1408 static void unterminated_string(void)
1410 QObject *obj = qobject_from_json("\"abc");
1411 g_assert(obj == NULL);
1414 static void unterminated_sq_string(void)
1416 QObject *obj = qobject_from_json("'abc");
1417 g_assert(obj == NULL);
1420 static void unterminated_escape(void)
1422 QObject *obj = qobject_from_json("\"abc\\\"");
1423 g_assert(obj == NULL);
1426 static void unterminated_array(void)
1428 QObject *obj = qobject_from_json("[32");
1429 g_assert(obj == NULL);
1432 static void unterminated_array_comma(void)
1434 QObject *obj = qobject_from_json("[32,");
1435 g_assert(obj == NULL);
1438 static void invalid_array_comma(void)
1440 QObject *obj = qobject_from_json("[32,}");
1441 g_assert(obj == NULL);
1444 static void unterminated_dict(void)
1446 QObject *obj = qobject_from_json("{'abc':32");
1447 g_assert(obj == NULL);
1450 static void unterminated_dict_comma(void)
1452 QObject *obj = qobject_from_json("{'abc':32,");
1453 g_assert(obj == NULL);
1456 static void invalid_dict_comma(void)
1458 QObject *obj = qobject_from_json("{'abc':32,}");
1459 g_assert(obj == NULL);
1462 static void unterminated_literal(void)
1464 QObject *obj = qobject_from_json("nul");
1465 g_assert(obj == NULL);
1468 int main(int argc, char **argv)
1470 g_test_init(&argc, &argv, NULL);
1472 g_test_add_func("/literals/string/simple", simple_string);
1473 g_test_add_func("/literals/string/escaped", escaped_string);
1474 g_test_add_func("/literals/string/utf8", utf8_string);
1475 g_test_add_func("/literals/string/single_quote", single_quote_string);
1476 g_test_add_func("/literals/string/vararg", vararg_string);
1478 g_test_add_func("/literals/number/simple", simple_number);
1479 g_test_add_func("/literals/number/float", float_number);
1480 g_test_add_func("/literals/number/vararg", vararg_number);
1482 g_test_add_func("/literals/keyword", keyword_literal);
1484 g_test_add_func("/dicts/simple_dict", simple_dict);
1485 g_test_add_func("/dicts/large_dict", large_dict);
1486 g_test_add_func("/lists/simple_list", simple_list);
1488 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1490 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1492 g_test_add_func("/errors/empty_input", empty_input);
1493 g_test_add_func("/errors/unterminated/string", unterminated_string);
1494 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1495 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1496 g_test_add_func("/errors/unterminated/array", unterminated_array);
1497 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1498 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1499 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1500 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1501 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1502 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1504 return g_test_run();