cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

test-qobject-input-visitor.c (38963B)


      1/*
      2 * QObject Input Visitor unit-tests.
      3 *
      4 * Copyright (C) 2011-2016 Red Hat Inc.
      5 *
      6 * Authors:
      7 *  Luiz Capitulino <lcapitulino@redhat.com>
      8 *  Paolo Bonzini <pbonzini@redhat.com>
      9 *
     10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     11 * See the COPYING file in the top-level directory.
     12 */
     13
     14#include "qemu/osdep.h"
     15
     16#include "qemu-common.h"
     17#include "qapi/error.h"
     18#include "qapi/qapi-visit-introspect.h"
     19#include "qapi/qobject-input-visitor.h"
     20#include "test-qapi-visit.h"
     21#include "qapi/qmp/qbool.h"
     22#include "qapi/qmp/qdict.h"
     23#include "qapi/qmp/qnull.h"
     24#include "qapi/qmp/qnum.h"
     25#include "qapi/qmp/qstring.h"
     26#include "qapi/qmp/qjson.h"
     27#include "test-qapi-introspect.h"
     28#include "qapi/qapi-introspect.h"
     29
     30typedef struct TestInputVisitorData {
     31    QObject *obj;
     32    Visitor *qiv;
     33} TestInputVisitorData;
     34
     35static void visitor_input_teardown(TestInputVisitorData *data,
     36                                   const void *unused)
     37{
     38    qobject_unref(data->obj);
     39    data->obj = NULL;
     40
     41    if (data->qiv) {
     42        visit_free(data->qiv);
     43        data->qiv = NULL;
     44    }
     45}
     46
     47/* The various test_init functions are provided instead of a test setup
     48   function so that the JSON string used by the tests are kept in the test
     49   functions (and not in main()). */
     50
     51static Visitor *test_init_internal(TestInputVisitorData *data, bool keyval,
     52                                   QObject *obj)
     53{
     54    visitor_input_teardown(data, NULL);
     55
     56    data->obj = obj;
     57
     58    if (keyval) {
     59        data->qiv = qobject_input_visitor_new_keyval(data->obj);
     60    } else {
     61        data->qiv = qobject_input_visitor_new(data->obj);
     62    }
     63    g_assert(data->qiv);
     64    return data->qiv;
     65}
     66
     67static GCC_FMT_ATTR(3, 4)
     68Visitor *visitor_input_test_init_full(TestInputVisitorData *data,
     69                                      bool keyval,
     70                                      const char *json_string, ...)
     71{
     72    Visitor *v;
     73    va_list ap;
     74
     75    va_start(ap, json_string);
     76    v = test_init_internal(data, keyval,
     77                           qobject_from_vjsonf_nofail(json_string, ap));
     78    va_end(ap);
     79    return v;
     80}
     81
     82static GCC_FMT_ATTR(2, 3)
     83Visitor *visitor_input_test_init(TestInputVisitorData *data,
     84                                 const char *json_string, ...)
     85{
     86    Visitor *v;
     87    va_list ap;
     88
     89    va_start(ap, json_string);
     90    v = test_init_internal(data, false,
     91                           qobject_from_vjsonf_nofail(json_string, ap));
     92    va_end(ap);
     93    return v;
     94}
     95
     96/* similar to visitor_input_test_init(), but does not expect a string
     97 * literal/format json_string argument and so can be used for
     98 * programatically generated strings (and we can't pass in programatically
     99 * generated strings via %s format parameters since qobject_from_jsonv()
    100 * will wrap those in double-quotes and treat the entire object as a
    101 * string)
    102 */
    103static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
    104                                            const char *json_string)
    105{
    106    return test_init_internal(data, false,
    107                              qobject_from_json(json_string, &error_abort));
    108}
    109
    110static void test_visitor_in_int(TestInputVisitorData *data,
    111                                const void *unused)
    112{
    113    int64_t res = 0;
    114    double dbl;
    115    int value = -42;
    116    Visitor *v;
    117
    118    v = visitor_input_test_init(data, "%d", value);
    119
    120    visit_type_int(v, NULL, &res, &error_abort);
    121    g_assert_cmpint(res, ==, value);
    122
    123    visit_type_number(v, NULL, &dbl, &error_abort);
    124    g_assert_cmpfloat(dbl, ==, -42.0);
    125}
    126
    127static void test_visitor_in_uint(TestInputVisitorData *data,
    128                                const void *unused)
    129{
    130    uint64_t res = 0;
    131    int64_t i64;
    132    double dbl;
    133    int value = 42;
    134    Visitor *v;
    135
    136    v = visitor_input_test_init(data, "%d", value);
    137
    138    visit_type_uint64(v, NULL, &res, &error_abort);
    139    g_assert_cmpuint(res, ==, (uint64_t)value);
    140
    141    visit_type_int(v, NULL, &i64, &error_abort);
    142    g_assert_cmpint(i64, ==, value);
    143
    144    visit_type_number(v, NULL, &dbl, &error_abort);
    145    g_assert_cmpfloat(dbl, ==, value);
    146
    147    /* BUG: value between INT64_MIN and -1 accepted modulo 2^64 */
    148    v = visitor_input_test_init(data, "%d", -value);
    149
    150    visit_type_uint64(v, NULL, &res, &error_abort);
    151    g_assert_cmpuint(res, ==, (uint64_t)-value);
    152
    153    v = visitor_input_test_init(data, "18446744073709551574");
    154
    155    visit_type_uint64(v, NULL, &res, &error_abort);
    156    g_assert_cmpuint(res, ==, 18446744073709551574U);
    157
    158    visit_type_number(v, NULL, &dbl, &error_abort);
    159    g_assert_cmpfloat(dbl, ==, 18446744073709552000.0);
    160}
    161
    162static void test_visitor_in_int_overflow(TestInputVisitorData *data,
    163                                         const void *unused)
    164{
    165    int64_t res = 0;
    166    Error *err = NULL;
    167    Visitor *v;
    168
    169    /*
    170     * This will overflow a QNUM_I64, so should be deserialized into a
    171     * QNUM_DOUBLE field instead, leading to an error if we pass it to
    172     * visit_type_int().  Confirm this.
    173     */
    174    v = visitor_input_test_init(data, "%f", DBL_MAX);
    175
    176    visit_type_int(v, NULL, &res, &err);
    177    error_free_or_abort(&err);
    178}
    179
    180static void test_visitor_in_int_keyval(TestInputVisitorData *data,
    181                                       const void *unused)
    182{
    183    int64_t res = 0, value = -42;
    184    Error *err = NULL;
    185    Visitor *v;
    186
    187    v = visitor_input_test_init_full(data, true, "%" PRId64, value);
    188    visit_type_int(v, NULL, &res, &err);
    189    error_free_or_abort(&err);
    190}
    191
    192static void test_visitor_in_int_str_keyval(TestInputVisitorData *data,
    193                                           const void *unused)
    194{
    195    int64_t res = 0, value = -42;
    196    Visitor *v;
    197
    198    v = visitor_input_test_init_full(data, true, "\"-42\"");
    199
    200    visit_type_int(v, NULL, &res, &error_abort);
    201    g_assert_cmpint(res, ==, value);
    202}
    203
    204static void test_visitor_in_int_str_fail(TestInputVisitorData *data,
    205                                         const void *unused)
    206{
    207    int64_t res = 0;
    208    Visitor *v;
    209    Error *err = NULL;
    210
    211    v = visitor_input_test_init(data, "\"-42\"");
    212
    213    visit_type_int(v, NULL, &res, &err);
    214    error_free_or_abort(&err);
    215}
    216
    217static void test_visitor_in_bool(TestInputVisitorData *data,
    218                                 const void *unused)
    219{
    220    bool res = false;
    221    Visitor *v;
    222
    223    v = visitor_input_test_init(data, "true");
    224
    225    visit_type_bool(v, NULL, &res, &error_abort);
    226    g_assert_cmpint(res, ==, true);
    227}
    228
    229static void test_visitor_in_bool_keyval(TestInputVisitorData *data,
    230                                        const void *unused)
    231{
    232    bool res = false;
    233    Error *err = NULL;
    234    Visitor *v;
    235
    236    v = visitor_input_test_init_full(data, true, "true");
    237
    238    visit_type_bool(v, NULL, &res, &err);
    239    error_free_or_abort(&err);
    240}
    241
    242static void test_visitor_in_bool_str_keyval(TestInputVisitorData *data,
    243                                            const void *unused)
    244{
    245    bool res = false;
    246    Visitor *v;
    247
    248    v = visitor_input_test_init_full(data, true, "\"on\"");
    249
    250    visit_type_bool(v, NULL, &res, &error_abort);
    251    g_assert_cmpint(res, ==, true);
    252}
    253
    254static void test_visitor_in_bool_str_fail(TestInputVisitorData *data,
    255                                          const void *unused)
    256{
    257    bool res = false;
    258    Visitor *v;
    259    Error *err = NULL;
    260
    261    v = visitor_input_test_init(data, "\"true\"");
    262
    263    visit_type_bool(v, NULL, &res, &err);
    264    error_free_or_abort(&err);
    265}
    266
    267static void test_visitor_in_number(TestInputVisitorData *data,
    268                                   const void *unused)
    269{
    270    double res = 0, value = 3.14;
    271    Visitor *v;
    272
    273    v = visitor_input_test_init(data, "%f", value);
    274
    275    visit_type_number(v, NULL, &res, &error_abort);
    276    g_assert_cmpfloat(res, ==, value);
    277}
    278
    279static void test_visitor_in_large_number(TestInputVisitorData *data,
    280                                         const void *unused)
    281{
    282    Error *err = NULL;
    283    double res = 0;
    284    int64_t i64;
    285    uint64_t u64;
    286    Visitor *v;
    287
    288    v = visitor_input_test_init(data, "-18446744073709551616"); /* -2^64 */
    289
    290    visit_type_number(v, NULL, &res, &error_abort);
    291    g_assert_cmpfloat(res, ==, -18446744073709552e3);
    292
    293    visit_type_int(v, NULL, &i64, &err);
    294    error_free_or_abort(&err);
    295
    296    visit_type_uint64(v, NULL, &u64, &err);
    297    error_free_or_abort(&err);
    298}
    299
    300static void test_visitor_in_number_keyval(TestInputVisitorData *data,
    301                                          const void *unused)
    302{
    303    double res = 0, value = 3.14;
    304    Error *err = NULL;
    305    Visitor *v;
    306
    307    v = visitor_input_test_init_full(data, true, "%f", value);
    308
    309    visit_type_number(v, NULL, &res, &err);
    310    error_free_or_abort(&err);
    311}
    312
    313static void test_visitor_in_number_str_keyval(TestInputVisitorData *data,
    314                                              const void *unused)
    315{
    316    double res = 0, value = 3.14;
    317    Visitor *v;
    318    Error *err = NULL;
    319
    320    v = visitor_input_test_init_full(data, true, "\"3.14\"");
    321
    322    visit_type_number(v, NULL, &res, &error_abort);
    323    g_assert_cmpfloat(res, ==, value);
    324
    325    v = visitor_input_test_init_full(data, true, "\"inf\"");
    326
    327    visit_type_number(v, NULL, &res, &err);
    328    error_free_or_abort(&err);
    329}
    330
    331static void test_visitor_in_number_str_fail(TestInputVisitorData *data,
    332                                            const void *unused)
    333{
    334    double res = 0;
    335    Visitor *v;
    336    Error *err = NULL;
    337
    338    v = visitor_input_test_init(data, "\"3.14\"");
    339
    340    visit_type_number(v, NULL, &res, &err);
    341    error_free_or_abort(&err);
    342}
    343
    344static void test_visitor_in_size_str_keyval(TestInputVisitorData *data,
    345                                            const void *unused)
    346{
    347    uint64_t res, value = 500 * 1024 * 1024;
    348    Visitor *v;
    349
    350    v = visitor_input_test_init_full(data, true, "\"500M\"");
    351
    352    visit_type_size(v, NULL, &res, &error_abort);
    353    g_assert_cmpfloat(res, ==, value);
    354}
    355
    356static void test_visitor_in_size_str_fail(TestInputVisitorData *data,
    357                                          const void *unused)
    358{
    359    uint64_t res = 0;
    360    Visitor *v;
    361    Error *err = NULL;
    362
    363    v = visitor_input_test_init(data, "\"500M\"");
    364
    365    visit_type_size(v, NULL, &res, &err);
    366    error_free_or_abort(&err);
    367}
    368
    369static void test_visitor_in_string(TestInputVisitorData *data,
    370                                   const void *unused)
    371{
    372    char *res = NULL, *value = (char *) "Q E M U";
    373    Visitor *v;
    374
    375    v = visitor_input_test_init(data, "%s", value);
    376
    377    visit_type_str(v, NULL, &res, &error_abort);
    378    g_assert_cmpstr(res, ==, value);
    379
    380    g_free(res);
    381}
    382
    383static void test_visitor_in_enum(TestInputVisitorData *data,
    384                                 const void *unused)
    385{
    386    Visitor *v;
    387    EnumOne i;
    388
    389    for (i = 0; i < ENUM_ONE__MAX; i++) {
    390        EnumOne res = -1;
    391
    392        v = visitor_input_test_init(data, "%s", EnumOne_str(i));
    393
    394        visit_type_EnumOne(v, NULL, &res, &error_abort);
    395        g_assert_cmpint(i, ==, res);
    396    }
    397}
    398
    399
    400static void test_visitor_in_struct(TestInputVisitorData *data,
    401                                   const void *unused)
    402{
    403    TestStruct *p = NULL;
    404    Visitor *v;
    405
    406    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
    407
    408    visit_type_TestStruct(v, NULL, &p, &error_abort);
    409    g_assert_cmpint(p->integer, ==, -42);
    410    g_assert(p->boolean == true);
    411    g_assert_cmpstr(p->string, ==, "foo");
    412
    413    g_free(p->string);
    414    g_free(p);
    415}
    416
    417static void test_visitor_in_struct_nested(TestInputVisitorData *data,
    418                                          const void *unused)
    419{
    420    g_autoptr(UserDefTwo) udp = NULL;
    421    Visitor *v;
    422
    423    v = visitor_input_test_init(data, "{ 'string0': 'string0', "
    424                                "'dict1': { 'string1': 'string1', "
    425                                "'dict2': { 'userdef': { 'integer': 42, "
    426                                "'string': 'string' }, 'string': 'string2'}}}");
    427
    428    visit_type_UserDefTwo(v, NULL, &udp, &error_abort);
    429
    430    g_assert_cmpstr(udp->string0, ==, "string0");
    431    g_assert_cmpstr(udp->dict1->string1, ==, "string1");
    432    g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
    433    g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
    434    g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
    435    g_assert(udp->dict1->has_dict3 == false);
    436}
    437
    438static void test_visitor_in_list(TestInputVisitorData *data,
    439                                 const void *unused)
    440{
    441    UserDefOneList *item, *head = NULL;
    442    Visitor *v;
    443    int i;
    444
    445    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
    446
    447    visit_type_UserDefOneList(v, NULL, &head, &error_abort);
    448    g_assert(head != NULL);
    449
    450    for (i = 0, item = head; item; item = item->next, i++) {
    451        char string[12];
    452
    453        snprintf(string, sizeof(string), "string%d", i);
    454        g_assert_cmpstr(item->value->string, ==, string);
    455        g_assert_cmpint(item->value->integer, ==, 42 + i);
    456    }
    457
    458    qapi_free_UserDefOneList(head);
    459    head = NULL;
    460
    461    /* An empty list is valid */
    462    v = visitor_input_test_init(data, "[]");
    463    visit_type_UserDefOneList(v, NULL, &head, &error_abort);
    464    g_assert(!head);
    465}
    466
    467static void test_visitor_in_list_struct(TestInputVisitorData *data,
    468                                        const void *unused)
    469{
    470    const char *int_member[] = {
    471        "integer", "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64" };
    472    g_autoptr(GString) json = g_string_new("");
    473    int i, j;
    474    const char *sep;
    475    g_autoptr(ArrayStruct) arrs = NULL;
    476    Visitor *v;
    477    intList *int_list;
    478    int8List *s8_list;
    479    int16List *s16_list;
    480    int32List *s32_list;
    481    int64List *s64_list;
    482    uint8List *u8_list;
    483    uint16List *u16_list;
    484    uint32List *u32_list;
    485    uint64List *u64_list;
    486    numberList *num_list;
    487    boolList *bool_list;
    488    strList *str_list;
    489
    490    g_string_append_printf(json, "{");
    491
    492    for (i = 0; i < G_N_ELEMENTS(int_member); i++) {
    493        g_string_append_printf(json, "'%s': [", int_member[i]);
    494        sep = "";
    495        for (j = 0; j < 32; j++) {
    496            g_string_append_printf(json, "%s%d", sep, j);
    497            sep = ", ";
    498        }
    499        g_string_append_printf(json, "], ");
    500    }
    501
    502    g_string_append_printf(json, "'number': [");
    503    sep = "";
    504    for (i = 0; i < 32; i++) {
    505        g_string_append_printf(json, "%s%f", sep, (double)i / 3);
    506        sep = ", ";
    507    }
    508    g_string_append_printf(json, "], ");
    509
    510    g_string_append_printf(json, "'boolean': [");
    511    sep = "";
    512    for (i = 0; i < 32; i++) {
    513        g_string_append_printf(json, "%s%s",
    514                               sep, i % 3 == 0 ? "true" : "false");
    515        sep = ", ";
    516    }
    517    g_string_append_printf(json, "], ");
    518
    519    g_string_append_printf(json, "'string': [");
    520    sep = "";
    521    for (i = 0; i < 32; i++) {
    522        g_string_append_printf(json, "%s'%d'", sep, i);
    523        sep = ", ";
    524    }
    525    g_string_append_printf(json, "]");
    526
    527    g_string_append_printf(json, "}");
    528
    529    v = visitor_input_test_init_raw(data, json->str);
    530    visit_type_ArrayStruct(v, NULL, &arrs, &error_abort);
    531
    532    i = 0;
    533    for (int_list = arrs->integer; int_list; int_list = int_list->next) {
    534        g_assert_cmpint(int_list->value, ==, i);
    535        i++;
    536    }
    537
    538    i = 0;
    539    for (s8_list = arrs->s8; s8_list; s8_list = s8_list->next) {
    540        g_assert_cmpint(s8_list->value, ==, i);
    541        i++;
    542    }
    543
    544    i = 0;
    545    for (s16_list = arrs->s16; s16_list; s16_list = s16_list->next) {
    546        g_assert_cmpint(s16_list->value, ==, i);
    547        i++;
    548    }
    549
    550    i = 0;
    551    for (s32_list = arrs->s32; s32_list; s32_list = s32_list->next) {
    552        g_assert_cmpint(s32_list->value, ==, i);
    553        i++;
    554    }
    555
    556    i = 0;
    557    for (s64_list = arrs->s64; s64_list; s64_list = s64_list->next) {
    558        g_assert_cmpint(s64_list->value, ==, i);
    559        i++;
    560    }
    561
    562    i = 0;
    563    for (u8_list = arrs->u8; u8_list; u8_list = u8_list->next) {
    564        g_assert_cmpint(u8_list->value, ==, i);
    565        i++;
    566    }
    567
    568    i = 0;
    569    for (u16_list = arrs->u16; u16_list; u16_list = u16_list->next) {
    570        g_assert_cmpint(u16_list->value, ==, i);
    571        i++;
    572    }
    573
    574    i = 0;
    575    for (u32_list = arrs->u32; u32_list; u32_list = u32_list->next) {
    576        g_assert_cmpint(u32_list->value, ==, i);
    577        i++;
    578    }
    579
    580    i = 0;
    581    for (u64_list = arrs->u64; u64_list; u64_list = u64_list->next) {
    582        g_assert_cmpint(u64_list->value, ==, i);
    583        i++;
    584    }
    585
    586    i = 0;
    587    for (num_list = arrs->number; num_list; num_list = num_list->next) {
    588        char expected[32], actual[32];
    589
    590        sprintf(expected, "%.6f", (double)i / 3);
    591        sprintf(actual, "%.6f", num_list->value);
    592        g_assert_cmpstr(expected, ==, actual);
    593        i++;
    594    }
    595
    596    i = 0;
    597    for (bool_list = arrs->boolean; bool_list; bool_list = bool_list->next) {
    598        g_assert_cmpint(bool_list->value, ==, i % 3 == 0);
    599        i++;
    600    }
    601
    602    i = 0;
    603    for (str_list = arrs->string; str_list; str_list = str_list->next) {
    604        char expected[32];
    605
    606        sprintf(expected, "%d", i);
    607        g_assert_cmpstr(str_list->value, ==, expected);
    608        i++;
    609    }
    610}
    611
    612static void test_visitor_in_any(TestInputVisitorData *data,
    613                                const void *unused)
    614{
    615    QObject *res = NULL;
    616    Visitor *v;
    617    QNum *qnum;
    618    QBool *qbool;
    619    QString *qstring;
    620    QDict *qdict;
    621    QObject *qobj;
    622    int64_t val;
    623
    624    v = visitor_input_test_init(data, "-42");
    625    visit_type_any(v, NULL, &res, &error_abort);
    626    qnum = qobject_to(QNum, res);
    627    g_assert(qnum);
    628    g_assert(qnum_get_try_int(qnum, &val));
    629    g_assert_cmpint(val, ==, -42);
    630    qobject_unref(res);
    631
    632    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
    633    visit_type_any(v, NULL, &res, &error_abort);
    634    qdict = qobject_to(QDict, res);
    635    g_assert(qdict && qdict_size(qdict) == 3);
    636    qobj = qdict_get(qdict, "integer");
    637    g_assert(qobj);
    638    qnum = qobject_to(QNum, qobj);
    639    g_assert(qnum);
    640    g_assert(qnum_get_try_int(qnum, &val));
    641    g_assert_cmpint(val, ==, -42);
    642    qobj = qdict_get(qdict, "boolean");
    643    g_assert(qobj);
    644    qbool = qobject_to(QBool, qobj);
    645    g_assert(qbool);
    646    g_assert(qbool_get_bool(qbool) == true);
    647    qobj = qdict_get(qdict, "string");
    648    g_assert(qobj);
    649    qstring = qobject_to(QString, qobj);
    650    g_assert(qstring);
    651    g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
    652    qobject_unref(res);
    653}
    654
    655static void test_visitor_in_null(TestInputVisitorData *data,
    656                                 const void *unused)
    657{
    658    Visitor *v;
    659    Error *err = NULL;
    660    QNull *null;
    661    char *tmp;
    662
    663    /*
    664     * FIXME: Since QAPI doesn't know the 'null' type yet, we can't
    665     * test visit_type_null() by reading into a QAPI struct then
    666     * checking that it was populated correctly.  The best we can do
    667     * for now is ensure that we consumed null from the input, proven
    668     * by the fact that we can't re-read the key; and that we detect
    669     * when input is not null.
    670     */
    671
    672    v = visitor_input_test_init_full(data, false,
    673                                     "{ 'a': null, 'b': '' }");
    674    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    675    visit_type_null(v, "a", &null, &error_abort);
    676    g_assert(qobject_type(QOBJECT(null)) == QTYPE_QNULL);
    677    qobject_unref(null);
    678    visit_type_null(v, "b", &null, &err);
    679    error_free_or_abort(&err);
    680    g_assert(!null);
    681    visit_type_str(v, "c", &tmp, &err);
    682    error_free_or_abort(&err);
    683    g_assert(!tmp);
    684    visit_check_struct(v, &error_abort);
    685    visit_end_struct(v, NULL);
    686}
    687
    688static void test_visitor_in_union_flat(TestInputVisitorData *data,
    689                                       const void *unused)
    690{
    691    Visitor *v;
    692    g_autoptr(UserDefFlatUnion) tmp = NULL;
    693    UserDefUnionBase *base;
    694
    695    v = visitor_input_test_init(data,
    696                                "{ 'enum1': 'value1', "
    697                                "'integer': 41, "
    698                                "'string': 'str', "
    699                                "'boolean': true }");
    700
    701    visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
    702    g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
    703    g_assert_cmpstr(tmp->string, ==, "str");
    704    g_assert_cmpint(tmp->integer, ==, 41);
    705    g_assert_cmpint(tmp->u.value1.boolean, ==, true);
    706
    707    base = qapi_UserDefFlatUnion_base(tmp);
    708    g_assert(&base->enum1 == &tmp->enum1);
    709}
    710
    711static void test_visitor_in_alternate(TestInputVisitorData *data,
    712                                      const void *unused)
    713{
    714    Visitor *v;
    715    UserDefAlternate *tmp;
    716    WrapAlternate *wrap;
    717
    718    v = visitor_input_test_init(data, "42");
    719    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
    720    g_assert_cmpint(tmp->type, ==, QTYPE_QNUM);
    721    g_assert_cmpint(tmp->u.i, ==, 42);
    722    qapi_free_UserDefAlternate(tmp);
    723
    724    v = visitor_input_test_init(data, "'value1'");
    725    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
    726    g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
    727    g_assert_cmpint(tmp->u.e, ==, ENUM_ONE_VALUE1);
    728    qapi_free_UserDefAlternate(tmp);
    729
    730    v = visitor_input_test_init(data, "null");
    731    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
    732    g_assert_cmpint(tmp->type, ==, QTYPE_QNULL);
    733    qapi_free_UserDefAlternate(tmp);
    734
    735    v = visitor_input_test_init(data, "{'integer':1, 'string':'str', "
    736                                "'enum1':'value1', 'boolean':true}");
    737    visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
    738    g_assert_cmpint(tmp->type, ==, QTYPE_QDICT);
    739    g_assert_cmpint(tmp->u.udfu.integer, ==, 1);
    740    g_assert_cmpstr(tmp->u.udfu.string, ==, "str");
    741    g_assert_cmpint(tmp->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
    742    g_assert_cmpint(tmp->u.udfu.u.value1.boolean, ==, true);
    743    g_assert_cmpint(tmp->u.udfu.u.value1.has_a_b, ==, false);
    744    qapi_free_UserDefAlternate(tmp);
    745
    746    v = visitor_input_test_init(data, "{ 'alt': 42 }");
    747    visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
    748    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QNUM);
    749    g_assert_cmpint(wrap->alt->u.i, ==, 42);
    750    qapi_free_WrapAlternate(wrap);
    751
    752    v = visitor_input_test_init(data, "{ 'alt': 'value1' }");
    753    visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
    754    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QSTRING);
    755    g_assert_cmpint(wrap->alt->u.e, ==, ENUM_ONE_VALUE1);
    756    qapi_free_WrapAlternate(wrap);
    757
    758    v = visitor_input_test_init(data, "{ 'alt': {'integer':1, 'string':'str', "
    759                                "'enum1':'value1', 'boolean':true} }");
    760    visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
    761    g_assert_cmpint(wrap->alt->type, ==, QTYPE_QDICT);
    762    g_assert_cmpint(wrap->alt->u.udfu.integer, ==, 1);
    763    g_assert_cmpstr(wrap->alt->u.udfu.string, ==, "str");
    764    g_assert_cmpint(wrap->alt->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
    765    g_assert_cmpint(wrap->alt->u.udfu.u.value1.boolean, ==, true);
    766    g_assert_cmpint(wrap->alt->u.udfu.u.value1.has_a_b, ==, false);
    767    qapi_free_WrapAlternate(wrap);
    768}
    769
    770static void test_visitor_in_alternate_number(TestInputVisitorData *data,
    771                                             const void *unused)
    772{
    773    Visitor *v;
    774    Error *err = NULL;
    775    AltEnumBool *aeb;
    776    AltEnumNum *aen;
    777    AltNumEnum *ans;
    778    AltEnumInt *asi;
    779
    780    /* Parsing an int */
    781
    782    v = visitor_input_test_init(data, "42");
    783    visit_type_AltEnumBool(v, NULL, &aeb, &err);
    784    error_free_or_abort(&err);
    785    qapi_free_AltEnumBool(aeb);
    786
    787    v = visitor_input_test_init(data, "42");
    788    visit_type_AltEnumNum(v, NULL, &aen, &error_abort);
    789    g_assert_cmpint(aen->type, ==, QTYPE_QNUM);
    790    g_assert_cmpfloat(aen->u.n, ==, 42);
    791    qapi_free_AltEnumNum(aen);
    792
    793    v = visitor_input_test_init(data, "42");
    794    visit_type_AltNumEnum(v, NULL, &ans, &error_abort);
    795    g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
    796    g_assert_cmpfloat(ans->u.n, ==, 42);
    797    qapi_free_AltNumEnum(ans);
    798
    799    v = visitor_input_test_init(data, "42");
    800    visit_type_AltEnumInt(v, NULL, &asi, &error_abort);
    801    g_assert_cmpint(asi->type, ==, QTYPE_QNUM);
    802    g_assert_cmpint(asi->u.i, ==, 42);
    803    qapi_free_AltEnumInt(asi);
    804
    805    /* Parsing a double */
    806
    807    v = visitor_input_test_init(data, "42.5");
    808    visit_type_AltEnumBool(v, NULL, &aeb, &err);
    809    error_free_or_abort(&err);
    810    qapi_free_AltEnumBool(aeb);
    811
    812    v = visitor_input_test_init(data, "42.5");
    813    visit_type_AltEnumNum(v, NULL, &aen, &error_abort);
    814    g_assert_cmpint(aen->type, ==, QTYPE_QNUM);
    815    g_assert_cmpfloat(aen->u.n, ==, 42.5);
    816    qapi_free_AltEnumNum(aen);
    817
    818    v = visitor_input_test_init(data, "42.5");
    819    visit_type_AltNumEnum(v, NULL, &ans, &error_abort);
    820    g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
    821    g_assert_cmpfloat(ans->u.n, ==, 42.5);
    822    qapi_free_AltNumEnum(ans);
    823
    824    v = visitor_input_test_init(data, "42.5");
    825    visit_type_AltEnumInt(v, NULL, &asi, &err);
    826    error_free_or_abort(&err);
    827    qapi_free_AltEnumInt(asi);
    828}
    829
    830static void input_visitor_test_add(const char *testpath,
    831                                   const void *user_data,
    832                                   void (*test_func)(TestInputVisitorData *data,
    833                                                     const void *user_data))
    834{
    835    g_test_add(testpath, TestInputVisitorData, user_data, NULL, test_func,
    836               visitor_input_teardown);
    837}
    838
    839static void test_visitor_in_errors(TestInputVisitorData *data,
    840                                   const void *unused)
    841{
    842    TestStruct *p = NULL;
    843    Error *err = NULL;
    844    Visitor *v;
    845    strList *q = NULL;
    846    UserDefTwo *r = NULL;
    847    WrapAlternate *s = NULL;
    848
    849    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
    850                                "'string': -42 }");
    851
    852    visit_type_TestStruct(v, NULL, &p, &err);
    853    error_free_or_abort(&err);
    854    g_assert(!p);
    855
    856    v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
    857    visit_type_strList(v, NULL, &q, &err);
    858    error_free_or_abort(&err);
    859    assert(!q);
    860
    861    v = visitor_input_test_init(data, "{ 'str':'hi' }");
    862    visit_type_UserDefTwo(v, NULL, &r, &err);
    863    error_free_or_abort(&err);
    864    assert(!r);
    865
    866    v = visitor_input_test_init(data, "{ }");
    867    visit_type_WrapAlternate(v, NULL, &s, &err);
    868    error_free_or_abort(&err);
    869    assert(!s);
    870}
    871
    872static void test_visitor_in_wrong_type(TestInputVisitorData *data,
    873                                       const void *unused)
    874{
    875    TestStruct *p = NULL;
    876    Visitor *v;
    877    strList *q = NULL;
    878    int64_t i;
    879    Error *err = NULL;
    880
    881    /* Make sure arrays and structs cannot be confused */
    882
    883    v = visitor_input_test_init(data, "[]");
    884    visit_type_TestStruct(v, NULL, &p, &err);
    885    error_free_or_abort(&err);
    886    g_assert(!p);
    887
    888    v = visitor_input_test_init(data, "{}");
    889    visit_type_strList(v, NULL, &q, &err);
    890    error_free_or_abort(&err);
    891    assert(!q);
    892
    893    /* Make sure primitives and struct cannot be confused */
    894
    895    v = visitor_input_test_init(data, "1");
    896    visit_type_TestStruct(v, NULL, &p, &err);
    897    error_free_or_abort(&err);
    898    g_assert(!p);
    899
    900    v = visitor_input_test_init(data, "{}");
    901    visit_type_int(v, NULL, &i, &err);
    902    error_free_or_abort(&err);
    903
    904    /* Make sure primitives and arrays cannot be confused */
    905
    906    v = visitor_input_test_init(data, "1");
    907    visit_type_strList(v, NULL, &q, &err);
    908    error_free_or_abort(&err);
    909    assert(!q);
    910
    911    v = visitor_input_test_init(data, "[]");
    912    visit_type_int(v, NULL, &i, &err);
    913    error_free_or_abort(&err);
    914}
    915
    916static void test_visitor_in_fail_struct(TestInputVisitorData *data,
    917                                        const void *unused)
    918{
    919    TestStruct *p = NULL;
    920    Error *err = NULL;
    921    Visitor *v;
    922
    923    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
    924
    925    visit_type_TestStruct(v, NULL, &p, &err);
    926    error_free_or_abort(&err);
    927    g_assert(!p);
    928}
    929
    930static void test_visitor_in_fail_struct_nested(TestInputVisitorData *data,
    931                                               const void *unused)
    932{
    933    UserDefTwo *udp = NULL;
    934    Error *err = NULL;
    935    Visitor *v;
    936
    937    v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
    938
    939    visit_type_UserDefTwo(v, NULL, &udp, &err);
    940    error_free_or_abort(&err);
    941    g_assert(!udp);
    942}
    943
    944static void test_visitor_in_fail_struct_in_list(TestInputVisitorData *data,
    945                                                const void *unused)
    946{
    947    UserDefOneList *head = NULL;
    948    Error *err = NULL;
    949    Visitor *v;
    950
    951    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
    952
    953    visit_type_UserDefOneList(v, NULL, &head, &err);
    954    error_free_or_abort(&err);
    955    g_assert(!head);
    956}
    957
    958static void test_visitor_in_fail_struct_missing(TestInputVisitorData *data,
    959                                                const void *unused)
    960{
    961    Error *err = NULL;
    962    Visitor *v;
    963    QObject *any;
    964    QNull *null;
    965    GenericAlternate *alt;
    966    bool present;
    967    int en;
    968    int64_t i64;
    969    uint32_t u32;
    970    int8_t i8;
    971    char *str;
    972    double dbl;
    973
    974    v = visitor_input_test_init(data, "{ 'sub': [ {} ] }");
    975    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    976    visit_start_struct(v, "struct", NULL, 0, &err);
    977    error_free_or_abort(&err);
    978    visit_start_list(v, "list", NULL, 0, &err);
    979    error_free_or_abort(&err);
    980    visit_start_alternate(v, "alternate", &alt, sizeof(*alt), &err);
    981    error_free_or_abort(&err);
    982    visit_optional(v, "optional", &present);
    983    g_assert(!present);
    984    visit_type_enum(v, "enum", &en, &EnumOne_lookup, &err);
    985    error_free_or_abort(&err);
    986    visit_type_int(v, "i64", &i64, &err);
    987    error_free_or_abort(&err);
    988    visit_type_uint32(v, "u32", &u32, &err);
    989    error_free_or_abort(&err);
    990    visit_type_int8(v, "i8", &i8, &err);
    991    error_free_or_abort(&err);
    992    visit_type_str(v, "i8", &str, &err);
    993    error_free_or_abort(&err);
    994    visit_type_number(v, "dbl", &dbl, &err);
    995    error_free_or_abort(&err);
    996    visit_type_any(v, "any", &any, &err);
    997    error_free_or_abort(&err);
    998    visit_type_null(v, "null", &null, &err);
    999    error_free_or_abort(&err);
   1000    visit_start_list(v, "sub", NULL, 0, &error_abort);
   1001    visit_start_struct(v, NULL, NULL, 0, &error_abort);
   1002    visit_type_int(v, "i64", &i64, &err);
   1003    error_free_or_abort(&err);
   1004    visit_end_struct(v, NULL);
   1005    visit_end_list(v, NULL);
   1006    visit_end_struct(v, NULL);
   1007}
   1008
   1009static void test_visitor_in_fail_list(TestInputVisitorData *data,
   1010                                      const void *unused)
   1011{
   1012    int64_t i64 = -1;
   1013    Error *err = NULL;
   1014    Visitor *v;
   1015
   1016    /* Unvisited list tail */
   1017
   1018    v = visitor_input_test_init(data, "[ 1, 2, 3 ]");
   1019
   1020    visit_start_list(v, NULL, NULL, 0, &error_abort);
   1021    visit_type_int(v, NULL, &i64, &error_abort);
   1022    g_assert_cmpint(i64, ==, 1);
   1023    visit_type_int(v, NULL, &i64, &error_abort);
   1024    g_assert_cmpint(i64, ==, 2);
   1025    visit_check_list(v, &err);
   1026    error_free_or_abort(&err);
   1027    visit_end_list(v, NULL);
   1028
   1029    /* Visit beyond end of list */
   1030    v = visitor_input_test_init(data, "[]");
   1031
   1032    visit_start_list(v, NULL, NULL, 0, &error_abort);
   1033    visit_type_int(v, NULL, &i64, &err);
   1034    error_free_or_abort(&err);
   1035    visit_end_list(v, NULL);
   1036}
   1037
   1038static void test_visitor_in_fail_list_nested(TestInputVisitorData *data,
   1039                                             const void *unused)
   1040{
   1041    int64_t i64 = -1;
   1042    Error *err = NULL;
   1043    Visitor *v;
   1044
   1045    /* Unvisited nested list tail */
   1046
   1047    v = visitor_input_test_init(data, "[ 0, [ 1, 2, 3 ] ]");
   1048
   1049    visit_start_list(v, NULL, NULL, 0, &error_abort);
   1050    visit_type_int(v, NULL, &i64, &error_abort);
   1051    g_assert_cmpint(i64, ==, 0);
   1052    visit_start_list(v, NULL, NULL, 0, &error_abort);
   1053    visit_type_int(v, NULL, &i64, &error_abort);
   1054    g_assert_cmpint(i64, ==, 1);
   1055    visit_check_list(v, &err);
   1056    error_free_or_abort(&err);
   1057    visit_end_list(v, NULL);
   1058    visit_check_list(v, &error_abort);
   1059    visit_end_list(v, NULL);
   1060}
   1061
   1062static void test_visitor_in_fail_union_flat(TestInputVisitorData *data,
   1063                                            const void *unused)
   1064{
   1065    UserDefFlatUnion *tmp = NULL;
   1066    Error *err = NULL;
   1067    Visitor *v;
   1068
   1069    v = visitor_input_test_init(data, "{ 'enum1': 'value2', 'string': 'c', 'integer': 41, 'boolean': true }");
   1070
   1071    visit_type_UserDefFlatUnion(v, NULL, &tmp, &err);
   1072    error_free_or_abort(&err);
   1073    g_assert(!tmp);
   1074}
   1075
   1076static void test_visitor_in_fail_union_flat_no_discrim(TestInputVisitorData *data,
   1077                                                       const void *unused)
   1078{
   1079    UserDefFlatUnion2 *tmp = NULL;
   1080    Error *err = NULL;
   1081    Visitor *v;
   1082
   1083    /* test situation where discriminator field ('enum1' here) is missing */
   1084    v = visitor_input_test_init(data, "{ 'integer': 42, 'string': 'c', 'string1': 'd', 'string2': 'e' }");
   1085
   1086    visit_type_UserDefFlatUnion2(v, NULL, &tmp, &err);
   1087    error_free_or_abort(&err);
   1088    g_assert(!tmp);
   1089}
   1090
   1091static void test_visitor_in_fail_alternate(TestInputVisitorData *data,
   1092                                           const void *unused)
   1093{
   1094    UserDefAlternate *tmp;
   1095    Visitor *v;
   1096    Error *err = NULL;
   1097
   1098    v = visitor_input_test_init(data, "3.14");
   1099
   1100    visit_type_UserDefAlternate(v, NULL, &tmp, &err);
   1101    error_free_or_abort(&err);
   1102    g_assert(!tmp);
   1103}
   1104
   1105static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data,
   1106                                              const QLitObject *qlit)
   1107{
   1108    g_autoptr(SchemaInfoList) schema = NULL;
   1109    QObject *obj = qobject_from_qlit(qlit);
   1110    Visitor *v;
   1111
   1112    v = qobject_input_visitor_new(obj);
   1113
   1114    visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
   1115    g_assert(schema);
   1116
   1117    qobject_unref(obj);
   1118    visit_free(v);
   1119}
   1120
   1121static void test_visitor_in_qmp_introspect(TestInputVisitorData *data,
   1122                                           const void *unused)
   1123{
   1124    do_test_visitor_in_qmp_introspect(data, &test_qmp_schema_qlit);
   1125}
   1126
   1127int main(int argc, char **argv)
   1128{
   1129    g_test_init(&argc, &argv, NULL);
   1130
   1131    input_visitor_test_add("/visitor/input/int",
   1132                           NULL, test_visitor_in_int);
   1133    input_visitor_test_add("/visitor/input/uint",
   1134                           NULL, test_visitor_in_uint);
   1135    input_visitor_test_add("/visitor/input/int_overflow",
   1136                           NULL, test_visitor_in_int_overflow);
   1137    input_visitor_test_add("/visitor/input/int_keyval",
   1138                           NULL, test_visitor_in_int_keyval);
   1139    input_visitor_test_add("/visitor/input/int_str_keyval",
   1140                           NULL, test_visitor_in_int_str_keyval);
   1141    input_visitor_test_add("/visitor/input/int_str_fail",
   1142                           NULL, test_visitor_in_int_str_fail);
   1143    input_visitor_test_add("/visitor/input/bool",
   1144                           NULL, test_visitor_in_bool);
   1145    input_visitor_test_add("/visitor/input/bool_keyval",
   1146                           NULL, test_visitor_in_bool_keyval);
   1147    input_visitor_test_add("/visitor/input/bool_str_keyval",
   1148                           NULL, test_visitor_in_bool_str_keyval);
   1149    input_visitor_test_add("/visitor/input/bool_str_fail",
   1150                           NULL, test_visitor_in_bool_str_fail);
   1151    input_visitor_test_add("/visitor/input/number",
   1152                           NULL, test_visitor_in_number);
   1153    input_visitor_test_add("/visitor/input/large_number",
   1154                           NULL, test_visitor_in_large_number);
   1155    input_visitor_test_add("/visitor/input/number_keyval",
   1156                           NULL, test_visitor_in_number_keyval);
   1157    input_visitor_test_add("/visitor/input/number_str_keyval",
   1158                           NULL, test_visitor_in_number_str_keyval);
   1159    input_visitor_test_add("/visitor/input/number_str_fail",
   1160                           NULL, test_visitor_in_number_str_fail);
   1161    input_visitor_test_add("/visitor/input/size_str_keyval",
   1162                           NULL, test_visitor_in_size_str_keyval);
   1163    input_visitor_test_add("/visitor/input/size_str_fail",
   1164                           NULL, test_visitor_in_size_str_fail);
   1165    input_visitor_test_add("/visitor/input/string",
   1166                           NULL, test_visitor_in_string);
   1167    input_visitor_test_add("/visitor/input/enum",
   1168                           NULL, test_visitor_in_enum);
   1169    input_visitor_test_add("/visitor/input/struct",
   1170                           NULL, test_visitor_in_struct);
   1171    input_visitor_test_add("/visitor/input/struct-nested",
   1172                           NULL, test_visitor_in_struct_nested);
   1173    input_visitor_test_add("/visitor/input/list2",
   1174                           NULL, test_visitor_in_list_struct);
   1175    input_visitor_test_add("/visitor/input/list",
   1176                           NULL, test_visitor_in_list);
   1177    input_visitor_test_add("/visitor/input/any",
   1178                           NULL, test_visitor_in_any);
   1179    input_visitor_test_add("/visitor/input/null",
   1180                           NULL, test_visitor_in_null);
   1181    input_visitor_test_add("/visitor/input/union-flat",
   1182                           NULL, test_visitor_in_union_flat);
   1183    input_visitor_test_add("/visitor/input/alternate",
   1184                           NULL, test_visitor_in_alternate);
   1185    input_visitor_test_add("/visitor/input/errors",
   1186                           NULL, test_visitor_in_errors);
   1187    input_visitor_test_add("/visitor/input/wrong-type",
   1188                           NULL, test_visitor_in_wrong_type);
   1189    input_visitor_test_add("/visitor/input/alternate-number",
   1190                           NULL, test_visitor_in_alternate_number);
   1191    input_visitor_test_add("/visitor/input/fail/struct",
   1192                           NULL, test_visitor_in_fail_struct);
   1193    input_visitor_test_add("/visitor/input/fail/struct-nested",
   1194                           NULL, test_visitor_in_fail_struct_nested);
   1195    input_visitor_test_add("/visitor/input/fail/struct-in-list",
   1196                           NULL, test_visitor_in_fail_struct_in_list);
   1197    input_visitor_test_add("/visitor/input/fail/struct-missing",
   1198                           NULL, test_visitor_in_fail_struct_missing);
   1199    input_visitor_test_add("/visitor/input/fail/list",
   1200                           NULL, test_visitor_in_fail_list);
   1201    input_visitor_test_add("/visitor/input/fail/list-nested",
   1202                           NULL, test_visitor_in_fail_list_nested);
   1203    input_visitor_test_add("/visitor/input/fail/union-flat",
   1204                           NULL, test_visitor_in_fail_union_flat);
   1205    input_visitor_test_add("/visitor/input/fail/union-flat-no-discriminator",
   1206                           NULL, test_visitor_in_fail_union_flat_no_discrim);
   1207    input_visitor_test_add("/visitor/input/fail/alternate",
   1208                           NULL, test_visitor_in_fail_alternate);
   1209    input_visitor_test_add("/visitor/input/qapi-introspect",
   1210                           NULL, test_visitor_in_qmp_introspect);
   1211
   1212    g_test_run();
   1213
   1214    return 0;
   1215}