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