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