Add qemu 2.4.0
[kvmfornfv.git] / qemu / tests / test-qmp-input-strict.c
1 /*
2  * QMP Input Visitor unit-tests (strict mode).
3  *
4  * Copyright (C) 2011-2012, 2015 Red Hat Inc.
5  *
6  * Authors:
7  *  Luiz Capitulino <lcapitulino@redhat.com>
8  *  Paolo Bonzini <pbonzini@redhat.com>
9  *
10  * This work is licensed under the terms of the GNU GPL, version 2 or later.
11  * See the COPYING file in the top-level directory.
12  */
13
14 #include <glib.h>
15 #include <stdarg.h>
16
17 #include "qemu-common.h"
18 #include "qapi/qmp-input-visitor.h"
19 #include "test-qapi-types.h"
20 #include "test-qapi-visit.h"
21 #include "qapi/qmp/types.h"
22
23 typedef struct TestInputVisitorData {
24     QObject *obj;
25     QmpInputVisitor *qiv;
26 } TestInputVisitorData;
27
28 static void validate_teardown(TestInputVisitorData *data,
29                                const void *unused)
30 {
31     qobject_decref(data->obj);
32     data->obj = NULL;
33
34     if (data->qiv) {
35         qmp_input_visitor_cleanup(data->qiv);
36         data->qiv = NULL;
37     }
38 }
39
40 /* This is provided instead of a test setup function so that the JSON
41    string used by the tests are kept in the test functions (and not
42    int main()) */
43 static GCC_FMT_ATTR(2, 3)
44 Visitor *validate_test_init(TestInputVisitorData *data,
45                              const char *json_string, ...)
46 {
47     Visitor *v;
48     va_list ap;
49
50     va_start(ap, json_string);
51     data->obj = qobject_from_jsonv(json_string, &ap);
52     va_end(ap);
53
54     g_assert(data->obj != NULL);
55
56     data->qiv = qmp_input_visitor_new_strict(data->obj);
57     g_assert(data->qiv != NULL);
58
59     v = qmp_input_get_visitor(data->qiv);
60     g_assert(v != NULL);
61
62     return v;
63 }
64
65 typedef struct TestStruct
66 {
67     int64_t integer;
68     bool boolean;
69     char *string;
70 } TestStruct;
71
72 static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
73                                   const char *name, Error **errp)
74 {
75     Error *err = NULL;
76
77     visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
78                        &err);
79     if (err) {
80         goto out;
81     }
82
83     visit_type_int(v, &(*obj)->integer, "integer", &err);
84     if (err) {
85         goto out_end;
86     }
87     visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
88     if (err) {
89         goto out_end;
90     }
91     visit_type_str(v, &(*obj)->string, "string", &err);
92
93 out_end:
94     error_propagate(errp, err);
95     err = NULL;
96     visit_end_struct(v, &err);
97 out:
98     error_propagate(errp, err);
99 }
100
101 static void test_validate_struct(TestInputVisitorData *data,
102                                   const void *unused)
103 {
104     TestStruct *p = NULL;
105     Error *err = NULL;
106     Visitor *v;
107
108     v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
109
110     visit_type_TestStruct(v, &p, NULL, &err);
111     g_assert(!err);
112     g_free(p->string);
113     g_free(p);
114 }
115
116 static void test_validate_struct_nested(TestInputVisitorData *data,
117                                          const void *unused)
118 {
119     UserDefTwo *udp = NULL;
120     Error *err = NULL;
121     Visitor *v;
122
123     v = validate_test_init(data, "{ 'string0': 'string0', "
124                            "'dict1': { 'string1': 'string1', "
125                            "'dict2': { 'userdef': { 'integer': 42, "
126                            "'string': 'string' }, 'string': 'string2'}}}");
127
128     visit_type_UserDefTwo(v, &udp, NULL, &err);
129     g_assert(!err);
130     qapi_free_UserDefTwo(udp);
131 }
132
133 static void test_validate_list(TestInputVisitorData *data,
134                                 const void *unused)
135 {
136     UserDefOneList *head = NULL;
137     Error *err = NULL;
138     Visitor *v;
139
140     v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
141
142     visit_type_UserDefOneList(v, &head, NULL, &err);
143     g_assert(!err);
144     qapi_free_UserDefOneList(head);
145 }
146
147 static void test_validate_union_native_list(TestInputVisitorData *data,
148                                             const void *unused)
149 {
150     UserDefNativeListUnion *tmp = NULL;
151     Visitor *v;
152     Error *err = NULL;
153
154     v = validate_test_init(data, "{ 'type': 'integer', 'data' : [ 1, 2 ] }");
155
156     visit_type_UserDefNativeListUnion(v, &tmp, NULL, &err);
157     g_assert(!err);
158     qapi_free_UserDefNativeListUnion(tmp);
159 }
160
161 static void test_validate_union_flat(TestInputVisitorData *data,
162                                      const void *unused)
163 {
164     UserDefFlatUnion *tmp = NULL;
165     Visitor *v;
166     Error *err = NULL;
167
168     v = validate_test_init(data,
169                            "{ 'enum1': 'value1', "
170                            "'string': 'str', "
171                            "'boolean': true }");
172     /* TODO when generator bug is fixed, add 'integer': 41 */
173
174     visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
175     g_assert(!err);
176     qapi_free_UserDefFlatUnion(tmp);
177 }
178
179 static void test_validate_alternate(TestInputVisitorData *data,
180                                     const void *unused)
181 {
182     UserDefAlternate *tmp = NULL;
183     Visitor *v;
184     Error *err = NULL;
185
186     v = validate_test_init(data, "42");
187
188     visit_type_UserDefAlternate(v, &tmp, NULL, &err);
189     g_assert(!err);
190     qapi_free_UserDefAlternate(tmp);
191 }
192
193 static void test_validate_fail_struct(TestInputVisitorData *data,
194                                        const void *unused)
195 {
196     TestStruct *p = NULL;
197     Error *err = NULL;
198     Visitor *v;
199
200     v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
201
202     visit_type_TestStruct(v, &p, NULL, &err);
203     g_assert(err);
204     if (p) {
205         g_free(p->string);
206     }
207     g_free(p);
208 }
209
210 static void test_validate_fail_struct_nested(TestInputVisitorData *data,
211                                               const void *unused)
212 {
213     UserDefTwo *udp = NULL;
214     Error *err = NULL;
215     Visitor *v;
216
217     v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
218
219     visit_type_UserDefTwo(v, &udp, NULL, &err);
220     g_assert(err);
221     qapi_free_UserDefTwo(udp);
222 }
223
224 static void test_validate_fail_list(TestInputVisitorData *data,
225                                      const void *unused)
226 {
227     UserDefOneList *head = NULL;
228     Error *err = NULL;
229     Visitor *v;
230
231     v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
232
233     visit_type_UserDefOneList(v, &head, NULL, &err);
234     g_assert(err);
235     qapi_free_UserDefOneList(head);
236 }
237
238 static void test_validate_fail_union_native_list(TestInputVisitorData *data,
239                                                  const void *unused)
240 {
241     UserDefNativeListUnion *tmp = NULL;
242     Error *err = NULL;
243     Visitor *v;
244
245     v = validate_test_init(data,
246                            "{ 'type': 'integer', 'data' : [ 'string' ] }");
247
248     visit_type_UserDefNativeListUnion(v, &tmp, NULL, &err);
249     g_assert(err);
250     qapi_free_UserDefNativeListUnion(tmp);
251 }
252
253 static void test_validate_fail_union_flat(TestInputVisitorData *data,
254                                           const void *unused)
255 {
256     UserDefFlatUnion *tmp = NULL;
257     Error *err = NULL;
258     Visitor *v;
259
260     v = validate_test_init(data, "{ 'string': 'c', 'integer': 41, 'boolean': true }");
261
262     visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
263     g_assert(err);
264     qapi_free_UserDefFlatUnion(tmp);
265 }
266
267 static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData *data,
268                                                      const void *unused)
269 {
270     UserDefFlatUnion2 *tmp = NULL;
271     Error *err = NULL;
272     Visitor *v;
273
274     /* test situation where discriminator field ('enum1' here) is missing */
275     v = validate_test_init(data, "{ 'string': 'c', 'string1': 'd', 'string2': 'e' }");
276
277     visit_type_UserDefFlatUnion2(v, &tmp, NULL, &err);
278     g_assert(err);
279     qapi_free_UserDefFlatUnion2(tmp);
280 }
281
282 static void test_validate_fail_alternate(TestInputVisitorData *data,
283                                          const void *unused)
284 {
285     UserDefAlternate *tmp = NULL;
286     Visitor *v;
287     Error *err = NULL;
288
289     v = validate_test_init(data, "3.14");
290
291     visit_type_UserDefAlternate(v, &tmp, NULL, &err);
292     g_assert(err);
293     qapi_free_UserDefAlternate(tmp);
294 }
295
296 static void validate_test_add(const char *testpath,
297                                TestInputVisitorData *data,
298                                void (*test_func)(TestInputVisitorData *data, const void *user_data))
299 {
300     g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
301                validate_teardown);
302 }
303
304 int main(int argc, char **argv)
305 {
306     TestInputVisitorData testdata;
307
308     g_test_init(&argc, &argv, NULL);
309
310     validate_test_add("/visitor/input-strict/pass/struct",
311                       &testdata, test_validate_struct);
312     validate_test_add("/visitor/input-strict/pass/struct-nested",
313                       &testdata, test_validate_struct_nested);
314     validate_test_add("/visitor/input-strict/pass/list",
315                       &testdata, test_validate_list);
316     validate_test_add("/visitor/input-strict/pass/union-flat",
317                       &testdata, test_validate_union_flat);
318     validate_test_add("/visitor/input-strict/pass/alternate",
319                       &testdata, test_validate_alternate);
320     validate_test_add("/visitor/input-strict/pass/union-native-list",
321                       &testdata, test_validate_union_native_list);
322     validate_test_add("/visitor/input-strict/fail/struct",
323                       &testdata, test_validate_fail_struct);
324     validate_test_add("/visitor/input-strict/fail/struct-nested",
325                       &testdata, test_validate_fail_struct_nested);
326     validate_test_add("/visitor/input-strict/fail/list",
327                       &testdata, test_validate_fail_list);
328     validate_test_add("/visitor/input-strict/fail/union-flat",
329                       &testdata, test_validate_fail_union_flat);
330     validate_test_add("/visitor/input-strict/fail/union-flat-no-discriminator",
331                       &testdata, test_validate_fail_union_flat_no_discrim);
332     validate_test_add("/visitor/input-strict/fail/alternate",
333                       &testdata, test_validate_fail_alternate);
334     validate_test_add("/visitor/input-strict/fail/union-native-list",
335                       &testdata, test_validate_fail_union_native_list);
336
337     g_test_run();
338
339     return 0;
340 }