qemu/tests/unit/test-forward-visitor.c
<<
>>
Prefs
   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
  20typedef 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 */
  28static 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
  53static 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
  73static 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
 101static 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
 129static 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
 138static 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
 149static 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
 167static 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
 183int 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}
 197