qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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/keyval.h"
     23 
     24 static 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 
    254 static 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 
    270 static 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 
    321 static 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 
    350 static 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 
    430 static 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 
    570 static 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 
    610 static 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 
    663 static 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 
    692 static 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 
    722 static 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 
    750 static 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 
    768 static 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 
    786 static 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 
    805 int 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 }