cirrus: fix off-by-one in cirrus_bitblt_rop_bkwd_transp_*_16
[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 QInt *qint;
890
891 qint = qobject_to_qint(qobject_from_json(test_cases[i].encoded,
892 &error_abort));
893 g_assert(qint);
894 g_assert(qint_get_int(qint) == test_cases[i].decoded);
895 if (test_cases[i].skip == 0) {
896 QString *str;
897
898 str = qobject_to_json(QOBJECT(qint));
899 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
900 QDECREF(str);
901 }
902
903 QDECREF(qint);
904 }
905 }
906
907 static void float_number(void)
908 {
909 int i;
910 struct {
911 const char *encoded;
912 double decoded;
913 int skip;
914 } test_cases[] = {
915 { "32.43", 32.43 },
916 { "0.222", 0.222 },
917 { "-32.12313", -32.12313 },
918 { "-32.20e-10", -32.20e-10, .skip = 1 },
919 { },
920 };
921
922 for (i = 0; test_cases[i].encoded; i++) {
923 QObject *obj;
924 QFloat *qfloat;
925
926 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
927 qfloat = qobject_to_qfloat(obj);
928 g_assert(qfloat);
929 g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
930
931 if (test_cases[i].skip == 0) {
932 QString *str;
933
934 str = qobject_to_json(obj);
935 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
936 QDECREF(str);
937 }
938
939 QDECREF(qfloat);
940 }
941 }
942
943 static void vararg_number(void)
944 {
945 QInt *qint;
946 QFloat *qfloat;
947 int value = 0x2342;
948 long long value_ll = 0x2342342343LL;
949 double valuef = 2.323423423;
950
951 qint = qobject_to_qint(qobject_from_jsonf("%d", value));
952 g_assert(qint_get_int(qint) == value);
953 QDECREF(qint);
954
955 qint = qobject_to_qint(qobject_from_jsonf("%lld", value_ll));
956 g_assert(qint_get_int(qint) == value_ll);
957 QDECREF(qint);
958
959 qfloat = qobject_to_qfloat(qobject_from_jsonf("%f", valuef));
960 g_assert(qfloat_get_double(qfloat) == valuef);
961 QDECREF(qfloat);
962 }
963
964 static void keyword_literal(void)
965 {
966 QObject *obj;
967 QBool *qbool;
968 QObject *null;
969 QString *str;
970
971 obj = qobject_from_json("true", &error_abort);
972 qbool = qobject_to_qbool(obj);
973 g_assert(qbool);
974 g_assert(qbool_get_bool(qbool) == true);
975
976 str = qobject_to_json(obj);
977 g_assert(strcmp(qstring_get_str(str), "true") == 0);
978 QDECREF(str);
979
980 QDECREF(qbool);
981
982 obj = qobject_from_json("false", &error_abort);
983 qbool = qobject_to_qbool(obj);
984 g_assert(qbool);
985 g_assert(qbool_get_bool(qbool) == false);
986
987 str = qobject_to_json(obj);
988 g_assert(strcmp(qstring_get_str(str), "false") == 0);
989 QDECREF(str);
990
991 QDECREF(qbool);
992
993 qbool = qobject_to_qbool(qobject_from_jsonf("%i", false));
994 g_assert(qbool);
995 g_assert(qbool_get_bool(qbool) == false);
996 QDECREF(qbool);
997
998 /* Test that non-zero values other than 1 get collapsed to true */
999 qbool = qobject_to_qbool(qobject_from_jsonf("%i", 2));
1000 g_assert(qbool);
1001 g_assert(qbool_get_bool(qbool) == true);
1002 QDECREF(qbool);
1003
1004 obj = qobject_from_json("null", &error_abort);
1005 g_assert(obj != NULL);
1006 g_assert(qobject_type(obj) == QTYPE_QNULL);
1007
1008 null = qnull();
1009 g_assert(null == obj);
1010
1011 qobject_decref(obj);
1012 qobject_decref(null);
1013 }
1014
1015 typedef struct LiteralQDictEntry LiteralQDictEntry;
1016 typedef struct LiteralQObject LiteralQObject;
1017
1018 struct LiteralQObject
1019 {
1020 int type;
1021 union {
1022 int64_t qint;
1023 const char *qstr;
1024 LiteralQDictEntry *qdict;
1025 LiteralQObject *qlist;
1026 } value;
1027 };
1028
1029 struct LiteralQDictEntry
1030 {
1031 const char *key;
1032 LiteralQObject value;
1033 };
1034
1035 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1036 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1037 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1038 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1039
1040 typedef struct QListCompareHelper
1041 {
1042 int index;
1043 LiteralQObject *objs;
1044 int result;
1045 } QListCompareHelper;
1046
1047 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1048
1049 static void compare_helper(QObject *obj, void *opaque)
1050 {
1051 QListCompareHelper *helper = opaque;
1052
1053 if (helper->result == 0) {
1054 return;
1055 }
1056
1057 if (helper->objs[helper->index].type == QTYPE_NONE) {
1058 helper->result = 0;
1059 return;
1060 }
1061
1062 helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1063 }
1064
1065 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1066 {
1067 if (!rhs || lhs->type != qobject_type(rhs)) {
1068 return 0;
1069 }
1070
1071 switch (lhs->type) {
1072 case QTYPE_QINT:
1073 return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
1074 case QTYPE_QSTRING:
1075 return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1076 case QTYPE_QDICT: {
1077 int i;
1078
1079 for (i = 0; lhs->value.qdict[i].key; i++) {
1080 QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1081
1082 if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1083 return 0;
1084 }
1085 }
1086
1087 return 1;
1088 }
1089 case QTYPE_QLIST: {
1090 QListCompareHelper helper;
1091
1092 helper.index = 0;
1093 helper.objs = lhs->value.qlist;
1094 helper.result = 1;
1095
1096 qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1097
1098 return helper.result;
1099 }
1100 default:
1101 break;
1102 }
1103
1104 return 0;
1105 }
1106
1107 static void simple_dict(void)
1108 {
1109 int i;
1110 struct {
1111 const char *encoded;
1112 LiteralQObject decoded;
1113 } test_cases[] = {
1114 {
1115 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1116 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1117 { "foo", QLIT_QINT(42) },
1118 { "bar", QLIT_QSTR("hello world") },
1119 { }
1120 })),
1121 }, {
1122 .encoded = "{}",
1123 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1124 { }
1125 })),
1126 }, {
1127 .encoded = "{\"foo\": 43}",
1128 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1129 { "foo", QLIT_QINT(43) },
1130 { }
1131 })),
1132 },
1133 { }
1134 };
1135
1136 for (i = 0; test_cases[i].encoded; i++) {
1137 QObject *obj;
1138 QString *str;
1139
1140 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1141 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1142
1143 str = qobject_to_json(obj);
1144 qobject_decref(obj);
1145
1146 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1147 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1148 qobject_decref(obj);
1149 QDECREF(str);
1150 }
1151 }
1152
1153 /*
1154 * this generates json of the form:
1155 * a(0,m) = [0, 1, ..., m-1]
1156 * a(n,m) = {
1157 * 'key0': a(0,m),
1158 * 'key1': a(1,m),
1159 * ...
1160 * 'key(n-1)': a(n-1,m)
1161 * }
1162 */
1163 static void gen_test_json(GString *gstr, int nest_level_max,
1164 int elem_count)
1165 {
1166 int i;
1167
1168 g_assert(gstr);
1169 if (nest_level_max == 0) {
1170 g_string_append(gstr, "[");
1171 for (i = 0; i < elem_count; i++) {
1172 g_string_append_printf(gstr, "%d", i);
1173 if (i < elem_count - 1) {
1174 g_string_append_printf(gstr, ", ");
1175 }
1176 }
1177 g_string_append(gstr, "]");
1178 return;
1179 }
1180
1181 g_string_append(gstr, "{");
1182 for (i = 0; i < nest_level_max; i++) {
1183 g_string_append_printf(gstr, "'key%d': ", i);
1184 gen_test_json(gstr, i, elem_count);
1185 if (i < nest_level_max - 1) {
1186 g_string_append(gstr, ",");
1187 }
1188 }
1189 g_string_append(gstr, "}");
1190 }
1191
1192 static void large_dict(void)
1193 {
1194 GString *gstr = g_string_new("");
1195 QObject *obj;
1196
1197 gen_test_json(gstr, 10, 100);
1198 obj = qobject_from_json(gstr->str, &error_abort);
1199 g_assert(obj != NULL);
1200
1201 qobject_decref(obj);
1202 g_string_free(gstr, true);
1203 }
1204
1205 static void simple_list(void)
1206 {
1207 int i;
1208 struct {
1209 const char *encoded;
1210 LiteralQObject decoded;
1211 } test_cases[] = {
1212 {
1213 .encoded = "[43,42]",
1214 .decoded = QLIT_QLIST(((LiteralQObject[]){
1215 QLIT_QINT(43),
1216 QLIT_QINT(42),
1217 { }
1218 })),
1219 },
1220 {
1221 .encoded = "[43]",
1222 .decoded = QLIT_QLIST(((LiteralQObject[]){
1223 QLIT_QINT(43),
1224 { }
1225 })),
1226 },
1227 {
1228 .encoded = "[]",
1229 .decoded = QLIT_QLIST(((LiteralQObject[]){
1230 { }
1231 })),
1232 },
1233 {
1234 .encoded = "[{}]",
1235 .decoded = QLIT_QLIST(((LiteralQObject[]){
1236 QLIT_QDICT(((LiteralQDictEntry[]){
1237 {},
1238 })),
1239 {},
1240 })),
1241 },
1242 { }
1243 };
1244
1245 for (i = 0; test_cases[i].encoded; i++) {
1246 QObject *obj;
1247 QString *str;
1248
1249 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1250 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1251
1252 str = qobject_to_json(obj);
1253 qobject_decref(obj);
1254
1255 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1256 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1257 qobject_decref(obj);
1258 QDECREF(str);
1259 }
1260 }
1261
1262 static void simple_whitespace(void)
1263 {
1264 int i;
1265 struct {
1266 const char *encoded;
1267 LiteralQObject decoded;
1268 } test_cases[] = {
1269 {
1270 .encoded = " [ 43 , 42 ]",
1271 .decoded = QLIT_QLIST(((LiteralQObject[]){
1272 QLIT_QINT(43),
1273 QLIT_QINT(42),
1274 { }
1275 })),
1276 },
1277 {
1278 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1279 .decoded = QLIT_QLIST(((LiteralQObject[]){
1280 QLIT_QINT(43),
1281 QLIT_QDICT(((LiteralQDictEntry[]){
1282 { "h", QLIT_QSTR("b") },
1283 { }})),
1284 QLIT_QLIST(((LiteralQObject[]){
1285 { }})),
1286 QLIT_QINT(42),
1287 { }
1288 })),
1289 },
1290 {
1291 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1292 .decoded = QLIT_QLIST(((LiteralQObject[]){
1293 QLIT_QINT(43),
1294 QLIT_QDICT(((LiteralQDictEntry[]){
1295 { "h", QLIT_QSTR("b") },
1296 { "a", QLIT_QINT(32) },
1297 { }})),
1298 QLIT_QLIST(((LiteralQObject[]){
1299 { }})),
1300 QLIT_QINT(42),
1301 { }
1302 })),
1303 },
1304 { }
1305 };
1306
1307 for (i = 0; test_cases[i].encoded; i++) {
1308 QObject *obj;
1309 QString *str;
1310
1311 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
1312 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1313
1314 str = qobject_to_json(obj);
1315 qobject_decref(obj);
1316
1317 obj = qobject_from_json(qstring_get_str(str), &error_abort);
1318 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1319
1320 qobject_decref(obj);
1321 QDECREF(str);
1322 }
1323 }
1324
1325 static void simple_varargs(void)
1326 {
1327 QObject *embedded_obj;
1328 QObject *obj;
1329 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1330 QLIT_QINT(1),
1331 QLIT_QINT(2),
1332 QLIT_QLIST(((LiteralQObject[]){
1333 QLIT_QINT(32),
1334 QLIT_QINT(42),
1335 {}})),
1336 {}}));
1337
1338 embedded_obj = qobject_from_json("[32, 42]", &error_abort);
1339 g_assert(embedded_obj != NULL);
1340
1341 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1342 g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1343
1344 qobject_decref(obj);
1345 }
1346
1347 static void empty_input(void)
1348 {
1349 const char *empty = "";
1350 QObject *obj = qobject_from_json(empty, &error_abort);
1351 g_assert(obj == NULL);
1352 }
1353
1354 static void unterminated_string(void)
1355 {
1356 Error *err = NULL;
1357 QObject *obj = qobject_from_json("\"abc", &err);
1358 g_assert(!err); /* BUG */
1359 g_assert(obj == NULL);
1360 }
1361
1362 static void unterminated_sq_string(void)
1363 {
1364 Error *err = NULL;
1365 QObject *obj = qobject_from_json("'abc", &err);
1366 g_assert(!err); /* BUG */
1367 g_assert(obj == NULL);
1368 }
1369
1370 static void unterminated_escape(void)
1371 {
1372 Error *err = NULL;
1373 QObject *obj = qobject_from_json("\"abc\\\"", &err);
1374 g_assert(!err); /* BUG */
1375 g_assert(obj == NULL);
1376 }
1377
1378 static void unterminated_array(void)
1379 {
1380 Error *err = NULL;
1381 QObject *obj = qobject_from_json("[32", &err);
1382 g_assert(!err); /* BUG */
1383 g_assert(obj == NULL);
1384 }
1385
1386 static void unterminated_array_comma(void)
1387 {
1388 Error *err = NULL;
1389 QObject *obj = qobject_from_json("[32,", &err);
1390 g_assert(!err); /* BUG */
1391 g_assert(obj == NULL);
1392 }
1393
1394 static void invalid_array_comma(void)
1395 {
1396 Error *err = NULL;
1397 QObject *obj = qobject_from_json("[32,}", &err);
1398 error_free_or_abort(&err);
1399 g_assert(obj == NULL);
1400 }
1401
1402 static void unterminated_dict(void)
1403 {
1404 Error *err = NULL;
1405 QObject *obj = qobject_from_json("{'abc':32", &err);
1406 g_assert(!err); /* BUG */
1407 g_assert(obj == NULL);
1408 }
1409
1410 static void unterminated_dict_comma(void)
1411 {
1412 Error *err = NULL;
1413 QObject *obj = qobject_from_json("{'abc':32,", &err);
1414 g_assert(!err); /* BUG */
1415 g_assert(obj == NULL);
1416 }
1417
1418 static void invalid_dict_comma(void)
1419 {
1420 Error *err = NULL;
1421 QObject *obj = qobject_from_json("{'abc':32,}", &err);
1422 error_free_or_abort(&err);
1423 g_assert(obj == NULL);
1424 }
1425
1426 static void unterminated_literal(void)
1427 {
1428 Error *err = NULL;
1429 QObject *obj = qobject_from_json("nul", &err);
1430 error_free_or_abort(&err);
1431 g_assert(obj == NULL);
1432 }
1433
1434 static char *make_nest(char *buf, size_t cnt)
1435 {
1436 memset(buf, '[', cnt - 1);
1437 buf[cnt - 1] = '{';
1438 buf[cnt] = '}';
1439 memset(buf + cnt + 1, ']', cnt - 1);
1440 buf[2 * cnt] = 0;
1441 return buf;
1442 }
1443
1444 static void limits_nesting(void)
1445 {
1446 Error *err = NULL;
1447 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1448 char buf[2 * (max_nesting + 1) + 1];
1449 QObject *obj;
1450
1451 obj = qobject_from_json(make_nest(buf, max_nesting), &error_abort);
1452 g_assert(obj != NULL);
1453 qobject_decref(obj);
1454
1455 obj = qobject_from_json(make_nest(buf, max_nesting + 1), &err);
1456 error_free_or_abort(&err);
1457 g_assert(obj == NULL);
1458 }
1459
1460 int main(int argc, char **argv)
1461 {
1462 g_test_init(&argc, &argv, NULL);
1463
1464 g_test_add_func("/literals/string/simple", simple_string);
1465 g_test_add_func("/literals/string/escaped", escaped_string);
1466 g_test_add_func("/literals/string/utf8", utf8_string);
1467 g_test_add_func("/literals/string/single_quote", single_quote_string);
1468 g_test_add_func("/literals/string/vararg", vararg_string);
1469
1470 g_test_add_func("/literals/number/simple", simple_number);
1471 g_test_add_func("/literals/number/float", float_number);
1472 g_test_add_func("/literals/number/vararg", vararg_number);
1473
1474 g_test_add_func("/literals/keyword", keyword_literal);
1475
1476 g_test_add_func("/dicts/simple_dict", simple_dict);
1477 g_test_add_func("/dicts/large_dict", large_dict);
1478 g_test_add_func("/lists/simple_list", simple_list);
1479
1480 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1481
1482 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1483
1484 g_test_add_func("/errors/empty_input", empty_input);
1485 g_test_add_func("/errors/unterminated/string", unterminated_string);
1486 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1487 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1488 g_test_add_func("/errors/unterminated/array", unterminated_array);
1489 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1490 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1491 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1492 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1493 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1494 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1495 g_test_add_func("/errors/limits/nesting", limits_nesting);
1496
1497 return g_test_run();
1498 }