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