2 * QMP Input Visitor unit-tests (strict mode).
4 * Copyright (C) 2011-2012, 2015 Red Hat Inc.
7 * Luiz Capitulino <lcapitulino@redhat.com>
8 * Paolo Bonzini <pbonzini@redhat.com>
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.
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 #include "test-qmp-introspect.h"
23 #include "qmp-introspect.h"
24 #include "qapi-visit.h"
26 typedef struct TestInputVisitorData
{
29 } TestInputVisitorData
;
31 static void validate_teardown(TestInputVisitorData
*data
,
34 qobject_decref(data
->obj
);
38 qmp_input_visitor_cleanup(data
->qiv
);
43 /* This is provided instead of a test setup function so that the JSON
44 string used by the tests are kept in the test functions (and not
46 static GCC_FMT_ATTR(2, 3)
47 Visitor
*validate_test_init(TestInputVisitorData
*data
,
48 const char *json_string
, ...)
53 va_start(ap
, json_string
);
54 data
->obj
= qobject_from_jsonv(json_string
, &ap
);
57 g_assert(data
->obj
!= NULL
);
59 data
->qiv
= qmp_input_visitor_new_strict(data
->obj
);
60 g_assert(data
->qiv
!= NULL
);
62 v
= qmp_input_get_visitor(data
->qiv
);
68 /* similar to validate_test_init(), but does not expect a string
69 * literal/format json_string argument and so can be used for
70 * programatically generated strings (and we can't pass in programatically
71 * generated strings via %s format parameters since qobject_from_jsonv()
72 * will wrap those in double-quotes and treat the entire object as a
75 static Visitor
*validate_test_init_raw(TestInputVisitorData
*data
,
76 const char *json_string
)
80 data
->obj
= qobject_from_json(json_string
);
81 g_assert(data
->obj
!= NULL
);
83 data
->qiv
= qmp_input_visitor_new_strict(data
->obj
);
84 g_assert(data
->qiv
!= NULL
);
86 v
= qmp_input_get_visitor(data
->qiv
);
92 typedef struct TestStruct
99 static void visit_type_TestStruct(Visitor
*v
, TestStruct
**obj
,
100 const char *name
, Error
**errp
)
104 visit_start_struct(v
, (void **)obj
, "TestStruct", name
, sizeof(TestStruct
),
110 visit_type_int(v
, &(*obj
)->integer
, "integer", &err
);
114 visit_type_bool(v
, &(*obj
)->boolean
, "boolean", &err
);
118 visit_type_str(v
, &(*obj
)->string
, "string", &err
);
121 error_propagate(errp
, err
);
123 visit_end_struct(v
, &err
);
125 error_propagate(errp
, err
);
128 static void test_validate_struct(TestInputVisitorData
*data
,
131 TestStruct
*p
= NULL
;
135 v
= validate_test_init(data
, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
137 visit_type_TestStruct(v
, &p
, NULL
, &err
);
143 static void test_validate_struct_nested(TestInputVisitorData
*data
,
146 UserDefTwo
*udp
= NULL
;
150 v
= validate_test_init(data
, "{ 'string0': 'string0', "
151 "'dict1': { 'string1': 'string1', "
152 "'dict2': { 'userdef': { 'integer': 42, "
153 "'string': 'string' }, 'string': 'string2'}}}");
155 visit_type_UserDefTwo(v
, &udp
, NULL
, &err
);
157 qapi_free_UserDefTwo(udp
);
160 static void test_validate_list(TestInputVisitorData
*data
,
163 UserDefOneList
*head
= NULL
;
167 v
= validate_test_init(data
, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
169 visit_type_UserDefOneList(v
, &head
, NULL
, &err
);
171 qapi_free_UserDefOneList(head
);
174 static void test_validate_union_native_list(TestInputVisitorData
*data
,
177 UserDefNativeListUnion
*tmp
= NULL
;
181 v
= validate_test_init(data
, "{ 'type': 'integer', 'data' : [ 1, 2 ] }");
183 visit_type_UserDefNativeListUnion(v
, &tmp
, NULL
, &err
);
185 qapi_free_UserDefNativeListUnion(tmp
);
188 static void test_validate_union_flat(TestInputVisitorData
*data
,
191 UserDefFlatUnion
*tmp
= NULL
;
195 v
= validate_test_init(data
,
196 "{ 'enum1': 'value1', "
199 "'boolean': true }");
201 visit_type_UserDefFlatUnion(v
, &tmp
, NULL
, &err
);
203 qapi_free_UserDefFlatUnion(tmp
);
206 static void test_validate_alternate(TestInputVisitorData
*data
,
209 UserDefAlternate
*tmp
= NULL
;
213 v
= validate_test_init(data
, "42");
215 visit_type_UserDefAlternate(v
, &tmp
, NULL
, &err
);
217 qapi_free_UserDefAlternate(tmp
);
220 static void test_validate_fail_struct(TestInputVisitorData
*data
,
223 TestStruct
*p
= NULL
;
227 v
= validate_test_init(data
, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
229 visit_type_TestStruct(v
, &p
, NULL
, &err
);
237 static void test_validate_fail_struct_nested(TestInputVisitorData
*data
,
240 UserDefTwo
*udp
= NULL
;
244 v
= validate_test_init(data
, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
246 visit_type_UserDefTwo(v
, &udp
, NULL
, &err
);
248 qapi_free_UserDefTwo(udp
);
251 static void test_validate_fail_list(TestInputVisitorData
*data
,
254 UserDefOneList
*head
= NULL
;
258 v
= validate_test_init(data
, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
260 visit_type_UserDefOneList(v
, &head
, NULL
, &err
);
262 qapi_free_UserDefOneList(head
);
265 static void test_validate_fail_union_native_list(TestInputVisitorData
*data
,
268 UserDefNativeListUnion
*tmp
= NULL
;
272 v
= validate_test_init(data
,
273 "{ 'type': 'integer', 'data' : [ 'string' ] }");
275 visit_type_UserDefNativeListUnion(v
, &tmp
, NULL
, &err
);
277 qapi_free_UserDefNativeListUnion(tmp
);
280 static void test_validate_fail_union_flat(TestInputVisitorData
*data
,
283 UserDefFlatUnion
*tmp
= NULL
;
287 v
= validate_test_init(data
, "{ 'string': 'c', 'integer': 41, 'boolean': true }");
289 visit_type_UserDefFlatUnion(v
, &tmp
, NULL
, &err
);
291 qapi_free_UserDefFlatUnion(tmp
);
294 static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData
*data
,
297 UserDefFlatUnion2
*tmp
= NULL
;
301 /* test situation where discriminator field ('enum1' here) is missing */
302 v
= validate_test_init(data
, "{ 'integer': 42, 'string': 'c', 'string1': 'd', 'string2': 'e' }");
304 visit_type_UserDefFlatUnion2(v
, &tmp
, NULL
, &err
);
306 qapi_free_UserDefFlatUnion2(tmp
);
309 static void test_validate_fail_alternate(TestInputVisitorData
*data
,
312 UserDefAlternate
*tmp
= NULL
;
316 v
= validate_test_init(data
, "3.14");
318 visit_type_UserDefAlternate(v
, &tmp
, NULL
, &err
);
320 qapi_free_UserDefAlternate(tmp
);
323 static void do_test_validate_qmp_introspect(TestInputVisitorData
*data
,
324 const char *schema_json
)
326 SchemaInfoList
*schema
= NULL
;
330 v
= validate_test_init_raw(data
, schema_json
);
332 visit_type_SchemaInfoList(v
, &schema
, NULL
, &err
);
334 fprintf(stderr
, "%s", error_get_pretty(err
));
339 qapi_free_SchemaInfoList(schema
);
342 static void test_validate_qmp_introspect(TestInputVisitorData
*data
,
345 do_test_validate_qmp_introspect(data
, test_qmp_schema_json
);
346 do_test_validate_qmp_introspect(data
, qmp_schema_json
);
349 static void validate_test_add(const char *testpath
,
350 TestInputVisitorData
*data
,
351 void (*test_func
)(TestInputVisitorData
*data
, const void *user_data
))
353 g_test_add(testpath
, TestInputVisitorData
, data
, NULL
, test_func
,
357 int main(int argc
, char **argv
)
359 TestInputVisitorData testdata
;
361 g_test_init(&argc
, &argv
, NULL
);
363 validate_test_add("/visitor/input-strict/pass/struct",
364 &testdata
, test_validate_struct
);
365 validate_test_add("/visitor/input-strict/pass/struct-nested",
366 &testdata
, test_validate_struct_nested
);
367 validate_test_add("/visitor/input-strict/pass/list",
368 &testdata
, test_validate_list
);
369 validate_test_add("/visitor/input-strict/pass/union-flat",
370 &testdata
, test_validate_union_flat
);
371 validate_test_add("/visitor/input-strict/pass/alternate",
372 &testdata
, test_validate_alternate
);
373 validate_test_add("/visitor/input-strict/pass/union-native-list",
374 &testdata
, test_validate_union_native_list
);
375 validate_test_add("/visitor/input-strict/fail/struct",
376 &testdata
, test_validate_fail_struct
);
377 validate_test_add("/visitor/input-strict/fail/struct-nested",
378 &testdata
, test_validate_fail_struct_nested
);
379 validate_test_add("/visitor/input-strict/fail/list",
380 &testdata
, test_validate_fail_list
);
381 validate_test_add("/visitor/input-strict/fail/union-flat",
382 &testdata
, test_validate_fail_union_flat
);
383 validate_test_add("/visitor/input-strict/fail/union-flat-no-discriminator",
384 &testdata
, test_validate_fail_union_flat_no_discrim
);
385 validate_test_add("/visitor/input-strict/fail/alternate",
386 &testdata
, test_validate_fail_alternate
);
387 validate_test_add("/visitor/input-strict/fail/union-native-list",
388 &testdata
, test_validate_fail_union_native_list
);
389 validate_test_add("/visitor/input-strict/pass/qmp-introspect",
390 &testdata
, test_validate_qmp_introspect
);