]> git.proxmox.com Git - qemu.git/blob - tests/check-qjson.c
Merge remote-tracking branch 'rth/tcg-pull' into staging
[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 * We should either reject all invalid sequences, or minimize
148 * overlong sequences and replace all other invalid sequences by a
149 * suitable replacement character. A common choice for
150 * replacement is U+FFFD.
151 *
152 * Problem: we can't easily deal with embedded U+0000. Parsing
153 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
154 * which gets misinterpreted as NUL-terminated "this ". We should
155 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
156 * UTF-8").
157 *
158 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
159 * capability and stress test at
160 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
161 */
162 static const struct {
163 const char *json_in;
164 const char *utf8_out;
165 const char *json_out; /* defaults to @json_in */
166 const char *utf8_in; /* defaults to @utf8_out */
167 } test_cases[] = {
168 /*
169 * Bug markers used here:
170 * - bug: not corrected
171 * JSON parser fails to correct invalid sequence(s)
172 * - bug: rejected
173 * JSON parser rejects invalid sequence(s)
174 * We may choose to define this as feature
175 * - bug: want "..."
176 * JSON parser produces incorrect result, this is the
177 * correct one, assuming replacement character U+FFFF
178 * We may choose to reject instead of replace
179 */
180
181 /* 1 Some correct UTF-8 text */
182 {
183 /* a bit of German */
184 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
185 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
186 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
187 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
188 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
189 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
190 },
191 {
192 /* a bit of Greek */
193 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
194 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
195 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
196 },
197 /* 2 Boundary condition test cases */
198 /* 2.1 First possible sequence of a certain length */
199 /* 2.1.1 1 byte U+0000 */
200 {
201 "\"\\u0000\"",
202 "", /* bug: want overlong "\xC0\x80" */
203 "\"\\u0000\"",
204 "\xC0\x80",
205 },
206 /* 2.1.2 2 bytes U+0080 */
207 {
208 "\"\xC2\x80\"",
209 "\xC2\x80",
210 "\"\\u0080\"",
211 },
212 /* 2.1.3 3 bytes U+0800 */
213 {
214 "\"\xE0\xA0\x80\"",
215 "\xE0\xA0\x80",
216 "\"\\u0800\"",
217 },
218 /* 2.1.4 4 bytes U+10000 */
219 {
220 "\"\xF0\x90\x80\x80\"",
221 "\xF0\x90\x80\x80",
222 "\"\\uD800\\uDC00\"",
223 },
224 /* 2.1.5 5 bytes U+200000 */
225 {
226 "\"\xF8\x88\x80\x80\x80\"",
227 NULL, /* bug: rejected */
228 "\"\\uFFFD\"",
229 "\xF8\x88\x80\x80\x80",
230 },
231 /* 2.1.6 6 bytes U+4000000 */
232 {
233 "\"\xFC\x84\x80\x80\x80\x80\"",
234 NULL, /* bug: rejected */
235 "\"\\uFFFD\"",
236 "\xFC\x84\x80\x80\x80\x80",
237 },
238 /* 2.2 Last possible sequence of a certain length */
239 /* 2.2.1 1 byte U+007F */
240 {
241 "\"\x7F\"",
242 "\x7F",
243 "\"\\u007F\"",
244 },
245 /* 2.2.2 2 bytes U+07FF */
246 {
247 "\"\xDF\xBF\"",
248 "\xDF\xBF",
249 "\"\\u07FF\"",
250 },
251 /*
252 * 2.2.3 3 bytes U+FFFC
253 * The last possible sequence is actually U+FFFF. But that's
254 * a noncharacter, and already covered by its own test case
255 * under 5.3. Same for U+FFFE. U+FFFD is the last character
256 * in the BMP, and covered under 2.3. Because of U+FFFD's
257 * special role as replacement character, it's worth testing
258 * U+FFFC here.
259 */
260 {
261 "\"\xEF\xBF\xBC\"",
262 "\xEF\xBF\xBC",
263 "\"\\uFFFC\"",
264 },
265 /* 2.2.4 4 bytes U+1FFFFF */
266 {
267 "\"\xF7\xBF\xBF\xBF\"",
268 NULL, /* bug: rejected */
269 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
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+10FFFD */
307 "\"\xF4\x8F\xBF\xBD\"",
308 "\xF4\x8F\xBF\xBD",
309 "\"\\uDBFF\\uDFFD\""
310 },
311 {
312 /* first one beyond Unicode range: U+110000 */
313 "\"\xF4\x90\x80\x80\"",
314 "\xF4\x90\x80\x80",
315 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
324 },
325 /* 3.1.2 Last continuation byte */
326 {
327 "\"\xBF\"",
328 "\xBF", /* bug: not corrected */
329 "\"\\uFFFD\"",
330 },
331 /* 3.1.3 2 continuation bytes */
332 {
333 "\"\x80\xBF\"",
334 "\x80\xBF", /* bug: not corrected */
335 "\"\\uFFFD\\uFFFD\"",
336 },
337 /* 3.1.4 3 continuation bytes */
338 {
339 "\"\x80\xBF\x80\"",
340 "\x80\xBF\x80", /* bug: not corrected */
341 "\"\\uFFFD\\uFFFD\\uFFFD\"",
342 },
343 /* 3.1.5 4 continuation bytes */
344 {
345 "\"\x80\xBF\x80\xBF\"",
346 "\x80\xBF\x80\xBF", /* bug: not corrected */
347 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
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 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
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 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
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 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
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 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
387 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
388 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
389 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
390 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
391 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
392 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
393 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
394 },
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 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
404 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
405 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
406 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
407 "\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 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
420 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
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 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
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 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
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 "\"\\uFFFD \\uFFFD \"",
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 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
488 },
489 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
490 {
491 "\"\xF7\xBF\xBF\"",
492 NULL, /* bug: rejected */
493 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
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 "\"\\uFFFD\"",
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 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
516 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
517 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
518 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
519 },
520 /* 3.5 Impossible bytes */
521 {
522 "\"\xFE\"",
523 NULL, /* bug: rejected */
524 "\"\\uFFFD\"",
525 "\xFE",
526 },
527 {
528 "\"\xFF\"",
529 NULL, /* bug: rejected */
530 "\"\\uFFFD\"",
531 "\xFF",
532 },
533 {
534 "\"\xFE\xFE\xFF\xFF\"",
535 NULL, /* bug: rejected */
536 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
537 "\xFE\xFE\xFF\xFF",
538 },
539 /* 4 Overlong sequences */
540 /* 4.1 Overlong '/' */
541 {
542 "\"\xC0\xAF\"",
543 NULL, /* bug: rejected */
544 "\"\\uFFFD\"",
545 "\xC0\xAF",
546 },
547 {
548 "\"\xE0\x80\xAF\"",
549 "\xE0\x80\xAF", /* bug: not corrected */
550 "\"\\uFFFD\"",
551 },
552 {
553 "\"\xF0\x80\x80\xAF\"",
554 "\xF0\x80\x80\xAF", /* bug: not corrected */
555 "\"\\uFFFD\"",
556 },
557 {
558 "\"\xF8\x80\x80\x80\xAF\"",
559 NULL, /* bug: rejected */
560 "\"\\uFFFD\"",
561 "\xF8\x80\x80\x80\xAF",
562 },
563 {
564 "\"\xFC\x80\x80\x80\x80\xAF\"",
565 NULL, /* bug: rejected */
566 "\"\\uFFFD\"",
567 "\xFC\x80\x80\x80\x80\xAF",
568 },
569 /*
570 * 4.2 Maximum overlong sequences
571 * Highest Unicode value that is still resulting in an
572 * overlong sequence if represented with the given number of
573 * bytes. This is a boundary test for safe UTF-8 decoders.
574 */
575 {
576 /* \U+007F */
577 "\"\xC1\xBF\"",
578 NULL, /* bug: rejected */
579 "\"\\uFFFD\"",
580 "\xC1\xBF",
581 },
582 {
583 /* \U+07FF */
584 "\"\xE0\x9F\xBF\"",
585 "\xE0\x9F\xBF", /* bug: not corrected */
586 "\"\\uFFFD\"",
587 },
588 {
589 /*
590 * \U+FFFC
591 * The actual maximum would be U+FFFF, but that's a
592 * noncharacter. Testing U+FFFC seems more useful. See
593 * also 2.2.3
594 */
595 "\"\xF0\x8F\xBF\xBC\"",
596 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
597 "\"\\uFFFD\"",
598 },
599 {
600 /* \U+1FFFFF */
601 "\"\xF8\x87\xBF\xBF\xBF\"",
602 NULL, /* bug: rejected */
603 "\"\\uFFFD\"",
604 "\xF8\x87\xBF\xBF\xBF",
605 },
606 {
607 /* \U+3FFFFFF */
608 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
609 NULL, /* bug: rejected */
610 "\"\\uFFFD\"",
611 "\xFC\x83\xBF\xBF\xBF\xBF",
612 },
613 /* 4.3 Overlong representation of the NUL character */
614 {
615 /* \U+0000 */
616 "\"\xC0\x80\"",
617 NULL, /* bug: rejected */
618 "\"\\u0000\"",
619 "\xC0\x80",
620 },
621 {
622 /* \U+0000 */
623 "\"\xE0\x80\x80\"",
624 "\xE0\x80\x80", /* bug: not corrected */
625 "\"\\uFFFD\"",
626 },
627 {
628 /* \U+0000 */
629 "\"\xF0\x80\x80\x80\"",
630 "\xF0\x80\x80\x80", /* bug: not corrected */
631 "\"\\uFFFD\"",
632 },
633 {
634 /* \U+0000 */
635 "\"\xF8\x80\x80\x80\x80\"",
636 NULL, /* bug: rejected */
637 "\"\\uFFFD\"",
638 "\xF8\x80\x80\x80\x80",
639 },
640 {
641 /* \U+0000 */
642 "\"\xFC\x80\x80\x80\x80\x80\"",
643 NULL, /* bug: rejected */
644 "\"\\uFFFD\"",
645 "\xFC\x80\x80\x80\x80\x80",
646 },
647 /* 5 Illegal code positions */
648 /* 5.1 Single UTF-16 surrogates */
649 {
650 /* \U+D800 */
651 "\"\xED\xA0\x80\"",
652 "\xED\xA0\x80", /* bug: not corrected */
653 "\"\\uFFFD\"",
654 },
655 {
656 /* \U+DB7F */
657 "\"\xED\xAD\xBF\"",
658 "\xED\xAD\xBF", /* bug: not corrected */
659 "\"\\uFFFD\"",
660 },
661 {
662 /* \U+DB80 */
663 "\"\xED\xAE\x80\"",
664 "\xED\xAE\x80", /* bug: not corrected */
665 "\"\\uFFFD\"",
666 },
667 {
668 /* \U+DBFF */
669 "\"\xED\xAF\xBF\"",
670 "\xED\xAF\xBF", /* bug: not corrected */
671 "\"\\uFFFD\"",
672 },
673 {
674 /* \U+DC00 */
675 "\"\xED\xB0\x80\"",
676 "\xED\xB0\x80", /* bug: not corrected */
677 "\"\\uFFFD\"",
678 },
679 {
680 /* \U+DF80 */
681 "\"\xED\xBE\x80\"",
682 "\xED\xBE\x80", /* bug: not corrected */
683 "\"\\uFFFD\"",
684 },
685 {
686 /* \U+DFFF */
687 "\"\xED\xBF\xBF\"",
688 "\xED\xBF\xBF", /* bug: not corrected */
689 "\"\\uFFFD\"",
690 },
691 /* 5.2 Paired UTF-16 surrogates */
692 {
693 /* \U+D800\U+DC00 */
694 "\"\xED\xA0\x80\xED\xB0\x80\"",
695 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
696 "\"\\uFFFD\\uFFFD\"",
697 },
698 {
699 /* \U+D800\U+DFFF */
700 "\"\xED\xA0\x80\xED\xBF\xBF\"",
701 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
702 "\"\\uFFFD\\uFFFD\"",
703 },
704 {
705 /* \U+DB7F\U+DC00 */
706 "\"\xED\xAD\xBF\xED\xB0\x80\"",
707 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
708 "\"\\uFFFD\\uFFFD\"",
709 },
710 {
711 /* \U+DB7F\U+DFFF */
712 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
713 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
714 "\"\\uFFFD\\uFFFD\"",
715 },
716 {
717 /* \U+DB80\U+DC00 */
718 "\"\xED\xAE\x80\xED\xB0\x80\"",
719 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
720 "\"\\uFFFD\\uFFFD\"",
721 },
722 {
723 /* \U+DB80\U+DFFF */
724 "\"\xED\xAE\x80\xED\xBF\xBF\"",
725 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
726 "\"\\uFFFD\\uFFFD\"",
727 },
728 {
729 /* \U+DBFF\U+DC00 */
730 "\"\xED\xAF\xBF\xED\xB0\x80\"",
731 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
732 "\"\\uFFFD\\uFFFD\"",
733 },
734 {
735 /* \U+DBFF\U+DFFF */
736 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
737 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
738 "\"\\uFFFD\\uFFFD\"",
739 },
740 /* 5.3 Other illegal code positions */
741 /* BMP noncharacters */
742 {
743 /* \U+FFFE */
744 "\"\xEF\xBF\xBE\"",
745 "\xEF\xBF\xBE", /* bug: not corrected */
746 "\"\\uFFFD\"",
747 },
748 {
749 /* \U+FFFF */
750 "\"\xEF\xBF\xBF\"",
751 "\xEF\xBF\xBF", /* bug: not corrected */
752 "\"\\uFFFD\"",
753 },
754 {
755 /* U+FDD0 */
756 "\"\xEF\xB7\x90\"",
757 "\xEF\xB7\x90", /* bug: not corrected */
758 "\"\\uFFFD\"",
759 },
760 {
761 /* U+FDEF */
762 "\"\xEF\xB7\xAF\"",
763 "\xEF\xB7\xAF", /* bug: not corrected */
764 "\"\\uFFFD\"",
765 },
766 /* Plane 1 .. 16 noncharacters */
767 {
768 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
769 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
770 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
771 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
772 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
773 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
774 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
775 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
776 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
777 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
778 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
779 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
780 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
781 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
782 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
783 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
784 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
785 /* bug: not corrected */
786 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
787 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
788 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
789 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
790 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
791 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
792 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
793 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
794 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
795 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
796 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
797 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
798 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
799 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
800 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
801 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
802 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
803 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
804 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
805 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
806 },
807 {}
808 };
809 int i;
810 QObject *obj;
811 QString *str;
812 const char *json_in, *utf8_out, *utf8_in, *json_out;
813
814 for (i = 0; test_cases[i].json_in; i++) {
815 json_in = test_cases[i].json_in;
816 utf8_out = test_cases[i].utf8_out;
817 utf8_in = test_cases[i].utf8_in ?: test_cases[i].utf8_out;
818 json_out = test_cases[i].json_out ?: test_cases[i].json_in;
819
820 obj = qobject_from_json(json_in);
821 if (utf8_out) {
822 g_assert(obj);
823 g_assert(qobject_type(obj) == QTYPE_QSTRING);
824 str = qobject_to_qstring(obj);
825 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
826 } else {
827 g_assert(!obj);
828 }
829 qobject_decref(obj);
830
831 obj = QOBJECT(qstring_from_str(utf8_in));
832 str = qobject_to_json(obj);
833 if (json_out) {
834 g_assert(str);
835 g_assert_cmpstr(qstring_get_str(str), ==, json_out);
836 } else {
837 g_assert(!str);
838 }
839 QDECREF(str);
840 qobject_decref(obj);
841
842 /*
843 * Disabled, because qobject_from_json() is buggy, and I can't
844 * be bothered to add the expected incorrect results.
845 * FIXME Enable once these bugs have been fixed.
846 */
847 if (0 && json_out != json_in) {
848 obj = qobject_from_json(json_out);
849 g_assert(obj);
850 g_assert(qobject_type(obj) == QTYPE_QSTRING);
851 str = qobject_to_qstring(obj);
852 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
853 }
854 }
855 }
856
857 static void vararg_string(void)
858 {
859 int i;
860 struct {
861 const char *decoded;
862 } test_cases[] = {
863 { "hello world" },
864 { "the quick brown fox jumped over the fence" },
865 {}
866 };
867
868 for (i = 0; test_cases[i].decoded; i++) {
869 QObject *obj;
870 QString *str;
871
872 obj = qobject_from_jsonf("%s", test_cases[i].decoded);
873
874 g_assert(obj != NULL);
875 g_assert(qobject_type(obj) == QTYPE_QSTRING);
876
877 str = qobject_to_qstring(obj);
878 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
879
880 QDECREF(str);
881 }
882 }
883
884 static void simple_number(void)
885 {
886 int i;
887 struct {
888 const char *encoded;
889 int64_t decoded;
890 int skip;
891 } test_cases[] = {
892 { "0", 0 },
893 { "1234", 1234 },
894 { "1", 1 },
895 { "-32", -32 },
896 { "-0", 0, .skip = 1 },
897 { },
898 };
899
900 for (i = 0; test_cases[i].encoded; i++) {
901 QObject *obj;
902 QInt *qint;
903
904 obj = qobject_from_json(test_cases[i].encoded);
905 g_assert(obj != NULL);
906 g_assert(qobject_type(obj) == QTYPE_QINT);
907
908 qint = qobject_to_qint(obj);
909 g_assert(qint_get_int(qint) == test_cases[i].decoded);
910 if (test_cases[i].skip == 0) {
911 QString *str;
912
913 str = qobject_to_json(obj);
914 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
915 QDECREF(str);
916 }
917
918 QDECREF(qint);
919 }
920 }
921
922 static void float_number(void)
923 {
924 int i;
925 struct {
926 const char *encoded;
927 double decoded;
928 int skip;
929 } test_cases[] = {
930 { "32.43", 32.43 },
931 { "0.222", 0.222 },
932 { "-32.12313", -32.12313 },
933 { "-32.20e-10", -32.20e-10, .skip = 1 },
934 { },
935 };
936
937 for (i = 0; test_cases[i].encoded; i++) {
938 QObject *obj;
939 QFloat *qfloat;
940
941 obj = qobject_from_json(test_cases[i].encoded);
942 g_assert(obj != NULL);
943 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
944
945 qfloat = qobject_to_qfloat(obj);
946 g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
947
948 if (test_cases[i].skip == 0) {
949 QString *str;
950
951 str = qobject_to_json(obj);
952 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
953 QDECREF(str);
954 }
955
956 QDECREF(qfloat);
957 }
958 }
959
960 static void vararg_number(void)
961 {
962 QObject *obj;
963 QInt *qint;
964 QFloat *qfloat;
965 int value = 0x2342;
966 int64_t value64 = 0x2342342343LL;
967 double valuef = 2.323423423;
968
969 obj = qobject_from_jsonf("%d", value);
970 g_assert(obj != NULL);
971 g_assert(qobject_type(obj) == QTYPE_QINT);
972
973 qint = qobject_to_qint(obj);
974 g_assert(qint_get_int(qint) == value);
975
976 QDECREF(qint);
977
978 obj = qobject_from_jsonf("%" PRId64, value64);
979 g_assert(obj != NULL);
980 g_assert(qobject_type(obj) == QTYPE_QINT);
981
982 qint = qobject_to_qint(obj);
983 g_assert(qint_get_int(qint) == value64);
984
985 QDECREF(qint);
986
987 obj = qobject_from_jsonf("%f", valuef);
988 g_assert(obj != NULL);
989 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
990
991 qfloat = qobject_to_qfloat(obj);
992 g_assert(qfloat_get_double(qfloat) == valuef);
993
994 QDECREF(qfloat);
995 }
996
997 static void keyword_literal(void)
998 {
999 QObject *obj;
1000 QBool *qbool;
1001 QString *str;
1002
1003 obj = qobject_from_json("true");
1004 g_assert(obj != NULL);
1005 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1006
1007 qbool = qobject_to_qbool(obj);
1008 g_assert(qbool_get_int(qbool) != 0);
1009
1010 str = qobject_to_json(obj);
1011 g_assert(strcmp(qstring_get_str(str), "true") == 0);
1012 QDECREF(str);
1013
1014 QDECREF(qbool);
1015
1016 obj = qobject_from_json("false");
1017 g_assert(obj != NULL);
1018 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1019
1020 qbool = qobject_to_qbool(obj);
1021 g_assert(qbool_get_int(qbool) == 0);
1022
1023 str = qobject_to_json(obj);
1024 g_assert(strcmp(qstring_get_str(str), "false") == 0);
1025 QDECREF(str);
1026
1027 QDECREF(qbool);
1028
1029 obj = qobject_from_jsonf("%i", false);
1030 g_assert(obj != NULL);
1031 g_assert(qobject_type(obj) == QTYPE_QBOOL);
1032
1033 qbool = qobject_to_qbool(obj);
1034 g_assert(qbool_get_int(qbool) == 0);
1035
1036 QDECREF(qbool);
1037
1038 obj = qobject_from_jsonf("%i", true);
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_int(qbool) != 0);
1044
1045 QDECREF(qbool);
1046 }
1047
1048 typedef struct LiteralQDictEntry LiteralQDictEntry;
1049 typedef struct LiteralQObject LiteralQObject;
1050
1051 struct LiteralQObject
1052 {
1053 int type;
1054 union {
1055 int64_t qint;
1056 const char *qstr;
1057 LiteralQDictEntry *qdict;
1058 LiteralQObject *qlist;
1059 } value;
1060 };
1061
1062 struct LiteralQDictEntry
1063 {
1064 const char *key;
1065 LiteralQObject value;
1066 };
1067
1068 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1069 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1070 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1071 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1072
1073 typedef struct QListCompareHelper
1074 {
1075 int index;
1076 LiteralQObject *objs;
1077 int result;
1078 } QListCompareHelper;
1079
1080 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1081
1082 static void compare_helper(QObject *obj, void *opaque)
1083 {
1084 QListCompareHelper *helper = opaque;
1085
1086 if (helper->result == 0) {
1087 return;
1088 }
1089
1090 if (helper->objs[helper->index].type == QTYPE_NONE) {
1091 helper->result = 0;
1092 return;
1093 }
1094
1095 helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1096 }
1097
1098 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1099 {
1100 if (lhs->type != qobject_type(rhs)) {
1101 return 0;
1102 }
1103
1104 switch (lhs->type) {
1105 case QTYPE_QINT:
1106 return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
1107 case QTYPE_QSTRING:
1108 return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1109 case QTYPE_QDICT: {
1110 int i;
1111
1112 for (i = 0; lhs->value.qdict[i].key; i++) {
1113 QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1114
1115 if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1116 return 0;
1117 }
1118 }
1119
1120 return 1;
1121 }
1122 case QTYPE_QLIST: {
1123 QListCompareHelper helper;
1124
1125 helper.index = 0;
1126 helper.objs = lhs->value.qlist;
1127 helper.result = 1;
1128
1129 qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1130
1131 return helper.result;
1132 }
1133 default:
1134 break;
1135 }
1136
1137 return 0;
1138 }
1139
1140 static void simple_dict(void)
1141 {
1142 int i;
1143 struct {
1144 const char *encoded;
1145 LiteralQObject decoded;
1146 } test_cases[] = {
1147 {
1148 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1149 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1150 { "foo", QLIT_QINT(42) },
1151 { "bar", QLIT_QSTR("hello world") },
1152 { }
1153 })),
1154 }, {
1155 .encoded = "{}",
1156 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1157 { }
1158 })),
1159 }, {
1160 .encoded = "{\"foo\": 43}",
1161 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1162 { "foo", QLIT_QINT(43) },
1163 { }
1164 })),
1165 },
1166 { }
1167 };
1168
1169 for (i = 0; test_cases[i].encoded; i++) {
1170 QObject *obj;
1171 QString *str;
1172
1173 obj = qobject_from_json(test_cases[i].encoded);
1174 g_assert(obj != NULL);
1175 g_assert(qobject_type(obj) == QTYPE_QDICT);
1176
1177 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1178
1179 str = qobject_to_json(obj);
1180 qobject_decref(obj);
1181
1182 obj = qobject_from_json(qstring_get_str(str));
1183 g_assert(obj != NULL);
1184 g_assert(qobject_type(obj) == QTYPE_QDICT);
1185
1186 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1187 qobject_decref(obj);
1188 QDECREF(str);
1189 }
1190 }
1191
1192 /*
1193 * this generates json of the form:
1194 * a(0,m) = [0, 1, ..., m-1]
1195 * a(n,m) = {
1196 * 'key0': a(0,m),
1197 * 'key1': a(1,m),
1198 * ...
1199 * 'key(n-1)': a(n-1,m)
1200 * }
1201 */
1202 static void gen_test_json(GString *gstr, int nest_level_max,
1203 int elem_count)
1204 {
1205 int i;
1206
1207 g_assert(gstr);
1208 if (nest_level_max == 0) {
1209 g_string_append(gstr, "[");
1210 for (i = 0; i < elem_count; i++) {
1211 g_string_append_printf(gstr, "%d", i);
1212 if (i < elem_count - 1) {
1213 g_string_append_printf(gstr, ", ");
1214 }
1215 }
1216 g_string_append(gstr, "]");
1217 return;
1218 }
1219
1220 g_string_append(gstr, "{");
1221 for (i = 0; i < nest_level_max; i++) {
1222 g_string_append_printf(gstr, "'key%d': ", i);
1223 gen_test_json(gstr, i, elem_count);
1224 if (i < nest_level_max - 1) {
1225 g_string_append(gstr, ",");
1226 }
1227 }
1228 g_string_append(gstr, "}");
1229 }
1230
1231 static void large_dict(void)
1232 {
1233 GString *gstr = g_string_new("");
1234 QObject *obj;
1235
1236 gen_test_json(gstr, 10, 100);
1237 obj = qobject_from_json(gstr->str);
1238 g_assert(obj != NULL);
1239
1240 qobject_decref(obj);
1241 g_string_free(gstr, true);
1242 }
1243
1244 static void simple_list(void)
1245 {
1246 int i;
1247 struct {
1248 const char *encoded;
1249 LiteralQObject decoded;
1250 } test_cases[] = {
1251 {
1252 .encoded = "[43,42]",
1253 .decoded = QLIT_QLIST(((LiteralQObject[]){
1254 QLIT_QINT(43),
1255 QLIT_QINT(42),
1256 { }
1257 })),
1258 },
1259 {
1260 .encoded = "[43]",
1261 .decoded = QLIT_QLIST(((LiteralQObject[]){
1262 QLIT_QINT(43),
1263 { }
1264 })),
1265 },
1266 {
1267 .encoded = "[]",
1268 .decoded = QLIT_QLIST(((LiteralQObject[]){
1269 { }
1270 })),
1271 },
1272 {
1273 .encoded = "[{}]",
1274 .decoded = QLIT_QLIST(((LiteralQObject[]){
1275 QLIT_QDICT(((LiteralQDictEntry[]){
1276 {},
1277 })),
1278 {},
1279 })),
1280 },
1281 { }
1282 };
1283
1284 for (i = 0; test_cases[i].encoded; i++) {
1285 QObject *obj;
1286 QString *str;
1287
1288 obj = qobject_from_json(test_cases[i].encoded);
1289 g_assert(obj != NULL);
1290 g_assert(qobject_type(obj) == QTYPE_QLIST);
1291
1292 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1293
1294 str = qobject_to_json(obj);
1295 qobject_decref(obj);
1296
1297 obj = qobject_from_json(qstring_get_str(str));
1298 g_assert(obj != NULL);
1299 g_assert(qobject_type(obj) == QTYPE_QLIST);
1300
1301 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1302 qobject_decref(obj);
1303 QDECREF(str);
1304 }
1305 }
1306
1307 static void simple_whitespace(void)
1308 {
1309 int i;
1310 struct {
1311 const char *encoded;
1312 LiteralQObject decoded;
1313 } test_cases[] = {
1314 {
1315 .encoded = " [ 43 , 42 ]",
1316 .decoded = QLIT_QLIST(((LiteralQObject[]){
1317 QLIT_QINT(43),
1318 QLIT_QINT(42),
1319 { }
1320 })),
1321 },
1322 {
1323 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1324 .decoded = QLIT_QLIST(((LiteralQObject[]){
1325 QLIT_QINT(43),
1326 QLIT_QDICT(((LiteralQDictEntry[]){
1327 { "h", QLIT_QSTR("b") },
1328 { }})),
1329 QLIT_QLIST(((LiteralQObject[]){
1330 { }})),
1331 QLIT_QINT(42),
1332 { }
1333 })),
1334 },
1335 {
1336 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1337 .decoded = QLIT_QLIST(((LiteralQObject[]){
1338 QLIT_QINT(43),
1339 QLIT_QDICT(((LiteralQDictEntry[]){
1340 { "h", QLIT_QSTR("b") },
1341 { "a", QLIT_QINT(32) },
1342 { }})),
1343 QLIT_QLIST(((LiteralQObject[]){
1344 { }})),
1345 QLIT_QINT(42),
1346 { }
1347 })),
1348 },
1349 { }
1350 };
1351
1352 for (i = 0; test_cases[i].encoded; i++) {
1353 QObject *obj;
1354 QString *str;
1355
1356 obj = qobject_from_json(test_cases[i].encoded);
1357 g_assert(obj != NULL);
1358 g_assert(qobject_type(obj) == QTYPE_QLIST);
1359
1360 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1361
1362 str = qobject_to_json(obj);
1363 qobject_decref(obj);
1364
1365 obj = qobject_from_json(qstring_get_str(str));
1366 g_assert(obj != NULL);
1367 g_assert(qobject_type(obj) == QTYPE_QLIST);
1368
1369 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1370
1371 qobject_decref(obj);
1372 QDECREF(str);
1373 }
1374 }
1375
1376 static void simple_varargs(void)
1377 {
1378 QObject *embedded_obj;
1379 QObject *obj;
1380 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1381 QLIT_QINT(1),
1382 QLIT_QINT(2),
1383 QLIT_QLIST(((LiteralQObject[]){
1384 QLIT_QINT(32),
1385 QLIT_QINT(42),
1386 {}})),
1387 {}}));
1388
1389 embedded_obj = qobject_from_json("[32, 42]");
1390 g_assert(embedded_obj != NULL);
1391
1392 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1393 g_assert(obj != NULL);
1394
1395 g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1396
1397 qobject_decref(obj);
1398 }
1399
1400 static void empty_input(void)
1401 {
1402 const char *empty = "";
1403
1404 QObject *obj = qobject_from_json(empty);
1405 g_assert(obj == NULL);
1406 }
1407
1408 static void unterminated_string(void)
1409 {
1410 QObject *obj = qobject_from_json("\"abc");
1411 g_assert(obj == NULL);
1412 }
1413
1414 static void unterminated_sq_string(void)
1415 {
1416 QObject *obj = qobject_from_json("'abc");
1417 g_assert(obj == NULL);
1418 }
1419
1420 static void unterminated_escape(void)
1421 {
1422 QObject *obj = qobject_from_json("\"abc\\\"");
1423 g_assert(obj == NULL);
1424 }
1425
1426 static void unterminated_array(void)
1427 {
1428 QObject *obj = qobject_from_json("[32");
1429 g_assert(obj == NULL);
1430 }
1431
1432 static void unterminated_array_comma(void)
1433 {
1434 QObject *obj = qobject_from_json("[32,");
1435 g_assert(obj == NULL);
1436 }
1437
1438 static void invalid_array_comma(void)
1439 {
1440 QObject *obj = qobject_from_json("[32,}");
1441 g_assert(obj == NULL);
1442 }
1443
1444 static void unterminated_dict(void)
1445 {
1446 QObject *obj = qobject_from_json("{'abc':32");
1447 g_assert(obj == NULL);
1448 }
1449
1450 static void unterminated_dict_comma(void)
1451 {
1452 QObject *obj = qobject_from_json("{'abc':32,");
1453 g_assert(obj == NULL);
1454 }
1455
1456 static void invalid_dict_comma(void)
1457 {
1458 QObject *obj = qobject_from_json("{'abc':32,}");
1459 g_assert(obj == NULL);
1460 }
1461
1462 static void unterminated_literal(void)
1463 {
1464 QObject *obj = qobject_from_json("nul");
1465 g_assert(obj == NULL);
1466 }
1467
1468 int main(int argc, char **argv)
1469 {
1470 g_test_init(&argc, &argv, NULL);
1471
1472 g_test_add_func("/literals/string/simple", simple_string);
1473 g_test_add_func("/literals/string/escaped", escaped_string);
1474 g_test_add_func("/literals/string/utf8", utf8_string);
1475 g_test_add_func("/literals/string/single_quote", single_quote_string);
1476 g_test_add_func("/literals/string/vararg", vararg_string);
1477
1478 g_test_add_func("/literals/number/simple", simple_number);
1479 g_test_add_func("/literals/number/float", float_number);
1480 g_test_add_func("/literals/number/vararg", vararg_number);
1481
1482 g_test_add_func("/literals/keyword", keyword_literal);
1483
1484 g_test_add_func("/dicts/simple_dict", simple_dict);
1485 g_test_add_func("/dicts/large_dict", large_dict);
1486 g_test_add_func("/lists/simple_list", simple_list);
1487
1488 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1489
1490 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1491
1492 g_test_add_func("/errors/empty_input", empty_input);
1493 g_test_add_func("/errors/unterminated/string", unterminated_string);
1494 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1495 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1496 g_test_add_func("/errors/unterminated/array", unterminated_array);
1497 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1498 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1499 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1500 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1501 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1502 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1503
1504 return g_test_run();
1505 }