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 */ 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 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 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 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 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 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 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 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 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