qga: fix off-by-one length check
[qemu.git] / tests / check-qjson.c
blob99de6f52527613f7b23e8937f4f1624721371cc1
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"
14 #include <glib.h>
16 #include "qapi/qmp/qstring.h"
17 #include "qapi/qmp/qint.h"
18 #include "qapi/qmp/qdict.h"
19 #include "qapi/qmp/qlist.h"
20 #include "qapi/qmp/qfloat.h"
21 #include "qapi/qmp/qbool.h"
22 #include "qapi/qmp/qjson.h"
24 #include "qemu-common.h"
26 static void escaped_string(void)
28 int i;
29 struct {
30 const char *encoded;
31 const char *decoded;
32 int skip;
33 } test_cases[] = {
34 { "\"\\b\"", "\b" },
35 { "\"\\f\"", "\f" },
36 { "\"\\n\"", "\n" },
37 { "\"\\r\"", "\r" },
38 { "\"\\t\"", "\t" },
39 { "\"/\"", "/" },
40 { "\"\\/\"", "/", .skip = 1 },
41 { "\"\\\\\"", "\\" },
42 { "\"\\\"\"", "\"" },
43 { "\"hello world \\\"embedded string\\\"\"",
44 "hello world \"embedded string\"" },
45 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
46 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
47 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
48 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
49 { "'\\b'", "\b", .skip = 1 },
50 { "'\\f'", "\f", .skip = 1 },
51 { "'\\n'", "\n", .skip = 1 },
52 { "'\\r'", "\r", .skip = 1 },
53 { "'\\t'", "\t", .skip = 1 },
54 { "'\\/'", "/", .skip = 1 },
55 { "'\\\\'", "\\", .skip = 1 },
59 for (i = 0; test_cases[i].encoded; i++) {
60 QObject *obj;
61 QString *str;
63 obj = qobject_from_json(test_cases[i].encoded);
65 g_assert(obj != NULL);
66 g_assert(qobject_type(obj) == QTYPE_QSTRING);
68 str = qobject_to_qstring(obj);
69 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
71 if (test_cases[i].skip == 0) {
72 str = qobject_to_json(obj);
73 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
74 qobject_decref(obj);
77 QDECREF(str);
81 static void simple_string(void)
83 int i;
84 struct {
85 const char *encoded;
86 const char *decoded;
87 } test_cases[] = {
88 { "\"hello world\"", "hello world" },
89 { "\"the quick brown fox jumped over the fence\"",
90 "the quick brown fox jumped over the fence" },
94 for (i = 0; test_cases[i].encoded; i++) {
95 QObject *obj;
96 QString *str;
98 obj = qobject_from_json(test_cases[i].encoded);
100 g_assert(obj != NULL);
101 g_assert(qobject_type(obj) == QTYPE_QSTRING);
103 str = qobject_to_qstring(obj);
104 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
106 str = qobject_to_json(obj);
107 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
109 qobject_decref(obj);
111 QDECREF(str);
115 static void single_quote_string(void)
117 int i;
118 struct {
119 const char *encoded;
120 const char *decoded;
121 } test_cases[] = {
122 { "'hello world'", "hello world" },
123 { "'the quick brown fox \\' jumped over the fence'",
124 "the quick brown fox ' jumped over the fence" },
128 for (i = 0; test_cases[i].encoded; i++) {
129 QObject *obj;
130 QString *str;
132 obj = qobject_from_json(test_cases[i].encoded);
134 g_assert(obj != NULL);
135 g_assert(qobject_type(obj) == QTYPE_QSTRING);
137 str = qobject_to_qstring(obj);
138 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
140 QDECREF(str);
144 static void utf8_string(void)
147 * FIXME Current behavior for invalid UTF-8 sequences is
148 * incorrect. This test expects current, incorrect results.
149 * They're all marked "bug:" below, and are to be replaced by
150 * correct ones as the bugs get fixed.
152 * The JSON parser rejects some invalid sequences, but accepts
153 * others without correcting the problem.
155 * We should either reject all invalid sequences, or minimize
156 * overlong sequences and replace all other invalid sequences by a
157 * suitable replacement character. A common choice for
158 * replacement is U+FFFD.
160 * Problem: we can't easily deal with embedded U+0000. Parsing
161 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
162 * which gets misinterpreted as NUL-terminated "this ". We should
163 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
164 * UTF-8").
166 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
167 * capability and stress test at
168 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
170 static const struct {
171 const char *json_in;
172 const char *utf8_out;
173 const char *json_out; /* defaults to @json_in */
174 const char *utf8_in; /* defaults to @utf8_out */
175 } test_cases[] = {
177 * Bug markers used here:
178 * - bug: not corrected
179 * JSON parser fails to correct invalid sequence(s)
180 * - bug: rejected
181 * JSON parser rejects invalid sequence(s)
182 * We may choose to define this as feature
183 * - bug: want "..."
184 * JSON parser produces incorrect result, this is the
185 * correct one, assuming replacement character U+FFFF
186 * We may choose to reject instead of replace
189 /* 1 Some correct UTF-8 text */
191 /* a bit of German */
192 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
193 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
194 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
195 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
196 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
197 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
200 /* a bit of Greek */
201 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
202 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
203 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
205 /* 2 Boundary condition test cases */
206 /* 2.1 First possible sequence of a certain length */
207 /* 2.1.1 1 byte U+0000 */
209 "\"\\u0000\"",
210 "", /* bug: want overlong "\xC0\x80" */
211 "\"\\u0000\"",
212 "\xC0\x80",
214 /* 2.1.2 2 bytes U+0080 */
216 "\"\xC2\x80\"",
217 "\xC2\x80",
218 "\"\\u0080\"",
220 /* 2.1.3 3 bytes U+0800 */
222 "\"\xE0\xA0\x80\"",
223 "\xE0\xA0\x80",
224 "\"\\u0800\"",
226 /* 2.1.4 4 bytes U+10000 */
228 "\"\xF0\x90\x80\x80\"",
229 "\xF0\x90\x80\x80",
230 "\"\\uD800\\uDC00\"",
232 /* 2.1.5 5 bytes U+200000 */
234 "\"\xF8\x88\x80\x80\x80\"",
235 NULL, /* bug: rejected */
236 "\"\\uFFFD\"",
237 "\xF8\x88\x80\x80\x80",
239 /* 2.1.6 6 bytes U+4000000 */
241 "\"\xFC\x84\x80\x80\x80\x80\"",
242 NULL, /* bug: rejected */
243 "\"\\uFFFD\"",
244 "\xFC\x84\x80\x80\x80\x80",
246 /* 2.2 Last possible sequence of a certain length */
247 /* 2.2.1 1 byte U+007F */
249 "\"\x7F\"",
250 "\x7F",
251 "\"\\u007F\"",
253 /* 2.2.2 2 bytes U+07FF */
255 "\"\xDF\xBF\"",
256 "\xDF\xBF",
257 "\"\\u07FF\"",
260 * 2.2.3 3 bytes U+FFFC
261 * The last possible sequence is actually U+FFFF. But that's
262 * a noncharacter, and already covered by its own test case
263 * under 5.3. Same for U+FFFE. U+FFFD is the last character
264 * in the BMP, and covered under 2.3. Because of U+FFFD's
265 * special role as replacement character, it's worth testing
266 * U+FFFC here.
269 "\"\xEF\xBF\xBC\"",
270 "\xEF\xBF\xBC",
271 "\"\\uFFFC\"",
273 /* 2.2.4 4 bytes U+1FFFFF */
275 "\"\xF7\xBF\xBF\xBF\"",
276 NULL, /* bug: rejected */
277 "\"\\uFFFD\"",
278 "\xF7\xBF\xBF\xBF",
280 /* 2.2.5 5 bytes U+3FFFFFF */
282 "\"\xFB\xBF\xBF\xBF\xBF\"",
283 NULL, /* bug: rejected */
284 "\"\\uFFFD\"",
285 "\xFB\xBF\xBF\xBF\xBF",
287 /* 2.2.6 6 bytes U+7FFFFFFF */
289 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
290 NULL, /* bug: rejected */
291 "\"\\uFFFD\"",
292 "\xFD\xBF\xBF\xBF\xBF\xBF",
294 /* 2.3 Other boundary conditions */
296 /* last one before surrogate range: U+D7FF */
297 "\"\xED\x9F\xBF\"",
298 "\xED\x9F\xBF",
299 "\"\\uD7FF\"",
302 /* first one after surrogate range: U+E000 */
303 "\"\xEE\x80\x80\"",
304 "\xEE\x80\x80",
305 "\"\\uE000\"",
308 /* last one in BMP: U+FFFD */
309 "\"\xEF\xBF\xBD\"",
310 "\xEF\xBF\xBD",
311 "\"\\uFFFD\"",
314 /* last one in last plane: U+10FFFD */
315 "\"\xF4\x8F\xBF\xBD\"",
316 "\xF4\x8F\xBF\xBD",
317 "\"\\uDBFF\\uDFFD\""
320 /* first one beyond Unicode range: U+110000 */
321 "\"\xF4\x90\x80\x80\"",
322 "\xF4\x90\x80\x80",
323 "\"\\uFFFD\"",
325 /* 3 Malformed sequences */
326 /* 3.1 Unexpected continuation bytes */
327 /* 3.1.1 First continuation byte */
329 "\"\x80\"",
330 "\x80", /* bug: not corrected */
331 "\"\\uFFFD\"",
333 /* 3.1.2 Last continuation byte */
335 "\"\xBF\"",
336 "\xBF", /* bug: not corrected */
337 "\"\\uFFFD\"",
339 /* 3.1.3 2 continuation bytes */
341 "\"\x80\xBF\"",
342 "\x80\xBF", /* bug: not corrected */
343 "\"\\uFFFD\\uFFFD\"",
345 /* 3.1.4 3 continuation bytes */
347 "\"\x80\xBF\x80\"",
348 "\x80\xBF\x80", /* bug: not corrected */
349 "\"\\uFFFD\\uFFFD\\uFFFD\"",
351 /* 3.1.5 4 continuation bytes */
353 "\"\x80\xBF\x80\xBF\"",
354 "\x80\xBF\x80\xBF", /* bug: not corrected */
355 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
357 /* 3.1.6 5 continuation bytes */
359 "\"\x80\xBF\x80\xBF\x80\"",
360 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
361 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
363 /* 3.1.7 6 continuation bytes */
365 "\"\x80\xBF\x80\xBF\x80\xBF\"",
366 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
367 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
369 /* 3.1.8 7 continuation bytes */
371 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
372 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
373 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
375 /* 3.1.9 Sequence of all 64 possible continuation bytes */
377 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
378 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
379 "\x90\x91\x92\x93\x94\x95\x96\x97"
380 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
381 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
382 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
383 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
384 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
385 /* bug: not corrected */
386 "\x80\x81\x82\x83\x84\x85\x86\x87"
387 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
388 "\x90\x91\x92\x93\x94\x95\x96\x97"
389 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
390 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
391 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
392 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
393 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
394 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
395 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
396 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
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 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
403 /* 3.2 Lonely start characters */
404 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
406 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
407 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
408 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
409 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
410 NULL, /* bug: rejected */
411 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
412 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
413 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
414 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
415 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
416 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
417 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
418 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
420 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
422 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
423 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
424 /* bug: not corrected */
425 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
426 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
427 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
428 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
430 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
432 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
433 NULL, /* bug: rejected */
434 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
435 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
437 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
439 "\"\xF8 \xF9 \xFA \xFB \"",
440 NULL, /* bug: rejected */
441 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
442 "\xF8 \xF9 \xFA \xFB ",
444 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
446 "\"\xFC \xFD \"",
447 NULL, /* bug: rejected */
448 "\"\\uFFFD \\uFFFD \"",
449 "\xFC \xFD ",
451 /* 3.3 Sequences with last continuation byte missing */
452 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
454 "\"\xC0\"",
455 NULL, /* bug: rejected */
456 "\"\\uFFFD\"",
457 "\xC0",
459 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
461 "\"\xE0\x80\"",
462 "\xE0\x80", /* bug: not corrected */
463 "\"\\uFFFD\"",
465 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
467 "\"\xF0\x80\x80\"",
468 "\xF0\x80\x80", /* bug: not corrected */
469 "\"\\uFFFD\"",
471 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
473 "\"\xF8\x80\x80\x80\"",
474 NULL, /* bug: rejected */
475 "\"\\uFFFD\"",
476 "\xF8\x80\x80\x80",
478 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
480 "\"\xFC\x80\x80\x80\x80\"",
481 NULL, /* bug: rejected */
482 "\"\\uFFFD\"",
483 "\xFC\x80\x80\x80\x80",
485 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
487 "\"\xDF\"",
488 "\xDF", /* bug: not corrected */
489 "\"\\uFFFD\"",
491 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
493 "\"\xEF\xBF\"",
494 "\xEF\xBF", /* bug: not corrected */
495 "\"\\uFFFD\"",
497 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
499 "\"\xF7\xBF\xBF\"",
500 NULL, /* bug: rejected */
501 "\"\\uFFFD\"",
502 "\xF7\xBF\xBF",
504 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
506 "\"\xFB\xBF\xBF\xBF\"",
507 NULL, /* bug: rejected */
508 "\"\\uFFFD\"",
509 "\xFB\xBF\xBF\xBF",
511 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
513 "\"\xFD\xBF\xBF\xBF\xBF\"",
514 NULL, /* bug: rejected */
515 "\"\\uFFFD\"",
516 "\xFD\xBF\xBF\xBF\xBF",
518 /* 3.4 Concatenation of incomplete sequences */
520 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
521 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
522 NULL, /* bug: rejected */
523 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
524 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
525 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
526 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
528 /* 3.5 Impossible bytes */
530 "\"\xFE\"",
531 NULL, /* bug: rejected */
532 "\"\\uFFFD\"",
533 "\xFE",
536 "\"\xFF\"",
537 NULL, /* bug: rejected */
538 "\"\\uFFFD\"",
539 "\xFF",
542 "\"\xFE\xFE\xFF\xFF\"",
543 NULL, /* bug: rejected */
544 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
545 "\xFE\xFE\xFF\xFF",
547 /* 4 Overlong sequences */
548 /* 4.1 Overlong '/' */
550 "\"\xC0\xAF\"",
551 NULL, /* bug: rejected */
552 "\"\\uFFFD\"",
553 "\xC0\xAF",
556 "\"\xE0\x80\xAF\"",
557 "\xE0\x80\xAF", /* bug: not corrected */
558 "\"\\uFFFD\"",
561 "\"\xF0\x80\x80\xAF\"",
562 "\xF0\x80\x80\xAF", /* bug: not corrected */
563 "\"\\uFFFD\"",
566 "\"\xF8\x80\x80\x80\xAF\"",
567 NULL, /* bug: rejected */
568 "\"\\uFFFD\"",
569 "\xF8\x80\x80\x80\xAF",
572 "\"\xFC\x80\x80\x80\x80\xAF\"",
573 NULL, /* bug: rejected */
574 "\"\\uFFFD\"",
575 "\xFC\x80\x80\x80\x80\xAF",
578 * 4.2 Maximum overlong sequences
579 * Highest Unicode value that is still resulting in an
580 * overlong sequence if represented with the given number of
581 * bytes. This is a boundary test for safe UTF-8 decoders.
584 /* \U+007F */
585 "\"\xC1\xBF\"",
586 NULL, /* bug: rejected */
587 "\"\\uFFFD\"",
588 "\xC1\xBF",
591 /* \U+07FF */
592 "\"\xE0\x9F\xBF\"",
593 "\xE0\x9F\xBF", /* bug: not corrected */
594 "\"\\uFFFD\"",
598 * \U+FFFC
599 * The actual maximum would be U+FFFF, but that's a
600 * noncharacter. Testing U+FFFC seems more useful. See
601 * also 2.2.3
603 "\"\xF0\x8F\xBF\xBC\"",
604 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
605 "\"\\uFFFD\"",
608 /* \U+1FFFFF */
609 "\"\xF8\x87\xBF\xBF\xBF\"",
610 NULL, /* bug: rejected */
611 "\"\\uFFFD\"",
612 "\xF8\x87\xBF\xBF\xBF",
615 /* \U+3FFFFFF */
616 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
617 NULL, /* bug: rejected */
618 "\"\\uFFFD\"",
619 "\xFC\x83\xBF\xBF\xBF\xBF",
621 /* 4.3 Overlong representation of the NUL character */
623 /* \U+0000 */
624 "\"\xC0\x80\"",
625 NULL, /* bug: rejected */
626 "\"\\u0000\"",
627 "\xC0\x80",
630 /* \U+0000 */
631 "\"\xE0\x80\x80\"",
632 "\xE0\x80\x80", /* bug: not corrected */
633 "\"\\uFFFD\"",
636 /* \U+0000 */
637 "\"\xF0\x80\x80\x80\"",
638 "\xF0\x80\x80\x80", /* bug: not corrected */
639 "\"\\uFFFD\"",
642 /* \U+0000 */
643 "\"\xF8\x80\x80\x80\x80\"",
644 NULL, /* bug: rejected */
645 "\"\\uFFFD\"",
646 "\xF8\x80\x80\x80\x80",
649 /* \U+0000 */
650 "\"\xFC\x80\x80\x80\x80\x80\"",
651 NULL, /* bug: rejected */
652 "\"\\uFFFD\"",
653 "\xFC\x80\x80\x80\x80\x80",
655 /* 5 Illegal code positions */
656 /* 5.1 Single UTF-16 surrogates */
658 /* \U+D800 */
659 "\"\xED\xA0\x80\"",
660 "\xED\xA0\x80", /* bug: not corrected */
661 "\"\\uFFFD\"",
664 /* \U+DB7F */
665 "\"\xED\xAD\xBF\"",
666 "\xED\xAD\xBF", /* bug: not corrected */
667 "\"\\uFFFD\"",
670 /* \U+DB80 */
671 "\"\xED\xAE\x80\"",
672 "\xED\xAE\x80", /* bug: not corrected */
673 "\"\\uFFFD\"",
676 /* \U+DBFF */
677 "\"\xED\xAF\xBF\"",
678 "\xED\xAF\xBF", /* bug: not corrected */
679 "\"\\uFFFD\"",
682 /* \U+DC00 */
683 "\"\xED\xB0\x80\"",
684 "\xED\xB0\x80", /* bug: not corrected */
685 "\"\\uFFFD\"",
688 /* \U+DF80 */
689 "\"\xED\xBE\x80\"",
690 "\xED\xBE\x80", /* bug: not corrected */
691 "\"\\uFFFD\"",
694 /* \U+DFFF */
695 "\"\xED\xBF\xBF\"",
696 "\xED\xBF\xBF", /* bug: not corrected */
697 "\"\\uFFFD\"",
699 /* 5.2 Paired UTF-16 surrogates */
701 /* \U+D800\U+DC00 */
702 "\"\xED\xA0\x80\xED\xB0\x80\"",
703 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
704 "\"\\uFFFD\\uFFFD\"",
707 /* \U+D800\U+DFFF */
708 "\"\xED\xA0\x80\xED\xBF\xBF\"",
709 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
710 "\"\\uFFFD\\uFFFD\"",
713 /* \U+DB7F\U+DC00 */
714 "\"\xED\xAD\xBF\xED\xB0\x80\"",
715 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
716 "\"\\uFFFD\\uFFFD\"",
719 /* \U+DB7F\U+DFFF */
720 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
721 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
722 "\"\\uFFFD\\uFFFD\"",
725 /* \U+DB80\U+DC00 */
726 "\"\xED\xAE\x80\xED\xB0\x80\"",
727 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
728 "\"\\uFFFD\\uFFFD\"",
731 /* \U+DB80\U+DFFF */
732 "\"\xED\xAE\x80\xED\xBF\xBF\"",
733 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
734 "\"\\uFFFD\\uFFFD\"",
737 /* \U+DBFF\U+DC00 */
738 "\"\xED\xAF\xBF\xED\xB0\x80\"",
739 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
740 "\"\\uFFFD\\uFFFD\"",
743 /* \U+DBFF\U+DFFF */
744 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
745 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
746 "\"\\uFFFD\\uFFFD\"",
748 /* 5.3 Other illegal code positions */
749 /* BMP noncharacters */
751 /* \U+FFFE */
752 "\"\xEF\xBF\xBE\"",
753 "\xEF\xBF\xBE", /* bug: not corrected */
754 "\"\\uFFFD\"",
757 /* \U+FFFF */
758 "\"\xEF\xBF\xBF\"",
759 "\xEF\xBF\xBF", /* bug: not corrected */
760 "\"\\uFFFD\"",
763 /* U+FDD0 */
764 "\"\xEF\xB7\x90\"",
765 "\xEF\xB7\x90", /* bug: not corrected */
766 "\"\\uFFFD\"",
769 /* U+FDEF */
770 "\"\xEF\xB7\xAF\"",
771 "\xEF\xB7\xAF", /* bug: not corrected */
772 "\"\\uFFFD\"",
774 /* Plane 1 .. 16 noncharacters */
776 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
777 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
778 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
779 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
780 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
781 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
782 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
783 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
784 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
785 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
786 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
787 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
788 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
789 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
790 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
791 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
792 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
793 /* bug: not corrected */
794 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
795 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
796 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
797 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
798 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
799 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
800 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
801 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
802 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
803 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
804 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
805 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
806 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
807 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
808 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
809 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
810 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
811 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
812 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
813 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
817 int i;
818 QObject *obj;
819 QString *str;
820 const char *json_in, *utf8_out, *utf8_in, *json_out;
822 for (i = 0; test_cases[i].json_in; i++) {
823 json_in = test_cases[i].json_in;
824 utf8_out = test_cases[i].utf8_out;
825 utf8_in = test_cases[i].utf8_in ?: test_cases[i].utf8_out;
826 json_out = test_cases[i].json_out ?: test_cases[i].json_in;
828 obj = qobject_from_json(json_in);
829 if (utf8_out) {
830 g_assert(obj);
831 g_assert(qobject_type(obj) == QTYPE_QSTRING);
832 str = qobject_to_qstring(obj);
833 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
834 } else {
835 g_assert(!obj);
837 qobject_decref(obj);
839 obj = QOBJECT(qstring_from_str(utf8_in));
840 str = qobject_to_json(obj);
841 if (json_out) {
842 g_assert(str);
843 g_assert_cmpstr(qstring_get_str(str), ==, json_out);
844 } else {
845 g_assert(!str);
847 QDECREF(str);
848 qobject_decref(obj);
851 * Disabled, because qobject_from_json() is buggy, and I can't
852 * be bothered to add the expected incorrect results.
853 * FIXME Enable once these bugs have been fixed.
855 if (0 && json_out != json_in) {
856 obj = qobject_from_json(json_out);
857 g_assert(obj);
858 g_assert(qobject_type(obj) == QTYPE_QSTRING);
859 str = qobject_to_qstring(obj);
860 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
865 static void vararg_string(void)
867 int i;
868 struct {
869 const char *decoded;
870 } test_cases[] = {
871 { "hello world" },
872 { "the quick brown fox jumped over the fence" },
876 for (i = 0; test_cases[i].decoded; i++) {
877 QObject *obj;
878 QString *str;
880 obj = qobject_from_jsonf("%s", test_cases[i].decoded);
882 g_assert(obj != NULL);
883 g_assert(qobject_type(obj) == QTYPE_QSTRING);
885 str = qobject_to_qstring(obj);
886 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
888 QDECREF(str);
892 static void simple_number(void)
894 int i;
895 struct {
896 const char *encoded;
897 int64_t decoded;
898 int skip;
899 } test_cases[] = {
900 { "0", 0 },
901 { "1234", 1234 },
902 { "1", 1 },
903 { "-32", -32 },
904 { "-0", 0, .skip = 1 },
905 { },
908 for (i = 0; test_cases[i].encoded; i++) {
909 QObject *obj;
910 QInt *qint;
912 obj = qobject_from_json(test_cases[i].encoded);
913 g_assert(obj != NULL);
914 g_assert(qobject_type(obj) == QTYPE_QINT);
916 qint = qobject_to_qint(obj);
917 g_assert(qint_get_int(qint) == test_cases[i].decoded);
918 if (test_cases[i].skip == 0) {
919 QString *str;
921 str = qobject_to_json(obj);
922 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
923 QDECREF(str);
926 QDECREF(qint);
930 static void float_number(void)
932 int i;
933 struct {
934 const char *encoded;
935 double decoded;
936 int skip;
937 } test_cases[] = {
938 { "32.43", 32.43 },
939 { "0.222", 0.222 },
940 { "-32.12313", -32.12313 },
941 { "-32.20e-10", -32.20e-10, .skip = 1 },
942 { },
945 for (i = 0; test_cases[i].encoded; i++) {
946 QObject *obj;
947 QFloat *qfloat;
949 obj = qobject_from_json(test_cases[i].encoded);
950 g_assert(obj != NULL);
951 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
953 qfloat = qobject_to_qfloat(obj);
954 g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
956 if (test_cases[i].skip == 0) {
957 QString *str;
959 str = qobject_to_json(obj);
960 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
961 QDECREF(str);
964 QDECREF(qfloat);
968 static void vararg_number(void)
970 QObject *obj;
971 QInt *qint;
972 QFloat *qfloat;
973 int value = 0x2342;
974 int64_t value64 = 0x2342342343LL;
975 double valuef = 2.323423423;
977 obj = qobject_from_jsonf("%d", value);
978 g_assert(obj != NULL);
979 g_assert(qobject_type(obj) == QTYPE_QINT);
981 qint = qobject_to_qint(obj);
982 g_assert(qint_get_int(qint) == value);
984 QDECREF(qint);
986 obj = qobject_from_jsonf("%" PRId64, value64);
987 g_assert(obj != NULL);
988 g_assert(qobject_type(obj) == QTYPE_QINT);
990 qint = qobject_to_qint(obj);
991 g_assert(qint_get_int(qint) == value64);
993 QDECREF(qint);
995 obj = qobject_from_jsonf("%f", valuef);
996 g_assert(obj != NULL);
997 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
999 qfloat = qobject_to_qfloat(obj);
1000 g_assert(qfloat_get_double(qfloat) == valuef);
1002 QDECREF(qfloat);
1005 static void keyword_literal(void)
1007 QObject *obj;
1008 QBool *qbool;
1009 QObject *null;
1010 QString *str;
1012 obj = qobject_from_json("true");
1013 g_assert(obj != NULL);
1014 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1016 qbool = qobject_to_qbool(obj);
1017 g_assert(qbool_get_bool(qbool) == true);
1019 str = qobject_to_json(obj);
1020 g_assert(strcmp(qstring_get_str(str), "true") == 0);
1021 QDECREF(str);
1023 QDECREF(qbool);
1025 obj = qobject_from_json("false");
1026 g_assert(obj != NULL);
1027 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1029 qbool = qobject_to_qbool(obj);
1030 g_assert(qbool_get_bool(qbool) == false);
1032 str = qobject_to_json(obj);
1033 g_assert(strcmp(qstring_get_str(str), "false") == 0);
1034 QDECREF(str);
1036 QDECREF(qbool);
1038 obj = qobject_from_jsonf("%i", false);
1039 g_assert(obj != NULL);
1040 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1042 qbool = qobject_to_qbool(obj);
1043 g_assert(qbool_get_bool(qbool) == false);
1045 QDECREF(qbool);
1047 /* Test that non-zero values other than 1 get collapsed to true */
1048 obj = qobject_from_jsonf("%i", 2);
1049 g_assert(obj != NULL);
1050 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1052 qbool = qobject_to_qbool(obj);
1053 g_assert(qbool_get_bool(qbool) == true);
1055 QDECREF(qbool);
1057 obj = qobject_from_json("null");
1058 g_assert(obj != NULL);
1059 g_assert(qobject_type(obj) == QTYPE_QNULL);
1061 null = qnull();
1062 g_assert(null == obj);
1064 qobject_decref(obj);
1065 qobject_decref(null);
1068 typedef struct LiteralQDictEntry LiteralQDictEntry;
1069 typedef struct LiteralQObject LiteralQObject;
1071 struct LiteralQObject
1073 int type;
1074 union {
1075 int64_t qint;
1076 const char *qstr;
1077 LiteralQDictEntry *qdict;
1078 LiteralQObject *qlist;
1079 } value;
1082 struct LiteralQDictEntry
1084 const char *key;
1085 LiteralQObject value;
1088 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1089 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1090 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1091 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1093 typedef struct QListCompareHelper
1095 int index;
1096 LiteralQObject *objs;
1097 int result;
1098 } QListCompareHelper;
1100 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1102 static void compare_helper(QObject *obj, void *opaque)
1104 QListCompareHelper *helper = opaque;
1106 if (helper->result == 0) {
1107 return;
1110 if (helper->objs[helper->index].type == QTYPE_NONE) {
1111 helper->result = 0;
1112 return;
1115 helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1118 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1120 if (lhs->type != qobject_type(rhs)) {
1121 return 0;
1124 switch (lhs->type) {
1125 case QTYPE_QINT:
1126 return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
1127 case QTYPE_QSTRING:
1128 return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1129 case QTYPE_QDICT: {
1130 int i;
1132 for (i = 0; lhs->value.qdict[i].key; i++) {
1133 QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1135 if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1136 return 0;
1140 return 1;
1142 case QTYPE_QLIST: {
1143 QListCompareHelper helper;
1145 helper.index = 0;
1146 helper.objs = lhs->value.qlist;
1147 helper.result = 1;
1149 qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1151 return helper.result;
1153 default:
1154 break;
1157 return 0;
1160 static void simple_dict(void)
1162 int i;
1163 struct {
1164 const char *encoded;
1165 LiteralQObject decoded;
1166 } test_cases[] = {
1168 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1169 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1170 { "foo", QLIT_QINT(42) },
1171 { "bar", QLIT_QSTR("hello world") },
1173 })),
1174 }, {
1175 .encoded = "{}",
1176 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1178 })),
1179 }, {
1180 .encoded = "{\"foo\": 43}",
1181 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1182 { "foo", QLIT_QINT(43) },
1184 })),
1189 for (i = 0; test_cases[i].encoded; i++) {
1190 QObject *obj;
1191 QString *str;
1193 obj = qobject_from_json(test_cases[i].encoded);
1194 g_assert(obj != NULL);
1195 g_assert(qobject_type(obj) == QTYPE_QDICT);
1197 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1199 str = qobject_to_json(obj);
1200 qobject_decref(obj);
1202 obj = qobject_from_json(qstring_get_str(str));
1203 g_assert(obj != NULL);
1204 g_assert(qobject_type(obj) == QTYPE_QDICT);
1206 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1207 qobject_decref(obj);
1208 QDECREF(str);
1213 * this generates json of the form:
1214 * a(0,m) = [0, 1, ..., m-1]
1215 * a(n,m) = {
1216 * 'key0': a(0,m),
1217 * 'key1': a(1,m),
1218 * ...
1219 * 'key(n-1)': a(n-1,m)
1222 static void gen_test_json(GString *gstr, int nest_level_max,
1223 int elem_count)
1225 int i;
1227 g_assert(gstr);
1228 if (nest_level_max == 0) {
1229 g_string_append(gstr, "[");
1230 for (i = 0; i < elem_count; i++) {
1231 g_string_append_printf(gstr, "%d", i);
1232 if (i < elem_count - 1) {
1233 g_string_append_printf(gstr, ", ");
1236 g_string_append(gstr, "]");
1237 return;
1240 g_string_append(gstr, "{");
1241 for (i = 0; i < nest_level_max; i++) {
1242 g_string_append_printf(gstr, "'key%d': ", i);
1243 gen_test_json(gstr, i, elem_count);
1244 if (i < nest_level_max - 1) {
1245 g_string_append(gstr, ",");
1248 g_string_append(gstr, "}");
1251 static void large_dict(void)
1253 GString *gstr = g_string_new("");
1254 QObject *obj;
1256 gen_test_json(gstr, 10, 100);
1257 obj = qobject_from_json(gstr->str);
1258 g_assert(obj != NULL);
1260 qobject_decref(obj);
1261 g_string_free(gstr, true);
1264 static void simple_list(void)
1266 int i;
1267 struct {
1268 const char *encoded;
1269 LiteralQObject decoded;
1270 } test_cases[] = {
1272 .encoded = "[43,42]",
1273 .decoded = QLIT_QLIST(((LiteralQObject[]){
1274 QLIT_QINT(43),
1275 QLIT_QINT(42),
1277 })),
1280 .encoded = "[43]",
1281 .decoded = QLIT_QLIST(((LiteralQObject[]){
1282 QLIT_QINT(43),
1284 })),
1287 .encoded = "[]",
1288 .decoded = QLIT_QLIST(((LiteralQObject[]){
1290 })),
1293 .encoded = "[{}]",
1294 .decoded = QLIT_QLIST(((LiteralQObject[]){
1295 QLIT_QDICT(((LiteralQDictEntry[]){
1297 })),
1299 })),
1304 for (i = 0; test_cases[i].encoded; i++) {
1305 QObject *obj;
1306 QString *str;
1308 obj = qobject_from_json(test_cases[i].encoded);
1309 g_assert(obj != NULL);
1310 g_assert(qobject_type(obj) == QTYPE_QLIST);
1312 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1314 str = qobject_to_json(obj);
1315 qobject_decref(obj);
1317 obj = qobject_from_json(qstring_get_str(str));
1318 g_assert(obj != NULL);
1319 g_assert(qobject_type(obj) == QTYPE_QLIST);
1321 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1322 qobject_decref(obj);
1323 QDECREF(str);
1327 static void simple_whitespace(void)
1329 int i;
1330 struct {
1331 const char *encoded;
1332 LiteralQObject decoded;
1333 } test_cases[] = {
1335 .encoded = " [ 43 , 42 ]",
1336 .decoded = QLIT_QLIST(((LiteralQObject[]){
1337 QLIT_QINT(43),
1338 QLIT_QINT(42),
1340 })),
1343 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1344 .decoded = QLIT_QLIST(((LiteralQObject[]){
1345 QLIT_QINT(43),
1346 QLIT_QDICT(((LiteralQDictEntry[]){
1347 { "h", QLIT_QSTR("b") },
1348 { }})),
1349 QLIT_QLIST(((LiteralQObject[]){
1350 { }})),
1351 QLIT_QINT(42),
1353 })),
1356 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1357 .decoded = QLIT_QLIST(((LiteralQObject[]){
1358 QLIT_QINT(43),
1359 QLIT_QDICT(((LiteralQDictEntry[]){
1360 { "h", QLIT_QSTR("b") },
1361 { "a", QLIT_QINT(32) },
1362 { }})),
1363 QLIT_QLIST(((LiteralQObject[]){
1364 { }})),
1365 QLIT_QINT(42),
1367 })),
1372 for (i = 0; test_cases[i].encoded; i++) {
1373 QObject *obj;
1374 QString *str;
1376 obj = qobject_from_json(test_cases[i].encoded);
1377 g_assert(obj != NULL);
1378 g_assert(qobject_type(obj) == QTYPE_QLIST);
1380 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1382 str = qobject_to_json(obj);
1383 qobject_decref(obj);
1385 obj = qobject_from_json(qstring_get_str(str));
1386 g_assert(obj != NULL);
1387 g_assert(qobject_type(obj) == QTYPE_QLIST);
1389 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1391 qobject_decref(obj);
1392 QDECREF(str);
1396 static void simple_varargs(void)
1398 QObject *embedded_obj;
1399 QObject *obj;
1400 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1401 QLIT_QINT(1),
1402 QLIT_QINT(2),
1403 QLIT_QLIST(((LiteralQObject[]){
1404 QLIT_QINT(32),
1405 QLIT_QINT(42),
1406 {}})),
1407 {}}));
1409 embedded_obj = qobject_from_json("[32, 42]");
1410 g_assert(embedded_obj != NULL);
1412 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1413 g_assert(obj != NULL);
1415 g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1417 qobject_decref(obj);
1420 static void empty_input(void)
1422 const char *empty = "";
1424 QObject *obj = qobject_from_json(empty);
1425 g_assert(obj == NULL);
1428 static void unterminated_string(void)
1430 QObject *obj = qobject_from_json("\"abc");
1431 g_assert(obj == NULL);
1434 static void unterminated_sq_string(void)
1436 QObject *obj = qobject_from_json("'abc");
1437 g_assert(obj == NULL);
1440 static void unterminated_escape(void)
1442 QObject *obj = qobject_from_json("\"abc\\\"");
1443 g_assert(obj == NULL);
1446 static void unterminated_array(void)
1448 QObject *obj = qobject_from_json("[32");
1449 g_assert(obj == NULL);
1452 static void unterminated_array_comma(void)
1454 QObject *obj = qobject_from_json("[32,");
1455 g_assert(obj == NULL);
1458 static void invalid_array_comma(void)
1460 QObject *obj = qobject_from_json("[32,}");
1461 g_assert(obj == NULL);
1464 static void unterminated_dict(void)
1466 QObject *obj = qobject_from_json("{'abc':32");
1467 g_assert(obj == NULL);
1470 static void unterminated_dict_comma(void)
1472 QObject *obj = qobject_from_json("{'abc':32,");
1473 g_assert(obj == NULL);
1476 static void invalid_dict_comma(void)
1478 QObject *obj = qobject_from_json("{'abc':32,}");
1479 g_assert(obj == NULL);
1482 static void unterminated_literal(void)
1484 QObject *obj = qobject_from_json("nul");
1485 g_assert(obj == NULL);
1488 static char *make_nest(char *buf, size_t cnt)
1490 memset(buf, '[', cnt - 1);
1491 buf[cnt - 1] = '{';
1492 buf[cnt] = '}';
1493 memset(buf + cnt + 1, ']', cnt - 1);
1494 buf[2 * cnt] = 0;
1495 return buf;
1498 static void limits_nesting(void)
1500 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1501 char buf[2 * (max_nesting + 1) + 1];
1502 QObject *obj;
1504 obj = qobject_from_json(make_nest(buf, max_nesting));
1505 g_assert(obj != NULL);
1506 qobject_decref(obj);
1508 obj = qobject_from_json(make_nest(buf, max_nesting + 1));
1509 g_assert(obj == NULL);
1512 int main(int argc, char **argv)
1514 g_test_init(&argc, &argv, NULL);
1516 g_test_add_func("/literals/string/simple", simple_string);
1517 g_test_add_func("/literals/string/escaped", escaped_string);
1518 g_test_add_func("/literals/string/utf8", utf8_string);
1519 g_test_add_func("/literals/string/single_quote", single_quote_string);
1520 g_test_add_func("/literals/string/vararg", vararg_string);
1522 g_test_add_func("/literals/number/simple", simple_number);
1523 g_test_add_func("/literals/number/float", float_number);
1524 g_test_add_func("/literals/number/vararg", vararg_number);
1526 g_test_add_func("/literals/keyword", keyword_literal);
1528 g_test_add_func("/dicts/simple_dict", simple_dict);
1529 g_test_add_func("/dicts/large_dict", large_dict);
1530 g_test_add_func("/lists/simple_list", simple_list);
1532 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1534 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1536 g_test_add_func("/errors/empty_input", empty_input);
1537 g_test_add_func("/errors/unterminated/string", unterminated_string);
1538 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1539 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1540 g_test_add_func("/errors/unterminated/array", unterminated_array);
1541 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1542 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1543 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1544 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1545 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1546 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1547 g_test_add_func("/errors/limits/nesting", limits_nesting);
1549 return g_test_run();