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