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