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