blob: 07a773e6530b561f2ecac7e127ccb8fd690ad740 [file] [log] [blame]
Anthony Liguori422c46a2009-11-11 10:39:47 -06001/*
2 * Copyright IBM, Corp. 2009
Eric Blakee549e712015-04-29 15:35:06 -06003 * Copyright (c) 2013, 2015 Red Hat Inc.
Anthony Liguori422c46a2009-11-11 10:39:47 -06004 *
5 * Authors:
6 * Anthony Liguori <aliguori@us.ibm.com>
Markus Armbrusterd6244e22013-04-11 18:07:19 +02007 * Markus Armbruster <armbru@redhat.com>
Anthony Liguori422c46a2009-11-11 10:39:47 -06008 *
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 */
Markus Armbrusteraec4b052017-02-28 22:27:00 +010013
Peter Maydell681c28a2016-02-08 18:08:51 +000014#include "qemu/osdep.h"
Anthony Liguori422c46a2009-11-11 10:39:47 -060015
Markus Armbrusteraec4b052017-02-28 22:27:00 +010016#include "qapi/error.h"
Markus Armbruster6b673952018-02-01 12:18:35 +010017#include "qapi/qmp/qbool.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010018#include "qapi/qmp/qjson.h"
Marc-André Lureau28035bc2017-08-25 12:59:01 +020019#include "qapi/qmp/qlit.h"
Markus Armbruster15280c32018-02-01 12:18:36 +010020#include "qapi/qmp/qnull.h"
21#include "qapi/qmp/qnum.h"
Markus Armbrusterfc81fa12018-02-01 12:18:40 +010022#include "qapi/qmp/qstring.h"
Markus Armbruster5f454e62018-08-23 18:39:41 +020023#include "qemu/unicode.h"
Anthony Liguori422c46a2009-11-11 10:39:47 -060024#include "qemu-common.h"
25
Markus Armbruster4e1df9b2018-08-23 18:39:35 +020026static 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
Anthony Liguorief76dc52012-01-10 13:10:49 -060051static void escaped_string(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -060052{
Anthony Liguori422c46a2009-11-11 10:39:47 -060053 struct {
Markus Armbruster4e1df9b2018-08-23 18:39:35 +020054 /* 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;
Anthony Liguori6ee59202009-11-11 13:16:03 -060058 int skip;
Anthony Liguori422c46a2009-11-11 10:39:47 -060059 } test_cases[] = {
Markus Armbrusterf3cfdd32018-08-23 18:39:36 +020060 { "\\b\\f\\n\\r\\t\\\\\\\"", "\b\f\n\r\t\\\"" },
Markus Armbrustere0fe2a92018-08-23 18:39:37 +020061 { "\\/\\'", "/'", .skip = 1 },
Markus Armbruster4e1df9b2018-08-23 18:39:35 +020062 { "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" },
Markus Armbrustere0fe2a92018-08-23 18:39:37 +020065 { "quadruple byte utf-8 \\uD834\\uDD1E", /* U+1D11E */
Markus Armbrusterdc45a072018-08-23 18:39:56 +020066 "quadruple byte utf-8 \xF0\x9D\x84\x9E" },
Markus Armbrustere0fe2a92018-08-23 18:39:37 +020067 { "\\", NULL },
68 { "\\z", NULL },
69 { "\\ux", NULL },
70 { "\\u1x", NULL },
71 { "\\u12x", NULL },
72 { "\\u123x", NULL },
73 { "\\u12345", "\341\210\2645" },
Markus Armbruster46a628b2018-08-23 18:39:55 +020074 { "\\u0000x", "\xC0\x80x" },
75 { "unpaired leading surrogate \\uD800", NULL },
76 { "unpaired leading surrogate \\uD800\\uCAFE", NULL },
77 { "unpaired leading surrogate \\uD800\\uD801\\uDC02", NULL },
78 { "unpaired trailing surrogate \\uDC00", NULL },
79 { "backward surrogate pair \\uDC00\\uD800", NULL },
80 { "noncharacter U+FDD0 \\uFDD0", NULL },
81 { "noncharacter U+FDEF \\uFDEF", NULL },
82 { "noncharacter U+1FFFE \\uD87F\\uDFFE", NULL },
83 { "noncharacter U+10FFFF \\uDC3F\\uDFFF", NULL },
Anthony Liguori422c46a2009-11-11 10:39:47 -060084 {}
85 };
Markus Armbruster4e1df9b2018-08-23 18:39:35 +020086 int i, j;
87 QString *cstr;
88 char *jstr;
Anthony Liguori422c46a2009-11-11 10:39:47 -060089
Markus Armbruster4e1df9b2018-08-23 18:39:35 +020090 for (i = 0; test_cases[i].json_in; i++) {
91 for (j = 0; j < 2; j++) {
Markus Armbrustere0fe2a92018-08-23 18:39:37 +020092 if (test_cases[i].utf8_out) {
93 cstr = from_json_str(test_cases[i].json_in, j, &error_abort);
94 g_assert_cmpstr(qstring_get_try_str(cstr),
95 ==, test_cases[i].utf8_out);
96 if (!test_cases[i].skip) {
97 jstr = to_json_str(cstr);
98 g_assert_cmpstr(jstr, ==, test_cases[i].json_in);
99 g_free(jstr);
100 }
101 qobject_unref(cstr);
102 } else {
103 cstr = from_json_str(test_cases[i].json_in, j, NULL);
104 g_assert(!cstr);
Markus Armbruster4e1df9b2018-08-23 18:39:35 +0200105 }
Anthony Liguori6ee59202009-11-11 13:16:03 -0600106 }
Anthony Liguori422c46a2009-11-11 10:39:47 -0600107 }
108}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600109
Markus Armbruster069946f2018-08-23 18:39:38 +0200110static void string_with_quotes(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600111{
Markus Armbruster069946f2018-08-23 18:39:38 +0200112 const char *test_cases[] = {
113 "\"the bee's knees\"",
114 "'double quote \"'",
115 NULL
Anthony Liguori422c46a2009-11-11 10:39:47 -0600116 };
Anthony Liguori422c46a2009-11-11 10:39:47 -0600117 int i;
Markus Armbruster069946f2018-08-23 18:39:38 +0200118 QString *str;
119 char *cstr;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600120
Markus Armbruster069946f2018-08-23 18:39:38 +0200121 for (i = 0; test_cases[i]; i++) {
122 str = qobject_to(QString,
123 qobject_from_json(test_cases[i], &error_abort));
Markus Armbruster363e13f2017-02-17 21:38:20 +0100124 g_assert(str);
Markus Armbruster069946f2018-08-23 18:39:38 +0200125 cstr = g_strndup(test_cases[i] + 1, strlen(test_cases[i]) - 2);
126 g_assert_cmpstr(qstring_get_str(str), ==, cstr);
127 g_free(cstr);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200128 qobject_unref(str);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600129 }
130}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600131
Markus Armbruster3960c412013-02-05 09:30:55 +0100132static void utf8_string(void)
133{
134 /*
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200135 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
Markus Armbruster3960c412013-02-05 09:30:55 +0100136 * capability and stress test at
137 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
138 */
139 static const struct {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200140 /* Content of JSON string to parse with qobject_from_json() */
Markus Armbruster3960c412013-02-05 09:30:55 +0100141 const char *json_in;
Markus Armbruster6ad84442018-08-23 18:39:39 +0200142 /* Expected parse output */
Markus Armbruster3960c412013-02-05 09:30:55 +0100143 const char *utf8_out;
Markus Armbruster6ad84442018-08-23 18:39:39 +0200144 /* Expected unparse output, defaults to @json_in */
145 const char *json_out;
Markus Armbruster3960c412013-02-05 09:30:55 +0100146 } test_cases[] = {
Markus Armbruster6bc93a32018-08-23 18:39:42 +0200147 /* 0 Control characters */
148 {
149 /*
150 * Note: \x00 is impossible, other representations of
151 * U+0000 are covered under 4.3
152 */
153 "\x01\x02\x03\x04\x05\x06\x07"
154 "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
155 "\x10\x11\x12\x13\x14\x15\x16\x17"
156 "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
Markus Armbruster340db1e2018-08-23 18:39:45 +0200157 NULL,
Markus Armbruster6bc93a32018-08-23 18:39:42 +0200158 "\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007"
159 "\\b\\t\\n\\u000B\\f\\r\\u000E\\u000F"
160 "\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017"
161 "\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F",
162 },
Markus Armbruster3960c412013-02-05 09:30:55 +0100163 /* 1 Some correct UTF-8 text */
164 {
165 /* a bit of German */
Markus Armbruster3960c412013-02-05 09:30:55 +0100166 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
167 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200168 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
169 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
170 "Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
171 " jeden gr\\u00F6\\u00DFeren Zwerg.",
Markus Armbruster3960c412013-02-05 09:30:55 +0100172 },
173 {
174 /* a bit of Greek */
Markus Armbruster3960c412013-02-05 09:30:55 +0100175 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200176 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
177 "\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5",
Markus Armbruster3960c412013-02-05 09:30:55 +0100178 },
Christophe Fergeaubbc05862019-01-02 15:05:35 +0100179 /* '%' character when not interpolating */
180 {
181 "100%",
182 "100%",
183 },
Markus Armbruster3960c412013-02-05 09:30:55 +0100184 /* 2 Boundary condition test cases */
185 /* 2.1 First possible sequence of a certain length */
Markus Armbruster32846e92018-08-23 18:39:40 +0200186 /*
Markus Armbruster6bc93a32018-08-23 18:39:42 +0200187 * 2.1.1 1 byte U+0020
188 * Control characters are already covered by their own test
189 * case under 0. Test the first 1 byte non-control character
190 * here.
Markus Armbruster32846e92018-08-23 18:39:40 +0200191 */
Markus Armbruster3960c412013-02-05 09:30:55 +0100192 {
Markus Armbruster6bc93a32018-08-23 18:39:42 +0200193 " ",
194 " ",
Markus Armbruster3960c412013-02-05 09:30:55 +0100195 },
196 /* 2.1.2 2 bytes U+0080 */
197 {
Markus Armbruster3960c412013-02-05 09:30:55 +0100198 "\xC2\x80",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200199 "\xC2\x80",
200 "\\u0080",
Markus Armbruster3960c412013-02-05 09:30:55 +0100201 },
202 /* 2.1.3 3 bytes U+0800 */
203 {
Markus Armbruster3960c412013-02-05 09:30:55 +0100204 "\xE0\xA0\x80",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200205 "\xE0\xA0\x80",
206 "\\u0800",
Markus Armbruster3960c412013-02-05 09:30:55 +0100207 },
208 /* 2.1.4 4 bytes U+10000 */
209 {
Markus Armbruster3960c412013-02-05 09:30:55 +0100210 "\xF0\x90\x80\x80",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200211 "\xF0\x90\x80\x80",
212 "\\uD800\\uDC00",
Markus Armbruster3960c412013-02-05 09:30:55 +0100213 },
214 /* 2.1.5 5 bytes U+200000 */
215 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200216 "\xF8\x88\x80\x80\x80",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200217 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200218 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100219 },
220 /* 2.1.6 6 bytes U+4000000 */
221 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200222 "\xFC\x84\x80\x80\x80\x80",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200223 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200224 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100225 },
226 /* 2.2 Last possible sequence of a certain length */
227 /* 2.2.1 1 byte U+007F */
228 {
Markus Armbruster3960c412013-02-05 09:30:55 +0100229 "\x7F",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200230 "\x7F",
231 "\\u007F",
Markus Armbruster3960c412013-02-05 09:30:55 +0100232 },
233 /* 2.2.2 2 bytes U+07FF */
234 {
Markus Armbruster3960c412013-02-05 09:30:55 +0100235 "\xDF\xBF",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200236 "\xDF\xBF",
237 "\\u07FF",
Markus Armbruster3960c412013-02-05 09:30:55 +0100238 },
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200239 /*
240 * 2.2.3 3 bytes U+FFFC
241 * The last possible sequence is actually U+FFFF. But that's
242 * a noncharacter, and already covered by its own test case
243 * under 5.3. Same for U+FFFE. U+FFFD is the last character
244 * in the BMP, and covered under 2.3. Because of U+FFFD's
245 * special role as replacement character, it's worth testing
246 * U+FFFC here.
247 */
Markus Armbruster3960c412013-02-05 09:30:55 +0100248 {
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200249 "\xEF\xBF\xBC",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200250 "\xEF\xBF\xBC",
251 "\\uFFFC",
Markus Armbruster3960c412013-02-05 09:30:55 +0100252 },
253 /* 2.2.4 4 bytes U+1FFFFF */
254 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200255 "\xF7\xBF\xBF\xBF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200256 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200257 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100258 },
259 /* 2.2.5 5 bytes U+3FFFFFF */
260 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200261 "\xFB\xBF\xBF\xBF\xBF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200262 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200263 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100264 },
265 /* 2.2.6 6 bytes U+7FFFFFFF */
266 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200267 "\xFD\xBF\xBF\xBF\xBF\xBF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200268 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200269 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100270 },
271 /* 2.3 Other boundary conditions */
272 {
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200273 /* last one before surrogate range: U+D7FF */
Markus Armbruster3960c412013-02-05 09:30:55 +0100274 "\xED\x9F\xBF",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200275 "\xED\x9F\xBF",
276 "\\uD7FF",
Markus Armbruster3960c412013-02-05 09:30:55 +0100277 },
278 {
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200279 /* first one after surrogate range: U+E000 */
Markus Armbruster3960c412013-02-05 09:30:55 +0100280 "\xEE\x80\x80",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200281 "\xEE\x80\x80",
282 "\\uE000",
Markus Armbruster3960c412013-02-05 09:30:55 +0100283 },
284 {
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200285 /* last one in BMP: U+FFFD */
Markus Armbruster3960c412013-02-05 09:30:55 +0100286 "\xEF\xBF\xBD",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200287 "\xEF\xBF\xBD",
288 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100289 },
290 {
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200291 /* last one in last plane: U+10FFFD */
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200292 "\xF4\x8F\xBF\xBD",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200293 "\xF4\x8F\xBF\xBD",
294 "\\uDBFF\\uDFFD"
Markus Armbruster3960c412013-02-05 09:30:55 +0100295 },
296 {
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200297 /* first one beyond Unicode range: U+110000 */
Markus Armbruster3960c412013-02-05 09:30:55 +0100298 "\xF4\x90\x80\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200299 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200300 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100301 },
302 /* 3 Malformed sequences */
303 /* 3.1 Unexpected continuation bytes */
304 /* 3.1.1 First continuation byte */
305 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200306 "\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200307 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200308 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100309 },
310 /* 3.1.2 Last continuation byte */
311 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200312 "\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200313 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200314 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100315 },
316 /* 3.1.3 2 continuation bytes */
317 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200318 "\x80\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200319 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200320 "\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100321 },
322 /* 3.1.4 3 continuation bytes */
323 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200324 "\x80\xBF\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200325 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200326 "\\uFFFD\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100327 },
328 /* 3.1.5 4 continuation bytes */
329 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200330 "\x80\xBF\x80\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200331 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200332 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100333 },
334 /* 3.1.6 5 continuation bytes */
335 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200336 "\x80\xBF\x80\xBF\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200337 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200338 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100339 },
340 /* 3.1.7 6 continuation bytes */
341 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200342 "\x80\xBF\x80\xBF\x80\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200343 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200344 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100345 },
346 /* 3.1.8 7 continuation bytes */
347 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200348 "\x80\xBF\x80\xBF\x80\xBF\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200349 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200350 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100351 },
352 /* 3.1.9 Sequence of all 64 possible continuation bytes */
353 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200354 "\x80\x81\x82\x83\x84\x85\x86\x87"
Markus Armbruster3960c412013-02-05 09:30:55 +0100355 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
356 "\x90\x91\x92\x93\x94\x95\x96\x97"
357 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
358 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
359 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
360 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
Markus Armbruster6ad84442018-08-23 18:39:39 +0200361 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200362 NULL,
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200363 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
364 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
365 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
366 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
367 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
368 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
Markus Armbruster6ad84442018-08-23 18:39:39 +0200369 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200370 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100371 },
372 /* 3.2 Lonely start characters */
373 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
374 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200375 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
Markus Armbruster3960c412013-02-05 09:30:55 +0100376 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
377 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
Markus Armbruster6ad84442018-08-23 18:39:39 +0200378 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200379 NULL,
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200380 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
381 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
Markus Armbruster6ad84442018-08-23 18:39:39 +0200382 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
383 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
Markus Armbruster3960c412013-02-05 09:30:55 +0100384 },
385 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
386 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200387 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
388 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200389 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200390 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
391 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
Markus Armbruster3960c412013-02-05 09:30:55 +0100392 },
393 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
394 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200395 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200396 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200397 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
Markus Armbruster3960c412013-02-05 09:30:55 +0100398 },
399 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
400 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200401 "\xF8 \xF9 \xFA \xFB ",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200402 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200403 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD ",
Markus Armbruster3960c412013-02-05 09:30:55 +0100404 },
405 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
406 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200407 "\xFC \xFD ",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200408 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200409 "\\uFFFD \\uFFFD ",
Markus Armbruster3960c412013-02-05 09:30:55 +0100410 },
411 /* 3.3 Sequences with last continuation byte missing */
412 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
413 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200414 "\xC0",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200415 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200416 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100417 },
418 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
419 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200420 "\xE0\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200421 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200422 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100423 },
424 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
425 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200426 "\xF0\x80\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200427 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200428 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100429 },
430 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
431 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200432 "\xF8\x80\x80\x80",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200433 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200434 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100435 },
436 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
437 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200438 "\xFC\x80\x80\x80\x80",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200439 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200440 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100441 },
442 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
443 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200444 "\xDF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200445 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200446 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100447 },
448 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
449 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200450 "\xEF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200451 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200452 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100453 },
454 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
455 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200456 "\xF7\xBF\xBF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200457 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200458 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100459 },
460 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
461 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200462 "\xFB\xBF\xBF\xBF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200463 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200464 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100465 },
466 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
467 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200468 "\xFD\xBF\xBF\xBF\xBF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200469 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200470 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100471 },
472 /* 3.4 Concatenation of incomplete sequences */
473 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200474 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
475 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200476 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200477 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
478 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100479 },
480 /* 3.5 Impossible bytes */
481 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200482 "\xFE",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200483 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200484 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100485 },
486 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200487 "\xFF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200488 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200489 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100490 },
491 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200492 "\xFE\xFE\xFF\xFF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200493 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200494 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100495 },
496 /* 4 Overlong sequences */
497 /* 4.1 Overlong '/' */
498 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200499 "\xC0\xAF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200500 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200501 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100502 },
503 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200504 "\xE0\x80\xAF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200505 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200506 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100507 },
508 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200509 "\xF0\x80\x80\xAF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200510 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200511 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100512 },
513 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200514 "\xF8\x80\x80\x80\xAF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200515 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200516 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100517 },
518 {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200519 "\xFC\x80\x80\x80\x80\xAF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200520 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200521 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100522 },
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200523 /*
524 * 4.2 Maximum overlong sequences
525 * Highest Unicode value that is still resulting in an
526 * overlong sequence if represented with the given number of
527 * bytes. This is a boundary test for safe UTF-8 decoders.
528 */
Markus Armbruster3960c412013-02-05 09:30:55 +0100529 {
530 /* \U+007F */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200531 "\xC1\xBF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200532 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200533 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100534 },
535 {
536 /* \U+07FF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200537 "\xE0\x9F\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200538 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200539 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100540 },
541 {
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200542 /*
543 * \U+FFFC
544 * The actual maximum would be U+FFFF, but that's a
545 * noncharacter. Testing U+FFFC seems more useful. See
546 * also 2.2.3
547 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200548 "\xF0\x8F\xBF\xBC",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200549 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200550 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100551 },
552 {
553 /* \U+1FFFFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200554 "\xF8\x87\xBF\xBF\xBF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200555 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200556 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100557 },
558 {
559 /* \U+3FFFFFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200560 "\xFC\x83\xBF\xBF\xBF\xBF",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200561 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200562 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100563 },
564 /* 4.3 Overlong representation of the NUL character */
565 {
566 /* \U+0000 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200567 "\xC0\x80",
Markus Armbruster4b1c0cd2018-08-23 18:39:52 +0200568 "\xC0\x80",
Markus Armbruster6ad84442018-08-23 18:39:39 +0200569 "\\u0000",
Markus Armbruster3960c412013-02-05 09:30:55 +0100570 },
571 {
572 /* \U+0000 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200573 "\xE0\x80\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200574 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200575 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100576 },
577 {
578 /* \U+0000 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200579 "\xF0\x80\x80\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200580 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200581 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100582 },
583 {
584 /* \U+0000 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200585 "\xF8\x80\x80\x80\x80",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200586 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200587 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100588 },
589 {
590 /* \U+0000 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200591 "\xFC\x80\x80\x80\x80\x80",
Markus Armbrustera89d3102018-08-23 18:39:48 +0200592 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200593 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100594 },
595 /* 5 Illegal code positions */
596 /* 5.1 Single UTF-16 surrogates */
597 {
598 /* \U+D800 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200599 "\xED\xA0\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200600 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200601 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100602 },
603 {
604 /* \U+DB7F */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200605 "\xED\xAD\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200606 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200607 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100608 },
609 {
610 /* \U+DB80 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200611 "\xED\xAE\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200612 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200613 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100614 },
615 {
616 /* \U+DBFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200617 "\xED\xAF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200618 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200619 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100620 },
621 {
622 /* \U+DC00 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200623 "\xED\xB0\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200624 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200625 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100626 },
627 {
628 /* \U+DF80 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200629 "\xED\xBE\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200630 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200631 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100632 },
633 {
634 /* \U+DFFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200635 "\xED\xBF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200636 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200637 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100638 },
639 /* 5.2 Paired UTF-16 surrogates */
640 {
641 /* \U+D800\U+DC00 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200642 "\xED\xA0\x80\xED\xB0\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200643 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200644 "\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100645 },
646 {
647 /* \U+D800\U+DFFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200648 "\xED\xA0\x80\xED\xBF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200649 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200650 "\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100651 },
652 {
653 /* \U+DB7F\U+DC00 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200654 "\xED\xAD\xBF\xED\xB0\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200655 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200656 "\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100657 },
658 {
659 /* \U+DB7F\U+DFFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200660 "\xED\xAD\xBF\xED\xBF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200661 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200662 "\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100663 },
664 {
665 /* \U+DB80\U+DC00 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200666 "\xED\xAE\x80\xED\xB0\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200667 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200668 "\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100669 },
670 {
671 /* \U+DB80\U+DFFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200672 "\xED\xAE\x80\xED\xBF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200673 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200674 "\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100675 },
676 {
677 /* \U+DBFF\U+DC00 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200678 "\xED\xAF\xBF\xED\xB0\x80",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200679 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200680 "\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100681 },
682 {
683 /* \U+DBFF\U+DFFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200684 "\xED\xAF\xBF\xED\xBF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200685 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200686 "\\uFFFD\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100687 },
688 /* 5.3 Other illegal code positions */
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200689 /* BMP noncharacters */
Markus Armbruster3960c412013-02-05 09:30:55 +0100690 {
691 /* \U+FFFE */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200692 "\xEF\xBF\xBE",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200693 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200694 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100695 },
696 {
697 /* \U+FFFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200698 "\xEF\xBF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200699 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200700 "\\uFFFD",
Markus Armbruster3960c412013-02-05 09:30:55 +0100701 },
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200702 {
703 /* U+FDD0 */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200704 "\xEF\xB7\x90",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200705 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200706 "\\uFFFD",
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200707 },
708 {
709 /* U+FDEF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200710 "\xEF\xB7\xAF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200711 NULL,
Markus Armbruster6ad84442018-08-23 18:39:39 +0200712 "\\uFFFD",
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200713 },
714 /* Plane 1 .. 16 noncharacters */
715 {
716 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
Markus Armbruster6ad84442018-08-23 18:39:39 +0200717 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200718 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
719 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
720 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
721 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
722 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
723 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
724 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
725 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
726 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
727 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
728 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
729 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
730 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
731 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
Markus Armbruster6ad84442018-08-23 18:39:39 +0200732 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
Markus Armbrustere59f39d2018-08-23 18:39:49 +0200733 NULL,
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200734 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
735 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
Markus Armbruster6ad84442018-08-23 18:39:39 +0200736 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
737 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD",
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200738 },
Markus Armbruster3960c412013-02-05 09:30:55 +0100739 {}
740 };
Markus Armbruster6ad84442018-08-23 18:39:39 +0200741 int i, j;
Markus Armbruster3960c412013-02-05 09:30:55 +0100742 QString *str;
Markus Armbruster5f454e62018-08-23 18:39:41 +0200743 const char *json_in, *utf8_out, *utf8_in, *json_out, *tail;
744 char *end, *in, *jstr;
Markus Armbruster3960c412013-02-05 09:30:55 +0100745
746 for (i = 0; test_cases[i].json_in; i++) {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200747 for (j = 0; j < 2; j++) {
748 json_in = test_cases[i].json_in;
749 utf8_out = test_cases[i].utf8_out;
Markus Armbruster32846e92018-08-23 18:39:40 +0200750 utf8_in = test_cases[i].utf8_out ?: test_cases[i].json_in;
Markus Armbruster6ad84442018-08-23 18:39:39 +0200751 json_out = test_cases[i].json_out ?: test_cases[i].json_in;
Markus Armbruster3960c412013-02-05 09:30:55 +0100752
Markus Armbruster6ad84442018-08-23 18:39:39 +0200753 /* Parse @json_in, expect @utf8_out */
754 if (utf8_out) {
755 str = from_json_str(json_in, j, &error_abort);
756 g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_out);
757 qobject_unref(str);
758 } else {
759 str = from_json_str(json_in, j, NULL);
760 g_assert(!str);
Markus Armbruster5f454e62018-08-23 18:39:41 +0200761 /*
762 * Failure may be due to any sequence, but *all* sequences
763 * are expected to fail. Test each one in isolation.
764 */
765 for (tail = json_in; *tail; tail = end) {
766 mod_utf8_codepoint(tail, 6, &end);
767 if (*end == ' ') {
768 end++;
769 }
tony.nguyen@bt.com348fbd52019-06-08 05:25:52 +0000770 in = g_strndup(tail, end - tail);
Markus Armbruster5f454e62018-08-23 18:39:41 +0200771 str = from_json_str(in, j, NULL);
Markus Armbruster5f454e62018-08-23 18:39:41 +0200772 g_assert(!str);
773 g_free(in);
774 }
Markus Armbruster6ad84442018-08-23 18:39:39 +0200775 }
Markus Armbruster3960c412013-02-05 09:30:55 +0100776
Markus Armbruster6ad84442018-08-23 18:39:39 +0200777 /* Unparse @utf8_in, expect @json_out */
778 str = qstring_from_str(utf8_in);
779 jstr = to_json_str(str);
780 g_assert_cmpstr(jstr, ==, json_out);
781 qobject_unref(str);
782 g_free(jstr);
Markus Armbruster3960c412013-02-05 09:30:55 +0100783
Markus Armbrusterc473c372018-08-23 18:39:57 +0200784 /* Parse @json_out right back, unless it has replacements */
785 if (!strstr(json_out, "\\uFFFD")) {
Markus Armbruster6ad84442018-08-23 18:39:39 +0200786 str = from_json_str(json_out, j, &error_abort);
Markus Armbrusterc473c372018-08-23 18:39:57 +0200787 g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_in);
Marc-André Lureau8b8fa992018-09-01 23:19:17 +0200788 qobject_unref(str);
Markus Armbruster6ad84442018-08-23 18:39:39 +0200789 }
Markus Armbruster3960c412013-02-05 09:30:55 +0100790 }
791 }
792}
793
Anthony Liguorief76dc52012-01-10 13:10:49 -0600794static void simple_number(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600795{
796 int i;
797 struct {
798 const char *encoded;
799 int64_t decoded;
Anthony Liguori6ee59202009-11-11 13:16:03 -0600800 int skip;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600801 } test_cases[] = {
802 { "0", 0 },
803 { "1234", 1234 },
804 { "1", 1 },
805 { "-32", -32 },
Anthony Liguori6ee59202009-11-11 13:16:03 -0600806 { "-0", 0, .skip = 1 },
Anthony Liguori422c46a2009-11-11 10:39:47 -0600807 { },
808 };
809
810 for (i = 0; test_cases[i].encoded; i++) {
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +0400811 QNum *qnum;
812 int64_t val;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600813
Max Reitz7dc847e2018-02-24 16:40:29 +0100814 qnum = qobject_to(QNum,
815 qobject_from_json(test_cases[i].encoded,
816 &error_abort));
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +0400817 g_assert(qnum);
818 g_assert(qnum_get_try_int(qnum, &val));
819 g_assert_cmpint(val, ==, test_cases[i].decoded);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600820 if (test_cases[i].skip == 0) {
821 QString *str;
822
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +0400823 str = qobject_to_json(QOBJECT(qnum));
Anthony Liguorief76dc52012-01-10 13:10:49 -0600824 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200825 qobject_unref(str);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600826 }
Anthony Liguori422c46a2009-11-11 10:39:47 -0600827
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200828 qobject_unref(qnum);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600829 }
830}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600831
Marc-André Lureau2bc7cfe2017-06-07 20:36:02 +0400832static void large_number(void)
833{
834 const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
835 const char *gtu64 = "18446744073709551616"; /* 2^64 */
836 const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
837 QNum *qnum;
838 QString *str;
839 uint64_t val;
840 int64_t ival;
841
Max Reitz7dc847e2018-02-24 16:40:29 +0100842 qnum = qobject_to(QNum, qobject_from_json(maxu64, &error_abort));
Marc-André Lureau2bc7cfe2017-06-07 20:36:02 +0400843 g_assert(qnum);
844 g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
845 g_assert(!qnum_get_try_int(qnum, &ival));
846
847 str = qobject_to_json(QOBJECT(qnum));
848 g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200849 qobject_unref(str);
850 qobject_unref(qnum);
Marc-André Lureau2bc7cfe2017-06-07 20:36:02 +0400851
Max Reitz7dc847e2018-02-24 16:40:29 +0100852 qnum = qobject_to(QNum, qobject_from_json(gtu64, &error_abort));
Marc-André Lureau2bc7cfe2017-06-07 20:36:02 +0400853 g_assert(qnum);
854 g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
855 g_assert(!qnum_get_try_uint(qnum, &val));
856 g_assert(!qnum_get_try_int(qnum, &ival));
857
858 str = qobject_to_json(QOBJECT(qnum));
859 g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200860 qobject_unref(str);
861 qobject_unref(qnum);
Marc-André Lureau2bc7cfe2017-06-07 20:36:02 +0400862
Max Reitz7dc847e2018-02-24 16:40:29 +0100863 qnum = qobject_to(QNum, qobject_from_json(lti64, &error_abort));
Marc-André Lureau2bc7cfe2017-06-07 20:36:02 +0400864 g_assert(qnum);
865 g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
866 g_assert(!qnum_get_try_uint(qnum, &val));
867 g_assert(!qnum_get_try_int(qnum, &ival));
868
869 str = qobject_to_json(QOBJECT(qnum));
870 g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200871 qobject_unref(str);
872 qobject_unref(qnum);
Marc-André Lureau2bc7cfe2017-06-07 20:36:02 +0400873}
874
Anthony Liguorief76dc52012-01-10 13:10:49 -0600875static void float_number(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600876{
877 int i;
878 struct {
879 const char *encoded;
880 double decoded;
Anthony Liguori6ee59202009-11-11 13:16:03 -0600881 int skip;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600882 } test_cases[] = {
883 { "32.43", 32.43 },
884 { "0.222", 0.222 },
885 { "-32.12313", -32.12313 },
Anthony Liguori6ee59202009-11-11 13:16:03 -0600886 { "-32.20e-10", -32.20e-10, .skip = 1 },
Anthony Liguori422c46a2009-11-11 10:39:47 -0600887 { },
888 };
889
890 for (i = 0; test_cases[i].encoded; i++) {
891 QObject *obj;
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +0400892 QNum *qnum;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600893
Markus Armbrusteraec4b052017-02-28 22:27:00 +0100894 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
Max Reitz7dc847e2018-02-24 16:40:29 +0100895 qnum = qobject_to(QNum, obj);
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +0400896 g_assert(qnum);
897 g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600898
Anthony Liguori6ee59202009-11-11 13:16:03 -0600899 if (test_cases[i].skip == 0) {
900 QString *str;
901
902 str = qobject_to_json(obj);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600903 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200904 qobject_unref(str);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600905 }
906
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200907 qobject_unref(qnum);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600908 }
909}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600910
Anthony Liguorief76dc52012-01-10 13:10:49 -0600911static void keyword_literal(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600912{
913 QObject *obj;
914 QBool *qbool;
Markus Armbruster006ca092017-06-26 13:52:24 +0200915 QNull *null;
Anthony Liguori6ee59202009-11-11 13:16:03 -0600916 QString *str;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600917
Markus Armbrusteraec4b052017-02-28 22:27:00 +0100918 obj = qobject_from_json("true", &error_abort);
Max Reitz7dc847e2018-02-24 16:40:29 +0100919 qbool = qobject_to(QBool, obj);
Markus Armbrusterdfad9ec2017-02-17 21:38:23 +0100920 g_assert(qbool);
Eric Blakefc48ffc2015-05-15 16:24:59 -0600921 g_assert(qbool_get_bool(qbool) == true);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600922
Anthony Liguori6ee59202009-11-11 13:16:03 -0600923 str = qobject_to_json(obj);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600924 g_assert(strcmp(qstring_get_str(str), "true") == 0);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200925 qobject_unref(str);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600926
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200927 qobject_unref(qbool);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600928
Markus Armbrusteraec4b052017-02-28 22:27:00 +0100929 obj = qobject_from_json("false", &error_abort);
Max Reitz7dc847e2018-02-24 16:40:29 +0100930 qbool = qobject_to(QBool, obj);
Markus Armbrusterdfad9ec2017-02-17 21:38:23 +0100931 g_assert(qbool);
Eric Blakefc48ffc2015-05-15 16:24:59 -0600932 g_assert(qbool_get_bool(qbool) == false);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600933
Anthony Liguori6ee59202009-11-11 13:16:03 -0600934 str = qobject_to_json(obj);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600935 g_assert(strcmp(qstring_get_str(str), "false") == 0);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200936 qobject_unref(str);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600937
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200938 qobject_unref(qbool);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600939
Markus Armbruster2e933f52018-08-23 18:39:43 +0200940 obj = qobject_from_json("null", &error_abort);
941 g_assert(obj != NULL);
942 g_assert(qobject_type(obj) == QTYPE_QNULL);
943
944 null = qnull();
945 g_assert(QOBJECT(null) == obj);
946
947 qobject_unref(obj);
948 qobject_unref(null);
949}
950
951static void interpolation_valid(void)
952{
953 long long value_lld = 0x123456789abcdefLL;
Markus Armbruster53a0d612018-08-23 18:40:08 +0200954 int64_t value_d64 = value_lld;
Markus Armbruster2e933f52018-08-23 18:39:43 +0200955 long value_ld = (long)value_lld;
956 int value_d = (int)value_lld;
957 unsigned long long value_llu = 0xfedcba9876543210ULL;
Markus Armbruster53a0d612018-08-23 18:40:08 +0200958 uint64_t value_u64 = value_llu;
Markus Armbruster2e933f52018-08-23 18:39:43 +0200959 unsigned long value_lu = (unsigned long)value_llu;
960 unsigned value_u = (unsigned)value_llu;
961 double value_f = 2.323423423;
962 const char *value_s = "hello world";
963 QObject *value_p = QOBJECT(qnull());
964 QBool *qbool;
965 QNum *qnum;
966 QString *qstr;
967 QObject *qobj;
968
969 /* bool */
970
Markus Armbruster6ce80fd2018-08-06 08:53:27 +0200971 qbool = qobject_to(QBool, qobject_from_jsonf_nofail("%i", false));
Markus Armbrusterdfad9ec2017-02-17 21:38:23 +0100972 g_assert(qbool);
Eric Blakefc48ffc2015-05-15 16:24:59 -0600973 g_assert(qbool_get_bool(qbool) == false);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200974 qobject_unref(qbool);
Eric Blakee549e712015-04-29 15:35:06 -0600975
Eric Blakefc48ffc2015-05-15 16:24:59 -0600976 /* Test that non-zero values other than 1 get collapsed to true */
Markus Armbruster6ce80fd2018-08-06 08:53:27 +0200977 qbool = qobject_to(QBool, qobject_from_jsonf_nofail("%i", 2));
Markus Armbrusterdfad9ec2017-02-17 21:38:23 +0100978 g_assert(qbool);
Eric Blakefc48ffc2015-05-15 16:24:59 -0600979 g_assert(qbool_get_bool(qbool) == true);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +0200980 qobject_unref(qbool);
Eric Blakee549e712015-04-29 15:35:06 -0600981
Markus Armbruster2e933f52018-08-23 18:39:43 +0200982 /* number */
Eric Blakee549e712015-04-29 15:35:06 -0600983
Markus Armbruster2e933f52018-08-23 18:39:43 +0200984 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%d", value_d));
985 g_assert_cmpint(qnum_get_int(qnum), ==, value_d);
986 qobject_unref(qnum);
Eric Blakee549e712015-04-29 15:35:06 -0600987
Markus Armbruster2e933f52018-08-23 18:39:43 +0200988 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%ld", value_ld));
989 g_assert_cmpint(qnum_get_int(qnum), ==, value_ld);
990 qobject_unref(qnum);
991
992 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%lld", value_lld));
993 g_assert_cmpint(qnum_get_int(qnum), ==, value_lld);
994 qobject_unref(qnum);
995
Markus Armbruster53a0d612018-08-23 18:40:08 +0200996 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%" PRId64, value_d64));
997 g_assert_cmpint(qnum_get_int(qnum), ==, value_lld);
998 qobject_unref(qnum);
999
Markus Armbruster2e933f52018-08-23 18:39:43 +02001000 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%u", value_u));
1001 g_assert_cmpuint(qnum_get_uint(qnum), ==, value_u);
1002 qobject_unref(qnum);
1003
1004 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%lu", value_lu));
1005 g_assert_cmpuint(qnum_get_uint(qnum), ==, value_lu);
1006 qobject_unref(qnum);
1007
1008 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%llu", value_llu));
1009 g_assert_cmpuint(qnum_get_uint(qnum), ==, value_llu);
1010 qobject_unref(qnum);
1011
Markus Armbruster53a0d612018-08-23 18:40:08 +02001012 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%" PRIu64, value_u64));
1013 g_assert_cmpuint(qnum_get_uint(qnum), ==, value_llu);
1014 qobject_unref(qnum);
1015
Markus Armbruster2e933f52018-08-23 18:39:43 +02001016 qnum = qobject_to(QNum, qobject_from_jsonf_nofail("%f", value_f));
1017 g_assert(qnum_get_double(qnum) == value_f);
1018 qobject_unref(qnum);
1019
1020 /* string */
1021
1022 qstr = qobject_to(QString,
1023 qobject_from_jsonf_nofail("%s", value_s));
1024 g_assert_cmpstr(qstring_get_try_str(qstr), ==, value_s);
1025 qobject_unref(qstr);
1026
1027 /* object */
1028
1029 qobj = qobject_from_jsonf_nofail("%p", value_p);
1030 g_assert(qobj == value_p);
1031}
1032
1033static void interpolation_unknown(void)
1034{
1035 if (g_test_subprocess()) {
1036 qobject_from_jsonf_nofail("%x", 666);
1037 }
1038 g_test_trap_subprocess(NULL, 0, 0);
1039 g_test_trap_assert_failed();
Markus Armbrusterf7617d42018-08-23 18:40:07 +02001040 g_test_trap_assert_stderr("*Unexpected error*"
1041 "invalid interpolation '%x'*");
Markus Armbruster2e933f52018-08-23 18:39:43 +02001042}
1043
1044static void interpolation_string(void)
1045{
Markus Armbruster16a48592018-08-23 18:40:23 +02001046 if (g_test_subprocess()) {
1047 qobject_from_jsonf_nofail("['%s', %s]", "eins", "zwei");
1048 }
1049 g_test_trap_subprocess(NULL, 0, 0);
1050 g_test_trap_assert_failed();
1051 g_test_trap_assert_stderr("*Unexpected error*"
1052 "can't interpolate into string*");
Anthony Liguori422c46a2009-11-11 10:39:47 -06001053}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001054
Anthony Liguorief76dc52012-01-10 13:10:49 -06001055static void simple_dict(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001056{
1057 int i;
1058 struct {
1059 const char *encoded;
Marc-André Lureau082696e2017-08-25 12:59:02 +02001060 QLitObject decoded;
Anthony Liguori422c46a2009-11-11 10:39:47 -06001061 } test_cases[] = {
1062 {
Anthony Liguori6ee59202009-11-11 13:16:03 -06001063 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001064 .decoded = QLIT_QDICT(((QLitDictEntry[]){
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001065 { "foo", QLIT_QNUM(42) },
Anthony Liguori422c46a2009-11-11 10:39:47 -06001066 { "bar", QLIT_QSTR("hello world") },
1067 { }
1068 })),
1069 }, {
1070 .encoded = "{}",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001071 .decoded = QLIT_QDICT(((QLitDictEntry[]){
Anthony Liguori422c46a2009-11-11 10:39:47 -06001072 { }
1073 })),
1074 }, {
Anthony Liguori6ee59202009-11-11 13:16:03 -06001075 .encoded = "{\"foo\": 43}",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001076 .decoded = QLIT_QDICT(((QLitDictEntry[]){
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001077 { "foo", QLIT_QNUM(43) },
Anthony Liguori422c46a2009-11-11 10:39:47 -06001078 { }
1079 })),
1080 },
1081 { }
1082 };
1083
1084 for (i = 0; test_cases[i].encoded; i++) {
1085 QObject *obj;
Anthony Liguori6ee59202009-11-11 13:16:03 -06001086 QString *str;
Anthony Liguori422c46a2009-11-11 10:39:47 -06001087
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001088 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
Marc-André Lureaud9eba572017-08-25 12:59:05 +02001089 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
Anthony Liguori422c46a2009-11-11 10:39:47 -06001090
Anthony Liguori6ee59202009-11-11 13:16:03 -06001091 str = qobject_to_json(obj);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001092 qobject_unref(obj);
Anthony Liguori6ee59202009-11-11 13:16:03 -06001093
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001094 obj = qobject_from_json(qstring_get_str(str), &error_abort);
Marc-André Lureaud9eba572017-08-25 12:59:05 +02001095 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001096 qobject_unref(obj);
1097 qobject_unref(str);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001098 }
1099}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001100
Michael Roth7109edf2012-08-15 13:45:44 -05001101/*
1102 * this generates json of the form:
1103 * a(0,m) = [0, 1, ..., m-1]
1104 * a(n,m) = {
1105 * 'key0': a(0,m),
1106 * 'key1': a(1,m),
1107 * ...
1108 * 'key(n-1)': a(n-1,m)
1109 * }
1110 */
1111static void gen_test_json(GString *gstr, int nest_level_max,
1112 int elem_count)
1113{
1114 int i;
1115
1116 g_assert(gstr);
1117 if (nest_level_max == 0) {
1118 g_string_append(gstr, "[");
1119 for (i = 0; i < elem_count; i++) {
1120 g_string_append_printf(gstr, "%d", i);
1121 if (i < elem_count - 1) {
1122 g_string_append_printf(gstr, ", ");
1123 }
1124 }
1125 g_string_append(gstr, "]");
1126 return;
1127 }
1128
1129 g_string_append(gstr, "{");
1130 for (i = 0; i < nest_level_max; i++) {
1131 g_string_append_printf(gstr, "'key%d': ", i);
1132 gen_test_json(gstr, i, elem_count);
1133 if (i < nest_level_max - 1) {
1134 g_string_append(gstr, ",");
1135 }
1136 }
1137 g_string_append(gstr, "}");
1138}
1139
1140static void large_dict(void)
1141{
1142 GString *gstr = g_string_new("");
1143 QObject *obj;
1144
1145 gen_test_json(gstr, 10, 100);
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001146 obj = qobject_from_json(gstr->str, &error_abort);
Michael Roth7109edf2012-08-15 13:45:44 -05001147 g_assert(obj != NULL);
1148
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001149 qobject_unref(obj);
Michael Roth7109edf2012-08-15 13:45:44 -05001150 g_string_free(gstr, true);
1151}
1152
Anthony Liguorief76dc52012-01-10 13:10:49 -06001153static void simple_list(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001154{
1155 int i;
1156 struct {
1157 const char *encoded;
Marc-André Lureau082696e2017-08-25 12:59:02 +02001158 QLitObject decoded;
Anthony Liguori422c46a2009-11-11 10:39:47 -06001159 } test_cases[] = {
1160 {
1161 .encoded = "[43,42]",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001162 .decoded = QLIT_QLIST(((QLitObject[]){
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001163 QLIT_QNUM(43),
1164 QLIT_QNUM(42),
Anthony Liguori422c46a2009-11-11 10:39:47 -06001165 { }
1166 })),
1167 },
1168 {
1169 .encoded = "[43]",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001170 .decoded = QLIT_QLIST(((QLitObject[]){
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001171 QLIT_QNUM(43),
Anthony Liguori422c46a2009-11-11 10:39:47 -06001172 { }
1173 })),
1174 },
1175 {
1176 .encoded = "[]",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001177 .decoded = QLIT_QLIST(((QLitObject[]){
Anthony Liguori422c46a2009-11-11 10:39:47 -06001178 { }
1179 })),
1180 },
1181 {
1182 .encoded = "[{}]",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001183 .decoded = QLIT_QLIST(((QLitObject[]){
1184 QLIT_QDICT(((QLitDictEntry[]){
Anthony Liguori422c46a2009-11-11 10:39:47 -06001185 {},
1186 })),
1187 {},
1188 })),
1189 },
1190 { }
1191 };
1192
1193 for (i = 0; test_cases[i].encoded; i++) {
1194 QObject *obj;
Anthony Liguori6ee59202009-11-11 13:16:03 -06001195 QString *str;
Anthony Liguori422c46a2009-11-11 10:39:47 -06001196
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001197 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
Marc-André Lureaud9eba572017-08-25 12:59:05 +02001198 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
Anthony Liguori422c46a2009-11-11 10:39:47 -06001199
Anthony Liguori6ee59202009-11-11 13:16:03 -06001200 str = qobject_to_json(obj);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001201 qobject_unref(obj);
Anthony Liguori6ee59202009-11-11 13:16:03 -06001202
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001203 obj = qobject_from_json(qstring_get_str(str), &error_abort);
Marc-André Lureaud9eba572017-08-25 12:59:05 +02001204 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001205 qobject_unref(obj);
1206 qobject_unref(str);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001207 }
1208}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001209
Anthony Liguorief76dc52012-01-10 13:10:49 -06001210static void simple_whitespace(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001211{
1212 int i;
1213 struct {
1214 const char *encoded;
Marc-André Lureau082696e2017-08-25 12:59:02 +02001215 QLitObject decoded;
Anthony Liguori422c46a2009-11-11 10:39:47 -06001216 } test_cases[] = {
1217 {
1218 .encoded = " [ 43 , 42 ]",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001219 .decoded = QLIT_QLIST(((QLitObject[]){
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001220 QLIT_QNUM(43),
1221 QLIT_QNUM(42),
Anthony Liguori422c46a2009-11-11 10:39:47 -06001222 { }
1223 })),
1224 },
1225 {
Markus Armbruster53654902018-08-23 18:39:31 +02001226 .encoded = "\t[ 43 , { 'h' : 'b' },\r\n\t[ ], 42 ]\n",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001227 .decoded = QLIT_QLIST(((QLitObject[]){
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001228 QLIT_QNUM(43),
Marc-André Lureau082696e2017-08-25 12:59:02 +02001229 QLIT_QDICT(((QLitDictEntry[]){
Anthony Liguori422c46a2009-11-11 10:39:47 -06001230 { "h", QLIT_QSTR("b") },
1231 { }})),
Marc-André Lureau082696e2017-08-25 12:59:02 +02001232 QLIT_QLIST(((QLitObject[]){
Anthony Liguori422c46a2009-11-11 10:39:47 -06001233 { }})),
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001234 QLIT_QNUM(42),
Anthony Liguori422c46a2009-11-11 10:39:47 -06001235 { }
1236 })),
1237 },
1238 {
1239 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
Marc-André Lureau082696e2017-08-25 12:59:02 +02001240 .decoded = QLIT_QLIST(((QLitObject[]){
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001241 QLIT_QNUM(43),
Marc-André Lureau082696e2017-08-25 12:59:02 +02001242 QLIT_QDICT(((QLitDictEntry[]){
Anthony Liguori422c46a2009-11-11 10:39:47 -06001243 { "h", QLIT_QSTR("b") },
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001244 { "a", QLIT_QNUM(32) },
Anthony Liguori422c46a2009-11-11 10:39:47 -06001245 { }})),
Marc-André Lureau082696e2017-08-25 12:59:02 +02001246 QLIT_QLIST(((QLitObject[]){
Anthony Liguori422c46a2009-11-11 10:39:47 -06001247 { }})),
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001248 QLIT_QNUM(42),
Anthony Liguori422c46a2009-11-11 10:39:47 -06001249 { }
1250 })),
1251 },
1252 { }
1253 };
1254
1255 for (i = 0; test_cases[i].encoded; i++) {
1256 QObject *obj;
Anthony Liguori6ee59202009-11-11 13:16:03 -06001257 QString *str;
Anthony Liguori422c46a2009-11-11 10:39:47 -06001258
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001259 obj = qobject_from_json(test_cases[i].encoded, &error_abort);
Marc-André Lureaud9eba572017-08-25 12:59:05 +02001260 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
Anthony Liguori422c46a2009-11-11 10:39:47 -06001261
Anthony Liguori6ee59202009-11-11 13:16:03 -06001262 str = qobject_to_json(obj);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001263 qobject_unref(obj);
Anthony Liguori6ee59202009-11-11 13:16:03 -06001264
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001265 obj = qobject_from_json(qstring_get_str(str), &error_abort);
Marc-André Lureaud9eba572017-08-25 12:59:05 +02001266 g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
Anthony Liguori6ee59202009-11-11 13:16:03 -06001267
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001268 qobject_unref(obj);
1269 qobject_unref(str);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001270 }
1271}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001272
Markus Armbruster2e933f52018-08-23 18:39:43 +02001273static void simple_interpolation(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001274{
1275 QObject *embedded_obj;
1276 QObject *obj;
Marc-André Lureau082696e2017-08-25 12:59:02 +02001277 QLitObject decoded = QLIT_QLIST(((QLitObject[]){
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001278 QLIT_QNUM(1),
Markus Armbruster8bca4612018-08-23 18:40:24 +02001279 QLIT_QSTR("100%"),
Marc-André Lureau082696e2017-08-25 12:59:02 +02001280 QLIT_QLIST(((QLitObject[]){
Marc-André Lureau01b2ffc2017-06-07 20:35:58 +04001281 QLIT_QNUM(32),
1282 QLIT_QNUM(42),
Anthony Liguori422c46a2009-11-11 10:39:47 -06001283 {}})),
1284 {}}));
1285
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001286 embedded_obj = qobject_from_json("[32, 42]", &error_abort);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001287 g_assert(embedded_obj != NULL);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001288
Markus Armbruster8bca4612018-08-23 18:40:24 +02001289 obj = qobject_from_jsonf_nofail("[%d, '100%%', %p]", 1, embedded_obj);
Marc-André Lureaud9eba572017-08-25 12:59:05 +02001290 g_assert(qlit_equal_qobject(&decoded, obj));
Anthony Liguori422c46a2009-11-11 10:39:47 -06001291
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001292 qobject_unref(obj);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001293}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001294
Anthony Liguorief76dc52012-01-10 13:10:49 -06001295static void empty_input(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001296{
Markus Armbrusterdd98e842018-08-23 18:40:14 +02001297 Error *err = NULL;
1298 QObject *obj;
1299
1300 obj = qobject_from_json("", &err);
1301 error_free_or_abort(&err);
Markus Armbrustera3694182018-08-23 18:39:30 +02001302 g_assert(obj == NULL);
1303}
1304
1305static void blank_input(void)
1306{
Markus Armbrusterdd98e842018-08-23 18:40:14 +02001307 Error *err = NULL;
1308 QObject *obj;
1309
1310 obj = qobject_from_json("\n ", &err);
1311 error_free_or_abort(&err);
Markus Armbrustera3694182018-08-23 18:39:30 +02001312 g_assert(obj == NULL);
1313}
1314
1315static void junk_input(void)
1316{
1317 /* Note: junk within strings is covered elsewhere */
1318 Error *err = NULL;
1319 QObject *obj;
1320
1321 obj = qobject_from_json("@", &err);
Markus Armbruster84a56f32018-08-23 18:40:06 +02001322 error_free_or_abort(&err);
Markus Armbrustera3694182018-08-23 18:39:30 +02001323 g_assert(obj == NULL);
1324
Markus Armbruster6bc93a32018-08-23 18:39:42 +02001325 obj = qobject_from_json("{\x01", &err);
Markus Armbruster84a56f32018-08-23 18:40:06 +02001326 error_free_or_abort(&err);
Markus Armbruster6bc93a32018-08-23 18:39:42 +02001327 g_assert(obj == NULL);
1328
Markus Armbrustera3694182018-08-23 18:39:30 +02001329 obj = qobject_from_json("[0\xFF]", &err);
1330 error_free_or_abort(&err);
1331 g_assert(obj == NULL);
1332
1333 obj = qobject_from_json("00", &err);
Markus Armbruster84a56f32018-08-23 18:40:06 +02001334 error_free_or_abort(&err);
Markus Armbrustera3694182018-08-23 18:39:30 +02001335 g_assert(obj == NULL);
1336
1337 obj = qobject_from_json("[1e", &err);
Markus Armbruster84a56f32018-08-23 18:40:06 +02001338 error_free_or_abort(&err);
Markus Armbrustera3694182018-08-23 18:39:30 +02001339 g_assert(obj == NULL);
1340
1341 obj = qobject_from_json("truer", &err);
1342 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001343 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001344}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001345
Anthony Liguorief76dc52012-01-10 13:10:49 -06001346static void unterminated_string(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001347{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001348 Error *err = NULL;
1349 QObject *obj = qobject_from_json("\"abc", &err);
Markus Armbruster84a56f32018-08-23 18:40:06 +02001350 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001351 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001352}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001353
Anthony Liguorief76dc52012-01-10 13:10:49 -06001354static void unterminated_sq_string(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001355{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001356 Error *err = NULL;
1357 QObject *obj = qobject_from_json("'abc", &err);
Markus Armbruster84a56f32018-08-23 18:40:06 +02001358 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001359 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001360}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001361
Anthony Liguorief76dc52012-01-10 13:10:49 -06001362static void unterminated_escape(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001363{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001364 Error *err = NULL;
1365 QObject *obj = qobject_from_json("\"abc\\\"", &err);
Markus Armbruster84a56f32018-08-23 18:40:06 +02001366 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001367 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001368}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001369
Anthony Liguorief76dc52012-01-10 13:10:49 -06001370static void unterminated_array(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001371{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001372 Error *err = NULL;
1373 QObject *obj = qobject_from_json("[32", &err);
Markus Armbrusterf9277912018-08-23 18:40:12 +02001374 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001375 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001376}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001377
Anthony Liguorief76dc52012-01-10 13:10:49 -06001378static void unterminated_array_comma(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001379{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001380 Error *err = NULL;
1381 QObject *obj = qobject_from_json("[32,", &err);
Markus Armbrusterf9277912018-08-23 18:40:12 +02001382 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001383 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001384}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001385
Anthony Liguorief76dc52012-01-10 13:10:49 -06001386static void invalid_array_comma(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001387{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001388 Error *err = NULL;
1389 QObject *obj = qobject_from_json("[32,}", &err);
1390 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001391 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001392}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001393
Anthony Liguorief76dc52012-01-10 13:10:49 -06001394static void unterminated_dict(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001395{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001396 Error *err = NULL;
1397 QObject *obj = qobject_from_json("{'abc':32", &err);
Markus Armbrusterf9277912018-08-23 18:40:12 +02001398 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001399 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001400}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001401
Anthony Liguorief76dc52012-01-10 13:10:49 -06001402static void unterminated_dict_comma(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001403{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001404 Error *err = NULL;
1405 QObject *obj = qobject_from_json("{'abc':32,", &err);
Markus Armbrusterf9277912018-08-23 18:40:12 +02001406 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001407 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001408}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001409
Anthony Liguorief76dc52012-01-10 13:10:49 -06001410static void invalid_dict_comma(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001411{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001412 Error *err = NULL;
1413 QObject *obj = qobject_from_json("{'abc':32,}", &err);
1414 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001415 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001416}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001417
Anthony Liguorief76dc52012-01-10 13:10:49 -06001418static void unterminated_literal(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001419{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001420 Error *err = NULL;
1421 QObject *obj = qobject_from_json("nul", &err);
1422 error_free_or_abort(&err);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001423 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001424}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001425
Markus Armbrusterf0ae0302015-11-25 22:23:24 +01001426static char *make_nest(char *buf, size_t cnt)
1427{
1428 memset(buf, '[', cnt - 1);
1429 buf[cnt - 1] = '{';
1430 buf[cnt] = '}';
1431 memset(buf + cnt + 1, ']', cnt - 1);
1432 buf[2 * cnt] = 0;
1433 return buf;
1434}
1435
1436static void limits_nesting(void)
1437{
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001438 Error *err = NULL;
Markus Armbrusterf0ae0302015-11-25 22:23:24 +01001439 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1440 char buf[2 * (max_nesting + 1) + 1];
1441 QObject *obj;
1442
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001443 obj = qobject_from_json(make_nest(buf, max_nesting), &error_abort);
Markus Armbrusterf0ae0302015-11-25 22:23:24 +01001444 g_assert(obj != NULL);
Marc-André Lureaucb3e7f02018-04-19 17:01:43 +02001445 qobject_unref(obj);
Markus Armbrusterf0ae0302015-11-25 22:23:24 +01001446
Markus Armbrusteraec4b052017-02-28 22:27:00 +01001447 obj = qobject_from_json(make_nest(buf, max_nesting + 1), &err);
1448 error_free_or_abort(&err);
Markus Armbrusterf0ae0302015-11-25 22:23:24 +01001449 g_assert(obj == NULL);
1450}
1451
Markus Armbruster956a1042018-08-23 18:39:29 +02001452static void multiple_values(void)
1453{
1454 Error *err = NULL;
1455 QObject *obj;
1456
Markus Armbruster956a1042018-08-23 18:39:29 +02001457 obj = qobject_from_json("false true", &err);
Markus Armbruster956a1042018-08-23 18:39:29 +02001458 error_free_or_abort(&err);
Markus Armbruster2a4794b2018-08-23 18:40:10 +02001459 g_assert(obj == NULL);
1460
1461 obj = qobject_from_json("} true", &err);
1462 error_free_or_abort(&err);
1463 g_assert(obj == NULL);
Markus Armbruster956a1042018-08-23 18:39:29 +02001464}
1465
Anthony Liguorief76dc52012-01-10 13:10:49 -06001466int main(int argc, char **argv)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001467{
Anthony Liguorief76dc52012-01-10 13:10:49 -06001468 g_test_init(&argc, &argv, NULL);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001469
Anthony Liguorief76dc52012-01-10 13:10:49 -06001470 g_test_add_func("/literals/string/escaped", escaped_string);
Markus Armbruster069946f2018-08-23 18:39:38 +02001471 g_test_add_func("/literals/string/quotes", string_with_quotes);
Markus Armbruster3960c412013-02-05 09:30:55 +01001472 g_test_add_func("/literals/string/utf8", utf8_string);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001473
Anthony Liguorief76dc52012-01-10 13:10:49 -06001474 g_test_add_func("/literals/number/simple", simple_number);
Marc-André Lureau2bc7cfe2017-06-07 20:36:02 +04001475 g_test_add_func("/literals/number/large", large_number);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001476 g_test_add_func("/literals/number/float", float_number);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001477
Anthony Liguorief76dc52012-01-10 13:10:49 -06001478 g_test_add_func("/literals/keyword", keyword_literal);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001479
Markus Armbruster2e933f52018-08-23 18:39:43 +02001480 g_test_add_func("/literals/interpolation/valid", interpolation_valid);
1481 g_test_add_func("/literals/interpolation/unkown", interpolation_unknown);
1482 g_test_add_func("/literals/interpolation/string", interpolation_string);
1483
Anthony Liguorief76dc52012-01-10 13:10:49 -06001484 g_test_add_func("/dicts/simple_dict", simple_dict);
Michael Roth7109edf2012-08-15 13:45:44 -05001485 g_test_add_func("/dicts/large_dict", large_dict);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001486 g_test_add_func("/lists/simple_list", simple_list);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001487
Markus Armbruster2e933f52018-08-23 18:39:43 +02001488 g_test_add_func("/mixed/simple_whitespace", simple_whitespace);
1489 g_test_add_func("/mixed/interpolation", simple_interpolation);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001490
Markus Armbrustera3694182018-08-23 18:39:30 +02001491 g_test_add_func("/errors/empty", empty_input);
1492 g_test_add_func("/errors/blank", blank_input);
1493 g_test_add_func("/errors/junk", junk_input);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001494 g_test_add_func("/errors/unterminated/string", unterminated_string);
1495 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1496 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1497 g_test_add_func("/errors/unterminated/array", unterminated_array);
1498 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1499 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1500 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1501 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001502 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1503 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
Markus Armbrusterf0ae0302015-11-25 22:23:24 +01001504 g_test_add_func("/errors/limits/nesting", limits_nesting);
Markus Armbruster956a1042018-08-23 18:39:29 +02001505 g_test_add_func("/errors/multiple_values", multiple_values);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001506
Anthony Liguorief76dc52012-01-10 13:10:49 -06001507 return g_test_run();
Anthony Liguori422c46a2009-11-11 10:39:47 -06001508}