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