test-qmp-input-visitor.c 29.6 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 <glib.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, 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
static void test_visitor_in_union_flat(TestInputVisitorData *data,
                                       const void *unused)
{
    Visitor *v;
    UserDefFlatUnion *tmp;
286
    UserDefUnionBase *base;
287

288 289
    v = visitor_input_test_init(data,
                                "{ 'enum1': 'value1', "
290
                                "'integer': 41, "
291 292
                                "'string': 'str', "
                                "'boolean': true }");
293

294
    visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
295
    g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
296
    g_assert_cmpstr(tmp->string, ==, "str");
297
    g_assert_cmpint(tmp->integer, ==, 41);
298
    g_assert_cmpint(tmp->u.value1->boolean, ==, true);
299 300 301 302

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

303 304 305
    qapi_free_UserDefFlatUnion(tmp);
}

306 307
static void test_visitor_in_alternate(TestInputVisitorData *data,
                                      const void *unused)
308 309 310
{
    Visitor *v;
    Error *err = NULL;
311
    UserDefAlternate *tmp;
312
    WrapAlternate *wrap;
313 314

    v = visitor_input_test_init(data, "42");
315
    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
316
    g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
317
    g_assert_cmpint(tmp->u.i, ==, 42);
318
    qapi_free_UserDefAlternate(tmp);
319 320

    v = visitor_input_test_init(data, "'string'");
321
    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
322
    g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
323
    g_assert_cmpstr(tmp->u.s, ==, "string");
324 325
    qapi_free_UserDefAlternate(tmp);

326 327 328 329
    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);
330 331 332 333 334
    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);
    g_assert_cmpint(tmp->u.udfu.u.value1->boolean, ==, true);
    g_assert_cmpint(tmp->u.udfu.u.value1->has_a_b, ==, false);
335 336
    qapi_free_UserDefAlternate(tmp);

337
    v = visitor_input_test_init(data, "false");
338
    visit_type_UserDefAlternate(v, NULL, &tmp, &err);
339
    error_free_or_abort(&err);
340
    qapi_free_UserDefAlternate(tmp);
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357

    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);
358 359 360 361 362
    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);
    g_assert_cmpint(wrap->alt->u.udfu.u.value1->boolean, ==, true);
    g_assert_cmpint(wrap->alt->u.udfu.u.value1->has_a_b, ==, false);
363
    qapi_free_WrapAlternate(wrap);
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
}

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");
381
    visit_type_AltStrBool(v, NULL, &asb, &err);
382
    error_free_or_abort(&err);
383 384 385
    qapi_free_AltStrBool(asb);

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

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

    v = visitor_input_test_init(data, "42");
398
    visit_type_AltStrInt(v, NULL, &asi, &error_abort);
399
    g_assert_cmpint(asi->type, ==, QTYPE_QINT);
400
    g_assert_cmpint(asi->u.i, ==, 42);
401 402 403
    qapi_free_AltStrInt(asi);

    v = visitor_input_test_init(data, "42");
404
    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
405
    g_assert_cmpint(ain->type, ==, QTYPE_QINT);
406
    g_assert_cmpint(ain->u.i, ==, 42);
407 408 409
    qapi_free_AltIntNum(ain);

    v = visitor_input_test_init(data, "42");
410
    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
411
    g_assert_cmpint(ani->type, ==, QTYPE_QINT);
412
    g_assert_cmpint(ani->u.i, ==, 42);
413 414 415 416 417
    qapi_free_AltNumInt(ani);

    /* Parsing a double */

    v = visitor_input_test_init(data, "42.5");
418
    visit_type_AltStrBool(v, NULL, &asb, &err);
419
    error_free_or_abort(&err);
420 421 422
    qapi_free_AltStrBool(asb);

    v = visitor_input_test_init(data, "42.5");
423
    visit_type_AltStrNum(v, NULL, &asn, &error_abort);
424
    g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
425
    g_assert_cmpfloat(asn->u.n, ==, 42.5);
426 427 428
    qapi_free_AltStrNum(asn);

    v = visitor_input_test_init(data, "42.5");
429
    visit_type_AltNumStr(v, NULL, &ans, &error_abort);
430
    g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
431
    g_assert_cmpfloat(ans->u.n, ==, 42.5);
432 433 434
    qapi_free_AltNumStr(ans);

    v = visitor_input_test_init(data, "42.5");
435
    visit_type_AltStrInt(v, NULL, &asi, &err);
436
    error_free_or_abort(&err);
437 438 439
    qapi_free_AltStrInt(asi);

    v = visitor_input_test_init(data, "42.5");
440
    visit_type_AltIntNum(v, NULL, &ain, &error_abort);
441
    g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT);
442
    g_assert_cmpfloat(ain->u.n, ==, 42.5);
443 444 445
    qapi_free_AltIntNum(ain);

    v = visitor_input_test_init(data, "42.5");
446
    visit_type_AltNumInt(v, NULL, &ani, &error_abort);
447
    g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT);
448
    g_assert_cmpfloat(ani->u.n, ==, 42.5);
449
    qapi_free_AltNumInt(ani);
450 451
}

452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
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);

473
    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
474
    g_assert(cvalue != NULL);
475
    g_assert_cmpint(cvalue->type, ==, kind);
476 477 478 479

    switch (kind) {
    case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
        intList *elem = NULL;
480
        for (i = 0, elem = cvalue->u.integer; elem; elem = elem->next, i++) {
481 482 483 484 485 486
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
        int8List *elem = NULL;
487
        for (i = 0, elem = cvalue->u.s8; elem; elem = elem->next, i++) {
488 489 490 491 492 493
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
        int16List *elem = NULL;
494
        for (i = 0, elem = cvalue->u.s16; elem; elem = elem->next, i++) {
495 496 497 498 499 500
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
        int32List *elem = NULL;
501
        for (i = 0, elem = cvalue->u.s32; elem; elem = elem->next, i++) {
502 503 504 505 506 507
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
        int64List *elem = NULL;
508
        for (i = 0, elem = cvalue->u.s64; elem; elem = elem->next, i++) {
509 510 511 512 513 514
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
        uint8List *elem = NULL;
515
        for (i = 0, elem = cvalue->u.u8; elem; elem = elem->next, i++) {
516 517 518 519 520 521
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
        uint16List *elem = NULL;
522
        for (i = 0, elem = cvalue->u.u16; elem; elem = elem->next, i++) {
523 524 525 526 527 528
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
        uint32List *elem = NULL;
529
        for (i = 0, elem = cvalue->u.u32; elem; elem = elem->next, i++) {
530 531 532 533 534 535
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
        uint64List *elem = NULL;
536
        for (i = 0, elem = cvalue->u.u64; elem; elem = elem->next, i++) {
537 538 539 540 541
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    default:
542
        g_assert_not_reached();
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 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
    }

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

634
    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
635
    g_assert(cvalue != NULL);
636
    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
637

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

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

671
    for (i = 0, elem = cvalue->u.string; elem; elem = elem->next, i++) {
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
        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);

704
    visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
705
    g_assert(cvalue != NULL);
706
    g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
707

708
    for (i = 0, elem = cvalue->u.number; elem; elem = elem->next, i++) {
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
        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 已提交
725 726 727 728 729 730 731 732
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);
}

733 734 735 736
static void test_visitor_in_errors(TestInputVisitorData *data,
                                   const void *unused)
{
    TestStruct *p = NULL;
737
    Error *err = NULL;
738
    Visitor *v;
739
    strList *q = NULL;
740

741 742
    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
                                "'string': -42 }");
743

744
    visit_type_TestStruct(v, NULL, &p, &err);
745
    error_free_or_abort(&err);
746 747
    /* FIXME - a failed parse should not leave a partially-allocated p
     * for us to clean up; this could cause callers to leak memory. */
748 749 750 751
    g_assert(p->string == NULL);

    g_free(p->string);
    g_free(p);
752 753

    v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
754
    visit_type_strList(v, NULL, &q, &err);
755 756 757
    error_free_or_abort(&err);
    assert(q);
    qapi_free_strList(q);
758 759
}

E
Eric Blake 已提交
760 761 762 763 764 765 766 767 768 769 770 771
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, "[]");
772
    visit_type_TestStruct(v, NULL, &p, &err);
E
Eric Blake 已提交
773 774 775 776
    error_free_or_abort(&err);
    g_assert(!p);

    v = visitor_input_test_init(data, "{}");
777
    visit_type_strList(v, NULL, &q, &err);
E
Eric Blake 已提交
778 779 780 781 782 783
    error_free_or_abort(&err);
    assert(!q);

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

    v = visitor_input_test_init(data, "1");
784
    visit_type_TestStruct(v, NULL, &p, &err);
E
Eric Blake 已提交
785 786 787 788
    error_free_or_abort(&err);
    g_assert(!p);

    v = visitor_input_test_init(data, "{}");
789
    visit_type_int(v, NULL, &i, &err);
E
Eric Blake 已提交
790 791 792 793 794
    error_free_or_abort(&err);

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

    v = visitor_input_test_init(data, "1");
795
    visit_type_strList(v, NULL, &q, &err);
E
Eric Blake 已提交
796 797 798 799
    error_free_or_abort(&err);
    assert(!q);

    v = visitor_input_test_init(data, "[]");
800
    visit_type_int(v, NULL, &i, &err);
E
Eric Blake 已提交
801 802 803
    error_free_or_abort(&err);
}

L
Luiz Capitulino 已提交
804 805 806 807 808 809 810 811
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);
812 813
    input_visitor_test_add("/visitor/input/int_overflow",
                           &in_visitor_data, test_visitor_in_int_overflow);
L
Luiz Capitulino 已提交
814 815 816 817 818
    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",
819
                           &in_visitor_data, test_visitor_in_string);
L
Luiz Capitulino 已提交
820
    input_visitor_test_add("/visitor/input/enum",
821
                           &in_visitor_data, test_visitor_in_enum);
L
Luiz Capitulino 已提交
822
    input_visitor_test_add("/visitor/input/struct",
823
                           &in_visitor_data, test_visitor_in_struct);
L
Luiz Capitulino 已提交
824
    input_visitor_test_add("/visitor/input/struct-nested",
825
                           &in_visitor_data, test_visitor_in_struct_nested);
L
Luiz Capitulino 已提交
826
    input_visitor_test_add("/visitor/input/list",
827
                           &in_visitor_data, test_visitor_in_list);
828 829
    input_visitor_test_add("/visitor/input/any",
                           &in_visitor_data, test_visitor_in_any);
830
    input_visitor_test_add("/visitor/input/union-flat",
831
                           &in_visitor_data, test_visitor_in_union_flat);
832 833
    input_visitor_test_add("/visitor/input/alternate",
                           &in_visitor_data, test_visitor_in_alternate);
834
    input_visitor_test_add("/visitor/input/errors",
835
                           &in_visitor_data, test_visitor_in_errors);
E
Eric Blake 已提交
836 837
    input_visitor_test_add("/visitor/input/wrong-type",
                           &in_visitor_data, test_visitor_in_wrong_type);
838 839
    input_visitor_test_add("/visitor/input/alternate-number",
                           &in_visitor_data, test_visitor_in_alternate_number);
840
    input_visitor_test_add("/visitor/input/native_list/int",
841 842
                           &in_visitor_data,
                           test_visitor_in_native_list_int);
843
    input_visitor_test_add("/visitor/input/native_list/int8",
844 845
                           &in_visitor_data,
                           test_visitor_in_native_list_int8);
846
    input_visitor_test_add("/visitor/input/native_list/int16",
847 848
                           &in_visitor_data,
                           test_visitor_in_native_list_int16);
849
    input_visitor_test_add("/visitor/input/native_list/int32",
850 851
                           &in_visitor_data,
                           test_visitor_in_native_list_int32);
852
    input_visitor_test_add("/visitor/input/native_list/int64",
853 854
                           &in_visitor_data,
                           test_visitor_in_native_list_int64);
855
    input_visitor_test_add("/visitor/input/native_list/uint8",
856 857
                           &in_visitor_data,
                           test_visitor_in_native_list_uint8);
858
    input_visitor_test_add("/visitor/input/native_list/uint16",
859 860
                           &in_visitor_data,
                           test_visitor_in_native_list_uint16);
861
    input_visitor_test_add("/visitor/input/native_list/uint32",
862 863
                           &in_visitor_data,
                           test_visitor_in_native_list_uint32);
864
    input_visitor_test_add("/visitor/input/native_list/uint64",
865 866
                           &in_visitor_data,
                           test_visitor_in_native_list_uint64);
867
    input_visitor_test_add("/visitor/input/native_list/bool",
868
                           &in_visitor_data, test_visitor_in_native_list_bool);
869
    input_visitor_test_add("/visitor/input/native_list/str",
870 871
                           &in_visitor_data,
                           test_visitor_in_native_list_string);
872
    input_visitor_test_add("/visitor/input/native_list/number",
873 874
                           &in_visitor_data,
                           test_visitor_in_native_list_number);
L
Luiz Capitulino 已提交
875 876 877 878 879

    g_test_run();

    return 0;
}