qapi: add Visitor interfaces for uint*_t and int*_t
[qemu/mdroth.git] / test-visitor.c
blob847ce14ea1328f4551c170c609cb3150e440b8ff
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"
8 typedef struct TestStruct
10 int64_t x;
11 int64_t y;
12 } TestStruct;
14 typedef struct TestStructList
16 TestStruct *value;
17 struct TestStructList *next;
18 } TestStructList;
20 static void visit_type_TestStruct(Visitor *v, TestStruct **obj, const char *name, Error **errp)
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);
28 static void visit_type_TestStructList(Visitor *m, TestStructList ** obj, const char *name, Error **errp)
30 GenericList *i, **head = (GenericList **)obj;
32 visit_start_list(m, name, errp);
34 for (*head = i = visit_next_list(m, head, 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);
39 visit_end_list(m, errp);
42 /* test core visitor methods */
43 static void test_visitor_core(void)
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 QList *qlist;
54 QDict *qdict;
55 QString *str;
56 int64_t value = 0;
58 mo = qmp_output_visitor_new();
59 v = qmp_output_get_visitor(mo);
61 visit_type_TestStruct(v, &pts, NULL, &err);
63 obj = qmp_output_get_qobject(mo);
65 str = qobject_to_json(obj);
67 printf("%s\n", qstring_get_str(str));
69 QDECREF(str);
71 obj = QOBJECT(qint_from_int(0x42));
73 mi = qmp_input_visitor_new(obj);
74 v = qmp_input_get_visitor(mi);
76 visit_type_int(v, &value, NULL, &err);
77 if (err) {
78 g_error("%s", error_get_pretty(err));
81 g_assert(value == 0x42);
83 qobject_decref(obj);
85 obj = qobject_from_json("{'x': 42, 'y': 84}");
86 mi = qmp_input_visitor_new(obj);
87 v = qmp_input_get_visitor(mi);
89 pts = NULL;
91 visit_type_TestStruct(v, &pts, NULL, &err);
92 if (err) {
93 g_error("%s", error_get_pretty(err));
96 g_assert(pts != NULL);
97 g_assert(pts->x == 42);
98 g_assert(pts->y == 84);
100 qobject_decref(obj);
101 g_free(pts);
103 /* test list input visitor */
104 obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]");
105 mi = qmp_input_visitor_new(obj);
106 v = qmp_input_get_visitor(mi);
108 visit_type_TestStructList(v, &lts, NULL, &err);
109 if (err) {
110 g_error("%s", error_get_pretty(err));
113 g_assert(lts != NULL);
114 g_assert(lts->value->x == 42);
115 g_assert(lts->value->y == 84);
117 g_assert(lts->next != NULL);
118 g_assert(lts->next->value->x == 12);
119 g_assert(lts->next->value->y == 24);
120 g_assert(lts->next->next == NULL);
122 qobject_decref(obj);
124 /* test list output visitor */
125 mo = qmp_output_visitor_new();
126 v = qmp_output_get_visitor(mo);
127 visit_type_TestStructList(v, &lts, NULL, &err);
128 if (err) {
129 g_error("%s", error_get_pretty(err));
131 obj = qmp_output_get_qobject(mo);
132 g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj)));
134 qlist = qobject_to_qlist(obj);
135 assert(qlist);
136 obj = qlist_pop(qlist);
137 qdict = qobject_to_qdict(obj);
138 assert(qdict);
139 assert(qdict_get_int(qdict, "x") == 42);
140 assert(qdict_get_int(qdict, "y") == 84);
141 qobject_decref(obj);
143 obj = qlist_pop(qlist);
144 qdict = qobject_to_qdict(obj);
145 assert(qdict);
146 assert(qdict_get_int(qdict, "x") == 12);
147 assert(qdict_get_int(qdict, "y") == 24);
148 qobject_decref(obj);
150 qmp_output_visitor_cleanup(mo);
151 QDECREF(qlist);
154 /* test deep nesting with refs to other user-defined types */
155 static void test_nested_structs(void)
157 QmpOutputVisitor *mo;
158 QmpInputVisitor *mi;
159 Visitor *v;
160 UserDefOne ud1;
161 UserDefOne *ud1_p = &ud1, *ud1c_p = NULL;
162 UserDefTwo ud2;
163 UserDefTwo *ud2_p = &ud2, *ud2c_p = NULL;
164 Error *err = NULL;
165 QObject *obj;
166 QString *str;
168 ud1.integer = 42;
169 ud1.string = strdup("fourty two");
171 /* sanity check */
172 mo = qmp_output_visitor_new();
173 v = qmp_output_get_visitor(mo);
174 visit_type_UserDefOne(v, &ud1_p, "o_O", &err);
175 if (err) {
176 g_error("%s", error_get_pretty(err));
178 obj = qmp_output_get_qobject(mo);
179 g_assert(obj);
180 qobject_decref(obj);
182 ud2.string = strdup("fourty three");
183 ud2.dict.string = strdup("fourty four");
184 ud2.dict.dict.userdef = ud1_p;
185 ud2.dict.dict.string = strdup("fourty five");
186 ud2.dict.has_dict2 = true;
187 ud2.dict.dict2.userdef = ud1_p;
188 ud2.dict.dict2.string = strdup("fourty six");
190 /* c type -> qobject */
191 mo = qmp_output_visitor_new();
192 v = qmp_output_get_visitor(mo);
193 visit_type_UserDefTwo(v, &ud2_p, "unused", &err);
194 if (err) {
195 g_error("%s", error_get_pretty(err));
197 obj = qmp_output_get_qobject(mo);
198 g_assert(obj);
199 str = qobject_to_json_pretty(obj);
200 g_print("%s\n", qstring_get_str(str));
201 QDECREF(str);
203 /* qobject -> c type, should match original struct */
204 mi = qmp_input_visitor_new(obj);
205 v = qmp_input_get_visitor(mi);
206 visit_type_UserDefTwo(v, &ud2c_p, NULL, &err);
207 if (err) {
208 g_error("%s", error_get_pretty(err));
211 g_assert(!g_strcmp0(ud2c_p->string, ud2.string));
212 g_assert(!g_strcmp0(ud2c_p->dict.string, ud2.dict.string));
214 ud1c_p = ud2c_p->dict.dict.userdef;
215 g_assert(ud1c_p->integer == ud1_p->integer);
216 g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
218 g_assert(!g_strcmp0(ud2c_p->dict.dict.string, ud2.dict.dict.string));
220 ud1c_p = ud2c_p->dict.dict2.userdef;
221 g_assert(ud1c_p->integer == ud1_p->integer);
222 g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string));
224 g_assert(!g_strcmp0(ud2c_p->dict.dict2.string, ud2.dict.dict2.string));
225 g_free(ud1.string);
226 g_free(ud2.string);
227 g_free(ud2.dict.string);
228 g_free(ud2.dict.dict.string);
229 g_free(ud2.dict.dict2.string);
231 qapi_free_UserDefTwo(ud2c_p);
233 qobject_decref(obj);
236 /* test enum values */
237 static void test_enums(void)
239 QmpOutputVisitor *mo;
240 QmpInputVisitor *mi;
241 Visitor *v;
242 EnumOne enum1 = ENUM_ONE_VALUE2, enum1_cpy = ENUM_ONE_VALUE1;
243 Error *err = NULL;
244 QObject *obj;
245 QString *str;
247 /* C type -> QObject */
248 mo = qmp_output_visitor_new();
249 v = qmp_output_get_visitor(mo);
250 visit_type_EnumOne(v, &enum1, "unused", &err);
251 if (err) {
252 g_error("%s", error_get_pretty(err));
254 obj = qmp_output_get_qobject(mo);
255 g_assert(obj);
256 str = qobject_to_json_pretty(obj);
257 g_print("%s\n", qstring_get_str(str));
258 QDECREF(str);
259 g_assert(g_strcmp0(qstring_get_str(qobject_to_qstring(obj)), "value2") == 0);
261 /* QObject -> C type */
262 mi = qmp_input_visitor_new(obj);
263 v = qmp_input_get_visitor(mi);
264 visit_type_EnumOne(v, &enum1_cpy, "unused", &err);
265 if (err) {
266 g_error("%s", error_get_pretty(err));
268 g_debug("enum1_cpy, enum1: %d, %d", enum1_cpy, enum1);
269 g_assert(enum1_cpy == enum1);
271 qobject_decref(obj);
274 /* test enum values nested in schema-defined structs */
275 static void test_nested_enums(void)
277 QmpOutputVisitor *mo;
278 QmpInputVisitor *mi;
279 Visitor *v;
280 NestedEnumsOne *nested_enums, *nested_enums_cpy = NULL;
281 Error *err = NULL;
282 QObject *obj;
283 QString *str;
285 nested_enums = g_malloc0(sizeof(NestedEnumsOne));
286 nested_enums->enum1 = ENUM_ONE_VALUE1;
287 nested_enums->enum2 = ENUM_ONE_VALUE2;
288 nested_enums->enum3 = ENUM_ONE_VALUE3;
289 nested_enums->enum4 = ENUM_ONE_VALUE3;
290 nested_enums->has_enum2 = false;
291 nested_enums->has_enum4 = true;
293 /* C type -> QObject */
294 mo = qmp_output_visitor_new();
295 v = qmp_output_get_visitor(mo);
296 visit_type_NestedEnumsOne(v, &nested_enums, NULL, &err);
297 if (err) {
298 g_error("%s", error_get_pretty(err));
300 obj = qmp_output_get_qobject(mo);
301 g_assert(obj);
302 str = qobject_to_json_pretty(obj);
303 g_print("%s\n", qstring_get_str(str));
304 QDECREF(str);
306 /* QObject -> C type */
307 mi = qmp_input_visitor_new(obj);
308 v = qmp_input_get_visitor(mi);
309 visit_type_NestedEnumsOne(v, &nested_enums_cpy, NULL, &err);
310 if (err) {
311 g_error("%s", error_get_pretty(err));
313 g_assert(nested_enums_cpy);
314 g_assert(nested_enums_cpy->enum1 == nested_enums->enum1);
315 g_assert(nested_enums_cpy->enum3 == nested_enums->enum3);
316 g_assert(nested_enums_cpy->enum4 == nested_enums->enum4);
317 g_assert(nested_enums_cpy->has_enum2 == false);
318 g_assert(nested_enums_cpy->has_enum4 == true);
320 qmp_output_visitor_cleanup(mo);
321 qmp_input_visitor_cleanup(mi);
322 qapi_free_NestedEnumsOne(nested_enums);
323 qapi_free_NestedEnumsOne(nested_enums_cpy);
326 int main(int argc, char **argv)
328 g_test_init(&argc, &argv, NULL);
330 g_test_add_func("/0.15/visitor_core", test_visitor_core);
331 g_test_add_func("/0.15/nested_structs", test_nested_structs);
332 g_test_add_func("/0.15/enums", test_enums);
333 g_test_add_func("/0.15/nested_enums", test_nested_enums);
335 g_test_run();
337 return 0;