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-keyval.c (29413B)


      1/*
      2 * Unit tests for parsing of KEY=VALUE,... strings
      3 *
      4 * Copyright (C) 2017 Red Hat Inc.
      5 *
      6 * Authors:
      7 *  Markus Armbruster <armbru@redhat.com>,
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10 * See the COPYING file in the top-level directory.
     11 */
     12
     13#include "qemu/osdep.h"
     14#include "qemu/units.h"
     15#include "qapi/error.h"
     16#include "qapi/qmp/qdict.h"
     17#include "qapi/qmp/qlist.h"
     18#include "qapi/qmp/qstring.h"
     19#include "qapi/qobject-input-visitor.h"
     20#include "test-qapi-visit.h"
     21#include "qemu/cutils.h"
     22#include "qemu/option.h"
     23
     24static void test_keyval_parse(void)
     25{
     26    Error *err = NULL;
     27    QDict *qdict, *sub_qdict;
     28    char long_key[129];
     29    char *params;
     30    bool help;
     31
     32    /* Nothing */
     33    qdict = keyval_parse("", NULL, NULL, &error_abort);
     34    g_assert_cmpuint(qdict_size(qdict), ==, 0);
     35    qobject_unref(qdict);
     36
     37    /* Empty key (qemu_opts_parse() accepts this) */
     38    qdict = keyval_parse("=val", NULL, NULL, &err);
     39    error_free_or_abort(&err);
     40    g_assert(!qdict);
     41
     42    /* Empty key fragment */
     43    qdict = keyval_parse(".", NULL, NULL, &err);
     44    error_free_or_abort(&err);
     45    g_assert(!qdict);
     46    qdict = keyval_parse("key.", NULL, NULL, &err);
     47    error_free_or_abort(&err);
     48    g_assert(!qdict);
     49
     50    /* Invalid non-empty key (qemu_opts_parse() doesn't care) */
     51    qdict = keyval_parse("7up=val", NULL, NULL, &err);
     52    error_free_or_abort(&err);
     53    g_assert(!qdict);
     54
     55    /* Overlong key */
     56    memset(long_key, 'a', 127);
     57    long_key[127] = 'z';
     58    long_key[128] = 0;
     59    params = g_strdup_printf("k.%s=v", long_key);
     60    qdict = keyval_parse(params + 2, NULL, NULL, &err);
     61    error_free_or_abort(&err);
     62    g_assert(!qdict);
     63
     64    /* Overlong key fragment */
     65    qdict = keyval_parse(params, NULL, NULL, &err);
     66    error_free_or_abort(&err);
     67    g_assert(!qdict);
     68    g_free(params);
     69
     70    /* Long key (qemu_opts_parse() accepts and truncates silently) */
     71    params = g_strdup_printf("k.%s=v", long_key + 1);
     72    qdict = keyval_parse(params + 2, NULL, NULL, &error_abort);
     73    g_assert_cmpuint(qdict_size(qdict), ==, 1);
     74    g_assert_cmpstr(qdict_get_try_str(qdict, long_key + 1), ==, "v");
     75    qobject_unref(qdict);
     76
     77    /* Long key fragment */
     78    qdict = keyval_parse(params, NULL, NULL, &error_abort);
     79    g_assert_cmpuint(qdict_size(qdict), ==, 1);
     80    sub_qdict = qdict_get_qdict(qdict, "k");
     81    g_assert(sub_qdict);
     82    g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
     83    g_assert_cmpstr(qdict_get_try_str(sub_qdict, long_key + 1), ==, "v");
     84    qobject_unref(qdict);
     85    g_free(params);
     86
     87    /* Crap after valid key */
     88    qdict = keyval_parse("key[0]=val", NULL, NULL, &err);
     89    error_free_or_abort(&err);
     90    g_assert(!qdict);
     91
     92    /* Multiple keys, last one wins */
     93    qdict = keyval_parse("a=1,b=2,,x,a=3", NULL, NULL, &error_abort);
     94    g_assert_cmpuint(qdict_size(qdict), ==, 2);
     95    g_assert_cmpstr(qdict_get_try_str(qdict, "a"), ==, "3");
     96    g_assert_cmpstr(qdict_get_try_str(qdict, "b"), ==, "2,x");
     97    qobject_unref(qdict);
     98
     99    /* Even when it doesn't in qemu_opts_parse() */
    100    qdict = keyval_parse("id=foo,id=bar", NULL, NULL, &error_abort);
    101    g_assert_cmpuint(qdict_size(qdict), ==, 1);
    102    g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "bar");
    103    qobject_unref(qdict);
    104
    105    /* Dotted keys */
    106    qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, NULL, &error_abort);
    107    g_assert_cmpuint(qdict_size(qdict), ==, 2);
    108    sub_qdict = qdict_get_qdict(qdict, "a");
    109    g_assert(sub_qdict);
    110    g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
    111    sub_qdict = qdict_get_qdict(sub_qdict, "b");
    112    g_assert(sub_qdict);
    113    g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
    114    g_assert_cmpstr(qdict_get_try_str(sub_qdict, "c"), ==, "2");
    115    g_assert_cmpstr(qdict_get_try_str(qdict, "d"), ==, "3");
    116    qobject_unref(qdict);
    117
    118    /* Inconsistent dotted keys */
    119    qdict = keyval_parse("a.b=1,a=2", NULL, NULL, &err);
    120    error_free_or_abort(&err);
    121    g_assert(!qdict);
    122    qdict = keyval_parse("a.b=1,a.b.c=2", NULL, NULL, &err);
    123    error_free_or_abort(&err);
    124    g_assert(!qdict);
    125
    126    /* Trailing comma is ignored */
    127    qdict = keyval_parse("x=y,", NULL, NULL, &error_abort);
    128    g_assert_cmpuint(qdict_size(qdict), ==, 1);
    129    g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, "y");
    130    qobject_unref(qdict);
    131
    132    /* Except when it isn't */
    133    qdict = keyval_parse(",", NULL, NULL, &err);
    134    error_free_or_abort(&err);
    135    g_assert(!qdict);
    136
    137    /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */
    138    qdict = keyval_parse("x=,,id=bar", NULL, NULL, &error_abort);
    139    g_assert_cmpuint(qdict_size(qdict), ==, 1);
    140    g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, ",id=bar");
    141    qobject_unref(qdict);
    142
    143    /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */
    144    qdict = keyval_parse("id=666", NULL, NULL, &error_abort);
    145    g_assert_cmpuint(qdict_size(qdict), ==, 1);
    146    g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "666");
    147    qobject_unref(qdict);
    148
    149    /* Implied value not supported (unlike qemu_opts_parse()) */
    150    qdict = keyval_parse("an,noaus,noaus=", NULL, NULL, &err);
    151    error_free_or_abort(&err);
    152    g_assert(!qdict);
    153
    154    /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */
    155    qdict = keyval_parse("no", NULL, NULL, &err);
    156    error_free_or_abort(&err);
    157    g_assert(!qdict);
    158
    159    /* Implied key */
    160    qdict = keyval_parse("an,aus=off,noaus=", "implied", NULL, &error_abort);
    161    g_assert_cmpuint(qdict_size(qdict), ==, 3);
    162    g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "an");
    163    g_assert_cmpstr(qdict_get_try_str(qdict, "aus"), ==, "off");
    164    g_assert_cmpstr(qdict_get_try_str(qdict, "noaus"), ==, "");
    165    qobject_unref(qdict);
    166
    167    /* Implied dotted key */
    168    qdict = keyval_parse("val", "eins.zwei", NULL, &error_abort);
    169    g_assert_cmpuint(qdict_size(qdict), ==, 1);
    170    sub_qdict = qdict_get_qdict(qdict, "eins");
    171    g_assert(sub_qdict);
    172    g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
    173    g_assert_cmpstr(qdict_get_try_str(sub_qdict, "zwei"), ==, "val");
    174    qobject_unref(qdict);
    175
    176    /* Implied key with empty value (qemu_opts_parse() accepts this) */
    177    qdict = keyval_parse(",", "implied", NULL, &err);
    178    error_free_or_abort(&err);
    179    g_assert(!qdict);
    180
    181    /* Likewise (qemu_opts_parse(): implied key with comma value) */
    182    qdict = keyval_parse(",,,a=1", "implied", NULL, &err);
    183    error_free_or_abort(&err);
    184    g_assert(!qdict);
    185
    186    /* Implied key's value can't have comma (qemu_opts_parse(): it can) */
    187    qdict = keyval_parse("val,,ue", "implied", NULL, &err);
    188    error_free_or_abort(&err);
    189    g_assert(!qdict);
    190
    191    /* Empty key is not an implied key */
    192    qdict = keyval_parse("=val", "implied", NULL, &err);
    193    error_free_or_abort(&err);
    194    g_assert(!qdict);
    195
    196    /* "help" by itself, without implied key */
    197    qdict = keyval_parse("help", NULL, &help, &error_abort);
    198    g_assert_cmpuint(qdict_size(qdict), ==, 0);
    199    g_assert(help);
    200    qobject_unref(qdict);
    201
    202    /* "help" by itself, with implied key */
    203    qdict = keyval_parse("help", "implied", &help, &error_abort);
    204    g_assert_cmpuint(qdict_size(qdict), ==, 0);
    205    g_assert(help);
    206    qobject_unref(qdict);
    207
    208    /* "help" when no help is available, without implied key */
    209    qdict = keyval_parse("help", NULL, NULL, &err);
    210    error_free_or_abort(&err);
    211    g_assert(!qdict);
    212
    213    /* "help" when no help is available, with implied key */
    214    qdict = keyval_parse("help", "implied", NULL, &err);
    215    error_free_or_abort(&err);
    216    g_assert(!qdict);
    217
    218    /* Key "help" */
    219    qdict = keyval_parse("help=on", NULL, &help, &error_abort);
    220    g_assert_cmpuint(qdict_size(qdict), ==, 1);
    221    g_assert_cmpstr(qdict_get_try_str(qdict, "help"), ==, "on");
    222    g_assert(!help);
    223    qobject_unref(qdict);
    224
    225    /* "help" followed by crap, without implied key */
    226    qdict = keyval_parse("help.abc", NULL, &help, &err);
    227    error_free_or_abort(&err);
    228    g_assert(!qdict);
    229
    230    /* "help" followed by crap, with implied key */
    231    qdict = keyval_parse("help.abc", "implied", &help, &err);
    232    g_assert_cmpuint(qdict_size(qdict), ==, 1);
    233    g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "help.abc");
    234    g_assert(!help);
    235    qobject_unref(qdict);
    236
    237    /* "help" with other stuff, without implied key */
    238    qdict = keyval_parse("number=42,help,foo=bar", NULL, &help, &error_abort);
    239    g_assert_cmpuint(qdict_size(qdict), ==, 2);
    240    g_assert_cmpstr(qdict_get_try_str(qdict, "number"), ==, "42");
    241    g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar");
    242    g_assert(help);
    243    qobject_unref(qdict);
    244
    245    /* "help" with other stuff, with implied key */
    246    qdict = keyval_parse("val,help,foo=bar", "implied", &help, &error_abort);
    247    g_assert_cmpuint(qdict_size(qdict), ==, 2);
    248    g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "val");
    249    g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar");
    250    g_assert(help);
    251    qobject_unref(qdict);
    252}
    253
    254static void check_list012(QList *qlist)
    255{
    256    static const char *expected[] = { "null", "eins", "zwei" };
    257    int i;
    258    QString *qstr;
    259
    260    g_assert(qlist);
    261    for (i = 0; i < ARRAY_SIZE(expected); i++) {
    262        qstr = qobject_to(QString, qlist_pop(qlist));
    263        g_assert(qstr);
    264        g_assert_cmpstr(qstring_get_str(qstr), ==, expected[i]);
    265        qobject_unref(qstr);
    266    }
    267    g_assert(qlist_empty(qlist));
    268}
    269
    270static void test_keyval_parse_list(void)
    271{
    272    Error *err = NULL;
    273    QDict *qdict, *sub_qdict;
    274
    275    /* Root can't be a list */
    276    qdict = keyval_parse("0=1", NULL, NULL, &err);
    277    error_free_or_abort(&err);
    278    g_assert(!qdict);
    279
    280    /* List elements need not be in order */
    281    qdict = keyval_parse("list.0=null,list.2=zwei,list.1=eins", NULL, NULL,
    282                         &error_abort);
    283    g_assert_cmpint(qdict_size(qdict), ==, 1);
    284    check_list012(qdict_get_qlist(qdict, "list"));
    285    qobject_unref(qdict);
    286
    287    /* Multiple indexes, last one wins */
    288    qdict = keyval_parse("list.1=goner,list.0=null,list.01=eins,list.2=zwei",
    289                         NULL, NULL, &error_abort);
    290    g_assert_cmpint(qdict_size(qdict), ==, 1);
    291    check_list012(qdict_get_qlist(qdict, "list"));
    292    qobject_unref(qdict);
    293
    294    /* List at deeper nesting */
    295    qdict = keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei", NULL,
    296                         NULL, &error_abort);
    297    g_assert_cmpint(qdict_size(qdict), ==, 1);
    298    sub_qdict = qdict_get_qdict(qdict, "a");
    299    g_assert_cmpint(qdict_size(sub_qdict), ==, 1);
    300    check_list012(qdict_get_qlist(sub_qdict, "list"));
    301    qobject_unref(qdict);
    302
    303    /* Inconsistent dotted keys: both list and dictionary */
    304    qdict = keyval_parse("a.b.c=1,a.b.0=2", NULL, NULL, &err);
    305    error_free_or_abort(&err);
    306    g_assert(!qdict);
    307    qdict = keyval_parse("a.0.c=1,a.b.c=2", NULL, NULL, &err);
    308    error_free_or_abort(&err);
    309    g_assert(!qdict);
    310
    311    /* Missing list indexes */
    312    qdict = keyval_parse("list.1=lonely", NULL, NULL, &err);
    313    error_free_or_abort(&err);
    314    g_assert(!qdict);
    315    qdict = keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL, NULL,
    316                         &err);
    317    error_free_or_abort(&err);
    318    g_assert(!qdict);
    319}
    320
    321static void test_keyval_visit_bool(void)
    322{
    323    Error *err = NULL;
    324    Visitor *v;
    325    QDict *qdict;
    326    bool b;
    327
    328    qdict = keyval_parse("bool1=on,bool2=off", NULL, NULL, &error_abort);
    329    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    330    qobject_unref(qdict);
    331    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    332    visit_type_bool(v, "bool1", &b, &error_abort);
    333    g_assert(b);
    334    visit_type_bool(v, "bool2", &b, &error_abort);
    335    g_assert(!b);
    336    visit_check_struct(v, &error_abort);
    337    visit_end_struct(v, NULL);
    338    visit_free(v);
    339
    340    qdict = keyval_parse("bool1=offer", NULL, NULL, &error_abort);
    341    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    342    qobject_unref(qdict);
    343    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    344    visit_type_bool(v, "bool1", &b, &err);
    345    error_free_or_abort(&err);
    346    visit_end_struct(v, NULL);
    347    visit_free(v);
    348}
    349
    350static void test_keyval_visit_number(void)
    351{
    352    Error *err = NULL;
    353    Visitor *v;
    354    QDict *qdict;
    355    uint64_t u;
    356
    357    /* Lower limit zero */
    358    qdict = keyval_parse("number1=0", NULL, NULL, &error_abort);
    359    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    360    qobject_unref(qdict);
    361    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    362    visit_type_uint64(v, "number1", &u, &error_abort);
    363    g_assert_cmpuint(u, ==, 0);
    364    visit_check_struct(v, &error_abort);
    365    visit_end_struct(v, NULL);
    366    visit_free(v);
    367
    368    /* Upper limit 2^64-1 */
    369    qdict = keyval_parse("number1=18446744073709551615,number2=-1", NULL,
    370                         NULL, &error_abort);
    371    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    372    qobject_unref(qdict);
    373    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    374    visit_type_uint64(v, "number1", &u, &error_abort);
    375    g_assert_cmphex(u, ==, UINT64_MAX);
    376    visit_type_uint64(v, "number2", &u, &error_abort);
    377    g_assert_cmphex(u, ==, UINT64_MAX);
    378    visit_check_struct(v, &error_abort);
    379    visit_end_struct(v, NULL);
    380    visit_free(v);
    381
    382    /* Above upper limit */
    383    qdict = keyval_parse("number1=18446744073709551616", NULL, NULL,
    384                         &error_abort);
    385    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    386    qobject_unref(qdict);
    387    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    388    visit_type_uint64(v, "number1", &u, &err);
    389    error_free_or_abort(&err);
    390    visit_end_struct(v, NULL);
    391    visit_free(v);
    392
    393    /* Below lower limit */
    394    qdict = keyval_parse("number1=-18446744073709551616", NULL, NULL,
    395                         &error_abort);
    396    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    397    qobject_unref(qdict);
    398    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    399    visit_type_uint64(v, "number1", &u, &err);
    400    error_free_or_abort(&err);
    401    visit_end_struct(v, NULL);
    402    visit_free(v);
    403
    404    /* Hex and octal */
    405    qdict = keyval_parse("number1=0x2a,number2=052", NULL, NULL, &error_abort);
    406    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    407    qobject_unref(qdict);
    408    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    409    visit_type_uint64(v, "number1", &u, &error_abort);
    410    g_assert_cmpuint(u, ==, 42);
    411    visit_type_uint64(v, "number2", &u, &error_abort);
    412    g_assert_cmpuint(u, ==, 42);
    413    visit_check_struct(v, &error_abort);
    414    visit_end_struct(v, NULL);
    415    visit_free(v);
    416
    417    /* Trailing crap */
    418    qdict = keyval_parse("number1=3.14,number2=08", NULL, NULL, &error_abort);
    419    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    420    qobject_unref(qdict);
    421    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    422    visit_type_uint64(v, "number1", &u, &err);
    423    error_free_or_abort(&err);
    424    visit_type_uint64(v, "number2", &u, &err);
    425    error_free_or_abort(&err);
    426    visit_end_struct(v, NULL);
    427    visit_free(v);
    428}
    429
    430static void test_keyval_visit_size(void)
    431{
    432    Error *err = NULL;
    433    Visitor *v;
    434    QDict *qdict;
    435    uint64_t sz;
    436
    437    /* Lower limit zero */
    438    qdict = keyval_parse("sz1=0", NULL, NULL, &error_abort);
    439    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    440    qobject_unref(qdict);
    441    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    442    visit_type_size(v, "sz1", &sz, &error_abort);
    443    g_assert_cmpuint(sz, ==, 0);
    444    visit_check_struct(v, &error_abort);
    445    visit_end_struct(v, NULL);
    446    visit_free(v);
    447
    448    /* Note: full 64 bits of precision */
    449
    450    /* Around double limit of precision: 2^53-1, 2^53, 2^53+1 */
    451    qdict = keyval_parse("sz1=9007199254740991,"
    452                         "sz2=9007199254740992,"
    453                         "sz3=9007199254740993",
    454                         NULL, NULL, &error_abort);
    455    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    456    qobject_unref(qdict);
    457    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    458    visit_type_size(v, "sz1", &sz, &error_abort);
    459    g_assert_cmphex(sz, ==, 0x1fffffffffffff);
    460    visit_type_size(v, "sz2", &sz, &error_abort);
    461    g_assert_cmphex(sz, ==, 0x20000000000000);
    462    visit_type_size(v, "sz3", &sz, &error_abort);
    463    g_assert_cmphex(sz, ==, 0x20000000000001);
    464    visit_check_struct(v, &error_abort);
    465    visit_end_struct(v, NULL);
    466    visit_free(v);
    467
    468    /* Close to signed integer limit 2^63 */
    469    qdict = keyval_parse("sz1=9223372036854775807," /* 7fffffffffffffff */
    470                         "sz2=9223372036854775808," /* 8000000000000000 */
    471                         "sz3=9223372036854775809", /* 8000000000000001 */
    472                         NULL, NULL, &error_abort);
    473    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    474    qobject_unref(qdict);
    475    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    476    visit_type_size(v, "sz1", &sz, &error_abort);
    477    g_assert_cmphex(sz, ==, 0x7fffffffffffffff);
    478    visit_type_size(v, "sz2", &sz, &error_abort);
    479    g_assert_cmphex(sz, ==, 0x8000000000000000);
    480    visit_type_size(v, "sz3", &sz, &error_abort);
    481    g_assert_cmphex(sz, ==, 0x8000000000000001);
    482    visit_check_struct(v, &error_abort);
    483    visit_end_struct(v, NULL);
    484    visit_free(v);
    485
    486    /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
    487    qdict = keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */
    488                         "sz2=18446744073709550591", /* fffffffffffffbff */
    489                         NULL, NULL, &error_abort);
    490    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    491    qobject_unref(qdict);
    492    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    493    visit_type_size(v, "sz1", &sz, &error_abort);
    494    g_assert_cmphex(sz, ==, 0xfffffffffffff800);
    495    visit_type_size(v, "sz2", &sz, &error_abort);
    496    g_assert_cmphex(sz, ==, 0xfffffffffffffbff);
    497    visit_check_struct(v, &error_abort);
    498    visit_end_struct(v, NULL);
    499    visit_free(v);
    500
    501    /* Actual limit 2^64-1*/
    502    qdict = keyval_parse("sz1=18446744073709551615", /* ffffffffffffffff */
    503                         NULL, NULL, &error_abort);
    504    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    505    qobject_unref(qdict);
    506    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    507    visit_type_size(v, "sz1", &sz, &error_abort);
    508    g_assert_cmphex(sz, ==, 0xffffffffffffffff);
    509    visit_check_struct(v, &error_abort);
    510    visit_end_struct(v, NULL);
    511    visit_free(v);
    512
    513    /* Beyond limits */
    514    qdict = keyval_parse("sz1=-1,"
    515                         "sz2=18446744073709551616", /* 2^64 */
    516                         NULL, NULL, &error_abort);
    517    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    518    qobject_unref(qdict);
    519    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    520    visit_type_size(v, "sz1", &sz, &err);
    521    error_free_or_abort(&err);
    522    visit_type_size(v, "sz2", &sz, &err);
    523    error_free_or_abort(&err);
    524    visit_end_struct(v, NULL);
    525    visit_free(v);
    526
    527    /* Suffixes */
    528    qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
    529                         NULL, NULL, &error_abort);
    530    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    531    qobject_unref(qdict);
    532    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    533    visit_type_size(v, "sz1", &sz, &error_abort);
    534    g_assert_cmpuint(sz, ==, 8);
    535    visit_type_size(v, "sz2", &sz, &error_abort);
    536    g_assert_cmpuint(sz, ==, 1536);
    537    visit_type_size(v, "sz3", &sz, &error_abort);
    538    g_assert_cmphex(sz, ==, 2 * MiB);
    539    visit_type_size(v, "sz4", &sz, &error_abort);
    540    g_assert_cmphex(sz, ==, GiB / 10);
    541    visit_type_size(v, "sz5", &sz, &error_abort);
    542    g_assert_cmphex(sz, ==, 16777215ULL * TiB);
    543    visit_check_struct(v, &error_abort);
    544    visit_end_struct(v, NULL);
    545    visit_free(v);
    546
    547    /* Beyond limit with suffix */
    548    qdict = keyval_parse("sz1=16777216T", NULL, NULL, &error_abort);
    549    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    550    qobject_unref(qdict);
    551    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    552    visit_type_size(v, "sz1", &sz, &err);
    553    error_free_or_abort(&err);
    554    visit_end_struct(v, NULL);
    555    visit_free(v);
    556
    557    /* Trailing crap */
    558    qdict = keyval_parse("sz1=0Z,sz2=16Gi", NULL, NULL, &error_abort);
    559    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    560    qobject_unref(qdict);
    561    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    562    visit_type_size(v, "sz1", &sz, &err);
    563    error_free_or_abort(&err);
    564    visit_type_size(v, "sz2", &sz, &err);
    565    error_free_or_abort(&err);
    566    visit_end_struct(v, NULL);
    567    visit_free(v);
    568}
    569
    570static void test_keyval_visit_dict(void)
    571{
    572    Error *err = NULL;
    573    Visitor *v;
    574    QDict *qdict;
    575    int64_t i;
    576
    577    qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, NULL, &error_abort);
    578    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    579    qobject_unref(qdict);
    580    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    581    visit_start_struct(v, "a", NULL, 0, &error_abort);
    582    visit_start_struct(v, "b", NULL, 0, &error_abort);
    583    visit_type_int(v, "c", &i, &error_abort);
    584    g_assert_cmpint(i, ==, 2);
    585    visit_check_struct(v, &error_abort);
    586    visit_end_struct(v, NULL);
    587    visit_check_struct(v, &error_abort);
    588    visit_end_struct(v, NULL);
    589    visit_type_int(v, "d", &i, &error_abort);
    590    g_assert_cmpint(i, ==, 3);
    591    visit_check_struct(v, &error_abort);
    592    visit_end_struct(v, NULL);
    593    visit_free(v);
    594
    595    qdict = keyval_parse("a.b=", NULL, NULL, &error_abort);
    596    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    597    qobject_unref(qdict);
    598    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    599    visit_start_struct(v, "a", NULL, 0, &error_abort);
    600    visit_type_int(v, "c", &i, &err);   /* a.c missing */
    601    error_free_or_abort(&err);
    602    visit_check_struct(v, &err);
    603    error_free_or_abort(&err);          /* a.b unexpected */
    604    visit_end_struct(v, NULL);
    605    visit_check_struct(v, &error_abort);
    606    visit_end_struct(v, NULL);
    607    visit_free(v);
    608}
    609
    610static void test_keyval_visit_list(void)
    611{
    612    Error *err = NULL;
    613    Visitor *v;
    614    QDict *qdict;
    615    char *s;
    616
    617    qdict = keyval_parse("a.0=,a.1=I,a.2.0=II", NULL, NULL, &error_abort);
    618    /* TODO empty list */
    619    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    620    qobject_unref(qdict);
    621    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    622    visit_start_list(v, "a", NULL, 0, &error_abort);
    623    visit_type_str(v, NULL, &s, &error_abort);
    624    g_assert_cmpstr(s, ==, "");
    625    g_free(s);
    626    visit_type_str(v, NULL, &s, &error_abort);
    627    g_assert_cmpstr(s, ==, "I");
    628    g_free(s);
    629    visit_start_list(v, NULL, NULL, 0, &error_abort);
    630    visit_type_str(v, NULL, &s, &error_abort);
    631    g_assert_cmpstr(s, ==, "II");
    632    g_free(s);
    633    visit_check_list(v, &error_abort);
    634    visit_end_list(v, NULL);
    635    visit_check_list(v, &error_abort);
    636    visit_end_list(v, NULL);
    637    visit_check_struct(v, &error_abort);
    638    visit_end_struct(v, NULL);
    639    visit_free(v);
    640
    641    qdict = keyval_parse("a.0=,b.0.0=head", NULL, NULL, &error_abort);
    642    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    643    qobject_unref(qdict);
    644    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    645    visit_start_list(v, "a", NULL, 0, &error_abort);
    646    visit_check_list(v, &err);  /* a[0] unexpected */
    647    error_free_or_abort(&err);
    648    visit_end_list(v, NULL);
    649    visit_start_list(v, "b", NULL, 0, &error_abort);
    650    visit_start_list(v, NULL, NULL, 0, &error_abort);
    651    visit_type_str(v, NULL, &s, &error_abort);
    652    g_assert_cmpstr(s, ==, "head");
    653    g_free(s);
    654    visit_type_str(v, NULL, &s, &err); /* b[0][1] missing */
    655    error_free_or_abort(&err);
    656    visit_end_list(v, NULL);
    657    visit_end_list(v, NULL);
    658    visit_check_struct(v, &error_abort);
    659    visit_end_struct(v, NULL);
    660    visit_free(v);
    661}
    662
    663static void test_keyval_visit_optional(void)
    664{
    665    Visitor *v;
    666    QDict *qdict;
    667    bool present;
    668    int64_t i;
    669
    670    qdict = keyval_parse("a.b=1", NULL, NULL, &error_abort);
    671    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    672    qobject_unref(qdict);
    673    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    674    visit_optional(v, "b", &present);
    675    g_assert(!present);         /* b missing */
    676    visit_optional(v, "a", &present);
    677    g_assert(present);          /* a present */
    678    visit_start_struct(v, "a", NULL, 0, &error_abort);
    679    visit_optional(v, "b", &present);
    680    g_assert(present);          /* a.b present */
    681    visit_type_int(v, "b", &i, &error_abort);
    682    g_assert_cmpint(i, ==, 1);
    683    visit_optional(v, "a", &present);
    684    g_assert(!present);         /* a.a missing */
    685    visit_check_struct(v, &error_abort);
    686    visit_end_struct(v, NULL);
    687    visit_check_struct(v, &error_abort);
    688    visit_end_struct(v, NULL);
    689    visit_free(v);
    690}
    691
    692static void test_keyval_visit_alternate(void)
    693{
    694    Error *err = NULL;
    695    Visitor *v;
    696    QDict *qdict;
    697    AltStrObj *aso;
    698    AltNumEnum *ane;
    699    AltEnumBool *aeb;
    700
    701    /*
    702     * Can't do scalar alternate variants other than string.  You get
    703     * the string variant if there is one, else an error.
    704     * TODO make it work for unambiguous cases like AltEnumBool below
    705     */
    706    qdict = keyval_parse("a=1,b=2,c=on", NULL, NULL, &error_abort);
    707    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    708    qobject_unref(qdict);
    709    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    710    visit_type_AltStrObj(v, "a", &aso, &error_abort);
    711    g_assert_cmpint(aso->type, ==, QTYPE_QSTRING);
    712    g_assert_cmpstr(aso->u.s, ==, "1");
    713    qapi_free_AltStrObj(aso);
    714    visit_type_AltNumEnum(v, "b", &ane, &err);
    715    error_free_or_abort(&err);
    716    visit_type_AltEnumBool(v, "c", &aeb, &err);
    717    error_free_or_abort(&err);
    718    visit_end_struct(v, NULL);
    719    visit_free(v);
    720}
    721
    722static void test_keyval_visit_any(void)
    723{
    724    Visitor *v;
    725    QDict *qdict;
    726    QObject *any;
    727    QList *qlist;
    728    QString *qstr;
    729
    730    qdict = keyval_parse("a.0=null,a.1=1", NULL, NULL, &error_abort);
    731    v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
    732    qobject_unref(qdict);
    733    visit_start_struct(v, NULL, NULL, 0, &error_abort);
    734    visit_type_any(v, "a", &any, &error_abort);
    735    qlist = qobject_to(QList, any);
    736    g_assert(qlist);
    737    qstr = qobject_to(QString, qlist_pop(qlist));
    738    g_assert_cmpstr(qstring_get_str(qstr), ==, "null");
    739    qobject_unref(qstr);
    740    qstr = qobject_to(QString, qlist_pop(qlist));
    741    g_assert_cmpstr(qstring_get_str(qstr), ==, "1");
    742    g_assert(qlist_empty(qlist));
    743    qobject_unref(qstr);
    744    qobject_unref(any);
    745    visit_check_struct(v, &error_abort);
    746    visit_end_struct(v, NULL);
    747    visit_free(v);
    748}
    749
    750static void test_keyval_merge_dict(void)
    751{
    752    QDict *first = keyval_parse("opt1=abc,opt2.sub1=def,opt2.sub2=ghi,opt3=xyz",
    753                                NULL, NULL, &error_abort);
    754    QDict *second = keyval_parse("opt1=ABC,opt2.sub2=GHI,opt2.sub3=JKL",
    755                                 NULL, NULL, &error_abort);
    756    QDict *combined = keyval_parse("opt1=ABC,opt2.sub1=def,opt2.sub2=GHI,opt2.sub3=JKL,opt3=xyz",
    757                                   NULL, NULL, &error_abort);
    758    Error *err = NULL;
    759
    760    keyval_merge(first, second, &err);
    761    g_assert(!err);
    762    g_assert(qobject_is_equal(QOBJECT(combined), QOBJECT(first)));
    763    qobject_unref(first);
    764    qobject_unref(second);
    765    qobject_unref(combined);
    766}
    767
    768static void test_keyval_merge_list(void)
    769{
    770    QDict *first = keyval_parse("opt1.0=abc,opt2.0=xyz",
    771                                NULL, NULL, &error_abort);
    772    QDict *second = keyval_parse("opt1.0=def",
    773                                 NULL, NULL, &error_abort);
    774    QDict *combined = keyval_parse("opt1.0=abc,opt1.1=def,opt2.0=xyz",
    775                                   NULL, NULL, &error_abort);
    776    Error *err = NULL;
    777
    778    keyval_merge(first, second, &err);
    779    g_assert(!err);
    780    g_assert(qobject_is_equal(QOBJECT(combined), QOBJECT(first)));
    781    qobject_unref(first);
    782    qobject_unref(second);
    783    qobject_unref(combined);
    784}
    785
    786static void test_keyval_merge_conflict(void)
    787{
    788    QDict *first = keyval_parse("opt2=ABC",
    789                                NULL, NULL, &error_abort);
    790    QDict *second = keyval_parse("opt2.sub1=def,opt2.sub2=ghi",
    791                                 NULL, NULL, &error_abort);
    792    QDict *third = qdict_clone_shallow(first);
    793    Error *err = NULL;
    794
    795    keyval_merge(first, second, &err);
    796    error_free_or_abort(&err);
    797    keyval_merge(second, third, &err);
    798    error_free_or_abort(&err);
    799
    800    qobject_unref(first);
    801    qobject_unref(second);
    802    qobject_unref(third);
    803}
    804
    805int main(int argc, char *argv[])
    806{
    807    g_test_init(&argc, &argv, NULL);
    808    g_test_add_func("/keyval/keyval_parse", test_keyval_parse);
    809    g_test_add_func("/keyval/keyval_parse/list", test_keyval_parse_list);
    810    g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool);
    811    g_test_add_func("/keyval/visit/number", test_keyval_visit_number);
    812    g_test_add_func("/keyval/visit/size", test_keyval_visit_size);
    813    g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict);
    814    g_test_add_func("/keyval/visit/list", test_keyval_visit_list);
    815    g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional);
    816    g_test_add_func("/keyval/visit/alternate", test_keyval_visit_alternate);
    817    g_test_add_func("/keyval/visit/any", test_keyval_visit_any);
    818    g_test_add_func("/keyval/merge/dict", test_keyval_merge_dict);
    819    g_test_add_func("/keyval/merge/list", test_keyval_merge_list);
    820    g_test_add_func("/keyval/merge/conflict", test_keyval_merge_conflict);
    821    g_test_run();
    822    return 0;
    823}