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