qemu

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

test-forward-visitor.c (5998B)


      1 /*
      2  * QAPI Forwarding Visitor unit-tests.
      3  *
      4  * Copyright (C) 2021 Red Hat Inc.
      5  *
      6  * This work is licensed under the terms of the GNU GPL, version 2 or later.
      7  * See the COPYING file in the top-level directory.
      8  */
      9 
     10 #include "qemu/osdep.h"
     11 
     12 #include "qapi/forward-visitor.h"
     13 #include "qapi/qobject-input-visitor.h"
     14 #include "qapi/error.h"
     15 #include "qapi/qmp/qobject.h"
     16 #include "qapi/qmp/qdict.h"
     17 #include "test-qapi-visit.h"
     18 #include "qemu/keyval.h"
     19 
     20 typedef bool GenericVisitor (Visitor *, const char *, void **, Error **);
     21 #define CAST_VISIT_TYPE(fn) ((GenericVisitor *)(fn))
     22 
     23 /*
     24  * Parse @srcstr and wrap it with a ForwardFieldVisitor converting "src" to
     25  * "dst". Check that visiting the result with "src" name fails, and return
     26  * the result of visiting "dst".
     27  */
     28 static void *visit_with_forward(const char *srcstr, GenericVisitor *fn)
     29 {
     30     bool help = false;
     31     QDict *src = keyval_parse(srcstr, NULL, &help, &error_abort);
     32     Visitor *v, *alias_v;
     33     Error *err = NULL;
     34     void *result = NULL;
     35 
     36     v = qobject_input_visitor_new_keyval(QOBJECT(src));
     37     visit_start_struct(v, NULL, NULL, 0, &error_abort);
     38 
     39     alias_v = visitor_forward_field(v, "dst", "src");
     40     fn(alias_v, "src", &result, &err);
     41     error_free_or_abort(&err);
     42     assert(!result);
     43     fn(alias_v, "dst", &result, &err);
     44     assert(err == NULL);
     45     visit_free(alias_v);
     46 
     47     visit_end_struct(v, NULL);
     48     visit_free(v);
     49     qobject_unref(QOBJECT(src));
     50     return result;
     51 }
     52 
     53 static void test_forward_any(void)
     54 {
     55     QObject *src = visit_with_forward("src.integer=42,src.string=Hello,src.enum1=value2",
     56                                       CAST_VISIT_TYPE(visit_type_any));
     57     Visitor *v = qobject_input_visitor_new_keyval(src);
     58     Error *err = NULL;
     59     UserDefOne *dst;
     60 
     61     visit_type_UserDefOne(v, NULL, &dst, &err);
     62     assert(err == NULL);
     63     visit_free(v);
     64 
     65     g_assert_cmpint(dst->integer, ==, 42);
     66     g_assert_cmpstr(dst->string, ==, "Hello");
     67     g_assert_cmpint(dst->has_enum1, ==, true);
     68     g_assert_cmpint(dst->enum1, ==, ENUM_ONE_VALUE2);
     69     qapi_free_UserDefOne(dst);
     70     qobject_unref(QOBJECT(src));
     71 }
     72 
     73 static void test_forward_size(void)
     74 {
     75     /*
     76      * visit_type_size does not return a pointer, so visit_with_forward
     77      * cannot be used.
     78      */
     79     bool help = false;
     80     QDict *src = keyval_parse("src=1.5M", NULL, &help, &error_abort);
     81     Visitor *v, *alias_v;
     82     Error *err = NULL;
     83     uint64_t result = 0;
     84 
     85     v = qobject_input_visitor_new_keyval(QOBJECT(src));
     86     visit_start_struct(v, NULL, NULL, 0, &error_abort);
     87 
     88     alias_v = visitor_forward_field(v, "dst", "src");
     89     visit_type_size(alias_v, "src", &result, &err);
     90     error_free_or_abort(&err);
     91     visit_type_size(alias_v, "dst", &result, &err);
     92     assert(result == 3 << 19);
     93     assert(err == NULL);
     94     visit_free(alias_v);
     95 
     96     visit_end_struct(v, NULL);
     97     visit_free(v);
     98     qobject_unref(QOBJECT(src));
     99 }
    100 
    101 static void test_forward_number(void)
    102 {
    103     /*
    104      * visit_type_number does not return a pointer, so visit_with_forward
    105      * cannot be used.
    106      */
    107     bool help = false;
    108     QDict *src = keyval_parse("src=1.5", NULL, &help, &error_abort);
    109     Visitor *v, *alias_v;
    110     Error *err = NULL;
    111     double result = 0.0;
    112 
    113     v = qobject_input_visitor_new_keyval(QOBJECT(src));
    114     visit_start_struct(v, NULL, NULL, 0, &error_abort);
    115 
    116     alias_v = visitor_forward_field(v, "dst", "src");
    117     visit_type_number(alias_v, "src", &result, &err);
    118     error_free_or_abort(&err);
    119     visit_type_number(alias_v, "dst", &result, &err);
    120     assert(result == 1.5);
    121     assert(err == NULL);
    122     visit_free(alias_v);
    123 
    124     visit_end_struct(v, NULL);
    125     visit_free(v);
    126     qobject_unref(QOBJECT(src));
    127 }
    128 
    129 static void test_forward_string(void)
    130 {
    131     char *dst = visit_with_forward("src=Hello",
    132                                    CAST_VISIT_TYPE(visit_type_str));
    133 
    134     g_assert_cmpstr(dst, ==, "Hello");
    135     g_free(dst);
    136 }
    137 
    138 static void test_forward_struct(void)
    139 {
    140     UserDefOne *dst = visit_with_forward("src.integer=42,src.string=Hello",
    141                                          CAST_VISIT_TYPE(visit_type_UserDefOne));
    142 
    143     g_assert_cmpint(dst->integer, ==, 42);
    144     g_assert_cmpstr(dst->string, ==, "Hello");
    145     g_assert_cmpint(dst->has_enum1, ==, false);
    146     qapi_free_UserDefOne(dst);
    147 }
    148 
    149 static void test_forward_alternate(void)
    150 {
    151     AltStrObj *s_dst = visit_with_forward("src=hello",
    152                                           CAST_VISIT_TYPE(visit_type_AltStrObj));
    153     AltStrObj *o_dst = visit_with_forward("src.integer=42,src.boolean=true,src.string=world",
    154                                           CAST_VISIT_TYPE(visit_type_AltStrObj));
    155 
    156     g_assert_cmpint(s_dst->type, ==, QTYPE_QSTRING);
    157     g_assert_cmpstr(s_dst->u.s, ==, "hello");
    158     g_assert_cmpint(o_dst->type, ==, QTYPE_QDICT);
    159     g_assert_cmpint(o_dst->u.o.integer, ==, 42);
    160     g_assert_cmpint(o_dst->u.o.boolean, ==, true);
    161     g_assert_cmpstr(o_dst->u.o.string, ==, "world");
    162 
    163     qapi_free_AltStrObj(s_dst);
    164     qapi_free_AltStrObj(o_dst);
    165 }
    166 
    167 static void test_forward_list(void)
    168 {
    169     uint8List *dst = visit_with_forward("src.0=1,src.1=2,src.2=3,src.3=4",
    170                                         CAST_VISIT_TYPE(visit_type_uint8List));
    171     uint8List *tmp;
    172     int i;
    173 
    174     for (tmp = dst, i = 1; i <= 4; i++) {
    175         g_assert(tmp);
    176         g_assert_cmpint(tmp->value, ==, i);
    177         tmp = tmp->next;
    178     }
    179     g_assert(!tmp);
    180     qapi_free_uint8List(dst);
    181 }
    182 
    183 int main(int argc, char **argv)
    184 {
    185     g_test_init(&argc, &argv, NULL);
    186 
    187     g_test_add_func("/visitor/forward/struct", test_forward_struct);
    188     g_test_add_func("/visitor/forward/alternate", test_forward_alternate);
    189     g_test_add_func("/visitor/forward/string", test_forward_string);
    190     g_test_add_func("/visitor/forward/size", test_forward_size);
    191     g_test_add_func("/visitor/forward/number", test_forward_number);
    192     g_test_add_func("/visitor/forward/any", test_forward_any);
    193     g_test_add_func("/visitor/forward/list", test_forward_list);
    194 
    195     return g_test_run();
    196 }