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