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