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