test-qmp-input-visitor.c 29.7 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
    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);
333 334
    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
    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);
361 362
    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 481
        for (i = 0, elem = cvalue->u.integer.data;
             elem; elem = elem->next, i++) {
482 483 484 485 486 487
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
        int8List *elem = NULL;
488
        for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) {
489 490 491 492 493 494
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
        int16List *elem = NULL;
495
        for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) {
496 497 498 499 500 501
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
        int32List *elem = NULL;
502
        for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) {
503 504 505 506 507 508
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
        int64List *elem = NULL;
509
        for (i = 0, elem = cvalue->u.s64.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_U8: {
        uint8List *elem = NULL;
516
        for (i = 0, elem = cvalue->u.u8.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_U16: {
        uint16List *elem = NULL;
523
        for (i = 0, elem = cvalue->u.u16.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_U32: {
        uint32List *elem = NULL;
530
        for (i = 0, elem = cvalue->u.u32.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_U64: {
        uint64List *elem = NULL;
537
        for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) {
538 539 540 541 542
            g_assert_cmpint(elem->value, ==, i);
        }
        break;
    }
    default:
543
        g_assert_not_reached();
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 634
    }

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

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

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

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

672
    for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) {
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 704
        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);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    g_test_run();

    return 0;
}