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