target/s390x: move cc_name() to helper.c
[qemu/ar7.git] / tests / check-qjson.c
bloba3a97b0d99a14fd981aeeb80fe5045730421ffca
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.
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)
23 int i;
24 struct {
25 const char *encoded;
26 const char *decoded;
27 int skip;
28 } test_cases[] = {
29 { "\"\\b\"", "\b" },
30 { "\"\\f\"", "\f" },
31 { "\"\\n\"", "\n" },
32 { "\"\\r\"", "\r" },
33 { "\"\\t\"", "\t" },
34 { "\"/\"", "/" },
35 { "\"\\/\"", "/", .skip = 1 },
36 { "\"\\\\\"", "\\" },
37 { "\"\\\"\"", "\"" },
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++) {
55 QObject *obj;
56 QString *str;
58 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
59 str = qobject_to_qstring(obj);
60 g_assert(str);
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, &error_abort);
91 str = qobject_to_qstring(obj);
92 g_assert(str);
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);
98 qobject_decref(obj);
100 QDECREF(str);
104 static void single_quote_string(void)
106 int i;
107 struct {
108 const char *encoded;
109 const char *decoded;
110 } test_cases[] = {
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++) {
118 QObject *obj;
119 QString *str;
121 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
122 str = qobject_to_qstring(obj);
123 g_assert(str);
124 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
126 QDECREF(str);
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
150 * UTF-8").
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 {
157 const char *json_in;
158 const char *utf8_out;
159 const char *json_out; /* defaults to @json_in */
160 const char *utf8_in; /* defaults to @utf8_out */
161 } test_cases[] = {
163 * Bug markers used here:
164 * - bug: not corrected
165 * JSON parser fails to correct invalid sequence(s)
166 * - bug: rejected
167 * JSON parser rejects invalid sequence(s)
168 * We may choose to define this as feature
169 * - bug: want "..."
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.\"",
186 /* a bit of Greek */
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 */
195 "\"\\u0000\"",
196 "", /* bug: want overlong "\xC0\x80" */
197 "\"\\u0000\"",
198 "\xC0\x80",
200 /* 2.1.2 2 bytes U+0080 */
202 "\"\xC2\x80\"",
203 "\xC2\x80",
204 "\"\\u0080\"",
206 /* 2.1.3 3 bytes U+0800 */
208 "\"\xE0\xA0\x80\"",
209 "\xE0\xA0\x80",
210 "\"\\u0800\"",
212 /* 2.1.4 4 bytes U+10000 */
214 "\"\xF0\x90\x80\x80\"",
215 "\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 */
222 "\"\\uFFFD\"",
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 */
229 "\"\\uFFFD\"",
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 */
235 "\"\x7F\"",
236 "\x7F",
237 "\"\\u007F\"",
239 /* 2.2.2 2 bytes U+07FF */
241 "\"\xDF\xBF\"",
242 "\xDF\xBF",
243 "\"\\u07FF\"",
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
252 * U+FFFC here.
255 "\"\xEF\xBF\xBC\"",
256 "\xEF\xBF\xBC",
257 "\"\\uFFFC\"",
259 /* 2.2.4 4 bytes U+1FFFFF */
261 "\"\xF7\xBF\xBF\xBF\"",
262 NULL, /* bug: rejected */
263 "\"\\uFFFD\"",
264 "\xF7\xBF\xBF\xBF",
266 /* 2.2.5 5 bytes U+3FFFFFF */
268 "\"\xFB\xBF\xBF\xBF\xBF\"",
269 NULL, /* bug: rejected */
270 "\"\\uFFFD\"",
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 */
277 "\"\\uFFFD\"",
278 "\xFD\xBF\xBF\xBF\xBF\xBF",
280 /* 2.3 Other boundary conditions */
282 /* last one before surrogate range: U+D7FF */
283 "\"\xED\x9F\xBF\"",
284 "\xED\x9F\xBF",
285 "\"\\uD7FF\"",
288 /* first one after surrogate range: U+E000 */
289 "\"\xEE\x80\x80\"",
290 "\xEE\x80\x80",
291 "\"\\uE000\"",
294 /* last one in BMP: U+FFFD */
295 "\"\xEF\xBF\xBD\"",
296 "\xEF\xBF\xBD",
297 "\"\\uFFFD\"",
300 /* last one in last plane: U+10FFFD */
301 "\"\xF4\x8F\xBF\xBD\"",
302 "\xF4\x8F\xBF\xBD",
303 "\"\\uDBFF\\uDFFD\""
306 /* first one beyond Unicode range: U+110000 */
307 "\"\xF4\x90\x80\x80\"",
308 "\xF4\x90\x80\x80",
309 "\"\\uFFFD\"",
311 /* 3 Malformed sequences */
312 /* 3.1 Unexpected continuation bytes */
313 /* 3.1.1 First continuation byte */
315 "\"\x80\"",
316 "\x80", /* bug: not corrected */
317 "\"\\uFFFD\"",
319 /* 3.1.2 Last continuation byte */
321 "\"\xBF\"",
322 "\xBF", /* bug: not corrected */
323 "\"\\uFFFD\"",
325 /* 3.1.3 2 continuation bytes */
327 "\"\x80\xBF\"",
328 "\x80\xBF", /* bug: not corrected */
329 "\"\\uFFFD\\uFFFD\"",
331 /* 3.1.4 3 continuation bytes */
333 "\"\x80\xBF\x80\"",
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 */
432 "\"\xFC \xFD \"",
433 NULL, /* bug: rejected */
434 "\"\\uFFFD \\uFFFD \"",
435 "\xFC \xFD ",
437 /* 3.3 Sequences with last continuation byte missing */
438 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
440 "\"\xC0\"",
441 NULL, /* bug: rejected */
442 "\"\\uFFFD\"",
443 "\xC0",
445 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
447 "\"\xE0\x80\"",
448 "\xE0\x80", /* bug: not corrected */
449 "\"\\uFFFD\"",
451 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
453 "\"\xF0\x80\x80\"",
454 "\xF0\x80\x80", /* bug: not corrected */
455 "\"\\uFFFD\"",
457 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
459 "\"\xF8\x80\x80\x80\"",
460 NULL, /* bug: rejected */
461 "\"\\uFFFD\"",
462 "\xF8\x80\x80\x80",
464 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
466 "\"\xFC\x80\x80\x80\x80\"",
467 NULL, /* bug: rejected */
468 "\"\\uFFFD\"",
469 "\xFC\x80\x80\x80\x80",
471 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
473 "\"\xDF\"",
474 "\xDF", /* bug: not corrected */
475 "\"\\uFFFD\"",
477 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
479 "\"\xEF\xBF\"",
480 "\xEF\xBF", /* bug: not corrected */
481 "\"\\uFFFD\"",
483 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
485 "\"\xF7\xBF\xBF\"",
486 NULL, /* bug: rejected */
487 "\"\\uFFFD\"",
488 "\xF7\xBF\xBF",
490 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
492 "\"\xFB\xBF\xBF\xBF\"",
493 NULL, /* bug: rejected */
494 "\"\\uFFFD\"",
495 "\xFB\xBF\xBF\xBF",
497 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
499 "\"\xFD\xBF\xBF\xBF\xBF\"",
500 NULL, /* bug: rejected */
501 "\"\\uFFFD\"",
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 */
516 "\"\xFE\"",
517 NULL, /* bug: rejected */
518 "\"\\uFFFD\"",
519 "\xFE",
522 "\"\xFF\"",
523 NULL, /* bug: rejected */
524 "\"\\uFFFD\"",
525 "\xFF",
528 "\"\xFE\xFE\xFF\xFF\"",
529 NULL, /* bug: rejected */
530 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
531 "\xFE\xFE\xFF\xFF",
533 /* 4 Overlong sequences */
534 /* 4.1 Overlong '/' */
536 "\"\xC0\xAF\"",
537 NULL, /* bug: rejected */
538 "\"\\uFFFD\"",
539 "\xC0\xAF",
542 "\"\xE0\x80\xAF\"",
543 "\xE0\x80\xAF", /* bug: not corrected */
544 "\"\\uFFFD\"",
547 "\"\xF0\x80\x80\xAF\"",
548 "\xF0\x80\x80\xAF", /* bug: not corrected */
549 "\"\\uFFFD\"",
552 "\"\xF8\x80\x80\x80\xAF\"",
553 NULL, /* bug: rejected */
554 "\"\\uFFFD\"",
555 "\xF8\x80\x80\x80\xAF",
558 "\"\xFC\x80\x80\x80\x80\xAF\"",
559 NULL, /* bug: rejected */
560 "\"\\uFFFD\"",
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.
570 /* \U+007F */
571 "\"\xC1\xBF\"",
572 NULL, /* bug: rejected */
573 "\"\\uFFFD\"",
574 "\xC1\xBF",
577 /* \U+07FF */
578 "\"\xE0\x9F\xBF\"",
579 "\xE0\x9F\xBF", /* bug: not corrected */
580 "\"\\uFFFD\"",
584 * \U+FFFC
585 * The actual maximum would be U+FFFF, but that's a
586 * noncharacter. Testing U+FFFC seems more useful. See
587 * also 2.2.3
589 "\"\xF0\x8F\xBF\xBC\"",
590 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
591 "\"\\uFFFD\"",
594 /* \U+1FFFFF */
595 "\"\xF8\x87\xBF\xBF\xBF\"",
596 NULL, /* bug: rejected */
597 "\"\\uFFFD\"",
598 "\xF8\x87\xBF\xBF\xBF",
601 /* \U+3FFFFFF */
602 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
603 NULL, /* bug: rejected */
604 "\"\\uFFFD\"",
605 "\xFC\x83\xBF\xBF\xBF\xBF",
607 /* 4.3 Overlong representation of the NUL character */
609 /* \U+0000 */
610 "\"\xC0\x80\"",
611 NULL, /* bug: rejected */
612 "\"\\u0000\"",
613 "\xC0\x80",
616 /* \U+0000 */
617 "\"\xE0\x80\x80\"",
618 "\xE0\x80\x80", /* bug: not corrected */
619 "\"\\uFFFD\"",
622 /* \U+0000 */
623 "\"\xF0\x80\x80\x80\"",
624 "\xF0\x80\x80\x80", /* bug: not corrected */
625 "\"\\uFFFD\"",
628 /* \U+0000 */
629 "\"\xF8\x80\x80\x80\x80\"",
630 NULL, /* bug: rejected */
631 "\"\\uFFFD\"",
632 "\xF8\x80\x80\x80\x80",
635 /* \U+0000 */
636 "\"\xFC\x80\x80\x80\x80\x80\"",
637 NULL, /* bug: rejected */
638 "\"\\uFFFD\"",
639 "\xFC\x80\x80\x80\x80\x80",
641 /* 5 Illegal code positions */
642 /* 5.1 Single UTF-16 surrogates */
644 /* \U+D800 */
645 "\"\xED\xA0\x80\"",
646 "\xED\xA0\x80", /* bug: not corrected */
647 "\"\\uFFFD\"",
650 /* \U+DB7F */
651 "\"\xED\xAD\xBF\"",
652 "\xED\xAD\xBF", /* bug: not corrected */
653 "\"\\uFFFD\"",
656 /* \U+DB80 */
657 "\"\xED\xAE\x80\"",
658 "\xED\xAE\x80", /* bug: not corrected */
659 "\"\\uFFFD\"",
662 /* \U+DBFF */
663 "\"\xED\xAF\xBF\"",
664 "\xED\xAF\xBF", /* bug: not corrected */
665 "\"\\uFFFD\"",
668 /* \U+DC00 */
669 "\"\xED\xB0\x80\"",
670 "\xED\xB0\x80", /* bug: not corrected */
671 "\"\\uFFFD\"",
674 /* \U+DF80 */
675 "\"\xED\xBE\x80\"",
676 "\xED\xBE\x80", /* bug: not corrected */
677 "\"\\uFFFD\"",
680 /* \U+DFFF */
681 "\"\xED\xBF\xBF\"",
682 "\xED\xBF\xBF", /* bug: not corrected */
683 "\"\\uFFFD\"",
685 /* 5.2 Paired UTF-16 surrogates */
687 /* \U+D800\U+DC00 */
688 "\"\xED\xA0\x80\xED\xB0\x80\"",
689 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
690 "\"\\uFFFD\\uFFFD\"",
693 /* \U+D800\U+DFFF */
694 "\"\xED\xA0\x80\xED\xBF\xBF\"",
695 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
696 "\"\\uFFFD\\uFFFD\"",
699 /* \U+DB7F\U+DC00 */
700 "\"\xED\xAD\xBF\xED\xB0\x80\"",
701 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
702 "\"\\uFFFD\\uFFFD\"",
705 /* \U+DB7F\U+DFFF */
706 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
707 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
708 "\"\\uFFFD\\uFFFD\"",
711 /* \U+DB80\U+DC00 */
712 "\"\xED\xAE\x80\xED\xB0\x80\"",
713 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
714 "\"\\uFFFD\\uFFFD\"",
717 /* \U+DB80\U+DFFF */
718 "\"\xED\xAE\x80\xED\xBF\xBF\"",
719 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
720 "\"\\uFFFD\\uFFFD\"",
723 /* \U+DBFF\U+DC00 */
724 "\"\xED\xAF\xBF\xED\xB0\x80\"",
725 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
726 "\"\\uFFFD\\uFFFD\"",
729 /* \U+DBFF\U+DFFF */
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 */
737 /* \U+FFFE */
738 "\"\xEF\xBF\xBE\"",
739 "\xEF\xBF\xBE", /* bug: not corrected */
740 "\"\\uFFFD\"",
743 /* \U+FFFF */
744 "\"\xEF\xBF\xBF\"",
745 "\xEF\xBF\xBF", /* bug: not corrected */
746 "\"\\uFFFD\"",
749 /* U+FDD0 */
750 "\"\xEF\xB7\x90\"",
751 "\xEF\xB7\x90", /* bug: not corrected */
752 "\"\\uFFFD\"",
755 /* U+FDEF */
756 "\"\xEF\xB7\xAF\"",
757 "\xEF\xB7\xAF", /* bug: not corrected */
758 "\"\\uFFFD\"",
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\"",
803 int i;
804 QObject *obj;
805 QString *str;
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);
815 if (utf8_out) {
816 str = qobject_to_qstring(obj);
817 g_assert(str);
818 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
819 } else {
820 g_assert(!obj);
822 qobject_decref(obj);
824 obj = QOBJECT(qstring_from_str(utf8_in));
825 str = qobject_to_json(obj);
826 if (json_out) {
827 g_assert(str);
828 g_assert_cmpstr(qstring_get_str(str), ==, json_out);
829 } else {
830 g_assert(!str);
832 QDECREF(str);
833 qobject_decref(obj);
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);
843 g_assert(str);
844 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
849 static void vararg_string(void)
851 int i;
852 struct {
853 const char *decoded;
854 } test_cases[] = {
855 { "hello world" },
856 { "the quick brown fox jumped over the fence" },
860 for (i = 0; test_cases[i].decoded; i++) {
861 QString *str;
863 str = qobject_to_qstring(qobject_from_jsonf("%s",
864 test_cases[i].decoded));
865 g_assert(str);
866 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
868 QDECREF(str);
872 static void simple_number(void)
874 int i;
875 struct {
876 const char *encoded;
877 int64_t decoded;
878 int skip;
879 } test_cases[] = {
880 { "0", 0 },
881 { "1234", 1234 },
882 { "1", 1 },
883 { "-32", -32 },
884 { "-0", 0, .skip = 1 },
885 { },
888 for (i = 0; test_cases[i].encoded; i++) {
889 QNum *qnum;
890 int64_t val;
892 qnum = qobject_to_qnum(qobject_from_json(test_cases[i].encoded,
893 &error_abort));
894 g_assert(qnum);
895 g_assert(qnum_get_try_int(qnum, &val));
896 g_assert_cmpint(val, ==, test_cases[i].decoded);
897 if (test_cases[i].skip == 0) {
898 QString *str;
900 str = qobject_to_json(QOBJECT(qnum));
901 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
902 QDECREF(str);
905 QDECREF(qnum);
909 static void large_number(void)
911 const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
912 const char *gtu64 = "18446744073709551616"; /* 2^64 */
913 const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
914 QNum *qnum;
915 QString *str;
916 uint64_t val;
917 int64_t ival;
919 qnum = qobject_to_qnum(qobject_from_json(maxu64, &error_abort));
920 g_assert(qnum);
921 g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
922 g_assert(!qnum_get_try_int(qnum, &ival));
924 str = qobject_to_json(QOBJECT(qnum));
925 g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
926 QDECREF(str);
927 QDECREF(qnum);
929 qnum = qobject_to_qnum(qobject_from_json(gtu64, &error_abort));
930 g_assert(qnum);
931 g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
932 g_assert(!qnum_get_try_uint(qnum, &val));
933 g_assert(!qnum_get_try_int(qnum, &ival));
935 str = qobject_to_json(QOBJECT(qnum));
936 g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
937 QDECREF(str);
938 QDECREF(qnum);
940 qnum = qobject_to_qnum(qobject_from_json(lti64, &error_abort));
941 g_assert(qnum);
942 g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
943 g_assert(!qnum_get_try_uint(qnum, &val));
944 g_assert(!qnum_get_try_int(qnum, &ival));
946 str = qobject_to_json(QOBJECT(qnum));
947 g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
948 QDECREF(str);
949 QDECREF(qnum);
952 static void float_number(void)
954 int i;
955 struct {
956 const char *encoded;
957 double decoded;
958 int skip;
959 } test_cases[] = {
960 { "32.43", 32.43 },
961 { "0.222", 0.222 },
962 { "-32.12313", -32.12313 },
963 { "-32.20e-10", -32.20e-10, .skip = 1 },
964 { },
967 for (i = 0; test_cases[i].encoded; i++) {
968 QObject *obj;
969 QNum *qnum;
971 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
972 qnum = qobject_to_qnum(obj);
973 g_assert(qnum);
974 g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
976 if (test_cases[i].skip == 0) {
977 QString *str;
979 str = qobject_to_json(obj);
980 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
981 QDECREF(str);
984 QDECREF(qnum);
988 static void vararg_number(void)
990 QNum *qnum;
991 int value = 0x2342;
992 long long value_ll = 0x2342342343LL;
993 double valuef = 2.323423423;
994 int64_t val;
996 qnum = qobject_to_qnum(qobject_from_jsonf("%d", value));
997 g_assert(qnum_get_try_int(qnum, &val));
998 g_assert_cmpint(val, ==, value);
999 QDECREF(qnum);
1001 qnum = qobject_to_qnum(qobject_from_jsonf("%lld", value_ll));
1002 g_assert(qnum_get_try_int(qnum, &val));
1003 g_assert_cmpint(val, ==, value_ll);
1004 QDECREF(qnum);
1006 qnum = qobject_to_qnum(qobject_from_jsonf("%f", valuef));
1007 g_assert(qnum_get_double(qnum) == valuef);
1008 QDECREF(qnum);
1011 static void keyword_literal(void)
1013 QObject *obj;
1014 QBool *qbool;
1015 QNull *null;
1016 QString *str;
1018 obj = qobject_from_json("true", &error_abort);
1019 qbool = qobject_to_qbool(obj);
1020 g_assert(qbool);
1021 g_assert(qbool_get_bool(qbool) == true);
1023 str = qobject_to_json(obj);
1024 g_assert(strcmp(qstring_get_str(str), "true") == 0);
1025 QDECREF(str);
1027 QDECREF(qbool);
1029 obj = qobject_from_json("false", &error_abort);
1030 qbool = qobject_to_qbool(obj);
1031 g_assert(qbool);
1032 g_assert(qbool_get_bool(qbool) == false);
1034 str = qobject_to_json(obj);
1035 g_assert(strcmp(qstring_get_str(str), "false") == 0);
1036 QDECREF(str);
1038 QDECREF(qbool);
1040 qbool = qobject_to_qbool(qobject_from_jsonf("%i", false));
1041 g_assert(qbool);
1042 g_assert(qbool_get_bool(qbool) == false);
1043 QDECREF(qbool);
1045 /* Test that non-zero values other than 1 get collapsed to true */
1046 qbool = qobject_to_qbool(qobject_from_jsonf("%i", 2));
1047 g_assert(qbool);
1048 g_assert(qbool_get_bool(qbool) == true);
1049 QDECREF(qbool);
1051 obj = qobject_from_json("null", &error_abort);
1052 g_assert(obj != NULL);
1053 g_assert(qobject_type(obj) == QTYPE_QNULL);
1055 null = qnull();
1056 g_assert(QOBJECT(null) == obj);
1058 qobject_decref(obj);
1059 QDECREF(null);
1062 typedef struct LiteralQDictEntry LiteralQDictEntry;
1063 typedef struct LiteralQObject LiteralQObject;
1065 struct LiteralQObject
1067 int type;
1068 union {
1069 int64_t qnum;
1070 const char *qstr;
1071 LiteralQDictEntry *qdict;
1072 LiteralQObject *qlist;
1073 } value;
1076 struct LiteralQDictEntry
1078 const char *key;
1079 LiteralQObject value;
1082 #define QLIT_QNUM(val) (LiteralQObject){.type = QTYPE_QNUM, .value.qnum = (val)}
1083 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1084 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1085 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1087 typedef struct QListCompareHelper
1089 int index;
1090 LiteralQObject *objs;
1091 int result;
1092 } QListCompareHelper;
1094 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1096 static void compare_helper(QObject *obj, void *opaque)
1098 QListCompareHelper *helper = opaque;
1100 if (helper->result == 0) {
1101 return;
1104 if (helper->objs[helper->index].type == QTYPE_NONE) {
1105 helper->result = 0;
1106 return;
1109 helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1112 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1114 int64_t val;
1116 if (!rhs || lhs->type != qobject_type(rhs)) {
1117 return 0;
1120 switch (lhs->type) {
1121 case QTYPE_QNUM:
1122 g_assert(qnum_get_try_int(qobject_to_qnum(rhs), &val));
1123 return lhs->value.qnum == val;
1124 case QTYPE_QSTRING:
1125 return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1126 case QTYPE_QDICT: {
1127 int i;
1129 for (i = 0; lhs->value.qdict[i].key; i++) {
1130 QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1132 if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1133 return 0;
1137 return 1;
1139 case QTYPE_QLIST: {
1140 QListCompareHelper helper;
1142 helper.index = 0;
1143 helper.objs = lhs->value.qlist;
1144 helper.result = 1;
1146 qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1148 return helper.result;
1150 default:
1151 break;
1154 return 0;
1157 static void simple_dict(void)
1159 int i;
1160 struct {
1161 const char *encoded;
1162 LiteralQObject decoded;
1163 } test_cases[] = {
1165 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1166 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1167 { "foo", QLIT_QNUM(42) },
1168 { "bar", QLIT_QSTR("hello world") },
1170 })),
1171 }, {
1172 .encoded = "{}",
1173 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1175 })),
1176 }, {
1177 .encoded = "{\"foo\": 43}",
1178 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1179 { "foo", QLIT_QNUM(43) },
1181 })),
1186 for (i = 0; test_cases[i].encoded; i++) {
1187 QObject *obj;
1188 QString *str;
1190 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1191 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1193 str = qobject_to_json(obj);
1194 qobject_decref(obj);
1196 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1197 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1198 qobject_decref(obj);
1199 QDECREF(str);
1204 * this generates json of the form:
1205 * a(0,m) = [0, 1, ..., m-1]
1206 * a(n,m) = {
1207 * 'key0': a(0,m),
1208 * 'key1': a(1,m),
1209 * ...
1210 * 'key(n-1)': a(n-1,m)
1213 static void gen_test_json(GString *gstr, int nest_level_max,
1214 int elem_count)
1216 int i;
1218 g_assert(gstr);
1219 if (nest_level_max == 0) {
1220 g_string_append(gstr, "[");
1221 for (i = 0; i < elem_count; i++) {
1222 g_string_append_printf(gstr, "%d", i);
1223 if (i < elem_count - 1) {
1224 g_string_append_printf(gstr, ", ");
1227 g_string_append(gstr, "]");
1228 return;
1231 g_string_append(gstr, "{");
1232 for (i = 0; i < nest_level_max; i++) {
1233 g_string_append_printf(gstr, "'key%d': ", i);
1234 gen_test_json(gstr, i, elem_count);
1235 if (i < nest_level_max - 1) {
1236 g_string_append(gstr, ",");
1239 g_string_append(gstr, "}");
1242 static void large_dict(void)
1244 GString *gstr = g_string_new("");
1245 QObject *obj;
1247 gen_test_json(gstr, 10, 100);
1248 obj = qobject_from_json(gstr->str, &error_abort);
1249 g_assert(obj != NULL);
1251 qobject_decref(obj);
1252 g_string_free(gstr, true);
1255 static void simple_list(void)
1257 int i;
1258 struct {
1259 const char *encoded;
1260 LiteralQObject decoded;
1261 } test_cases[] = {
1263 .encoded = "[43,42]",
1264 .decoded = QLIT_QLIST(((LiteralQObject[]){
1265 QLIT_QNUM(43),
1266 QLIT_QNUM(42),
1268 })),
1271 .encoded = "[43]",
1272 .decoded = QLIT_QLIST(((LiteralQObject[]){
1273 QLIT_QNUM(43),
1275 })),
1278 .encoded = "[]",
1279 .decoded = QLIT_QLIST(((LiteralQObject[]){
1281 })),
1284 .encoded = "[{}]",
1285 .decoded = QLIT_QLIST(((LiteralQObject[]){
1286 QLIT_QDICT(((LiteralQDictEntry[]){
1288 })),
1290 })),
1295 for (i = 0; test_cases[i].encoded; i++) {
1296 QObject *obj;
1297 QString *str;
1299 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1300 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1302 str = qobject_to_json(obj);
1303 qobject_decref(obj);
1305 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1306 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1307 qobject_decref(obj);
1308 QDECREF(str);
1312 static void simple_whitespace(void)
1314 int i;
1315 struct {
1316 const char *encoded;
1317 LiteralQObject decoded;
1318 } test_cases[] = {
1320 .encoded = " [ 43 , 42 ]",
1321 .decoded = QLIT_QLIST(((LiteralQObject[]){
1322 QLIT_QNUM(43),
1323 QLIT_QNUM(42),
1325 })),
1328 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1329 .decoded = QLIT_QLIST(((LiteralQObject[]){
1330 QLIT_QNUM(43),
1331 QLIT_QDICT(((LiteralQDictEntry[]){
1332 { "h", QLIT_QSTR("b") },
1333 { }})),
1334 QLIT_QLIST(((LiteralQObject[]){
1335 { }})),
1336 QLIT_QNUM(42),
1338 })),
1341 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1342 .decoded = QLIT_QLIST(((LiteralQObject[]){
1343 QLIT_QNUM(43),
1344 QLIT_QDICT(((LiteralQDictEntry[]){
1345 { "h", QLIT_QSTR("b") },
1346 { "a", QLIT_QNUM(32) },
1347 { }})),
1348 QLIT_QLIST(((LiteralQObject[]){
1349 { }})),
1350 QLIT_QNUM(42),
1352 })),
1357 for (i = 0; test_cases[i].encoded; i++) {
1358 QObject *obj;
1359 QString *str;
1361 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1362 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1364 str = qobject_to_json(obj);
1365 qobject_decref(obj);
1367 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1368 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1370 qobject_decref(obj);
1371 QDECREF(str);
1375 static void simple_varargs(void)
1377 QObject *embedded_obj;
1378 QObject *obj;
1379 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1380 QLIT_QNUM(1),
1381 QLIT_QNUM(2),
1382 QLIT_QLIST(((LiteralQObject[]){
1383 QLIT_QNUM(32),
1384 QLIT_QNUM(42),
1385 {}})),
1386 {}}));
1388 embedded_obj = qobject_from_json("[32, 42]", &error_abort);
1389 g_assert(embedded_obj != NULL);
1391 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1392 g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1394 qobject_decref(obj);
1397 static void empty_input(void)
1399 const char *empty = "";
1400 QObject *obj = qobject_from_json(empty, &error_abort);
1401 g_assert(obj == NULL);
1404 static void unterminated_string(void)
1406 Error *err = NULL;
1407 QObject *obj = qobject_from_json("\"abc", &err);
1408 g_assert(!err); /* BUG */
1409 g_assert(obj == NULL);
1412 static void unterminated_sq_string(void)
1414 Error *err = NULL;
1415 QObject *obj = qobject_from_json("'abc", &err);
1416 g_assert(!err); /* BUG */
1417 g_assert(obj == NULL);
1420 static void unterminated_escape(void)
1422 Error *err = NULL;
1423 QObject *obj = qobject_from_json("\"abc\\\"", &err);
1424 g_assert(!err); /* BUG */
1425 g_assert(obj == NULL);
1428 static void unterminated_array(void)
1430 Error *err = NULL;
1431 QObject *obj = qobject_from_json("[32", &err);
1432 g_assert(!err); /* BUG */
1433 g_assert(obj == NULL);
1436 static void unterminated_array_comma(void)
1438 Error *err = NULL;
1439 QObject *obj = qobject_from_json("[32,", &err);
1440 g_assert(!err); /* BUG */
1441 g_assert(obj == NULL);
1444 static void invalid_array_comma(void)
1446 Error *err = NULL;
1447 QObject *obj = qobject_from_json("[32,}", &err);
1448 error_free_or_abort(&err);
1449 g_assert(obj == NULL);
1452 static void unterminated_dict(void)
1454 Error *err = NULL;
1455 QObject *obj = qobject_from_json("{'abc':32", &err);
1456 g_assert(!err); /* BUG */
1457 g_assert(obj == NULL);
1460 static void unterminated_dict_comma(void)
1462 Error *err = NULL;
1463 QObject *obj = qobject_from_json("{'abc':32,", &err);
1464 g_assert(!err); /* BUG */
1465 g_assert(obj == NULL);
1468 static void invalid_dict_comma(void)
1470 Error *err = NULL;
1471 QObject *obj = qobject_from_json("{'abc':32,}", &err);
1472 error_free_or_abort(&err);
1473 g_assert(obj == NULL);
1476 static void unterminated_literal(void)
1478 Error *err = NULL;
1479 QObject *obj = qobject_from_json("nul", &err);
1480 error_free_or_abort(&err);
1481 g_assert(obj == NULL);
1484 static char *make_nest(char *buf, size_t cnt)
1486 memset(buf, '[', cnt - 1);
1487 buf[cnt - 1] = '{';
1488 buf[cnt] = '}';
1489 memset(buf + cnt + 1, ']', cnt - 1);
1490 buf[2 * cnt] = 0;
1491 return buf;
1494 static void limits_nesting(void)
1496 Error *err = NULL;
1497 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1498 char buf[2 * (max_nesting + 1) + 1];
1499 QObject *obj;
1501 obj = qobject_from_json(make_nest(buf, max_nesting), &error_abort);
1502 g_assert(obj != NULL);
1503 qobject_decref(obj);
1505 obj = qobject_from_json(make_nest(buf, max_nesting + 1), &err);
1506 error_free_or_abort(&err);
1507 g_assert(obj == NULL);
1510 int main(int argc, char **argv)
1512 g_test_init(&argc, &argv, NULL);
1514 g_test_add_func("/literals/string/simple", simple_string);
1515 g_test_add_func("/literals/string/escaped", escaped_string);
1516 g_test_add_func("/literals/string/utf8", utf8_string);
1517 g_test_add_func("/literals/string/single_quote", single_quote_string);
1518 g_test_add_func("/literals/string/vararg", vararg_string);
1520 g_test_add_func("/literals/number/simple", simple_number);
1521 g_test_add_func("/literals/number/large", large_number);
1522 g_test_add_func("/literals/number/float", float_number);
1523 g_test_add_func("/literals/number/vararg", vararg_number);
1525 g_test_add_func("/literals/keyword", keyword_literal);
1527 g_test_add_func("/dicts/simple_dict", simple_dict);
1528 g_test_add_func("/dicts/large_dict", large_dict);
1529 g_test_add_func("/lists/simple_list", simple_list);
1531 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1533 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1535 g_test_add_func("/errors/empty_input", empty_input);
1536 g_test_add_func("/errors/unterminated/string", unterminated_string);
1537 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1538 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1539 g_test_add_func("/errors/unterminated/array", unterminated_array);
1540 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1541 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1542 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1543 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1544 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1545 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1546 g_test_add_func("/errors/limits/nesting", limits_nesting);
1548 return g_test_run();