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