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