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