qemu/tests/test-qobject-output-visitor.c
<<
>>
Prefs
   1/*
   2 * QObject Output Visitor unit-tests.
   3 *
   4 * Copyright (C) 2011-2016 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 "qemu/osdep.h"
  14
  15#include "qemu-common.h"
  16#include "qapi/error.h"
  17#include "qapi/qobject-output-visitor.h"
  18#include "test-qapi-visit.h"
  19#include "qapi/qmp/qbool.h"
  20#include "qapi/qmp/qdict.h"
  21#include "qapi/qmp/qlist.h"
  22#include "qapi/qmp/qnull.h"
  23#include "qapi/qmp/qnum.h"
  24#include "qapi/qmp/qstring.h"
  25
  26typedef struct TestOutputVisitorData {
  27    Visitor *ov;
  28    QObject *obj;
  29} TestOutputVisitorData;
  30
  31static void visitor_output_setup(TestOutputVisitorData *data,
  32                                 const void *unused)
  33{
  34    data->ov = qobject_output_visitor_new(&data->obj);
  35    g_assert(data->ov);
  36}
  37
  38static void visitor_output_teardown(TestOutputVisitorData *data,
  39                                    const void *unused)
  40{
  41    visit_free(data->ov);
  42    data->ov = NULL;
  43    qobject_unref(data->obj);
  44    data->obj = NULL;
  45}
  46
  47static QObject *visitor_get(TestOutputVisitorData *data)
  48{
  49    visit_complete(data->ov, &data->obj);
  50    g_assert(data->obj);
  51    return data->obj;
  52}
  53
  54static void visitor_reset(TestOutputVisitorData *data)
  55{
  56    visitor_output_teardown(data, NULL);
  57    visitor_output_setup(data, NULL);
  58}
  59
  60static void test_visitor_out_int(TestOutputVisitorData *data,
  61                                 const void *unused)
  62{
  63    int64_t value = -42;
  64    int64_t val;
  65    QNum *qnum;
  66
  67    visit_type_int(data->ov, NULL, &value, &error_abort);
  68
  69    qnum = qobject_to(QNum, visitor_get(data));
  70    g_assert(qnum);
  71    g_assert(qnum_get_try_int(qnum, &val));
  72    g_assert_cmpint(val, ==, value);
  73}
  74
  75static void test_visitor_out_bool(TestOutputVisitorData *data,
  76                                  const void *unused)
  77{
  78    bool value = true;
  79    QBool *qbool;
  80
  81    visit_type_bool(data->ov, NULL, &value, &error_abort);
  82
  83    qbool = qobject_to(QBool, visitor_get(data));
  84    g_assert(qbool);
  85    g_assert(qbool_get_bool(qbool) == value);
  86}
  87
  88static void test_visitor_out_number(TestOutputVisitorData *data,
  89                                    const void *unused)
  90{
  91    double value = 3.14;
  92    QNum *qnum;
  93
  94    visit_type_number(data->ov, NULL, &value, &error_abort);
  95
  96    qnum = qobject_to(QNum, visitor_get(data));
  97    g_assert(qnum);
  98    g_assert(qnum_get_double(qnum) == value);
  99}
 100
 101static void test_visitor_out_string(TestOutputVisitorData *data,
 102                                    const void *unused)
 103{
 104    char *string = (char *) "Q E M U";
 105    QString *qstr;
 106
 107    visit_type_str(data->ov, NULL, &string, &error_abort);
 108
 109    qstr = qobject_to(QString, visitor_get(data));
 110    g_assert(qstr);
 111    g_assert_cmpstr(qstring_get_str(qstr), ==, string);
 112}
 113
 114static void test_visitor_out_no_string(TestOutputVisitorData *data,
 115                                       const void *unused)
 116{
 117    char *string = NULL;
 118    QString *qstr;
 119
 120    /* A null string should return "" */
 121    visit_type_str(data->ov, NULL, &string, &error_abort);
 122
 123    qstr = qobject_to(QString, visitor_get(data));
 124    g_assert(qstr);
 125    g_assert_cmpstr(qstring_get_str(qstr), ==, "");
 126}
 127
 128static void test_visitor_out_enum(TestOutputVisitorData *data,
 129                                  const void *unused)
 130{
 131    EnumOne i;
 132    QString *qstr;
 133
 134    for (i = 0; i < ENUM_ONE__MAX; i++) {
 135        visit_type_EnumOne(data->ov, "unused", &i, &error_abort);
 136
 137        qstr = qobject_to(QString, visitor_get(data));
 138        g_assert(qstr);
 139        g_assert_cmpstr(qstring_get_str(qstr), ==, EnumOne_str(i));
 140        visitor_reset(data);
 141    }
 142}
 143
 144static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
 145                                         const void *unused)
 146{
 147    EnumOne i, bad_values[] = { ENUM_ONE__MAX, -1 };
 148    Error *err;
 149
 150    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
 151        err = NULL;
 152        visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err);
 153        error_free_or_abort(&err);
 154        visitor_reset(data);
 155    }
 156}
 157
 158
 159static void test_visitor_out_struct(TestOutputVisitorData *data,
 160                                    const void *unused)
 161{
 162    TestStruct test_struct = { .integer = 42,
 163                               .boolean = false,
 164                               .string = (char *) "foo"};
 165    TestStruct *p = &test_struct;
 166    QDict *qdict;
 167
 168    visit_type_TestStruct(data->ov, NULL, &p, &error_abort);
 169
 170    qdict = qobject_to(QDict, visitor_get(data));
 171    g_assert(qdict);
 172    g_assert_cmpint(qdict_size(qdict), ==, 3);
 173    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
 174    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, false);
 175    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
 176}
 177
 178static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
 179                                           const void *unused)
 180{
 181    int64_t value = 42;
 182    UserDefTwo *ud2;
 183    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
 184    const char *string = "user def string";
 185    const char *strings[] = { "forty two", "forty three", "forty four",
 186                              "forty five" };
 187
 188    ud2 = g_malloc0(sizeof(*ud2));
 189    ud2->string0 = g_strdup(strings[0]);
 190
 191    ud2->dict1 = g_malloc0(sizeof(*ud2->dict1));
 192    ud2->dict1->string1 = g_strdup(strings[1]);
 193
 194    ud2->dict1->dict2 = g_malloc0(sizeof(*ud2->dict1->dict2));
 195    ud2->dict1->dict2->userdef = g_new0(UserDefOne, 1);
 196    ud2->dict1->dict2->userdef->string = g_strdup(string);
 197    ud2->dict1->dict2->userdef->integer = value;
 198    ud2->dict1->dict2->string = g_strdup(strings[2]);
 199
 200    ud2->dict1->dict3 = g_malloc0(sizeof(*ud2->dict1->dict3));
 201    ud2->dict1->has_dict3 = true;
 202    ud2->dict1->dict3->userdef = g_new0(UserDefOne, 1);
 203    ud2->dict1->dict3->userdef->string = g_strdup(string);
 204    ud2->dict1->dict3->userdef->integer = value;
 205    ud2->dict1->dict3->string = g_strdup(strings[3]);
 206
 207    visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);
 208
 209    qdict = qobject_to(QDict, visitor_get(data));
 210    g_assert(qdict);
 211    g_assert_cmpint(qdict_size(qdict), ==, 2);
 212    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
 213
 214    dict1 = qdict_get_qdict(qdict, "dict1");
 215    g_assert_cmpint(qdict_size(dict1), ==, 3);
 216    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
 217
 218    dict2 = qdict_get_qdict(dict1, "dict2");
 219    g_assert_cmpint(qdict_size(dict2), ==, 2);
 220    g_assert_cmpstr(qdict_get_str(dict2, "string"), ==, strings[2]);
 221    userdef = qdict_get_qdict(dict2, "userdef");
 222    g_assert_cmpint(qdict_size(userdef), ==, 2);
 223    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
 224    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
 225
 226    dict3 = qdict_get_qdict(dict1, "dict3");
 227    g_assert_cmpint(qdict_size(dict3), ==, 2);
 228    g_assert_cmpstr(qdict_get_str(dict3, "string"), ==, strings[3]);
 229    userdef = qdict_get_qdict(dict3, "userdef");
 230    g_assert_cmpint(qdict_size(userdef), ==, 2);
 231    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
 232    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
 233
 234    qapi_free_UserDefTwo(ud2);
 235}
 236
 237static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
 238                                           const void *unused)
 239{
 240    EnumOne bad_values[] = { ENUM_ONE__MAX, -1 };
 241    UserDefOne u = {0};
 242    UserDefOne *pu = &u;
 243    Error *err;
 244    int i;
 245
 246    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
 247        err = NULL;
 248        u.has_enum1 = true;
 249        u.enum1 = bad_values[i];
 250        visit_type_UserDefOne(data->ov, "unused", &pu, &err);
 251        error_free_or_abort(&err);
 252        visitor_reset(data);
 253    }
 254}
 255
 256
 257static void test_visitor_out_list(TestOutputVisitorData *data,
 258                                  const void *unused)
 259{
 260    const char *value_str = "list value";
 261    TestStructList *p, *head = NULL;
 262    const int max_items = 10;
 263    bool value_bool = true;
 264    int value_int = 10;
 265    QListEntry *entry;
 266    QList *qlist;
 267    int i;
 268
 269    /* Build the list in reverse order... */
 270    for (i = 0; i < max_items; i++) {
 271        p = g_malloc0(sizeof(*p));
 272        p->value = g_malloc0(sizeof(*p->value));
 273        p->value->integer = value_int + (max_items - i - 1);
 274        p->value->boolean = value_bool;
 275        p->value->string = g_strdup(value_str);
 276
 277        p->next = head;
 278        head = p;
 279    }
 280
 281    visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
 282
 283    qlist = qobject_to(QList, visitor_get(data));
 284    g_assert(qlist);
 285    g_assert(!qlist_empty(qlist));
 286
 287    /* ...and ensure that the visitor sees it in order */
 288    i = 0;
 289    QLIST_FOREACH_ENTRY(qlist, entry) {
 290        QDict *qdict;
 291
 292        qdict = qobject_to(QDict, entry->value);
 293        g_assert(qdict);
 294        g_assert_cmpint(qdict_size(qdict), ==, 3);
 295        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int + i);
 296        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
 297        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
 298        i++;
 299    }
 300    g_assert_cmpint(i, ==, max_items);
 301
 302    qapi_free_TestStructList(head);
 303}
 304
 305static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
 306                                            const void *unused)
 307{
 308    UserDefTwoList *p, *head = NULL;
 309    const char string[] = "foo bar";
 310    int i, max_count = 1024;
 311
 312    for (i = 0; i < max_count; i++) {
 313        p = g_malloc0(sizeof(*p));
 314        p->value = g_malloc0(sizeof(*p->value));
 315
 316        p->value->string0 = g_strdup(string);
 317        p->value->dict1 = g_new0(UserDefTwoDict, 1);
 318        p->value->dict1->string1 = g_strdup(string);
 319        p->value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
 320        p->value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
 321        p->value->dict1->dict2->userdef->string = g_strdup(string);
 322        p->value->dict1->dict2->userdef->integer = 42;
 323        p->value->dict1->dict2->string = g_strdup(string);
 324        p->value->dict1->has_dict3 = false;
 325
 326        p->next = head;
 327        head = p;
 328    }
 329
 330    qapi_free_UserDefTwoList(head);
 331}
 332
 333static void test_visitor_out_any(TestOutputVisitorData *data,
 334                                 const void *unused)
 335{
 336    QObject *qobj;
 337    QNum *qnum;
 338    QBool *qbool;
 339    QString *qstring;
 340    QDict *qdict;
 341    int64_t val;
 342
 343    qobj = QOBJECT(qnum_from_int(-42));
 344    visit_type_any(data->ov, NULL, &qobj, &error_abort);
 345    qnum = qobject_to(QNum, visitor_get(data));
 346    g_assert(qnum);
 347    g_assert(qnum_get_try_int(qnum, &val));
 348    g_assert_cmpint(val, ==, -42);
 349    qobject_unref(qobj);
 350
 351    visitor_reset(data);
 352    qdict = qdict_new();
 353    qdict_put_int(qdict, "integer", -42);
 354    qdict_put_bool(qdict, "boolean", true);
 355    qdict_put_str(qdict, "string", "foo");
 356    qobj = QOBJECT(qdict);
 357    visit_type_any(data->ov, NULL, &qobj, &error_abort);
 358    qobject_unref(qobj);
 359    qdict = qobject_to(QDict, visitor_get(data));
 360    g_assert(qdict);
 361    qnum = qobject_to(QNum, qdict_get(qdict, "integer"));
 362    g_assert(qnum);
 363    g_assert(qnum_get_try_int(qnum, &val));
 364    g_assert_cmpint(val, ==, -42);
 365    qbool = qobject_to(QBool, qdict_get(qdict, "boolean"));
 366    g_assert(qbool);
 367    g_assert(qbool_get_bool(qbool) == true);
 368    qstring = qobject_to(QString, qdict_get(qdict, "string"));
 369    g_assert(qstring);
 370    g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
 371}
 372
 373static void test_visitor_out_union_flat(TestOutputVisitorData *data,
 374                                        const void *unused)
 375{
 376    QDict *qdict;
 377
 378    UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion));
 379    tmp->enum1 = ENUM_ONE_VALUE1;
 380    tmp->string = g_strdup("str");
 381    tmp->integer = 41;
 382    tmp->u.value1.boolean = true;
 383
 384    visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort);
 385    qdict = qobject_to(QDict, visitor_get(data));
 386    g_assert(qdict);
 387    g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
 388    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
 389    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41);
 390    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
 391
 392    qapi_free_UserDefFlatUnion(tmp);
 393}
 394
 395static void test_visitor_out_alternate(TestOutputVisitorData *data,
 396                                       const void *unused)
 397{
 398    UserDefAlternate *tmp;
 399    QNum *qnum;
 400    QString *qstr;
 401    QDict *qdict;
 402    int64_t val;
 403
 404    tmp = g_new0(UserDefAlternate, 1);
 405    tmp->type = QTYPE_QNUM;
 406    tmp->u.i = 42;
 407
 408    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 409    qnum = qobject_to(QNum, visitor_get(data));
 410    g_assert(qnum);
 411    g_assert(qnum_get_try_int(qnum, &val));
 412    g_assert_cmpint(val, ==, 42);
 413
 414    qapi_free_UserDefAlternate(tmp);
 415
 416    visitor_reset(data);
 417    tmp = g_new0(UserDefAlternate, 1);
 418    tmp->type = QTYPE_QSTRING;
 419    tmp->u.e = ENUM_ONE_VALUE1;
 420
 421    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 422    qstr = qobject_to(QString, visitor_get(data));
 423    g_assert(qstr);
 424    g_assert_cmpstr(qstring_get_str(qstr), ==, "value1");
 425
 426    qapi_free_UserDefAlternate(tmp);
 427
 428    visitor_reset(data);
 429    tmp = g_new0(UserDefAlternate, 1);
 430    tmp->type = QTYPE_QNULL;
 431    tmp->u.n = qnull();
 432
 433    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 434    g_assert_cmpint(qobject_type(visitor_get(data)), ==, QTYPE_QNULL);
 435
 436    qapi_free_UserDefAlternate(tmp);
 437
 438    visitor_reset(data);
 439    tmp = g_new0(UserDefAlternate, 1);
 440    tmp->type = QTYPE_QDICT;
 441    tmp->u.udfu.integer = 1;
 442    tmp->u.udfu.string = g_strdup("str");
 443    tmp->u.udfu.enum1 = ENUM_ONE_VALUE1;
 444    tmp->u.udfu.u.value1.boolean = true;
 445
 446    visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
 447    qdict = qobject_to(QDict, visitor_get(data));
 448    g_assert(qdict);
 449    g_assert_cmpint(qdict_size(qdict), ==, 4);
 450    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1);
 451    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
 452    g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
 453    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
 454
 455    qapi_free_UserDefAlternate(tmp);
 456}
 457
 458static void test_visitor_out_null(TestOutputVisitorData *data,
 459                                  const void *unused)
 460{
 461    QNull *null = NULL;
 462    QDict *qdict;
 463    QObject *nil;
 464
 465    visit_start_struct(data->ov, NULL, NULL, 0, &error_abort);
 466    visit_type_null(data->ov, "a", &null, &error_abort);
 467    visit_check_struct(data->ov, &error_abort);
 468    visit_end_struct(data->ov, NULL);
 469    qdict = qobject_to(QDict, visitor_get(data));
 470    g_assert(qdict);
 471    g_assert_cmpint(qdict_size(qdict), ==, 1);
 472    nil = qdict_get(qdict, "a");
 473    g_assert(nil);
 474    g_assert(qobject_type(nil) == QTYPE_QNULL);
 475}
 476
 477static void init_list_union(UserDefListUnion *cvalue)
 478{
 479    int i;
 480    switch (cvalue->type) {
 481    case USER_DEF_LIST_UNION_KIND_INTEGER: {
 482        intList **list = &cvalue->u.integer.data;
 483        for (i = 0; i < 32; i++) {
 484            *list = g_new0(intList, 1);
 485            (*list)->value = i;
 486            (*list)->next = NULL;
 487            list = &(*list)->next;
 488        }
 489        break;
 490    }
 491    case USER_DEF_LIST_UNION_KIND_S8: {
 492        int8List **list = &cvalue->u.s8.data;
 493        for (i = 0; i < 32; i++) {
 494            *list = g_new0(int8List, 1);
 495            (*list)->value = i;
 496            (*list)->next = NULL;
 497            list = &(*list)->next;
 498        }
 499        break;
 500    }
 501    case USER_DEF_LIST_UNION_KIND_S16: {
 502        int16List **list = &cvalue->u.s16.data;
 503        for (i = 0; i < 32; i++) {
 504            *list = g_new0(int16List, 1);
 505            (*list)->value = i;
 506            (*list)->next = NULL;
 507            list = &(*list)->next;
 508        }
 509        break;
 510    }
 511    case USER_DEF_LIST_UNION_KIND_S32: {
 512        int32List **list = &cvalue->u.s32.data;
 513        for (i = 0; i < 32; i++) {
 514            *list = g_new0(int32List, 1);
 515            (*list)->value = i;
 516            (*list)->next = NULL;
 517            list = &(*list)->next;
 518        }
 519        break;
 520    }
 521    case USER_DEF_LIST_UNION_KIND_S64: {
 522        int64List **list = &cvalue->u.s64.data;
 523        for (i = 0; i < 32; i++) {
 524            *list = g_new0(int64List, 1);
 525            (*list)->value = i;
 526            (*list)->next = NULL;
 527            list = &(*list)->next;
 528        }
 529        break;
 530    }
 531    case USER_DEF_LIST_UNION_KIND_U8: {
 532        uint8List **list = &cvalue->u.u8.data;
 533        for (i = 0; i < 32; i++) {
 534            *list = g_new0(uint8List, 1);
 535            (*list)->value = i;
 536            (*list)->next = NULL;
 537            list = &(*list)->next;
 538        }
 539        break;
 540    }
 541    case USER_DEF_LIST_UNION_KIND_U16: {
 542        uint16List **list = &cvalue->u.u16.data;
 543        for (i = 0; i < 32; i++) {
 544            *list = g_new0(uint16List, 1);
 545            (*list)->value = i;
 546            (*list)->next = NULL;
 547            list = &(*list)->next;
 548        }
 549        break;
 550    }
 551    case USER_DEF_LIST_UNION_KIND_U32: {
 552        uint32List **list = &cvalue->u.u32.data;
 553        for (i = 0; i < 32; i++) {
 554            *list = g_new0(uint32List, 1);
 555            (*list)->value = i;
 556            (*list)->next = NULL;
 557            list = &(*list)->next;
 558        }
 559        break;
 560    }
 561    case USER_DEF_LIST_UNION_KIND_U64: {
 562        uint64List **list = &cvalue->u.u64.data;
 563        for (i = 0; i < 32; i++) {
 564            *list = g_new0(uint64List, 1);
 565            (*list)->value = i;
 566            (*list)->next = NULL;
 567            list = &(*list)->next;
 568        }
 569        break;
 570    }
 571    case USER_DEF_LIST_UNION_KIND_BOOLEAN: {
 572        boolList **list = &cvalue->u.boolean.data;
 573        for (i = 0; i < 32; i++) {
 574            *list = g_new0(boolList, 1);
 575            (*list)->value = QEMU_IS_ALIGNED(i, 3);
 576            (*list)->next = NULL;
 577            list = &(*list)->next;
 578        }
 579        break;
 580    }
 581    case USER_DEF_LIST_UNION_KIND_STRING: {
 582        strList **list = &cvalue->u.string.data;
 583        for (i = 0; i < 32; i++) {
 584            *list = g_new0(strList, 1);
 585            (*list)->value = g_strdup_printf("%d", i);
 586            (*list)->next = NULL;
 587            list = &(*list)->next;
 588        }
 589        break;
 590    }
 591    case USER_DEF_LIST_UNION_KIND_NUMBER: {
 592        numberList **list = &cvalue->u.number.data;
 593        for (i = 0; i < 32; i++) {
 594            *list = g_new0(numberList, 1);
 595            (*list)->value = (double)i / 3;
 596            (*list)->next = NULL;
 597            list = &(*list)->next;
 598        }
 599        break;
 600    }
 601    default:
 602        g_assert_not_reached();
 603    }
 604}
 605
 606static void check_list_union(QObject *qobj,
 607                             UserDefListUnionKind kind)
 608{
 609    QDict *qdict;
 610    QList *qlist;
 611    int i;
 612
 613    qdict = qobject_to(QDict, qobj);
 614    g_assert(qdict);
 615    g_assert(qdict_haskey(qdict, "data"));
 616    qlist = qlist_copy(qobject_to(QList, qdict_get(qdict, "data")));
 617
 618    switch (kind) {
 619    case USER_DEF_LIST_UNION_KIND_U8:
 620    case USER_DEF_LIST_UNION_KIND_U16:
 621    case USER_DEF_LIST_UNION_KIND_U32:
 622    case USER_DEF_LIST_UNION_KIND_U64:
 623        for (i = 0; i < 32; i++) {
 624            QObject *tmp;
 625            QNum *qvalue;
 626            uint64_t val;
 627
 628            tmp = qlist_peek(qlist);
 629            g_assert(tmp);
 630            qvalue = qobject_to(QNum, tmp);
 631            g_assert(qnum_get_try_uint(qvalue, &val));
 632            g_assert_cmpint(val, ==, i);
 633            qobject_unref(qlist_pop(qlist));
 634        }
 635        break;
 636
 637    case USER_DEF_LIST_UNION_KIND_S8:
 638    case USER_DEF_LIST_UNION_KIND_S16:
 639    case USER_DEF_LIST_UNION_KIND_S32:
 640    case USER_DEF_LIST_UNION_KIND_S64:
 641        /*
 642         * All integer elements in JSON arrays get stored into QNums
 643         * when we convert to QObjects, so we can check them all in
 644         * the same fashion, so simply fall through here.
 645         */
 646    case USER_DEF_LIST_UNION_KIND_INTEGER:
 647        for (i = 0; i < 32; i++) {
 648            QObject *tmp;
 649            QNum *qvalue;
 650            int64_t val;
 651
 652            tmp = qlist_peek(qlist);
 653            g_assert(tmp);
 654            qvalue = qobject_to(QNum, tmp);
 655            g_assert(qnum_get_try_int(qvalue, &val));
 656            g_assert_cmpint(val, ==, i);
 657            qobject_unref(qlist_pop(qlist));
 658        }
 659        break;
 660    case USER_DEF_LIST_UNION_KIND_BOOLEAN:
 661        for (i = 0; i < 32; i++) {
 662            QObject *tmp;
 663            QBool *qvalue;
 664            tmp = qlist_peek(qlist);
 665            g_assert(tmp);
 666            qvalue = qobject_to(QBool, tmp);
 667            g_assert_cmpint(qbool_get_bool(qvalue), ==, i % 3 == 0);
 668            qobject_unref(qlist_pop(qlist));
 669        }
 670        break;
 671    case USER_DEF_LIST_UNION_KIND_STRING:
 672        for (i = 0; i < 32; i++) {
 673            QObject *tmp;
 674            QString *qvalue;
 675            gchar str[8];
 676            tmp = qlist_peek(qlist);
 677            g_assert(tmp);
 678            qvalue = qobject_to(QString, tmp);
 679            sprintf(str, "%d", i);
 680            g_assert_cmpstr(qstring_get_str(qvalue), ==, str);
 681            qobject_unref(qlist_pop(qlist));
 682        }
 683        break;
 684    case USER_DEF_LIST_UNION_KIND_NUMBER:
 685        for (i = 0; i < 32; i++) {
 686            QObject *tmp;
 687            QNum *qvalue;
 688            GString *double_expected = g_string_new("");
 689            GString *double_actual = g_string_new("");
 690
 691            tmp = qlist_peek(qlist);
 692            g_assert(tmp);
 693            qvalue = qobject_to(QNum, tmp);
 694            g_string_printf(double_expected, "%.6f", (double)i / 3);
 695            g_string_printf(double_actual, "%.6f", qnum_get_double(qvalue));
 696            g_assert_cmpstr(double_actual->str, ==, double_expected->str);
 697
 698            qobject_unref(qlist_pop(qlist));
 699            g_string_free(double_expected, true);
 700            g_string_free(double_actual, true);
 701        }
 702        break;
 703    default:
 704        g_assert_not_reached();
 705    }
 706    qobject_unref(qlist);
 707}
 708
 709static void test_list_union(TestOutputVisitorData *data,
 710                            const void *unused,
 711                            UserDefListUnionKind kind)
 712{
 713    UserDefListUnion *cvalue = g_new0(UserDefListUnion, 1);
 714    QObject *obj;
 715
 716    cvalue->type = kind;
 717    init_list_union(cvalue);
 718
 719    visit_type_UserDefListUnion(data->ov, NULL, &cvalue, &error_abort);
 720
 721    obj = visitor_get(data);
 722    check_list_union(obj, cvalue->type);
 723    qapi_free_UserDefListUnion(cvalue);
 724}
 725
 726static void test_visitor_out_list_union_int(TestOutputVisitorData *data,
 727                                            const void *unused)
 728{
 729    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_INTEGER);
 730}
 731
 732static void test_visitor_out_list_union_int8(TestOutputVisitorData *data,
 733                                             const void *unused)
 734{
 735    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_S8);
 736}
 737
 738static void test_visitor_out_list_union_int16(TestOutputVisitorData *data,
 739                                              const void *unused)
 740{
 741    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_S16);
 742}
 743
 744static void test_visitor_out_list_union_int32(TestOutputVisitorData *data,
 745                                              const void *unused)
 746{
 747    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_S32);
 748}
 749
 750static void test_visitor_out_list_union_int64(TestOutputVisitorData *data,
 751                                              const void *unused)
 752{
 753    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_S64);
 754}
 755
 756static void test_visitor_out_list_union_uint8(TestOutputVisitorData *data,
 757                                              const void *unused)
 758{
 759    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_U8);
 760}
 761
 762static void test_visitor_out_list_union_uint16(TestOutputVisitorData *data,
 763                                               const void *unused)
 764{
 765    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_U16);
 766}
 767
 768static void test_visitor_out_list_union_uint32(TestOutputVisitorData *data,
 769                                               const void *unused)
 770{
 771    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_U32);
 772}
 773
 774static void test_visitor_out_list_union_uint64(TestOutputVisitorData *data,
 775                                               const void *unused)
 776{
 777    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_U64);
 778}
 779
 780static void test_visitor_out_list_union_bool(TestOutputVisitorData *data,
 781                                             const void *unused)
 782{
 783    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_BOOLEAN);
 784}
 785
 786static void test_visitor_out_list_union_str(TestOutputVisitorData *data,
 787                                            const void *unused)
 788{
 789    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_STRING);
 790}
 791
 792static void test_visitor_out_list_union_number(TestOutputVisitorData *data,
 793                                               const void *unused)
 794{
 795    test_list_union(data, unused, USER_DEF_LIST_UNION_KIND_NUMBER);
 796}
 797
 798static void output_visitor_test_add(const char *testpath,
 799                                    TestOutputVisitorData *data,
 800                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
 801{
 802    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
 803               test_func, visitor_output_teardown);
 804}
 805
 806int main(int argc, char **argv)
 807{
 808    TestOutputVisitorData out_visitor_data;
 809
 810    g_test_init(&argc, &argv, NULL);
 811
 812    output_visitor_test_add("/visitor/output/int",
 813                            &out_visitor_data, test_visitor_out_int);
 814    output_visitor_test_add("/visitor/output/bool",
 815                            &out_visitor_data, test_visitor_out_bool);
 816    output_visitor_test_add("/visitor/output/number",
 817                            &out_visitor_data, test_visitor_out_number);
 818    output_visitor_test_add("/visitor/output/string",
 819                            &out_visitor_data, test_visitor_out_string);
 820    output_visitor_test_add("/visitor/output/no-string",
 821                            &out_visitor_data, test_visitor_out_no_string);
 822    output_visitor_test_add("/visitor/output/enum",
 823                            &out_visitor_data, test_visitor_out_enum);
 824    output_visitor_test_add("/visitor/output/enum-errors",
 825                            &out_visitor_data, test_visitor_out_enum_errors);
 826    output_visitor_test_add("/visitor/output/struct",
 827                            &out_visitor_data, test_visitor_out_struct);
 828    output_visitor_test_add("/visitor/output/struct-nested",
 829                            &out_visitor_data, test_visitor_out_struct_nested);
 830    output_visitor_test_add("/visitor/output/struct-errors",
 831                            &out_visitor_data, test_visitor_out_struct_errors);
 832    output_visitor_test_add("/visitor/output/list",
 833                            &out_visitor_data, test_visitor_out_list);
 834    output_visitor_test_add("/visitor/output/any",
 835                            &out_visitor_data, test_visitor_out_any);
 836    output_visitor_test_add("/visitor/output/list-qapi-free",
 837                            &out_visitor_data, test_visitor_out_list_qapi_free);
 838    output_visitor_test_add("/visitor/output/union-flat",
 839                            &out_visitor_data, test_visitor_out_union_flat);
 840    output_visitor_test_add("/visitor/output/alternate",
 841                            &out_visitor_data, test_visitor_out_alternate);
 842    output_visitor_test_add("/visitor/output/null",
 843                            &out_visitor_data, test_visitor_out_null);
 844    output_visitor_test_add("/visitor/output/list_union/int",
 845                            &out_visitor_data,
 846                            test_visitor_out_list_union_int);
 847    output_visitor_test_add("/visitor/output/list_union/int8",
 848                            &out_visitor_data,
 849                            test_visitor_out_list_union_int8);
 850    output_visitor_test_add("/visitor/output/list_union/int16",
 851                            &out_visitor_data,
 852                            test_visitor_out_list_union_int16);
 853    output_visitor_test_add("/visitor/output/list_union/int32",
 854                            &out_visitor_data,
 855                            test_visitor_out_list_union_int32);
 856    output_visitor_test_add("/visitor/output/list_union/int64",
 857                            &out_visitor_data,
 858                            test_visitor_out_list_union_int64);
 859    output_visitor_test_add("/visitor/output/list_union/uint8",
 860                            &out_visitor_data,
 861                            test_visitor_out_list_union_uint8);
 862    output_visitor_test_add("/visitor/output/list_union/uint16",
 863                            &out_visitor_data,
 864                            test_visitor_out_list_union_uint16);
 865    output_visitor_test_add("/visitor/output/list_union/uint32",
 866                            &out_visitor_data,
 867                            test_visitor_out_list_union_uint32);
 868    output_visitor_test_add("/visitor/output/list_union/uint64",
 869                            &out_visitor_data,
 870                            test_visitor_out_list_union_uint64);
 871    output_visitor_test_add("/visitor/output/list_union/bool",
 872                            &out_visitor_data,
 873                            test_visitor_out_list_union_bool);
 874    output_visitor_test_add("/visitor/output/list_union/string",
 875                            &out_visitor_data,
 876                            test_visitor_out_list_union_str);
 877    output_visitor_test_add("/visitor/output/list_union/number",
 878                            &out_visitor_data,
 879                            test_visitor_out_list_union_number);
 880
 881    g_test_run();
 882
 883    return 0;
 884}
 885