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