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