|
|
1.1 root 1: /*
2: * QMP Input Visitor unit-tests.
3: *
4: * Copyright (C) 2011 Red Hat Inc.
5: *
6: * Authors:
7: * Luiz Capitulino <[email protected]>
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: #include <stdarg.h>
15:
16: #include "qapi/qmp-input-visitor.h"
17: #include "test-qapi-types.h"
18: #include "test-qapi-visit.h"
19: #include "qemu-objects.h"
20:
21: typedef struct TestInputVisitorData {
22: QObject *obj;
23: QmpInputVisitor *qiv;
24: } TestInputVisitorData;
25:
26: static void visitor_input_teardown(TestInputVisitorData *data,
27: const void *unused)
28: {
29: qobject_decref(data->obj);
30: data->obj = NULL;
31:
32: if (data->qiv) {
33: qmp_input_visitor_cleanup(data->qiv);
34: data->qiv = NULL;
35: }
36: }
37:
38: /* This is provided instead of a test setup function so that the JSON
39: string used by the tests are kept in the test functions (and not
40: int main()) */
41: static GCC_FMT_ATTR(2, 3)
42: Visitor *visitor_input_test_init(TestInputVisitorData *data,
43: const char *json_string, ...)
44: {
45: Visitor *v;
46: va_list ap;
47:
48: va_start(ap, json_string);
49: data->obj = qobject_from_jsonv(json_string, &ap);
50: va_end(ap);
51:
52: g_assert(data->obj != NULL);
53:
54: data->qiv = qmp_input_visitor_new(data->obj);
55: g_assert(data->qiv != NULL);
56:
57: v = qmp_input_get_visitor(data->qiv);
58: g_assert(v != NULL);
59:
60: return v;
61: }
62:
63: static void test_visitor_in_int(TestInputVisitorData *data,
64: const void *unused)
65: {
66: int64_t res = 0, value = -42;
67: Error *errp = NULL;
68: Visitor *v;
69:
70: v = visitor_input_test_init(data, "%" PRId64, value);
71:
72: visit_type_int(v, &res, NULL, &errp);
73: g_assert(!error_is_set(&errp));
74: g_assert_cmpint(res, ==, value);
75: }
76:
77: static void test_visitor_in_bool(TestInputVisitorData *data,
78: const void *unused)
79: {
80: Error *errp = NULL;
81: bool res = false;
82: Visitor *v;
83:
84: v = visitor_input_test_init(data, "true");
85:
86: visit_type_bool(v, &res, NULL, &errp);
87: g_assert(!error_is_set(&errp));
88: g_assert_cmpint(res, ==, true);
89: }
90:
91: static void test_visitor_in_number(TestInputVisitorData *data,
92: const void *unused)
93: {
94: double res = 0, value = 3.14;
95: Error *errp = NULL;
96: Visitor *v;
97:
98: v = visitor_input_test_init(data, "%f", value);
99:
100: visit_type_number(v, &res, NULL, &errp);
101: g_assert(!error_is_set(&errp));
102: g_assert_cmpfloat(res, ==, value);
103: }
104:
105: static void test_visitor_in_string(TestInputVisitorData *data,
106: const void *unused)
107: {
108: char *res = NULL, *value = (char *) "Q E M U";
109: Error *errp = NULL;
110: Visitor *v;
111:
112: v = visitor_input_test_init(data, "%s", value);
113:
114: visit_type_str(v, &res, NULL, &errp);
115: g_assert(!error_is_set(&errp));
116: g_assert_cmpstr(res, ==, value);
117:
118: g_free(res);
119: }
120:
121: static void test_visitor_in_enum(TestInputVisitorData *data,
122: const void *unused)
123: {
124: Error *errp = NULL;
125: Visitor *v;
126: EnumOne i;
127:
128: for (i = 0; EnumOne_lookup[i]; i++) {
129: EnumOne res = -1;
130:
131: v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
132:
133: visit_type_EnumOne(v, &res, NULL, &errp);
134: g_assert(!error_is_set(&errp));
135: g_assert_cmpint(i, ==, res);
136:
137: visitor_input_teardown(data, NULL);
138: }
139:
140: data->obj = NULL;
141: data->qiv = NULL;
142: }
143:
144: typedef struct TestStruct
145: {
146: int64_t integer;
147: bool boolean;
148: char *string;
149: } TestStruct;
150:
151: static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
152: const char *name, Error **errp)
153: {
154: visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
155: errp);
156:
157: visit_type_int(v, &(*obj)->integer, "integer", errp);
158: visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
159: visit_type_str(v, &(*obj)->string, "string", errp);
160:
161: visit_end_struct(v, errp);
162: }
163:
164: static void test_visitor_in_struct(TestInputVisitorData *data,
165: const void *unused)
166: {
167: TestStruct *p = NULL;
168: Error *errp = NULL;
169: Visitor *v;
170:
171: v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
172:
173: visit_type_TestStruct(v, &p, NULL, &errp);
174: g_assert(!error_is_set(&errp));
175: g_assert_cmpint(p->integer, ==, -42);
176: g_assert(p->boolean == true);
177: g_assert_cmpstr(p->string, ==, "foo");
178:
179: g_free(p->string);
180: g_free(p);
181: }
182:
183: static void check_and_free_str(char *str, const char *cmp)
184: {
185: g_assert_cmpstr(str, ==, cmp);
186: g_free(str);
187: }
188:
189: static void test_visitor_in_struct_nested(TestInputVisitorData *data,
190: const void *unused)
191: {
192: UserDefNested *udp = NULL;
193: Error *errp = NULL;
194: Visitor *v;
195:
196: v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
197:
198: visit_type_UserDefNested(v, &udp, NULL, &errp);
199: g_assert(!error_is_set(&errp));
200:
201: check_and_free_str(udp->string0, "string0");
202: check_and_free_str(udp->dict1.string1, "string1");
203: g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
204: check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
205: check_and_free_str(udp->dict1.dict2.string2, "string2");
206: g_assert(udp->dict1.has_dict3 == false);
207:
208: g_free(udp->dict1.dict2.userdef1);
209: g_free(udp);
210: }
211:
212: static void test_visitor_in_list(TestInputVisitorData *data,
213: const void *unused)
214: {
215: UserDefOneList *item, *head = NULL;
216: Error *errp = NULL;
217: Visitor *v;
218: int i;
219:
220: v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
221:
222: visit_type_UserDefOneList(v, &head, NULL, &errp);
223: g_assert(!error_is_set(&errp));
224: g_assert(head != NULL);
225:
226: for (i = 0, item = head; item; item = item->next, i++) {
227: char string[12];
228:
229: snprintf(string, sizeof(string), "string%d", i);
230: g_assert_cmpstr(item->value->string, ==, string);
231: g_assert_cmpint(item->value->integer, ==, 42 + i);
232: }
233:
234: qapi_free_UserDefOneList(head);
235: }
236:
237: static void test_visitor_in_union(TestInputVisitorData *data,
238: const void *unused)
239: {
240: Visitor *v;
241: Error *err = NULL;
242: UserDefUnion *tmp;
243:
244: v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
245:
246: visit_type_UserDefUnion(v, &tmp, NULL, &err);
247: g_assert(err == NULL);
248: g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B);
249: g_assert_cmpint(tmp->b->integer, ==, 42);
250: qapi_free_UserDefUnion(tmp);
251: }
252:
253: static void input_visitor_test_add(const char *testpath,
254: TestInputVisitorData *data,
255: void (*test_func)(TestInputVisitorData *data, const void *user_data))
256: {
257: g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
258: visitor_input_teardown);
259: }
260:
261: static void test_visitor_in_errors(TestInputVisitorData *data,
262: const void *unused)
263: {
264: TestStruct *p = NULL;
265: Error *errp = NULL;
266: Visitor *v;
267:
268: v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
269:
270: visit_type_TestStruct(v, &p, NULL, &errp);
271: g_assert(error_is_set(&errp));
272: g_assert(p->string == NULL);
273:
274: g_free(p->string);
275: g_free(p);
276: }
277:
278: int main(int argc, char **argv)
279: {
280: TestInputVisitorData in_visitor_data;
281:
282: g_test_init(&argc, &argv, NULL);
283:
284: input_visitor_test_add("/visitor/input/int",
285: &in_visitor_data, test_visitor_in_int);
286: input_visitor_test_add("/visitor/input/bool",
287: &in_visitor_data, test_visitor_in_bool);
288: input_visitor_test_add("/visitor/input/number",
289: &in_visitor_data, test_visitor_in_number);
290: input_visitor_test_add("/visitor/input/string",
291: &in_visitor_data, test_visitor_in_string);
292: input_visitor_test_add("/visitor/input/enum",
293: &in_visitor_data, test_visitor_in_enum);
294: input_visitor_test_add("/visitor/input/struct",
295: &in_visitor_data, test_visitor_in_struct);
296: input_visitor_test_add("/visitor/input/struct-nested",
297: &in_visitor_data, test_visitor_in_struct_nested);
298: input_visitor_test_add("/visitor/input/list",
299: &in_visitor_data, test_visitor_in_list);
300: input_visitor_test_add("/visitor/input/union",
301: &in_visitor_data, test_visitor_in_union);
302: input_visitor_test_add("/visitor/input/errors",
303: &in_visitor_data, test_visitor_in_errors);
304:
305: g_test_run();
306:
307: return 0;
308: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.