Statistics
| Branch: | Revision:

root / check-qjson.c @ 7a3766f3

History | View | Annotate | Download (17.5 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
#include <stdbool.h>
13

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

    
22
#include "qemu-common.h"
23

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

    
42
    for (i = 0; test_cases[i].encoded; i++) {
43
        QObject *obj;
44
        QString *str;
45

    
46
        obj = qobject_from_json(test_cases[i].encoded);
47

    
48
        fail_unless(obj != NULL);
49
        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
50
        
51
        str = qobject_to_qstring(obj);
52
        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
53

    
54
        if (test_cases[i].skip == 0) {
55
            str = qobject_to_json(obj);
56
            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
57

    
58
            qobject_decref(obj);
59
        }
60

    
61
        QDECREF(str);
62
    }
63
}
64
END_TEST
65

    
66
START_TEST(simple_string)
67
{
68
    int i;
69
    struct {
70
        const char *encoded;
71
        const char *decoded;
72
    } test_cases[] = {
73
        { "\"hello world\"", "hello world" },
74
        { "\"the quick brown fox jumped over the fence\"",
75
          "the quick brown fox jumped over the fence" },
76
        {}
77
    };
78

    
79
    for (i = 0; test_cases[i].encoded; i++) {
80
        QObject *obj;
81
        QString *str;
82

    
83
        obj = qobject_from_json(test_cases[i].encoded);
84

    
85
        fail_unless(obj != NULL);
86
        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
87
        
88
        str = qobject_to_qstring(obj);
89
        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
90

    
91
        str = qobject_to_json(obj);
92
        fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
93

    
94
        qobject_decref(obj);
95
        
96
        QDECREF(str);
97
    }
98
}
99
END_TEST
100

    
101
START_TEST(single_quote_string)
102
{
103
    int i;
104
    struct {
105
        const char *encoded;
106
        const char *decoded;
107
    } test_cases[] = {
108
        { "'hello world'", "hello world" },
109
        { "'the quick brown fox \\' jumped over the fence'",
110
          "the quick brown fox ' jumped over the fence" },
111
        {}
112
    };
113

    
114
    for (i = 0; test_cases[i].encoded; i++) {
115
        QObject *obj;
116
        QString *str;
117

    
118
        obj = qobject_from_json(test_cases[i].encoded);
119

    
120
        fail_unless(obj != NULL);
121
        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
122
        
123
        str = qobject_to_qstring(obj);
124
        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
125

    
126
        QDECREF(str);
127
    }
128
}
129
END_TEST
130

    
131
START_TEST(vararg_string)
132
{
133
    int i;
134
    struct {
135
        const char *decoded;
136
    } test_cases[] = {
137
        { "hello world" },
138
        { "the quick brown fox jumped over the fence" },
139
        {}
140
    };
141

    
142
    for (i = 0; test_cases[i].decoded; i++) {
143
        QObject *obj;
144
        QString *str;
145

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

    
148
        fail_unless(obj != NULL);
149
        fail_unless(qobject_type(obj) == QTYPE_QSTRING);
150
        
151
        str = qobject_to_qstring(obj);
152
        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
153

    
154
        QDECREF(str);
155
    }
156
}
157
END_TEST
158

    
159
START_TEST(simple_number)
160
{
161
    int i;
162
    struct {
163
        const char *encoded;
164
        int64_t decoded;
165
        int skip;
166
    } test_cases[] = {
167
        { "0", 0 },
168
        { "1234", 1234 },
169
        { "1", 1 },
170
        { "-32", -32 },
171
        { "-0", 0, .skip = 1 },
172
        { },
173
    };
174

    
175
    for (i = 0; test_cases[i].encoded; i++) {
176
        QObject *obj;
177
        QInt *qint;
178

    
179
        obj = qobject_from_json(test_cases[i].encoded);
180
        fail_unless(obj != NULL);
181
        fail_unless(qobject_type(obj) == QTYPE_QINT);
182

    
183
        qint = qobject_to_qint(obj);
184
        fail_unless(qint_get_int(qint) == test_cases[i].decoded);
185
        if (test_cases[i].skip == 0) {
186
            QString *str;
187

    
188
            str = qobject_to_json(obj);
189
            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
190
            QDECREF(str);
191
        }
192

    
193
        QDECREF(qint);
194
    }
195
}
196
END_TEST
197

    
198
START_TEST(float_number)
199
{
200
    int i;
201
    struct {
202
        const char *encoded;
203
        double decoded;
204
        int skip;
205
    } test_cases[] = {
206
        { "32.43", 32.43 },
207
        { "0.222", 0.222 },
208
        { "-32.12313", -32.12313 },
209
        { "-32.20e-10", -32.20e-10, .skip = 1 },
210
        { },
211
    };
212

    
213
    for (i = 0; test_cases[i].encoded; i++) {
214
        QObject *obj;
215
        QFloat *qfloat;
216

    
217
        obj = qobject_from_json(test_cases[i].encoded);
218
        fail_unless(obj != NULL);
219
        fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
220

    
221
        qfloat = qobject_to_qfloat(obj);
222
        fail_unless(qfloat_get_double(qfloat) == test_cases[i].decoded);
223

    
224
        if (test_cases[i].skip == 0) {
225
            QString *str;
226

    
227
            str = qobject_to_json(obj);
228
            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
229
            QDECREF(str);
230
        }
231

    
232
        QDECREF(qfloat);
233
    }
234
}
235
END_TEST
236

    
237
START_TEST(vararg_number)
238
{
239
    QObject *obj;
240
    QInt *qint;
241
    QFloat *qfloat;
242
    int value = 0x2342;
243
    int64_t value64 = 0x2342342343LL;
244
    double valuef = 2.323423423;
245

    
246
    obj = qobject_from_jsonf("%d", value);
247
    fail_unless(obj != NULL);
248
    fail_unless(qobject_type(obj) == QTYPE_QINT);
249

    
250
    qint = qobject_to_qint(obj);
251
    fail_unless(qint_get_int(qint) == value);
252

    
253
    QDECREF(qint);
254

    
255
    obj = qobject_from_jsonf("%" PRId64, value64);
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) == value64);
261

    
262
    QDECREF(qint);
263

    
264
    obj = qobject_from_jsonf("%f", valuef);
265
    fail_unless(obj != NULL);
266
    fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
267

    
268
    qfloat = qobject_to_qfloat(obj);
269
    fail_unless(qfloat_get_double(qfloat) == valuef);
270

    
271
    QDECREF(qfloat);
272
}
273
END_TEST
274

    
275
START_TEST(keyword_literal)
276
{
277
    QObject *obj;
278
    QBool *qbool;
279
    QString *str;
280

    
281
    obj = qobject_from_json("true");
282
    fail_unless(obj != NULL);
283
    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
284

    
285
    qbool = qobject_to_qbool(obj);
286
    fail_unless(qbool_get_int(qbool) != 0);
287

    
288
    str = qobject_to_json(obj);
289
    fail_unless(strcmp(qstring_get_str(str), "true") == 0);
290
    QDECREF(str);
291

    
292
    QDECREF(qbool);
293

    
294
    obj = qobject_from_json("false");
295
    fail_unless(obj != NULL);
296
    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
297

    
298
    qbool = qobject_to_qbool(obj);
299
    fail_unless(qbool_get_int(qbool) == 0);
300

    
301
    str = qobject_to_json(obj);
302
    fail_unless(strcmp(qstring_get_str(str), "false") == 0);
303
    QDECREF(str);
304

    
305
    QDECREF(qbool);
306

    
307
    obj = qobject_from_jsonf("%i", false);
308
    fail_unless(obj != NULL);
309
    fail_unless(qobject_type(obj) == QTYPE_QBOOL);
310

    
311
    qbool = qobject_to_qbool(obj);
312
    fail_unless(qbool_get_int(qbool) == 0);
313

    
314
    QDECREF(qbool);
315
    
316
    obj = qobject_from_jsonf("%i", true);
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
END_TEST
326

    
327
typedef struct LiteralQDictEntry LiteralQDictEntry;
328
typedef struct LiteralQObject LiteralQObject;
329

    
330
struct LiteralQObject
331
{
332
    int type;
333
    union {
334
        int64_t qint;
335
        const char *qstr;
336
        LiteralQDictEntry *qdict;
337
        LiteralQObject *qlist;
338
    } value;
339
};
340

    
341
struct LiteralQDictEntry
342
{
343
    const char *key;
344
    LiteralQObject value;
345
};
346

    
347
#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
348
#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
349
#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
350
#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
351

    
352
typedef struct QListCompareHelper
353
{
354
    int index;
355
    LiteralQObject *objs;
356
    int result;
357
} QListCompareHelper;
358

    
359
static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
360

    
361
static void compare_helper(QObject *obj, void *opaque)
362
{
363
    QListCompareHelper *helper = opaque;
364

    
365
    if (helper->result == 0) {
366
        return;
367
    }
368

    
369
    if (helper->objs[helper->index].type == QTYPE_NONE) {
370
        helper->result = 0;
371
        return;
372
    }
373

    
374
    helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
375
}
376

    
377
static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
378
{
379
    if (lhs->type != qobject_type(rhs)) {
380
        return 0;
381
    }
382

    
383
    switch (lhs->type) {
384
    case QTYPE_QINT:
385
        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
386
    case QTYPE_QSTRING:
387
        return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
388
    case QTYPE_QDICT: {
389
        int i;
390

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

    
394
            if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
395
                return 0;
396
            }
397
        }
398

    
399
        return 1;
400
    }
401
    case QTYPE_QLIST: {
402
        QListCompareHelper helper;
403

    
404
        helper.index = 0;
405
        helper.objs = lhs->value.qlist;
406
        helper.result = 1;
407
        
408
        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
409

    
410
        return helper.result;
411
    }
412
    default:
413
        break;
414
    }
415

    
416
    return 0;
417
}
418

    
419
START_TEST(simple_dict)
420
{
421
    int i;
422
    struct {
423
        const char *encoded;
424
        LiteralQObject decoded;
425
    } test_cases[] = {
426
        {
427
            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
428
            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
429
                        { "foo", QLIT_QINT(42) },
430
                        { "bar", QLIT_QSTR("hello world") },
431
                        { }
432
                    })),
433
        }, {
434
            .encoded = "{}",
435
            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
436
                        { }
437
                    })),
438
        }, {
439
            .encoded = "{\"foo\": 43}",
440
            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
441
                        { "foo", QLIT_QINT(43) },
442
                        { }
443
                    })),
444
        },
445
        { }
446
    };
447

    
448
    for (i = 0; test_cases[i].encoded; i++) {
449
        QObject *obj;
450
        QString *str;
451

    
452
        obj = qobject_from_json(test_cases[i].encoded);
453
        fail_unless(obj != NULL);
454
        fail_unless(qobject_type(obj) == QTYPE_QDICT);
455

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

    
458
        str = qobject_to_json(obj);
459
        qobject_decref(obj);
460

    
461
        obj = qobject_from_json(qstring_get_str(str));
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
        qobject_decref(obj);
467
        QDECREF(str);
468
    }
469
}
470
END_TEST
471

    
472
START_TEST(simple_list)
473
{
474
    int i;
475
    struct {
476
        const char *encoded;
477
        LiteralQObject decoded;
478
    } test_cases[] = {
479
        {
480
            .encoded = "[43,42]",
481
            .decoded = QLIT_QLIST(((LiteralQObject[]){
482
                        QLIT_QINT(43),
483
                        QLIT_QINT(42),
484
                        { }
485
                    })),
486
        },
487
        {
488
            .encoded = "[43]",
489
            .decoded = QLIT_QLIST(((LiteralQObject[]){
490
                        QLIT_QINT(43),
491
                        { }
492
                    })),
493
        },
494
        {
495
            .encoded = "[]",
496
            .decoded = QLIT_QLIST(((LiteralQObject[]){
497
                        { }
498
                    })),
499
        },
500
        {
501
            .encoded = "[{}]",
502
            .decoded = QLIT_QLIST(((LiteralQObject[]){
503
                        QLIT_QDICT(((LiteralQDictEntry[]){
504
                                    {},
505
                                        })),
506
                        {},
507
                            })),
508
        },
509
        { }
510
    };
511

    
512
    for (i = 0; test_cases[i].encoded; i++) {
513
        QObject *obj;
514
        QString *str;
515

    
516
        obj = qobject_from_json(test_cases[i].encoded);
517
        fail_unless(obj != NULL);
518
        fail_unless(qobject_type(obj) == QTYPE_QLIST);
519

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

    
522
        str = qobject_to_json(obj);
523
        qobject_decref(obj);
524

    
525
        obj = qobject_from_json(qstring_get_str(str));
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
        qobject_decref(obj);
531
        QDECREF(str);
532
    }
533
}
534
END_TEST
535

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

    
581
    for (i = 0; test_cases[i].encoded; i++) {
582
        QObject *obj;
583
        QString *str;
584

    
585
        obj = qobject_from_json(test_cases[i].encoded);
586
        fail_unless(obj != NULL);
587
        fail_unless(qobject_type(obj) == QTYPE_QLIST);
588

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

    
591
        str = qobject_to_json(obj);
592
        qobject_decref(obj);
593

    
594
        obj = qobject_from_json(qstring_get_str(str));
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
        qobject_decref(obj);
601
        QDECREF(str);
602
    }
603
}
604
END_TEST
605

    
606
START_TEST(simple_varargs)
607
{
608
    QObject *embedded_obj;
609
    QObject *obj;
610
    LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
611
            QLIT_QINT(1),
612
            QLIT_QINT(2),
613
            QLIT_QLIST(((LiteralQObject[]){
614
                        QLIT_QINT(32),
615
                        QLIT_QINT(42),
616
                        {}})),
617
            {}}));
618

    
619
    embedded_obj = qobject_from_json("[32, 42]");
620
    fail_unless(embedded_obj != NULL);
621

    
622
    obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
623
    fail_unless(obj != NULL);
624

    
625
    fail_unless(compare_litqobj_to_qobj(&decoded, obj) == 1);
626

    
627
    qobject_decref(obj);
628
}
629
END_TEST
630

    
631
static Suite *qjson_suite(void)
632
{
633
    Suite *suite;
634
    TCase *string_literals, *number_literals, *keyword_literals;
635
    TCase *dicts, *lists, *whitespace, *varargs;
636

    
637
    string_literals = tcase_create("String Literals");
638
    tcase_add_test(string_literals, simple_string);
639
    tcase_add_test(string_literals, escaped_string);
640
    tcase_add_test(string_literals, single_quote_string);
641
    tcase_add_test(string_literals, vararg_string);
642

    
643
    number_literals = tcase_create("Number Literals");
644
    tcase_add_test(number_literals, simple_number);
645
    tcase_add_test(number_literals, float_number);
646
    tcase_add_test(number_literals, vararg_number);
647

    
648
    keyword_literals = tcase_create("Keywords");
649
    tcase_add_test(keyword_literals, keyword_literal);
650
    dicts = tcase_create("Objects");
651
    tcase_add_test(dicts, simple_dict);
652
    lists = tcase_create("Lists");
653
    tcase_add_test(lists, simple_list);
654

    
655
    whitespace = tcase_create("Whitespace");
656
    tcase_add_test(whitespace, simple_whitespace);
657

    
658
    varargs = tcase_create("Varargs");
659
    tcase_add_test(varargs, simple_varargs);
660

    
661
    suite = suite_create("QJSON test-suite");
662
    suite_add_tcase(suite, string_literals);
663
    suite_add_tcase(suite, number_literals);
664
    suite_add_tcase(suite, keyword_literals);
665
    suite_add_tcase(suite, dicts);
666
    suite_add_tcase(suite, lists);
667
    suite_add_tcase(suite, whitespace);
668
    suite_add_tcase(suite, varargs);
669

    
670
    return suite;
671
}
672

    
673
int main(void)
674
{
675
    int nf;
676
    Suite *s;
677
    SRunner *sr;
678

    
679
    s = qjson_suite();
680
    sr = srunner_create(s);
681
        
682
    srunner_run_all(sr, CK_NORMAL);
683
    nf = srunner_ntests_failed(sr);
684
    srunner_free(sr);
685
    
686
    return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
687
}