qemu/tests/test-qmp-input-visitor.c
<<
>>
Prefs
   1/*
   2 * QMP Input 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-input-visitor.h"
  19#include "test-qapi-types.h"
  20#include "test-qapi-visit.h"
  21#include "qapi/qmp/types.h"
  22
  23typedef struct TestInputVisitorData {
  24    QObject *obj;
  25    QmpInputVisitor *qiv;
  26} TestInputVisitorData;
  27
  28static void visitor_input_teardown(TestInputVisitorData *data,
  29                                   const void *unused)
  30{
  31    qobject_decref(data->obj);
  32    data->obj = NULL;
  33
  34    if (data->qiv) {
  35        qmp_input_visitor_cleanup(data->qiv);
  36        data->qiv = NULL;
  37    }
  38}
  39
  40/* The various test_init functions are provided instead of a test setup
  41   function so that the JSON string used by the tests are kept in the test
  42   functions (and not in main()). */
  43static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
  44                                                 const char *json_string,
  45                                                 va_list *ap)
  46{
  47    Visitor *v;
  48
  49    visitor_input_teardown(data, NULL);
  50
  51    data->obj = qobject_from_jsonv(json_string, ap);
  52    g_assert(data->obj);
  53
  54    data->qiv = qmp_input_visitor_new(data->obj);
  55    g_assert(data->qiv);
  56
  57    v = qmp_input_get_visitor(data->qiv);
  58    g_assert(v);
  59
  60    return v;
  61}
  62
  63static GCC_FMT_ATTR(2, 3)
  64Visitor *visitor_input_test_init(TestInputVisitorData *data,
  65                                 const char *json_string, ...)
  66{
  67    Visitor *v;
  68    va_list ap;
  69
  70    va_start(ap, json_string);
  71    v = visitor_input_test_init_internal(data, json_string, &ap);
  72    va_end(ap);
  73    return v;
  74}
  75
  76/* similar to visitor_input_test_init(), but does not expect a string
  77 * literal/format json_string argument and so can be used for
  78 * programatically generated strings (and we can't pass in programatically
  79 * generated strings via %s format parameters since qobject_from_jsonv()
  80 * will wrap those in double-quotes and treat the entire object as a
  81 * string)
  82 */
  83static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
  84                                            const char *json_string)
  85{
  86    return visitor_input_test_init_internal(data, json_string, NULL);
  87}
  88
  89static void test_visitor_in_int(TestInputVisitorData *data,
  90                                const void *unused)
  91{
  92    int64_t res = 0, value = -42;
  93    Visitor *v;
  94
  95    v = visitor_input_test_init(data, "%" PRId64, value);
  96
  97    visit_type_int(v, NULL, &res, &error_abort);
  98    g_assert_cmpint(res, ==, value);
  99}
 100
 101static void test_visitor_in_int_overflow(TestInputVisitorData *data,
 102                                         const void *unused)
 103{
 104    int64_t res = 0;
 105    Error *err = NULL;
 106    Visitor *v;
 107
 108    /* this will overflow a Qint/int64, so should be deserialized into
 109     * a QFloat/double field instead, leading to an error if we pass it
 110     * to visit_type_int. confirm this.
 111     */
 112    v = visitor_input_test_init(data, "%f", DBL_MAX);
 113
 114    visit_type_int(v, NULL, &res, &err);
 115    error_free_or_abort(&err);
 116}
 117
 118static void test_visitor_in_bool(TestInputVisitorData *data,
 119                                 const void *unused)
 120{
 121    bool res = false;
 122    Visitor *v;
 123
 124    v = visitor_input_test_init(data, "true");
 125
 126    visit_type_bool(v, NULL, &res, &error_abort);
 127    g_assert_cmpint(res, ==, true);
 128}
 129
 130static void test_visitor_in_number(TestInputVisitorData *data,
 131                                   const void *unused)
 132{
 133    double res = 0, value = 3.14;
 134    Visitor *v;
 135
 136    v = visitor_input_test_init(data, "%f", value);
 137
 138    visit_type_number(v, NULL, &res, &error_abort);
 139    g_assert_cmpfloat(res, ==, value);
 140}
 141
 142static void test_visitor_in_string(TestInputVisitorData *data,
 143                                   const void *unused)
 144{
 145    char *res = NULL, *value = (char *) "Q E M U";
 146    Visitor *v;
 147
 148    v = visitor_input_test_init(data, "%s", value);
 149
 150    visit_type_str(v, NULL, &res, &error_abort);
 151    g_assert_cmpstr(res, ==, value);
 152
 153    g_free(res);
 154}
 155
 156static void test_visitor_in_enum(TestInputVisitorData *data,
 157                                 const void *unused)
 158{
 159    Visitor *v;
 160    EnumOne i;
 161
 162    for (i = 0; EnumOne_lookup[i]; i++) {
 163        EnumOne res = -1;
 164
 165        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
 166
 167        visit_type_EnumOne(v, NULL, &res, &error_abort);
 168        g_assert_cmpint(i, ==, res);
 169    }
 170}
 171
 172
 173static void test_visitor_in_struct(TestInputVisitorData *data,
 174                                   const void *unused)
 175{
 176    TestStruct *p = NULL;
 177    Visitor *v;
 178
 179    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
 180
 181    visit_type_TestStruct(v, NULL, &p, &error_abort);
 182    g_assert_cmpint(p->integer, ==, -42);
 183    g_assert(p->boolean == true);
 184    g_assert_cmpstr(p->string, ==, "foo");
 185
 186    g_free(p->string);
 187    g_free(p);
 188}
 189
 190static void test_visitor_in_struct_nested(TestInputVisitorData *data,
 191                                          const void *unused)
 192{
 193    UserDefTwo *udp = NULL;
 194    Visitor *v;
 195
 196    v = visitor_input_test_init(data, "{ 'string0': 'string0', "
 197                                "'dict1': { 'string1': 'string1', "
 198                                "'dict2': { 'userdef': { 'integer': 42, "
 199                                "'string': 'string' }, 'string': 'string2'}}}");
 200
 201    visit_type_UserDefTwo(v, NULL, &udp, &error_abort);
 202
 203    g_assert_cmpstr(udp->string0, ==, "string0");
 204    g_assert_cmpstr(udp->dict1->string1, ==, "string1");
 205    g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
 206    g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
 207    g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
 208    g_assert(udp->dict1->has_dict3 == false);
 209
 210    qapi_free_UserDefTwo(udp);
 211}
 212
 213static void test_visitor_in_list(TestInputVisitorData *data,
 214                                 const void *unused)
 215{
 216    UserDefOneList *item, *head = NULL;
 217    Visitor *v;
 218    int i;
 219
 220    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
 221
 222    visit_type_UserDefOneList(v, NULL, &head, &error_abort);
 223    g_assert(head != NULL);
 224
 225    for (i = 0, item = head; item; item = item->next, i++) {
 226        char string[12];
 227
 228        snprintf(string, sizeof(string), "string%d", i);
 229        g_assert_cmpstr(item->value->string, ==, string);
 230        g_assert_cmpint(item->value->integer, ==, 42 + i);
 231    }
 232
 233    qapi_free_UserDefOneList(head);
 234    head = NULL;
 235
 236    /* An empty list is valid */
 237    v = visitor_input_test_init(data, "[]");
 238    visit_type_UserDefOneList(v, NULL, &head, &error_abort);
 239    g_assert(!head);
 240}
 241
 242static void test_visitor_in_any(TestInputVisitorData *data,
 243                                const void *unused)
 244{
 245    QObject *res = NULL;
 246    Visitor *v;
 247    QInt *qint;
 248    QBool *qbool;
 249    QString *qstring;
 250    QDict *qdict;
 251    QObject *qobj;
 252
 253    v = visitor_input_test_init(data, "-42");
 254    visit_type_any(v, NULL, &res, &error_abort);
 255    qint = qobject_to_qint(res);
 256    g_assert(qint);
 257    g_assert_cmpint(qint_get_int(qint), ==, -42);
 258    qobject_decref(res);
 259
 260    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
 261    visit_type_any(v, NULL, &res, &error_abort);
 262    qdict = qobject_to_qdict(res);
 263    g_assert(qdict && qdict_size(qdict) == 3);
 264    qobj = qdict_get(qdict, "integer");
 265    g_assert(qobj);
 266    qint = qobject_to_qint(qobj);
 267    g_assert(qint);
 268    g_assert_cmpint(qint_get_int(qint), ==, -42);
 269    qobj = qdict_get(qdict, "boolean");
 270    g_assert(qobj);
 271    qbool = qobject_to_qbool(qobj);
 272    g_assert(qbool);
 273    g_assert(qbool_get_bool(qbool) == true);
 274    qobj = qdict_get(qdict, "string");
 275    g_assert(qobj);
 276    qstring = qobject_to_qstring(qobj);
 277    g_assert(qstring);
 278    g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
 279    qobject_decref(res);
 280}
 281
 282static void test_visitor_in_union_flat(TestInputVisitorData *data,
 283                                       const void *unused)
 284{
 285    Visitor *v;
 286    UserDefFlatUnion *tmp;
 287    UserDefUnionBase *base;
 288
 289    v = visitor_input_test_init(data,
 290                                "{ 'enum1': 'value1', "
 291                                "'integer': 41, "
 292                                "'string': 'str', "
 293                                "'boolean': true }");
 294
 295    visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
 296    g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
 297    g_assert_cmpstr(tmp->string, ==, "str");
 298    g_assert_cmpint(tmp->integer, ==, 41);
 299    g_assert_cmpint(tmp->u.value1.boolean, ==, true);
 300
 301    base = qapi_UserDefFlatUnion_base(tmp);
 302    g_assert(&base->enum1 == &tmp->enum1);
 303
 304    qapi_free_UserDefFlatUnion(tmp);
 305}
 306
 307static void test_visitor_in_alternate(TestInputVisitorData *data,
 308                                      const void *unused)
 309{
 310    Visitor *v;
 311    Error *err = NULL;
 312    UserDefAlternate *tmp;
 313    WrapAlternate *wrap;
 314
 315    v = visitor_input_test_init(data, "42");
 316    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
 317    g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
 318    g_assert_cmpint(tmp->u.i, ==, 42);
 319    qapi_free_UserDefAlternate(tmp);
 320
 321    v = visitor_input_test_init(data, "'string'");
 322    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
 323    g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
 324    g_assert_cmpstr(tmp->u.s, ==, "string");
 325    qapi_free_UserDefAlternate(tmp);
 326
 327    v = visitor_input_test_init(data, "{'integer':1, 'string':'str', "
 328                                "'enum1':'value1', 'boolean':true}");
 329    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
 330    g_assert_cmpint(tmp->type, ==, QTYPE_QDICT);
 331    g_assert_cmpint(tmp->u.udfu.integer, ==, 1);
 332    g_assert_cmpstr(tmp->u.udfu.string, ==, "str");
 333    g_assert_cmpint(tmp->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
 334    g_assert_cmpint(tmp->u.udfu.u.value1.boolean, ==, true);
 335    g_assert_cmpint(tmp->u.udfu.u.value1.has_a_b, ==, false);
 336    qapi_free_UserDefAlternate(tmp);
 337
 338    v = visitor_input_test_init(data, "false");
 339    visit_type_UserDefAlternate(v, NULL, &tmp, &err);
 340    error_free_or_abort(&err);
 341    qapi_free_UserDefAlternate(tmp);
 342
 343    v = visitor_input_test_init(data, "{ 'alt': 42 }");
 344    visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
 345    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QINT);
 346    g_assert_cmpint(wrap->alt->u.i, ==, 42);
 347    qapi_free_WrapAlternate(wrap);
 348
 349    v = visitor_input_test_init(data, "{ 'alt': 'string' }");
 350    visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
 351    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QSTRING);
 352    g_assert_cmpstr(wrap->alt->u.s, ==, "string");
 353    qapi_free_WrapAlternate(wrap);
 354
 355    v = visitor_input_test_init(data, "{ 'alt': {'integer':1, 'string':'str', "
 356                                "'enum1':'value1', 'boolean':true} }");
 357    visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
 358    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QDICT);
 359    g_assert_cmpint(wrap->alt->u.udfu.integer, ==, 1);
 360    g_assert_cmpstr(wrap->alt->u.udfu.string, ==, "str");
 361    g_assert_cmpint(wrap->alt->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
 362    g_assert_cmpint(wrap->alt->u.udfu.u.value1.boolean, ==, true);
 363    g_assert_cmpint(wrap->alt->u.udfu.u.value1.has_a_b, ==, false);
 364    qapi_free_WrapAlternate(wrap);
 365}
 366
 367static void test_visitor_in_alternate_number(TestInputVisitorData *data,
 368                                             const void *unused)
 369{
 370    Visitor *v;
 371    Error *err = NULL;
 372    AltStrBool *asb;
 373    AltStrNum *asn;
 374    AltNumStr *ans;
 375    AltStrInt *asi;
 376    AltIntNum *ain;
 377    AltNumInt *ani;
 378
 379    /* Parsing an int */
 380
 381    v = visitor_input_test_init(data, "42");
 382    visit_type_AltStrBool(v, NULL, &asb, &err);
 383    error_free_or_abort(&err);
 384    qapi_free_AltStrBool(asb);
 385
 386    v = visitor_input_test_init(data, "42");
 387    visit_type_AltStrNum(v, NULL, &asn, &error_abort);
 388    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
 389    g_assert_cmpfloat(asn->u.n, ==, 42);
 390    qapi_free_AltStrNum(asn);
 391
 392    v = visitor_input_test_init(data, "42");
 393    visit_type_AltNumStr(v, NULL, &ans, &error_abort);
 394    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
 395    g_assert_cmpfloat(ans->u.n, ==, 42);
 396    qapi_free_AltNumStr(ans);
 397
 398    v = visitor_input_test_init(data, "42");
 399    visit_type_AltStrInt(v, NULL, &asi, &error_abort);
 400    g_assert_cmpint(asi->type, ==, QTYPE_QINT);
 401    g_assert_cmpint(asi->u.i, ==, 42);
 402    qapi_free_AltStrInt(asi);
 403
 404    v = visitor_input_test_init(data, "42");
 405    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
 406    g_assert_cmpint(ain->type, ==, QTYPE_QINT);
 407    g_assert_cmpint(ain->u.i, ==, 42);
 408    qapi_free_AltIntNum(ain);
 409
 410    v = visitor_input_test_init(data, "42");
 411    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
 412    g_assert_cmpint(ani->type, ==, QTYPE_QINT);
 413    g_assert_cmpint(ani->u.i, ==, 42);
 414    qapi_free_AltNumInt(ani);
 415
 416    /* Parsing a double */
 417
 418    v = visitor_input_test_init(data, "42.5");
 419    visit_type_AltStrBool(v, NULL, &asb, &err);
 420    error_free_or_abort(&err);
 421    qapi_free_AltStrBool(asb);
 422
 423    v = visitor_input_test_init(data, "42.5");
 424    visit_type_AltStrNum(v, NULL, &asn, &error_abort);
 425    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
 426    g_assert_cmpfloat(asn->u.n, ==, 42.5);
 427    qapi_free_AltStrNum(asn);
 428
 429    v = visitor_input_test_init(data, "42.5");
 430    visit_type_AltNumStr(v, NULL, &ans, &error_abort);
 431    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
 432    g_assert_cmpfloat(ans->u.n, ==, 42.5);
 433    qapi_free_AltNumStr(ans);
 434
 435    v = visitor_input_test_init(data, "42.5");
 436    visit_type_AltStrInt(v, NULL, &asi, &err);
 437    error_free_or_abort(&err);
 438    qapi_free_AltStrInt(asi);
 439
 440    v = visitor_input_test_init(data, "42.5");
 441    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
 442    g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT);
 443    g_assert_cmpfloat(ain->u.n, ==, 42.5);
 444    qapi_free_AltIntNum(ain);
 445
 446    v = visitor_input_test_init(data, "42.5");
 447    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
 448    g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT);
 449    g_assert_cmpfloat(ani->u.n, ==, 42.5);
 450    qapi_free_AltNumInt(ani);
 451}
 452
 453static void test_native_list_integer_helper(TestInputVisitorData *data,
 454                                            const void *unused,
 455                                            UserDefNativeListUnionKind kind)
 456{
 457    UserDefNativeListUnion *cvalue = NULL;
 458    Visitor *v;
 459    GString *gstr_list = g_string_new("");
 460    GString *gstr_union = g_string_new("");
 461    int i;
 462
 463    for (i = 0; i < 32; i++) {
 464        g_string_append_printf(gstr_list, "%d", i);
 465        if (i != 31) {
 466            g_string_append(gstr_list, ", ");
 467        }
 468    }
 469    g_string_append_printf(gstr_union,  "{ 'type': '%s', 'data': [ %s ] }",
 470                           UserDefNativeListUnionKind_lookup[kind],
 471                           gstr_list->str);
 472    v = visitor_input_test_init_raw(data,  gstr_union->str);
 473
 474    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
 475    g_assert(cvalue != NULL);
 476    g_assert_cmpint(cvalue->type, ==, kind);
 477
 478    switch (kind) {
 479    case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
 480        intList *elem = NULL;
 481        for (i = 0, elem = cvalue->u.integer.data;
 482             elem; elem = elem->next, i++) {
 483            g_assert_cmpint(elem->value, ==, i);
 484        }
 485        break;
 486    }
 487    case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
 488        int8List *elem = NULL;
 489        for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) {
 490            g_assert_cmpint(elem->value, ==, i);
 491        }
 492        break;
 493    }
 494    case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
 495        int16List *elem = NULL;
 496        for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) {
 497            g_assert_cmpint(elem->value, ==, i);
 498        }
 499        break;
 500    }
 501    case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
 502        int32List *elem = NULL;
 503        for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) {
 504            g_assert_cmpint(elem->value, ==, i);
 505        }
 506        break;
 507    }
 508    case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
 509        int64List *elem = NULL;
 510        for (i = 0, elem = cvalue->u.s64.data; elem; elem = elem->next, i++) {
 511            g_assert_cmpint(elem->value, ==, i);
 512        }
 513        break;
 514    }
 515    case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
 516        uint8List *elem = NULL;
 517        for (i = 0, elem = cvalue->u.u8.data; elem; elem = elem->next, i++) {
 518            g_assert_cmpint(elem->value, ==, i);
 519        }
 520        break;
 521    }
 522    case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
 523        uint16List *elem = NULL;
 524        for (i = 0, elem = cvalue->u.u16.data; elem; elem = elem->next, i++) {
 525            g_assert_cmpint(elem->value, ==, i);
 526        }
 527        break;
 528    }
 529    case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
 530        uint32List *elem = NULL;
 531        for (i = 0, elem = cvalue->u.u32.data; elem; elem = elem->next, i++) {
 532            g_assert_cmpint(elem->value, ==, i);
 533        }
 534        break;
 535    }
 536    case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
 537        uint64List *elem = NULL;
 538        for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) {
 539            g_assert_cmpint(elem->value, ==, i);
 540        }
 541        break;
 542    }
 543    default:
 544        g_assert_not_reached();
 545    }
 546
 547    g_string_free(gstr_union, true);
 548    g_string_free(gstr_list, true);
 549    qapi_free_UserDefNativeListUnion(cvalue);
 550}
 551
 552static void test_visitor_in_native_list_int(TestInputVisitorData *data,
 553                                            const void *unused)
 554{
 555    test_native_list_integer_helper(data, unused,
 556                                    USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
 557}
 558
 559static void test_visitor_in_native_list_int8(TestInputVisitorData *data,
 560                                             const void *unused)
 561{
 562    test_native_list_integer_helper(data, unused,
 563                                    USER_DEF_NATIVE_LIST_UNION_KIND_S8);
 564}
 565
 566static void test_visitor_in_native_list_int16(TestInputVisitorData *data,
 567                                              const void *unused)
 568{
 569    test_native_list_integer_helper(data, unused,
 570                                    USER_DEF_NATIVE_LIST_UNION_KIND_S16);
 571}
 572
 573static void test_visitor_in_native_list_int32(TestInputVisitorData *data,
 574                                              const void *unused)
 575{
 576    test_native_list_integer_helper(data, unused,
 577                                    USER_DEF_NATIVE_LIST_UNION_KIND_S32);
 578}
 579
 580static void test_visitor_in_native_list_int64(TestInputVisitorData *data,
 581                                              const void *unused)
 582{
 583    test_native_list_integer_helper(data, unused,
 584                                    USER_DEF_NATIVE_LIST_UNION_KIND_S64);
 585}
 586
 587static void test_visitor_in_native_list_uint8(TestInputVisitorData *data,
 588                                             const void *unused)
 589{
 590    test_native_list_integer_helper(data, unused,
 591                                    USER_DEF_NATIVE_LIST_UNION_KIND_U8);
 592}
 593
 594static void test_visitor_in_native_list_uint16(TestInputVisitorData *data,
 595                                               const void *unused)
 596{
 597    test_native_list_integer_helper(data, unused,
 598                                    USER_DEF_NATIVE_LIST_UNION_KIND_U16);
 599}
 600
 601static void test_visitor_in_native_list_uint32(TestInputVisitorData *data,
 602                                               const void *unused)
 603{
 604    test_native_list_integer_helper(data, unused,
 605                                    USER_DEF_NATIVE_LIST_UNION_KIND_U32);
 606}
 607
 608static void test_visitor_in_native_list_uint64(TestInputVisitorData *data,
 609                                               const void *unused)
 610{
 611    test_native_list_integer_helper(data, unused,
 612                                    USER_DEF_NATIVE_LIST_UNION_KIND_U64);
 613}
 614
 615static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
 616                                            const void *unused)
 617{
 618    UserDefNativeListUnion *cvalue = NULL;
 619    boolList *elem = NULL;
 620    Visitor *v;
 621    GString *gstr_list = g_string_new("");
 622    GString *gstr_union = g_string_new("");
 623    int i;
 624
 625    for (i = 0; i < 32; i++) {
 626        g_string_append_printf(gstr_list, "%s",
 627                               (i % 3 == 0) ? "true" : "false");
 628        if (i != 31) {
 629            g_string_append(gstr_list, ", ");
 630        }
 631    }
 632    g_string_append_printf(gstr_union,  "{ 'type': 'boolean', 'data': [ %s ] }",
 633                           gstr_list->str);
 634    v = visitor_input_test_init_raw(data,  gstr_union->str);
 635
 636    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
 637    g_assert(cvalue != NULL);
 638    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
 639
 640    for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next, i++) {
 641        g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
 642    }
 643
 644    g_string_free(gstr_union, true);
 645    g_string_free(gstr_list, true);
 646    qapi_free_UserDefNativeListUnion(cvalue);
 647}
 648
 649static void test_visitor_in_native_list_string(TestInputVisitorData *data,
 650                                               const void *unused)
 651{
 652    UserDefNativeListUnion *cvalue = NULL;
 653    strList *elem = NULL;
 654    Visitor *v;
 655    GString *gstr_list = g_string_new("");
 656    GString *gstr_union = g_string_new("");
 657    int i;
 658
 659    for (i = 0; i < 32; i++) {
 660        g_string_append_printf(gstr_list, "'%d'", i);
 661        if (i != 31) {
 662            g_string_append(gstr_list, ", ");
 663        }
 664    }
 665    g_string_append_printf(gstr_union,  "{ 'type': 'string', 'data': [ %s ] }",
 666                           gstr_list->str);
 667    v = visitor_input_test_init_raw(data,  gstr_union->str);
 668
 669    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
 670    g_assert(cvalue != NULL);
 671    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
 672
 673    for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) {
 674        gchar str[8];
 675        sprintf(str, "%d", i);
 676        g_assert_cmpstr(elem->value, ==, str);
 677    }
 678
 679    g_string_free(gstr_union, true);
 680    g_string_free(gstr_list, true);
 681    qapi_free_UserDefNativeListUnion(cvalue);
 682}
 683
 684#define DOUBLE_STR_MAX 16
 685
 686static void test_visitor_in_native_list_number(TestInputVisitorData *data,
 687                                               const void *unused)
 688{
 689    UserDefNativeListUnion *cvalue = NULL;
 690    numberList *elem = NULL;
 691    Visitor *v;
 692    GString *gstr_list = g_string_new("");
 693    GString *gstr_union = g_string_new("");
 694    int i;
 695
 696    for (i = 0; i < 32; i++) {
 697        g_string_append_printf(gstr_list, "%f", (double)i / 3);
 698        if (i != 31) {
 699            g_string_append(gstr_list, ", ");
 700        }
 701    }
 702    g_string_append_printf(gstr_union,  "{ 'type': 'number', 'data': [ %s ] }",
 703                           gstr_list->str);
 704    v = visitor_input_test_init_raw(data,  gstr_union->str);
 705
 706    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
 707    g_assert(cvalue != NULL);
 708    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
 709
 710    for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next, i++) {
 711        GString *double_expected = g_string_new("");
 712        GString *double_actual = g_string_new("");
 713
 714        g_string_printf(double_expected, "%.6f", (double)i / 3);
 715        g_string_printf(double_actual, "%.6f", elem->value);
 716        g_assert_cmpstr(double_expected->str, ==, double_actual->str);
 717
 718        g_string_free(double_expected, true);
 719        g_string_free(double_actual, true);
 720    }
 721
 722    g_string_free(gstr_union, true);
 723    g_string_free(gstr_list, true);
 724    qapi_free_UserDefNativeListUnion(cvalue);
 725}
 726
 727static void input_visitor_test_add(const char *testpath,
 728                                   TestInputVisitorData *data,
 729                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
 730{
 731    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
 732               visitor_input_teardown);
 733}
 734
 735static void test_visitor_in_errors(TestInputVisitorData *data,
 736                                   const void *unused)
 737{
 738    TestStruct *p = NULL;
 739    Error *err = NULL;
 740    Visitor *v;
 741    strList *q = NULL;
 742
 743    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
 744                                "'string': -42 }");
 745
 746    visit_type_TestStruct(v, NULL, &p, &err);
 747    error_free_or_abort(&err);
 748    /* FIXME - a failed parse should not leave a partially-allocated p
 749     * for us to clean up; this could cause callers to leak memory. */
 750    g_assert(p->string == NULL);
 751
 752    g_free(p->string);
 753    g_free(p);
 754
 755    v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
 756    visit_type_strList(v, NULL, &q, &err);
 757    error_free_or_abort(&err);
 758    assert(q);
 759    qapi_free_strList(q);
 760}
 761
 762static void test_visitor_in_wrong_type(TestInputVisitorData *data,
 763                                       const void *unused)
 764{
 765    TestStruct *p = NULL;
 766    Visitor *v;
 767    strList *q = NULL;
 768    int64_t i;
 769    Error *err = NULL;
 770
 771    /* Make sure arrays and structs cannot be confused */
 772
 773    v = visitor_input_test_init(data, "[]");
 774    visit_type_TestStruct(v, NULL, &p, &err);
 775    error_free_or_abort(&err);
 776    g_assert(!p);
 777
 778    v = visitor_input_test_init(data, "{}");
 779    visit_type_strList(v, NULL, &q, &err);
 780    error_free_or_abort(&err);
 781    assert(!q);
 782
 783    /* Make sure primitives and struct cannot be confused */
 784
 785    v = visitor_input_test_init(data, "1");
 786    visit_type_TestStruct(v, NULL, &p, &err);
 787    error_free_or_abort(&err);
 788    g_assert(!p);
 789
 790    v = visitor_input_test_init(data, "{}");
 791    visit_type_int(v, NULL, &i, &err);
 792    error_free_or_abort(&err);
 793
 794    /* Make sure primitives and arrays cannot be confused */
 795
 796    v = visitor_input_test_init(data, "1");
 797    visit_type_strList(v, NULL, &q, &err);
 798    error_free_or_abort(&err);
 799    assert(!q);
 800
 801    v = visitor_input_test_init(data, "[]");
 802    visit_type_int(v, NULL, &i, &err);
 803    error_free_or_abort(&err);
 804}
 805
 806int main(int argc, char **argv)
 807{
 808    TestInputVisitorData in_visitor_data;
 809
 810    g_test_init(&argc, &argv, NULL);
 811
 812    input_visitor_test_add("/visitor/input/int",
 813                           &in_visitor_data, test_visitor_in_int);
 814    input_visitor_test_add("/visitor/input/int_overflow",
 815                           &in_visitor_data, test_visitor_in_int_overflow);
 816    input_visitor_test_add("/visitor/input/bool",
 817                           &in_visitor_data, test_visitor_in_bool);
 818    input_visitor_test_add("/visitor/input/number",
 819                           &in_visitor_data, test_visitor_in_number);
 820    input_visitor_test_add("/visitor/input/string",
 821                           &in_visitor_data, test_visitor_in_string);
 822    input_visitor_test_add("/visitor/input/enum",
 823                           &in_visitor_data, test_visitor_in_enum);
 824    input_visitor_test_add("/visitor/input/struct",
 825                           &in_visitor_data, test_visitor_in_struct);
 826    input_visitor_test_add("/visitor/input/struct-nested",
 827                           &in_visitor_data, test_visitor_in_struct_nested);
 828    input_visitor_test_add("/visitor/input/list",
 829                           &in_visitor_data, test_visitor_in_list);
 830    input_visitor_test_add("/visitor/input/any",
 831                           &in_visitor_data, test_visitor_in_any);
 832    input_visitor_test_add("/visitor/input/union-flat",
 833                           &in_visitor_data, test_visitor_in_union_flat);
 834    input_visitor_test_add("/visitor/input/alternate",
 835                           &in_visitor_data, test_visitor_in_alternate);
 836    input_visitor_test_add("/visitor/input/errors",
 837                           &in_visitor_data, test_visitor_in_errors);
 838    input_visitor_test_add("/visitor/input/wrong-type",
 839                           &in_visitor_data, test_visitor_in_wrong_type);
 840    input_visitor_test_add("/visitor/input/alternate-number",
 841                           &in_visitor_data, test_visitor_in_alternate_number);
 842    input_visitor_test_add("/visitor/input/native_list/int",
 843                           &in_visitor_data,
 844                           test_visitor_in_native_list_int);
 845    input_visitor_test_add("/visitor/input/native_list/int8",
 846                           &in_visitor_data,
 847                           test_visitor_in_native_list_int8);
 848    input_visitor_test_add("/visitor/input/native_list/int16",
 849                           &in_visitor_data,
 850                           test_visitor_in_native_list_int16);
 851    input_visitor_test_add("/visitor/input/native_list/int32",
 852                           &in_visitor_data,
 853                           test_visitor_in_native_list_int32);
 854    input_visitor_test_add("/visitor/input/native_list/int64",
 855                           &in_visitor_data,
 856                           test_visitor_in_native_list_int64);
 857    input_visitor_test_add("/visitor/input/native_list/uint8",
 858                           &in_visitor_data,
 859                           test_visitor_in_native_list_uint8);
 860    input_visitor_test_add("/visitor/input/native_list/uint16",
 861                           &in_visitor_data,
 862                           test_visitor_in_native_list_uint16);
 863    input_visitor_test_add("/visitor/input/native_list/uint32",
 864                           &in_visitor_data,
 865                           test_visitor_in_native_list_uint32);
 866    input_visitor_test_add("/visitor/input/native_list/uint64",
 867                           &in_visitor_data,
 868                           test_visitor_in_native_list_uint64);
 869    input_visitor_test_add("/visitor/input/native_list/bool",
 870                           &in_visitor_data, test_visitor_in_native_list_bool);
 871    input_visitor_test_add("/visitor/input/native_list/str",
 872                           &in_visitor_data,
 873                           test_visitor_in_native_list_string);
 874    input_visitor_test_add("/visitor/input/native_list/number",
 875                           &in_visitor_data,
 876                           test_visitor_in_native_list_number);
 877
 878    g_test_run();
 879
 880    return 0;
 881}
 882