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