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