test-qmp-input-visitor.c 30.5 KB
Newer Older
L
Luiz Capitulino 已提交
1 2 3
/*
 * QMP Input Visitor unit-tests.
 *
4
 * Copyright (C) 2011-2016 Red Hat Inc.
L
Luiz Capitulino 已提交
5 6 7 8 9 10 11 12
 *
 * Authors:
 *  Luiz Capitulino <lcapitulino@redhat.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */

P
Peter Maydell 已提交
13
#include "qemu/osdep.h"
L
Luiz Capitulino 已提交
14

15
#include "qemu-common.h"
16
#include "qapi/error.h"
L
Luiz Capitulino 已提交
17 18 19
#include "qapi/qmp-input-visitor.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
20
#include "qapi/qmp/types.h"
L
Luiz Capitulino 已提交
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

typedef struct TestInputVisitorData {
    QObject *obj;
    QmpInputVisitor *qiv;
} TestInputVisitorData;

static void visitor_input_teardown(TestInputVisitorData *data,
                                   const void *unused)
{
    qobject_decref(data->obj);
    data->obj = NULL;

    if (data->qiv) {
        qmp_input_visitor_cleanup(data->qiv);
        data->qiv = NULL;
    }
}

39 40 41 42 43 44 45 46 47
/* The various test_init functions are provided instead of a test setup
   function so that the JSON string used by the tests are kept in the test
   functions (and not in main()). */
static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
                                                 const char *json_string,
                                                 va_list *ap)
{
    Visitor *v;

E
Eric Blake 已提交
48 49
    visitor_input_teardown(data, NULL);

50 51 52
    data->obj = qobject_from_jsonv(json_string, ap);
    g_assert(data->obj);

53
    data->qiv = qmp_input_visitor_new(data->obj, false);
54 55 56 57 58 59 60 61
    g_assert(data->qiv);

    v = qmp_input_get_visitor(data->qiv);
    g_assert(v);

    return v;
}

62 63 64
static GCC_FMT_ATTR(2, 3)
Visitor *visitor_input_test_init(TestInputVisitorData *data,
                                 const char *json_string, ...)
L
Luiz Capitulino 已提交
65 66 67 68 69
{
    Visitor *v;
    va_list ap;

    va_start(ap, json_string);
70
    v = visitor_input_test_init_internal(data, json_string, &ap);
L
Luiz Capitulino 已提交
71 72 73 74
    va_end(ap);
    return v;
}

75 76 77 78 79 80 81 82 83 84
/* similar to visitor_input_test_init(), but does not expect a string
 * literal/format json_string argument and so can be used for
 * programatically generated strings (and we can't pass in programatically
 * generated strings via %s format parameters since qobject_from_jsonv()
 * will wrap those in double-quotes and treat the entire object as a
 * string)
 */
static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
                                            const char *json_string)
{
85
    return visitor_input_test_init_internal(data, json_string, NULL);
86 87
}

L
Luiz Capitulino 已提交
88 89 90 91 92 93
static void test_visitor_in_int(TestInputVisitorData *data,
                                const void *unused)
{
    int64_t res = 0, value = -42;
    Visitor *v;

94
    v = visitor_input_test_init(data, "%" PRId64, value);
L
Luiz Capitulino 已提交
95

96
    visit_type_int(v, NULL, &res, &error_abort);
L
Luiz Capitulino 已提交
97 98 99
    g_assert_cmpint(res, ==, value);
}

100 101 102 103
static void test_visitor_in_int_overflow(TestInputVisitorData *data,
                                         const void *unused)
{
    int64_t res = 0;
104
    Error *err = NULL;
105 106 107 108 109 110 111 112
    Visitor *v;

    /* this will overflow a Qint/int64, so should be deserialized into
     * a QFloat/double field instead, leading to an error if we pass it
     * to visit_type_int. confirm this.
     */
    v = visitor_input_test_init(data, "%f", DBL_MAX);

113
    visit_type_int(v, NULL, &res, &err);
114
    error_free_or_abort(&err);
115 116
}

L
Luiz Capitulino 已提交
117 118 119 120 121 122 123 124
static void test_visitor_in_bool(TestInputVisitorData *data,
                                 const void *unused)
{
    bool res = false;
    Visitor *v;

    v = visitor_input_test_init(data, "true");

125
    visit_type_bool(v, NULL, &res, &error_abort);
L
Luiz Capitulino 已提交
126 127 128 129 130 131 132 133 134 135 136
    g_assert_cmpint(res, ==, true);
}

static void test_visitor_in_number(TestInputVisitorData *data,
                                   const void *unused)
{
    double res = 0, value = 3.14;
    Visitor *v;

    v = visitor_input_test_init(data, "%f", value);

137
    visit_type_number(v, NULL, &res, &error_abort);
L
Luiz Capitulino 已提交
138 139 140 141 142 143 144 145 146 147 148
    g_assert_cmpfloat(res, ==, value);
}

static void test_visitor_in_string(TestInputVisitorData *data,
                                   const void *unused)
{
    char *res = NULL, *value = (char *) "Q E M U";
    Visitor *v;

    v = visitor_input_test_init(data, "%s", value);

149
    visit_type_str(v, NULL, &res, &error_abort);
L
Luiz Capitulino 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    g_assert_cmpstr(res, ==, value);

    g_free(res);
}

static void test_visitor_in_enum(TestInputVisitorData *data,
                                 const void *unused)
{
    Visitor *v;
    EnumOne i;

    for (i = 0; EnumOne_lookup[i]; i++) {
        EnumOne res = -1;

        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);

166
        visit_type_EnumOne(v, NULL, &res, &error_abort);
L
Luiz Capitulino 已提交
167 168 169 170 171 172 173 174 175 176 177 178 179
        g_assert_cmpint(i, ==, res);
    }
}


static void test_visitor_in_struct(TestInputVisitorData *data,
                                   const void *unused)
{
    TestStruct *p = NULL;
    Visitor *v;

    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");

180
    visit_type_TestStruct(v, NULL, &p, &error_abort);
L
Luiz Capitulino 已提交
181 182 183 184 185 186 187 188 189 190 191
    g_assert_cmpint(p->integer, ==, -42);
    g_assert(p->boolean == true);
    g_assert_cmpstr(p->string, ==, "foo");

    g_free(p->string);
    g_free(p);
}

static void test_visitor_in_struct_nested(TestInputVisitorData *data,
                                          const void *unused)
{
192
    UserDefTwo *udp = NULL;
L
Luiz Capitulino 已提交
193 194
    Visitor *v;

195 196 197 198
    v = visitor_input_test_init(data, "{ 'string0': 'string0', "
                                "'dict1': { 'string1': 'string1', "
                                "'dict2': { 'userdef': { 'integer': 42, "
                                "'string': 'string' }, 'string': 'string2'}}}");
L
Luiz Capitulino 已提交
199

200
    visit_type_UserDefTwo(v, NULL, &udp, &error_abort);
L
Luiz Capitulino 已提交
201

E
Eric Blake 已提交
202 203
    g_assert_cmpstr(udp->string0, ==, "string0");
    g_assert_cmpstr(udp->dict1->string1, ==, "string1");
E
Eric Blake 已提交
204
    g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
E
Eric Blake 已提交
205 206
    g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
    g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
207 208
    g_assert(udp->dict1->has_dict3 == false);

E
Eric Blake 已提交
209
    qapi_free_UserDefTwo(udp);
L
Luiz Capitulino 已提交
210 211 212 213 214 215 216 217 218 219 220
}

static void test_visitor_in_list(TestInputVisitorData *data,
                                 const void *unused)
{
    UserDefOneList *item, *head = NULL;
    Visitor *v;
    int i;

    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");

221
    visit_type_UserDefOneList(v, NULL, &head, &error_abort);
L
Luiz Capitulino 已提交
222 223 224 225 226 227 228
    g_assert(head != NULL);

    for (i = 0, item = head; item; item = item->next, i++) {
        char string[12];

        snprintf(string, sizeof(string), "string%d", i);
        g_assert_cmpstr(item->value->string, ==, string);
E
Eric Blake 已提交
229
        g_assert_cmpint(item->value->integer, ==, 42 + i);
L
Luiz Capitulino 已提交
230 231 232
    }

    qapi_free_UserDefOneList(head);
E
Eric Blake 已提交
233 234 235 236
    head = NULL;

    /* An empty list is valid */
    v = visitor_input_test_init(data, "[]");
237
    visit_type_UserDefOneList(v, NULL, &head, &error_abort);
E
Eric Blake 已提交
238
    g_assert(!head);
L
Luiz Capitulino 已提交
239 240
}

241 242 243 244 245 246 247 248 249 250 251 252
static void test_visitor_in_any(TestInputVisitorData *data,
                                const void *unused)
{
    QObject *res = NULL;
    Visitor *v;
    QInt *qint;
    QBool *qbool;
    QString *qstring;
    QDict *qdict;
    QObject *qobj;

    v = visitor_input_test_init(data, "-42");
253
    visit_type_any(v, NULL, &res, &error_abort);
254 255 256 257 258 259
    qint = qobject_to_qint(res);
    g_assert(qint);
    g_assert_cmpint(qint_get_int(qint), ==, -42);
    qobject_decref(res);

    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
260
    visit_type_any(v, NULL, &res, &error_abort);
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
    qdict = qobject_to_qdict(res);
    g_assert(qdict && qdict_size(qdict) == 3);
    qobj = qdict_get(qdict, "integer");
    g_assert(qobj);
    qint = qobject_to_qint(qobj);
    g_assert(qint);
    g_assert_cmpint(qint_get_int(qint), ==, -42);
    qobj = qdict_get(qdict, "boolean");
    g_assert(qobj);
    qbool = qobject_to_qbool(qobj);
    g_assert(qbool);
    g_assert(qbool_get_bool(qbool) == true);
    qobj = qdict_get(qdict, "string");
    g_assert(qobj);
    qstring = qobject_to_qstring(qobj);
    g_assert(qstring);
    g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
    qobject_decref(res);
}

281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
static void test_visitor_in_null(TestInputVisitorData *data,
                                 const void *unused)
{
    Visitor *v;
    Error *err = NULL;
    char *tmp;

    /*
     * FIXME: Since QAPI doesn't know the 'null' type yet, we can't
     * test visit_type_null() by reading into a QAPI struct then
     * checking that it was populated correctly.  The best we can do
     * for now is ensure that we consumed null from the input, proven
     * by the fact that we can't re-read the key; and that we detect
     * when input is not null.
     */

    v = visitor_input_test_init(data, "{ 'a': null, 'b': '' }");
    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    visit_type_null(v, "a", &error_abort);
    visit_type_str(v, "a", &tmp, &err);
    g_assert(!tmp);
    error_free_or_abort(&err);
    visit_type_null(v, "b", &err);
    error_free_or_abort(&err);
305 306
    visit_check_struct(v, &error_abort);
    visit_end_struct(v);
307 308
}

309 310 311 312 313
static void test_visitor_in_union_flat(TestInputVisitorData *data,
                                       const void *unused)
{
    Visitor *v;
    UserDefFlatUnion *tmp;
314
    UserDefUnionBase *base;
315

316 317
    v = visitor_input_test_init(data,
                                "{ 'enum1': 'value1', "
318
                                "'integer': 41, "
319 320
                                "'string': 'str', "
                                "'boolean': true }");
321

322
    visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
323
    g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
324
    g_assert_cmpstr(tmp->string, ==, "str");
325
    g_assert_cmpint(tmp->integer, ==, 41);
326
    g_assert_cmpint(tmp->u.value1.boolean, ==, true);
327 328 329 330

    base = qapi_UserDefFlatUnion_base(tmp);
    g_assert(&base->enum1 == &tmp->enum1);

331 332 333
    qapi_free_UserDefFlatUnion(tmp);
}

334 335
static void test_visitor_in_alternate(TestInputVisitorData *data,
                                      const void *unused)
336 337 338
{
    Visitor *v;
    Error *err = NULL;
339
    UserDefAlternate *tmp;
340
    WrapAlternate *wrap;
341 342

    v = visitor_input_test_init(data, "42");
343
    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
344
    g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
345
    g_assert_cmpint(tmp->u.i, ==, 42);
346
    qapi_free_UserDefAlternate(tmp);
347 348

    v = visitor_input_test_init(data, "'string'");
349
    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
350
    g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
351
    g_assert_cmpstr(tmp->u.s, ==, "string");
352 353
    qapi_free_UserDefAlternate(tmp);

354 355 356 357
    v = visitor_input_test_init(data, "{'integer':1, 'string':'str', "
                                "'enum1':'value1', 'boolean':true}");
    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
    g_assert_cmpint(tmp->type, ==, QTYPE_QDICT);
358 359 360
    g_assert_cmpint(tmp->u.udfu.integer, ==, 1);
    g_assert_cmpstr(tmp->u.udfu.string, ==, "str");
    g_assert_cmpint(tmp->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
361 362
    g_assert_cmpint(tmp->u.udfu.u.value1.boolean, ==, true);
    g_assert_cmpint(tmp->u.udfu.u.value1.has_a_b, ==, false);
363 364
    qapi_free_UserDefAlternate(tmp);

365
    v = visitor_input_test_init(data, "false");
366
    visit_type_UserDefAlternate(v, NULL, &tmp, &err);
367
    error_free_or_abort(&err);
368
    qapi_free_UserDefAlternate(tmp);
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385

    v = visitor_input_test_init(data, "{ 'alt': 42 }");
    visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QINT);
    g_assert_cmpint(wrap->alt->u.i, ==, 42);
    qapi_free_WrapAlternate(wrap);

    v = visitor_input_test_init(data, "{ 'alt': 'string' }");
    visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QSTRING);
    g_assert_cmpstr(wrap->alt->u.s, ==, "string");
    qapi_free_WrapAlternate(wrap);

    v = visitor_input_test_init(data, "{ 'alt': {'integer':1, 'string':'str', "
                                "'enum1':'value1', 'boolean':true} }");
    visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QDICT);
386 387 388
    g_assert_cmpint(wrap->alt->u.udfu.integer, ==, 1);
    g_assert_cmpstr(wrap->alt->u.udfu.string, ==, "str");
    g_assert_cmpint(wrap->alt->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
389 390
    g_assert_cmpint(wrap->alt->u.udfu.u.value1.boolean, ==, true);
    g_assert_cmpint(wrap->alt->u.udfu.u.value1.has_a_b, ==, false);
391
    qapi_free_WrapAlternate(wrap);
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
}

static void test_visitor_in_alternate_number(TestInputVisitorData *data,
                                             const void *unused)
{
    Visitor *v;
    Error *err = NULL;
    AltStrBool *asb;
    AltStrNum *asn;
    AltNumStr *ans;
    AltStrInt *asi;
    AltIntNum *ain;
    AltNumInt *ani;

    /* Parsing an int */

    v = visitor_input_test_init(data, "42");
409
    visit_type_AltStrBool(v, NULL, &asb, &err);
410
    error_free_or_abort(&err);
411 412 413
    qapi_free_AltStrBool(asb);

    v = visitor_input_test_init(data, "42");
414
    visit_type_AltStrNum(v, NULL, &asn, &error_abort);
415 416
    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
    g_assert_cmpfloat(asn->u.n, ==, 42);
417 418 419
    qapi_free_AltStrNum(asn);

    v = visitor_input_test_init(data, "42");
420
    visit_type_AltNumStr(v, NULL, &ans, &error_abort);
421 422
    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
    g_assert_cmpfloat(ans->u.n, ==, 42);
423 424 425
    qapi_free_AltNumStr(ans);

    v = visitor_input_test_init(data, "42");
426
    visit_type_AltStrInt(v, NULL, &asi, &error_abort);
427
    g_assert_cmpint(asi->type, ==, QTYPE_QINT);
428
    g_assert_cmpint(asi->u.i, ==, 42);
429 430 431
    qapi_free_AltStrInt(asi);

    v = visitor_input_test_init(data, "42");
432
    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
433
    g_assert_cmpint(ain->type, ==, QTYPE_QINT);
434
    g_assert_cmpint(ain->u.i, ==, 42);
435 436 437
    qapi_free_AltIntNum(ain);

    v = visitor_input_test_init(data, "42");
438
    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
439
    g_assert_cmpint(ani->type, ==, QTYPE_QINT);
440
    g_assert_cmpint(ani->u.i, ==, 42);
441 442 443 444 445
    qapi_free_AltNumInt(ani);

    /* Parsing a double */

    v = visitor_input_test_init(data, "42.5");
446
    visit_type_AltStrBool(v, NULL, &asb, &err);
447
    error_free_or_abort(&err);
448 449 450
    qapi_free_AltStrBool(asb);

    v = visitor_input_test_init(data, "42.5");
451
    visit_type_AltStrNum(v, NULL, &asn, &error_abort);
452
    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
453
    g_assert_cmpfloat(asn->u.n, ==, 42.5);
454 455 456
    qapi_free_AltStrNum(asn);

    v = visitor_input_test_init(data, "42.5");
457
    visit_type_AltNumStr(v, NULL, &ans, &error_abort);
458
    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
459
    g_assert_cmpfloat(ans->u.n, ==, 42.5);
460 461 462
    qapi_free_AltNumStr(ans);

    v = visitor_input_test_init(data, "42.5");
463
    visit_type_AltStrInt(v, NULL, &asi, &err);
464
    error_free_or_abort(&err);
465 466 467
    qapi_free_AltStrInt(asi);

    v = visitor_input_test_init(data, "42.5");
468
    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
469
    g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT);
470
    g_assert_cmpfloat(ain->u.n, ==, 42.5);
471 472 473
    qapi_free_AltIntNum(ain);

    v = visitor_input_test_init(data, "42.5");
474
    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
475
    g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT);
476
    g_assert_cmpfloat(ani->u.n, ==, 42.5);
477
    qapi_free_AltNumInt(ani);
478 479
}

480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
static void test_native_list_integer_helper(TestInputVisitorData *data,
                                            const void *unused,
                                            UserDefNativeListUnionKind kind)
{
    UserDefNativeListUnion *cvalue = NULL;
    Visitor *v;
    GString *gstr_list = g_string_new("");
    GString *gstr_union = g_string_new("");
    int i;

    for (i = 0; i < 32; i++) {
        g_string_append_printf(gstr_list, "%d", i);
        if (i != 31) {
            g_string_append(gstr_list, ", ");
        }
    }
    g_string_append_printf(gstr_union,  "{ 'type': '%s', 'data': [ %s ] }",
                           UserDefNativeListUnionKind_lookup[kind],
                           gstr_list->str);
    v = visitor_input_test_init_raw(data,  gstr_union->str);

501
    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
502
    g_assert(cvalue != NULL);
503
    g_assert_cmpint(cvalue->type, ==, kind);
504 505 506 507

    switch (kind) {
    case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
        intList *elem = NULL;
508 509
        for (i = 0, elem = cvalue->u.integer.data;
             elem; elem = elem->next, i++) {
510 511 512 513 514 515
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
        int8List *elem = NULL;
516
        for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) {
517 518 519 520 521 522
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
        int16List *elem = NULL;
523
        for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) {
524 525 526 527 528 529
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
        int32List *elem = NULL;
530
        for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) {
531 532 533 534 535 536
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
        int64List *elem = NULL;
537
        for (i = 0, elem = cvalue->u.s64.data; elem; elem = elem->next, i++) {
538 539 540 541 542 543
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
        uint8List *elem = NULL;
544
        for (i = 0, elem = cvalue->u.u8.data; elem; elem = elem->next, i++) {
545 546 547 548 549 550
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
        uint16List *elem = NULL;
551
        for (i = 0, elem = cvalue->u.u16.data; elem; elem = elem->next, i++) {
552 553 554 555 556 557
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
        uint32List *elem = NULL;
558
        for (i = 0, elem = cvalue->u.u32.data; elem; elem = elem->next, i++) {
559 560 561 562 563 564
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
        uint64List *elem = NULL;
565
        for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) {
566 567 568 569 570
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    default:
571
        g_assert_not_reached();
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
    }

    g_string_free(gstr_union, true);
    g_string_free(gstr_list, true);
    qapi_free_UserDefNativeListUnion(cvalue);
}

static void test_visitor_in_native_list_int(TestInputVisitorData *data,
                                            const void *unused)
{
    test_native_list_integer_helper(data, unused,
                                    USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
}

static void test_visitor_in_native_list_int8(TestInputVisitorData *data,
                                             const void *unused)
{
    test_native_list_integer_helper(data, unused,
                                    USER_DEF_NATIVE_LIST_UNION_KIND_S8);
}

static void test_visitor_in_native_list_int16(TestInputVisitorData *data,
                                              const void *unused)
{
    test_native_list_integer_helper(data, unused,
                                    USER_DEF_NATIVE_LIST_UNION_KIND_S16);
}

static void test_visitor_in_native_list_int32(TestInputVisitorData *data,
                                              const void *unused)
{
    test_native_list_integer_helper(data, unused,
                                    USER_DEF_NATIVE_LIST_UNION_KIND_S32);
}

static void test_visitor_in_native_list_int64(TestInputVisitorData *data,
                                              const void *unused)
{
    test_native_list_integer_helper(data, unused,
                                    USER_DEF_NATIVE_LIST_UNION_KIND_S64);
}

static void test_visitor_in_native_list_uint8(TestInputVisitorData *data,
                                             const void *unused)
{
    test_native_list_integer_helper(data, unused,
                                    USER_DEF_NATIVE_LIST_UNION_KIND_U8);
}

static void test_visitor_in_native_list_uint16(TestInputVisitorData *data,
                                               const void *unused)
{
    test_native_list_integer_helper(data, unused,
                                    USER_DEF_NATIVE_LIST_UNION_KIND_U16);
}

static void test_visitor_in_native_list_uint32(TestInputVisitorData *data,
                                               const void *unused)
{
    test_native_list_integer_helper(data, unused,
                                    USER_DEF_NATIVE_LIST_UNION_KIND_U32);
}

static void test_visitor_in_native_list_uint64(TestInputVisitorData *data,
                                               const void *unused)
{
    test_native_list_integer_helper(data, unused,
                                    USER_DEF_NATIVE_LIST_UNION_KIND_U64);
}

static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
                                            const void *unused)
{
    UserDefNativeListUnion *cvalue = NULL;
    boolList *elem = NULL;
    Visitor *v;
    GString *gstr_list = g_string_new("");
    GString *gstr_union = g_string_new("");
    int i;

    for (i = 0; i < 32; i++) {
        g_string_append_printf(gstr_list, "%s",
                               (i % 3 == 0) ? "true" : "false");
        if (i != 31) {
            g_string_append(gstr_list, ", ");
        }
    }
    g_string_append_printf(gstr_union,  "{ 'type': 'boolean', 'data': [ %s ] }",
                           gstr_list->str);
    v = visitor_input_test_init_raw(data,  gstr_union->str);

663
    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
664
    g_assert(cvalue != NULL);
665
    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
666

667
    for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next, i++) {
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
        g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
    }

    g_string_free(gstr_union, true);
    g_string_free(gstr_list, true);
    qapi_free_UserDefNativeListUnion(cvalue);
}

static void test_visitor_in_native_list_string(TestInputVisitorData *data,
                                               const void *unused)
{
    UserDefNativeListUnion *cvalue = NULL;
    strList *elem = NULL;
    Visitor *v;
    GString *gstr_list = g_string_new("");
    GString *gstr_union = g_string_new("");
    int i;

    for (i = 0; i < 32; i++) {
        g_string_append_printf(gstr_list, "'%d'", i);
        if (i != 31) {
            g_string_append(gstr_list, ", ");
        }
    }
    g_string_append_printf(gstr_union,  "{ 'type': 'string', 'data': [ %s ] }",
                           gstr_list->str);
    v = visitor_input_test_init_raw(data,  gstr_union->str);

696
    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
697
    g_assert(cvalue != NULL);
698
    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
699

700
    for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) {
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
        gchar str[8];
        sprintf(str, "%d", i);
        g_assert_cmpstr(elem->value, ==, str);
    }

    g_string_free(gstr_union, true);
    g_string_free(gstr_list, true);
    qapi_free_UserDefNativeListUnion(cvalue);
}

#define DOUBLE_STR_MAX 16

static void test_visitor_in_native_list_number(TestInputVisitorData *data,
                                               const void *unused)
{
    UserDefNativeListUnion *cvalue = NULL;
    numberList *elem = NULL;
    Visitor *v;
    GString *gstr_list = g_string_new("");
    GString *gstr_union = g_string_new("");
    int i;

    for (i = 0; i < 32; i++) {
        g_string_append_printf(gstr_list, "%f", (double)i / 3);
        if (i != 31) {
            g_string_append(gstr_list, ", ");
        }
    }
    g_string_append_printf(gstr_union,  "{ 'type': 'number', 'data': [ %s ] }",
                           gstr_list->str);
    v = visitor_input_test_init_raw(data,  gstr_union->str);

733
    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
734
    g_assert(cvalue != NULL);
735
    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
736

737
    for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next, i++) {
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
        GString *double_expected = g_string_new("");
        GString *double_actual = g_string_new("");

        g_string_printf(double_expected, "%.6f", (double)i / 3);
        g_string_printf(double_actual, "%.6f", elem->value);
        g_assert_cmpstr(double_expected->str, ==, double_actual->str);

        g_string_free(double_expected, true);
        g_string_free(double_actual, true);
    }

    g_string_free(gstr_union, true);
    g_string_free(gstr_list, true);
    qapi_free_UserDefNativeListUnion(cvalue);
}

L
Luiz Capitulino 已提交
754 755 756 757 758 759 760 761
static void input_visitor_test_add(const char *testpath,
                                   TestInputVisitorData *data,
                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
{
    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
               visitor_input_teardown);
}

762 763 764 765
static void test_visitor_in_errors(TestInputVisitorData *data,
                                   const void *unused)
{
    TestStruct *p = NULL;
766
    Error *err = NULL;
767
    Visitor *v;
768
    strList *q = NULL;
769

770 771
    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
                                "'string': -42 }");
772

773
    visit_type_TestStruct(v, NULL, &p, &err);
774
    error_free_or_abort(&err);
775
    g_assert(!p);
776 777

    v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
778
    visit_type_strList(v, NULL, &q, &err);
779
    error_free_or_abort(&err);
780
    assert(!q);
781 782
}

E
Eric Blake 已提交
783 784 785 786 787 788 789 790 791 792 793 794
static void test_visitor_in_wrong_type(TestInputVisitorData *data,
                                       const void *unused)
{
    TestStruct *p = NULL;
    Visitor *v;
    strList *q = NULL;
    int64_t i;
    Error *err = NULL;

    /* Make sure arrays and structs cannot be confused */

    v = visitor_input_test_init(data, "[]");
795
    visit_type_TestStruct(v, NULL, &p, &err);
E
Eric Blake 已提交
796 797 798 799
    error_free_or_abort(&err);
    g_assert(!p);

    v = visitor_input_test_init(data, "{}");
800
    visit_type_strList(v, NULL, &q, &err);
E
Eric Blake 已提交
801 802 803 804 805 806
    error_free_or_abort(&err);
    assert(!q);

    /* Make sure primitives and struct cannot be confused */

    v = visitor_input_test_init(data, "1");
807
    visit_type_TestStruct(v, NULL, &p, &err);
E
Eric Blake 已提交
808 809 810 811
    error_free_or_abort(&err);
    g_assert(!p);

    v = visitor_input_test_init(data, "{}");
812
    visit_type_int(v, NULL, &i, &err);
E
Eric Blake 已提交
813 814 815 816 817
    error_free_or_abort(&err);

    /* Make sure primitives and arrays cannot be confused */

    v = visitor_input_test_init(data, "1");
818
    visit_type_strList(v, NULL, &q, &err);
E
Eric Blake 已提交
819 820 821 822
    error_free_or_abort(&err);
    assert(!q);

    v = visitor_input_test_init(data, "[]");
823
    visit_type_int(v, NULL, &i, &err);
E
Eric Blake 已提交
824 825 826
    error_free_or_abort(&err);
}

L
Luiz Capitulino 已提交
827 828 829 830 831 832 833 834
int main(int argc, char **argv)
{
    TestInputVisitorData in_visitor_data;

    g_test_init(&argc, &argv, NULL);

    input_visitor_test_add("/visitor/input/int",
                           &in_visitor_data, test_visitor_in_int);
835 836
    input_visitor_test_add("/visitor/input/int_overflow",
                           &in_visitor_data, test_visitor_in_int_overflow);
L
Luiz Capitulino 已提交
837 838 839 840 841
    input_visitor_test_add("/visitor/input/bool",
                           &in_visitor_data, test_visitor_in_bool);
    input_visitor_test_add("/visitor/input/number",
                           &in_visitor_data, test_visitor_in_number);
    input_visitor_test_add("/visitor/input/string",
842
                           &in_visitor_data, test_visitor_in_string);
L
Luiz Capitulino 已提交
843
    input_visitor_test_add("/visitor/input/enum",
844
                           &in_visitor_data, test_visitor_in_enum);
L
Luiz Capitulino 已提交
845
    input_visitor_test_add("/visitor/input/struct",
846
                           &in_visitor_data, test_visitor_in_struct);
L
Luiz Capitulino 已提交
847
    input_visitor_test_add("/visitor/input/struct-nested",
848
                           &in_visitor_data, test_visitor_in_struct_nested);
L
Luiz Capitulino 已提交
849
    input_visitor_test_add("/visitor/input/list",
850
                           &in_visitor_data, test_visitor_in_list);
851 852
    input_visitor_test_add("/visitor/input/any",
                           &in_visitor_data, test_visitor_in_any);
853 854
    input_visitor_test_add("/visitor/input/null",
                           &in_visitor_data, test_visitor_in_null);
855
    input_visitor_test_add("/visitor/input/union-flat",
856
                           &in_visitor_data, test_visitor_in_union_flat);
857 858
    input_visitor_test_add("/visitor/input/alternate",
                           &in_visitor_data, test_visitor_in_alternate);
859
    input_visitor_test_add("/visitor/input/errors",
860
                           &in_visitor_data, test_visitor_in_errors);
E
Eric Blake 已提交
861 862
    input_visitor_test_add("/visitor/input/wrong-type",
                           &in_visitor_data, test_visitor_in_wrong_type);
863 864
    input_visitor_test_add("/visitor/input/alternate-number",
                           &in_visitor_data, test_visitor_in_alternate_number);
865
    input_visitor_test_add("/visitor/input/native_list/int",
866 867
                           &in_visitor_data,
                           test_visitor_in_native_list_int);
868
    input_visitor_test_add("/visitor/input/native_list/int8",
869 870
                           &in_visitor_data,
                           test_visitor_in_native_list_int8);
871
    input_visitor_test_add("/visitor/input/native_list/int16",
872 873
                           &in_visitor_data,
                           test_visitor_in_native_list_int16);
874
    input_visitor_test_add("/visitor/input/native_list/int32",
875 876
                           &in_visitor_data,
                           test_visitor_in_native_list_int32);
877
    input_visitor_test_add("/visitor/input/native_list/int64",
878 879
                           &in_visitor_data,
                           test_visitor_in_native_list_int64);
880
    input_visitor_test_add("/visitor/input/native_list/uint8",
881 882
                           &in_visitor_data,
                           test_visitor_in_native_list_uint8);
883
    input_visitor_test_add("/visitor/input/native_list/uint16",
884 885
                           &in_visitor_data,
                           test_visitor_in_native_list_uint16);
886
    input_visitor_test_add("/visitor/input/native_list/uint32",
887 888
                           &in_visitor_data,
                           test_visitor_in_native_list_uint32);
889
    input_visitor_test_add("/visitor/input/native_list/uint64",
890 891
                           &in_visitor_data,
                           test_visitor_in_native_list_uint64);
892
    input_visitor_test_add("/visitor/input/native_list/bool",
893
                           &in_visitor_data, test_visitor_in_native_list_bool);
894
    input_visitor_test_add("/visitor/input/native_list/str",
895 896
                           &in_visitor_data,
                           test_visitor_in_native_list_string);
897
    input_visitor_test_add("/visitor/input/native_list/number",
898 899
                           &in_visitor_data,
                           test_visitor_in_native_list_number);
L
Luiz Capitulino 已提交
900 901 902 903 904

    g_test_run();

    return 0;
}