xref: /openbmc/qemu/tests/unit/test-forward-visitor.c (revision 28298069afff3eb696e4995e63b2579b27adf378)
118fa3ebcSPaolo Bonzini /*
218fa3ebcSPaolo Bonzini  * QAPI Forwarding Visitor unit-tests.
318fa3ebcSPaolo Bonzini  *
418fa3ebcSPaolo Bonzini  * Copyright (C) 2021 Red Hat Inc.
518fa3ebcSPaolo Bonzini  *
618fa3ebcSPaolo Bonzini  * This work is licensed under the terms of the GNU GPL, version 2 or later.
718fa3ebcSPaolo Bonzini  * See the COPYING file in the top-level directory.
818fa3ebcSPaolo Bonzini  */
918fa3ebcSPaolo Bonzini 
1018fa3ebcSPaolo Bonzini #include "qemu/osdep.h"
1118fa3ebcSPaolo Bonzini 
1218fa3ebcSPaolo Bonzini #include "qapi/forward-visitor.h"
1318fa3ebcSPaolo Bonzini #include "qapi/qobject-input-visitor.h"
1418fa3ebcSPaolo Bonzini #include "qapi/error.h"
1518fa3ebcSPaolo Bonzini #include "qapi/qmp/qobject.h"
1618fa3ebcSPaolo Bonzini #include "qapi/qmp/qdict.h"
1718fa3ebcSPaolo Bonzini #include "test-qapi-visit.h"
18*9ca9c893SMarc-André Lureau #include "qemu/keyval.h"
1918fa3ebcSPaolo Bonzini 
2018fa3ebcSPaolo Bonzini typedef bool GenericVisitor (Visitor *, const char *, void **, Error **);
2118fa3ebcSPaolo Bonzini #define CAST_VISIT_TYPE(fn) ((GenericVisitor *)(fn))
2218fa3ebcSPaolo Bonzini 
2318fa3ebcSPaolo Bonzini /*
2418fa3ebcSPaolo Bonzini  * Parse @srcstr and wrap it with a ForwardFieldVisitor converting "src" to
2518fa3ebcSPaolo Bonzini  * "dst". Check that visiting the result with "src" name fails, and return
2618fa3ebcSPaolo Bonzini  * the result of visiting "dst".
2718fa3ebcSPaolo Bonzini  */
visit_with_forward(const char * srcstr,GenericVisitor * fn)2818fa3ebcSPaolo Bonzini static void *visit_with_forward(const char *srcstr, GenericVisitor *fn)
2918fa3ebcSPaolo Bonzini {
3018fa3ebcSPaolo Bonzini     bool help = false;
3118fa3ebcSPaolo Bonzini     QDict *src = keyval_parse(srcstr, NULL, &help, &error_abort);
3218fa3ebcSPaolo Bonzini     Visitor *v, *alias_v;
3318fa3ebcSPaolo Bonzini     Error *err = NULL;
3418fa3ebcSPaolo Bonzini     void *result = NULL;
3518fa3ebcSPaolo Bonzini 
3618fa3ebcSPaolo Bonzini     v = qobject_input_visitor_new_keyval(QOBJECT(src));
3718fa3ebcSPaolo Bonzini     visit_start_struct(v, NULL, NULL, 0, &error_abort);
3818fa3ebcSPaolo Bonzini 
3918fa3ebcSPaolo Bonzini     alias_v = visitor_forward_field(v, "dst", "src");
4018fa3ebcSPaolo Bonzini     fn(alias_v, "src", &result, &err);
4118fa3ebcSPaolo Bonzini     error_free_or_abort(&err);
4218fa3ebcSPaolo Bonzini     assert(!result);
4318fa3ebcSPaolo Bonzini     fn(alias_v, "dst", &result, &err);
4418fa3ebcSPaolo Bonzini     assert(err == NULL);
4518fa3ebcSPaolo Bonzini     visit_free(alias_v);
4618fa3ebcSPaolo Bonzini 
4718fa3ebcSPaolo Bonzini     visit_end_struct(v, NULL);
4818fa3ebcSPaolo Bonzini     visit_free(v);
4918fa3ebcSPaolo Bonzini     qobject_unref(QOBJECT(src));
5018fa3ebcSPaolo Bonzini     return result;
5118fa3ebcSPaolo Bonzini }
5218fa3ebcSPaolo Bonzini 
test_forward_any(void)5318fa3ebcSPaolo Bonzini static void test_forward_any(void)
5418fa3ebcSPaolo Bonzini {
5518fa3ebcSPaolo Bonzini     QObject *src = visit_with_forward("src.integer=42,src.string=Hello,src.enum1=value2",
5618fa3ebcSPaolo Bonzini                                       CAST_VISIT_TYPE(visit_type_any));
5718fa3ebcSPaolo Bonzini     Visitor *v = qobject_input_visitor_new_keyval(src);
5818fa3ebcSPaolo Bonzini     Error *err = NULL;
5918fa3ebcSPaolo Bonzini     UserDefOne *dst;
6018fa3ebcSPaolo Bonzini 
6118fa3ebcSPaolo Bonzini     visit_type_UserDefOne(v, NULL, &dst, &err);
6218fa3ebcSPaolo Bonzini     assert(err == NULL);
6318fa3ebcSPaolo Bonzini     visit_free(v);
6418fa3ebcSPaolo Bonzini 
6518fa3ebcSPaolo Bonzini     g_assert_cmpint(dst->integer, ==, 42);
6618fa3ebcSPaolo Bonzini     g_assert_cmpstr(dst->string, ==, "Hello");
6718fa3ebcSPaolo Bonzini     g_assert_cmpint(dst->has_enum1, ==, true);
6818fa3ebcSPaolo Bonzini     g_assert_cmpint(dst->enum1, ==, ENUM_ONE_VALUE2);
6918fa3ebcSPaolo Bonzini     qapi_free_UserDefOne(dst);
7018fa3ebcSPaolo Bonzini     qobject_unref(QOBJECT(src));
7118fa3ebcSPaolo Bonzini }
7218fa3ebcSPaolo Bonzini 
test_forward_size(void)7318fa3ebcSPaolo Bonzini static void test_forward_size(void)
7418fa3ebcSPaolo Bonzini {
7518fa3ebcSPaolo Bonzini     /*
7618fa3ebcSPaolo Bonzini      * visit_type_size does not return a pointer, so visit_with_forward
7718fa3ebcSPaolo Bonzini      * cannot be used.
7818fa3ebcSPaolo Bonzini      */
7918fa3ebcSPaolo Bonzini     bool help = false;
8018fa3ebcSPaolo Bonzini     QDict *src = keyval_parse("src=1.5M", NULL, &help, &error_abort);
8118fa3ebcSPaolo Bonzini     Visitor *v, *alias_v;
8218fa3ebcSPaolo Bonzini     Error *err = NULL;
8318fa3ebcSPaolo Bonzini     uint64_t result = 0;
8418fa3ebcSPaolo Bonzini 
8518fa3ebcSPaolo Bonzini     v = qobject_input_visitor_new_keyval(QOBJECT(src));
8618fa3ebcSPaolo Bonzini     visit_start_struct(v, NULL, NULL, 0, &error_abort);
8718fa3ebcSPaolo Bonzini 
8818fa3ebcSPaolo Bonzini     alias_v = visitor_forward_field(v, "dst", "src");
8918fa3ebcSPaolo Bonzini     visit_type_size(alias_v, "src", &result, &err);
9018fa3ebcSPaolo Bonzini     error_free_or_abort(&err);
9118fa3ebcSPaolo Bonzini     visit_type_size(alias_v, "dst", &result, &err);
9218fa3ebcSPaolo Bonzini     assert(result == 3 << 19);
9318fa3ebcSPaolo Bonzini     assert(err == NULL);
9418fa3ebcSPaolo Bonzini     visit_free(alias_v);
9518fa3ebcSPaolo Bonzini 
9618fa3ebcSPaolo Bonzini     visit_end_struct(v, NULL);
9718fa3ebcSPaolo Bonzini     visit_free(v);
9818fa3ebcSPaolo Bonzini     qobject_unref(QOBJECT(src));
9918fa3ebcSPaolo Bonzini }
10018fa3ebcSPaolo Bonzini 
test_forward_number(void)10118fa3ebcSPaolo Bonzini static void test_forward_number(void)
10218fa3ebcSPaolo Bonzini {
10318fa3ebcSPaolo Bonzini     /*
10418fa3ebcSPaolo Bonzini      * visit_type_number does not return a pointer, so visit_with_forward
10518fa3ebcSPaolo Bonzini      * cannot be used.
10618fa3ebcSPaolo Bonzini      */
10718fa3ebcSPaolo Bonzini     bool help = false;
10818fa3ebcSPaolo Bonzini     QDict *src = keyval_parse("src=1.5", NULL, &help, &error_abort);
10918fa3ebcSPaolo Bonzini     Visitor *v, *alias_v;
11018fa3ebcSPaolo Bonzini     Error *err = NULL;
11118fa3ebcSPaolo Bonzini     double result = 0.0;
11218fa3ebcSPaolo Bonzini 
11318fa3ebcSPaolo Bonzini     v = qobject_input_visitor_new_keyval(QOBJECT(src));
11418fa3ebcSPaolo Bonzini     visit_start_struct(v, NULL, NULL, 0, &error_abort);
11518fa3ebcSPaolo Bonzini 
11618fa3ebcSPaolo Bonzini     alias_v = visitor_forward_field(v, "dst", "src");
11718fa3ebcSPaolo Bonzini     visit_type_number(alias_v, "src", &result, &err);
11818fa3ebcSPaolo Bonzini     error_free_or_abort(&err);
11918fa3ebcSPaolo Bonzini     visit_type_number(alias_v, "dst", &result, &err);
12018fa3ebcSPaolo Bonzini     assert(result == 1.5);
12118fa3ebcSPaolo Bonzini     assert(err == NULL);
12218fa3ebcSPaolo Bonzini     visit_free(alias_v);
12318fa3ebcSPaolo Bonzini 
12418fa3ebcSPaolo Bonzini     visit_end_struct(v, NULL);
12518fa3ebcSPaolo Bonzini     visit_free(v);
12618fa3ebcSPaolo Bonzini     qobject_unref(QOBJECT(src));
12718fa3ebcSPaolo Bonzini }
12818fa3ebcSPaolo Bonzini 
test_forward_string(void)12918fa3ebcSPaolo Bonzini static void test_forward_string(void)
13018fa3ebcSPaolo Bonzini {
13118fa3ebcSPaolo Bonzini     char *dst = visit_with_forward("src=Hello",
13218fa3ebcSPaolo Bonzini                                    CAST_VISIT_TYPE(visit_type_str));
13318fa3ebcSPaolo Bonzini 
13418fa3ebcSPaolo Bonzini     g_assert_cmpstr(dst, ==, "Hello");
13518fa3ebcSPaolo Bonzini     g_free(dst);
13618fa3ebcSPaolo Bonzini }
13718fa3ebcSPaolo Bonzini 
test_forward_struct(void)13818fa3ebcSPaolo Bonzini static void test_forward_struct(void)
13918fa3ebcSPaolo Bonzini {
14018fa3ebcSPaolo Bonzini     UserDefOne *dst = visit_with_forward("src.integer=42,src.string=Hello",
14118fa3ebcSPaolo Bonzini                                          CAST_VISIT_TYPE(visit_type_UserDefOne));
14218fa3ebcSPaolo Bonzini 
14318fa3ebcSPaolo Bonzini     g_assert_cmpint(dst->integer, ==, 42);
14418fa3ebcSPaolo Bonzini     g_assert_cmpstr(dst->string, ==, "Hello");
14518fa3ebcSPaolo Bonzini     g_assert_cmpint(dst->has_enum1, ==, false);
14618fa3ebcSPaolo Bonzini     qapi_free_UserDefOne(dst);
14718fa3ebcSPaolo Bonzini }
14818fa3ebcSPaolo Bonzini 
test_forward_alternate(void)14918fa3ebcSPaolo Bonzini static void test_forward_alternate(void)
15018fa3ebcSPaolo Bonzini {
15118fa3ebcSPaolo Bonzini     AltStrObj *s_dst = visit_with_forward("src=hello",
15218fa3ebcSPaolo Bonzini                                           CAST_VISIT_TYPE(visit_type_AltStrObj));
15318fa3ebcSPaolo Bonzini     AltStrObj *o_dst = visit_with_forward("src.integer=42,src.boolean=true,src.string=world",
15418fa3ebcSPaolo Bonzini                                           CAST_VISIT_TYPE(visit_type_AltStrObj));
15518fa3ebcSPaolo Bonzini 
15618fa3ebcSPaolo Bonzini     g_assert_cmpint(s_dst->type, ==, QTYPE_QSTRING);
15718fa3ebcSPaolo Bonzini     g_assert_cmpstr(s_dst->u.s, ==, "hello");
15818fa3ebcSPaolo Bonzini     g_assert_cmpint(o_dst->type, ==, QTYPE_QDICT);
15918fa3ebcSPaolo Bonzini     g_assert_cmpint(o_dst->u.o.integer, ==, 42);
16018fa3ebcSPaolo Bonzini     g_assert_cmpint(o_dst->u.o.boolean, ==, true);
16118fa3ebcSPaolo Bonzini     g_assert_cmpstr(o_dst->u.o.string, ==, "world");
16218fa3ebcSPaolo Bonzini 
16318fa3ebcSPaolo Bonzini     qapi_free_AltStrObj(s_dst);
16418fa3ebcSPaolo Bonzini     qapi_free_AltStrObj(o_dst);
16518fa3ebcSPaolo Bonzini }
16618fa3ebcSPaolo Bonzini 
test_forward_list(void)16718fa3ebcSPaolo Bonzini static void test_forward_list(void)
16818fa3ebcSPaolo Bonzini {
16918fa3ebcSPaolo Bonzini     uint8List *dst = visit_with_forward("src.0=1,src.1=2,src.2=3,src.3=4",
17018fa3ebcSPaolo Bonzini                                         CAST_VISIT_TYPE(visit_type_uint8List));
17118fa3ebcSPaolo Bonzini     uint8List *tmp;
17218fa3ebcSPaolo Bonzini     int i;
17318fa3ebcSPaolo Bonzini 
17418fa3ebcSPaolo Bonzini     for (tmp = dst, i = 1; i <= 4; i++) {
17518fa3ebcSPaolo Bonzini         g_assert(tmp);
17618fa3ebcSPaolo Bonzini         g_assert_cmpint(tmp->value, ==, i);
17718fa3ebcSPaolo Bonzini         tmp = tmp->next;
17818fa3ebcSPaolo Bonzini     }
17918fa3ebcSPaolo Bonzini     g_assert(!tmp);
18018fa3ebcSPaolo Bonzini     qapi_free_uint8List(dst);
18118fa3ebcSPaolo Bonzini }
18218fa3ebcSPaolo Bonzini 
main(int argc,char ** argv)18318fa3ebcSPaolo Bonzini int main(int argc, char **argv)
18418fa3ebcSPaolo Bonzini {
18518fa3ebcSPaolo Bonzini     g_test_init(&argc, &argv, NULL);
18618fa3ebcSPaolo Bonzini 
18718fa3ebcSPaolo Bonzini     g_test_add_func("/visitor/forward/struct", test_forward_struct);
18818fa3ebcSPaolo Bonzini     g_test_add_func("/visitor/forward/alternate", test_forward_alternate);
18918fa3ebcSPaolo Bonzini     g_test_add_func("/visitor/forward/string", test_forward_string);
19018fa3ebcSPaolo Bonzini     g_test_add_func("/visitor/forward/size", test_forward_size);
19118fa3ebcSPaolo Bonzini     g_test_add_func("/visitor/forward/number", test_forward_number);
19218fa3ebcSPaolo Bonzini     g_test_add_func("/visitor/forward/any", test_forward_any);
19318fa3ebcSPaolo Bonzini     g_test_add_func("/visitor/forward/list", test_forward_list);
19418fa3ebcSPaolo Bonzini 
19518fa3ebcSPaolo Bonzini     return g_test_run();
19618fa3ebcSPaolo Bonzini }
197