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