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