Statistics
| Branch: | Revision:

root / check-qjson.c @ a74cdab4

History | View | Annotate | Download (19.9 kB)

1
/*
2
 * Copyright IBM, Corp. 2009
3
 *
4
 * Authors:
5
 *  Anthony Liguori   <aliguori@us.ibm.com>
6
 *
7
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
8
 * See the COPYING.LIB file in the top-level directory.
9
 *
10
 */
11
#include <check.h>
12

    
13
#include "qstring.h"
14
#include "qint.h"
15
#include "qdict.h"
16
#include "qlist.h"
17
#include "qfloat.h"
18
#include "qbool.h"
19
#include "qjson.h"
20

    
21
#include "qemu-common.h"
22

    
23
START_TEST(escaped_string)
24
{
25
    int i;
26
    struct {
27
        const char *encoded;
28
        const char *decoded;
29
        int skip;
30
    } test_cases[] = {
31
        { "\"\\b\"", "\b" },
32
        { "\"\\f\"", "\f" },
33
        { "\"\\n\"", "\n" },
34
        { "\"\\r\"", "\r" },
35
        { "\"\\t\"", "\t" },
36
        { "\"\\/\"", "\\/" },
37
        { "\"\\\\\"", "\\" },
38
        { "\"\\\"\"", "\"" },
39
        { "\"hello world \\\"embedded string\\\"\"",
40
          "hello world \"embedded string\"" },
41
        { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
42
        { "\"single byte utf-8 \\u0020\"", "single byte utf-8  ", .skip = 1 },
43
        { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
44
        { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
45
        {}
46
    };
47

    
48
    for (i = 0; test_cases[i].encoded; i++) {
49
        QObject *obj;
50
        QString *str;
51

    
52
        obj = qobject_from_json(test_cases[i].encoded);
53

    
54
        fail_unless(obj != NULL);
55
        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
56
        
57
        str = qobject_to_qstring(obj);
58
        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0,
59
                    "%s != %s\n", qstring_get_str(str), test_cases[i].decoded);
60

    
61
        if (test_cases[i].skip == 0) {
62
            str = qobject_to_json(obj);
63
            fail_unless(strcmp(qstring_get_str(str),test_cases[i].encoded) == 0,
64
                        "%s != %s\n", qstring_get_str(str),
65
                                      test_cases[i].encoded);
66

    
67
            qobject_decref(obj);
68
        }
69

    
70
        QDECREF(str);
71
    }
72
}
73
END_TEST
74

    
75
START_TEST(simple_string)
76
{
77
    int i;
78
    struct {
79
        const char *encoded;
80
        const char *decoded;
81
    } test_cases[] = {
82
        { "\"hello world\"", "hello world" },
83
        { "\"the quick brown fox jumped over the fence\"",
84
          "the quick brown fox jumped over the fence" },
85
        {}
86
    };
87

    
88
    for (i = 0; test_cases[i].encoded; i++) {
89
        QObject *obj;
90
        QString *str;
91

    
92
        obj = qobject_from_json(test_cases[i].encoded);
93

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

    
100
        str = qobject_to_json(obj);
101
        fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
102

    
103
        qobject_decref(obj);
104
        
105
        QDECREF(str);
106
    }
107
}
108
END_TEST
109

    
110
START_TEST(single_quote_string)
111
{
112
    int i;
113
    struct {
114
        const char *encoded;
115
        const char *decoded;
116
    } test_cases[] = {
117
        { "'hello world'", "hello world" },
118
        { "'the quick brown fox \\' jumped over the fence'",
119
          "the quick brown fox ' jumped over the fence" },
120
        {}
121
    };
122

    
123
    for (i = 0; test_cases[i].encoded; i++) {
124
        QObject *obj;
125
        QString *str;
126

    
127
        obj = qobject_from_json(test_cases[i].encoded);
128

    
129
        fail_unless(obj != NULL);
130
        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
131
        
132
        str = qobject_to_qstring(obj);
133
        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
134

    
135
        QDECREF(str);
136
    }
137
}
138
END_TEST
139

    
140
START_TEST(vararg_string)
141
{
142
    int i;
143
    struct {
144
        const char *decoded;
145
    } test_cases[] = {
146
        { "hello world" },
147
        { "the quick brown fox jumped over the fence" },
148
        {}
149
    };
150

    
151
    for (i = 0; test_cases[i].decoded; i++) {
152
        QObject *obj;
153
        QString *str;
154

    
155
        obj = qobject_from_jsonf("%s", test_cases[i].decoded);
156

    
157
        fail_unless(obj != NULL);
158
        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
159
        
160
        str = qobject_to_qstring(obj);
161
        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
162

    
163
        QDECREF(str);
164
    }
165
}
166
END_TEST
167

    
168
START_TEST(simple_number)
169
{
170
    int i;
171
    struct {
172
        const char *encoded;
173
        int64_t decoded;
174
        int skip;
175
    } test_cases[] = {
176
        { "0", 0 },
177
        { "1234", 1234 },
178
        { "1", 1 },
179
        { "-32", -32 },
180
        { "-0", 0, .skip = 1 },
181
        { },
182
    };
183

    
184
    for (i = 0; test_cases[i].encoded; i++) {
185
        QObject *obj;
186
        QInt *qint;
187

    
188
        obj = qobject_from_json(test_cases[i].encoded);
189
        fail_unless(obj != NULL);
190
        fail_unless(qobject_type(obj) == QTYPE_QINT);
191

    
192
        qint = qobject_to_qint(obj);
193
        fail_unless(qint_get_int(qint) == test_cases[i].decoded);
194
        if (test_cases[i].skip == 0) {
195
            QString *str;
196

    
197
            str = qobject_to_json(obj);
198
            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
199
            QDECREF(str);
200
        }
201

    
202
        QDECREF(qint);
203
    }
204
}
205
END_TEST
206

    
207
START_TEST(float_number)
208
{
209
    int i;
210
    struct {
211
        const char *encoded;
212
        double decoded;
213
        int skip;
214
    } test_cases[] = {
215
        { "32.43", 32.43 },
216
        { "0.222", 0.222 },
217
        { "-32.12313", -32.12313 },
218
        { "-32.20e-10", -32.20e-10, .skip = 1 },
219
        { },
220
    };
221

    
222
    for (i = 0; test_cases[i].encoded; i++) {
223
        QObject *obj;
224
        QFloat *qfloat;
225

    
226
        obj = qobject_from_json(test_cases[i].encoded);
227
        fail_unless(obj != NULL);
228
        fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
229

    
230
        qfloat = qobject_to_qfloat(obj);
231
        fail_unless(qfloat_get_double(qfloat) == test_cases[i].decoded);
232

    
233
        if (test_cases[i].skip == 0) {
234
            QString *str;
235

    
236
            str = qobject_to_json(obj);
237
            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
238
            QDECREF(str);
239
        }
240

    
241
        QDECREF(qfloat);
242
    }
243
}
244
END_TEST
245

    
246
START_TEST(vararg_number)
247
{
248
    QObject *obj;
249
    QInt *qint;
250
    QFloat *qfloat;
251
    int value = 0x2342;
252
    int64_t value64 = 0x2342342343LL;
253
    double valuef = 2.323423423;
254

    
255
    obj = qobject_from_jsonf("%d", value);
256
    fail_unless(obj != NULL);
257
    fail_unless(qobject_type(obj) == QTYPE_QINT);
258

    
259
    qint = qobject_to_qint(obj);
260
    fail_unless(qint_get_int(qint) == value);
261

    
262
    QDECREF(qint);
263

    
264
    obj = qobject_from_jsonf("%" PRId64, value64);
265
    fail_unless(obj != NULL);
266
    fail_unless(qobject_type(obj) == QTYPE_QINT);
267

    
268
    qint = qobject_to_qint(obj);
269
    fail_unless(qint_get_int(qint) == value64);
270

    
271
    QDECREF(qint);
272

    
273
    obj = qobject_from_jsonf("%f", valuef);
274
    fail_unless(obj != NULL);
275
    fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
276

    
277
    qfloat = qobject_to_qfloat(obj);
278
    fail_unless(qfloat_get_double(qfloat) == valuef);
279

    
280
    QDECREF(qfloat);
281
}
282
END_TEST
283

    
284
START_TEST(keyword_literal)
285
{
286
    QObject *obj;
287
    QBool *qbool;
288
    QString *str;
289

    
290
    obj = qobject_from_json("true");
291
    fail_unless(obj != NULL);
292
    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
293

    
294
    qbool = qobject_to_qbool(obj);
295
    fail_unless(qbool_get_int(qbool) != 0);
296

    
297
    str = qobject_to_json(obj);
298
    fail_unless(strcmp(qstring_get_str(str), "true") == 0);
299
    QDECREF(str);
300

    
301
    QDECREF(qbool);
302

    
303
    obj = qobject_from_json("false");
304
    fail_unless(obj != NULL);
305
    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
306

    
307
    qbool = qobject_to_qbool(obj);
308
    fail_unless(qbool_get_int(qbool) == 0);
309

    
310
    str = qobject_to_json(obj);
311
    fail_unless(strcmp(qstring_get_str(str), "false") == 0);
312
    QDECREF(str);
313

    
314
    QDECREF(qbool);
315

    
316
    obj = qobject_from_jsonf("%i", false);
317
    fail_unless(obj != NULL);
318
    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
319

    
320
    qbool = qobject_to_qbool(obj);
321
    fail_unless(qbool_get_int(qbool) == 0);
322

    
323
    QDECREF(qbool);
324
    
325
    obj = qobject_from_jsonf("%i", true);
326
    fail_unless(obj != NULL);
327
    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
328

    
329
    qbool = qobject_to_qbool(obj);
330
    fail_unless(qbool_get_int(qbool) != 0);
331

    
332
    QDECREF(qbool);
333
}
334
END_TEST
335

    
336
typedef struct LiteralQDictEntry LiteralQDictEntry;
337
typedef struct LiteralQObject LiteralQObject;
338

    
339
struct LiteralQObject
340
{
341
    int type;
342
    union {
343
        int64_t qint;
344
        const char *qstr;
345
        LiteralQDictEntry *qdict;
346
        LiteralQObject *qlist;
347
    } value;
348
};
349

    
350
struct LiteralQDictEntry
351
{
352
    const char *key;
353
    LiteralQObject value;
354
};
355

    
356
#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
357
#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
358
#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
359
#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
360

    
361
typedef struct QListCompareHelper
362
{
363
    int index;
364
    LiteralQObject *objs;
365
    int result;
366
} QListCompareHelper;
367

    
368
static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
369

    
370
static void compare_helper(QObject *obj, void *opaque)
371
{
372
    QListCompareHelper *helper = opaque;
373

    
374
    if (helper->result == 0) {
375
        return;
376
    }
377

    
378
    if (helper->objs[helper->index].type == QTYPE_NONE) {
379
        helper->result = 0;
380
        return;
381
    }
382

    
383
    helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
384
}
385

    
386
static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
387
{
388
    if (lhs->type != qobject_type(rhs)) {
389
        return 0;
390
    }
391

    
392
    switch (lhs->type) {
393
    case QTYPE_QINT:
394
        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
395
    case QTYPE_QSTRING:
396
        return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
397
    case QTYPE_QDICT: {
398
        int i;
399

    
400
        for (i = 0; lhs->value.qdict[i].key; i++) {
401
            QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
402

    
403
            if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
404
                return 0;
405
            }
406
        }
407

    
408
        return 1;
409
    }
410
    case QTYPE_QLIST: {
411
        QListCompareHelper helper;
412

    
413
        helper.index = 0;
414
        helper.objs = lhs->value.qlist;
415
        helper.result = 1;
416
        
417
        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
418

    
419
        return helper.result;
420
    }
421
    default:
422
        break;
423
    }
424

    
425
    return 0;
426
}
427

    
428
START_TEST(simple_dict)
429
{
430
    int i;
431
    struct {
432
        const char *encoded;
433
        LiteralQObject decoded;
434
    } test_cases[] = {
435
        {
436
            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
437
            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
438
                        { "foo", QLIT_QINT(42) },
439
                        { "bar", QLIT_QSTR("hello world") },
440
                        { }
441
                    })),
442
        }, {
443
            .encoded = "{}",
444
            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
445
                        { }
446
                    })),
447
        }, {
448
            .encoded = "{\"foo\": 43}",
449
            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
450
                        { "foo", QLIT_QINT(43) },
451
                        { }
452
                    })),
453
        },
454
        { }
455
    };
456

    
457
    for (i = 0; test_cases[i].encoded; i++) {
458
        QObject *obj;
459
        QString *str;
460

    
461
        obj = qobject_from_json(test_cases[i].encoded);
462
        fail_unless(obj != NULL);
463
        fail_unless(qobject_type(obj) == QTYPE_QDICT);
464

    
465
        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
466

    
467
        str = qobject_to_json(obj);
468
        qobject_decref(obj);
469

    
470
        obj = qobject_from_json(qstring_get_str(str));
471
        fail_unless(obj != NULL);
472
        fail_unless(qobject_type(obj) == QTYPE_QDICT);
473

    
474
        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
475
        qobject_decref(obj);
476
        QDECREF(str);
477
    }
478
}
479
END_TEST
480

    
481
START_TEST(simple_list)
482
{
483
    int i;
484
    struct {
485
        const char *encoded;
486
        LiteralQObject decoded;
487
    } test_cases[] = {
488
        {
489
            .encoded = "[43,42]",
490
            .decoded = QLIT_QLIST(((LiteralQObject[]){
491
                        QLIT_QINT(43),
492
                        QLIT_QINT(42),
493
                        { }
494
                    })),
495
        },
496
        {
497
            .encoded = "[43]",
498
            .decoded = QLIT_QLIST(((LiteralQObject[]){
499
                        QLIT_QINT(43),
500
                        { }
501
                    })),
502
        },
503
        {
504
            .encoded = "[]",
505
            .decoded = QLIT_QLIST(((LiteralQObject[]){
506
                        { }
507
                    })),
508
        },
509
        {
510
            .encoded = "[{}]",
511
            .decoded = QLIT_QLIST(((LiteralQObject[]){
512
                        QLIT_QDICT(((LiteralQDictEntry[]){
513
                                    {},
514
                                        })),
515
                        {},
516
                            })),
517
        },
518
        { }
519
    };
520

    
521
    for (i = 0; test_cases[i].encoded; i++) {
522
        QObject *obj;
523
        QString *str;
524

    
525
        obj = qobject_from_json(test_cases[i].encoded);
526
        fail_unless(obj != NULL);
527
        fail_unless(qobject_type(obj) == QTYPE_QLIST);
528

    
529
        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
530

    
531
        str = qobject_to_json(obj);
532
        qobject_decref(obj);
533

    
534
        obj = qobject_from_json(qstring_get_str(str));
535
        fail_unless(obj != NULL);
536
        fail_unless(qobject_type(obj) == QTYPE_QLIST);
537

    
538
        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
539
        qobject_decref(obj);
540
        QDECREF(str);
541
    }
542
}
543
END_TEST
544

    
545
START_TEST(simple_whitespace)
546
{
547
    int i;
548
    struct {
549
        const char *encoded;
550
        LiteralQObject decoded;
551
    } test_cases[] = {
552
        {
553
            .encoded = " [ 43 , 42 ]",
554
            .decoded = QLIT_QLIST(((LiteralQObject[]){
555
                        QLIT_QINT(43),
556
                        QLIT_QINT(42),
557
                        { }
558
                    })),
559
        },
560
        {
561
            .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
562
            .decoded = QLIT_QLIST(((LiteralQObject[]){
563
                        QLIT_QINT(43),
564
                        QLIT_QDICT(((LiteralQDictEntry[]){
565
                                    { "h", QLIT_QSTR("b") },
566
                                    { }})),
567
                        QLIT_QLIST(((LiteralQObject[]){
568
                                    { }})),
569
                        QLIT_QINT(42),
570
                        { }
571
                    })),
572
        },
573
        {
574
            .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
575
            .decoded = QLIT_QLIST(((LiteralQObject[]){
576
                        QLIT_QINT(43),
577
                        QLIT_QDICT(((LiteralQDictEntry[]){
578
                                    { "h", QLIT_QSTR("b") },
579
                                    { "a", QLIT_QINT(32) },
580
                                    { }})),
581
                        QLIT_QLIST(((LiteralQObject[]){
582
                                    { }})),
583
                        QLIT_QINT(42),
584
                        { }
585
                    })),
586
        },
587
        { }
588
    };
589

    
590
    for (i = 0; test_cases[i].encoded; i++) {
591
        QObject *obj;
592
        QString *str;
593

    
594
        obj = qobject_from_json(test_cases[i].encoded);
595
        fail_unless(obj != NULL);
596
        fail_unless(qobject_type(obj) == QTYPE_QLIST);
597

    
598
        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
599

    
600
        str = qobject_to_json(obj);
601
        qobject_decref(obj);
602

    
603
        obj = qobject_from_json(qstring_get_str(str));
604
        fail_unless(obj != NULL);
605
        fail_unless(qobject_type(obj) == QTYPE_QLIST);
606

    
607
        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
608

    
609
        qobject_decref(obj);
610
        QDECREF(str);
611
    }
612
}
613
END_TEST
614

    
615
START_TEST(simple_varargs)
616
{
617
    QObject *embedded_obj;
618
    QObject *obj;
619
    LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
620
            QLIT_QINT(1),
621
            QLIT_QINT(2),
622
            QLIT_QLIST(((LiteralQObject[]){
623
                        QLIT_QINT(32),
624
                        QLIT_QINT(42),
625
                        {}})),
626
            {}}));
627

    
628
    embedded_obj = qobject_from_json("[32, 42]");
629
    fail_unless(embedded_obj != NULL);
630

    
631
    obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
632
    fail_unless(obj != NULL);
633

    
634
    fail_unless(compare_litqobj_to_qobj(&decoded, obj) == 1);
635

    
636
    qobject_decref(obj);
637
}
638
END_TEST
639

    
640
START_TEST(empty_input)
641
{
642
    const char *empty = "";
643

    
644
    QObject *obj = qobject_from_json(empty);
645
    fail_unless(obj == NULL);
646
}
647
END_TEST
648

    
649
START_TEST(unterminated_string)
650
{
651
    QObject *obj = qobject_from_json("\"abc");
652
    fail_unless(obj == NULL);
653
}
654
END_TEST
655

    
656
START_TEST(unterminated_sq_string)
657
{
658
    QObject *obj = qobject_from_json("'abc");
659
    fail_unless(obj == NULL);
660
}
661
END_TEST
662

    
663
START_TEST(unterminated_escape)
664
{
665
    QObject *obj = qobject_from_json("\"abc\\\"");
666
    fail_unless(obj == NULL);
667
}
668
END_TEST
669

    
670
START_TEST(unterminated_array)
671
{
672
    QObject *obj = qobject_from_json("[32");
673
    fail_unless(obj == NULL);
674
}
675
END_TEST
676

    
677
START_TEST(unterminated_array_comma)
678
{
679
    QObject *obj = qobject_from_json("[32,");
680
    fail_unless(obj == NULL);
681
}
682
END_TEST
683

    
684
START_TEST(invalid_array_comma)
685
{
686
    QObject *obj = qobject_from_json("[32,}");
687
    fail_unless(obj == NULL);
688
}
689
END_TEST
690

    
691
START_TEST(unterminated_dict)
692
{
693
    QObject *obj = qobject_from_json("{'abc':32");
694
    fail_unless(obj == NULL);
695
}
696
END_TEST
697

    
698
START_TEST(unterminated_dict_comma)
699
{
700
    QObject *obj = qobject_from_json("{'abc':32,");
701
    fail_unless(obj == NULL);
702
}
703
END_TEST
704

    
705
#if 0
706
START_TEST(invalid_dict_comma)
707
{
708
    QObject *obj = qobject_from_json("{'abc':32,}");
709
    fail_unless(obj == NULL);
710
}
711
END_TEST
712

713
START_TEST(unterminated_literal)
714
{
715
    QObject *obj = qobject_from_json("nul");
716
    fail_unless(obj == NULL);
717
}
718
END_TEST
719
#endif
720

    
721
static Suite *qjson_suite(void)
722
{
723
    Suite *suite;
724
    TCase *string_literals, *number_literals, *keyword_literals;
725
    TCase *dicts, *lists, *whitespace, *varargs, *errors;
726

    
727
    string_literals = tcase_create("String Literals");
728
    tcase_add_test(string_literals, simple_string);
729
    tcase_add_test(string_literals, escaped_string);
730
    tcase_add_test(string_literals, single_quote_string);
731
    tcase_add_test(string_literals, vararg_string);
732

    
733
    number_literals = tcase_create("Number Literals");
734
    tcase_add_test(number_literals, simple_number);
735
    tcase_add_test(number_literals, float_number);
736
    tcase_add_test(number_literals, vararg_number);
737

    
738
    keyword_literals = tcase_create("Keywords");
739
    tcase_add_test(keyword_literals, keyword_literal);
740
    dicts = tcase_create("Objects");
741
    tcase_add_test(dicts, simple_dict);
742
    lists = tcase_create("Lists");
743
    tcase_add_test(lists, simple_list);
744

    
745
    whitespace = tcase_create("Whitespace");
746
    tcase_add_test(whitespace, simple_whitespace);
747

    
748
    varargs = tcase_create("Varargs");
749
    tcase_add_test(varargs, simple_varargs);
750

    
751
    errors = tcase_create("Invalid JSON");
752
    tcase_add_test(errors, empty_input);
753
    tcase_add_test(errors, unterminated_string);
754
    tcase_add_test(errors, unterminated_escape);
755
    tcase_add_test(errors, unterminated_sq_string);
756
    tcase_add_test(errors, unterminated_array);
757
    tcase_add_test(errors, unterminated_array_comma);
758
    tcase_add_test(errors, invalid_array_comma);
759
    tcase_add_test(errors, unterminated_dict);
760
    tcase_add_test(errors, unterminated_dict_comma);
761
#if 0
762
    /* FIXME: this print parse error messages on stderr.  */
763
    tcase_add_test(errors, invalid_dict_comma);
764
    tcase_add_test(errors, unterminated_literal);
765
#endif
766

    
767
    suite = suite_create("QJSON test-suite");
768
    suite_add_tcase(suite, string_literals);
769
    suite_add_tcase(suite, number_literals);
770
    suite_add_tcase(suite, keyword_literals);
771
    suite_add_tcase(suite, dicts);
772
    suite_add_tcase(suite, lists);
773
    suite_add_tcase(suite, whitespace);
774
    suite_add_tcase(suite, varargs);
775
    suite_add_tcase(suite, errors);
776

    
777
    return suite;
778
}
779

    
780
int main(void)
781
{
782
    int nf;
783
    Suite *s;
784
    SRunner *sr;
785

    
786
    s = qjson_suite();
787
    sr = srunner_create(s);
788
        
789
    srunner_run_all(sr, CK_NORMAL);
790
    nf = srunner_ntests_failed(sr);
791
    srunner_free(sr);
792
    
793
    return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
794
}