qemu

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

test-opts-visitor.c (12193B)


      1 /*
      2  * Options Visitor unit-tests.
      3  *
      4  * Copyright (C) 2013 Red Hat, Inc.
      5  *
      6  * Authors:
      7  *   Laszlo Ersek <lersek@redhat.com> (based on test-string-output-visitor)
      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 
     15 #include "qemu/config-file.h"     /* qemu_add_opts() */
     16 #include "qemu/option.h"          /* qemu_opts_parse() */
     17 #include "qapi/error.h"
     18 #include "qapi/opts-visitor.h"    /* opts_visitor_new() */
     19 #include "test-qapi-visit.h"      /* visit_type_UserDefOptions() */
     20 
     21 static QemuOptsList userdef_opts = {
     22     .name = "userdef",
     23     .head = QTAILQ_HEAD_INITIALIZER(userdef_opts.head),
     24     .desc = { { 0 } } /* validated with OptsVisitor */
     25 };
     26 
     27 /* fixture (= glib test case context) and test case manipulation */
     28 
     29 typedef struct OptsVisitorFixture {
     30     UserDefOptions *userdef;
     31     Error *err;
     32 } OptsVisitorFixture;
     33 
     34 
     35 static void
     36 setup_fixture(OptsVisitorFixture *f, gconstpointer test_data)
     37 {
     38     const char *opts_string = test_data;
     39     QemuOpts *opts;
     40     Visitor *v;
     41 
     42     opts = qemu_opts_parse(qemu_find_opts("userdef"), opts_string, false,
     43                            NULL);
     44     g_assert(opts != NULL);
     45 
     46     v = opts_visitor_new(opts);
     47     visit_type_UserDefOptions(v, NULL, &f->userdef, &f->err);
     48     visit_free(v);
     49     qemu_opts_del(opts);
     50 }
     51 
     52 
     53 static void
     54 teardown_fixture(OptsVisitorFixture *f, gconstpointer test_data)
     55 {
     56     qapi_free_UserDefOptions(f->userdef);
     57     error_free(f->err);
     58 }
     59 
     60 
     61 static void
     62 add_test(const char *testpath,
     63          void (*test_func)(OptsVisitorFixture *f, gconstpointer test_data),
     64          gconstpointer test_data)
     65 {
     66     g_test_add(testpath, OptsVisitorFixture, test_data, setup_fixture,
     67                test_func, teardown_fixture);
     68 }
     69 
     70 /* test output evaluation */
     71 
     72 static void
     73 expect_ok(OptsVisitorFixture *f, gconstpointer test_data)
     74 {
     75     g_assert(f->err == NULL);
     76     g_assert(f->userdef != NULL);
     77 }
     78 
     79 
     80 static void
     81 expect_fail(OptsVisitorFixture *f, gconstpointer test_data)
     82 {
     83     g_assert(f->err != NULL);
     84 
     85     /* The error message is printed when this test utility is invoked directly
     86      * (ie. without gtester) and the --verbose flag is passed:
     87      *
     88      * tests/test-opts-visitor --verbose
     89      */
     90     g_test_message("'%s': %s", (const char *)test_data,
     91                    error_get_pretty(f->err));
     92 }
     93 
     94 
     95 static void
     96 test_value(OptsVisitorFixture *f, gconstpointer test_data)
     97 {
     98     uint64_t magic, bitval;
     99     intList *i64;
    100     uint64List *u64;
    101     uint16List *u16;
    102 
    103     expect_ok(f, test_data);
    104 
    105     magic = 0;
    106     for (i64 = f->userdef->i64; i64 != NULL; i64 = i64->next) {
    107         g_assert(-16 <= i64->value && i64->value < 64-16);
    108         bitval = 1ull << (i64->value + 16);
    109         g_assert((magic & bitval) == 0);
    110         magic |= bitval;
    111     }
    112     g_assert(magic == 0xDEADBEEF);
    113 
    114     magic = 0;
    115     for (u64 = f->userdef->u64; u64 != NULL; u64 = u64->next) {
    116         g_assert(u64->value < 64);
    117         bitval = 1ull << u64->value;
    118         g_assert((magic & bitval) == 0);
    119         magic |= bitval;
    120     }
    121     g_assert(magic == 0xBADC0FFEE0DDF00DULL);
    122 
    123     magic = 0;
    124     for (u16 = f->userdef->u16; u16 != NULL; u16 = u16->next) {
    125         g_assert(u16->value < 64);
    126         bitval = 1ull << u16->value;
    127         g_assert((magic & bitval) == 0);
    128         magic |= bitval;
    129     }
    130     g_assert(magic == 0xD15EA5E);
    131 }
    132 
    133 
    134 static void
    135 expect_i64_min(OptsVisitorFixture *f, gconstpointer test_data)
    136 {
    137     expect_ok(f, test_data);
    138     g_assert(f->userdef->has_i64);
    139     g_assert(f->userdef->i64->next == NULL);
    140     g_assert(f->userdef->i64->value == INT64_MIN);
    141 }
    142 
    143 
    144 static void
    145 expect_i64_max(OptsVisitorFixture *f, gconstpointer test_data)
    146 {
    147     expect_ok(f, test_data);
    148     g_assert(f->userdef->has_i64);
    149     g_assert(f->userdef->i64->next == NULL);
    150     g_assert(f->userdef->i64->value == INT64_MAX);
    151 }
    152 
    153 
    154 static void
    155 expect_zero(OptsVisitorFixture *f, gconstpointer test_data)
    156 {
    157     expect_ok(f, test_data);
    158     g_assert(f->userdef->has_u64);
    159     g_assert(f->userdef->u64->next == NULL);
    160     g_assert(f->userdef->u64->value == 0);
    161 }
    162 
    163 
    164 static void
    165 expect_u64_max(OptsVisitorFixture *f, gconstpointer test_data)
    166 {
    167     expect_ok(f, test_data);
    168     g_assert(f->userdef->has_u64);
    169     g_assert(f->userdef->u64->next == NULL);
    170     g_assert(f->userdef->u64->value == UINT64_MAX);
    171 }
    172 
    173 /* test cases */
    174 
    175 static void
    176 test_opts_range_unvisited(void)
    177 {
    178     Error *err = NULL;
    179     intList *list = NULL;
    180     intList *tail;
    181     QemuOpts *opts;
    182     Visitor *v;
    183 
    184     opts = qemu_opts_parse(qemu_find_opts("userdef"), "ilist=0-2", false,
    185                            &error_abort);
    186 
    187     v = opts_visitor_new(opts);
    188 
    189     visit_start_struct(v, NULL, NULL, 0, &error_abort);
    190 
    191     /* Would be simpler if the visitor genuinely supported virtual walks */
    192     visit_start_list(v, "ilist", (GenericList **)&list, sizeof(*list),
    193                      &error_abort);
    194     tail = list;
    195     visit_type_int(v, NULL, &tail->value, &error_abort);
    196     g_assert_cmpint(tail->value, ==, 0);
    197     tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));
    198     g_assert(tail);
    199     visit_type_int(v, NULL, &tail->value, &error_abort);
    200     g_assert_cmpint(tail->value, ==, 1);
    201     tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*list));
    202     g_assert(tail);
    203     visit_check_list(v, &error_abort); /* unvisited tail ignored until... */
    204     visit_end_list(v, (void **)&list);
    205 
    206     visit_check_struct(v, &err); /* ...here */
    207     error_free_or_abort(&err);
    208     visit_end_struct(v, NULL);
    209 
    210     qapi_free_intList(list);
    211     visit_free(v);
    212     qemu_opts_del(opts);
    213 }
    214 
    215 static void
    216 test_opts_range_beyond(void)
    217 {
    218     Error *err = NULL;
    219     intList *list = NULL;
    220     intList *tail;
    221     QemuOpts *opts;
    222     Visitor *v;
    223     int64_t val;
    224 
    225     opts = qemu_opts_parse(qemu_find_opts("userdef"), "ilist=0", false,
    226                            &error_abort);
    227 
    228     v = opts_visitor_new(opts);
    229 
    230     visit_start_struct(v, NULL, NULL, 0, &error_abort);
    231 
    232     /* Would be simpler if the visitor genuinely supported virtual walks */
    233     visit_start_list(v, "ilist", (GenericList **)&list, sizeof(*list),
    234                      &error_abort);
    235     tail = list;
    236     visit_type_int(v, NULL, &tail->value, &error_abort);
    237     g_assert_cmpint(tail->value, ==, 0);
    238     tail = (intList *)visit_next_list(v, (GenericList *)tail, sizeof(*tail));
    239     g_assert(!tail);
    240     visit_type_int(v, NULL, &val, &err);
    241     error_free_or_abort(&err);
    242     visit_end_list(v, (void **)&list);
    243 
    244     visit_check_struct(v, &error_abort);
    245     visit_end_struct(v, NULL);
    246 
    247     qapi_free_intList(list);
    248     visit_free(v);
    249     qemu_opts_del(opts);
    250 }
    251 
    252 static void
    253 test_opts_dict_unvisited(void)
    254 {
    255     Error *err = NULL;
    256     QemuOpts *opts;
    257     Visitor *v;
    258     UserDefOptions *userdef;
    259 
    260     opts = qemu_opts_parse(qemu_find_opts("userdef"), "i64x=0,bogus=1", false,
    261                            &error_abort);
    262 
    263     v = opts_visitor_new(opts);
    264     visit_type_UserDefOptions(v, NULL, &userdef, &err);
    265     error_free_or_abort(&err);
    266     visit_free(v);
    267     qemu_opts_del(opts);
    268     g_assert(!userdef);
    269 }
    270 
    271 int
    272 main(int argc, char **argv)
    273 {
    274     g_test_init(&argc, &argv, NULL);
    275 
    276     qemu_add_opts(&userdef_opts);
    277 
    278     /* Three hexadecimal magic numbers, "dead beef", "bad coffee, odd food" and
    279      * "disease", from
    280      * <http://en.wikipedia.org/wiki/Magic_number_%28programming%29>, were
    281      * converted to binary and dissected into bit ranges. Each magic number is
    282      * going to be recomposed using the lists called "i64", "u64" and "u16",
    283      * respectively.
    284      *
    285      * (Note that these types pertain to the individual bit shift counts, not
    286      * the magic numbers themselves; the intent is to exercise opts_type_int()
    287      * and opts_type_uint64().)
    288      *
    289      * The "i64" shift counts have been decreased by 16 (decimal) in order to
    290      * test negative values as well. Finally, the full list of QemuOpt elements
    291      * has been permuted with "shuf".
    292      *
    293      * Both "i64" and "u64" have some (distinct) single-element ranges
    294      * represented as both "a" and "a-a". "u16" is a special case of "i64" (see
    295      * visit_type_uint16()), so it wouldn't add a separate test in this regard.
    296      */
    297 
    298     add_test("/visitor/opts/flatten/value", &test_value,
    299              "i64=-1-0,u64=12-16,u64=2-3,i64=-11--9,u64=57,u16=9,i64=5-5,"
    300              "u16=1-4,u16=20,u64=63-63,i64=-16--13,u64=50-52,i64=14-15,u16=11,"
    301              "i64=7,u16=18,i64=2-3,u16=6,u64=54-55,u64=0,u64=18-20,u64=33-43,"
    302              "i64=9-12,u16=26-27,u64=59-61,u16=13-16,u64=29-31,u64=22-23,"
    303              "u16=24,i64=-7--3");
    304 
    305     add_test("/visitor/opts/i64/val1/errno",    &expect_fail,
    306              "i64=0x8000000000000000");
    307     add_test("/visitor/opts/i64/val1/empty",    &expect_fail, "i64=");
    308     add_test("/visitor/opts/i64/val1/trailing", &expect_fail, "i64=5z");
    309     add_test("/visitor/opts/i64/nonlist",       &expect_fail, "i64x=5-6");
    310     add_test("/visitor/opts/i64/val2/errno",    &expect_fail,
    311              "i64=0x7fffffffffffffff-0x8000000000000000");
    312     add_test("/visitor/opts/i64/val2/empty",    &expect_fail, "i64=5-");
    313     add_test("/visitor/opts/i64/val2/trailing", &expect_fail, "i64=5-6z");
    314     add_test("/visitor/opts/i64/range/empty",   &expect_fail, "i64=6-5");
    315     add_test("/visitor/opts/i64/range/minval",  &expect_i64_min,
    316              "i64=-0x8000000000000000--0x8000000000000000");
    317     add_test("/visitor/opts/i64/range/maxval",  &expect_i64_max,
    318              "i64=0x7fffffffffffffff-0x7fffffffffffffff");
    319 
    320     add_test("/visitor/opts/u64/val1/errno",    &expect_fail, "u64=-1");
    321     add_test("/visitor/opts/u64/val1/empty",    &expect_fail, "u64=");
    322     add_test("/visitor/opts/u64/val1/trailing", &expect_fail, "u64=5z");
    323     add_test("/visitor/opts/u64/nonlist",       &expect_fail, "u64x=5-6");
    324     add_test("/visitor/opts/u64/val2/errno",    &expect_fail,
    325              "u64=0xffffffffffffffff-0x10000000000000000");
    326     add_test("/visitor/opts/u64/val2/empty",    &expect_fail, "u64=5-");
    327     add_test("/visitor/opts/u64/val2/trailing", &expect_fail, "u64=5-6z");
    328     add_test("/visitor/opts/u64/range/empty",   &expect_fail, "u64=6-5");
    329     add_test("/visitor/opts/u64/range/minval",  &expect_zero, "u64=0-0");
    330     add_test("/visitor/opts/u64/range/maxval",  &expect_u64_max,
    331              "u64=0xffffffffffffffff-0xffffffffffffffff");
    332 
    333     /* Test maximum range sizes. The macro value is open-coded here
    334      * *intentionally*; the test case must use concrete values by design. If
    335      * OPTS_VISITOR_RANGE_MAX is changed, the following values need to be
    336      * recalculated as well. The assert and this comment should help with it.
    337      */
    338     g_assert(OPTS_VISITOR_RANGE_MAX == 65536);
    339 
    340     /* The unsigned case is simple, a u64-u64 difference can always be
    341      * represented as a u64.
    342      */
    343     add_test("/visitor/opts/u64/range/max",  &expect_ok,   "u64=0-65535");
    344     add_test("/visitor/opts/u64/range/2big", &expect_fail, "u64=0-65536");
    345 
    346     /* The same cannot be said about an i64-i64 difference. */
    347     add_test("/visitor/opts/i64/range/max/pos/a", &expect_ok,
    348              "i64=0x7fffffffffff0000-0x7fffffffffffffff");
    349     add_test("/visitor/opts/i64/range/max/pos/b", &expect_ok,
    350              "i64=0x7ffffffffffeffff-0x7ffffffffffffffe");
    351     add_test("/visitor/opts/i64/range/2big/pos",  &expect_fail,
    352              "i64=0x7ffffffffffeffff-0x7fffffffffffffff");
    353     add_test("/visitor/opts/i64/range/max/neg/a", &expect_ok,
    354              "i64=-0x8000000000000000--0x7fffffffffff0001");
    355     add_test("/visitor/opts/i64/range/max/neg/b", &expect_ok,
    356              "i64=-0x7fffffffffffffff--0x7fffffffffff0000");
    357     add_test("/visitor/opts/i64/range/2big/neg",  &expect_fail,
    358              "i64=-0x8000000000000000--0x7fffffffffff0000");
    359     add_test("/visitor/opts/i64/range/2big/full", &expect_fail,
    360              "i64=-0x8000000000000000-0x7fffffffffffffff");
    361 
    362     g_test_add_func("/visitor/opts/range/unvisited",
    363                     test_opts_range_unvisited);
    364     g_test_add_func("/visitor/opts/range/beyond",
    365                     test_opts_range_beyond);
    366 
    367     g_test_add_func("/visitor/opts/dict/unvisited", test_opts_dict_unvisited);
    368 
    369     g_test_run();
    370     return 0;
    371 }