]> git.proxmox.com Git - mirror_qemu.git/blame - tests/check-qjson.c
virtio-balloon: convert VMSTATE_VIRTIO_DEVICE
[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;
967 int64_t value64 = 0x2342342343LL;
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
979 obj = qobject_from_jsonf("%" PRId64, value64);
ef76dc59
AL
980 g_assert(obj != NULL);
981 g_assert(qobject_type(obj) == QTYPE_QINT);
422c46a8
AL
982
983 qint = qobject_to_qint(obj);
ef76dc59 984 g_assert(qint_get_int(qint) == value64);
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{
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
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
AL
1187 g_assert(obj != NULL);
1188 g_assert(qobject_type(obj) == QTYPE_QDICT);
422c46a8 1189
ef76dc59 1190 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1191
6ee59202
AL
1192 str = qobject_to_json(obj);
1193 qobject_decref(obj);
1194
1195 obj = qobject_from_json(qstring_get_str(str));
ef76dc59
AL
1196 g_assert(obj != NULL);
1197 g_assert(qobject_type(obj) == QTYPE_QDICT);
6ee59202 1198
ef76dc59 1199 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1200 qobject_decref(obj);
6ee59202 1201 QDECREF(str);
422c46a8
AL
1202 }
1203}
422c46a8 1204
7109edfe
MR
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 */
1215static 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
1244static 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
ef76dc59 1257static void simple_list(void)
422c46a8
AL
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;
6ee59202 1299 QString *str;
422c46a8
AL
1300
1301 obj = qobject_from_json(test_cases[i].encoded);
ef76dc59
AL
1302 g_assert(obj != NULL);
1303 g_assert(qobject_type(obj) == QTYPE_QLIST);
422c46a8 1304
ef76dc59 1305 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1306
6ee59202
AL
1307 str = qobject_to_json(obj);
1308 qobject_decref(obj);
1309
1310 obj = qobject_from_json(qstring_get_str(str));
ef76dc59
AL
1311 g_assert(obj != NULL);
1312 g_assert(qobject_type(obj) == QTYPE_QLIST);
6ee59202 1313
ef76dc59 1314 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1315 qobject_decref(obj);
6ee59202 1316 QDECREF(str);
422c46a8
AL
1317 }
1318}
422c46a8 1319
ef76dc59 1320static void simple_whitespace(void)
422c46a8
AL
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;
6ee59202 1367 QString *str;
422c46a8
AL
1368
1369 obj = qobject_from_json(test_cases[i].encoded);
ef76dc59
AL
1370 g_assert(obj != NULL);
1371 g_assert(qobject_type(obj) == QTYPE_QLIST);
422c46a8 1372
ef76dc59 1373 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
422c46a8 1374
6ee59202 1375 str = qobject_to_json(obj);
422c46a8 1376 qobject_decref(obj);
6ee59202
AL
1377
1378 obj = qobject_from_json(qstring_get_str(str));
ef76dc59
AL
1379 g_assert(obj != NULL);
1380 g_assert(qobject_type(obj) == QTYPE_QLIST);
6ee59202 1381
ef76dc59 1382 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
6ee59202
AL
1383
1384 qobject_decref(obj);
1385 QDECREF(str);
422c46a8
AL
1386 }
1387}
422c46a8 1388
ef76dc59 1389static void simple_varargs(void)
422c46a8
AL
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]");
ef76dc59 1403 g_assert(embedded_obj != NULL);
422c46a8
AL
1404
1405 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
ef76dc59 1406 g_assert(obj != NULL);
422c46a8 1407
ef76dc59 1408 g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
422c46a8
AL
1409
1410 qobject_decref(obj);
1411}
422c46a8 1412
ef76dc59 1413static void empty_input(void)
7f8fca7c 1414{
e7a06af8
JK
1415 const char *empty = "";
1416
1417 QObject *obj = qobject_from_json(empty);
ef76dc59 1418 g_assert(obj == NULL);
7f8fca7c 1419}
7f8fca7c 1420
ef76dc59 1421static void unterminated_string(void)
7f8fca7c
PB
1422{
1423 QObject *obj = qobject_from_json("\"abc");
ef76dc59 1424 g_assert(obj == NULL);
7f8fca7c 1425}
7f8fca7c 1426
ef76dc59 1427static void unterminated_sq_string(void)
7f8fca7c
PB
1428{
1429 QObject *obj = qobject_from_json("'abc");
ef76dc59 1430 g_assert(obj == NULL);
7f8fca7c 1431}
7f8fca7c 1432
ef76dc59 1433static void unterminated_escape(void)
7f8fca7c
PB
1434{
1435 QObject *obj = qobject_from_json("\"abc\\\"");
ef76dc59 1436 g_assert(obj == NULL);
7f8fca7c 1437}
7f8fca7c 1438
ef76dc59 1439static void unterminated_array(void)
7f8fca7c
PB
1440{
1441 QObject *obj = qobject_from_json("[32");
ef76dc59 1442 g_assert(obj == NULL);
7f8fca7c 1443}
7f8fca7c 1444
ef76dc59 1445static void unterminated_array_comma(void)
7f8fca7c
PB
1446{
1447 QObject *obj = qobject_from_json("[32,");
ef76dc59 1448 g_assert(obj == NULL);
7f8fca7c 1449}
7f8fca7c 1450
ef76dc59 1451static void invalid_array_comma(void)
7f8fca7c
PB
1452{
1453 QObject *obj = qobject_from_json("[32,}");
ef76dc59 1454 g_assert(obj == NULL);
7f8fca7c 1455}
7f8fca7c 1456
ef76dc59 1457static void unterminated_dict(void)
7f8fca7c
PB
1458{
1459 QObject *obj = qobject_from_json("{'abc':32");
ef76dc59 1460 g_assert(obj == NULL);
7f8fca7c 1461}
7f8fca7c 1462
ef76dc59 1463static void unterminated_dict_comma(void)
7f8fca7c
PB
1464{
1465 QObject *obj = qobject_from_json("{'abc':32,");
ef76dc59 1466 g_assert(obj == NULL);
7f8fca7c 1467}
7f8fca7c 1468
ef76dc59 1469static void invalid_dict_comma(void)
7f8fca7c
PB
1470{
1471 QObject *obj = qobject_from_json("{'abc':32,}");
ef76dc59 1472 g_assert(obj == NULL);
7f8fca7c 1473}
7f8fca7c 1474
ef76dc59 1475static void unterminated_literal(void)
7f8fca7c
PB
1476{
1477 QObject *obj = qobject_from_json("nul");
ef76dc59 1478 g_assert(obj == NULL);
7f8fca7c 1479}
7f8fca7c 1480
f0ae0304
MA
1481static 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
1491static 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
ef76dc59 1505int main(int argc, char **argv)
422c46a8 1506{
ef76dc59
AL
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);
3960c41f 1511 g_test_add_func("/literals/string/utf8", utf8_string);
ef76dc59
AL
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);
7109edfe 1522 g_test_add_func("/dicts/large_dict", large_dict);
ef76dc59
AL
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);
ef76dc59
AL
1538 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1539 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
f0ae0304 1540 g_test_add_func("/errors/limits/nesting", limits_nesting);
7f8fca7c 1541
ef76dc59 1542 return g_test_run();
422c46a8 1543}