qemu/tests/test-qmp-output-visitor.c
<<
>>
Prefs
   1/*
   2 * QMP Output Visitor unit-tests.
   3 *
   4 * Copyright (C) 2011 Red Hat Inc.
   5 *
   6 * Authors:
   7 *  Luiz Capitulino <lcapitulino@redhat.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10 * See the COPYING file in the top-level directory.
  11 */
  12
  13#include <glib.h>
  14
  15#include "qemu-common.h"
  16#include "qapi/qmp-output-visitor.h"
  17#include "test-qapi-types.h"
  18#include "test-qapi-visit.h"
  19#include "qapi/qmp/types.h"
  20
  21typedef struct TestOutputVisitorData {
  22    QmpOutputVisitor *qov;
  23    Visitor *ov;
  24} TestOutputVisitorData;
  25
  26static void visitor_output_setup(TestOutputVisitorData *data,
  27                                 const void *unused)
  28{
  29    data->qov = qmp_output_visitor_new();
  30    g_assert(data->qov != NULL);
  31
  32    data->ov = qmp_output_get_visitor(data->qov);
  33    g_assert(data->ov != NULL);
  34}
  35
  36static void visitor_output_teardown(TestOutputVisitorData *data,
  37                                    const void *unused)
  38{
  39    qmp_output_visitor_cleanup(data->qov);
  40    data->qov = NULL;
  41    data->ov = NULL;
  42}
  43
  44static void test_visitor_out_int(TestOutputVisitorData *data,
  45                                 const void *unused)
  46{
  47    int64_t value = -42;
  48    Error *errp = NULL;
  49    QObject *obj;
  50
  51    visit_type_int(data->ov, &value, NULL, &errp);
  52    g_assert(error_is_set(&errp) == 0);
  53
  54    obj = qmp_output_get_qobject(data->qov);
  55    g_assert(obj != NULL);
  56    g_assert(qobject_type(obj) == QTYPE_QINT);
  57    g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
  58
  59    qobject_decref(obj);
  60}
  61
  62static void test_visitor_out_bool(TestOutputVisitorData *data,
  63                                  const void *unused)
  64{
  65    Error *errp = NULL;
  66    bool value = true;
  67    QObject *obj;
  68
  69    visit_type_bool(data->ov, &value, NULL, &errp);
  70    g_assert(error_is_set(&errp) == 0);
  71
  72    obj = qmp_output_get_qobject(data->qov);
  73    g_assert(obj != NULL);
  74    g_assert(qobject_type(obj) == QTYPE_QBOOL);
  75    g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
  76
  77    qobject_decref(obj);
  78}
  79
  80static void test_visitor_out_number(TestOutputVisitorData *data,
  81                                    const void *unused)
  82{
  83    double value = 3.14;
  84    Error *errp = NULL;
  85    QObject *obj;
  86
  87    visit_type_number(data->ov, &value, NULL, &errp);
  88    g_assert(error_is_set(&errp) == 0);
  89
  90    obj = qmp_output_get_qobject(data->qov);
  91    g_assert(obj != NULL);
  92    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
  93    g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
  94
  95    qobject_decref(obj);
  96}
  97
  98static void test_visitor_out_string(TestOutputVisitorData *data,
  99                                    const void *unused)
 100{
 101    char *string = (char *) "Q E M U";
 102    Error *errp = NULL;
 103    QObject *obj;
 104
 105    visit_type_str(data->ov, &string, NULL, &errp);
 106    g_assert(error_is_set(&errp) == 0);
 107
 108    obj = qmp_output_get_qobject(data->qov);
 109    g_assert(obj != NULL);
 110    g_assert(qobject_type(obj) == QTYPE_QSTRING);
 111    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
 112
 113    qobject_decref(obj);
 114}
 115
 116static void test_visitor_out_no_string(TestOutputVisitorData *data,
 117                                       const void *unused)
 118{
 119    char *string = NULL;
 120    Error *errp = NULL;
 121    QObject *obj;
 122
 123    /* A null string should return "" */
 124    visit_type_str(data->ov, &string, NULL, &errp);
 125    g_assert(error_is_set(&errp) == 0);
 126
 127    obj = qmp_output_get_qobject(data->qov);
 128    g_assert(obj != NULL);
 129    g_assert(qobject_type(obj) == QTYPE_QSTRING);
 130    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
 131
 132    qobject_decref(obj);
 133}
 134
 135static void test_visitor_out_enum(TestOutputVisitorData *data,
 136                                  const void *unused)
 137{
 138    Error *errp = NULL;
 139    QObject *obj;
 140    EnumOne i;
 141
 142    for (i = 0; i < ENUM_ONE_MAX; i++) {
 143        visit_type_EnumOne(data->ov, &i, "unused", &errp);
 144        g_assert(!error_is_set(&errp));
 145
 146        obj = qmp_output_get_qobject(data->qov);
 147        g_assert(obj != NULL);
 148        g_assert(qobject_type(obj) == QTYPE_QSTRING);
 149        g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
 150                        EnumOne_lookup[i]);
 151        qobject_decref(obj);
 152    }
 153}
 154
 155static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
 156                                         const void *unused)
 157{
 158    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
 159    Error *errp;
 160
 161    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
 162        errp = NULL;
 163        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
 164        g_assert(error_is_set(&errp) == true);
 165        error_free(errp);
 166    }
 167}
 168
 169typedef struct TestStruct
 170{
 171    int64_t integer;
 172    bool boolean;
 173    char *string;
 174} TestStruct;
 175
 176static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
 177                                  const char *name, Error **errp)
 178{
 179    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
 180                       errp);
 181
 182    visit_type_int(v, &(*obj)->integer, "integer", errp);
 183    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
 184    visit_type_str(v, &(*obj)->string, "string", errp);
 185
 186    visit_end_struct(v, errp);
 187}
 188
 189static void test_visitor_out_struct(TestOutputVisitorData *data,
 190                                    const void *unused)
 191{
 192    TestStruct test_struct = { .integer = 42,
 193                               .boolean = false,
 194                               .string = (char *) "foo"};
 195    TestStruct *p = &test_struct;
 196    Error *errp = NULL;
 197    QObject *obj;
 198    QDict *qdict;
 199
 200    visit_type_TestStruct(data->ov, &p, NULL, &errp);
 201    g_assert(!error_is_set(&errp));
 202
 203    obj = qmp_output_get_qobject(data->qov);
 204    g_assert(obj != NULL);
 205    g_assert(qobject_type(obj) == QTYPE_QDICT);
 206
 207    qdict = qobject_to_qdict(obj);
 208    g_assert_cmpint(qdict_size(qdict), ==, 3);
 209    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
 210    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
 211    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
 212
 213    QDECREF(qdict);
 214}
 215
 216static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
 217                                           const void *unused)
 218{
 219    int64_t value = 42;
 220    Error *errp = NULL;
 221    UserDefNested *ud2;
 222    QObject *obj;
 223    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
 224    const char *string = "user def string";
 225    const char *strings[] = { "forty two", "forty three", "forty four",
 226                              "forty five" };
 227
 228    ud2 = g_malloc0(sizeof(*ud2));
 229    ud2->string0 = g_strdup(strings[0]);
 230
 231    ud2->dict1.string1 = g_strdup(strings[1]);
 232    ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
 233    ud2->dict1.dict2.userdef1->string = g_strdup(string);
 234    ud2->dict1.dict2.userdef1->integer = value;
 235    ud2->dict1.dict2.string2 = g_strdup(strings[2]);
 236
 237    ud2->dict1.has_dict3 = true;
 238    ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
 239    ud2->dict1.dict3.userdef2->string = g_strdup(string);
 240    ud2->dict1.dict3.userdef2->integer = value;
 241    ud2->dict1.dict3.string3 = g_strdup(strings[3]);
 242
 243    visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
 244    g_assert(!error_is_set(&errp));
 245
 246    obj = qmp_output_get_qobject(data->qov);
 247    g_assert(obj != NULL);
 248    g_assert(qobject_type(obj) == QTYPE_QDICT);
 249
 250    qdict = qobject_to_qdict(obj);
 251    g_assert_cmpint(qdict_size(qdict), ==, 2);
 252    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
 253
 254    dict1 = qdict_get_qdict(qdict, "dict1");
 255    g_assert_cmpint(qdict_size(dict1), ==, 3);
 256    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
 257
 258    dict2 = qdict_get_qdict(dict1, "dict2");
 259    g_assert_cmpint(qdict_size(dict2), ==, 2);
 260    g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
 261    userdef = qdict_get_qdict(dict2, "userdef1");
 262    g_assert_cmpint(qdict_size(userdef), ==, 2);
 263    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
 264    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
 265
 266    dict3 = qdict_get_qdict(dict1, "dict3");
 267    g_assert_cmpint(qdict_size(dict3), ==, 2);
 268    g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
 269    userdef = qdict_get_qdict(dict3, "userdef2");
 270    g_assert_cmpint(qdict_size(userdef), ==, 2);
 271    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
 272    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
 273
 274    QDECREF(qdict);
 275    qapi_free_UserDefNested(ud2);
 276}
 277
 278static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
 279                                           const void *unused)
 280{
 281    EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
 282    UserDefOne u = { 0 }, *pu = &u;
 283    Error *errp;
 284    int i;
 285
 286    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
 287        errp = NULL;
 288        u.has_enum1 = true;
 289        u.enum1 = bad_values[i];
 290        visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
 291        g_assert(error_is_set(&errp) == true);
 292        error_free(errp);
 293    }
 294}
 295
 296typedef struct TestStructList
 297{
 298    union {
 299        TestStruct *value;
 300        uint64_t padding;
 301    };
 302    struct TestStructList *next;
 303} TestStructList;
 304
 305static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
 306                                      const char *name, Error **errp)
 307{
 308    GenericList *i, **head = (GenericList **)obj;
 309
 310    visit_start_list(v, name, errp);
 311
 312    for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
 313        TestStructList *native_i = (TestStructList *)i;
 314        visit_type_TestStruct(v, &native_i->value, NULL, errp);
 315    }
 316
 317    visit_end_list(v, errp);
 318}
 319
 320static void test_visitor_out_list(TestOutputVisitorData *data,
 321                                  const void *unused)
 322{
 323    char *value_str = (char *) "list value";
 324    TestStructList *p, *head = NULL;
 325    const int max_items = 10;
 326    bool value_bool = true;
 327    int value_int = 10;
 328    Error *errp = NULL;
 329    QListEntry *entry;
 330    QObject *obj;
 331    QList *qlist;
 332    int i;
 333
 334    for (i = 0; i < max_items; i++) {
 335        p = g_malloc0(sizeof(*p));
 336        p->value = g_malloc0(sizeof(*p->value));
 337        p->value->integer = value_int;
 338        p->value->boolean = value_bool;
 339        p->value->string = value_str;
 340
 341        p->next = head;
 342        head = p;
 343    }
 344
 345    visit_type_TestStructList(data->ov, &head, NULL, &errp);
 346    g_assert(!error_is_set(&errp));
 347
 348    obj = qmp_output_get_qobject(data->qov);
 349    g_assert(obj != NULL);
 350    g_assert(qobject_type(obj) == QTYPE_QLIST);
 351
 352    qlist = qobject_to_qlist(obj);
 353    g_assert(!qlist_empty(qlist));
 354
 355    i = 0;
 356    QLIST_FOREACH_ENTRY(qlist, entry) {
 357        QDict *qdict;
 358
 359        g_assert(qobject_type(entry->value) == QTYPE_QDICT);
 360        qdict = qobject_to_qdict(entry->value);
 361        g_assert_cmpint(qdict_size(qdict), ==, 3);
 362        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
 363        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
 364        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
 365        i++;
 366    }
 367    g_assert_cmpint(i, ==, max_items);
 368
 369    QDECREF(qlist);
 370
 371    for (p = head; p;) {
 372        TestStructList *tmp = p->next;
 373        g_free(p->value);
 374        g_free(p);
 375        p = tmp;
 376    }
 377}
 378
 379static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
 380                                            const void *unused)
 381{
 382    UserDefNestedList *p, *head = NULL;
 383    const char string[] = "foo bar";
 384    int i, max_count = 1024;
 385
 386    for (i = 0; i < max_count; i++) {
 387        p = g_malloc0(sizeof(*p));
 388        p->value = g_malloc0(sizeof(*p->value));
 389
 390        p->value->string0 = g_strdup(string);
 391        p->value->dict1.string1 = g_strdup(string);
 392        p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
 393        p->value->dict1.dict2.userdef1->string = g_strdup(string);
 394        p->value->dict1.dict2.userdef1->integer = 42;
 395        p->value->dict1.dict2.string2 = g_strdup(string);
 396        p->value->dict1.has_dict3 = false;
 397
 398        p->next = head;
 399        head = p;
 400    }
 401
 402    qapi_free_UserDefNestedList(head);
 403}
 404
 405static void test_visitor_out_union(TestOutputVisitorData *data,
 406                                   const void *unused)
 407{
 408    QObject *arg, *qvalue;
 409    QDict *qdict, *value;
 410
 411    Error *err = NULL;
 412
 413    UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion));
 414    tmp->kind = USER_DEF_UNION_KIND_A;
 415    tmp->a = g_malloc0(sizeof(UserDefA));
 416    tmp->a->boolean = true;
 417
 418    visit_type_UserDefUnion(data->ov, &tmp, NULL, &err);
 419    g_assert(err == NULL);
 420    arg = qmp_output_get_qobject(data->qov);
 421
 422    g_assert(qobject_type(arg) == QTYPE_QDICT);
 423    qdict = qobject_to_qdict(arg);
 424
 425    g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a");
 426
 427    qvalue = qdict_get(qdict, "data");
 428    g_assert(data != NULL);
 429    g_assert(qobject_type(qvalue) == QTYPE_QDICT);
 430    value = qobject_to_qdict(qvalue);
 431    g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true);
 432
 433    qapi_free_UserDefUnion(tmp);
 434    QDECREF(qdict);
 435}
 436
 437static void init_native_list(UserDefNativeListUnion *cvalue)
 438{
 439    int i;
 440    switch (cvalue->kind) {
 441    case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
 442        intList **list = &cvalue->integer;
 443        for (i = 0; i < 32; i++) {
 444            *list = g_new0(intList, 1);
 445            (*list)->value = i;
 446            (*list)->next = NULL;
 447            list = &(*list)->next;
 448        }
 449        break;
 450    }
 451    case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
 452        int8List **list = &cvalue->s8;
 453        for (i = 0; i < 32; i++) {
 454            *list = g_new0(int8List, 1);
 455            (*list)->value = i;
 456            (*list)->next = NULL;
 457            list = &(*list)->next;
 458        }
 459        break;
 460    }
 461    case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
 462        int16List **list = &cvalue->s16;
 463        for (i = 0; i < 32; i++) {
 464            *list = g_new0(int16List, 1);
 465            (*list)->value = i;
 466            (*list)->next = NULL;
 467            list = &(*list)->next;
 468        }
 469        break;
 470    }
 471    case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
 472        int32List **list = &cvalue->s32;
 473        for (i = 0; i < 32; i++) {
 474            *list = g_new0(int32List, 1);
 475            (*list)->value = i;
 476            (*list)->next = NULL;
 477            list = &(*list)->next;
 478        }
 479        break;
 480    }
 481    case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
 482        int64List **list = &cvalue->s64;
 483        for (i = 0; i < 32; i++) {
 484            *list = g_new0(int64List, 1);
 485            (*list)->value = i;
 486            (*list)->next = NULL;
 487            list = &(*list)->next;
 488        }
 489        break;
 490    }
 491    case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
 492        uint8List **list = &cvalue->u8;
 493        for (i = 0; i < 32; i++) {
 494            *list = g_new0(uint8List, 1);
 495            (*list)->value = i;
 496            (*list)->next = NULL;
 497            list = &(*list)->next;
 498        }
 499        break;
 500    }
 501    case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
 502        uint16List **list = &cvalue->u16;
 503        for (i = 0; i < 32; i++) {
 504            *list = g_new0(uint16List, 1);
 505            (*list)->value = i;
 506            (*list)->next = NULL;
 507            list = &(*list)->next;
 508        }
 509        break;
 510    }
 511    case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
 512        uint32List **list = &cvalue->u32;
 513        for (i = 0; i < 32; i++) {
 514            *list = g_new0(uint32List, 1);
 515            (*list)->value = i;
 516            (*list)->next = NULL;
 517            list = &(*list)->next;
 518        }
 519        break;
 520    }
 521    case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
 522        uint64List **list = &cvalue->u64;
 523        for (i = 0; i < 32; i++) {
 524            *list = g_new0(uint64List, 1);
 525            (*list)->value = i;
 526            (*list)->next = NULL;
 527            list = &(*list)->next;
 528        }
 529        break;
 530    }
 531    case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN: {
 532        boolList **list = &cvalue->boolean;
 533        for (i = 0; i < 32; i++) {
 534            *list = g_new0(boolList, 1);
 535            (*list)->value = (i % 3 == 0);
 536            (*list)->next = NULL;
 537            list = &(*list)->next;
 538        }
 539        break;
 540    }
 541    case USER_DEF_NATIVE_LIST_UNION_KIND_STRING: {
 542        strList **list = &cvalue->string;
 543        for (i = 0; i < 32; i++) {
 544            *list = g_new0(strList, 1);
 545            (*list)->value = g_strdup_printf("%d", i);
 546            (*list)->next = NULL;
 547            list = &(*list)->next;
 548        }
 549        break;
 550    }
 551    case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER: {
 552        numberList **list = &cvalue->number;
 553        for (i = 0; i < 32; i++) {
 554            *list = g_new0(numberList, 1);
 555            (*list)->value = (double)i / 3;
 556            (*list)->next = NULL;
 557            list = &(*list)->next;
 558        }
 559        break;
 560    }
 561    default:
 562        g_assert_not_reached();
 563    }
 564}
 565
 566static void check_native_list(QObject *qobj,
 567                              UserDefNativeListUnionKind kind)
 568{
 569    QDict *qdict;
 570    QList *qlist;
 571    int i;
 572
 573    g_assert(qobj);
 574    g_assert(qobject_type(qobj) == QTYPE_QDICT);
 575    qdict = qobject_to_qdict(qobj);
 576    g_assert(qdict);
 577    g_assert(qdict_haskey(qdict, "data"));
 578    qlist = qlist_copy(qobject_to_qlist(qdict_get(qdict, "data")));
 579
 580    switch (kind) {
 581    case USER_DEF_NATIVE_LIST_UNION_KIND_S8:
 582    case USER_DEF_NATIVE_LIST_UNION_KIND_S16:
 583    case USER_DEF_NATIVE_LIST_UNION_KIND_S32:
 584    case USER_DEF_NATIVE_LIST_UNION_KIND_S64:
 585    case USER_DEF_NATIVE_LIST_UNION_KIND_U8:
 586    case USER_DEF_NATIVE_LIST_UNION_KIND_U16:
 587    case USER_DEF_NATIVE_LIST_UNION_KIND_U32:
 588    case USER_DEF_NATIVE_LIST_UNION_KIND_U64:
 589        /* all integer elements in JSON arrays get stored into QInts when
 590         * we convert to QObjects, so we can check them all in the same
 591         * fashion, so simply fall through here
 592         */
 593    case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER:
 594        for (i = 0; i < 32; i++) {
 595            QObject *tmp;
 596            QInt *qvalue;
 597            tmp = qlist_peek(qlist);
 598            g_assert(tmp);
 599            qvalue = qobject_to_qint(tmp);
 600            g_assert_cmpint(qint_get_int(qvalue), ==, i);
 601            qobject_decref(qlist_pop(qlist));
 602        }
 603        break;
 604    case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN:
 605        for (i = 0; i < 32; i++) {
 606            QObject *tmp;
 607            QBool *qvalue;
 608            tmp = qlist_peek(qlist);
 609            g_assert(tmp);
 610            qvalue = qobject_to_qbool(tmp);
 611            g_assert_cmpint(qbool_get_int(qvalue), ==, (i % 3 == 0) ? 1 : 0);
 612            qobject_decref(qlist_pop(qlist));
 613        }
 614        break;
 615    case USER_DEF_NATIVE_LIST_UNION_KIND_STRING:
 616        for (i = 0; i < 32; i++) {
 617            QObject *tmp;
 618            QString *qvalue;
 619            gchar str[8];
 620            tmp = qlist_peek(qlist);
 621            g_assert(tmp);
 622            qvalue = qobject_to_qstring(tmp);
 623            sprintf(str, "%d", i);
 624            g_assert_cmpstr(qstring_get_str(qvalue), ==, str);
 625            qobject_decref(qlist_pop(qlist));
 626        }
 627        break;
 628    case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER:
 629        for (i = 0; i < 32; i++) {
 630            QObject *tmp;
 631            QFloat *qvalue;
 632            GString *double_expected = g_string_new("");
 633            GString *double_actual = g_string_new("");
 634
 635            tmp = qlist_peek(qlist);
 636            g_assert(tmp);
 637            qvalue = qobject_to_qfloat(tmp);
 638            g_string_printf(double_expected, "%.6f", (double)i / 3);
 639            g_string_printf(double_actual, "%.6f", qfloat_get_double(qvalue));
 640            g_assert_cmpstr(double_actual->str, ==, double_expected->str);
 641
 642            qobject_decref(qlist_pop(qlist));
 643            g_string_free(double_expected, true);
 644            g_string_free(double_actual, true);
 645        }
 646        break;
 647    default:
 648        g_assert_not_reached();
 649    }
 650    QDECREF(qlist);
 651}
 652
 653static void test_native_list(TestOutputVisitorData *data,
 654                             const void *unused,
 655                             UserDefNativeListUnionKind kind)
 656{
 657    UserDefNativeListUnion *cvalue = g_new0(UserDefNativeListUnion, 1);
 658    Error *err = NULL;
 659    QObject *obj;
 660
 661    cvalue->kind = kind;
 662    init_native_list(cvalue);
 663
 664    visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &err);
 665    g_assert(err == NULL);
 666
 667    obj = qmp_output_get_qobject(data->qov);
 668    check_native_list(obj, cvalue->kind);
 669    qapi_free_UserDefNativeListUnion(cvalue);
 670    qobject_decref(obj);
 671}
 672
 673static void test_visitor_out_native_list_int(TestOutputVisitorData *data,
 674                                             const void *unused)
 675{
 676    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
 677}
 678
 679static void test_visitor_out_native_list_int8(TestOutputVisitorData *data,
 680                                              const void *unused)
 681{
 682    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S8);
 683}
 684
 685static void test_visitor_out_native_list_int16(TestOutputVisitorData *data,
 686                                               const void *unused)
 687{
 688    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S16);
 689}
 690
 691static void test_visitor_out_native_list_int32(TestOutputVisitorData *data,
 692                                               const void *unused)
 693{
 694    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S32);
 695}
 696
 697static void test_visitor_out_native_list_int64(TestOutputVisitorData *data,
 698                                               const void *unused)
 699{
 700    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_S64);
 701}
 702
 703static void test_visitor_out_native_list_uint8(TestOutputVisitorData *data,
 704                                               const void *unused)
 705{
 706    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U8);
 707}
 708
 709static void test_visitor_out_native_list_uint16(TestOutputVisitorData *data,
 710                                                const void *unused)
 711{
 712    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U16);
 713}
 714
 715static void test_visitor_out_native_list_uint32(TestOutputVisitorData *data,
 716                                                const void *unused)
 717{
 718    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U32);
 719}
 720
 721static void test_visitor_out_native_list_uint64(TestOutputVisitorData *data,
 722                                                const void *unused)
 723{
 724    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_U64);
 725}
 726
 727static void test_visitor_out_native_list_bool(TestOutputVisitorData *data,
 728                                              const void *unused)
 729{
 730    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
 731}
 732
 733static void test_visitor_out_native_list_str(TestOutputVisitorData *data,
 734                                              const void *unused)
 735{
 736    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
 737}
 738
 739static void test_visitor_out_native_list_number(TestOutputVisitorData *data,
 740                                                const void *unused)
 741{
 742    test_native_list(data, unused, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
 743}
 744
 745static void output_visitor_test_add(const char *testpath,
 746                                    TestOutputVisitorData *data,
 747                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
 748{
 749    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
 750               test_func, visitor_output_teardown);
 751}
 752
 753int main(int argc, char **argv)
 754{
 755    TestOutputVisitorData out_visitor_data;
 756
 757    g_test_init(&argc, &argv, NULL);
 758
 759    output_visitor_test_add("/visitor/output/int",
 760                            &out_visitor_data, test_visitor_out_int);
 761    output_visitor_test_add("/visitor/output/bool",
 762                            &out_visitor_data, test_visitor_out_bool);
 763    output_visitor_test_add("/visitor/output/number",
 764                            &out_visitor_data, test_visitor_out_number);
 765    output_visitor_test_add("/visitor/output/string",
 766                            &out_visitor_data, test_visitor_out_string);
 767    output_visitor_test_add("/visitor/output/no-string",
 768                            &out_visitor_data, test_visitor_out_no_string);
 769    output_visitor_test_add("/visitor/output/enum",
 770                            &out_visitor_data, test_visitor_out_enum);
 771    output_visitor_test_add("/visitor/output/enum-errors",
 772                            &out_visitor_data, test_visitor_out_enum_errors);
 773    output_visitor_test_add("/visitor/output/struct",
 774                            &out_visitor_data, test_visitor_out_struct);
 775    output_visitor_test_add("/visitor/output/struct-nested",
 776                            &out_visitor_data, test_visitor_out_struct_nested);
 777    output_visitor_test_add("/visitor/output/struct-errors",
 778                            &out_visitor_data, test_visitor_out_struct_errors);
 779    output_visitor_test_add("/visitor/output/list",
 780                            &out_visitor_data, test_visitor_out_list);
 781    output_visitor_test_add("/visitor/output/list-qapi-free",
 782                            &out_visitor_data, test_visitor_out_list_qapi_free);
 783    output_visitor_test_add("/visitor/output/union",
 784                            &out_visitor_data, test_visitor_out_union);
 785    output_visitor_test_add("/visitor/output/native_list/int",
 786                            &out_visitor_data, test_visitor_out_native_list_int);
 787    output_visitor_test_add("/visitor/output/native_list/int8",
 788                            &out_visitor_data, test_visitor_out_native_list_int8);
 789    output_visitor_test_add("/visitor/output/native_list/int16",
 790                            &out_visitor_data, test_visitor_out_native_list_int16);
 791    output_visitor_test_add("/visitor/output/native_list/int32",
 792                            &out_visitor_data, test_visitor_out_native_list_int32);
 793    output_visitor_test_add("/visitor/output/native_list/int64",
 794                            &out_visitor_data, test_visitor_out_native_list_int64);
 795    output_visitor_test_add("/visitor/output/native_list/uint8",
 796                            &out_visitor_data, test_visitor_out_native_list_uint8);
 797    output_visitor_test_add("/visitor/output/native_list/uint16",
 798                            &out_visitor_data, test_visitor_out_native_list_uint16);
 799    output_visitor_test_add("/visitor/output/native_list/uint32",
 800                            &out_visitor_data, test_visitor_out_native_list_uint32);
 801    output_visitor_test_add("/visitor/output/native_list/uint64",
 802                            &out_visitor_data, test_visitor_out_native_list_uint64);
 803    output_visitor_test_add("/visitor/output/native_list/bool",
 804                            &out_visitor_data, test_visitor_out_native_list_bool);
 805    output_visitor_test_add("/visitor/output/native_list/string",
 806                            &out_visitor_data, test_visitor_out_native_list_str);
 807    output_visitor_test_add("/visitor/output/native_list/number",
 808                            &out_visitor_data, test_visitor_out_native_list_number);
 809
 810    g_test_run();
 811
 812    return 0;
 813}
 814