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