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