]> git.proxmox.com Git - mirror_qemu.git/blob - tests/check-qjson.c
Merge remote-tracking branch 'remotes/armbru/tags/pull-tests-2018-08-16' 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_unref(obj);
71 }
72
73 qobject_unref(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_unref(obj);
103
104 qobject_unref(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 qobject_unref(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_unref(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 qobject_unref(str);
837 qobject_unref(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,
868 qobject_from_jsonf_nofail("%s",
869 test_cases[i].decoded));
870 g_assert(str);
871 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
872
873 qobject_unref(str);
874 }
875 }
876
877 static void simple_number(void)
878 {
879 int i;
880 struct {
881 const char *encoded;
882 int64_t decoded;
883 int skip;
884 } test_cases[] = {
885 { "0", 0 },
886 { "1234", 1234 },
887 { "1", 1 },
888 { "-32", -32 },
889 { "-0", 0, .skip = 1 },
890 { },
891 };
892
893 for (i = 0; test_cases[i].encoded; i++) {
894 QNum *qnum;
895 int64_t val;
896
897 qnum = qobject_to(QNum,
898 qobject_from_json(test_cases[i].encoded,
899 &error_abort));
900 g_assert(qnum);
901 g_assert(qnum_get_try_int(qnum, &val));
902 g_assert_cmpint(val, ==, test_cases[i].decoded);
903 if (test_cases[i].skip == 0) {
904 QString *str;
905
906 str = qobject_to_json(QOBJECT(qnum));
907 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
908 qobject_unref(str);
909 }
910
911 qobject_unref(qnum);
912 }
913 }
914
915 static void large_number(void)
916 {
917 const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
918 const char *gtu64 = "18446744073709551616"; /* 2^64 */
919 const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
920 QNum *qnum;
921 QString *str;
922 uint64_t val;
923 int64_t ival;
924
925 qnum = qobject_to(QNum, qobject_from_json(maxu64, &error_abort));
926 g_assert(qnum);
927 g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
928 g_assert(!qnum_get_try_int(qnum, &ival));
929
930 str = qobject_to_json(QOBJECT(qnum));
931 g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
932 qobject_unref(str);
933 qobject_unref(qnum);
934
935 qnum = qobject_to(QNum, qobject_from_json(gtu64, &error_abort));
936 g_assert(qnum);
937 g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
938 g_assert(!qnum_get_try_uint(qnum, &val));
939 g_assert(!qnum_get_try_int(qnum, &ival));
940
941 str = qobject_to_json(QOBJECT(qnum));
942 g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
943 qobject_unref(str);
944 qobject_unref(qnum);
945
946 qnum = qobject_to(QNum, qobject_from_json(lti64, &error_abort));
947 g_assert(qnum);
948 g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
949 g_assert(!qnum_get_try_uint(qnum, &val));
950 g_assert(!qnum_get_try_int(qnum, &ival));
951
952 str = qobject_to_json(QOBJECT(qnum));
953 g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
954 qobject_unref(str);
955 qobject_unref(qnum);
956 }
957
958 static void float_number(void)
959 {
960 int i;
961 struct {
962 const char *encoded;
963 double decoded;
964 int skip;
965 } test_cases[] = {
966 { "32.43", 32.43 },
967 { "0.222", 0.222 },
968 { "-32.12313", -32.12313 },
969 { "-32.20e-10", -32.20e-10, .skip = 1 },
970 { },
971 };
972
973 for (i = 0; test_cases[i].encoded; i++) {
974 QObject *obj;
975 QNum *qnum;
976
977 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
978 qnum = qobject_to(QNum, obj);
979 g_assert(qnum);
980 g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
981
982 if (test_cases[i].skip == 0) {
983 QString *str;
984
985 str = qobject_to_json(obj);
986 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
987 qobject_unref(str);
988 }
989
990 qobject_unref(qnum);
991 }
992 }
993
994 static void vararg_number(void)
995 {
996 QNum *qnum;
997 int value = 0x2342;
998 long long value_ll = 0x2342342343LL;
999 double valuef = 2.323423423;
1000 int64_t val;
1001
1002 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%d", value));
1003 g_assert(qnum_get_try_int(qnum, &val));
1004 g_assert_cmpint(val, ==, value);
1005 qobject_unref(qnum);
1006
1007 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%lld", value_ll));
1008 g_assert(qnum_get_try_int(qnum, &val));
1009 g_assert_cmpint(val, ==, value_ll);
1010 qobject_unref(qnum);
1011
1012 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%f", valuef));
1013 g_assert(qnum_get_double(qnum) == valuef);
1014 qobject_unref(qnum);
1015 }
1016
1017 static void keyword_literal(void)
1018 {
1019 QObject *obj;
1020 QBool *qbool;
1021 QNull *null;
1022 QString *str;
1023
1024 obj = qobject_from_json("true", &error_abort);
1025 qbool = qobject_to(QBool, obj);
1026 g_assert(qbool);
1027 g_assert(qbool_get_bool(qbool) == true);
1028
1029 str = qobject_to_json(obj);
1030 g_assert(strcmp(qstring_get_str(str), "true") == 0);
1031 qobject_unref(str);
1032
1033 qobject_unref(qbool);
1034
1035 obj = qobject_from_json("false", &error_abort);
1036 qbool = qobject_to(QBool, obj);
1037 g_assert(qbool);
1038 g_assert(qbool_get_bool(qbool) == false);
1039
1040 str = qobject_to_json(obj);
1041 g_assert(strcmp(qstring_get_str(str), "false") == 0);
1042 qobject_unref(str);
1043
1044 qobject_unref(qbool);
1045
1046 qbool = qobject_to(QBool, qobject_from_jsonf_nofail("%i", false));
1047 g_assert(qbool);
1048 g_assert(qbool_get_bool(qbool) == false);
1049 qobject_unref(qbool);
1050
1051 /* Test that non-zero values other than 1 get collapsed to true */
1052 qbool = qobject_to(QBool, qobject_from_jsonf_nofail("%i", 2));
1053 g_assert(qbool);
1054 g_assert(qbool_get_bool(qbool) == true);
1055 qobject_unref(qbool);
1056
1057 obj = qobject_from_json("null", &error_abort);
1058 g_assert(obj != NULL);
1059 g_assert(qobject_type(obj) == QTYPE_QNULL);
1060
1061 null = qnull();
1062 g_assert(QOBJECT(null) == obj);
1063
1064 qobject_unref(obj);
1065 qobject_unref(null);
1066 }
1067
1068 static void simple_dict(void)
1069 {
1070 int i;
1071 struct {
1072 const char *encoded;
1073 QLitObject decoded;
1074 } test_cases[] = {
1075 {
1076 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1077 .decoded = QLIT_QDICT(((QLitDictEntry[]){
1078 { "foo", QLIT_QNUM(42) },
1079 { "bar", QLIT_QSTR("hello world") },
1080 { }
1081 })),
1082 }, {
1083 .encoded = "{}",
1084 .decoded = QLIT_QDICT(((QLitDictEntry[]){
1085 { }
1086 })),
1087 }, {
1088 .encoded = "{\"foo\": 43}",
1089 .decoded = QLIT_QDICT(((QLitDictEntry[]){
1090 { "foo", QLIT_QNUM(43) },
1091 { }
1092 })),
1093 },
1094 { }
1095 };
1096
1097 for (i = 0; test_cases[i].encoded; i++) {
1098 QObject *obj;
1099 QString *str;
1100
1101 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1102 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1103
1104 str = qobject_to_json(obj);
1105 qobject_unref(obj);
1106
1107 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1108 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1109 qobject_unref(obj);
1110 qobject_unref(str);
1111 }
1112 }
1113
1114 /*
1115 * this generates json of the form:
1116 * a(0,m) = [0, 1, ..., m-1]
1117 * a(n,m) = {
1118 * 'key0': a(0,m),
1119 * 'key1': a(1,m),
1120 * ...
1121 * 'key(n-1)': a(n-1,m)
1122 * }
1123 */
1124 static void gen_test_json(GString *gstr, int nest_level_max,
1125 int elem_count)
1126 {
1127 int i;
1128
1129 g_assert(gstr);
1130 if (nest_level_max == 0) {
1131 g_string_append(gstr, "[");
1132 for (i = 0; i < elem_count; i++) {
1133 g_string_append_printf(gstr, "%d", i);
1134 if (i < elem_count - 1) {
1135 g_string_append_printf(gstr, ", ");
1136 }
1137 }
1138 g_string_append(gstr, "]");
1139 return;
1140 }
1141
1142 g_string_append(gstr, "{");
1143 for (i = 0; i < nest_level_max; i++) {
1144 g_string_append_printf(gstr, "'key%d': ", i);
1145 gen_test_json(gstr, i, elem_count);
1146 if (i < nest_level_max - 1) {
1147 g_string_append(gstr, ",");
1148 }
1149 }
1150 g_string_append(gstr, "}");
1151 }
1152
1153 static void large_dict(void)
1154 {
1155 GString *gstr = g_string_new("");
1156 QObject *obj;
1157
1158 gen_test_json(gstr, 10, 100);
1159 obj = qobject_from_json(gstr->str, &error_abort);
1160 g_assert(obj != NULL);
1161
1162 qobject_unref(obj);
1163 g_string_free(gstr, true);
1164 }
1165
1166 static void simple_list(void)
1167 {
1168 int i;
1169 struct {
1170 const char *encoded;
1171 QLitObject decoded;
1172 } test_cases[] = {
1173 {
1174 .encoded = "[43,42]",
1175 .decoded = QLIT_QLIST(((QLitObject[]){
1176 QLIT_QNUM(43),
1177 QLIT_QNUM(42),
1178 { }
1179 })),
1180 },
1181 {
1182 .encoded = "[43]",
1183 .decoded = QLIT_QLIST(((QLitObject[]){
1184 QLIT_QNUM(43),
1185 { }
1186 })),
1187 },
1188 {
1189 .encoded = "[]",
1190 .decoded = QLIT_QLIST(((QLitObject[]){
1191 { }
1192 })),
1193 },
1194 {
1195 .encoded = "[{}]",
1196 .decoded = QLIT_QLIST(((QLitObject[]){
1197 QLIT_QDICT(((QLitDictEntry[]){
1198 {},
1199 })),
1200 {},
1201 })),
1202 },
1203 { }
1204 };
1205
1206 for (i = 0; test_cases[i].encoded; i++) {
1207 QObject *obj;
1208 QString *str;
1209
1210 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1211 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1212
1213 str = qobject_to_json(obj);
1214 qobject_unref(obj);
1215
1216 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1217 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1218 qobject_unref(obj);
1219 qobject_unref(str);
1220 }
1221 }
1222
1223 static void simple_whitespace(void)
1224 {
1225 int i;
1226 struct {
1227 const char *encoded;
1228 QLitObject decoded;
1229 } test_cases[] = {
1230 {
1231 .encoded = " [ 43 , 42 ]",
1232 .decoded = QLIT_QLIST(((QLitObject[]){
1233 QLIT_QNUM(43),
1234 QLIT_QNUM(42),
1235 { }
1236 })),
1237 },
1238 {
1239 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1240 .decoded = QLIT_QLIST(((QLitObject[]){
1241 QLIT_QNUM(43),
1242 QLIT_QDICT(((QLitDictEntry[]){
1243 { "h", QLIT_QSTR("b") },
1244 { }})),
1245 QLIT_QLIST(((QLitObject[]){
1246 { }})),
1247 QLIT_QNUM(42),
1248 { }
1249 })),
1250 },
1251 {
1252 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1253 .decoded = QLIT_QLIST(((QLitObject[]){
1254 QLIT_QNUM(43),
1255 QLIT_QDICT(((QLitDictEntry[]){
1256 { "h", QLIT_QSTR("b") },
1257 { "a", QLIT_QNUM(32) },
1258 { }})),
1259 QLIT_QLIST(((QLitObject[]){
1260 { }})),
1261 QLIT_QNUM(42),
1262 { }
1263 })),
1264 },
1265 { }
1266 };
1267
1268 for (i = 0; test_cases[i].encoded; i++) {
1269 QObject *obj;
1270 QString *str;
1271
1272 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1273 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1274
1275 str = qobject_to_json(obj);
1276 qobject_unref(obj);
1277
1278 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1279 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
1280
1281 qobject_unref(obj);
1282 qobject_unref(str);
1283 }
1284 }
1285
1286 static void simple_varargs(void)
1287 {
1288 QObject *embedded_obj;
1289 QObject *obj;
1290 QLitObject decoded = QLIT_QLIST(((QLitObject[]){
1291 QLIT_QNUM(1),
1292 QLIT_QNUM(2),
1293 QLIT_QLIST(((QLitObject[]){
1294 QLIT_QNUM(32),
1295 QLIT_QNUM(42),
1296 {}})),
1297 {}}));
1298
1299 embedded_obj = qobject_from_json("[32, 42]", &error_abort);
1300 g_assert(embedded_obj != NULL);
1301
1302 obj = qobject_from_jsonf_nofail("[%d, 2, %p]", 1, embedded_obj);
1303 g_assert(qlit_equal_qobject(&decoded, obj));
1304
1305 qobject_unref(obj);
1306 }
1307
1308 static void empty_input(void)
1309 {
1310 const char *empty = "";
1311 QObject *obj = qobject_from_json(empty, &error_abort);
1312 g_assert(obj == NULL);
1313 }
1314
1315 static void unterminated_string(void)
1316 {
1317 Error *err = NULL;
1318 QObject *obj = qobject_from_json("\"abc", &err);
1319 g_assert(!err); /* BUG */
1320 g_assert(obj == NULL);
1321 }
1322
1323 static void unterminated_sq_string(void)
1324 {
1325 Error *err = NULL;
1326 QObject *obj = qobject_from_json("'abc", &err);
1327 g_assert(!err); /* BUG */
1328 g_assert(obj == NULL);
1329 }
1330
1331 static void unterminated_escape(void)
1332 {
1333 Error *err = NULL;
1334 QObject *obj = qobject_from_json("\"abc\\\"", &err);
1335 g_assert(!err); /* BUG */
1336 g_assert(obj == NULL);
1337 }
1338
1339 static void unterminated_array(void)
1340 {
1341 Error *err = NULL;
1342 QObject *obj = qobject_from_json("[32", &err);
1343 g_assert(!err); /* BUG */
1344 g_assert(obj == NULL);
1345 }
1346
1347 static void unterminated_array_comma(void)
1348 {
1349 Error *err = NULL;
1350 QObject *obj = qobject_from_json("[32,", &err);
1351 g_assert(!err); /* BUG */
1352 g_assert(obj == NULL);
1353 }
1354
1355 static void invalid_array_comma(void)
1356 {
1357 Error *err = NULL;
1358 QObject *obj = qobject_from_json("[32,}", &err);
1359 error_free_or_abort(&err);
1360 g_assert(obj == NULL);
1361 }
1362
1363 static void unterminated_dict(void)
1364 {
1365 Error *err = NULL;
1366 QObject *obj = qobject_from_json("{'abc':32", &err);
1367 g_assert(!err); /* BUG */
1368 g_assert(obj == NULL);
1369 }
1370
1371 static void unterminated_dict_comma(void)
1372 {
1373 Error *err = NULL;
1374 QObject *obj = qobject_from_json("{'abc':32,", &err);
1375 g_assert(!err); /* BUG */
1376 g_assert(obj == NULL);
1377 }
1378
1379 static void invalid_dict_comma(void)
1380 {
1381 Error *err = NULL;
1382 QObject *obj = qobject_from_json("{'abc':32,}", &err);
1383 error_free_or_abort(&err);
1384 g_assert(obj == NULL);
1385 }
1386
1387 static void unterminated_literal(void)
1388 {
1389 Error *err = NULL;
1390 QObject *obj = qobject_from_json("nul", &err);
1391 error_free_or_abort(&err);
1392 g_assert(obj == NULL);
1393 }
1394
1395 static char *make_nest(char *buf, size_t cnt)
1396 {
1397 memset(buf, '[', cnt - 1);
1398 buf[cnt - 1] = '{';
1399 buf[cnt] = '}';
1400 memset(buf + cnt + 1, ']', cnt - 1);
1401 buf[2 * cnt] = 0;
1402 return buf;
1403 }
1404
1405 static void limits_nesting(void)
1406 {
1407 Error *err = NULL;
1408 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1409 char buf[2 * (max_nesting + 1) + 1];
1410 QObject *obj;
1411
1412 obj = qobject_from_json(make_nest(buf, max_nesting), &error_abort);
1413 g_assert(obj != NULL);
1414 qobject_unref(obj);
1415
1416 obj = qobject_from_json(make_nest(buf, max_nesting + 1), &err);
1417 error_free_or_abort(&err);
1418 g_assert(obj == NULL);
1419 }
1420
1421 int main(int argc, char **argv)
1422 {
1423 g_test_init(&argc, &argv, NULL);
1424
1425 g_test_add_func("/literals/string/simple", simple_string);
1426 g_test_add_func("/literals/string/escaped", escaped_string);
1427 g_test_add_func("/literals/string/utf8", utf8_string);
1428 g_test_add_func("/literals/string/single_quote", single_quote_string);
1429 g_test_add_func("/literals/string/vararg", vararg_string);
1430
1431 g_test_add_func("/literals/number/simple", simple_number);
1432 g_test_add_func("/literals/number/large", large_number);
1433 g_test_add_func("/literals/number/float", float_number);
1434 g_test_add_func("/literals/number/vararg", vararg_number);
1435
1436 g_test_add_func("/literals/keyword", keyword_literal);
1437
1438 g_test_add_func("/dicts/simple_dict", simple_dict);
1439 g_test_add_func("/dicts/large_dict", large_dict);
1440 g_test_add_func("/lists/simple_list", simple_list);
1441
1442 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1443
1444 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1445
1446 g_test_add_func("/errors/empty_input", empty_input);
1447 g_test_add_func("/errors/unterminated/string", unterminated_string);
1448 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1449 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1450 g_test_add_func("/errors/unterminated/array", unterminated_array);
1451 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1452 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1453 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1454 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1455 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1456 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1457 g_test_add_func("/errors/limits/nesting", limits_nesting);
1458
1459 return g_test_run();
1460 }