]> git.proxmox.com Git - qemu.git/blame - test-visitor.c
monitor: fix build breakage for !CONFIG_VNC
[qemu.git] / test-visitor.c
CommitLineData
640e5404
MR
1#include <glib.h>
2#include "qapi/qmp-output-visitor.h"
3#include "qapi/qmp-input-visitor.h"
4#include "test-qapi-types.h"
5#include "test-qapi-visit.h"
6#include "qemu-objects.h"
7
8typedef struct TestStruct
9{
10 int64_t x;
11 int64_t y;
12} TestStruct;
13
14typedef struct TestStructList
15{
16 TestStruct *value;
17 struct TestStructList *next;
18} TestStructList;
19
20static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name, Error **errp)
21{
22 visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), errp);
23 visit_type_int(v, &(*obj)->x, "x", errp);
24 visit_type_int(v, &(*obj)->y, "y", errp);
25 visit_end_struct(v, errp);
26}
27
28static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
29{
30 GenericList *i;
31
32 visit_start_list(m, name, errp);
33
34 for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
35 TestStructList *native_i = (TestStructList *)i;
36 visit_type_TestStruct(m, &native_i->value, NULL, errp);
37 }
38
39 visit_end_list(m, errp);
40}
41
42/* test core visitor methods */
43static void test_visitor_core(void)
44{
45 QmpOutputVisitor *mo;
46 QmpInputVisitor *mi;
47 Visitor *v;
48 TestStruct ts = { 42, 82 };
49 TestStruct *pts = &ts;
50 TestStructList *lts = NULL;
51 Error *err = NULL;
52 QObject *obj;
53 QString *str;
54 int64_t value = 0;
55
56 mo = qmp_output_visitor_new();
57 v = qmp_output_get_visitor(mo);
58
59 visit_type_TestStruct(v, &pts, NULL, &err);
60
61 obj = qmp_output_get_qobject(mo);
62
63 str = qobject_to_json(obj);
64
65 printf("%s\n", qstring_get_str(str));
66
67 QDECREF(str);
68
69 obj = QOBJECT(qint_from_int(0x42));
70
71 mi = qmp_input_visitor_new(obj);
72 v = qmp_input_get_visitor(mi);
73
74 visit_type_int(v, &value, NULL, &err);
75 if (err) {
76 g_error("%s", error_get_pretty(err));
77 }
78
79 g_assert(value == 0x42);
80
81 qobject_decref(obj);
82
83 obj = qobject_from_json("{'x': 42, 'y': 84}");
84 mi = qmp_input_visitor_new(obj);
85 v = qmp_input_get_visitor(mi);
86
87 pts = NULL;
88
89 visit_type_TestStruct(v, &pts, NULL, &err);
90 if (err) {
91 g_error("%s", error_get_pretty(err));
92 }
93
94 g_assert(pts != NULL);
95 g_assert(pts->x == 42);
96 g_assert(pts->y == 84);
97
98 qobject_decref(obj);
99
100 obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
101 mi = qmp_input_visitor_new(obj);
102 v = qmp_input_get_visitor(mi);
103
104 visit_type_TestStructList(v, &lts, NULL, &err);
105 if (err) {
106 g_error("%s", error_get_pretty(err));
107 }
108
109 g_assert(lts != NULL);
110 g_assert(lts->value->x == 42);
111 g_assert(lts->value->y == 84);
112
113 lts = lts->next;
114 g_assert(lts != NULL);
115 g_assert(lts->value->x == 12);
116 g_assert(lts->value->y == 24);
117
118 g_assert(lts->next == NULL);
119
120 qobject_decref(obj);
121}
122
123/* test deep nesting with refs to other user-defined types */
124static void test_nested_structs(void)
125{
126 QmpOutputVisitor *mo;
127 QmpInputVisitor *mi;
128 Visitor *v;
129 UserDefOne ud1;
130 UserDefOne *ud1_p = &ud1, *ud1c_p = NULL;
131 UserDefTwo ud2;
132 UserDefTwo *ud2_p = &ud2, *ud2c_p = NULL;
133 Error *err = NULL;
134 QObject *obj;
135 QString *str;
136
137 ud1.integer = 42;
138 ud1.string = strdup("fourty two");
139
140 /* sanity check */
141 mo = qmp_output_visitor_new();
142 v = qmp_output_get_visitor(mo);
143 visit_type_UserDefOne(v, &ud1_p, "o_O", &err);
144 if (err) {
145 g_error("%s", error_get_pretty(err));
146 }
147 obj = qmp_output_get_qobject(mo);
148 g_assert(obj);
149 qobject_decref(obj);
150
151 ud2.string = strdup("fourty three");
152 ud2.dict.string = strdup("fourty four");
153 ud2.dict.dict.userdef = ud1_p;
154 ud2.dict.dict.string = strdup("fourty five");
155 ud2.dict.has_dict2 = true;
156 ud2.dict.dict2.userdef = ud1_p;
157 ud2.dict.dict2.string = strdup("fourty six");
158
159 /* c type -> qobject */
160 mo = qmp_output_visitor_new();
161 v = qmp_output_get_visitor(mo);
162 visit_type_UserDefTwo(v, &ud2_p, "unused", &err);
163 if (err) {
164 g_error("%s", error_get_pretty(err));
165 }
166 obj = qmp_output_get_qobject(mo);
167 g_assert(obj);
168 str = qobject_to_json_pretty(obj);
169 g_print("%s\n", qstring_get_str(str));
170 QDECREF(str);
171
172 /* qobject -> c type, should match original struct */
173 mi = qmp_input_visitor_new(obj);
174 v = qmp_input_get_visitor(mi);
175 visit_type_UserDefTwo(v, &ud2c_p, NULL, &err);
176 if (err) {
177 g_error("%s", error_get_pretty(err));
178 }
179
180 g_assert(!g_strcmp0(ud2c_p->string, ud2.string));
181 g_assert(!g_strcmp0(ud2c_p->dict.string, ud2.dict.string));
182
183 ud1c_p = ud2c_p->dict.dict.userdef;
184 g_assert(ud1c_p->integer == ud1_p->integer);
185 g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
186
187 g_assert(!g_strcmp0(ud2c_p->dict.dict.string, ud2.dict.dict.string));
188
189 ud1c_p = ud2c_p->dict.dict2.userdef;
190 g_assert(ud1c_p->integer == ud1_p->integer);
191 g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
192
193 g_assert(!g_strcmp0(ud2c_p->dict.dict2.string, ud2.dict.dict2.string));
194 qemu_free(ud1.string);
195 qemu_free(ud2.string);
196 qemu_free(ud2.dict.string);
197 qemu_free(ud2.dict.dict.string);
198 qemu_free(ud2.dict.dict2.string);
199
200 qapi_free_UserDefTwo(ud2c_p);
201
202 qobject_decref(obj);
203}
204
205/* test enum values */
206static void test_enums(void)
207{
208 QmpOutputVisitor *mo;
209 QmpInputVisitor *mi;
210 Visitor *v;
211 EnumOne enum1 = ENUM_ONE_VALUE2, enum1_cpy = ENUM_ONE_VALUE1;
212 Error *err = NULL;
213 QObject *obj;
214 QString *str;
215
216 /* C type -> QObject */
217 mo = qmp_output_visitor_new();
218 v = qmp_output_get_visitor(mo);
219 visit_type_EnumOne(v, &enum1, "unused", &err);
220 if (err) {
221 g_error("%s", error_get_pretty(err));
222 }
223 obj = qmp_output_get_qobject(mo);
224 g_assert(obj);
225 str = qobject_to_json_pretty(obj);
226 g_print("%s\n", qstring_get_str(str));
227 QDECREF(str);
228 g_assert(g_strcmp0(qstring_get_str(qobject_to_qstring(obj)), "value2") == 0);
229
230 /* QObject -> C type */
231 mi = qmp_input_visitor_new(obj);
232 v = qmp_input_get_visitor(mi);
233 visit_type_EnumOne(v, &enum1_cpy, "unused", &err);
234 if (err) {
235 g_error("%s", error_get_pretty(err));
236 }
237 g_debug("enum1_cpy, enum1: %d, %d", enum1_cpy, enum1);
238 g_assert(enum1_cpy == enum1);
239
240 qobject_decref(obj);
241}
242
243/* test enum values nested in schema-defined structs */
244static void test_nested_enums(void)
245{
246 QmpOutputVisitor *mo;
247 QmpInputVisitor *mi;
248 Visitor *v;
249 NestedEnumsOne *nested_enums, *nested_enums_cpy = NULL;
250 Error *err = NULL;
251 QObject *obj;
252 QString *str;
253
254 nested_enums = qemu_mallocz(sizeof(NestedEnumsOne));
255 nested_enums->enum1 = ENUM_ONE_VALUE1;
256 nested_enums->enum2 = ENUM_ONE_VALUE2;
257 nested_enums->enum3 = ENUM_ONE_VALUE3;
258 nested_enums->enum4 = ENUM_ONE_VALUE3;
259 nested_enums->has_enum2 = false;
260 nested_enums->has_enum4 = true;
261
262 /* C type -> QObject */
263 mo = qmp_output_visitor_new();
264 v = qmp_output_get_visitor(mo);
265 visit_type_NestedEnumsOne(v, &nested_enums, NULL, &err);
266 if (err) {
267 g_error("%s", error_get_pretty(err));
268 }
269 obj = qmp_output_get_qobject(mo);
270 g_assert(obj);
271 str = qobject_to_json_pretty(obj);
272 g_print("%s\n", qstring_get_str(str));
273 QDECREF(str);
274
275 /* QObject -> C type */
276 mi = qmp_input_visitor_new(obj);
277 v = qmp_input_get_visitor(mi);
278 visit_type_NestedEnumsOne(v, &nested_enums_cpy, NULL, &err);
279 if (err) {
280 g_error("%s", error_get_pretty(err));
281 }
282 g_assert(nested_enums_cpy);
283 g_assert(nested_enums_cpy->enum1 == nested_enums->enum1);
284 g_assert(nested_enums_cpy->enum3 == nested_enums->enum3);
285 g_assert(nested_enums_cpy->enum4 == nested_enums->enum4);
286 g_assert(nested_enums_cpy->has_enum2 == false);
287 g_assert(nested_enums_cpy->has_enum4 == true);
288
289 qobject_decref(obj);
290 qapi_free_NestedEnumsOne(nested_enums);
291 qapi_free_NestedEnumsOne(nested_enums_cpy);
292}
293
294int main(int argc, char **argv)
295{
296 g_test_init(&argc, &argv, NULL);
297
298 g_test_add_func("/0.15/visitor_core", test_visitor_core);
299 g_test_add_func("/0.15/nested_structs", test_nested_structs);
300 g_test_add_func("/0.15/enums", test_enums);
301 g_test_add_func("/0.15/nested_enums", test_nested_enums);
302
303 g_test_run();
304
305 return 0;
306}