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