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