blob: e6d6935653db0519e5b73302d3f6d9098b6c1ab1 [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 */
Peter Maydell681c28a2016-02-08 18:08:51 +000013#include "qemu/osdep.h"
Anthony Liguori422c46a2009-11-11 10:39:47 -060014
Eric Blakec7eb39c2016-06-09 10:48:32 -060015#include "qapi/qmp/types.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010016#include "qapi/qmp/qjson.h"
Anthony Liguori422c46a2009-11-11 10:39:47 -060017#include "qemu-common.h"
18
Anthony Liguorief76dc52012-01-10 13:10:49 -060019static void escaped_string(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -060020{
21 int i;
22 struct {
23 const char *encoded;
24 const char *decoded;
Anthony Liguori6ee59202009-11-11 13:16:03 -060025 int skip;
Anthony Liguori422c46a2009-11-11 10:39:47 -060026 } test_cases[] = {
Luiz Capitulinod22b0bd2010-05-19 17:08:37 -030027 { "\"\\b\"", "\b" },
28 { "\"\\f\"", "\f" },
29 { "\"\\n\"", "\n" },
30 { "\"\\r\"", "\r" },
31 { "\"\\t\"", "\t" },
Jan Kiszka69faeee2011-08-26 19:52:11 +020032 { "\"/\"", "/" },
33 { "\"\\/\"", "/", .skip = 1 },
Luiz Capitulinod22b0bd2010-05-19 17:08:37 -030034 { "\"\\\\\"", "\\" },
Anthony Liguori422c46a2009-11-11 10:39:47 -060035 { "\"\\\"\"", "\"" },
36 { "\"hello world \\\"embedded string\\\"\"",
37 "hello world \"embedded string\"" },
38 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
Anthony Liguori6ee59202009-11-11 13:16:03 -060039 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
Anthony Liguori422c46a2009-11-11 10:39:47 -060040 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
41 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
Paolo Bonzinid5932332014-06-13 10:13:02 +020042 { "'\\b'", "\b", .skip = 1 },
43 { "'\\f'", "\f", .skip = 1 },
44 { "'\\n'", "\n", .skip = 1 },
45 { "'\\r'", "\r", .skip = 1 },
46 { "'\\t'", "\t", .skip = 1 },
47 { "'\\/'", "/", .skip = 1 },
48 { "'\\\\'", "\\", .skip = 1 },
Anthony Liguori422c46a2009-11-11 10:39:47 -060049 {}
50 };
51
52 for (i = 0; test_cases[i].encoded; i++) {
53 QObject *obj;
54 QString *str;
55
56 obj = qobject_from_json(test_cases[i].encoded);
Anthony Liguori422c46a2009-11-11 10:39:47 -060057 str = qobject_to_qstring(obj);
Markus Armbruster363e13f2017-02-17 21:38:20 +010058 g_assert(str);
Anthony Liguorief76dc52012-01-10 13:10:49 -060059 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
Anthony Liguori422c46a2009-11-11 10:39:47 -060060
Anthony Liguori6ee59202009-11-11 13:16:03 -060061 if (test_cases[i].skip == 0) {
62 str = qobject_to_json(obj);
Anthony Liguorief76dc52012-01-10 13:10:49 -060063 g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
Anthony Liguori6ee59202009-11-11 13:16:03 -060064 qobject_decref(obj);
65 }
66
Anthony Liguori422c46a2009-11-11 10:39:47 -060067 QDECREF(str);
68 }
69}
Anthony Liguori422c46a2009-11-11 10:39:47 -060070
Anthony Liguorief76dc52012-01-10 13:10:49 -060071static void simple_string(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -060072{
73 int i;
74 struct {
75 const char *encoded;
76 const char *decoded;
77 } test_cases[] = {
78 { "\"hello world\"", "hello world" },
79 { "\"the quick brown fox jumped over the fence\"",
80 "the quick brown fox jumped over the fence" },
81 {}
82 };
83
84 for (i = 0; test_cases[i].encoded; i++) {
85 QObject *obj;
86 QString *str;
87
88 obj = qobject_from_json(test_cases[i].encoded);
Anthony Liguori422c46a2009-11-11 10:39:47 -060089 str = qobject_to_qstring(obj);
Markus Armbruster363e13f2017-02-17 21:38:20 +010090 g_assert(str);
Anthony Liguorief76dc52012-01-10 13:10:49 -060091 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
Anthony Liguori422c46a2009-11-11 10:39:47 -060092
Anthony Liguori6ee59202009-11-11 13:16:03 -060093 str = qobject_to_json(obj);
Anthony Liguorief76dc52012-01-10 13:10:49 -060094 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
Anthony Liguori6ee59202009-11-11 13:16:03 -060095
96 qobject_decref(obj);
97
Anthony Liguori422c46a2009-11-11 10:39:47 -060098 QDECREF(str);
99 }
100}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600101
Anthony Liguorief76dc52012-01-10 13:10:49 -0600102static void single_quote_string(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600103{
104 int i;
105 struct {
106 const char *encoded;
107 const char *decoded;
108 } test_cases[] = {
109 { "'hello world'", "hello world" },
110 { "'the quick brown fox \\' jumped over the fence'",
111 "the quick brown fox ' jumped over the fence" },
112 {}
113 };
114
115 for (i = 0; test_cases[i].encoded; i++) {
116 QObject *obj;
117 QString *str;
118
119 obj = qobject_from_json(test_cases[i].encoded);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600120 str = qobject_to_qstring(obj);
Markus Armbruster363e13f2017-02-17 21:38:20 +0100121 g_assert(str);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600122 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600123
124 QDECREF(str);
125 }
126}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600127
Markus Armbruster3960c412013-02-05 09:30:55 +0100128static void utf8_string(void)
129{
130 /*
131 * FIXME Current behavior for invalid UTF-8 sequences is
132 * incorrect. This test expects current, incorrect results.
133 * They're all marked "bug:" below, and are to be replaced by
134 * correct ones as the bugs get fixed.
135 *
136 * The JSON parser rejects some invalid sequences, but accepts
137 * others without correcting the problem.
138 *
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200139 * We should either reject all invalid sequences, or minimize
140 * overlong sequences and replace all other invalid sequences by a
141 * suitable replacement character. A common choice for
142 * replacement is U+FFFD.
Markus Armbruster3960c412013-02-05 09:30:55 +0100143 *
144 * Problem: we can't easily deal with embedded U+0000. Parsing
145 * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
146 * which gets misinterpreted as NUL-terminated "this ". We should
147 * consider using overlong encoding \xC0\x80 for U+0000 ("modified
148 * UTF-8").
149 *
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200150 * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
Markus Armbruster3960c412013-02-05 09:30:55 +0100151 * capability and stress test at
152 * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
153 */
154 static const struct {
155 const char *json_in;
156 const char *utf8_out;
157 const char *json_out; /* defaults to @json_in */
158 const char *utf8_in; /* defaults to @utf8_out */
159 } test_cases[] = {
160 /*
161 * Bug markers used here:
162 * - bug: not corrected
163 * JSON parser fails to correct invalid sequence(s)
164 * - bug: rejected
165 * JSON parser rejects invalid sequence(s)
166 * We may choose to define this as feature
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200167 * - bug: want "..."
Markus Armbruster3960c412013-02-05 09:30:55 +0100168 * JSON parser produces incorrect result, this is the
169 * correct one, assuming replacement character U+FFFF
170 * We may choose to reject instead of replace
Markus Armbruster3960c412013-02-05 09:30:55 +0100171 */
172
173 /* 1 Some correct UTF-8 text */
174 {
175 /* a bit of German */
176 "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
177 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
178 "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
179 " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
180 "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
181 " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
182 },
183 {
184 /* a bit of Greek */
185 "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
186 "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
187 "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
188 },
189 /* 2 Boundary condition test cases */
190 /* 2.1 First possible sequence of a certain length */
191 /* 2.1.1 1 byte U+0000 */
192 {
193 "\"\\u0000\"",
194 "", /* bug: want overlong "\xC0\x80" */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200195 "\"\\u0000\"",
196 "\xC0\x80",
Markus Armbruster3960c412013-02-05 09:30:55 +0100197 },
198 /* 2.1.2 2 bytes U+0080 */
199 {
200 "\"\xC2\x80\"",
201 "\xC2\x80",
202 "\"\\u0080\"",
203 },
204 /* 2.1.3 3 bytes U+0800 */
205 {
206 "\"\xE0\xA0\x80\"",
207 "\xE0\xA0\x80",
208 "\"\\u0800\"",
209 },
210 /* 2.1.4 4 bytes U+10000 */
211 {
212 "\"\xF0\x90\x80\x80\"",
213 "\xF0\x90\x80\x80",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200214 "\"\\uD800\\uDC00\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100215 },
216 /* 2.1.5 5 bytes U+200000 */
217 {
218 "\"\xF8\x88\x80\x80\x80\"",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200219 NULL, /* bug: rejected */
220 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100221 "\xF8\x88\x80\x80\x80",
222 },
223 /* 2.1.6 6 bytes U+4000000 */
224 {
225 "\"\xFC\x84\x80\x80\x80\x80\"",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200226 NULL, /* bug: rejected */
227 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100228 "\xFC\x84\x80\x80\x80\x80",
229 },
230 /* 2.2 Last possible sequence of a certain length */
231 /* 2.2.1 1 byte U+007F */
232 {
233 "\"\x7F\"",
234 "\x7F",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200235 "\"\\u007F\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100236 },
237 /* 2.2.2 2 bytes U+07FF */
238 {
239 "\"\xDF\xBF\"",
240 "\xDF\xBF",
241 "\"\\u07FF\"",
242 },
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200243 /*
244 * 2.2.3 3 bytes U+FFFC
245 * The last possible sequence is actually U+FFFF. But that's
246 * a noncharacter, and already covered by its own test case
247 * under 5.3. Same for U+FFFE. U+FFFD is the last character
248 * in the BMP, and covered under 2.3. Because of U+FFFD's
249 * special role as replacement character, it's worth testing
250 * U+FFFC here.
251 */
Markus Armbruster3960c412013-02-05 09:30:55 +0100252 {
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200253 "\"\xEF\xBF\xBC\"",
254 "\xEF\xBF\xBC",
255 "\"\\uFFFC\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100256 },
257 /* 2.2.4 4 bytes U+1FFFFF */
258 {
259 "\"\xF7\xBF\xBF\xBF\"",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200260 NULL, /* bug: rejected */
261 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100262 "\xF7\xBF\xBF\xBF",
263 },
264 /* 2.2.5 5 bytes U+3FFFFFF */
265 {
266 "\"\xFB\xBF\xBF\xBF\xBF\"",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200267 NULL, /* bug: rejected */
268 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100269 "\xFB\xBF\xBF\xBF\xBF",
270 },
271 /* 2.2.6 6 bytes U+7FFFFFFF */
272 {
273 "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200274 NULL, /* bug: rejected */
275 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100276 "\xFD\xBF\xBF\xBF\xBF\xBF",
277 },
278 /* 2.3 Other boundary conditions */
279 {
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200280 /* last one before surrogate range: U+D7FF */
Markus Armbruster3960c412013-02-05 09:30:55 +0100281 "\"\xED\x9F\xBF\"",
282 "\xED\x9F\xBF",
283 "\"\\uD7FF\"",
284 },
285 {
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200286 /* first one after surrogate range: U+E000 */
Markus Armbruster3960c412013-02-05 09:30:55 +0100287 "\"\xEE\x80\x80\"",
288 "\xEE\x80\x80",
289 "\"\\uE000\"",
290 },
291 {
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200292 /* last one in BMP: U+FFFD */
Markus Armbruster3960c412013-02-05 09:30:55 +0100293 "\"\xEF\xBF\xBD\"",
294 "\xEF\xBF\xBD",
295 "\"\\uFFFD\"",
296 },
297 {
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200298 /* last one in last plane: U+10FFFD */
299 "\"\xF4\x8F\xBF\xBD\"",
300 "\xF4\x8F\xBF\xBD",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200301 "\"\\uDBFF\\uDFFD\""
Markus Armbruster3960c412013-02-05 09:30:55 +0100302 },
303 {
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200304 /* first one beyond Unicode range: U+110000 */
Markus Armbruster3960c412013-02-05 09:30:55 +0100305 "\"\xF4\x90\x80\x80\"",
306 "\xF4\x90\x80\x80",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200307 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100308 },
309 /* 3 Malformed sequences */
310 /* 3.1 Unexpected continuation bytes */
311 /* 3.1.1 First continuation byte */
312 {
313 "\"\x80\"",
314 "\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200315 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100316 },
317 /* 3.1.2 Last continuation byte */
318 {
319 "\"\xBF\"",
320 "\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200321 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100322 },
323 /* 3.1.3 2 continuation bytes */
324 {
325 "\"\x80\xBF\"",
326 "\x80\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200327 "\"\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100328 },
329 /* 3.1.4 3 continuation bytes */
330 {
331 "\"\x80\xBF\x80\"",
332 "\x80\xBF\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200333 "\"\\uFFFD\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100334 },
335 /* 3.1.5 4 continuation bytes */
336 {
337 "\"\x80\xBF\x80\xBF\"",
338 "\x80\xBF\x80\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200339 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100340 },
341 /* 3.1.6 5 continuation bytes */
342 {
343 "\"\x80\xBF\x80\xBF\x80\"",
344 "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200345 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100346 },
347 /* 3.1.7 6 continuation bytes */
348 {
349 "\"\x80\xBF\x80\xBF\x80\xBF\"",
350 "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200351 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100352 },
353 /* 3.1.8 7 continuation bytes */
354 {
355 "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
356 "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200357 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100358 },
359 /* 3.1.9 Sequence of all 64 possible continuation bytes */
360 {
361 "\"\x80\x81\x82\x83\x84\x85\x86\x87"
362 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
363 "\x90\x91\x92\x93\x94\x95\x96\x97"
364 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
365 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
366 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
367 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
368 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
369 /* bug: not corrected */
370 "\x80\x81\x82\x83\x84\x85\x86\x87"
371 "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
372 "\x90\x91\x92\x93\x94\x95\x96\x97"
373 "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
374 "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
375 "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
376 "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
377 "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200378 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
379 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
380 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
381 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
382 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
383 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
384 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
385 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
Markus Armbruster3960c412013-02-05 09:30:55 +0100386 },
387 /* 3.2 Lonely start characters */
388 /* 3.2.1 All 32 first bytes of 2-byte sequences, followed by space */
389 {
390 "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
391 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
392 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
393 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
394 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200395 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
396 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
397 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
398 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100399 "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
400 "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
401 "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
402 "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
403 },
404 /* 3.2.2 All 16 first bytes of 3-byte sequences, followed by space */
405 {
406 "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
407 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
408 /* bug: not corrected */
409 "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
410 "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200411 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
412 "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100413 },
414 /* 3.2.3 All 8 first bytes of 4-byte sequences, followed by space */
415 {
416 "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
417 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200418 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100419 "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
420 },
421 /* 3.2.4 All 4 first bytes of 5-byte sequences, followed by space */
422 {
423 "\"\xF8 \xF9 \xFA \xFB \"",
424 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200425 "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100426 "\xF8 \xF9 \xFA \xFB ",
427 },
428 /* 3.2.5 All 2 first bytes of 6-byte sequences, followed by space */
429 {
430 "\"\xFC \xFD \"",
431 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200432 "\"\\uFFFD \\uFFFD \"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100433 "\xFC \xFD ",
434 },
435 /* 3.3 Sequences with last continuation byte missing */
436 /* 3.3.1 2-byte sequence with last byte missing (U+0000) */
437 {
438 "\"\xC0\"",
439 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200440 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100441 "\xC0",
442 },
443 /* 3.3.2 3-byte sequence with last byte missing (U+0000) */
444 {
445 "\"\xE0\x80\"",
446 "\xE0\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200447 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100448 },
449 /* 3.3.3 4-byte sequence with last byte missing (U+0000) */
450 {
451 "\"\xF0\x80\x80\"",
452 "\xF0\x80\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200453 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100454 },
455 /* 3.3.4 5-byte sequence with last byte missing (U+0000) */
456 {
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200457 "\"\xF8\x80\x80\x80\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100458 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200459 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100460 "\xF8\x80\x80\x80",
461 },
462 /* 3.3.5 6-byte sequence with last byte missing (U+0000) */
463 {
464 "\"\xFC\x80\x80\x80\x80\"",
465 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200466 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100467 "\xFC\x80\x80\x80\x80",
468 },
469 /* 3.3.6 2-byte sequence with last byte missing (U+07FF) */
470 {
471 "\"\xDF\"",
472 "\xDF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200473 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100474 },
475 /* 3.3.7 3-byte sequence with last byte missing (U+FFFF) */
476 {
477 "\"\xEF\xBF\"",
478 "\xEF\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200479 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100480 },
481 /* 3.3.8 4-byte sequence with last byte missing (U+1FFFFF) */
482 {
483 "\"\xF7\xBF\xBF\"",
484 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200485 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100486 "\xF7\xBF\xBF",
487 },
488 /* 3.3.9 5-byte sequence with last byte missing (U+3FFFFFF) */
489 {
490 "\"\xFB\xBF\xBF\xBF\"",
491 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200492 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100493 "\xFB\xBF\xBF\xBF",
494 },
495 /* 3.3.10 6-byte sequence with last byte missing (U+7FFFFFFF) */
496 {
497 "\"\xFD\xBF\xBF\xBF\xBF\"",
498 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200499 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100500 "\xFD\xBF\xBF\xBF\xBF",
501 },
502 /* 3.4 Concatenation of incomplete sequences */
503 {
504 "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
505 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
506 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200507 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
508 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100509 "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
510 "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
511 },
512 /* 3.5 Impossible bytes */
513 {
514 "\"\xFE\"",
515 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200516 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100517 "\xFE",
518 },
519 {
520 "\"\xFF\"",
521 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200522 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100523 "\xFF",
524 },
525 {
526 "\"\xFE\xFE\xFF\xFF\"",
527 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200528 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100529 "\xFE\xFE\xFF\xFF",
530 },
531 /* 4 Overlong sequences */
532 /* 4.1 Overlong '/' */
533 {
534 "\"\xC0\xAF\"",
535 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200536 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100537 "\xC0\xAF",
538 },
539 {
540 "\"\xE0\x80\xAF\"",
541 "\xE0\x80\xAF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200542 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100543 },
544 {
545 "\"\xF0\x80\x80\xAF\"",
546 "\xF0\x80\x80\xAF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200547 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100548 },
549 {
550 "\"\xF8\x80\x80\x80\xAF\"",
551 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200552 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100553 "\xF8\x80\x80\x80\xAF",
554 },
555 {
556 "\"\xFC\x80\x80\x80\x80\xAF\"",
557 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200558 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100559 "\xFC\x80\x80\x80\x80\xAF",
560 },
Markus Armbrusterd6244e22013-04-11 18:07:19 +0200561 /*
562 * 4.2 Maximum overlong sequences
563 * Highest Unicode value that is still resulting in an
564 * overlong sequence if represented with the given number of
565 * bytes. This is a boundary test for safe UTF-8 decoders.
566 */
Markus Armbruster3960c412013-02-05 09:30:55 +0100567 {
568 /* \U+007F */
569 "\"\xC1\xBF\"",
570 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200571 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100572 "\xC1\xBF",
573 },
574 {
575 /* \U+07FF */
576 "\"\xE0\x9F\xBF\"",
577 "\xE0\x9F\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200578 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100579 },
580 {
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200581 /*
582 * \U+FFFC
583 * The actual maximum would be U+FFFF, but that's a
584 * noncharacter. Testing U+FFFC seems more useful. See
585 * also 2.2.3
586 */
587 "\"\xF0\x8F\xBF\xBC\"",
588 "\xF0\x8F\xBF\xBC", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200589 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100590 },
591 {
592 /* \U+1FFFFF */
593 "\"\xF8\x87\xBF\xBF\xBF\"",
594 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200595 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100596 "\xF8\x87\xBF\xBF\xBF",
597 },
598 {
599 /* \U+3FFFFFF */
600 "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
601 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200602 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100603 "\xFC\x83\xBF\xBF\xBF\xBF",
604 },
605 /* 4.3 Overlong representation of the NUL character */
606 {
607 /* \U+0000 */
608 "\"\xC0\x80\"",
609 NULL, /* bug: rejected */
610 "\"\\u0000\"",
611 "\xC0\x80",
612 },
613 {
614 /* \U+0000 */
615 "\"\xE0\x80\x80\"",
616 "\xE0\x80\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200617 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100618 },
619 {
620 /* \U+0000 */
621 "\"\xF0\x80\x80\x80\"",
622 "\xF0\x80\x80\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200623 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100624 },
625 {
626 /* \U+0000 */
627 "\"\xF8\x80\x80\x80\x80\"",
628 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200629 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100630 "\xF8\x80\x80\x80\x80",
631 },
632 {
633 /* \U+0000 */
634 "\"\xFC\x80\x80\x80\x80\x80\"",
635 NULL, /* bug: rejected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200636 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100637 "\xFC\x80\x80\x80\x80\x80",
638 },
639 /* 5 Illegal code positions */
640 /* 5.1 Single UTF-16 surrogates */
641 {
642 /* \U+D800 */
643 "\"\xED\xA0\x80\"",
644 "\xED\xA0\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200645 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100646 },
647 {
648 /* \U+DB7F */
649 "\"\xED\xAD\xBF\"",
650 "\xED\xAD\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200651 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100652 },
653 {
654 /* \U+DB80 */
655 "\"\xED\xAE\x80\"",
656 "\xED\xAE\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200657 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100658 },
659 {
660 /* \U+DBFF */
661 "\"\xED\xAF\xBF\"",
662 "\xED\xAF\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200663 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100664 },
665 {
666 /* \U+DC00 */
667 "\"\xED\xB0\x80\"",
668 "\xED\xB0\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200669 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100670 },
671 {
672 /* \U+DF80 */
673 "\"\xED\xBE\x80\"",
674 "\xED\xBE\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200675 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100676 },
677 {
678 /* \U+DFFF */
679 "\"\xED\xBF\xBF\"",
680 "\xED\xBF\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200681 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100682 },
683 /* 5.2 Paired UTF-16 surrogates */
684 {
685 /* \U+D800\U+DC00 */
686 "\"\xED\xA0\x80\xED\xB0\x80\"",
687 "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200688 "\"\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100689 },
690 {
691 /* \U+D800\U+DFFF */
692 "\"\xED\xA0\x80\xED\xBF\xBF\"",
693 "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200694 "\"\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100695 },
696 {
697 /* \U+DB7F\U+DC00 */
698 "\"\xED\xAD\xBF\xED\xB0\x80\"",
699 "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200700 "\"\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100701 },
702 {
703 /* \U+DB7F\U+DFFF */
704 "\"\xED\xAD\xBF\xED\xBF\xBF\"",
705 "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200706 "\"\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100707 },
708 {
709 /* \U+DB80\U+DC00 */
710 "\"\xED\xAE\x80\xED\xB0\x80\"",
711 "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200712 "\"\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100713 },
714 {
715 /* \U+DB80\U+DFFF */
716 "\"\xED\xAE\x80\xED\xBF\xBF\"",
717 "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200718 "\"\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100719 },
720 {
721 /* \U+DBFF\U+DC00 */
722 "\"\xED\xAF\xBF\xED\xB0\x80\"",
723 "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200724 "\"\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100725 },
726 {
727 /* \U+DBFF\U+DFFF */
728 "\"\xED\xAF\xBF\xED\xBF\xBF\"",
729 "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200730 "\"\\uFFFD\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100731 },
732 /* 5.3 Other illegal code positions */
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200733 /* BMP noncharacters */
Markus Armbruster3960c412013-02-05 09:30:55 +0100734 {
735 /* \U+FFFE */
736 "\"\xEF\xBF\xBE\"",
737 "\xEF\xBF\xBE", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200738 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100739 },
740 {
741 /* \U+FFFF */
742 "\"\xEF\xBF\xBF\"",
743 "\xEF\xBF\xBF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200744 "\"\\uFFFD\"",
Markus Armbruster3960c412013-02-05 09:30:55 +0100745 },
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200746 {
747 /* U+FDD0 */
748 "\"\xEF\xB7\x90\"",
749 "\xEF\xB7\x90", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200750 "\"\\uFFFD\"",
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200751 },
752 {
753 /* U+FDEF */
754 "\"\xEF\xB7\xAF\"",
755 "\xEF\xB7\xAF", /* bug: not corrected */
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200756 "\"\\uFFFD\"",
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200757 },
758 /* Plane 1 .. 16 noncharacters */
759 {
760 /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
761 "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
762 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
763 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
764 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
765 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
766 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
767 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
768 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
769 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
770 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
771 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
772 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
773 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
774 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
775 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
776 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
777 /* bug: not corrected */
778 "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
779 "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
780 "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
781 "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
782 "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
783 "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
784 "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
785 "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
786 "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
787 "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
788 "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
789 "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
790 "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
791 "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
792 "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
793 "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200794 "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
795 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
796 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
797 "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
Markus Armbruster1d50c8e2013-04-11 18:07:20 +0200798 },
Markus Armbruster3960c412013-02-05 09:30:55 +0100799 {}
800 };
801 int i;
802 QObject *obj;
803 QString *str;
804 const char *json_in, *utf8_out, *utf8_in, *json_out;
805
806 for (i = 0; test_cases[i].json_in; i++) {
807 json_in = test_cases[i].json_in;
808 utf8_out = test_cases[i].utf8_out;
809 utf8_in = test_cases[i].utf8_in ?: test_cases[i].utf8_out;
810 json_out = test_cases[i].json_out ?: test_cases[i].json_in;
811
812 obj = qobject_from_json(json_in);
813 if (utf8_out) {
Markus Armbruster3960c412013-02-05 09:30:55 +0100814 str = qobject_to_qstring(obj);
Markus Armbruster363e13f2017-02-17 21:38:20 +0100815 g_assert(str);
Markus Armbruster3960c412013-02-05 09:30:55 +0100816 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
817 } else {
818 g_assert(!obj);
819 }
820 qobject_decref(obj);
821
822 obj = QOBJECT(qstring_from_str(utf8_in));
823 str = qobject_to_json(obj);
824 if (json_out) {
825 g_assert(str);
826 g_assert_cmpstr(qstring_get_str(str), ==, json_out);
827 } else {
828 g_assert(!str);
829 }
830 QDECREF(str);
831 qobject_decref(obj);
832
833 /*
Markus Armbrustere2ec3f92013-04-11 18:07:21 +0200834 * Disabled, because qobject_from_json() is buggy, and I can't
835 * be bothered to add the expected incorrect results.
Markus Armbruster3960c412013-02-05 09:30:55 +0100836 * FIXME Enable once these bugs have been fixed.
837 */
838 if (0 && json_out != json_in) {
839 obj = qobject_from_json(json_out);
Markus Armbruster3960c412013-02-05 09:30:55 +0100840 str = qobject_to_qstring(obj);
Markus Armbruster363e13f2017-02-17 21:38:20 +0100841 g_assert(str);
Markus Armbruster3960c412013-02-05 09:30:55 +0100842 g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
843 }
844 }
845}
846
Anthony Liguorief76dc52012-01-10 13:10:49 -0600847static void vararg_string(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600848{
849 int i;
850 struct {
851 const char *decoded;
852 } test_cases[] = {
853 { "hello world" },
854 { "the quick brown fox jumped over the fence" },
855 {}
856 };
857
858 for (i = 0; test_cases[i].decoded; i++) {
Anthony Liguori422c46a2009-11-11 10:39:47 -0600859 QString *str;
860
Markus Armbruster363e13f2017-02-17 21:38:20 +0100861 str = qobject_to_qstring(qobject_from_jsonf("%s",
862 test_cases[i].decoded));
863 g_assert(str);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600864 g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600865
866 QDECREF(str);
867 }
868}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600869
Anthony Liguorief76dc52012-01-10 13:10:49 -0600870static void simple_number(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600871{
872 int i;
873 struct {
874 const char *encoded;
875 int64_t decoded;
Anthony Liguori6ee59202009-11-11 13:16:03 -0600876 int skip;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600877 } test_cases[] = {
878 { "0", 0 },
879 { "1234", 1234 },
880 { "1", 1 },
881 { "-32", -32 },
Anthony Liguori6ee59202009-11-11 13:16:03 -0600882 { "-0", 0, .skip = 1 },
Anthony Liguori422c46a2009-11-11 10:39:47 -0600883 { },
884 };
885
886 for (i = 0; test_cases[i].encoded; i++) {
Anthony Liguori422c46a2009-11-11 10:39:47 -0600887 QInt *qint;
888
Markus Armbruster0abfc4b2017-02-17 21:38:21 +0100889 qint = qobject_to_qint(qobject_from_json(test_cases[i].encoded));
890 g_assert(qint);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600891 g_assert(qint_get_int(qint) == test_cases[i].decoded);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600892 if (test_cases[i].skip == 0) {
893 QString *str;
894
Markus Armbruster0abfc4b2017-02-17 21:38:21 +0100895 str = qobject_to_json(QOBJECT(qint));
Anthony Liguorief76dc52012-01-10 13:10:49 -0600896 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600897 QDECREF(str);
898 }
Anthony Liguori422c46a2009-11-11 10:39:47 -0600899
900 QDECREF(qint);
901 }
902}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600903
Anthony Liguorief76dc52012-01-10 13:10:49 -0600904static void float_number(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600905{
906 int i;
907 struct {
908 const char *encoded;
909 double decoded;
Anthony Liguori6ee59202009-11-11 13:16:03 -0600910 int skip;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600911 } test_cases[] = {
912 { "32.43", 32.43 },
913 { "0.222", 0.222 },
914 { "-32.12313", -32.12313 },
Anthony Liguori6ee59202009-11-11 13:16:03 -0600915 { "-32.20e-10", -32.20e-10, .skip = 1 },
Anthony Liguori422c46a2009-11-11 10:39:47 -0600916 { },
917 };
918
919 for (i = 0; test_cases[i].encoded; i++) {
920 QObject *obj;
921 QFloat *qfloat;
922
923 obj = qobject_from_json(test_cases[i].encoded);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600924 qfloat = qobject_to_qfloat(obj);
Markus Armbruster8978b342017-02-17 21:38:22 +0100925 g_assert(qfloat);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600926 g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600927
Anthony Liguori6ee59202009-11-11 13:16:03 -0600928 if (test_cases[i].skip == 0) {
929 QString *str;
930
931 str = qobject_to_json(obj);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600932 g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600933 QDECREF(str);
934 }
935
Anthony Liguori422c46a2009-11-11 10:39:47 -0600936 QDECREF(qfloat);
937 }
938}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600939
Anthony Liguorief76dc52012-01-10 13:10:49 -0600940static void vararg_number(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600941{
Anthony Liguori422c46a2009-11-11 10:39:47 -0600942 QInt *qint;
943 QFloat *qfloat;
944 int value = 0x2342;
Eric Blake29a67312016-11-23 11:36:56 -0600945 long long value_ll = 0x2342342343LL;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600946 double valuef = 2.323423423;
947
Markus Armbruster0abfc4b2017-02-17 21:38:21 +0100948 qint = qobject_to_qint(qobject_from_jsonf("%d", value));
Anthony Liguorief76dc52012-01-10 13:10:49 -0600949 g_assert(qint_get_int(qint) == value);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600950 QDECREF(qint);
951
Markus Armbruster0abfc4b2017-02-17 21:38:21 +0100952 qint = qobject_to_qint(qobject_from_jsonf("%lld", value_ll));
Eric Blake29a67312016-11-23 11:36:56 -0600953 g_assert(qint_get_int(qint) == value_ll);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600954 QDECREF(qint);
955
Markus Armbruster8978b342017-02-17 21:38:22 +0100956 qfloat = qobject_to_qfloat(qobject_from_jsonf("%f", valuef));
Anthony Liguorief76dc52012-01-10 13:10:49 -0600957 g_assert(qfloat_get_double(qfloat) == valuef);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600958 QDECREF(qfloat);
959}
Anthony Liguori422c46a2009-11-11 10:39:47 -0600960
Anthony Liguorief76dc52012-01-10 13:10:49 -0600961static void keyword_literal(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -0600962{
963 QObject *obj;
964 QBool *qbool;
Eric Blakee549e712015-04-29 15:35:06 -0600965 QObject *null;
Anthony Liguori6ee59202009-11-11 13:16:03 -0600966 QString *str;
Anthony Liguori422c46a2009-11-11 10:39:47 -0600967
968 obj = qobject_from_json("true");
Anthony Liguori422c46a2009-11-11 10:39:47 -0600969 qbool = qobject_to_qbool(obj);
Markus Armbrusterdfad9ec2017-02-17 21:38:23 +0100970 g_assert(qbool);
Eric Blakefc48ffc2015-05-15 16:24:59 -0600971 g_assert(qbool_get_bool(qbool) == true);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600972
Anthony Liguori6ee59202009-11-11 13:16:03 -0600973 str = qobject_to_json(obj);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600974 g_assert(strcmp(qstring_get_str(str), "true") == 0);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600975 QDECREF(str);
976
Anthony Liguori422c46a2009-11-11 10:39:47 -0600977 QDECREF(qbool);
978
979 obj = qobject_from_json("false");
Anthony Liguori422c46a2009-11-11 10:39:47 -0600980 qbool = qobject_to_qbool(obj);
Markus Armbrusterdfad9ec2017-02-17 21:38:23 +0100981 g_assert(qbool);
Eric Blakefc48ffc2015-05-15 16:24:59 -0600982 g_assert(qbool_get_bool(qbool) == false);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600983
Anthony Liguori6ee59202009-11-11 13:16:03 -0600984 str = qobject_to_json(obj);
Anthony Liguorief76dc52012-01-10 13:10:49 -0600985 g_assert(strcmp(qstring_get_str(str), "false") == 0);
Anthony Liguori6ee59202009-11-11 13:16:03 -0600986 QDECREF(str);
987
Anthony Liguori422c46a2009-11-11 10:39:47 -0600988 QDECREF(qbool);
989
Markus Armbrusterdfad9ec2017-02-17 21:38:23 +0100990 qbool = qobject_to_qbool(qobject_from_jsonf("%i", false));
991 g_assert(qbool);
Eric Blakefc48ffc2015-05-15 16:24:59 -0600992 g_assert(qbool_get_bool(qbool) == false);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600993 QDECREF(qbool);
Eric Blakee549e712015-04-29 15:35:06 -0600994
Eric Blakefc48ffc2015-05-15 16:24:59 -0600995 /* Test that non-zero values other than 1 get collapsed to true */
Markus Armbrusterdfad9ec2017-02-17 21:38:23 +0100996 qbool = qobject_to_qbool(qobject_from_jsonf("%i", 2));
997 g_assert(qbool);
Eric Blakefc48ffc2015-05-15 16:24:59 -0600998 g_assert(qbool_get_bool(qbool) == true);
Anthony Liguori422c46a2009-11-11 10:39:47 -0600999 QDECREF(qbool);
Eric Blakee549e712015-04-29 15:35:06 -06001000
1001 obj = qobject_from_json("null");
1002 g_assert(obj != NULL);
1003 g_assert(qobject_type(obj) == QTYPE_QNULL);
1004
1005 null = qnull();
1006 g_assert(null == obj);
1007
1008 qobject_decref(obj);
1009 qobject_decref(null);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001010}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001011
1012typedef struct LiteralQDictEntry LiteralQDictEntry;
1013typedef struct LiteralQObject LiteralQObject;
1014
1015struct LiteralQObject
1016{
1017 int type;
1018 union {
1019 int64_t qint;
1020 const char *qstr;
1021 LiteralQDictEntry *qdict;
1022 LiteralQObject *qlist;
1023 } value;
1024};
1025
1026struct LiteralQDictEntry
1027{
1028 const char *key;
1029 LiteralQObject value;
1030};
1031
1032#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1033#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1034#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1035#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1036
1037typedef struct QListCompareHelper
1038{
1039 int index;
1040 LiteralQObject *objs;
1041 int result;
1042} QListCompareHelper;
1043
1044static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1045
1046static void compare_helper(QObject *obj, void *opaque)
1047{
1048 QListCompareHelper *helper = opaque;
1049
1050 if (helper->result == 0) {
1051 return;
1052 }
1053
1054 if (helper->objs[helper->index].type == QTYPE_NONE) {
1055 helper->result = 0;
1056 return;
1057 }
1058
1059 helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1060}
1061
1062static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1063{
Markus Armbruster9eaaf972017-02-17 21:38:15 +01001064 if (!rhs || lhs->type != qobject_type(rhs)) {
Anthony Liguori422c46a2009-11-11 10:39:47 -06001065 return 0;
1066 }
1067
1068 switch (lhs->type) {
1069 case QTYPE_QINT:
1070 return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
1071 case QTYPE_QSTRING:
1072 return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1073 case QTYPE_QDICT: {
1074 int i;
1075
1076 for (i = 0; lhs->value.qdict[i].key; i++) {
1077 QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1078
1079 if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1080 return 0;
1081 }
1082 }
1083
1084 return 1;
1085 }
1086 case QTYPE_QLIST: {
1087 QListCompareHelper helper;
1088
1089 helper.index = 0;
1090 helper.objs = lhs->value.qlist;
1091 helper.result = 1;
1092
1093 qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1094
1095 return helper.result;
1096 }
1097 default:
1098 break;
1099 }
1100
1101 return 0;
1102}
1103
Anthony Liguorief76dc52012-01-10 13:10:49 -06001104static void simple_dict(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001105{
1106 int i;
1107 struct {
1108 const char *encoded;
1109 LiteralQObject decoded;
1110 } test_cases[] = {
1111 {
Anthony Liguori6ee59202009-11-11 13:16:03 -06001112 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
Anthony Liguori422c46a2009-11-11 10:39:47 -06001113 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1114 { "foo", QLIT_QINT(42) },
1115 { "bar", QLIT_QSTR("hello world") },
1116 { }
1117 })),
1118 }, {
1119 .encoded = "{}",
1120 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1121 { }
1122 })),
1123 }, {
Anthony Liguori6ee59202009-11-11 13:16:03 -06001124 .encoded = "{\"foo\": 43}",
Anthony Liguori422c46a2009-11-11 10:39:47 -06001125 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1126 { "foo", QLIT_QINT(43) },
1127 { }
1128 })),
1129 },
1130 { }
1131 };
1132
1133 for (i = 0; test_cases[i].encoded; i++) {
1134 QObject *obj;
Anthony Liguori6ee59202009-11-11 13:16:03 -06001135 QString *str;
Anthony Liguori422c46a2009-11-11 10:39:47 -06001136
1137 obj = qobject_from_json(test_cases[i].encoded);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001138 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001139
Anthony Liguori6ee59202009-11-11 13:16:03 -06001140 str = qobject_to_json(obj);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001141 qobject_decref(obj);
Anthony Liguori6ee59202009-11-11 13:16:03 -06001142
1143 obj = qobject_from_json(qstring_get_str(str));
Anthony Liguorief76dc52012-01-10 13:10:49 -06001144 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
Anthony Liguori6ee59202009-11-11 13:16:03 -06001145 qobject_decref(obj);
1146 QDECREF(str);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001147 }
1148}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001149
Michael Roth7109edf2012-08-15 13:45:44 -05001150/*
1151 * this generates json of the form:
1152 * a(0,m) = [0, 1, ..., m-1]
1153 * a(n,m) = {
1154 * 'key0': a(0,m),
1155 * 'key1': a(1,m),
1156 * ...
1157 * 'key(n-1)': a(n-1,m)
1158 * }
1159 */
1160static void gen_test_json(GString *gstr, int nest_level_max,
1161 int elem_count)
1162{
1163 int i;
1164
1165 g_assert(gstr);
1166 if (nest_level_max == 0) {
1167 g_string_append(gstr, "[");
1168 for (i = 0; i < elem_count; i++) {
1169 g_string_append_printf(gstr, "%d", i);
1170 if (i < elem_count - 1) {
1171 g_string_append_printf(gstr, ", ");
1172 }
1173 }
1174 g_string_append(gstr, "]");
1175 return;
1176 }
1177
1178 g_string_append(gstr, "{");
1179 for (i = 0; i < nest_level_max; i++) {
1180 g_string_append_printf(gstr, "'key%d': ", i);
1181 gen_test_json(gstr, i, elem_count);
1182 if (i < nest_level_max - 1) {
1183 g_string_append(gstr, ",");
1184 }
1185 }
1186 g_string_append(gstr, "}");
1187}
1188
1189static void large_dict(void)
1190{
1191 GString *gstr = g_string_new("");
1192 QObject *obj;
1193
1194 gen_test_json(gstr, 10, 100);
1195 obj = qobject_from_json(gstr->str);
1196 g_assert(obj != NULL);
1197
1198 qobject_decref(obj);
1199 g_string_free(gstr, true);
1200}
1201
Anthony Liguorief76dc52012-01-10 13:10:49 -06001202static void simple_list(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001203{
1204 int i;
1205 struct {
1206 const char *encoded;
1207 LiteralQObject decoded;
1208 } test_cases[] = {
1209 {
1210 .encoded = "[43,42]",
1211 .decoded = QLIT_QLIST(((LiteralQObject[]){
1212 QLIT_QINT(43),
1213 QLIT_QINT(42),
1214 { }
1215 })),
1216 },
1217 {
1218 .encoded = "[43]",
1219 .decoded = QLIT_QLIST(((LiteralQObject[]){
1220 QLIT_QINT(43),
1221 { }
1222 })),
1223 },
1224 {
1225 .encoded = "[]",
1226 .decoded = QLIT_QLIST(((LiteralQObject[]){
1227 { }
1228 })),
1229 },
1230 {
1231 .encoded = "[{}]",
1232 .decoded = QLIT_QLIST(((LiteralQObject[]){
1233 QLIT_QDICT(((LiteralQDictEntry[]){
1234 {},
1235 })),
1236 {},
1237 })),
1238 },
1239 { }
1240 };
1241
1242 for (i = 0; test_cases[i].encoded; i++) {
1243 QObject *obj;
Anthony Liguori6ee59202009-11-11 13:16:03 -06001244 QString *str;
Anthony Liguori422c46a2009-11-11 10:39:47 -06001245
1246 obj = qobject_from_json(test_cases[i].encoded);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001247 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001248
Anthony Liguori6ee59202009-11-11 13:16:03 -06001249 str = qobject_to_json(obj);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001250 qobject_decref(obj);
Anthony Liguori6ee59202009-11-11 13:16:03 -06001251
1252 obj = qobject_from_json(qstring_get_str(str));
Anthony Liguorief76dc52012-01-10 13:10:49 -06001253 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
Anthony Liguori6ee59202009-11-11 13:16:03 -06001254 qobject_decref(obj);
1255 QDECREF(str);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001256 }
1257}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001258
Anthony Liguorief76dc52012-01-10 13:10:49 -06001259static void simple_whitespace(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001260{
1261 int i;
1262 struct {
1263 const char *encoded;
1264 LiteralQObject decoded;
1265 } test_cases[] = {
1266 {
1267 .encoded = " [ 43 , 42 ]",
1268 .decoded = QLIT_QLIST(((LiteralQObject[]){
1269 QLIT_QINT(43),
1270 QLIT_QINT(42),
1271 { }
1272 })),
1273 },
1274 {
1275 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1276 .decoded = QLIT_QLIST(((LiteralQObject[]){
1277 QLIT_QINT(43),
1278 QLIT_QDICT(((LiteralQDictEntry[]){
1279 { "h", QLIT_QSTR("b") },
1280 { }})),
1281 QLIT_QLIST(((LiteralQObject[]){
1282 { }})),
1283 QLIT_QINT(42),
1284 { }
1285 })),
1286 },
1287 {
1288 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1289 .decoded = QLIT_QLIST(((LiteralQObject[]){
1290 QLIT_QINT(43),
1291 QLIT_QDICT(((LiteralQDictEntry[]){
1292 { "h", QLIT_QSTR("b") },
1293 { "a", QLIT_QINT(32) },
1294 { }})),
1295 QLIT_QLIST(((LiteralQObject[]){
1296 { }})),
1297 QLIT_QINT(42),
1298 { }
1299 })),
1300 },
1301 { }
1302 };
1303
1304 for (i = 0; test_cases[i].encoded; i++) {
1305 QObject *obj;
Anthony Liguori6ee59202009-11-11 13:16:03 -06001306 QString *str;
Anthony Liguori422c46a2009-11-11 10:39:47 -06001307
1308 obj = qobject_from_json(test_cases[i].encoded);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001309 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001310
Anthony Liguori6ee59202009-11-11 13:16:03 -06001311 str = qobject_to_json(obj);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001312 qobject_decref(obj);
Anthony Liguori6ee59202009-11-11 13:16:03 -06001313
1314 obj = qobject_from_json(qstring_get_str(str));
Anthony Liguorief76dc52012-01-10 13:10:49 -06001315 g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
Anthony Liguori6ee59202009-11-11 13:16:03 -06001316
1317 qobject_decref(obj);
1318 QDECREF(str);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001319 }
1320}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001321
Anthony Liguorief76dc52012-01-10 13:10:49 -06001322static void simple_varargs(void)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001323{
1324 QObject *embedded_obj;
1325 QObject *obj;
1326 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1327 QLIT_QINT(1),
1328 QLIT_QINT(2),
1329 QLIT_QLIST(((LiteralQObject[]){
1330 QLIT_QINT(32),
1331 QLIT_QINT(42),
1332 {}})),
1333 {}}));
1334
1335 embedded_obj = qobject_from_json("[32, 42]");
Anthony Liguorief76dc52012-01-10 13:10:49 -06001336 g_assert(embedded_obj != NULL);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001337
1338 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001339 g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001340
1341 qobject_decref(obj);
1342}
Anthony Liguori422c46a2009-11-11 10:39:47 -06001343
Anthony Liguorief76dc52012-01-10 13:10:49 -06001344static void empty_input(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001345{
Jan Kiszkae7a06af2010-10-16 19:42:43 +02001346 const char *empty = "";
1347
1348 QObject *obj = qobject_from_json(empty);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001349 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001350}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001351
Anthony Liguorief76dc52012-01-10 13:10:49 -06001352static void unterminated_string(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001353{
1354 QObject *obj = qobject_from_json("\"abc");
Anthony Liguorief76dc52012-01-10 13:10:49 -06001355 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001356}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001357
Anthony Liguorief76dc52012-01-10 13:10:49 -06001358static void unterminated_sq_string(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001359{
1360 QObject *obj = qobject_from_json("'abc");
Anthony Liguorief76dc52012-01-10 13:10:49 -06001361 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001362}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001363
Anthony Liguorief76dc52012-01-10 13:10:49 -06001364static void unterminated_escape(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001365{
1366 QObject *obj = qobject_from_json("\"abc\\\"");
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{
1372 QObject *obj = qobject_from_json("[32");
Anthony Liguorief76dc52012-01-10 13:10:49 -06001373 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001374}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001375
Anthony Liguorief76dc52012-01-10 13:10:49 -06001376static void unterminated_array_comma(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001377{
1378 QObject *obj = qobject_from_json("[32,");
Anthony Liguorief76dc52012-01-10 13:10:49 -06001379 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001380}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001381
Anthony Liguorief76dc52012-01-10 13:10:49 -06001382static void invalid_array_comma(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001383{
1384 QObject *obj = qobject_from_json("[32,}");
Anthony Liguorief76dc52012-01-10 13:10:49 -06001385 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001386}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001387
Anthony Liguorief76dc52012-01-10 13:10:49 -06001388static void unterminated_dict(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001389{
1390 QObject *obj = qobject_from_json("{'abc':32");
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_comma(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001395{
1396 QObject *obj = qobject_from_json("{'abc':32,");
Anthony Liguorief76dc52012-01-10 13:10:49 -06001397 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001398}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001399
Anthony Liguorief76dc52012-01-10 13:10:49 -06001400static void invalid_dict_comma(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001401{
1402 QObject *obj = qobject_from_json("{'abc':32,}");
Anthony Liguorief76dc52012-01-10 13:10:49 -06001403 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001404}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001405
Anthony Liguorief76dc52012-01-10 13:10:49 -06001406static void unterminated_literal(void)
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001407{
1408 QObject *obj = qobject_from_json("nul");
Anthony Liguorief76dc52012-01-10 13:10:49 -06001409 g_assert(obj == NULL);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001410}
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001411
Markus Armbrusterf0ae0302015-11-25 22:23:24 +01001412static char *make_nest(char *buf, size_t cnt)
1413{
1414 memset(buf, '[', cnt - 1);
1415 buf[cnt - 1] = '{';
1416 buf[cnt] = '}';
1417 memset(buf + cnt + 1, ']', cnt - 1);
1418 buf[2 * cnt] = 0;
1419 return buf;
1420}
1421
1422static void limits_nesting(void)
1423{
1424 enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1425 char buf[2 * (max_nesting + 1) + 1];
1426 QObject *obj;
1427
1428 obj = qobject_from_json(make_nest(buf, max_nesting));
1429 g_assert(obj != NULL);
1430 qobject_decref(obj);
1431
1432 obj = qobject_from_json(make_nest(buf, max_nesting + 1));
1433 g_assert(obj == NULL);
1434}
1435
Anthony Liguorief76dc52012-01-10 13:10:49 -06001436int main(int argc, char **argv)
Anthony Liguori422c46a2009-11-11 10:39:47 -06001437{
Anthony Liguorief76dc52012-01-10 13:10:49 -06001438 g_test_init(&argc, &argv, NULL);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001439
Anthony Liguorief76dc52012-01-10 13:10:49 -06001440 g_test_add_func("/literals/string/simple", simple_string);
1441 g_test_add_func("/literals/string/escaped", escaped_string);
Markus Armbruster3960c412013-02-05 09:30:55 +01001442 g_test_add_func("/literals/string/utf8", utf8_string);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001443 g_test_add_func("/literals/string/single_quote", single_quote_string);
1444 g_test_add_func("/literals/string/vararg", vararg_string);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001445
Anthony Liguorief76dc52012-01-10 13:10:49 -06001446 g_test_add_func("/literals/number/simple", simple_number);
1447 g_test_add_func("/literals/number/float", float_number);
1448 g_test_add_func("/literals/number/vararg", vararg_number);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001449
Anthony Liguorief76dc52012-01-10 13:10:49 -06001450 g_test_add_func("/literals/keyword", keyword_literal);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001451
Anthony Liguorief76dc52012-01-10 13:10:49 -06001452 g_test_add_func("/dicts/simple_dict", simple_dict);
Michael Roth7109edf2012-08-15 13:45:44 -05001453 g_test_add_func("/dicts/large_dict", large_dict);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001454 g_test_add_func("/lists/simple_list", simple_list);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001455
Anthony Liguorief76dc52012-01-10 13:10:49 -06001456 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
Anthony Liguori422c46a2009-11-11 10:39:47 -06001457
Anthony Liguorief76dc52012-01-10 13:10:49 -06001458 g_test_add_func("/varargs/simple_varargs", simple_varargs);
1459
1460 g_test_add_func("/errors/empty_input", empty_input);
1461 g_test_add_func("/errors/unterminated/string", unterminated_string);
1462 g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1463 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1464 g_test_add_func("/errors/unterminated/array", unterminated_array);
1465 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1466 g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1467 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1468 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
Anthony Liguorief76dc52012-01-10 13:10:49 -06001469 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1470 g_test_add_func("/errors/unterminated/literal", unterminated_literal);
Markus Armbrusterf0ae0302015-11-25 22:23:24 +01001471 g_test_add_func("/errors/limits/nesting", limits_nesting);
Paolo Bonzini7f8fca72010-05-24 09:39:51 +02001472
Anthony Liguorief76dc52012-01-10 13:10:49 -06001473 return g_test_run();
Anthony Liguori422c46a2009-11-11 10:39:47 -06001474}