]> git.proxmox.com Git - mirror_qemu.git/blame - tests/check-qjson.c
tests: Don't check qobject_type() before qobject_to_qlist()
[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 */
681c28a3 13#include "qemu/osdep.h"
422c46a8 14
c7eb39cb 15#include "qapi/qmp/types.h"
7b1b5d19 16#include "qapi/qmp/qjson.h"
422c46a8
AL
17#include "qemu-common.h"
18
ef76dc59 19static void escaped_string(void)
422c46a8
AL
20{
21 int i;
22 struct {
23 const char *encoded;
24 const char *decoded;
6ee59202 25 int skip;
422c46a8 26 } test_cases[] = {
d22b0bd7
LC
27 { "\"\\b\"", "\b" },
28 { "\"\\f\"", "\f" },
29 { "\"\\n\"", "\n" },
30 { "\"\\r\"", "\r" },
31 { "\"\\t\"", "\t" },
69faeee1
JK
32 { "\"/\"", "/" },
33 { "\"\\/\"", "/", .skip = 1 },
d22b0bd7 34 { "\"\\\\\"", "\\" },
422c46a8
AL
35 { "\"\\\"\"", "\"" },
36 { "\"hello world \\\"embedded string\\\"\"",
37 "hello world \"embedded string\"" },
38 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
6ee59202 39 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
422c46a8
AL
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" },
d5932334
PB
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 },
422c46a8
AL
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
ef76dc59
AL
58 g_assert(obj != NULL);
59 g_assert(qobject_type(obj) == QTYPE_QSTRING);
422c46a8
AL
60
61 str = qobject_to_qstring(obj);
ef76dc59 62 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
422c46a8 63
6ee59202
AL
64 if (test_cases[i].skip == 0) {
65 str = qobject_to_json(obj);
ef76dc59 66 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
6ee59202
AL
67 qobject_decref(obj);
68 }
69
422c46a8
AL
70 QDECREF(str);
71 }
72}
422c46a8 73
ef76dc59 74static void simple_string(void)
422c46a8
AL
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
ef76dc59
AL
93 g_assert(obj != NULL);
94 g_assert(qobject_type(obj) == QTYPE_QSTRING);
422c46a8
AL
95
96 str = qobject_to_qstring(obj);
ef76dc59 97 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
422c46a8 98
6ee59202 99 str = qobject_to_json(obj);
ef76dc59 100 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
6ee59202
AL
101
102 qobject_decref(obj);
103
422c46a8
AL
104 QDECREF(str);
105 }
106}
422c46a8 107
ef76dc59 108static void single_quote_string(void)
422c46a8
AL
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
ef76dc59
AL
127 g_assert(obj != NULL);
128 g_assert(qobject_type(obj) == QTYPE_QSTRING);
422c46a8
AL
129
130 str = qobject_to_qstring(obj);
ef76dc59 131 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
422c46a8
AL
132
133 QDECREF(str);
134 }
135}
422c46a8 136
3960c41f
MA
137static 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 *
e2ec3f97
MA
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.
3960c41f
MA
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 *
1d50c8e9 159 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
3960c41f
MA
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
e2ec3f97 176 * - bug: want "..."
3960c41f
MA
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
3960c41f
MA
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" */
e2ec3f97
MA
204 "\"\\u0000\"",
205 "\xC0\x80",
3960c41f
MA
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",
e2ec3f97 223 "\"\\uD800\\uDC00\"",
3960c41f
MA
224 },
225 /* 2.1.5 5 bytes U+200000 */
226 {
227 "\"\xF8\x88\x80\x80\x80\"",
e2ec3f97
MA
228 NULL, /* bug: rejected */
229 "\"\\uFFFD\"",
3960c41f
MA
230 "\xF8\x88\x80\x80\x80",
231 },
232 /* 2.1.6 6 bytes U+4000000 */
233 {
234 "\"\xFC\x84\x80\x80\x80\x80\"",
e2ec3f97
MA
235 NULL, /* bug: rejected */
236 "\"\\uFFFD\"",
3960c41f
MA
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",
e2ec3f97 244 "\"\\u007F\"",
3960c41f
MA
245 },
246 /* 2.2.2 2 bytes U+07FF */
247 {
248 "\"\xDF\xBF\"",
249 "\xDF\xBF",
250 "\"\\u07FF\"",
251 },
1d50c8e9
MA
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 */
3960c41f 261 {
1d50c8e9
MA
262 "\"\xEF\xBF\xBC\"",
263 "\xEF\xBF\xBC",
264 "\"\\uFFFC\"",
3960c41f
MA
265 },
266 /* 2.2.4 4 bytes U+1FFFFF */
267 {
268 "\"\xF7\xBF\xBF\xBF\"",
e2ec3f97
MA
269 NULL, /* bug: rejected */
270 "\"\\uFFFD\"",
3960c41f
MA
271 "\xF7\xBF\xBF\xBF",
272 },
273 /* 2.2.5 5 bytes U+3FFFFFF */
274 {
275 "\"\xFB\xBF\xBF\xBF\xBF\"",
e2ec3f97
MA
276 NULL, /* bug: rejected */
277 "\"\\uFFFD\"",
3960c41f
MA
278 "\xFB\xBF\xBF\xBF\xBF",
279 },
280 /* 2.2.6 6 bytes U+7FFFFFFF */
281 {
282 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
e2ec3f97
MA
283 NULL, /* bug: rejected */
284 "\"\\uFFFD\"",
3960c41f
MA
285 "\xFD\xBF\xBF\xBF\xBF\xBF",
286 },
287 /* 2.3 Other boundary conditions */
288 {
d6244e2c 289 /* last one before surrogate range: U+D7FF */
3960c41f
MA
290 "\"\xED\x9F\xBF\"",
291 "\xED\x9F\xBF",
292 "\"\\uD7FF\"",
293 },
294 {
d6244e2c 295 /* first one after surrogate range: U+E000 */
3960c41f
MA
296 "\"\xEE\x80\x80\"",
297 "\xEE\x80\x80",
298 "\"\\uE000\"",
299 },
300 {
d6244e2c 301 /* last one in BMP: U+FFFD */
3960c41f
MA
302 "\"\xEF\xBF\xBD\"",
303 "\xEF\xBF\xBD",
304 "\"\\uFFFD\"",
305 },
306 {
1d50c8e9
MA
307 /* last one in last plane: U+10FFFD */
308 "\"\xF4\x8F\xBF\xBD\"",
309 "\xF4\x8F\xBF\xBD",
e2ec3f97 310 "\"\\uDBFF\\uDFFD\""
3960c41f
MA
311 },
312 {
d6244e2c 313 /* first one beyond Unicode range: U+110000 */
3960c41f
MA
314 "\"\xF4\x90\x80\x80\"",
315 "\xF4\x90\x80\x80",
e2ec3f97 316 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 324 "\"\\uFFFD\"",
3960c41f
MA
325 },
326 /* 3.1.2 Last continuation byte */
327 {
328 "\"\xBF\"",
329 "\xBF", /* bug: not corrected */
e2ec3f97 330 "\"\\uFFFD\"",
3960c41f
MA
331 },
332 /* 3.1.3 2 continuation bytes */
333 {
334 "\"\x80\xBF\"",
335 "\x80\xBF", /* bug: not corrected */
e2ec3f97 336 "\"\\uFFFD\\uFFFD\"",
3960c41f
MA
337 },
338 /* 3.1.4 3 continuation bytes */
339 {
340 "\"\x80\xBF\x80\"",
341 "\x80\xBF\x80", /* bug: not corrected */
e2ec3f97 342 "\"\\uFFFD\\uFFFD\\uFFFD\"",
3960c41f
MA
343 },
344 /* 3.1.5 4 continuation bytes */
345 {
346 "\"\x80\xBF\x80\xBF\"",
347 "\x80\xBF\x80\xBF", /* bug: not corrected */
e2ec3f97 348 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
3960c41f
MA
349 },
350 /* 3.1.6 5 continuation bytes */
351 {
352 "\"\x80\xBF\x80\xBF\x80\"",
353 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
e2ec3f97 354 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 360 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 366 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
3960c41f
MA
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",
e2ec3f97
MA
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\""
3960c41f
MA
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 */
e2ec3f97
MA
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 \"",
3960c41f
MA
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 ",
e2ec3f97
MA
420 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
421 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
3960c41f
MA
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 */
e2ec3f97 427 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
3960c41f
MA
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 */
e2ec3f97 434 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
3960c41f
MA
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 */
e2ec3f97 441 "\"\\uFFFD \\uFFFD \"",
3960c41f
MA
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 */
e2ec3f97 449 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 456 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 462 "\"\\uFFFD\"",
3960c41f
MA
463 },
464 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
465 {
d6244e2c 466 "\"\xF8\x80\x80\x80\"",
3960c41f 467 NULL, /* bug: rejected */
e2ec3f97 468 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 475 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 482 "\"\\uFFFD\"",
3960c41f
MA
483 },
484 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
485 {
486 "\"\xEF\xBF\"",
487 "\xEF\xBF", /* bug: not corrected */
e2ec3f97 488 "\"\\uFFFD\"",
3960c41f
MA
489 },
490 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
491 {
492 "\"\xF7\xBF\xBF\"",
493 NULL, /* bug: rejected */
e2ec3f97 494 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 501 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 508 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97
MA
516 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
517 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 525 "\"\\uFFFD\"",
3960c41f
MA
526 "\xFE",
527 },
528 {
529 "\"\xFF\"",
530 NULL, /* bug: rejected */
e2ec3f97 531 "\"\\uFFFD\"",
3960c41f
MA
532 "\xFF",
533 },
534 {
535 "\"\xFE\xFE\xFF\xFF\"",
536 NULL, /* bug: rejected */
e2ec3f97 537 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
3960c41f
MA
538 "\xFE\xFE\xFF\xFF",
539 },
540 /* 4 Overlong sequences */
541 /* 4.1 Overlong '/' */
542 {
543 "\"\xC0\xAF\"",
544 NULL, /* bug: rejected */
e2ec3f97 545 "\"\\uFFFD\"",
3960c41f
MA
546 "\xC0\xAF",
547 },
548 {
549 "\"\xE0\x80\xAF\"",
550 "\xE0\x80\xAF", /* bug: not corrected */
e2ec3f97 551 "\"\\uFFFD\"",
3960c41f
MA
552 },
553 {
554 "\"\xF0\x80\x80\xAF\"",
555 "\xF0\x80\x80\xAF", /* bug: not corrected */
e2ec3f97 556 "\"\\uFFFD\"",
3960c41f
MA
557 },
558 {
559 "\"\xF8\x80\x80\x80\xAF\"",
560 NULL, /* bug: rejected */
e2ec3f97 561 "\"\\uFFFD\"",
3960c41f
MA
562 "\xF8\x80\x80\x80\xAF",
563 },
564 {
565 "\"\xFC\x80\x80\x80\x80\xAF\"",
566 NULL, /* bug: rejected */
e2ec3f97 567 "\"\\uFFFD\"",
3960c41f
MA
568 "\xFC\x80\x80\x80\x80\xAF",
569 },
d6244e2c
MA
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 */
3960c41f
MA
576 {
577 /* \U+007F */
578 "\"\xC1\xBF\"",
579 NULL, /* bug: rejected */
e2ec3f97 580 "\"\\uFFFD\"",
3960c41f
MA
581 "\xC1\xBF",
582 },
583 {
584 /* \U+07FF */
585 "\"\xE0\x9F\xBF\"",
586 "\xE0\x9F\xBF", /* bug: not corrected */
e2ec3f97 587 "\"\\uFFFD\"",
3960c41f
MA
588 },
589 {
1d50c8e9
MA
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 */
e2ec3f97 598 "\"\\uFFFD\"",
3960c41f
MA
599 },
600 {
601 /* \U+1FFFFF */
602 "\"\xF8\x87\xBF\xBF\xBF\"",
603 NULL, /* bug: rejected */
e2ec3f97 604 "\"\\uFFFD\"",
3960c41f
MA
605 "\xF8\x87\xBF\xBF\xBF",
606 },
607 {
608 /* \U+3FFFFFF */
609 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
610 NULL, /* bug: rejected */
e2ec3f97 611 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 626 "\"\\uFFFD\"",
3960c41f
MA
627 },
628 {
629 /* \U+0000 */
630 "\"\xF0\x80\x80\x80\"",
631 "\xF0\x80\x80\x80", /* bug: not corrected */
e2ec3f97 632 "\"\\uFFFD\"",
3960c41f
MA
633 },
634 {
635 /* \U+0000 */
636 "\"\xF8\x80\x80\x80\x80\"",
637 NULL, /* bug: rejected */
e2ec3f97 638 "\"\\uFFFD\"",
3960c41f
MA
639 "\xF8\x80\x80\x80\x80",
640 },
641 {
642 /* \U+0000 */
643 "\"\xFC\x80\x80\x80\x80\x80\"",
644 NULL, /* bug: rejected */
e2ec3f97 645 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 654 "\"\\uFFFD\"",
3960c41f
MA
655 },
656 {
657 /* \U+DB7F */
658 "\"\xED\xAD\xBF\"",
659 "\xED\xAD\xBF", /* bug: not corrected */
e2ec3f97 660 "\"\\uFFFD\"",
3960c41f
MA
661 },
662 {
663 /* \U+DB80 */
664 "\"\xED\xAE\x80\"",
665 "\xED\xAE\x80", /* bug: not corrected */
e2ec3f97 666 "\"\\uFFFD\"",
3960c41f
MA
667 },
668 {
669 /* \U+DBFF */
670 "\"\xED\xAF\xBF\"",
671 "\xED\xAF\xBF", /* bug: not corrected */
e2ec3f97 672 "\"\\uFFFD\"",
3960c41f
MA
673 },
674 {
675 /* \U+DC00 */
676 "\"\xED\xB0\x80\"",
677 "\xED\xB0\x80", /* bug: not corrected */
e2ec3f97 678 "\"\\uFFFD\"",
3960c41f
MA
679 },
680 {
681 /* \U+DF80 */
682 "\"\xED\xBE\x80\"",
683 "\xED\xBE\x80", /* bug: not corrected */
e2ec3f97 684 "\"\\uFFFD\"",
3960c41f
MA
685 },
686 {
687 /* \U+DFFF */
688 "\"\xED\xBF\xBF\"",
689 "\xED\xBF\xBF", /* bug: not corrected */
e2ec3f97 690 "\"\\uFFFD\"",
3960c41f
MA
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 */
e2ec3f97 697 "\"\\uFFFD\\uFFFD\"",
3960c41f
MA
698 },
699 {
700 /* \U+D800\U+DFFF */
701 "\"\xED\xA0\x80\xED\xBF\xBF\"",
702 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
e2ec3f97 703 "\"\\uFFFD\\uFFFD\"",
3960c41f
MA
704 },
705 {
706 /* \U+DB7F\U+DC00 */
707 "\"\xED\xAD\xBF\xED\xB0\x80\"",
708 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
e2ec3f97 709 "\"\\uFFFD\\uFFFD\"",
3960c41f
MA
710 },
711 {
712 /* \U+DB7F\U+DFFF */
713 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
714 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
e2ec3f97 715 "\"\\uFFFD\\uFFFD\"",
3960c41f
MA
716 },
717 {
718 /* \U+DB80\U+DC00 */
719 "\"\xED\xAE\x80\xED\xB0\x80\"",
720 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
e2ec3f97 721 "\"\\uFFFD\\uFFFD\"",
3960c41f
MA
722 },
723 {
724 /* \U+DB80\U+DFFF */
725 "\"\xED\xAE\x80\xED\xBF\xBF\"",
726 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
e2ec3f97 727 "\"\\uFFFD\\uFFFD\"",
3960c41f
MA
728 },
729 {
730 /* \U+DBFF\U+DC00 */
731 "\"\xED\xAF\xBF\xED\xB0\x80\"",
732 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
e2ec3f97 733 "\"\\uFFFD\\uFFFD\"",
3960c41f
MA
734 },
735 {
736 /* \U+DBFF\U+DFFF */
737 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
738 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
e2ec3f97 739 "\"\\uFFFD\\uFFFD\"",
3960c41f
MA
740 },
741 /* 5.3 Other illegal code positions */
1d50c8e9 742 /* BMP noncharacters */
3960c41f
MA
743 {
744 /* \U+FFFE */
745 "\"\xEF\xBF\xBE\"",
746 "\xEF\xBF\xBE", /* bug: not corrected */
e2ec3f97 747 "\"\\uFFFD\"",
3960c41f
MA
748 },
749 {
750 /* \U+FFFF */
751 "\"\xEF\xBF\xBF\"",
752 "\xEF\xBF\xBF", /* bug: not corrected */
e2ec3f97 753 "\"\\uFFFD\"",
3960c41f 754 },
1d50c8e9
MA
755 {
756 /* U+FDD0 */
757 "\"\xEF\xB7\x90\"",
758 "\xEF\xB7\x90", /* bug: not corrected */
e2ec3f97 759 "\"\\uFFFD\"",
1d50c8e9
MA
760 },
761 {
762 /* U+FDEF */
763 "\"\xEF\xB7\xAF\"",
764 "\xEF\xB7\xAF", /* bug: not corrected */
e2ec3f97 765 "\"\\uFFFD\"",
1d50c8e9
MA
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",
e2ec3f97
MA
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\"",
1d50c8e9 807 },
3960c41f
MA
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 /*
e2ec3f97
MA
844 * Disabled, because qobject_from_json() is buggy, and I can't
845 * be bothered to add the expected incorrect results.
3960c41f
MA
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
ef76dc59 858static void vararg_string(void)
422c46a8
AL
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
ef76dc59
AL
875 g_assert(obj != NULL);
876 g_assert(qobject_type(obj) == QTYPE_QSTRING);
422c46a8
AL
877
878 str = qobject_to_qstring(obj);
ef76dc59 879 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
422c46a8
AL
880
881 QDECREF(str);
882 }
883}
422c46a8 884
ef76dc59 885static void simple_number(void)
422c46a8
AL
886{
887 int i;
888 struct {
889 const char *encoded;
890 int64_t decoded;
6ee59202 891 int skip;
422c46a8
AL
892 } test_cases[] = {
893 { "0", 0 },
894 { "1234", 1234 },
895 { "1", 1 },
896 { "-32", -32 },
6ee59202 897 { "-0", 0, .skip = 1 },
422c46a8
AL
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);
ef76dc59
AL
906 g_assert(obj != NULL);
907 g_assert(qobject_type(obj) == QTYPE_QINT);
422c46a8
AL
908
909 qint = qobject_to_qint(obj);
ef76dc59 910 g_assert(qint_get_int(qint) == test_cases[i].decoded);
6ee59202
AL
911 if (test_cases[i].skip == 0) {
912 QString *str;
913
914 str = qobject_to_json(obj);
ef76dc59 915 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
6ee59202
AL
916 QDECREF(str);
917 }
422c46a8
AL
918
919 QDECREF(qint);
920 }
921}
422c46a8 922
ef76dc59 923static void float_number(void)
422c46a8
AL
924{
925 int i;
926 struct {
927 const char *encoded;
928 double decoded;
6ee59202 929 int skip;
422c46a8
AL
930 } test_cases[] = {
931 { "32.43", 32.43 },
932 { "0.222", 0.222 },
933 { "-32.12313", -32.12313 },
6ee59202 934 { "-32.20e-10", -32.20e-10, .skip = 1 },
422c46a8
AL
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);
ef76dc59
AL
943 g_assert(obj != NULL);
944 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
422c46a8
AL
945
946 qfloat = qobject_to_qfloat(obj);
ef76dc59 947 g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
422c46a8 948
6ee59202
AL
949 if (test_cases[i].skip == 0) {
950 QString *str;
951
952 str = qobject_to_json(obj);
ef76dc59 953 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
6ee59202
AL
954 QDECREF(str);
955 }
956
422c46a8
AL
957 QDECREF(qfloat);
958 }
959}
422c46a8 960
ef76dc59 961static void vararg_number(void)
422c46a8
AL
962{
963 QObject *obj;
964 QInt *qint;
965 QFloat *qfloat;
966 int value = 0x2342;
29a6731a 967 long long value_ll = 0x2342342343LL;
422c46a8
AL
968 double valuef = 2.323423423;
969
970 obj = qobject_from_jsonf("%d", value);
ef76dc59
AL
971 g_assert(obj != NULL);
972 g_assert(qobject_type(obj) == QTYPE_QINT);
422c46a8
AL
973
974 qint = qobject_to_qint(obj);
ef76dc59 975 g_assert(qint_get_int(qint) == value);
422c46a8
AL
976
977 QDECREF(qint);
978
29a6731a 979 obj = qobject_from_jsonf("%lld", value_ll);
ef76dc59
AL
980 g_assert(obj != NULL);
981 g_assert(qobject_type(obj) == QTYPE_QINT);
422c46a8
AL
982
983 qint = qobject_to_qint(obj);
29a6731a 984 g_assert(qint_get_int(qint) == value_ll);
422c46a8
AL
985
986 QDECREF(qint);
987
988 obj = qobject_from_jsonf("%f", valuef);
ef76dc59
AL
989 g_assert(obj != NULL);
990 g_assert(qobject_type(obj) == QTYPE_QFLOAT);
422c46a8
AL
991
992 qfloat = qobject_to_qfloat(obj);
ef76dc59 993 g_assert(qfloat_get_double(qfloat) == valuef);
422c46a8
AL
994
995 QDECREF(qfloat);
996}
422c46a8 997
ef76dc59 998static void keyword_literal(void)
422c46a8
AL
999{
1000 QObject *obj;
1001 QBool *qbool;
e549e716 1002 QObject *null;
6ee59202 1003 QString *str;
422c46a8
AL
1004
1005 obj = qobject_from_json("true");
ef76dc59
AL
1006 g_assert(obj != NULL);
1007 g_assert(qobject_type(obj) == QTYPE_QBOOL);
422c46a8
AL
1008
1009 qbool = qobject_to_qbool(obj);
fc48ffc3 1010 g_assert(qbool_get_bool(qbool) == true);
422c46a8 1011
6ee59202 1012 str = qobject_to_json(obj);
ef76dc59 1013 g_assert(strcmp(qstring_get_str(str), "true") == 0);
6ee59202
AL
1014 QDECREF(str);
1015
422c46a8
AL
1016 QDECREF(qbool);
1017
1018 obj = qobject_from_json("false");
ef76dc59
AL
1019 g_assert(obj != NULL);
1020 g_assert(qobject_type(obj) == QTYPE_QBOOL);
422c46a8
AL
1021
1022 qbool = qobject_to_qbool(obj);
fc48ffc3 1023 g_assert(qbool_get_bool(qbool) == false);
422c46a8 1024
6ee59202 1025 str = qobject_to_json(obj);
ef76dc59 1026 g_assert(strcmp(qstring_get_str(str), "false") == 0);
6ee59202
AL
1027 QDECREF(str);
1028
422c46a8
AL
1029 QDECREF(qbool);
1030
1031 obj = qobject_from_jsonf("%i", false);
ef76dc59
AL
1032 g_assert(obj != NULL);
1033 g_assert(qobject_type(obj) == QTYPE_QBOOL);
422c46a8
AL
1034
1035 qbool = qobject_to_qbool(obj);
fc48ffc3 1036 g_assert(qbool_get_bool(qbool) == false);
422c46a8
AL
1037
1038 QDECREF(qbool);
e549e716 1039
fc48ffc3
EB
1040 /* Test that non-zero values other than 1 get collapsed to true */
1041 obj = qobject_from_jsonf("%i", 2);
ef76dc59
AL
1042 g_assert(obj != NULL);
1043 g_assert(qobject_type(obj) == QTYPE_QBOOL);
422c46a8
AL
1044
1045 qbool = qobject_to_qbool(obj);
fc48ffc3 1046 g_assert(qbool_get_bool(qbool) == true);
422c46a8
AL
1047
1048 QDECREF(qbool);
e549e716
EB
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);
422c46a8 1059}
422c46a8
AL
1060
1061typedef struct LiteralQDictEntry LiteralQDictEntry;
1062typedef struct LiteralQObject LiteralQObject;
1063
1064struct 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
1075struct 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
1086typedef struct QListCompareHelper
1087{
1088 int index;
1089 LiteralQObject *objs;
1090 int result;
1091} QListCompareHelper;
1092
1093static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1094
1095static 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
1111static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1112{
9eaaf971 1113 if (!rhs || lhs->type != qobject_type(rhs)) {
422c46a8
AL
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
ef76dc59 1153static void simple_dict(void)
422c46a8
AL
1154{
1155 int i;
1156 struct {
1157 const char *encoded;
1158 LiteralQObject decoded;
1159 } test_cases[] = {
1160 {
6ee59202 1161 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
422c46a8
AL
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 }, {
6ee59202 1173 .encoded = "{\"foo\": 43}",
422c46a8
AL
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;
6ee59202 1184 QString *str;
422c46a8
AL
1185
1186 obj = qobject_from_json(test_cases[i].encoded);
ef76dc59 1187 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1188
6ee59202
AL
1189 str = qobject_to_json(obj);
1190 qobject_decref(obj);
1191
1192 obj = qobject_from_json(qstring_get_str(str));
ef76dc59 1193 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1194 qobject_decref(obj);
6ee59202 1195 QDECREF(str);
422c46a8
AL
1196 }
1197}
422c46a8 1198
7109edfe
MR
1199/*
1200 * this generates json of the form:
1201 * a(0,m) = [0, 1, ..., m-1]
1202 * a(n,m) = {
1203 * 'key0': a(0,m),
1204 * 'key1': a(1,m),
1205 * ...
1206 * 'key(n-1)': a(n-1,m)
1207 * }
1208 */
1209static void gen_test_json(GString *gstr, int nest_level_max,
1210 int elem_count)
1211{
1212 int i;
1213
1214 g_assert(gstr);
1215 if (nest_level_max == 0) {
1216 g_string_append(gstr, "[");
1217 for (i = 0; i < elem_count; i++) {
1218 g_string_append_printf(gstr, "%d", i);
1219 if (i < elem_count - 1) {
1220 g_string_append_printf(gstr, ", ");
1221 }
1222 }
1223 g_string_append(gstr, "]");
1224 return;
1225 }
1226
1227 g_string_append(gstr, "{");
1228 for (i = 0; i < nest_level_max; i++) {
1229 g_string_append_printf(gstr, "'key%d': ", i);
1230 gen_test_json(gstr, i, elem_count);
1231 if (i < nest_level_max - 1) {
1232 g_string_append(gstr, ",");
1233 }
1234 }
1235 g_string_append(gstr, "}");
1236}
1237
1238static void large_dict(void)
1239{
1240 GString *gstr = g_string_new("");
1241 QObject *obj;
1242
1243 gen_test_json(gstr, 10, 100);
1244 obj = qobject_from_json(gstr->str);
1245 g_assert(obj != NULL);
1246
1247 qobject_decref(obj);
1248 g_string_free(gstr, true);
1249}
1250
ef76dc59 1251static void simple_list(void)
422c46a8
AL
1252{
1253 int i;
1254 struct {
1255 const char *encoded;
1256 LiteralQObject decoded;
1257 } test_cases[] = {
1258 {
1259 .encoded = "[43,42]",
1260 .decoded = QLIT_QLIST(((LiteralQObject[]){
1261 QLIT_QINT(43),
1262 QLIT_QINT(42),
1263 { }
1264 })),
1265 },
1266 {
1267 .encoded = "[43]",
1268 .decoded = QLIT_QLIST(((LiteralQObject[]){
1269 QLIT_QINT(43),
1270 { }
1271 })),
1272 },
1273 {
1274 .encoded = "[]",
1275 .decoded = QLIT_QLIST(((LiteralQObject[]){
1276 { }
1277 })),
1278 },
1279 {
1280 .encoded = "[{}]",
1281 .decoded = QLIT_QLIST(((LiteralQObject[]){
1282 QLIT_QDICT(((LiteralQDictEntry[]){
1283 {},
1284 })),
1285 {},
1286 })),
1287 },
1288 { }
1289 };
1290
1291 for (i = 0; test_cases[i].encoded; i++) {
1292 QObject *obj;
6ee59202 1293 QString *str;
422c46a8
AL
1294
1295 obj = qobject_from_json(test_cases[i].encoded);
ef76dc59 1296 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1297
6ee59202
AL
1298 str = qobject_to_json(obj);
1299 qobject_decref(obj);
1300
1301 obj = qobject_from_json(qstring_get_str(str));
ef76dc59 1302 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1303 qobject_decref(obj);
6ee59202 1304 QDECREF(str);
422c46a8
AL
1305 }
1306}
422c46a8 1307
ef76dc59 1308static void simple_whitespace(void)
422c46a8
AL
1309{
1310 int i;
1311 struct {
1312 const char *encoded;
1313 LiteralQObject decoded;
1314 } test_cases[] = {
1315 {
1316 .encoded = " [ 43 , 42 ]",
1317 .decoded = QLIT_QLIST(((LiteralQObject[]){
1318 QLIT_QINT(43),
1319 QLIT_QINT(42),
1320 { }
1321 })),
1322 },
1323 {
1324 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1325 .decoded = QLIT_QLIST(((LiteralQObject[]){
1326 QLIT_QINT(43),
1327 QLIT_QDICT(((LiteralQDictEntry[]){
1328 { "h", QLIT_QSTR("b") },
1329 { }})),
1330 QLIT_QLIST(((LiteralQObject[]){
1331 { }})),
1332 QLIT_QINT(42),
1333 { }
1334 })),
1335 },
1336 {
1337 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1338 .decoded = QLIT_QLIST(((LiteralQObject[]){
1339 QLIT_QINT(43),
1340 QLIT_QDICT(((LiteralQDictEntry[]){
1341 { "h", QLIT_QSTR("b") },
1342 { "a", QLIT_QINT(32) },
1343 { }})),
1344 QLIT_QLIST(((LiteralQObject[]){
1345 { }})),
1346 QLIT_QINT(42),
1347 { }
1348 })),
1349 },
1350 { }
1351 };
1352
1353 for (i = 0; test_cases[i].encoded; i++) {
1354 QObject *obj;
6ee59202 1355 QString *str;
422c46a8
AL
1356
1357 obj = qobject_from_json(test_cases[i].encoded);
ef76dc59 1358 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1359
6ee59202 1360 str = qobject_to_json(obj);
422c46a8 1361 qobject_decref(obj);
6ee59202
AL
1362
1363 obj = qobject_from_json(qstring_get_str(str));
ef76dc59 1364 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
6ee59202
AL
1365
1366 qobject_decref(obj);
1367 QDECREF(str);
422c46a8
AL
1368 }
1369}
422c46a8 1370
ef76dc59 1371static void simple_varargs(void)
422c46a8
AL
1372{
1373 QObject *embedded_obj;
1374 QObject *obj;
1375 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1376 QLIT_QINT(1),
1377 QLIT_QINT(2),
1378 QLIT_QLIST(((LiteralQObject[]){
1379 QLIT_QINT(32),
1380 QLIT_QINT(42),
1381 {}})),
1382 {}}));
1383
1384 embedded_obj = qobject_from_json("[32, 42]");
ef76dc59 1385 g_assert(embedded_obj != NULL);
422c46a8
AL
1386
1387 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
ef76dc59 1388 g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
422c46a8
AL
1389
1390 qobject_decref(obj);
1391}
422c46a8 1392
ef76dc59 1393static void empty_input(void)
7f8fca7c 1394{
e7a06af8
JK
1395 const char *empty = "";
1396
1397 QObject *obj = qobject_from_json(empty);
ef76dc59 1398 g_assert(obj == NULL);
7f8fca7c 1399}
7f8fca7c 1400
ef76dc59 1401static void unterminated_string(void)
7f8fca7c
PB
1402{
1403 QObject *obj = qobject_from_json("\"abc");
ef76dc59 1404 g_assert(obj == NULL);
7f8fca7c 1405}
7f8fca7c 1406
ef76dc59 1407static void unterminated_sq_string(void)
7f8fca7c
PB
1408{
1409 QObject *obj = qobject_from_json("'abc");
ef76dc59 1410 g_assert(obj == NULL);
7f8fca7c 1411}
7f8fca7c 1412
ef76dc59 1413static void unterminated_escape(void)
7f8fca7c
PB
1414{
1415 QObject *obj = qobject_from_json("\"abc\\\"");
ef76dc59 1416 g_assert(obj == NULL);
7f8fca7c 1417}
7f8fca7c 1418
ef76dc59 1419static void unterminated_array(void)
7f8fca7c
PB
1420{
1421 QObject *obj = qobject_from_json("[32");
ef76dc59 1422 g_assert(obj == NULL);
7f8fca7c 1423}
7f8fca7c 1424
ef76dc59 1425static void unterminated_array_comma(void)
7f8fca7c
PB
1426{
1427 QObject *obj = qobject_from_json("[32,");
ef76dc59 1428 g_assert(obj == NULL);
7f8fca7c 1429}
7f8fca7c 1430
ef76dc59 1431static void invalid_array_comma(void)
7f8fca7c
PB
1432{
1433 QObject *obj = qobject_from_json("[32,}");
ef76dc59 1434 g_assert(obj == NULL);
7f8fca7c 1435}
7f8fca7c 1436
ef76dc59 1437static void unterminated_dict(void)
7f8fca7c
PB
1438{
1439 QObject *obj = qobject_from_json("{'abc':32");
ef76dc59 1440 g_assert(obj == NULL);
7f8fca7c 1441}
7f8fca7c 1442
ef76dc59 1443static void unterminated_dict_comma(void)
7f8fca7c
PB
1444{
1445 QObject *obj = qobject_from_json("{'abc':32,");
ef76dc59 1446 g_assert(obj == NULL);
7f8fca7c 1447}
7f8fca7c 1448
ef76dc59 1449static void invalid_dict_comma(void)
7f8fca7c
PB
1450{
1451 QObject *obj = qobject_from_json("{'abc':32,}");
ef76dc59 1452 g_assert(obj == NULL);
7f8fca7c 1453}
7f8fca7c 1454
ef76dc59 1455static void unterminated_literal(void)
7f8fca7c
PB
1456{
1457 QObject *obj = qobject_from_json("nul");
ef76dc59 1458 g_assert(obj == NULL);
7f8fca7c 1459}
7f8fca7c 1460
f0ae0304
MA
1461static char *make_nest(char *buf, size_t cnt)
1462{
1463 memset(buf, '[', cnt - 1);
1464 buf[cnt - 1] = '{';
1465 buf[cnt] = '}';
1466 memset(buf + cnt + 1, ']', cnt - 1);
1467 buf[2 * cnt] = 0;
1468 return buf;
1469}
1470
1471static void limits_nesting(void)
1472{
1473 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1474 char buf[2 * (max_nesting + 1) + 1];
1475 QObject *obj;
1476
1477 obj = qobject_from_json(make_nest(buf, max_nesting));
1478 g_assert(obj != NULL);
1479 qobject_decref(obj);
1480
1481 obj = qobject_from_json(make_nest(buf, max_nesting + 1));
1482 g_assert(obj == NULL);
1483}
1484
ef76dc59 1485int main(int argc, char **argv)
422c46a8 1486{
ef76dc59
AL
1487 g_test_init(&argc, &argv, NULL);
1488
1489 g_test_add_func("/literals/string/simple", simple_string);
1490 g_test_add_func("/literals/string/escaped", escaped_string);
3960c41f 1491 g_test_add_func("/literals/string/utf8", utf8_string);
ef76dc59
AL
1492 g_test_add_func("/literals/string/single_quote", single_quote_string);
1493 g_test_add_func("/literals/string/vararg", vararg_string);
1494
1495 g_test_add_func("/literals/number/simple", simple_number);
1496 g_test_add_func("/literals/number/float", float_number);
1497 g_test_add_func("/literals/number/vararg", vararg_number);
1498
1499 g_test_add_func("/literals/keyword", keyword_literal);
1500
1501 g_test_add_func("/dicts/simple_dict", simple_dict);
7109edfe 1502 g_test_add_func("/dicts/large_dict", large_dict);
ef76dc59
AL
1503 g_test_add_func("/lists/simple_list", simple_list);
1504
1505 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1506
1507 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1508
1509 g_test_add_func("/errors/empty_input", empty_input);
1510 g_test_add_func("/errors/unterminated/string", unterminated_string);
1511 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1512 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1513 g_test_add_func("/errors/unterminated/array", unterminated_array);
1514 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1515 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1516 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1517 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
ef76dc59
AL
1518 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1519 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
f0ae0304 1520 g_test_add_func("/errors/limits/nesting", limits_nesting);
7f8fca7c 1521
ef76dc59 1522 return g_test_run();
422c46a8 1523}