root / test-qmp-output-visitor.c @ beae9d79
History | View | Annotate | Download (13.2 kB)
1 |
/*
|
---|---|
2 |
* QMP Output Visitor unit-tests.
|
3 |
*
|
4 |
* Copyright (C) 2011 Red Hat Inc.
|
5 |
*
|
6 |
* Authors:
|
7 |
* Luiz Capitulino <lcapitulino@redhat.com>
|
8 |
*
|
9 |
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
10 |
* See the COPYING file in the top-level directory.
|
11 |
*/
|
12 |
|
13 |
#include <glib.h> |
14 |
|
15 |
#include "qapi/qmp-output-visitor.h" |
16 |
#include "test-qapi-types.h" |
17 |
#include "test-qapi-visit.h" |
18 |
#include "qemu-objects.h" |
19 |
|
20 |
typedef struct TestOutputVisitorData { |
21 |
QmpOutputVisitor *qov; |
22 |
Visitor *ov; |
23 |
} TestOutputVisitorData; |
24 |
|
25 |
static void visitor_output_setup(TestOutputVisitorData *data, |
26 |
const void *unused) |
27 |
{ |
28 |
data->qov = qmp_output_visitor_new(); |
29 |
g_assert(data->qov != NULL);
|
30 |
|
31 |
data->ov = qmp_output_get_visitor(data->qov); |
32 |
g_assert(data->ov != NULL);
|
33 |
} |
34 |
|
35 |
static void visitor_output_teardown(TestOutputVisitorData *data, |
36 |
const void *unused) |
37 |
{ |
38 |
qmp_output_visitor_cleanup(data->qov); |
39 |
data->qov = NULL;
|
40 |
data->ov = NULL;
|
41 |
} |
42 |
|
43 |
static void test_visitor_out_int(TestOutputVisitorData *data, |
44 |
const void *unused) |
45 |
{ |
46 |
int64_t value = -42;
|
47 |
Error *errp = NULL;
|
48 |
QObject *obj; |
49 |
|
50 |
visit_type_int(data->ov, &value, NULL, &errp);
|
51 |
g_assert(error_is_set(&errp) == 0);
|
52 |
|
53 |
obj = qmp_output_get_qobject(data->qov); |
54 |
g_assert(obj != NULL);
|
55 |
g_assert(qobject_type(obj) == QTYPE_QINT); |
56 |
g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value); |
57 |
|
58 |
qobject_decref(obj); |
59 |
} |
60 |
|
61 |
static void test_visitor_out_bool(TestOutputVisitorData *data, |
62 |
const void *unused) |
63 |
{ |
64 |
Error *errp = NULL;
|
65 |
bool value = true; |
66 |
QObject *obj; |
67 |
|
68 |
visit_type_bool(data->ov, &value, NULL, &errp);
|
69 |
g_assert(error_is_set(&errp) == 0);
|
70 |
|
71 |
obj = qmp_output_get_qobject(data->qov); |
72 |
g_assert(obj != NULL);
|
73 |
g_assert(qobject_type(obj) == QTYPE_QBOOL); |
74 |
g_assert(qbool_get_int(qobject_to_qbool(obj)) == value); |
75 |
|
76 |
qobject_decref(obj); |
77 |
} |
78 |
|
79 |
static void test_visitor_out_number(TestOutputVisitorData *data, |
80 |
const void *unused) |
81 |
{ |
82 |
double value = 3.14; |
83 |
Error *errp = NULL;
|
84 |
QObject *obj; |
85 |
|
86 |
visit_type_number(data->ov, &value, NULL, &errp);
|
87 |
g_assert(error_is_set(&errp) == 0);
|
88 |
|
89 |
obj = qmp_output_get_qobject(data->qov); |
90 |
g_assert(obj != NULL);
|
91 |
g_assert(qobject_type(obj) == QTYPE_QFLOAT); |
92 |
g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value); |
93 |
|
94 |
qobject_decref(obj); |
95 |
} |
96 |
|
97 |
static void test_visitor_out_string(TestOutputVisitorData *data, |
98 |
const void *unused) |
99 |
{ |
100 |
char *string = (char *) "Q E M U"; |
101 |
Error *errp = NULL;
|
102 |
QObject *obj; |
103 |
|
104 |
visit_type_str(data->ov, &string, NULL, &errp);
|
105 |
g_assert(error_is_set(&errp) == 0);
|
106 |
|
107 |
obj = qmp_output_get_qobject(data->qov); |
108 |
g_assert(obj != NULL);
|
109 |
g_assert(qobject_type(obj) == QTYPE_QSTRING); |
110 |
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string); |
111 |
|
112 |
qobject_decref(obj); |
113 |
} |
114 |
|
115 |
static void test_visitor_out_no_string(TestOutputVisitorData *data, |
116 |
const void *unused) |
117 |
{ |
118 |
char *string = NULL; |
119 |
Error *errp = NULL;
|
120 |
QObject *obj; |
121 |
|
122 |
/* A null string should return "" */
|
123 |
visit_type_str(data->ov, &string, NULL, &errp);
|
124 |
g_assert(error_is_set(&errp) == 0);
|
125 |
|
126 |
obj = qmp_output_get_qobject(data->qov); |
127 |
g_assert(obj != NULL);
|
128 |
g_assert(qobject_type(obj) == QTYPE_QSTRING); |
129 |
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
|
130 |
|
131 |
qobject_decref(obj); |
132 |
} |
133 |
|
134 |
static void test_visitor_out_enum(TestOutputVisitorData *data, |
135 |
const void *unused) |
136 |
{ |
137 |
Error *errp = NULL;
|
138 |
QObject *obj; |
139 |
EnumOne i; |
140 |
|
141 |
for (i = 0; i < ENUM_ONE_MAX; i++) { |
142 |
visit_type_EnumOne(data->ov, &i, "unused", &errp);
|
143 |
g_assert(!error_is_set(&errp)); |
144 |
|
145 |
obj = qmp_output_get_qobject(data->qov); |
146 |
g_assert(obj != NULL);
|
147 |
g_assert(qobject_type(obj) == QTYPE_QSTRING); |
148 |
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, |
149 |
EnumOne_lookup[i]); |
150 |
qobject_decref(obj); |
151 |
} |
152 |
} |
153 |
|
154 |
static void test_visitor_out_enum_errors(TestOutputVisitorData *data, |
155 |
const void *unused) |
156 |
{ |
157 |
EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
|
158 |
Error *errp; |
159 |
|
160 |
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) { |
161 |
errp = NULL;
|
162 |
visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
|
163 |
g_assert(error_is_set(&errp) == true);
|
164 |
error_free(errp); |
165 |
} |
166 |
} |
167 |
|
168 |
typedef struct TestStruct |
169 |
{ |
170 |
int64_t integer; |
171 |
bool boolean;
|
172 |
char *string;
|
173 |
} TestStruct; |
174 |
|
175 |
static void visit_type_TestStruct(Visitor *v, TestStruct **obj, |
176 |
const char *name, Error **errp) |
177 |
{ |
178 |
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), |
179 |
errp); |
180 |
|
181 |
visit_type_int(v, &(*obj)->integer, "integer", errp);
|
182 |
visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
|
183 |
visit_type_str(v, &(*obj)->string, "string", errp);
|
184 |
|
185 |
visit_end_struct(v, errp); |
186 |
} |
187 |
|
188 |
static void test_visitor_out_struct(TestOutputVisitorData *data, |
189 |
const void *unused) |
190 |
{ |
191 |
TestStruct test_struct = { .integer = 42,
|
192 |
.boolean = false,
|
193 |
.string = (char *) "foo"}; |
194 |
TestStruct *p = &test_struct; |
195 |
Error *errp = NULL;
|
196 |
QObject *obj; |
197 |
QDict *qdict; |
198 |
|
199 |
visit_type_TestStruct(data->ov, &p, NULL, &errp);
|
200 |
g_assert(!error_is_set(&errp)); |
201 |
|
202 |
obj = qmp_output_get_qobject(data->qov); |
203 |
g_assert(obj != NULL);
|
204 |
g_assert(qobject_type(obj) == QTYPE_QDICT); |
205 |
|
206 |
qdict = qobject_to_qdict(obj); |
207 |
g_assert_cmpint(qdict_size(qdict), ==, 3);
|
208 |
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42); |
209 |
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0); |
210 |
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo"); |
211 |
|
212 |
QDECREF(qdict); |
213 |
} |
214 |
|
215 |
static void test_visitor_out_struct_nested(TestOutputVisitorData *data, |
216 |
const void *unused) |
217 |
{ |
218 |
int64_t value = 42;
|
219 |
Error *errp = NULL;
|
220 |
UserDefNested *ud2; |
221 |
QObject *obj; |
222 |
QDict *qdict, *dict1, *dict2, *dict3, *userdef; |
223 |
const char *string = "user def string"; |
224 |
const char *strings[] = { "forty two", "forty three", "forty four", |
225 |
"forty five" };
|
226 |
|
227 |
ud2 = g_malloc0(sizeof(*ud2));
|
228 |
ud2->string0 = g_strdup(strings[0]);
|
229 |
|
230 |
ud2->dict1.string1 = g_strdup(strings[1]);
|
231 |
ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
|
232 |
ud2->dict1.dict2.userdef1->string = g_strdup(string); |
233 |
ud2->dict1.dict2.userdef1->integer = value; |
234 |
ud2->dict1.dict2.string2 = g_strdup(strings[2]);
|
235 |
|
236 |
ud2->dict1.has_dict3 = true;
|
237 |
ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
|
238 |
ud2->dict1.dict3.userdef2->string = g_strdup(string); |
239 |
ud2->dict1.dict3.userdef2->integer = value; |
240 |
ud2->dict1.dict3.string3 = g_strdup(strings[3]);
|
241 |
|
242 |
visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
|
243 |
g_assert(!error_is_set(&errp)); |
244 |
|
245 |
obj = qmp_output_get_qobject(data->qov); |
246 |
g_assert(obj != NULL);
|
247 |
g_assert(qobject_type(obj) == QTYPE_QDICT); |
248 |
|
249 |
qdict = qobject_to_qdict(obj); |
250 |
g_assert_cmpint(qdict_size(qdict), ==, 2);
|
251 |
g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]); |
252 |
|
253 |
dict1 = qdict_get_qdict(qdict, "dict1");
|
254 |
g_assert_cmpint(qdict_size(dict1), ==, 3);
|
255 |
g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]); |
256 |
|
257 |
dict2 = qdict_get_qdict(dict1, "dict2");
|
258 |
g_assert_cmpint(qdict_size(dict2), ==, 2);
|
259 |
g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]); |
260 |
userdef = qdict_get_qdict(dict2, "userdef1");
|
261 |
g_assert_cmpint(qdict_size(userdef), ==, 2);
|
262 |
g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
|
263 |
g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
|
264 |
|
265 |
dict3 = qdict_get_qdict(dict1, "dict3");
|
266 |
g_assert_cmpint(qdict_size(dict3), ==, 2);
|
267 |
g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]); |
268 |
userdef = qdict_get_qdict(dict3, "userdef2");
|
269 |
g_assert_cmpint(qdict_size(userdef), ==, 2);
|
270 |
g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
|
271 |
g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
|
272 |
|
273 |
QDECREF(qdict); |
274 |
qapi_free_UserDefNested(ud2); |
275 |
} |
276 |
|
277 |
typedef struct TestStructList |
278 |
{ |
279 |
TestStruct *value; |
280 |
struct TestStructList *next;
|
281 |
} TestStructList; |
282 |
|
283 |
static void visit_type_TestStructList(Visitor *v, TestStructList **obj, |
284 |
const char *name, Error **errp) |
285 |
{ |
286 |
GenericList *i, **head = (GenericList **)obj; |
287 |
|
288 |
visit_start_list(v, name, errp); |
289 |
|
290 |
for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
|
291 |
TestStructList *native_i = (TestStructList *)i; |
292 |
visit_type_TestStruct(v, &native_i->value, NULL, errp);
|
293 |
} |
294 |
|
295 |
visit_end_list(v, errp); |
296 |
} |
297 |
|
298 |
static void test_visitor_out_list(TestOutputVisitorData *data, |
299 |
const void *unused) |
300 |
{ |
301 |
char *value_str = (char *) "list value"; |
302 |
TestStructList *p, *head = NULL;
|
303 |
const int max_items = 10; |
304 |
bool value_bool = true; |
305 |
int value_int = 10; |
306 |
Error *errp = NULL;
|
307 |
QListEntry *entry; |
308 |
QObject *obj; |
309 |
QList *qlist; |
310 |
int i;
|
311 |
|
312 |
for (i = 0; i < max_items; i++) { |
313 |
p = g_malloc0(sizeof(*p));
|
314 |
p->value = g_malloc0(sizeof(*p->value));
|
315 |
p->value->integer = value_int; |
316 |
p->value->boolean = value_bool; |
317 |
p->value->string = value_str; |
318 |
|
319 |
p->next = head; |
320 |
head = p; |
321 |
} |
322 |
|
323 |
visit_type_TestStructList(data->ov, &head, NULL, &errp);
|
324 |
g_assert(!error_is_set(&errp)); |
325 |
|
326 |
obj = qmp_output_get_qobject(data->qov); |
327 |
g_assert(obj != NULL);
|
328 |
g_assert(qobject_type(obj) == QTYPE_QLIST); |
329 |
|
330 |
qlist = qobject_to_qlist(obj); |
331 |
g_assert(!qlist_empty(qlist)); |
332 |
|
333 |
i = 0;
|
334 |
QLIST_FOREACH_ENTRY(qlist, entry) { |
335 |
QDict *qdict; |
336 |
|
337 |
g_assert(qobject_type(entry->value) == QTYPE_QDICT); |
338 |
qdict = qobject_to_qdict(entry->value); |
339 |
g_assert_cmpint(qdict_size(qdict), ==, 3);
|
340 |
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
|
341 |
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
|
342 |
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
|
343 |
i++; |
344 |
} |
345 |
g_assert_cmpint(i, ==, max_items); |
346 |
|
347 |
QDECREF(qlist); |
348 |
|
349 |
for (p = head; p;) {
|
350 |
TestStructList *tmp = p->next; |
351 |
g_free(p->value); |
352 |
g_free(p); |
353 |
p = tmp; |
354 |
} |
355 |
} |
356 |
|
357 |
static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data, |
358 |
const void *unused) |
359 |
{ |
360 |
UserDefNestedList *p, *head = NULL;
|
361 |
const char string[] = "foo bar"; |
362 |
int i, max_count = 1024; |
363 |
|
364 |
for (i = 0; i < max_count; i++) { |
365 |
p = g_malloc0(sizeof(*p));
|
366 |
p->value = g_malloc0(sizeof(*p->value));
|
367 |
|
368 |
p->value->string0 = g_strdup(string); |
369 |
p->value->dict1.string1 = g_strdup(string); |
370 |
p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
|
371 |
p->value->dict1.dict2.userdef1->string = g_strdup(string); |
372 |
p->value->dict1.dict2.userdef1->integer = 42;
|
373 |
p->value->dict1.dict2.string2 = g_strdup(string); |
374 |
p->value->dict1.has_dict3 = false;
|
375 |
|
376 |
p->next = head; |
377 |
head = p; |
378 |
} |
379 |
|
380 |
qapi_free_UserDefNestedList(head); |
381 |
} |
382 |
|
383 |
static void output_visitor_test_add(const char *testpath, |
384 |
TestOutputVisitorData *data, |
385 |
void (*test_func)(TestOutputVisitorData *data, const void *user_data)) |
386 |
{ |
387 |
g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup, |
388 |
test_func, visitor_output_teardown); |
389 |
} |
390 |
|
391 |
int main(int argc, char **argv) |
392 |
{ |
393 |
TestOutputVisitorData out_visitor_data; |
394 |
|
395 |
g_test_init(&argc, &argv, NULL);
|
396 |
|
397 |
output_visitor_test_add("/visitor/output/int",
|
398 |
&out_visitor_data, test_visitor_out_int); |
399 |
output_visitor_test_add("/visitor/output/bool",
|
400 |
&out_visitor_data, test_visitor_out_bool); |
401 |
output_visitor_test_add("/visitor/output/number",
|
402 |
&out_visitor_data, test_visitor_out_number); |
403 |
output_visitor_test_add("/visitor/output/string",
|
404 |
&out_visitor_data, test_visitor_out_string); |
405 |
output_visitor_test_add("/visitor/output/no-string",
|
406 |
&out_visitor_data, test_visitor_out_no_string); |
407 |
output_visitor_test_add("/visitor/output/enum",
|
408 |
&out_visitor_data, test_visitor_out_enum); |
409 |
output_visitor_test_add("/visitor/output/enum-errors",
|
410 |
&out_visitor_data, test_visitor_out_enum_errors); |
411 |
output_visitor_test_add("/visitor/output/struct",
|
412 |
&out_visitor_data, test_visitor_out_struct); |
413 |
output_visitor_test_add("/visitor/output/struct-nested",
|
414 |
&out_visitor_data, test_visitor_out_struct_nested); |
415 |
output_visitor_test_add("/visitor/output/list",
|
416 |
&out_visitor_data, test_visitor_out_list); |
417 |
output_visitor_test_add("/visitor/output/list-qapi-free",
|
418 |
&out_visitor_data, test_visitor_out_list_qapi_free); |
419 |
|
420 |
g_test_run(); |
421 |
|
422 |
return 0; |
423 |
} |