Revision 8addacdd

b/tests/test-visitor-serialization.c
23 23
#include "qapi/qmp-output-visitor.h"
24 24
#include "qapi/string-input-visitor.h"
25 25
#include "qapi/string-output-visitor.h"
26
#include "qapi-types.h"
27
#include "qapi-visit.h"
28
#include "qapi/dealloc-visitor.h"
29

  
30
enum PrimitiveTypeKind {
31
    PTYPE_STRING = 0,
32
    PTYPE_BOOLEAN,
33
    PTYPE_NUMBER,
34
    PTYPE_INTEGER,
35
    PTYPE_U8,
36
    PTYPE_U16,
37
    PTYPE_U32,
38
    PTYPE_U64,
39
    PTYPE_S8,
40
    PTYPE_S16,
41
    PTYPE_S32,
42
    PTYPE_S64,
43
    PTYPE_EOL,
44
};
26 45

  
27 46
typedef struct PrimitiveType {
28 47
    union {
......
40 59
        int64_t s64;
41 60
        intmax_t max;
42 61
    } value;
43
    enum {
44
        PTYPE_STRING = 0,
45
        PTYPE_BOOLEAN,
46
        PTYPE_NUMBER,
47
        PTYPE_INTEGER,
48
        PTYPE_U8,
49
        PTYPE_U16,
50
        PTYPE_U32,
51
        PTYPE_U64,
52
        PTYPE_S8,
53
        PTYPE_S16,
54
        PTYPE_S32,
55
        PTYPE_S64,
56
        PTYPE_EOL,
57
    } type;
62
    enum PrimitiveTypeKind type;
58 63
    const char *description;
59 64
} PrimitiveType;
60 65

  
66
typedef struct PrimitiveList {
67
    union {
68
        strList *strings;
69
        boolList *booleans;
70
        numberList *numbers;
71
        intList *integers;
72
        int8List *s8_integers;
73
        int16List *s16_integers;
74
        int32List *s32_integers;
75
        int64List *s64_integers;
76
        uint8List *u8_integers;
77
        uint16List *u16_integers;
78
        uint32List *u32_integers;
79
        uint64List *u64_integers;
80
    } value;
81
    enum PrimitiveTypeKind type;
82
    const char *description;
83
} PrimitiveList;
84

  
61 85
/* test helpers */
62 86

  
87
typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
88

  
89
static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp)
90
{
91
    QapiDeallocVisitor *qdv = qapi_dealloc_visitor_new();
92

  
93
    visit(qapi_dealloc_get_visitor(qdv), &native_in, errp);
94

  
95
    qapi_dealloc_visitor_cleanup(qdv);
96
}
97

  
63 98
static void visit_primitive_type(Visitor *v, void **native, Error **errp)
64 99
{
65 100
    PrimitiveType *pt = *native;
......
105 140
    }
106 141
}
107 142

  
143
static void visit_primitive_list(Visitor *v, void **native, Error **errp)
144
{
145
    PrimitiveList *pl = *native;
146
    switch (pl->type) {
147
    case PTYPE_STRING:
148
        visit_type_strList(v, &pl->value.strings, NULL, errp);
149
        break;
150
    case PTYPE_BOOLEAN:
151
        visit_type_boolList(v, &pl->value.booleans, NULL, errp);
152
        break;
153
    case PTYPE_NUMBER:
154
        visit_type_numberList(v, &pl->value.numbers, NULL, errp);
155
        break;
156
    case PTYPE_INTEGER:
157
        visit_type_intList(v, &pl->value.integers, NULL, errp);
158
        break;
159
    case PTYPE_S8:
160
        visit_type_int8List(v, &pl->value.s8_integers, NULL, errp);
161
        break;
162
    case PTYPE_S16:
163
        visit_type_int16List(v, &pl->value.s16_integers, NULL, errp);
164
        break;
165
    case PTYPE_S32:
166
        visit_type_int32List(v, &pl->value.s32_integers, NULL, errp);
167
        break;
168
    case PTYPE_S64:
169
        visit_type_int64List(v, &pl->value.s64_integers, NULL, errp);
170
        break;
171
    case PTYPE_U8:
172
        visit_type_uint8List(v, &pl->value.u8_integers, NULL, errp);
173
        break;
174
    case PTYPE_U16:
175
        visit_type_uint16List(v, &pl->value.u16_integers, NULL, errp);
176
        break;
177
    case PTYPE_U32:
178
        visit_type_uint32List(v, &pl->value.u32_integers, NULL, errp);
179
        break;
180
    case PTYPE_U64:
181
        visit_type_uint64List(v, &pl->value.u64_integers, NULL, errp);
182
        break;
183
    default:
184
        g_assert(false);
185
    }
186
}
187

  
108 188
typedef struct TestStruct
109 189
{
110 190
    int64_t integer;
......
206 286

  
207 287
/* test cases */
208 288

  
209
typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
210

  
211 289
typedef enum VisitorCapabilities {
212 290
    VCAP_PRIMITIVES = 1,
213 291
    VCAP_STRUCTURES = 2,
214 292
    VCAP_LISTS = 4,
293
    VCAP_PRIMITIVE_LISTS = 8,
215 294
} VisitorCapabilities;
216 295

  
217 296
typedef struct SerializeOps {
......
270 349
    g_free(pt_copy);
271 350
}
272 351

  
352
static void test_primitive_lists(gconstpointer opaque)
353
{
354
    TestArgs *args = (TestArgs *) opaque;
355
    const SerializeOps *ops = args->ops;
356
    PrimitiveType *pt = args->test_data;
357
    PrimitiveList pl = { .value = { 0 } };
358
    PrimitiveList pl_copy = { .value = { 0 } };
359
    PrimitiveList *pl_copy_ptr = &pl_copy;
360
    Error *err = NULL;
361
    void *serialize_data;
362
    void *cur_head = NULL;
363
    int i;
364

  
365
    pl.type = pl_copy.type = pt->type;
366

  
367
    /* build up our list of primitive types */
368
    for (i = 0; i < 32; i++) {
369
        switch (pl.type) {
370
        case PTYPE_STRING: {
371
            strList *tmp = g_new0(strList, 1);
372
            tmp->value = g_strdup(pt->value.string);
373
            if (pl.value.strings == NULL) {
374
                pl.value.strings = tmp;
375
            } else {
376
                tmp->next = pl.value.strings;
377
                pl.value.strings = tmp;
378
            }
379
            break;
380
        }
381
        case PTYPE_INTEGER: {
382
            intList *tmp = g_new0(intList, 1);
383
            tmp->value = pt->value.integer;
384
            if (pl.value.integers == NULL) {
385
                pl.value.integers = tmp;
386
            } else {
387
                tmp->next = pl.value.integers;
388
                pl.value.integers = tmp;
389
            }
390
            break;
391
        }
392
        case PTYPE_S8: {
393
            int8List *tmp = g_new0(int8List, 1);
394
            tmp->value = pt->value.s8;
395
            if (pl.value.s8_integers == NULL) {
396
                pl.value.s8_integers = tmp;
397
            } else {
398
                tmp->next = pl.value.s8_integers;
399
                pl.value.s8_integers = tmp;
400
            }
401
            break;
402
        }
403
        case PTYPE_S16: {
404
            int16List *tmp = g_new0(int16List, 1);
405
            tmp->value = pt->value.s16;
406
            if (pl.value.s16_integers == NULL) {
407
                pl.value.s16_integers = tmp;
408
            } else {
409
                tmp->next = pl.value.s16_integers;
410
                pl.value.s16_integers = tmp;
411
            }
412
            break;
413
        }
414
        case PTYPE_S32: {
415
            int32List *tmp = g_new0(int32List, 1);
416
            tmp->value = pt->value.s32;
417
            if (pl.value.s32_integers == NULL) {
418
                pl.value.s32_integers = tmp;
419
            } else {
420
                tmp->next = pl.value.s32_integers;
421
                pl.value.s32_integers = tmp;
422
            }
423
            break;
424
        }
425
        case PTYPE_S64: {
426
            int64List *tmp = g_new0(int64List, 1);
427
            tmp->value = pt->value.s64;
428
            if (pl.value.s64_integers == NULL) {
429
                pl.value.s64_integers = tmp;
430
            } else {
431
                tmp->next = pl.value.s64_integers;
432
                pl.value.s64_integers = tmp;
433
            }
434
            break;
435
        }
436
        case PTYPE_U8: {
437
            uint8List *tmp = g_new0(uint8List, 1);
438
            tmp->value = pt->value.u8;
439
            if (pl.value.u8_integers == NULL) {
440
                pl.value.u8_integers = tmp;
441
            } else {
442
                tmp->next = pl.value.u8_integers;
443
                pl.value.u8_integers = tmp;
444
            }
445
            break;
446
        }
447
        case PTYPE_U16: {
448
            uint16List *tmp = g_new0(uint16List, 1);
449
            tmp->value = pt->value.u16;
450
            if (pl.value.u16_integers == NULL) {
451
                pl.value.u16_integers = tmp;
452
            } else {
453
                tmp->next = pl.value.u16_integers;
454
                pl.value.u16_integers = tmp;
455
            }
456
            break;
457
        }
458
        case PTYPE_U32: {
459
            uint32List *tmp = g_new0(uint32List, 1);
460
            tmp->value = pt->value.u32;
461
            if (pl.value.u32_integers == NULL) {
462
                pl.value.u32_integers = tmp;
463
            } else {
464
                tmp->next = pl.value.u32_integers;
465
                pl.value.u32_integers = tmp;
466
            }
467
            break;
468
        }
469
        case PTYPE_U64: {
470
            uint64List *tmp = g_new0(uint64List, 1);
471
            tmp->value = pt->value.u64;
472
            if (pl.value.u64_integers == NULL) {
473
                pl.value.u64_integers = tmp;
474
            } else {
475
                tmp->next = pl.value.u64_integers;
476
                pl.value.u64_integers = tmp;
477
            }
478
            break;
479
        }
480
        case PTYPE_NUMBER: {
481
            numberList *tmp = g_new0(numberList, 1);
482
            tmp->value = pt->value.number;
483
            if (pl.value.numbers == NULL) {
484
                pl.value.numbers = tmp;
485
            } else {
486
                tmp->next = pl.value.numbers;
487
                pl.value.numbers = tmp;
488
            }
489
            break;
490
        }
491
        case PTYPE_BOOLEAN: {
492
            boolList *tmp = g_new0(boolList, 1);
493
            tmp->value = pt->value.boolean;
494
            if (pl.value.booleans == NULL) {
495
                pl.value.booleans = tmp;
496
            } else {
497
                tmp->next = pl.value.booleans;
498
                pl.value.booleans = tmp;
499
            }
500
            break;
501
        }
502
        default:
503
            g_assert(0);
504
        }
505
    }
506

  
507
    ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, &err);
508
    ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &err);
509

  
510
    g_assert(err == NULL);
511
    i = 0;
512

  
513
    /* compare our deserialized list of primitives to the original */
514
    do {
515
        switch (pl_copy.type) {
516
        case PTYPE_STRING: {
517
            strList *ptr;
518
            if (cur_head) {
519
                ptr = cur_head;
520
                cur_head = ptr->next;
521
            } else {
522
                cur_head = ptr = pl_copy.value.strings;
523
            }
524
            g_assert_cmpstr(pt->value.string, ==, ptr->value);
525
            break;
526
        }
527
        case PTYPE_INTEGER: {
528
            intList *ptr;
529
            if (cur_head) {
530
                ptr = cur_head;
531
                cur_head = ptr->next;
532
            } else {
533
                cur_head = ptr = pl_copy.value.integers;
534
            }
535
            g_assert_cmpint(pt->value.integer, ==, ptr->value);
536
            break;
537
        }
538
        case PTYPE_S8: {
539
            int8List *ptr;
540
            if (cur_head) {
541
                ptr = cur_head;
542
                cur_head = ptr->next;
543
            } else {
544
                cur_head = ptr = pl_copy.value.s8_integers;
545
            }
546
            g_assert_cmpint(pt->value.s8, ==, ptr->value);
547
            break;
548
        }
549
        case PTYPE_S16: {
550
            int16List *ptr;
551
            if (cur_head) {
552
                ptr = cur_head;
553
                cur_head = ptr->next;
554
            } else {
555
                cur_head = ptr = pl_copy.value.s16_integers;
556
            }
557
            g_assert_cmpint(pt->value.s16, ==, ptr->value);
558
            break;
559
        }
560
        case PTYPE_S32: {
561
            int32List *ptr;
562
            if (cur_head) {
563
                ptr = cur_head;
564
                cur_head = ptr->next;
565
            } else {
566
                cur_head = ptr = pl_copy.value.s32_integers;
567
            }
568
            g_assert_cmpint(pt->value.s32, ==, ptr->value);
569
            break;
570
        }
571
        case PTYPE_S64: {
572
            int64List *ptr;
573
            if (cur_head) {
574
                ptr = cur_head;
575
                cur_head = ptr->next;
576
            } else {
577
                cur_head = ptr = pl_copy.value.s64_integers;
578
            }
579
            g_assert_cmpint(pt->value.s64, ==, ptr->value);
580
            break;
581
        }
582
        case PTYPE_U8: {
583
            uint8List *ptr;
584
            if (cur_head) {
585
                ptr = cur_head;
586
                cur_head = ptr->next;
587
            } else {
588
                cur_head = ptr = pl_copy.value.u8_integers;
589
            }
590
            g_assert_cmpint(pt->value.u8, ==, ptr->value);
591
            break;
592
        }
593
        case PTYPE_U16: {
594
            uint16List *ptr;
595
            if (cur_head) {
596
                ptr = cur_head;
597
                cur_head = ptr->next;
598
            } else {
599
                cur_head = ptr = pl_copy.value.u16_integers;
600
            }
601
            g_assert_cmpint(pt->value.u16, ==, ptr->value);
602
            break;
603
        }
604
        case PTYPE_U32: {
605
            uint32List *ptr;
606
            if (cur_head) {
607
                ptr = cur_head;
608
                cur_head = ptr->next;
609
            } else {
610
                cur_head = ptr = pl_copy.value.u32_integers;
611
            }
612
            g_assert_cmpint(pt->value.u32, ==, ptr->value);
613
            break;
614
        }
615
        case PTYPE_U64: {
616
            uint64List *ptr;
617
            if (cur_head) {
618
                ptr = cur_head;
619
                cur_head = ptr->next;
620
            } else {
621
                cur_head = ptr = pl_copy.value.u64_integers;
622
            }
623
            g_assert_cmpint(pt->value.u64, ==, ptr->value);
624
            break;
625
        }
626
        case PTYPE_NUMBER: {
627
            numberList *ptr;
628
            GString *double_expected = g_string_new("");
629
            GString *double_actual = g_string_new("");
630
            if (cur_head) {
631
                ptr = cur_head;
632
                cur_head = ptr->next;
633
            } else {
634
                cur_head = ptr = pl_copy.value.numbers;
635
            }
636
            /* we serialize with %f for our reference visitors, so rather than
637
             * fuzzy floating math to test "equality", just compare the
638
             * formatted values
639
             */
640
            g_string_printf(double_expected, "%.6f", pt->value.number);
641
            g_string_printf(double_actual, "%.6f", ptr->value);
642
            g_assert_cmpstr(double_actual->str, ==, double_expected->str);
643
            g_string_free(double_expected, true);
644
            g_string_free(double_actual, true);
645
            break;
646
        }
647
        case PTYPE_BOOLEAN: {
648
            boolList *ptr;
649
            if (cur_head) {
650
                ptr = cur_head;
651
                cur_head = ptr->next;
652
            } else {
653
                cur_head = ptr = pl_copy.value.booleans;
654
            }
655
            g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value);
656
            break;
657
        }
658
        default:
659
            g_assert(0);
660
        }
661
        i++;
662
    } while (cur_head);
663

  
664
    g_assert_cmpint(i, ==, 33);
665

  
666
    ops->cleanup(serialize_data);
667
    dealloc_helper(&pl, visit_primitive_list, &err);
668
    g_assert(!err);
669
    dealloc_helper(&pl_copy, visit_primitive_list, &err);
670
    g_assert(!err);
671
    g_free(args);
672
}
673

  
273 674
static void test_struct(gconstpointer opaque)
274 675
{
275 676
    TestArgs *args = (TestArgs *) opaque;
......
719 1120
        .serialize = qmp_serialize,
720 1121
        .deserialize = qmp_deserialize,
721 1122
        .cleanup = qmp_cleanup,
722
        .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS
1123
        .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS |
1124
                VCAP_PRIMITIVE_LISTS
723 1125
    },
724 1126
    {
725 1127
        .type = "String",
......
773 1175
        args->test_data = NULL;
774 1176
        g_test_add_data_func(testname, args, test_nested_struct_list);
775 1177
    }
1178

  
1179
    if (ops->caps & VCAP_PRIMITIVE_LISTS) {
1180
        i = 0;
1181
        while (pt_values[i].type != PTYPE_EOL) {
1182
            sprintf(testname, "%s/primitive_list/%s", testname_prefix,
1183
                    pt_values[i].description);
1184
            args = g_malloc0(sizeof(*args));
1185
            args->ops = ops;
1186
            args->test_data = &pt_values[i];
1187
            g_test_add_data_func(testname, args, test_primitive_lists);
1188
            i++;
1189
        }
1190
    }
776 1191
}
777 1192

  
778 1193
int main(int argc, char **argv)

Also available in: Unified diff