Statistics
| Branch: | Revision:

root / tests / check-qjson.c @ f53ec699

History | View | Annotate | Download (45 kB)

1
/*
2
 * Copyright IBM, Corp. 2009
3
 * Copyright (c) 2013 Red Hat Inc.
4
 *
5
 * Authors:
6
 *  Anthony Liguori   <aliguori@us.ibm.com>
7
 *  Markus Armbruster <armbru@redhat.com>
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
 */
13
#include <glib.h>
14

    
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"
22

    
23
#include "qemu-common.h"
24

    
25
static void escaped_string(void)
26
{
27
    int i;
28
    struct {
29
        const char *encoded;
30
        const char *decoded;
31
        int skip;
32
    } test_cases[] = {
33
        { "\"\\b\"", "\b" },
34
        { "\"\\f\"", "\f" },
35
        { "\"\\n\"", "\n" },
36
        { "\"\\r\"", "\r" },
37
        { "\"\\t\"", "\t" },
38
        { "\"/\"", "/" },
39
        { "\"\\/\"", "/", .skip = 1 },
40
        { "\"\\\\\"", "\\" },
41
        { "\"\\\"\"", "\"" },
42
        { "\"hello world \\\"embedded string\\\"\"",
43
          "hello world \"embedded string\"" },
44
        { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
45
        { "\"single byte utf-8 \\u0020\"", "single byte utf-8  ", .skip = 1 },
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

    
57
        g_assert(obj != NULL);
58
        g_assert(qobject_type(obj) == QTYPE_QSTRING);
59
        
60
        str = qobject_to_qstring(obj);
61
        g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
62

    
63
        if (test_cases[i].skip == 0) {
64
            str = qobject_to_json(obj);
65
            g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
66
            qobject_decref(obj);
67
        }
68

    
69
        QDECREF(str);
70
    }
71
}
72

    
73
static void simple_string(void)
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

    
92
        g_assert(obj != NULL);
93
        g_assert(qobject_type(obj) == QTYPE_QSTRING);
94
        
95
        str = qobject_to_qstring(obj);
96
        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
97

    
98
        str = qobject_to_json(obj);
99
        g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
100

    
101
        qobject_decref(obj);
102
        
103
        QDECREF(str);
104
    }
105
}
106

    
107
static void single_quote_string(void)
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

    
126
        g_assert(obj != NULL);
127
        g_assert(qobject_type(obj) == QTYPE_QSTRING);
128
        
129
        str = qobject_to_qstring(obj);
130
        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
131

    
132
        QDECREF(str);
133
    }
134
}
135

    
136
static 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
     *
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.
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
     *
158
     * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
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
175
         * - bug: want "..."
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
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" */
203
            "\"\\u0000\"",
204
            "\xC0\x80",
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",
222
            "\"\\uD800\\uDC00\"",
223
        },
224
        /* 2.1.5  5 bytes U+200000 */
225
        {
226
            "\"\xF8\x88\x80\x80\x80\"",
227
            NULL,               /* bug: rejected */
228
            "\"\\uFFFD\"",
229
            "\xF8\x88\x80\x80\x80",
230
        },
231
        /* 2.1.6  6 bytes U+4000000 */
232
        {
233
            "\"\xFC\x84\x80\x80\x80\x80\"",
234
            NULL,               /* bug: rejected */
235
            "\"\\uFFFD\"",
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",
243
            "\"\\u007F\"",
244
        },
245
        /* 2.2.2  2 bytes U+07FF */
246
        {
247
            "\"\xDF\xBF\"",
248
            "\xDF\xBF",
249
            "\"\\u07FF\"",
250
        },
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
         */
260
        {
261
            "\"\xEF\xBF\xBC\"",
262
            "\xEF\xBF\xBC",
263
            "\"\\uFFFC\"",
264
        },
265
        /* 2.2.4  4 bytes U+1FFFFF */
266
        {
267
            "\"\xF7\xBF\xBF\xBF\"",
268
            NULL,               /* bug: rejected */
269
            "\"\\uFFFD\"",
270
            "\xF7\xBF\xBF\xBF",
271
        },
272
        /* 2.2.5  5 bytes U+3FFFFFF */
273
        {
274
            "\"\xFB\xBF\xBF\xBF\xBF\"",
275
            NULL,               /* bug: rejected */
276
            "\"\\uFFFD\"",
277
            "\xFB\xBF\xBF\xBF\xBF",
278
        },
279
        /* 2.2.6  6 bytes U+7FFFFFFF */
280
        {
281
            "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
282
            NULL,               /* bug: rejected */
283
            "\"\\uFFFD\"",
284
            "\xFD\xBF\xBF\xBF\xBF\xBF",
285
        },
286
        /* 2.3  Other boundary conditions */
287
        {
288
            /* last one before surrogate range: U+D7FF */
289
            "\"\xED\x9F\xBF\"",
290
            "\xED\x9F\xBF",
291
            "\"\\uD7FF\"",
292
        },
293
        {
294
            /* first one after surrogate range: U+E000 */
295
            "\"\xEE\x80\x80\"",
296
            "\xEE\x80\x80",
297
            "\"\\uE000\"",
298
        },
299
        {
300
            /* last one in BMP: U+FFFD */
301
            "\"\xEF\xBF\xBD\"",
302
            "\xEF\xBF\xBD",
303
            "\"\\uFFFD\"",
304
        },
305
        {
306
            /* last one in last plane: U+10FFFD */
307
            "\"\xF4\x8F\xBF\xBD\"",
308
            "\xF4\x8F\xBF\xBD",
309
            "\"\\uDBFF\\uDFFD\""
310
        },
311
        {
312
            /* first one beyond Unicode range: U+110000 */
313
            "\"\xF4\x90\x80\x80\"",
314
            "\xF4\x90\x80\x80",
315
            "\"\\uFFFD\"",
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 */
323
            "\"\\uFFFD\"",
324
        },
325
        /* 3.1.2  Last continuation byte */
326
        {
327
            "\"\xBF\"",
328
            "\xBF",             /* bug: not corrected */
329
            "\"\\uFFFD\"",
330
        },
331
        /* 3.1.3  2 continuation bytes */
332
        {
333
            "\"\x80\xBF\"",
334
            "\x80\xBF",         /* bug: not corrected */
335
            "\"\\uFFFD\\uFFFD\"",
336
        },
337
        /* 3.1.4  3 continuation bytes */
338
        {
339
            "\"\x80\xBF\x80\"",
340
            "\x80\xBF\x80",     /* bug: not corrected */
341
            "\"\\uFFFD\\uFFFD\\uFFFD\"",
342
        },
343
        /* 3.1.5  4 continuation bytes */
344
        {
345
            "\"\x80\xBF\x80\xBF\"",
346
            "\x80\xBF\x80\xBF", /* bug: not corrected */
347
            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
348
        },
349
        /* 3.1.6  5 continuation bytes */
350
        {
351
            "\"\x80\xBF\x80\xBF\x80\"",
352
            "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
353
            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
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 */
359
            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
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 */
365
            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
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",
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\""
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 */
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 \"",
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 ",
419
            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
420
            "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
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 */
426
            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
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 */
433
            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
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 */
440
            "\"\\uFFFD \\uFFFD \"",
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 */
448
            "\"\\uFFFD\"",
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 */
455
            "\"\\uFFFD\"",
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 */
461
            "\"\\uFFFD\"",
462
        },
463
        /* 3.3.4  5-byte sequence with last byte missing (U+0000) */
464
        {
465
            "\"\xF8\x80\x80\x80\"",
466
            NULL,                   /* bug: rejected */
467
            "\"\\uFFFD\"",
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 */
474
            "\"\\uFFFD\"",
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 */
481
            "\"\\uFFFD\"",
482
        },
483
        /* 3.3.7  3-byte sequence with last byte missing (U+FFFF) */
484
        {
485
            "\"\xEF\xBF\"",
486
            "\xEF\xBF",           /* bug: not corrected */
487
            "\"\\uFFFD\"",
488
        },
489
        /* 3.3.8  4-byte sequence with last byte missing (U+1FFFFF) */
490
        {
491
            "\"\xF7\xBF\xBF\"",
492
            NULL,               /* bug: rejected */
493
            "\"\\uFFFD\"",
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 */
500
            "\"\\uFFFD\"",
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 */
507
            "\"\\uFFFD\"",
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 */
515
            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
516
            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
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 */
524
            "\"\\uFFFD\"",
525
            "\xFE",
526
        },
527
        {
528
            "\"\xFF\"",
529
            NULL,               /* bug: rejected */
530
            "\"\\uFFFD\"",
531
            "\xFF",
532
        },
533
        {
534
            "\"\xFE\xFE\xFF\xFF\"",
535
            NULL,                 /* bug: rejected */
536
            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
537
            "\xFE\xFE\xFF\xFF",
538
        },
539
        /* 4  Overlong sequences */
540
        /* 4.1  Overlong '/' */
541
        {
542
            "\"\xC0\xAF\"",
543
            NULL,               /* bug: rejected */
544
            "\"\\uFFFD\"",
545
            "\xC0\xAF",
546
        },
547
        {
548
            "\"\xE0\x80\xAF\"",
549
            "\xE0\x80\xAF",     /* bug: not corrected */
550
            "\"\\uFFFD\"",
551
        },
552
        {
553
            "\"\xF0\x80\x80\xAF\"",
554
            "\xF0\x80\x80\xAF",  /* bug: not corrected */
555
            "\"\\uFFFD\"",
556
        },
557
        {
558
            "\"\xF8\x80\x80\x80\xAF\"",
559
            NULL,                        /* bug: rejected */
560
            "\"\\uFFFD\"",
561
            "\xF8\x80\x80\x80\xAF",
562
        },
563
        {
564
            "\"\xFC\x80\x80\x80\x80\xAF\"",
565
            NULL,                               /* bug: rejected */
566
            "\"\\uFFFD\"",
567
            "\xFC\x80\x80\x80\x80\xAF",
568
        },
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
         */
575
        {
576
            /* \U+007F */
577
            "\"\xC1\xBF\"",
578
            NULL,               /* bug: rejected */
579
            "\"\\uFFFD\"",
580
            "\xC1\xBF",
581
        },
582
        {
583
            /* \U+07FF */
584
            "\"\xE0\x9F\xBF\"",
585
            "\xE0\x9F\xBF",     /* bug: not corrected */
586
            "\"\\uFFFD\"",
587
        },
588
        {
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 */
597
            "\"\\uFFFD\"",
598
        },
599
        {
600
            /* \U+1FFFFF */
601
            "\"\xF8\x87\xBF\xBF\xBF\"",
602
            NULL,                        /* bug: rejected */
603
            "\"\\uFFFD\"",
604
            "\xF8\x87\xBF\xBF\xBF",
605
        },
606
        {
607
            /* \U+3FFFFFF */
608
            "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
609
            NULL,                               /* bug: rejected */
610
            "\"\\uFFFD\"",
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 */
625
            "\"\\uFFFD\"",
626
        },
627
        {
628
            /* \U+0000 */
629
            "\"\xF0\x80\x80\x80\"",
630
            "\xF0\x80\x80\x80",   /* bug: not corrected */
631
            "\"\\uFFFD\"",
632
        },
633
        {
634
            /* \U+0000 */
635
            "\"\xF8\x80\x80\x80\x80\"",
636
            NULL,                        /* bug: rejected */
637
            "\"\\uFFFD\"",
638
            "\xF8\x80\x80\x80\x80",
639
        },
640
        {
641
            /* \U+0000 */
642
            "\"\xFC\x80\x80\x80\x80\x80\"",
643
            NULL,                               /* bug: rejected */
644
            "\"\\uFFFD\"",
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 */
653
            "\"\\uFFFD\"",
654
        },
655
        {
656
            /* \U+DB7F */
657
            "\"\xED\xAD\xBF\"",
658
            "\xED\xAD\xBF",     /* bug: not corrected */
659
            "\"\\uFFFD\"",
660
        },
661
        {
662
            /* \U+DB80 */
663
            "\"\xED\xAE\x80\"",
664
            "\xED\xAE\x80",     /* bug: not corrected */
665
            "\"\\uFFFD\"",
666
        },
667
        {
668
            /* \U+DBFF */
669
            "\"\xED\xAF\xBF\"",
670
            "\xED\xAF\xBF",     /* bug: not corrected */
671
            "\"\\uFFFD\"",
672
        },
673
        {
674
            /* \U+DC00 */
675
            "\"\xED\xB0\x80\"",
676
            "\xED\xB0\x80",     /* bug: not corrected */
677
            "\"\\uFFFD\"",
678
        },
679
        {
680
            /* \U+DF80 */
681
            "\"\xED\xBE\x80\"",
682
            "\xED\xBE\x80",     /* bug: not corrected */
683
            "\"\\uFFFD\"",
684
        },
685
        {
686
            /* \U+DFFF */
687
            "\"\xED\xBF\xBF\"",
688
            "\xED\xBF\xBF",     /* bug: not corrected */
689
            "\"\\uFFFD\"",
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 */
696
            "\"\\uFFFD\\uFFFD\"",
697
        },
698
        {
699
            /* \U+D800\U+DFFF */
700
            "\"\xED\xA0\x80\xED\xBF\xBF\"",
701
            "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
702
            "\"\\uFFFD\\uFFFD\"",
703
        },
704
        {
705
            /* \U+DB7F\U+DC00 */
706
            "\"\xED\xAD\xBF\xED\xB0\x80\"",
707
            "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
708
            "\"\\uFFFD\\uFFFD\"",
709
        },
710
        {
711
            /* \U+DB7F\U+DFFF */
712
            "\"\xED\xAD\xBF\xED\xBF\xBF\"",
713
            "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
714
            "\"\\uFFFD\\uFFFD\"",
715
        },
716
        {
717
            /* \U+DB80\U+DC00 */
718
            "\"\xED\xAE\x80\xED\xB0\x80\"",
719
            "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
720
            "\"\\uFFFD\\uFFFD\"",
721
        },
722
        {
723
            /* \U+DB80\U+DFFF */
724
            "\"\xED\xAE\x80\xED\xBF\xBF\"",
725
            "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
726
            "\"\\uFFFD\\uFFFD\"",
727
        },
728
        {
729
            /* \U+DBFF\U+DC00 */
730
            "\"\xED\xAF\xBF\xED\xB0\x80\"",
731
            "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
732
            "\"\\uFFFD\\uFFFD\"",
733
        },
734
        {
735
            /* \U+DBFF\U+DFFF */
736
            "\"\xED\xAF\xBF\xED\xBF\xBF\"",
737
            "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
738
            "\"\\uFFFD\\uFFFD\"",
739
        },
740
        /* 5.3  Other illegal code positions */
741
        /* BMP noncharacters */
742
        {
743
            /* \U+FFFE */
744
            "\"\xEF\xBF\xBE\"",
745
            "\xEF\xBF\xBE",     /* bug: not corrected */
746
            "\"\\uFFFD\"",
747
        },
748
        {
749
            /* \U+FFFF */
750
            "\"\xEF\xBF\xBF\"",
751
            "\xEF\xBF\xBF",     /* bug: not corrected */
752
            "\"\\uFFFD\"",
753
        },
754
        {
755
            /* U+FDD0 */
756
            "\"\xEF\xB7\x90\"",
757
            "\xEF\xB7\x90",     /* bug: not corrected */
758
            "\"\\uFFFD\"",
759
        },
760
        {
761
            /* U+FDEF */
762
            "\"\xEF\xB7\xAF\"",
763
            "\xEF\xB7\xAF",     /* bug: not corrected */
764
            "\"\\uFFFD\"",
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",
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\"",
806
        },
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
        /*
843
         * Disabled, because qobject_from_json() is buggy, and I can't
844
         * be bothered to add the expected incorrect results.
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

    
857
static void vararg_string(void)
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

    
874
        g_assert(obj != NULL);
875
        g_assert(qobject_type(obj) == QTYPE_QSTRING);
876
        
877
        str = qobject_to_qstring(obj);
878
        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
879

    
880
        QDECREF(str);
881
    }
882
}
883

    
884
static void simple_number(void)
885
{
886
    int i;
887
    struct {
888
        const char *encoded;
889
        int64_t decoded;
890
        int skip;
891
    } test_cases[] = {
892
        { "0", 0 },
893
        { "1234", 1234 },
894
        { "1", 1 },
895
        { "-32", -32 },
896
        { "-0", 0, .skip = 1 },
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);
905
        g_assert(obj != NULL);
906
        g_assert(qobject_type(obj) == QTYPE_QINT);
907

    
908
        qint = qobject_to_qint(obj);
909
        g_assert(qint_get_int(qint) == test_cases[i].decoded);
910
        if (test_cases[i].skip == 0) {
911
            QString *str;
912

    
913
            str = qobject_to_json(obj);
914
            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
915
            QDECREF(str);
916
        }
917

    
918
        QDECREF(qint);
919
    }
920
}
921

    
922
static void float_number(void)
923
{
924
    int i;
925
    struct {
926
        const char *encoded;
927
        double decoded;
928
        int skip;
929
    } test_cases[] = {
930
        { "32.43", 32.43 },
931
        { "0.222", 0.222 },
932
        { "-32.12313", -32.12313 },
933
        { "-32.20e-10", -32.20e-10, .skip = 1 },
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);
942
        g_assert(obj != NULL);
943
        g_assert(qobject_type(obj) == QTYPE_QFLOAT);
944

    
945
        qfloat = qobject_to_qfloat(obj);
946
        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
947

    
948
        if (test_cases[i].skip == 0) {
949
            QString *str;
950

    
951
            str = qobject_to_json(obj);
952
            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
953
            QDECREF(str);
954
        }
955

    
956
        QDECREF(qfloat);
957
    }
958
}
959

    
960
static void vararg_number(void)
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);
970
    g_assert(obj != NULL);
971
    g_assert(qobject_type(obj) == QTYPE_QINT);
972

    
973
    qint = qobject_to_qint(obj);
974
    g_assert(qint_get_int(qint) == value);
975

    
976
    QDECREF(qint);
977

    
978
    obj = qobject_from_jsonf("%" PRId64, value64);
979
    g_assert(obj != NULL);
980
    g_assert(qobject_type(obj) == QTYPE_QINT);
981

    
982
    qint = qobject_to_qint(obj);
983
    g_assert(qint_get_int(qint) == value64);
984

    
985
    QDECREF(qint);
986

    
987
    obj = qobject_from_jsonf("%f", valuef);
988
    g_assert(obj != NULL);
989
    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
990

    
991
    qfloat = qobject_to_qfloat(obj);
992
    g_assert(qfloat_get_double(qfloat) == valuef);
993

    
994
    QDECREF(qfloat);
995
}
996

    
997
static void keyword_literal(void)
998
{
999
    QObject *obj;
1000
    QBool *qbool;
1001
    QString *str;
1002

    
1003
    obj = qobject_from_json("true");
1004
    g_assert(obj != NULL);
1005
    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1006

    
1007
    qbool = qobject_to_qbool(obj);
1008
    g_assert(qbool_get_int(qbool) != 0);
1009

    
1010
    str = qobject_to_json(obj);
1011
    g_assert(strcmp(qstring_get_str(str), "true") == 0);
1012
    QDECREF(str);
1013

    
1014
    QDECREF(qbool);
1015

    
1016
    obj = qobject_from_json("false");
1017
    g_assert(obj != NULL);
1018
    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1019

    
1020
    qbool = qobject_to_qbool(obj);
1021
    g_assert(qbool_get_int(qbool) == 0);
1022

    
1023
    str = qobject_to_json(obj);
1024
    g_assert(strcmp(qstring_get_str(str), "false") == 0);
1025
    QDECREF(str);
1026

    
1027
    QDECREF(qbool);
1028

    
1029
    obj = qobject_from_jsonf("%i", false);
1030
    g_assert(obj != NULL);
1031
    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1032

    
1033
    qbool = qobject_to_qbool(obj);
1034
    g_assert(qbool_get_int(qbool) == 0);
1035

    
1036
    QDECREF(qbool);
1037
    
1038
    obj = qobject_from_jsonf("%i", true);
1039
    g_assert(obj != NULL);
1040
    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1041

    
1042
    qbool = qobject_to_qbool(obj);
1043
    g_assert(qbool_get_int(qbool) != 0);
1044

    
1045
    QDECREF(qbool);
1046
}
1047

    
1048
typedef struct LiteralQDictEntry LiteralQDictEntry;
1049
typedef struct LiteralQObject LiteralQObject;
1050

    
1051
struct 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

    
1062
struct 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

    
1073
typedef struct QListCompareHelper
1074
{
1075
    int index;
1076
    LiteralQObject *objs;
1077
    int result;
1078
} QListCompareHelper;
1079

    
1080
static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1081

    
1082
static 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

    
1098
static 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

    
1140
static void simple_dict(void)
1141
{
1142
    int i;
1143
    struct {
1144
        const char *encoded;
1145
        LiteralQObject decoded;
1146
    } test_cases[] = {
1147
        {
1148
            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
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
        }, {
1160
            .encoded = "{\"foo\": 43}",
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;
1171
        QString *str;
1172

    
1173
        obj = qobject_from_json(test_cases[i].encoded);
1174
        g_assert(obj != NULL);
1175
        g_assert(qobject_type(obj) == QTYPE_QDICT);
1176

    
1177
        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1178

    
1179
        str = qobject_to_json(obj);
1180
        qobject_decref(obj);
1181

    
1182
        obj = qobject_from_json(qstring_get_str(str));
1183
        g_assert(obj != NULL);
1184
        g_assert(qobject_type(obj) == QTYPE_QDICT);
1185

    
1186
        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1187
        qobject_decref(obj);
1188
        QDECREF(str);
1189
    }
1190
}
1191

    
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
 */
1202
static 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

    
1231
static 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

    
1244
static void simple_list(void)
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;
1286
        QString *str;
1287

    
1288
        obj = qobject_from_json(test_cases[i].encoded);
1289
        g_assert(obj != NULL);
1290
        g_assert(qobject_type(obj) == QTYPE_QLIST);
1291

    
1292
        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1293

    
1294
        str = qobject_to_json(obj);
1295
        qobject_decref(obj);
1296

    
1297
        obj = qobject_from_json(qstring_get_str(str));
1298
        g_assert(obj != NULL);
1299
        g_assert(qobject_type(obj) == QTYPE_QLIST);
1300

    
1301
        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1302
        qobject_decref(obj);
1303
        QDECREF(str);
1304
    }
1305
}
1306

    
1307
static void simple_whitespace(void)
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;
1354
        QString *str;
1355

    
1356
        obj = qobject_from_json(test_cases[i].encoded);
1357
        g_assert(obj != NULL);
1358
        g_assert(qobject_type(obj) == QTYPE_QLIST);
1359

    
1360
        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1361

    
1362
        str = qobject_to_json(obj);
1363
        qobject_decref(obj);
1364

    
1365
        obj = qobject_from_json(qstring_get_str(str));
1366
        g_assert(obj != NULL);
1367
        g_assert(qobject_type(obj) == QTYPE_QLIST);
1368

    
1369
        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1370

    
1371
        qobject_decref(obj);
1372
        QDECREF(str);
1373
    }
1374
}
1375

    
1376
static void simple_varargs(void)
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]");
1390
    g_assert(embedded_obj != NULL);
1391

    
1392
    obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1393
    g_assert(obj != NULL);
1394

    
1395
    g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1396

    
1397
    qobject_decref(obj);
1398
}
1399

    
1400
static void empty_input(void)
1401
{
1402
    const char *empty = "";
1403

    
1404
    QObject *obj = qobject_from_json(empty);
1405
    g_assert(obj == NULL);
1406
}
1407

    
1408
static void unterminated_string(void)
1409
{
1410
    QObject *obj = qobject_from_json("\"abc");
1411
    g_assert(obj == NULL);
1412
}
1413

    
1414
static void unterminated_sq_string(void)
1415
{
1416
    QObject *obj = qobject_from_json("'abc");
1417
    g_assert(obj == NULL);
1418
}
1419

    
1420
static void unterminated_escape(void)
1421
{
1422
    QObject *obj = qobject_from_json("\"abc\\\"");
1423
    g_assert(obj == NULL);
1424
}
1425

    
1426
static void unterminated_array(void)
1427
{
1428
    QObject *obj = qobject_from_json("[32");
1429
    g_assert(obj == NULL);
1430
}
1431

    
1432
static void unterminated_array_comma(void)
1433
{
1434
    QObject *obj = qobject_from_json("[32,");
1435
    g_assert(obj == NULL);
1436
}
1437

    
1438
static void invalid_array_comma(void)
1439
{
1440
    QObject *obj = qobject_from_json("[32,}");
1441
    g_assert(obj == NULL);
1442
}
1443

    
1444
static void unterminated_dict(void)
1445
{
1446
    QObject *obj = qobject_from_json("{'abc':32");
1447
    g_assert(obj == NULL);
1448
}
1449

    
1450
static void unterminated_dict_comma(void)
1451
{
1452
    QObject *obj = qobject_from_json("{'abc':32,");
1453
    g_assert(obj == NULL);
1454
}
1455

    
1456
static void invalid_dict_comma(void)
1457
{
1458
    QObject *obj = qobject_from_json("{'abc':32,}");
1459
    g_assert(obj == NULL);
1460
}
1461

    
1462
static void unterminated_literal(void)
1463
{
1464
    QObject *obj = qobject_from_json("nul");
1465
    g_assert(obj == NULL);
1466
}
1467

    
1468
int main(int argc, char **argv)
1469
{
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);
1474
    g_test_add_func("/literals/string/utf8", utf8_string);
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);
1485
    g_test_add_func("/dicts/large_dict", large_dict);
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);
1501
    g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1502
    g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1503

    
1504
    return g_test_run();
1505
}