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
14 typedef struct TestStructList
17 struct TestStructList
*next
;
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)
48 TestStruct ts
= { 42, 82 };
49 TestStruct
*pts
= &ts
;
50 TestStructList
*lts
= NULL
;
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
));
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
);
78 g_error("%s", error_get_pretty(err
));
81 g_assert(value
== 0x42);
85 obj
= qobject_from_json("{'x': 42, 'y': 84}");
86 mi
= qmp_input_visitor_new(obj
);
87 v
= qmp_input_get_visitor(mi
);
91 visit_type_TestStruct(v
, &pts
, NULL
, &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);
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
, <s
, NULL
, &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
);
124 /* test list output visitor */
125 mo
= qmp_output_visitor_new();
126 v
= qmp_output_get_visitor(mo
);
127 visit_type_TestStructList(v
, <s
, NULL
, &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
);
136 obj
= qlist_pop(qlist
);
137 qdict
= qobject_to_qdict(obj
);
139 assert(qdict_get_int(qdict
, "x") == 42);
140 assert(qdict_get_int(qdict
, "y") == 84);
143 obj
= qlist_pop(qlist
);
144 qdict
= qobject_to_qdict(obj
);
146 assert(qdict_get_int(qdict
, "x") == 12);
147 assert(qdict_get_int(qdict
, "y") == 24);
150 qmp_output_visitor_cleanup(mo
);
154 /* test deep nesting with refs to other user-defined types */
155 static void test_nested_structs(void)
157 QmpOutputVisitor
*mo
;
161 UserDefOne
*ud1_p
= &ud1
, *ud1c_p
= NULL
;
163 UserDefTwo
*ud2_p
= &ud2
, *ud2c_p
= NULL
;
169 ud1
.string
= strdup("forty two");
172 mo
= qmp_output_visitor_new();
173 v
= qmp_output_get_visitor(mo
);
174 visit_type_UserDefOne(v
, &ud1_p
, "o_O", &err
);
176 g_error("%s", error_get_pretty(err
));
178 obj
= qmp_output_get_qobject(mo
);
182 ud2
.string
= strdup("forty three");
183 ud2
.dict
.string
= strdup("forty four");
184 ud2
.dict
.dict
.userdef
= ud1_p
;
185 ud2
.dict
.dict
.string
= strdup("forty five");
186 ud2
.dict
.has_dict2
= true;
187 ud2
.dict
.dict2
.userdef
= ud1_p
;
188 ud2
.dict
.dict2
.string
= strdup("forty 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
);
195 g_error("%s", error_get_pretty(err
));
197 obj
= qmp_output_get_qobject(mo
);
199 str
= qobject_to_json_pretty(obj
);
200 g_print("%s\n", qstring_get_str(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
);
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
));
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
);
236 /* test enum values */
237 static void test_enums(void)
239 QmpOutputVisitor
*mo
;
242 EnumOne enum1
= ENUM_ONE_VALUE2
, enum1_cpy
= ENUM_ONE_VALUE1
;
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
);
252 g_error("%s", error_get_pretty(err
));
254 obj
= qmp_output_get_qobject(mo
);
256 str
= qobject_to_json_pretty(obj
);
257 g_print("%s\n", qstring_get_str(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
);
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
);
274 /* test enum values nested in schema-defined structs */
275 static void test_nested_enums(void)
277 QmpOutputVisitor
*mo
;
280 NestedEnumsOne
*nested_enums
, *nested_enums_cpy
= NULL
;
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
);
298 g_error("%s", error_get_pretty(err
));
300 obj
= qmp_output_get_qobject(mo
);
302 str
= qobject_to_json_pretty(obj
);
303 g_print("%s\n", qstring_get_str(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
);
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
);