]> git.proxmox.com Git - mirror_qemu.git/blob - tests/check-qjson.c
Merge remote-tracking branch 'remotes/armbru/tags/pull-misc-2018-02-07-v4' into staging
[mirror_qemu.git] / tests / check-qjson.c
1 /*
2 * Copyright IBM, Corp. 2009
3 * Copyright (c) 2013, 2015 Red Hat Inc.
4 *
5 * Authors:
6 * Anthony Liguori <aliguori@us.ibm.com>
7 * Markus Armbruster <armbru@redhat.com>
8 *
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.
11 *
12 */
13
14 #include "qemu/osdep.h"
15
16 #include "qapi/error.h"
17 #include "qapi/qmp/qbool.h"
18 #include "qapi/qmp/qjson.h"
19 #include "qapi/qmp/qlit.h"
20 #include "qapi/qmp/qnull.h"
21 #include "qapi/qmp/qnum.h"
22 #include "qapi/qmp/qstring.h"
23 #include "qemu-common.h"
24
25 static void escaped_string(void)
26 {
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" },
48 { "'\\b'", "\b", .skip = 1 },
49 { "'\\f'", "\f", .skip = 1 },
50 { "'\\n'", "\n", .skip = 1 },
51 { "'\\r'", "\r", .skip = 1 },
52 { "'\\t'", "\t", .skip = 1 },
53 { "'\\/'", "/", .skip = 1 },
54 { "'\\\\'", "\\", .skip = 1 },
55 {}
56 };
57
58 for (i = 0; test_cases[i].encoded; i++) {
59 QObject *obj;
60 QString *str;
61
62 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
63 str = qobject_to_qstring(obj);
64 g_assert(str);
65 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
66
67 if (test_cases[i].skip == 0) {
68 str = qobject_to_json(obj);
69 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
70 qobject_decref(obj);
71 }
72
73 QDECREF(str);
74 }
75 }
76
77 static void simple_string(void)
78 {
79 int i;
80 struct {
81 const char *encoded;
82 const char *decoded;
83 } test_cases[] = {
84 { "\"hello world\"", "hello world" },
85 { "\"the quick brown fox jumped over the fence\"",
86 "the quick brown fox jumped over the fence" },
87 {}
88 };
89
90 for (i = 0; test_cases[i].encoded; i++) {
91 QObject *obj;
92 QString *str;
93
94 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
95 str = qobject_to_qstring(obj);
96 g_assert(str);
97 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
98
99 str = qobject_to_json(obj);
100 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
101
102 qobject_decref(obj);
103
104 QDECREF(str);
105 }
106 }
107
108 static void single_quote_string(void)
109 {
110 int i;
111 struct {
112 const char *encoded;
113 const char *decoded;
114 } test_cases[] = {
115 { "'hello world'", "hello world" },
116 { "'the quick brown fox \\' jumped over the fence'",
117 "the quick brown fox ' jumped over the fence" },
118 {}
119 };
120
121 for (i = 0; test_cases[i].encoded; i++) {
122 QObject *obj;
123 QString *str;
124
125 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
126 str = qobject_to_qstring(obj);
127 g_assert(str);
128 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
129
130 QDECREF(str);
131 }
132 }
133
134 static void utf8_string(void)
135 {
136 /*
137 * FIXME Current behavior for invalid UTF-8 sequences is
138 * incorrect. This test expects current, incorrect results.
139 * They're all marked "bug:" below, and are to be replaced by
140 * correct ones as the bugs get fixed.
141 *
142 * The JSON parser rejects some invalid sequences, but accepts
143 * others without correcting the problem.
144 *
145 * We should either reject all invalid sequences, or minimize
146 * overlong sequences and replace all other invalid sequences by a
147 * suitable replacement character. A common choice for
148 * replacement is U+FFFD.
149 *
150 * Problem: we can't easily deal with embedded U+0000. Parsing
151 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
152 * which gets misinterpreted as NUL-terminated "this ". We should
153 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
154 * UTF-8").
155 *
156 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
157 * capability and stress test at
158 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
159 */
160 static const struct {
161 const char *json_in;
162 const char *utf8_out;
163 const char *json_out; /* defaults to @json_in */
164 const char *utf8_in; /* defaults to @utf8_out */
165 } test_cases[] = {
166 /*
167 * Bug markers used here:
168 * - bug: not corrected
169 * JSON parser fails to correct invalid sequence(s)
170 * - bug: rejected
171 * JSON parser rejects invalid sequence(s)
172 * We may choose to define this as feature
173 * - bug: want "..."
174 * JSON parser produces incorrect result, this is the
175 * correct one, assuming replacement character U+FFFF
176 * We may choose to reject instead of replace
177 */
178
179 /* 1 Some correct UTF-8 text */
180 {
181 /* a bit of German */
182 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
183 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
184 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
185 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
186 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
187 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
188 },
189 {
190 /* a bit of Greek */
191 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
192 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
193 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
194 },
195 /* 2 Boundary condition test cases */
196 /* 2.1 First possible sequence of a certain length */
197 /* 2.1.1 1 byte U+0000 */
198 {
199 "\"\\u0000\"",
200 "", /* bug: want overlong "\xC0\x80" */
201 "\"\\u0000\"",
202 "\xC0\x80",
203 },
204 /* 2.1.2 2 bytes U+0080 */
205 {
206 "\"\xC2\x80\"",
207 "\xC2\x80",
208 "\"\\u0080\"",
209 },
210 /* 2.1.3 3 bytes U+0800 */
211 {
212 "\"\xE0\xA0\x80\"",
213 "\xE0\xA0\x80",
214 "\"\\u0800\"",
215 },
216 /* 2.1.4 4 bytes U+10000 */
217 {
218 "\"\xF0\x90\x80\x80\"",
219 "\xF0\x90\x80\x80",
220 "\"\\uD800\\uDC00\"",
221 },
222 /* 2.1.5 5 bytes U+200000 */
223 {
224 "\"\xF8\x88\x80\x80\x80\"",
225 NULL, /* bug: rejected */
226 "\"\\uFFFD\"",
227 "\xF8\x88\x80\x80\x80",
228 },
229 /* 2.1.6 6 bytes U+4000000 */
230 {
231 "\"\xFC\x84\x80\x80\x80\x80\"",
232 NULL, /* bug: rejected */
233 "\"\\uFFFD\"",
234 "\xFC\x84\x80\x80\x80\x80",
235 },
236 /* 2.2 Last possible sequence of a certain length */
237 /* 2.2.1 1 byte U+007F */
238 {
239 "\"\x7F\"",
240 "\x7F",
241 "\"\\u007F\"",
242 },
243 /* 2.2.2 2 bytes U+07FF */
244 {
245 "\"\xDF\xBF\"",
246 "\xDF\xBF",
247 "\"\\u07FF\"",
248 },
249 /*
250 * 2.2.3 3 bytes U+FFFC
251 * The last possible sequence is actually U+FFFF. But that's
252 * a noncharacter, and already covered by its own test case
253 * under 5.3. Same for U+FFFE. U+FFFD is the last character
254 * in the BMP, and covered under 2.3. Because of U+FFFD's
255 * special role as replacement character, it's worth testing
256 * U+FFFC here.
257 */
258 {
259 "\"\xEF\xBF\xBC\"",
260 "\xEF\xBF\xBC",
261 "\"\\uFFFC\"",
262 },
263 /* 2.2.4 4 bytes U+1FFFFF */
264 {
265 "\"\xF7\xBF\xBF\xBF\"",
266 NULL, /* bug: rejected */
267 "\"\\uFFFD\"",
268 "\xF7\xBF\xBF\xBF",
269 },
270 /* 2.2.5 5 bytes U+3FFFFFF */
271 {
272 "\"\xFB\xBF\xBF\xBF\xBF\"",
273 NULL, /* bug: rejected */
274 "\"\\uFFFD\"",
275 "\xFB\xBF\xBF\xBF\xBF",
276 },
277 /* 2.2.6 6 bytes U+7FFFFFFF */
278 {
279 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
280 NULL, /* bug: rejected */
281 "\"\\uFFFD\"",
282 "\xFD\xBF\xBF\xBF\xBF\xBF",
283 },
284 /* 2.3 Other boundary conditions */
285 {
286 /* last one before surrogate range: U+D7FF */
287 "\"\xED\x9F\xBF\"",
288 "\xED\x9F\xBF",
289 "\"\\uD7FF\"",
290 },
291 {
292 /* first one after surrogate range: U+E000 */
293 "\"\xEE\x80\x80\"",
294 "\xEE\x80\x80",
295 "\"\\uE000\"",
296 },
297 {
298 /* last one in BMP: U+FFFD */
299 "\"\xEF\xBF\xBD\"",
300 "\xEF\xBF\xBD",
301 "\"\\uFFFD\"",
302 },
303 {
304 /* last one in last plane: U+10FFFD */
305 "\"\xF4\x8F\xBF\xBD\"",
306 "\xF4\x8F\xBF\xBD",
307 "\"\\uDBFF\\uDFFD\""
308 },
309 {
310 /* first one beyond Unicode range: U+110000 */
311 "\"\xF4\x90\x80\x80\"",
312 "\xF4\x90\x80\x80",
313 "\"\\uFFFD\"",
314 },
315 /* 3 Malformed sequences */
316 /* 3.1 Unexpected continuation bytes */
317 /* 3.1.1 First continuation byte */
318 {
319 "\"\x80\"",
320 "\x80", /* bug: not corrected */
321 "\"\\uFFFD\"",
322 },
323 /* 3.1.2 Last continuation byte */
324 {
325 "\"\xBF\"",
326 "\xBF", /* bug: not corrected */
327 "\"\\uFFFD\"",
328 },
329 /* 3.1.3 2 continuation bytes */
330 {
331 "\"\x80\xBF\"",
332 "\x80\xBF", /* bug: not corrected */
333 "\"\\uFFFD\\uFFFD\"",
334 },
335 /* 3.1.4 3 continuation bytes */
336 {
337 "\"\x80\xBF\x80\"",
338 "\x80\xBF\x80", /* bug: not corrected */
339 "\"\\uFFFD\\uFFFD\\uFFFD\"",
340 },
341 /* 3.1.5 4 continuation bytes */
342 {
343 "\"\x80\xBF\x80\xBF\"",
344 "\x80\xBF\x80\xBF", /* bug: not corrected */
345 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
346 },
347 /* 3.1.6 5 continuation bytes */
348 {
349 "\"\x80\xBF\x80\xBF\x80\"",
350 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
351 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
352 },
353 /* 3.1.7 6 continuation bytes */
354 {
355 "\"\x80\xBF\x80\xBF\x80\xBF\"",
356 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
357 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
358 },
359 /* 3.1.8 7 continuation bytes */
360 {
361 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
362 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
363 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
364 },
365 /* 3.1.9 Sequence of all 64 possible continuation bytes */
366 {
367 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
368 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
369 "\x90\x91\x92\x93\x94\x95\x96\x97"
370 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
371 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
372 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
373 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
374 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
375 /* bug: not corrected */
376 "\x80\x81\x82\x83\x84\x85\x86\x87"
377 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
378 "\x90\x91\x92\x93\x94\x95\x96\x97"
379 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
380 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
381 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
382 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
383 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
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"
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 },
393 /* 3.2 Lonely start characters */
394 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
395 {
396 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
397 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
398 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
399 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
400 NULL, /* bug: rejected */
401 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
402 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
403 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
404 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
405 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
406 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
407 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
408 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
409 },
410 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
411 {
412 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
413 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
414 /* bug: not corrected */
415 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
416 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
417 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
418 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
419 },
420 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
421 {
422 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
423 NULL, /* bug: rejected */
424 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
425 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
426 },
427 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
428 {
429 "\"\xF8 \xF9 \xFA \xFB \"",
430 NULL, /* bug: rejected */
431 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
432 "\xF8 \xF9 \xFA \xFB ",
433 },
434 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
435 {
436 "\"\xFC \xFD \"",
437 NULL, /* bug: rejected */
438 "\"\\uFFFD \\uFFFD \"",
439 "\xFC \xFD ",
440 },
441 /* 3.3 Sequences with last continuation byte missing */
442 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
443 {
444 "\"\xC0\"",
445 NULL, /* bug: rejected */
446 "\"\\uFFFD\"",
447 "\xC0",
448 },
449 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
450 {
451 "\"\xE0\x80\"",
452 "\xE0\x80", /* bug: not corrected */
453 "\"\\uFFFD\"",
454 },
455 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
456 {
457 "\"\xF0\x80\x80\"",
458 "\xF0\x80\x80", /* bug: not corrected */
459 "\"\\uFFFD\"",
460 },
461 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
462 {
463 "\"\xF8\x80\x80\x80\"",
464 NULL, /* bug: rejected */
465 "\"\\uFFFD\"",
466 "\xF8\x80\x80\x80",
467 },
468 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
469 {
470 "\"\xFC\x80\x80\x80\x80\"",
471 NULL, /* bug: rejected */
472 "\"\\uFFFD\"",
473 "\xFC\x80\x80\x80\x80",
474 },
475 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
476 {
477 "\"\xDF\"",
478 "\xDF", /* bug: not corrected */
479 "\"\\uFFFD\"",
480 },
481 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
482 {
483 "\"\xEF\xBF\"",
484 "\xEF\xBF", /* bug: not corrected */
485 "\"\\uFFFD\"",
486 },
487 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
488 {
489 "\"\xF7\xBF\xBF\"",
490 NULL, /* bug: rejected */
491 "\"\\uFFFD\"",
492 "\xF7\xBF\xBF",
493 },
494 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
495 {
496 "\"\xFB\xBF\xBF\xBF\"",
497 NULL, /* bug: rejected */
498 "\"\\uFFFD\"",
499 "\xFB\xBF\xBF\xBF",
500 },
501 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
502 {
503 "\"\xFD\xBF\xBF\xBF\xBF\"",
504 NULL, /* bug: rejected */
505 "\"\\uFFFD\"",
506 "\xFD\xBF\xBF\xBF\xBF",
507 },
508 /* 3.4 Concatenation of incomplete sequences */
509 {
510 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
511 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
512 NULL, /* bug: rejected */
513 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
514 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
515 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
516 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
517 },
518 /* 3.5 Impossible bytes */
519 {
520 "\"\xFE\"",
521 NULL, /* bug: rejected */
522 "\"\\uFFFD\"",
523 "\xFE",
524 },
525 {
526 "\"\xFF\"",
527 NULL, /* bug: rejected */
528 "\"\\uFFFD\"",
529 "\xFF",
530 },
531 {
532 "\"\xFE\xFE\xFF\xFF\"",
533 NULL, /* bug: rejected */
534 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
535 "\xFE\xFE\xFF\xFF",
536 },
537 /* 4 Overlong sequences */
538 /* 4.1 Overlong '/' */
539 {
540 "\"\xC0\xAF\"",
541 NULL, /* bug: rejected */
542 "\"\\uFFFD\"",
543 "\xC0\xAF",
544 },
545 {
546 "\"\xE0\x80\xAF\"",
547 "\xE0\x80\xAF", /* bug: not corrected */
548 "\"\\uFFFD\"",
549 },
550 {
551 "\"\xF0\x80\x80\xAF\"",
552 "\xF0\x80\x80\xAF", /* bug: not corrected */
553 "\"\\uFFFD\"",
554 },
555 {
556 "\"\xF8\x80\x80\x80\xAF\"",
557 NULL, /* bug: rejected */
558 "\"\\uFFFD\"",
559 "\xF8\x80\x80\x80\xAF",
560 },
561 {
562 "\"\xFC\x80\x80\x80\x80\xAF\"",
563 NULL, /* bug: rejected */
564 "\"\\uFFFD\"",
565 "\xFC\x80\x80\x80\x80\xAF",
566 },
567 /*
568 * 4.2 Maximum overlong sequences
569 * Highest Unicode value that is still resulting in an
570 * overlong sequence if represented with the given number of
571 * bytes. This is a boundary test for safe UTF-8 decoders.
572 */
573 {
574 /* \U+007F */
575 "\"\xC1\xBF\"",
576 NULL, /* bug: rejected */
577 "\"\\uFFFD\"",
578 "\xC1\xBF",
579 },
580 {
581 /* \U+07FF */
582 "\"\xE0\x9F\xBF\"",
583 "\xE0\x9F\xBF", /* bug: not corrected */
584 "\"\\uFFFD\"",
585 },
586 {
587 /*
588 * \U+FFFC
589 * The actual maximum would be U+FFFF, but that's a
590 * noncharacter. Testing U+FFFC seems more useful. See
591 * also 2.2.3
592 */
593 "\"\xF0\x8F\xBF\xBC\"",
594 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
595 "\"\\uFFFD\"",
596 },
597 {
598 /* \U+1FFFFF */
599 "\"\xF8\x87\xBF\xBF\xBF\"",
600 NULL, /* bug: rejected */
601 "\"\\uFFFD\"",
602 "\xF8\x87\xBF\xBF\xBF",
603 },
604 {
605 /* \U+3FFFFFF */
606 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
607 NULL, /* bug: rejected */
608 "\"\\uFFFD\"",
609 "\xFC\x83\xBF\xBF\xBF\xBF",
610 },
611 /* 4.3 Overlong representation of the NUL character */
612 {
613 /* \U+0000 */
614 "\"\xC0\x80\"",
615 NULL, /* bug: rejected */
616 "\"\\u0000\"",
617 "\xC0\x80",
618 },
619 {
620 /* \U+0000 */
621 "\"\xE0\x80\x80\"",
622 "\xE0\x80\x80", /* bug: not corrected */
623 "\"\\uFFFD\"",
624 },
625 {
626 /* \U+0000 */
627 "\"\xF0\x80\x80\x80\"",
628 "\xF0\x80\x80\x80", /* bug: not corrected */
629 "\"\\uFFFD\"",
630 },
631 {
632 /* \U+0000 */
633 "\"\xF8\x80\x80\x80\x80\"",
634 NULL, /* bug: rejected */
635 "\"\\uFFFD\"",
636 "\xF8\x80\x80\x80\x80",
637 },
638 {
639 /* \U+0000 */
640 "\"\xFC\x80\x80\x80\x80\x80\"",
641 NULL, /* bug: rejected */
642 "\"\\uFFFD\"",
643 "\xFC\x80\x80\x80\x80\x80",
644 },
645 /* 5 Illegal code positions */
646 /* 5.1 Single UTF-16 surrogates */
647 {
648 /* \U+D800 */
649 "\"\xED\xA0\x80\"",
650 "\xED\xA0\x80", /* bug: not corrected */
651 "\"\\uFFFD\"",
652 },
653 {
654 /* \U+DB7F */
655 "\"\xED\xAD\xBF\"",
656 "\xED\xAD\xBF", /* bug: not corrected */
657 "\"\\uFFFD\"",
658 },
659 {
660 /* \U+DB80 */
661 "\"\xED\xAE\x80\"",
662 "\xED\xAE\x80", /* bug: not corrected */
663 "\"\\uFFFD\"",
664 },
665 {
666 /* \U+DBFF */
667 "\"\xED\xAF\xBF\"",
668 "\xED\xAF\xBF", /* bug: not corrected */
669 "\"\\uFFFD\"",
670 },
671 {
672 /* \U+DC00 */
673 "\"\xED\xB0\x80\"",
674 "\xED\xB0\x80", /* bug: not corrected */
675 "\"\\uFFFD\"",
676 },
677 {
678 /* \U+DF80 */
679 "\"\xED\xBE\x80\"",
680 "\xED\xBE\x80", /* bug: not corrected */
681 "\"\\uFFFD\"",
682 },
683 {
684 /* \U+DFFF */
685 "\"\xED\xBF\xBF\"",
686 "\xED\xBF\xBF", /* bug: not corrected */
687 "\"\\uFFFD\"",
688 },
689 /* 5.2 Paired UTF-16 surrogates */
690 {
691 /* \U+D800\U+DC00 */
692 "\"\xED\xA0\x80\xED\xB0\x80\"",
693 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
694 "\"\\uFFFD\\uFFFD\"",
695 },
696 {
697 /* \U+D800\U+DFFF */
698 "\"\xED\xA0\x80\xED\xBF\xBF\"",
699 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
700 "\"\\uFFFD\\uFFFD\"",
701 },
702 {
703 /* \U+DB7F\U+DC00 */
704 "\"\xED\xAD\xBF\xED\xB0\x80\"",
705 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
706 "\"\\uFFFD\\uFFFD\"",
707 },
708 {
709 /* \U+DB7F\U+DFFF */
710 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
711 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
712 "\"\\uFFFD\\uFFFD\"",
713 },
714 {
715 /* \U+DB80\U+DC00 */
716 "\"\xED\xAE\x80\xED\xB0\x80\"",
717 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
718 "\"\\uFFFD\\uFFFD\"",
719 },
720 {
721 /* \U+DB80\U+DFFF */
722 "\"\xED\xAE\x80\xED\xBF\xBF\"",
723 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
724 "\"\\uFFFD\\uFFFD\"",
725 },
726 {
727 /* \U+DBFF\U+DC00 */
728 "\"\xED\xAF\xBF\xED\xB0\x80\"",
729 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
730 "\"\\uFFFD\\uFFFD\"",
731 },
732 {
733 /* \U+DBFF\U+DFFF */
734 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
735 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
736 "\"\\uFFFD\\uFFFD\"",
737 },
738 /* 5.3 Other illegal code positions */
739 /* BMP noncharacters */
740 {
741 /* \U+FFFE */
742 "\"\xEF\xBF\xBE\"",
743 "\xEF\xBF\xBE", /* bug: not corrected */
744 "\"\\uFFFD\"",
745 },
746 {
747 /* \U+FFFF */
748 "\"\xEF\xBF\xBF\"",
749 "\xEF\xBF\xBF", /* bug: not corrected */
750 "\"\\uFFFD\"",
751 },
752 {
753 /* U+FDD0 */
754 "\"\xEF\xB7\x90\"",
755 "\xEF\xB7\x90", /* bug: not corrected */
756 "\"\\uFFFD\"",
757 },
758 {
759 /* U+FDEF */
760 "\"\xEF\xB7\xAF\"",
761 "\xEF\xB7\xAF", /* bug: not corrected */
762 "\"\\uFFFD\"",
763 },
764 /* Plane 1 .. 16 noncharacters */
765 {
766 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
767 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
768 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
769 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
770 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
771 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
772 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
773 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
774 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
775 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
776 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
777 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
778 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
779 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
780 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
781 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
782 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
783 /* bug: not corrected */
784 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
785 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
786 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
787 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
788 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
789 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
790 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
791 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
792 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
793 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
794 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
795 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
796 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
797 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
798 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
799 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
800 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
801 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
802 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
803 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
804 },
805 {}
806 };
807 int i;
808 QObject *obj;
809 QString *str;
810 const char *json_in, *utf8_out, *utf8_in, *json_out;
811
812 for (i = 0; test_cases[i].json_in; i++) {
813 json_in = test_cases[i].json_in;
814 utf8_out = test_cases[i].utf8_out;
815 utf8_in = test_cases[i].utf8_in ?: test_cases[i].utf8_out;
816 json_out = test_cases[i].json_out ?: test_cases[i].json_in;
817
818 obj = qobject_from_json(json_in, utf8_out ? &error_abort : NULL);
819 if (utf8_out) {
820 str = qobject_to_qstring(obj);
821 g_assert(str);
822 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
823 } else {
824 g_assert(!obj);
825 }
826 qobject_decref(obj);
827
828 obj = QOBJECT(qstring_from_str(utf8_in));
829 str = qobject_to_json(obj);
830 if (json_out) {
831 g_assert(str);
832 g_assert_cmpstr(qstring_get_str(str), ==, json_out);
833 } else {
834 g_assert(!str);
835 }
836 QDECREF(str);
837 qobject_decref(obj);
838
839 /*
840 * Disabled, because qobject_from_json() is buggy, and I can't
841 * be bothered to add the expected incorrect results.
842 * FIXME Enable once these bugs have been fixed.
843 */
844 if (0 && json_out != json_in) {
845 obj = qobject_from_json(json_out, &error_abort);
846 str = qobject_to_qstring(obj);
847 g_assert(str);
848 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
849 }
850 }
851 }
852
853 static void vararg_string(void)
854 {
855 int i;
856 struct {
857 const char *decoded;
858 } test_cases[] = {
859 { "hello world" },
860 { "the quick brown fox jumped over the fence" },
861 {}
862 };
863
864 for (i = 0; test_cases[i].decoded; i++) {
865 QString *str;
866
867 str = qobject_to_qstring(qobject_from_jsonf("%s",
868 test_cases[i].decoded));
869 g_assert(str);
870 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
871
872 QDECREF(str);
873 }
874 }
875
876 static void simple_number(void)
877 {
878 int i;
879 struct {
880 const char *encoded;
881 int64_t decoded;
882 int skip;
883 } test_cases[] = {
884 { "0", 0 },
885 { "1234", 1234 },
886 { "1", 1 },
887 { "-32", -32 },
888 { "-0", 0, .skip = 1 },
889 { },
890 };
891
892 for (i = 0; test_cases[i].encoded; i++) {
893 QNum *qnum;
894 int64_t val;
895
896 qnum = qobject_to_qnum(qobject_from_json(test_cases[i].encoded,
897 &error_abort));
898 g_assert(qnum);
899 g_assert(qnum_get_try_int(qnum, &val));
900 g_assert_cmpint(val, ==, test_cases[i].decoded);
901 if (test_cases[i].skip == 0) {
902 QString *str;
903
904 str = qobject_to_json(QOBJECT(qnum));
905 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
906 QDECREF(str);
907 }
908
909 QDECREF(qnum);
910 }
911 }
912
913 static void large_number(void)
914 {
915 const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
916 const char *gtu64 = "18446744073709551616"; /* 2^64 */
917 const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
918 QNum *qnum;
919 QString *str;
920 uint64_t val;
921 int64_t ival;
922
923 qnum = qobject_to_qnum(qobject_from_json(maxu64, &error_abort));
924 g_assert(qnum);
925 g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
926 g_assert(!qnum_get_try_int(qnum, &ival));
927
928 str = qobject_to_json(QOBJECT(qnum));
929 g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
930 QDECREF(str);
931 QDECREF(qnum);
932
933 qnum = qobject_to_qnum(qobject_from_json(gtu64, &error_abort));
934 g_assert(qnum);
935 g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
936 g_assert(!qnum_get_try_uint(qnum, &val));
937 g_assert(!qnum_get_try_int(qnum, &ival));
938
939 str = qobject_to_json(QOBJECT(qnum));
940 g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
941 QDECREF(str);
942 QDECREF(qnum);
943
944 qnum = qobject_to_qnum(qobject_from_json(lti64, &error_abort));
945 g_assert(qnum);
946 g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
947 g_assert(!qnum_get_try_uint(qnum, &val));
948 g_assert(!qnum_get_try_int(qnum, &ival));
949
950 str = qobject_to_json(QOBJECT(qnum));
951 g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
952 QDECREF(str);
953 QDECREF(qnum);
954 }
955
956 static void float_number(void)
957 {
958 int i;
959 struct {
960 const char *encoded;
961 double decoded;
962 int skip;
963 } test_cases[] = {
964 { "32.43", 32.43 },
965 { "0.222", 0.222 },
966 { "-32.12313", -32.12313 },
967 { "-32.20e-10", -32.20e-10, .skip = 1 },
968 { },
969 };
970
971 for (i = 0; test_cases[i].encoded; i++) {
972 QObject *obj;
973 QNum *qnum;
974
975 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
976 qnum = qobject_to_qnum(obj);
977 g_assert(qnum);
978 g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
979
980 if (test_cases[i].skip == 0) {
981 QString *str;
982
983 str = qobject_to_json(obj);
984 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
985 QDECREF(str);
986 }
987
988 QDECREF(qnum);
989 }
990 }
991
992 static void vararg_number(void)
993 {
994 QNum *qnum;
995 int value = 0x2342;
996 long long value_ll = 0x2342342343LL;
997 double valuef = 2.323423423;
998 int64_t val;
999
1000 qnum = qobject_to_qnum(qobject_from_jsonf("%d", value));
1001 g_assert(qnum_get_try_int(qnum, &val));
1002 g_assert_cmpint(val, ==, value);
1003 QDECREF(qnum);
1004
1005 qnum = qobject_to_qnum(qobject_from_jsonf("%lld", value_ll));
1006 g_assert(qnum_get_try_int(qnum, &val));
1007 g_assert_cmpint(val, ==, value_ll);
1008 QDECREF(qnum);
1009
1010 qnum = qobject_to_qnum(qobject_from_jsonf("%f", valuef));
1011 g_assert(qnum_get_double(qnum) == valuef);
1012 QDECREF(qnum);
1013 }
1014
1015 static void keyword_literal(void)
1016 {
1017 QObject *obj;
1018 QBool *qbool;
1019 QNull *null;
1020 QString *str;
1021
1022 obj = qobject_from_json("true", &error_abort);
1023 qbool = qobject_to_qbool(obj);
1024 g_assert(qbool);
1025 g_assert(qbool_get_bool(qbool) == true);
1026
1027 str = qobject_to_json(obj);
1028 g_assert(strcmp(qstring_get_str(str), "true") == 0);
1029 QDECREF(str);
1030
1031 QDECREF(qbool);
1032
1033 obj = qobject_from_json("false", &error_abort);
1034 qbool = qobject_to_qbool(obj);
1035 g_assert(qbool);
1036 g_assert(qbool_get_bool(qbool) == false);
1037
1038 str = qobject_to_json(obj);
1039 g_assert(strcmp(qstring_get_str(str), "false") == 0);
1040 QDECREF(str);
1041
1042 QDECREF(qbool);
1043
1044 qbool = qobject_to_qbool(qobject_from_jsonf("%i", false));
1045 g_assert(qbool);
1046 g_assert(qbool_get_bool(qbool) == false);
1047 QDECREF(qbool);
1048
1049 /* Test that non-zero values other than 1 get collapsed to true */
1050 qbool = qobject_to_qbool(qobject_from_jsonf("%i", 2));
1051 g_assert(qbool);
1052 g_assert(qbool_get_bool(qbool) == true);
1053 QDECREF(qbool);
1054
1055 obj = qobject_from_json("null", &error_abort);
1056 g_assert(obj != NULL);
1057 g_assert(qobject_type(obj) == QTYPE_QNULL);
1058
1059 null = qnull();
1060 g_assert(QOBJECT(null) == obj);
1061
1062 qobject_decref(obj);
1063 QDECREF(null);
1064 }
1065
1066 static void simple_dict(void)
1067 {
1068 int i;
1069 struct {
1070 const char *encoded;
1071 QLitObject decoded;
1072 } test_cases[] = {
1073 {
1074 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1075 .decoded = QLIT_QDICT(((QLitDictEntry[]){
1076 { "foo", QLIT_QNUM(42) },
1077 { "bar", QLIT_QSTR("hello world") },
1078 { }
1079 })),
1080 }, {
1081 .encoded = "{}",
1082 .decoded = QLIT_QDICT(((QLitDictEntry[]){
1083 { }
1084 })),
1085 }, {
1086 .encoded = "{\"foo\": 43}",
1087 .decoded = QLIT_QDICT(((QLitDictEntry[]){
1088 { "foo", QLIT_QNUM(43) },
1089 { }
1090 })),
1091 },
1092 { }
1093 };
1094
1095 for (i = 0; test_cases[i].encoded; i++) {
1096 QObject *obj;
1097 QString *str;
1098
1099 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1100 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1101
1102 str = qobject_to_json(obj);
1103 qobject_decref(obj);
1104
1105 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1106 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1107 qobject_decref(obj);
1108 QDECREF(str);
1109 }
1110 }
1111
1112 /*
1113 * this generates json of the form:
1114 * a(0,m) = [0, 1, ..., m-1]
1115 * a(n,m) = {
1116 * 'key0': a(0,m),
1117 * 'key1': a(1,m),
1118 * ...
1119 * 'key(n-1)': a(n-1,m)
1120 * }
1121 */
1122 static void gen_test_json(GString *gstr, int nest_level_max,
1123 int elem_count)
1124 {
1125 int i;
1126
1127 g_assert(gstr);
1128 if (nest_level_max == 0) {
1129 g_string_append(gstr, "[");
1130 for (i = 0; i < elem_count; i++) {
1131 g_string_append_printf(gstr, "%d", i);
1132 if (i < elem_count - 1) {
1133 g_string_append_printf(gstr, ", ");
1134 }
1135 }
1136 g_string_append(gstr, "]");
1137 return;
1138 }
1139
1140 g_string_append(gstr, "{");
1141 for (i = 0; i < nest_level_max; i++) {
1142 g_string_append_printf(gstr, "'key%d': ", i);
1143 gen_test_json(gstr, i, elem_count);
1144 if (i < nest_level_max - 1) {
1145 g_string_append(gstr, ",");
1146 }
1147 }
1148 g_string_append(gstr, "}");
1149 }
1150
1151 static void large_dict(void)
1152 {
1153 GString *gstr = g_string_new("");
1154 QObject *obj;
1155
1156 gen_test_json(gstr, 10, 100);
1157 obj = qobject_from_json(gstr->str, &error_abort);
1158 g_assert(obj != NULL);
1159
1160 qobject_decref(obj);
1161 g_string_free(gstr, true);
1162 }
1163
1164 static void simple_list(void)
1165 {
1166 int i;
1167 struct {
1168 const char *encoded;
1169 QLitObject decoded;
1170 } test_cases[] = {
1171 {
1172 .encoded = "[43,42]",
1173 .decoded = QLIT_QLIST(((QLitObject[]){
1174 QLIT_QNUM(43),
1175 QLIT_QNUM(42),
1176 { }
1177 })),
1178 },
1179 {
1180 .encoded = "[43]",
1181 .decoded = QLIT_QLIST(((QLitObject[]){
1182 QLIT_QNUM(43),
1183 { }
1184 })),
1185 },
1186 {
1187 .encoded = "[]",
1188 .decoded = QLIT_QLIST(((QLitObject[]){
1189 { }
1190 })),
1191 },
1192 {
1193 .encoded = "[{}]",
1194 .decoded = QLIT_QLIST(((QLitObject[]){
1195 QLIT_QDICT(((QLitDictEntry[]){
1196 {},
1197 })),
1198 {},
1199 })),
1200 },
1201 { }
1202 };
1203
1204 for (i = 0; test_cases[i].encoded; i++) {
1205 QObject *obj;
1206 QString *str;
1207
1208 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1209 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1210
1211 str = qobject_to_json(obj);
1212 qobject_decref(obj);
1213
1214 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1215 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1216 qobject_decref(obj);
1217 QDECREF(str);
1218 }
1219 }
1220
1221 static void simple_whitespace(void)
1222 {
1223 int i;
1224 struct {
1225 const char *encoded;
1226 QLitObject decoded;
1227 } test_cases[] = {
1228 {
1229 .encoded = " [ 43 , 42 ]",
1230 .decoded = QLIT_QLIST(((QLitObject[]){
1231 QLIT_QNUM(43),
1232 QLIT_QNUM(42),
1233 { }
1234 })),
1235 },
1236 {
1237 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1238 .decoded = QLIT_QLIST(((QLitObject[]){
1239 QLIT_QNUM(43),
1240 QLIT_QDICT(((QLitDictEntry[]){
1241 { "h", QLIT_QSTR("b") },
1242 { }})),
1243 QLIT_QLIST(((QLitObject[]){
1244 { }})),
1245 QLIT_QNUM(42),
1246 { }
1247 })),
1248 },
1249 {
1250 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1251 .decoded = QLIT_QLIST(((QLitObject[]){
1252 QLIT_QNUM(43),
1253 QLIT_QDICT(((QLitDictEntry[]){
1254 { "h", QLIT_QSTR("b") },
1255 { "a", QLIT_QNUM(32) },
1256 { }})),
1257 QLIT_QLIST(((QLitObject[]){
1258 { }})),
1259 QLIT_QNUM(42),
1260 { }
1261 })),
1262 },
1263 { }
1264 };
1265
1266 for (i = 0; test_cases[i].encoded; i++) {
1267 QObject *obj;
1268 QString *str;
1269
1270 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1271 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1272
1273 str = qobject_to_json(obj);
1274 qobject_decref(obj);
1275
1276 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1277 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1278
1279 qobject_decref(obj);
1280 QDECREF(str);
1281 }
1282 }
1283
1284 static void simple_varargs(void)
1285 {
1286 QObject *embedded_obj;
1287 QObject *obj;
1288 QLitObject decoded = QLIT_QLIST(((QLitObject[]){
1289 QLIT_QNUM(1),
1290 QLIT_QNUM(2),
1291 QLIT_QLIST(((QLitObject[]){
1292 QLIT_QNUM(32),
1293 QLIT_QNUM(42),
1294 {}})),
1295 {}}));
1296
1297 embedded_obj = qobject_from_json("[32, 42]", &error_abort);
1298 g_assert(embedded_obj != NULL);
1299
1300 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1301 g_assert(qlit_equal_qobject(&decoded, obj));
1302
1303 qobject_decref(obj);
1304 }
1305
1306 static void empty_input(void)
1307 {
1308 const char *empty = "";
1309 QObject *obj = qobject_from_json(empty, &error_abort);
1310 g_assert(obj == NULL);
1311 }
1312
1313 static void unterminated_string(void)
1314 {
1315 Error *err = NULL;
1316 QObject *obj = qobject_from_json("\"abc", &err);
1317 g_assert(!err); /* BUG */
1318 g_assert(obj == NULL);
1319 }
1320
1321 static void unterminated_sq_string(void)
1322 {
1323 Error *err = NULL;
1324 QObject *obj = qobject_from_json("'abc", &err);
1325 g_assert(!err); /* BUG */
1326 g_assert(obj == NULL);
1327 }
1328
1329 static void unterminated_escape(void)
1330 {
1331 Error *err = NULL;
1332 QObject *obj = qobject_from_json("\"abc\\\"", &err);
1333 g_assert(!err); /* BUG */
1334 g_assert(obj == NULL);
1335 }
1336
1337 static void unterminated_array(void)
1338 {
1339 Error *err = NULL;
1340 QObject *obj = qobject_from_json("[32", &err);
1341 g_assert(!err); /* BUG */
1342 g_assert(obj == NULL);
1343 }
1344
1345 static void unterminated_array_comma(void)
1346 {
1347 Error *err = NULL;
1348 QObject *obj = qobject_from_json("[32,", &err);
1349 g_assert(!err); /* BUG */
1350 g_assert(obj == NULL);
1351 }
1352
1353 static void invalid_array_comma(void)
1354 {
1355 Error *err = NULL;
1356 QObject *obj = qobject_from_json("[32,}", &err);
1357 error_free_or_abort(&err);
1358 g_assert(obj == NULL);
1359 }
1360
1361 static void unterminated_dict(void)
1362 {
1363 Error *err = NULL;
1364 QObject *obj = qobject_from_json("{'abc':32", &err);
1365 g_assert(!err); /* BUG */
1366 g_assert(obj == NULL);
1367 }
1368
1369 static void unterminated_dict_comma(void)
1370 {
1371 Error *err = NULL;
1372 QObject *obj = qobject_from_json("{'abc':32,", &err);
1373 g_assert(!err); /* BUG */
1374 g_assert(obj == NULL);
1375 }
1376
1377 static void invalid_dict_comma(void)
1378 {
1379 Error *err = NULL;
1380 QObject *obj = qobject_from_json("{'abc':32,}", &err);
1381 error_free_or_abort(&err);
1382 g_assert(obj == NULL);
1383 }
1384
1385 static void unterminated_literal(void)
1386 {
1387 Error *err = NULL;
1388 QObject *obj = qobject_from_json("nul", &err);
1389 error_free_or_abort(&err);
1390 g_assert(obj == NULL);
1391 }
1392
1393 static char *make_nest(char *buf, size_t cnt)
1394 {
1395 memset(buf, '[', cnt - 1);
1396 buf[cnt - 1] = '{';
1397 buf[cnt] = '}';
1398 memset(buf + cnt + 1, ']', cnt - 1);
1399 buf[2 * cnt] = 0;
1400 return buf;
1401 }
1402
1403 static void limits_nesting(void)
1404 {
1405 Error *err = NULL;
1406 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1407 char buf[2 * (max_nesting + 1) + 1];
1408 QObject *obj;
1409
1410 obj = qobject_from_json(make_nest(buf, max_nesting), &error_abort);
1411 g_assert(obj != NULL);
1412 qobject_decref(obj);
1413
1414 obj = qobject_from_json(make_nest(buf, max_nesting + 1), &err);
1415 error_free_or_abort(&err);
1416 g_assert(obj == NULL);
1417 }
1418
1419 int main(int argc, char **argv)
1420 {
1421 g_test_init(&argc, &argv, NULL);
1422
1423 g_test_add_func("/literals/string/simple", simple_string);
1424 g_test_add_func("/literals/string/escaped", escaped_string);
1425 g_test_add_func("/literals/string/utf8", utf8_string);
1426 g_test_add_func("/literals/string/single_quote", single_quote_string);
1427 g_test_add_func("/literals/string/vararg", vararg_string);
1428
1429 g_test_add_func("/literals/number/simple", simple_number);
1430 g_test_add_func("/literals/number/large", large_number);
1431 g_test_add_func("/literals/number/float", float_number);
1432 g_test_add_func("/literals/number/vararg", vararg_number);
1433
1434 g_test_add_func("/literals/keyword", keyword_literal);
1435
1436 g_test_add_func("/dicts/simple_dict", simple_dict);
1437 g_test_add_func("/dicts/large_dict", large_dict);
1438 g_test_add_func("/lists/simple_list", simple_list);
1439
1440 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1441
1442 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1443
1444 g_test_add_func("/errors/empty_input", empty_input);
1445 g_test_add_func("/errors/unterminated/string", unterminated_string);
1446 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1447 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1448 g_test_add_func("/errors/unterminated/array", unterminated_array);
1449 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1450 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1451 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1452 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1453 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1454 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1455 g_test_add_func("/errors/limits/nesting", limits_nesting);
1456
1457 return g_test_run();
1458 }