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