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