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