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