test-qmp-input-visitor.c 26.7 KB
Newer Older
L
Luiz Capitulino 已提交
1 2 3
/*
 * QMP Input Visitor unit-tests.
 *
4
 * Copyright (C) 2011, 2015 Red Hat Inc.
L
Luiz Capitulino 已提交
5 6 7 8 9 10 11 12 13 14 15
 *
 * 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.
 */

#include <glib.h>
#include <stdarg.h>

16
#include "qemu-common.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 53 54 55 56 57 58 59 60 61
    data->obj = qobject_from_jsonv(json_string, ap);
    g_assert(data->obj);

    data->qiv = qmp_input_visitor_new(data->obj);
    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, &res, NULL, &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, &res, NULL, &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, &res, NULL, &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, &res, NULL, &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, &res, NULL, &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, &res, NULL, &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, &p, NULL, &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, &udp, NULL, &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, &head, NULL, &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 233 234
    }

    qapi_free_UserDefOneList(head);
}

235 236 237 238 239 240 241 242 243 244 245 246
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");
247
    visit_type_any(v, &res, NULL, &error_abort);
248 249 250 251 252 253
    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' }");
254
    visit_type_any(v, &res, NULL, &error_abort);
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
    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);
}

275 276 277 278 279
static void test_visitor_in_union_flat(TestInputVisitorData *data,
                                       const void *unused)
{
    Visitor *v;
    UserDefFlatUnion *tmp;
280
    UserDefUnionBase *base;
281

282 283
    v = visitor_input_test_init(data,
                                "{ 'enum1': 'value1', "
284
                                "'integer': 41, "
285 286
                                "'string': 'str', "
                                "'boolean': true }");
287

288
    visit_type_UserDefFlatUnion(v, &tmp, NULL, &error_abort);
289
    g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
290
    g_assert_cmpstr(tmp->string, ==, "str");
291
    g_assert_cmpint(tmp->integer, ==, 41);
292
    g_assert_cmpint(tmp->u.value1->boolean, ==, true);
293 294 295 296

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

297 298 299
    qapi_free_UserDefFlatUnion(tmp);
}

300 301
static void test_visitor_in_alternate(TestInputVisitorData *data,
                                      const void *unused)
302 303 304
{
    Visitor *v;
    Error *err = NULL;
305
    UserDefAlternate *tmp;
306 307

    v = visitor_input_test_init(data, "42");
308
    visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
309 310
    g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_I);
    g_assert_cmpint(tmp->u.i, ==, 42);
311
    qapi_free_UserDefAlternate(tmp);
312 313 314

    v = visitor_input_test_init(data, "'string'");
    visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
315 316
    g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_S);
    g_assert_cmpstr(tmp->u.s, ==, "string");
317 318 319 320
    qapi_free_UserDefAlternate(tmp);

    v = visitor_input_test_init(data, "false");
    visit_type_UserDefAlternate(v, &tmp, NULL, &err);
321
    error_free_or_abort(&err);
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
    qapi_free_UserDefAlternate(tmp);
}

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");
    visit_type_AltStrBool(v, &asb, NULL, &err);
341
    error_free_or_abort(&err);
342 343 344 345 346 347
    qapi_free_AltStrBool(asb);

    /* FIXME: Order of alternate should not affect semantics; asn should
     * parse the same as ans */
    v = visitor_input_test_init(data, "42");
    visit_type_AltStrNum(v, &asn, NULL, &err);
348 349
    /* FIXME g_assert_cmpint(asn->type, == ALT_STR_NUM_KIND_N); */
    /* FIXME g_assert_cmpfloat(asn->u.n, ==, 42); */
350
    error_free_or_abort(&err);
351 352 353 354
    qapi_free_AltStrNum(asn);

    v = visitor_input_test_init(data, "42");
    visit_type_AltNumStr(v, &ans, NULL, &error_abort);
355 356
    g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N);
    g_assert_cmpfloat(ans->u.n, ==, 42);
357 358 359 360
    qapi_free_AltNumStr(ans);

    v = visitor_input_test_init(data, "42");
    visit_type_AltStrInt(v, &asi, NULL, &error_abort);
361 362
    g_assert_cmpint(asi->type, ==, ALT_STR_INT_KIND_I);
    g_assert_cmpint(asi->u.i, ==, 42);
363 364 365 366
    qapi_free_AltStrInt(asi);

    v = visitor_input_test_init(data, "42");
    visit_type_AltIntNum(v, &ain, NULL, &error_abort);
367 368
    g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_I);
    g_assert_cmpint(ain->u.i, ==, 42);
369 370 371 372
    qapi_free_AltIntNum(ain);

    v = visitor_input_test_init(data, "42");
    visit_type_AltNumInt(v, &ani, NULL, &error_abort);
373 374
    g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_I);
    g_assert_cmpint(ani->u.i, ==, 42);
375 376 377 378 379 380
    qapi_free_AltNumInt(ani);

    /* Parsing a double */

    v = visitor_input_test_init(data, "42.5");
    visit_type_AltStrBool(v, &asb, NULL, &err);
381
    error_free_or_abort(&err);
382 383 384 385
    qapi_free_AltStrBool(asb);

    v = visitor_input_test_init(data, "42.5");
    visit_type_AltStrNum(v, &asn, NULL, &error_abort);
386 387
    g_assert_cmpint(asn->type, ==, ALT_STR_NUM_KIND_N);
    g_assert_cmpfloat(asn->u.n, ==, 42.5);
388 389 390 391
    qapi_free_AltStrNum(asn);

    v = visitor_input_test_init(data, "42.5");
    visit_type_AltNumStr(v, &ans, NULL, &error_abort);
392 393
    g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N);
    g_assert_cmpfloat(ans->u.n, ==, 42.5);
394 395 396 397
    qapi_free_AltNumStr(ans);

    v = visitor_input_test_init(data, "42.5");
    visit_type_AltStrInt(v, &asi, NULL, &err);
398
    error_free_or_abort(&err);
399 400 401 402
    qapi_free_AltStrInt(asi);

    v = visitor_input_test_init(data, "42.5");
    visit_type_AltIntNum(v, &ain, NULL, &error_abort);
403 404
    g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_N);
    g_assert_cmpfloat(ain->u.n, ==, 42.5);
405 406 407 408
    qapi_free_AltIntNum(ain);

    v = visitor_input_test_init(data, "42.5");
    visit_type_AltNumInt(v, &ani, NULL, &error_abort);
409 410
    g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_N);
    g_assert_cmpfloat(ani->u.n, ==, 42.5);
411
    qapi_free_AltNumInt(ani);
412 413
}

414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
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);

435
    visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
436
    g_assert(cvalue != NULL);
437
    g_assert_cmpint(cvalue->type, ==, kind);
438 439 440 441

    switch (kind) {
    case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
        intList *elem = NULL;
442
        for (i = 0, elem = cvalue->u.integer; elem; elem = elem->next, i++) {
443 444 445 446 447 448
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
        int8List *elem = NULL;
449
        for (i = 0, elem = cvalue->u.s8; elem; elem = elem->next, i++) {
450 451 452 453 454 455
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
        int16List *elem = NULL;
456
        for (i = 0, elem = cvalue->u.s16; elem; elem = elem->next, i++) {
457 458 459 460 461 462
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
        int32List *elem = NULL;
463
        for (i = 0, elem = cvalue->u.s32; elem; elem = elem->next, i++) {
464 465 466 467 468 469
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
        int64List *elem = NULL;
470
        for (i = 0, elem = cvalue->u.s64; elem; elem = elem->next, i++) {
471 472 473 474 475 476
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
        uint8List *elem = NULL;
477
        for (i = 0, elem = cvalue->u.u8; elem; elem = elem->next, i++) {
478 479 480 481 482 483
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
        uint16List *elem = NULL;
484
        for (i = 0, elem = cvalue->u.u16; elem; elem = elem->next, i++) {
485 486 487 488 489 490
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
        uint32List *elem = NULL;
491
        for (i = 0, elem = cvalue->u.u32; elem; elem = elem->next, i++) {
492 493 494 495 496 497
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
        uint64List *elem = NULL;
498
        for (i = 0, elem = cvalue->u.u64; elem; elem = elem->next, i++) {
499 500 501 502 503
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    default:
504
        g_assert_not_reached();
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
    }

    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);

596
    visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
597
    g_assert(cvalue != NULL);
598
    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
599

600
    for (i = 0, elem = cvalue->u.boolean; elem; elem = elem->next, i++) {
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
        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);

629
    visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
630
    g_assert(cvalue != NULL);
631
    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
632

633
    for (i = 0, elem = cvalue->u.string; elem; elem = elem->next, i++) {
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 663 664 665
        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);

666
    visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
667
    g_assert(cvalue != NULL);
668
    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
669

670
    for (i = 0, elem = cvalue->u.number; elem; elem = elem->next, i++) {
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
        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 已提交
687 688 689 690 691 692 693 694
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);
}

695 696 697 698
static void test_visitor_in_errors(TestInputVisitorData *data,
                                   const void *unused)
{
    TestStruct *p = NULL;
699
    Error *err = NULL;
700
    Visitor *v;
701
    strList *q = NULL;
702

703 704
    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
                                "'string': -42 }");
705

706
    visit_type_TestStruct(v, &p, NULL, &err);
707
    error_free_or_abort(&err);
708 709
    /* FIXME - a failed parse should not leave a partially-allocated p
     * for us to clean up; this could cause callers to leak memory. */
710 711 712 713
    g_assert(p->string == NULL);

    g_free(p->string);
    g_free(p);
714 715 716 717 718 719

    v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
    visit_type_strList(v, &q, NULL, &err);
    error_free_or_abort(&err);
    assert(q);
    qapi_free_strList(q);
720 721
}

L
Luiz Capitulino 已提交
722 723 724 725 726 727 728 729
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);
730 731
    input_visitor_test_add("/visitor/input/int_overflow",
                           &in_visitor_data, test_visitor_in_int_overflow);
L
Luiz Capitulino 已提交
732 733 734 735 736
    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",
737
                           &in_visitor_data, test_visitor_in_string);
L
Luiz Capitulino 已提交
738
    input_visitor_test_add("/visitor/input/enum",
739
                           &in_visitor_data, test_visitor_in_enum);
L
Luiz Capitulino 已提交
740
    input_visitor_test_add("/visitor/input/struct",
741
                           &in_visitor_data, test_visitor_in_struct);
L
Luiz Capitulino 已提交
742
    input_visitor_test_add("/visitor/input/struct-nested",
743
                           &in_visitor_data, test_visitor_in_struct_nested);
L
Luiz Capitulino 已提交
744
    input_visitor_test_add("/visitor/input/list",
745
                           &in_visitor_data, test_visitor_in_list);
746 747
    input_visitor_test_add("/visitor/input/any",
                           &in_visitor_data, test_visitor_in_any);
748
    input_visitor_test_add("/visitor/input/union-flat",
749
                           &in_visitor_data, test_visitor_in_union_flat);
750 751
    input_visitor_test_add("/visitor/input/alternate",
                           &in_visitor_data, test_visitor_in_alternate);
752
    input_visitor_test_add("/visitor/input/errors",
753
                           &in_visitor_data, test_visitor_in_errors);
754 755
    input_visitor_test_add("/visitor/input/alternate-number",
                           &in_visitor_data, test_visitor_in_alternate_number);
756
    input_visitor_test_add("/visitor/input/native_list/int",
757 758
                           &in_visitor_data,
                           test_visitor_in_native_list_int);
759
    input_visitor_test_add("/visitor/input/native_list/int8",
760 761
                           &in_visitor_data,
                           test_visitor_in_native_list_int8);
762
    input_visitor_test_add("/visitor/input/native_list/int16",
763 764
                           &in_visitor_data,
                           test_visitor_in_native_list_int16);
765
    input_visitor_test_add("/visitor/input/native_list/int32",
766 767
                           &in_visitor_data,
                           test_visitor_in_native_list_int32);
768
    input_visitor_test_add("/visitor/input/native_list/int64",
769 770
                           &in_visitor_data,
                           test_visitor_in_native_list_int64);
771
    input_visitor_test_add("/visitor/input/native_list/uint8",
772 773
                           &in_visitor_data,
                           test_visitor_in_native_list_uint8);
774
    input_visitor_test_add("/visitor/input/native_list/uint16",
775 776
                           &in_visitor_data,
                           test_visitor_in_native_list_uint16);
777
    input_visitor_test_add("/visitor/input/native_list/uint32",
778 779
                           &in_visitor_data,
                           test_visitor_in_native_list_uint32);
780
    input_visitor_test_add("/visitor/input/native_list/uint64",
781 782
                           &in_visitor_data,
                           test_visitor_in_native_list_uint64);
783
    input_visitor_test_add("/visitor/input/native_list/bool",
784
                           &in_visitor_data, test_visitor_in_native_list_bool);
785
    input_visitor_test_add("/visitor/input/native_list/str",
786 787
                           &in_visitor_data,
                           test_visitor_in_native_list_string);
788
    input_visitor_test_add("/visitor/input/native_list/number",
789 790
                           &in_visitor_data,
                           test_visitor_in_native_list_number);
L
Luiz Capitulino 已提交
791 792 793 794 795

    g_test_run();

    return 0;
}