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