提交 a8b4f958 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2015-11-10' into staging

QAPI patches

# gpg: Signature made Tue 10 Nov 2015 07:12:25 GMT using RSA key ID EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"

* remotes/armbru/tags/pull-qapi-2015-11-10:
  qapi-introspect: Document lack of sorting
  qapi: Provide nicer array names in introspection
  qapi: More tests of input arrays
  qapi: Test failure in middle of array parse
  qapi: More tests of alternate output
  qapi: Simplify error cleanup in test-qmp-*
  qapi: Simplify non-error testing in test-qmp-*
  qapi: Plug leaks in test-qmp-*
  qapi: Share test_init code in test-qmp-input*
  qobject: Protect against use-after-free in qobject_decref()
  qapi: Strengthen test of TestStructList
  qapi: Use generated TestStruct machinery in tests
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
...@@ -516,6 +516,10 @@ query-qmp-schema. QGA currently doesn't support introspection. ...@@ -516,6 +516,10 @@ query-qmp-schema. QGA currently doesn't support introspection.
query-qmp-schema returns a JSON array of SchemaInfo objects. These query-qmp-schema returns a JSON array of SchemaInfo objects. These
objects together describe the wire ABI, as defined in the QAPI schema. objects together describe the wire ABI, as defined in the QAPI schema.
There is no specified order to the SchemaInfo objects returned; a
client must search for a particular name throughout the entire array
to learn more about that name, but is at least guaranteed that there
will be no collisions between type, command, and event names.
However, the SchemaInfo can't reflect all the rules and restrictions However, the SchemaInfo can't reflect all the rules and restrictions
that apply to QMP. It's interface introspection (figuring out what's that apply to QMP. It's interface introspection (figuring out what's
...@@ -596,7 +600,9 @@ any. Each element is a JSON object with members "name" (the member's ...@@ -596,7 +600,9 @@ any. Each element is a JSON object with members "name" (the member's
name), "type" (the name of its type), and optionally "default". The name), "type" (the name of its type), and optionally "default". The
member is optional if "default" is present. Currently, "default" can member is optional if "default" is present. Currently, "default" can
only have value null. Other values are reserved for future only have value null. Other values are reserved for future
extensions. extensions. The "members" array is in no particular order; clients
must search the entire object when learning whether a particular
member is supported.
Example: the SchemaInfo for MyType from section Struct types Example: the SchemaInfo for MyType from section Struct types
...@@ -610,7 +616,9 @@ Example: the SchemaInfo for MyType from section Struct types ...@@ -610,7 +616,9 @@ Example: the SchemaInfo for MyType from section Struct types
"variants" is a JSON array describing the object's variant members. "variants" is a JSON array describing the object's variant members.
Each element is a JSON object with members "case" (the value of type Each element is a JSON object with members "case" (the value of type
tag this element applies to) and "type" (the name of an object type tag this element applies to) and "type" (the name of an object type
that provides the variant members for this type tag value). that provides the variant members for this type tag value). The
"variants" array is in no particular order, and is not guaranteed to
list cases in the same order as the corresponding "tag" enum type.
Example: the SchemaInfo for flat union BlockdevOptions from section Example: the SchemaInfo for flat union BlockdevOptions from section
Union types Union types
...@@ -651,7 +659,8 @@ Union types ...@@ -651,7 +659,8 @@ Union types
The SchemaInfo for an alternate type has meta-type "alternate", and The SchemaInfo for an alternate type has meta-type "alternate", and
variant member "members". "members" is a JSON array. Each element is variant member "members". "members" is a JSON array. Each element is
a JSON object with member "type", which names a type. Values of the a JSON object with member "type", which names a type. Values of the
alternate type conform to exactly one of its member types. alternate type conform to exactly one of its member types. There is
no guarantee on the order in which "members" will be listed.
Example: the SchemaInfo for BlockRef from section Alternate types Example: the SchemaInfo for BlockRef from section Alternate types
...@@ -662,15 +671,20 @@ Example: the SchemaInfo for BlockRef from section Alternate types ...@@ -662,15 +671,20 @@ Example: the SchemaInfo for BlockRef from section Alternate types
The SchemaInfo for an array type has meta-type "array", and variant The SchemaInfo for an array type has meta-type "array", and variant
member "element-type", which names the array's element type. Array member "element-type", which names the array's element type. Array
types are implicitly defined. types are implicitly defined. For convenience, the array's name may
resemble the element type; however, clients should examine member
"element-type" instead of making assumptions based on parsing member
"name".
Example: the SchemaInfo for ['str'] Example: the SchemaInfo for ['str']
{ "name": "strList", "meta-type": "array", { "name": "[str]", "meta-type": "array",
"element-type": "str" } "element-type": "str" }
The SchemaInfo for an enumeration type has meta-type "enum" and The SchemaInfo for an enumeration type has meta-type "enum" and
variant member "values". variant member "values". The values are listed in no particular
order; clients must search the entire enum when learning whether a
particular value is supported.
Example: the SchemaInfo for MyEnum from section Enumeration types Example: the SchemaInfo for MyEnum from section Enumeration types
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
* Handle an error without reporting it (just for completeness): * Handle an error without reporting it (just for completeness):
* error_free(err); * error_free(err);
* *
* Assert that an expected error occurred, but clean it up without
* reporting it (primarily useful in testsuites):
* error_free_or_abort(&err);
*
* Pass an existing error to the caller: * Pass an existing error to the caller:
* error_propagate(errp, err); * error_propagate(errp, err);
* where Error **errp is a parameter, by convention the last one. * where Error **errp is a parameter, by convention the last one.
...@@ -189,6 +193,11 @@ Error *error_copy(const Error *err); ...@@ -189,6 +193,11 @@ Error *error_copy(const Error *err);
*/ */
void error_free(Error *err); void error_free(Error *err);
/*
* Convenience function to assert that *@errp is set, then silently free it.
*/
void error_free_or_abort(Error **errp);
/* /*
* Convenience function to error_report() and free @err. * Convenience function to error_report() and free @err.
*/ */
......
...@@ -90,6 +90,7 @@ static inline void qobject_incref(QObject *obj) ...@@ -90,6 +90,7 @@ static inline void qobject_incref(QObject *obj)
*/ */
static inline void qobject_decref(QObject *obj) static inline void qobject_decref(QObject *obj)
{ {
assert(!obj || obj->refcnt);
if (obj && --obj->refcnt == 0) { if (obj && --obj->refcnt == 0) {
assert(obj->type != NULL); assert(obj->type != NULL);
assert(obj->type->destroy != NULL); assert(obj->type->destroy != NULL);
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
# Returns: array of @SchemaInfo, where each element describes an # Returns: array of @SchemaInfo, where each element describes an
# entity in the ABI: command, event, type, ... # entity in the ABI: command, event, type, ...
# #
# The order of the various SchemaInfo is unspecified; however, all
# names are guaranteed to be unique (no name will be duplicated with
# different meta-types).
#
# Note: the QAPI schema is also used to help define *internal* # Note: the QAPI schema is also used to help define *internal*
# interfaces, by defining QAPI types. These are not part of the QMP # interfaces, by defining QAPI types. These are not part of the QMP
# wire ABI, and therefore not returned by this command. # wire ABI, and therefore not returned by this command.
...@@ -78,7 +82,8 @@ ...@@ -78,7 +82,8 @@
# Commands and events have the name defined in the QAPI schema. # Commands and events have the name defined in the QAPI schema.
# Unlike command and event names, type names are not part of # Unlike command and event names, type names are not part of
# the wire ABI. Consequently, type names are meaningless # the wire ABI. Consequently, type names are meaningless
# strings here. # strings here, although they are still guaranteed unique
# regardless of @meta-type.
# #
# All references to other SchemaInfo are by name. # All references to other SchemaInfo are by name.
# #
...@@ -130,7 +135,7 @@ ...@@ -130,7 +135,7 @@
# #
# Additional SchemaInfo members for meta-type 'enum'. # Additional SchemaInfo members for meta-type 'enum'.
# #
# @values: the enumeration type's values. # @values: the enumeration type's values, in no particular order.
# #
# Values of this type are JSON string on the wire. # Values of this type are JSON string on the wire.
# #
...@@ -158,14 +163,16 @@ ...@@ -158,14 +163,16 @@
# #
# Additional SchemaInfo members for meta-type 'object'. # Additional SchemaInfo members for meta-type 'object'.
# #
# @members: the object type's (non-variant) members. # @members: the object type's (non-variant) members, in no particular order.
# #
# @tag: #optional the name of the member serving as type tag. # @tag: #optional the name of the member serving as type tag.
# An element of @members with this name must exist. # An element of @members with this name must exist.
# #
# @variants: #optional variant members, i.e. additional members that # @variants: #optional variant members, i.e. additional members that
# depend on the type tag's value. Present exactly when # depend on the type tag's value. Present exactly when
# @tag is present. # @tag is present. The variants are in no particular order,
# and may even differ from the order of the values of the
# enum type of the @tag.
# #
# Values of this type are JSON object on the wire. # Values of this type are JSON object on the wire.
# #
...@@ -219,7 +226,7 @@ ...@@ -219,7 +226,7 @@
# #
# Additional SchemaInfo members for meta-type 'alternate'. # Additional SchemaInfo members for meta-type 'alternate'.
# #
# @members: the alternate type's members. # @members: the alternate type's members, in no particular order.
# The members' wire encoding is distinct, see # The members' wire encoding is distinct, see
# docs/qapi-code-gen.txt section Alternate types. # docs/qapi-code-gen.txt section Alternate types.
# #
......
...@@ -107,10 +107,12 @@ const char %(c_name)s[] = %(c_string)s; ...@@ -107,10 +107,12 @@ const char %(c_name)s[] = %(c_string)s;
# characters. # characters.
if isinstance(typ, QAPISchemaBuiltinType): if isinstance(typ, QAPISchemaBuiltinType):
return typ.name return typ.name
if isinstance(typ, QAPISchemaArrayType):
return '[' + self._use_type(typ.element_type) + ']'
return self._name(typ.name) return self._name(typ.name)
def _gen_json(self, name, mtype, obj): def _gen_json(self, name, mtype, obj):
if mtype != 'command' and mtype != 'event' and mtype != 'builtin': if mtype not in ('command', 'event', 'builtin', 'array'):
name = self._name(name) name = self._name(name)
obj['name'] = name obj['name'] = name
obj['meta-type'] = mtype obj['meta-type'] = mtype
...@@ -136,8 +138,8 @@ const char %(c_name)s[] = %(c_string)s; ...@@ -136,8 +138,8 @@ const char %(c_name)s[] = %(c_string)s;
self._gen_json(name, 'enum', {'values': values}) self._gen_json(name, 'enum', {'values': values})
def visit_array_type(self, name, info, element_type): def visit_array_type(self, name, info, element_type):
self._gen_json(name, 'array', element = self._use_type(element_type)
{'element-type': self._use_type(element_type)}) self._gen_json('[' + element + ']', 'array', {'element-type': element})
def visit_object_type_flat(self, name, info, members, variants): def visit_object_type_flat(self, name, info, members, variants):
obj = {'members': [self._gen_member(m) for m in members]} obj = {'members': [self._gen_member(m) for m in members]}
......
...@@ -138,6 +138,10 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error ...@@ -138,6 +138,10 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error
def gen_visit_list(name, element_type): def gen_visit_list(name, element_type):
# FIXME: if *obj is NULL on entry, and the first visit_next_list()
# assigns to *obj, while a later one fails, we should clean up *obj
# rather than leaving it non-NULL. As currently written, the caller must
# call qapi_free_FOOList() to avoid a memory leak of the partial FOOList.
return mcgen(''' return mcgen('''
void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp) void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
# This file is a stress test of supported qapi constructs that must # This file is a stress test of supported qapi constructs that must
# parse and compile correctly. # parse and compile correctly.
{ 'struct': 'TestStruct',
'data': { 'integer': 'int', 'boolean': 'bool', 'string': 'str' } }
# for testing enums # for testing enums
{ 'struct': 'NestedEnumsOne', { 'struct': 'NestedEnumsOne',
'data': { 'enum1': 'EnumOne', # Intentional forward reference 'data': { 'enum1': 'EnumOne', # Intentional forward reference
...@@ -46,7 +49,8 @@ ...@@ -46,7 +49,8 @@
# dummy struct to force generation of array types not otherwise mentioned # dummy struct to force generation of array types not otherwise mentioned
{ 'struct': 'ForceArrays', { 'struct': 'ForceArrays',
'data': { 'unused1':['UserDefOne'], 'unused2':['UserDefTwo'] } } 'data': { 'unused1':['UserDefOne'], 'unused2':['UserDefTwo'],
'unused3':['TestStruct'] } }
# for testing unions # for testing unions
# Among other things, test that a name collision between branches does # Among other things, test that a name collision between branches does
......
...@@ -92,6 +92,7 @@ object EventStructOne ...@@ -92,6 +92,7 @@ object EventStructOne
object ForceArrays object ForceArrays
member unused1: UserDefOneList optional=False member unused1: UserDefOneList optional=False
member unused2: UserDefTwoList optional=False member unused2: UserDefTwoList optional=False
member unused3: TestStructList optional=False
enum MyEnum [] enum MyEnum []
object NestedEnumsOne object NestedEnumsOne
member enum1: EnumOne optional=False member enum1: EnumOne optional=False
...@@ -100,6 +101,10 @@ object NestedEnumsOne ...@@ -100,6 +101,10 @@ object NestedEnumsOne
member enum4: EnumOne optional=True member enum4: EnumOne optional=True
enum QEnumTwo ['value1', 'value2'] enum QEnumTwo ['value1', 'value2']
prefix QENUM_TWO prefix QENUM_TWO
object TestStruct
member integer: int optional=False
member boolean: bool optional=False
member string: str optional=False
object UserDefA object UserDefA
member boolean: bool optional=False member boolean: bool optional=False
member a_b: int optional=True member a_b: int optional=True
......
...@@ -225,8 +225,7 @@ static void test_dealloc_partial(void) ...@@ -225,8 +225,7 @@ static void test_dealloc_partial(void)
assert(ud2->dict1 == NULL); assert(ud2->dict1 == NULL);
/* confirm & release construction error */ /* confirm & release construction error */
assert(err != NULL); error_free_or_abort(&err);
error_free(err);
/* tear down partial object */ /* tear down partial object */
qapi_free_UserDefTwo(ud2); qapi_free_UserDefTwo(ud2);
......
...@@ -40,31 +40,42 @@ static void validate_teardown(TestInputVisitorData *data, ...@@ -40,31 +40,42 @@ static void validate_teardown(TestInputVisitorData *data,
} }
} }
/* This is provided instead of a test setup function so that the JSON /* The various test_init functions are provided instead of a test setup
string used by the tests are kept in the test functions (and not function so that the JSON string used by the tests are kept in the test
int main()) */ functions (and not in main()). */
static GCC_FMT_ATTR(2, 3) static Visitor *validate_test_init_internal(TestInputVisitorData *data,
Visitor *validate_test_init(TestInputVisitorData *data, const char *json_string,
const char *json_string, ...) va_list *ap)
{ {
Visitor *v; Visitor *v;
va_list ap;
va_start(ap, json_string); validate_teardown(data, NULL);
data->obj = qobject_from_jsonv(json_string, &ap);
va_end(ap);
g_assert(data->obj != NULL); data->obj = qobject_from_jsonv(json_string, ap);
g_assert(data->obj);
data->qiv = qmp_input_visitor_new_strict(data->obj); data->qiv = qmp_input_visitor_new_strict(data->obj);
g_assert(data->qiv != NULL); g_assert(data->qiv);
v = qmp_input_get_visitor(data->qiv); v = qmp_input_get_visitor(data->qiv);
g_assert(v != NULL); g_assert(v);
return v; return v;
} }
static GCC_FMT_ATTR(2, 3)
Visitor *validate_test_init(TestInputVisitorData *data,
const char *json_string, ...)
{
Visitor *v;
va_list ap;
va_start(ap, json_string);
v = validate_test_init_internal(data, json_string, &ap);
va_end(ap);
return v;
}
/* similar to validate_test_init(), but does not expect a string /* similar to validate_test_init(), but does not expect a string
* literal/format json_string argument and so can be used for * literal/format json_string argument and so can be used for
* programatically generated strings (and we can't pass in programatically * programatically generated strings (and we can't pass in programatically
...@@ -75,67 +86,19 @@ Visitor *validate_test_init(TestInputVisitorData *data, ...@@ -75,67 +86,19 @@ Visitor *validate_test_init(TestInputVisitorData *data,
static Visitor *validate_test_init_raw(TestInputVisitorData *data, static Visitor *validate_test_init_raw(TestInputVisitorData *data,
const char *json_string) const char *json_string)
{ {
Visitor *v; return validate_test_init_internal(data, json_string, NULL);
data->obj = qobject_from_json(json_string);
g_assert(data->obj != NULL);
data->qiv = qmp_input_visitor_new_strict(data->obj);
g_assert(data->qiv != NULL);
v = qmp_input_get_visitor(data->qiv);
g_assert(v != NULL);
return v;
} }
typedef struct TestStruct
{
int64_t integer;
bool boolean;
char *string;
} TestStruct;
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
const char *name, Error **errp)
{
Error *err = NULL;
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
&err);
if (err) {
goto out;
}
visit_type_int(v, &(*obj)->integer, "integer", &err);
if (err) {
goto out_end;
}
visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
if (err) {
goto out_end;
}
visit_type_str(v, &(*obj)->string, "string", &err);
out_end:
error_propagate(errp, err);
err = NULL;
visit_end_struct(v, &err);
out:
error_propagate(errp, err);
}
static void test_validate_struct(TestInputVisitorData *data, static void test_validate_struct(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
TestStruct *p = NULL; TestStruct *p = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }"); v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
visit_type_TestStruct(v, &p, NULL, &err); visit_type_TestStruct(v, &p, NULL, &error_abort);
g_assert(!err);
g_free(p->string); g_free(p->string);
g_free(p); g_free(p);
} }
...@@ -144,7 +107,6 @@ static void test_validate_struct_nested(TestInputVisitorData *data, ...@@ -144,7 +107,6 @@ static void test_validate_struct_nested(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
UserDefTwo *udp = NULL; UserDefTwo *udp = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
v = validate_test_init(data, "{ 'string0': 'string0', " v = validate_test_init(data, "{ 'string0': 'string0', "
...@@ -152,8 +114,7 @@ static void test_validate_struct_nested(TestInputVisitorData *data, ...@@ -152,8 +114,7 @@ static void test_validate_struct_nested(TestInputVisitorData *data,
"'dict2': { 'userdef': { 'integer': 42, " "'dict2': { 'userdef': { 'integer': 42, "
"'string': 'string' }, 'string': 'string2'}}}"); "'string': 'string' }, 'string': 'string2'}}}");
visit_type_UserDefTwo(v, &udp, NULL, &err); visit_type_UserDefTwo(v, &udp, NULL, &error_abort);
g_assert(!err);
qapi_free_UserDefTwo(udp); qapi_free_UserDefTwo(udp);
} }
...@@ -161,13 +122,11 @@ static void test_validate_list(TestInputVisitorData *data, ...@@ -161,13 +122,11 @@ static void test_validate_list(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
UserDefOneList *head = NULL; UserDefOneList *head = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]"); v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
visit_type_UserDefOneList(v, &head, NULL, &err); visit_type_UserDefOneList(v, &head, NULL, &error_abort);
g_assert(!err);
qapi_free_UserDefOneList(head); qapi_free_UserDefOneList(head);
} }
...@@ -176,12 +135,10 @@ static void test_validate_union_native_list(TestInputVisitorData *data, ...@@ -176,12 +135,10 @@ static void test_validate_union_native_list(TestInputVisitorData *data,
{ {
UserDefNativeListUnion *tmp = NULL; UserDefNativeListUnion *tmp = NULL;
Visitor *v; Visitor *v;
Error *err = NULL;
v = validate_test_init(data, "{ 'type': 'integer', 'data' : [ 1, 2 ] }"); v = validate_test_init(data, "{ 'type': 'integer', 'data' : [ 1, 2 ] }");
visit_type_UserDefNativeListUnion(v, &tmp, NULL, &err); visit_type_UserDefNativeListUnion(v, &tmp, NULL, &error_abort);
g_assert(!err);
qapi_free_UserDefNativeListUnion(tmp); qapi_free_UserDefNativeListUnion(tmp);
} }
...@@ -190,7 +147,6 @@ static void test_validate_union_flat(TestInputVisitorData *data, ...@@ -190,7 +147,6 @@ static void test_validate_union_flat(TestInputVisitorData *data,
{ {
UserDefFlatUnion *tmp = NULL; UserDefFlatUnion *tmp = NULL;
Visitor *v; Visitor *v;
Error *err = NULL;
v = validate_test_init(data, v = validate_test_init(data,
"{ 'enum1': 'value1', " "{ 'enum1': 'value1', "
...@@ -198,8 +154,7 @@ static void test_validate_union_flat(TestInputVisitorData *data, ...@@ -198,8 +154,7 @@ static void test_validate_union_flat(TestInputVisitorData *data,
"'string': 'str', " "'string': 'str', "
"'boolean': true }"); "'boolean': true }");
visit_type_UserDefFlatUnion(v, &tmp, NULL, &err); visit_type_UserDefFlatUnion(v, &tmp, NULL, &error_abort);
g_assert(!err);
qapi_free_UserDefFlatUnion(tmp); qapi_free_UserDefFlatUnion(tmp);
} }
...@@ -208,12 +163,10 @@ static void test_validate_alternate(TestInputVisitorData *data, ...@@ -208,12 +163,10 @@ static void test_validate_alternate(TestInputVisitorData *data,
{ {
UserDefAlternate *tmp = NULL; UserDefAlternate *tmp = NULL;
Visitor *v; Visitor *v;
Error *err = NULL;
v = validate_test_init(data, "42"); v = validate_test_init(data, "42");
visit_type_UserDefAlternate(v, &tmp, NULL, &err); visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
g_assert(!err);
qapi_free_UserDefAlternate(tmp); qapi_free_UserDefAlternate(tmp);
} }
...@@ -227,7 +180,7 @@ static void test_validate_fail_struct(TestInputVisitorData *data, ...@@ -227,7 +180,7 @@ static void test_validate_fail_struct(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }"); v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
visit_type_TestStruct(v, &p, NULL, &err); visit_type_TestStruct(v, &p, NULL, &err);
g_assert(err); error_free_or_abort(&err);
if (p) { if (p) {
g_free(p->string); g_free(p->string);
} }
...@@ -244,7 +197,7 @@ static void test_validate_fail_struct_nested(TestInputVisitorData *data, ...@@ -244,7 +197,7 @@ static void test_validate_fail_struct_nested(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}"); v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
visit_type_UserDefTwo(v, &udp, NULL, &err); visit_type_UserDefTwo(v, &udp, NULL, &err);
g_assert(err); error_free_or_abort(&err);
qapi_free_UserDefTwo(udp); qapi_free_UserDefTwo(udp);
} }
...@@ -258,7 +211,7 @@ static void test_validate_fail_list(TestInputVisitorData *data, ...@@ -258,7 +211,7 @@ static void test_validate_fail_list(TestInputVisitorData *data,
v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]"); v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
visit_type_UserDefOneList(v, &head, NULL, &err); visit_type_UserDefOneList(v, &head, NULL, &err);
g_assert(err); error_free_or_abort(&err);
qapi_free_UserDefOneList(head); qapi_free_UserDefOneList(head);
} }
...@@ -273,7 +226,7 @@ static void test_validate_fail_union_native_list(TestInputVisitorData *data, ...@@ -273,7 +226,7 @@ static void test_validate_fail_union_native_list(TestInputVisitorData *data,
"{ 'type': 'integer', 'data' : [ 'string' ] }"); "{ 'type': 'integer', 'data' : [ 'string' ] }");
visit_type_UserDefNativeListUnion(v, &tmp, NULL, &err); visit_type_UserDefNativeListUnion(v, &tmp, NULL, &err);
g_assert(err); error_free_or_abort(&err);
qapi_free_UserDefNativeListUnion(tmp); qapi_free_UserDefNativeListUnion(tmp);
} }
...@@ -287,7 +240,7 @@ static void test_validate_fail_union_flat(TestInputVisitorData *data, ...@@ -287,7 +240,7 @@ static void test_validate_fail_union_flat(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'string': 'c', 'integer': 41, 'boolean': true }"); v = validate_test_init(data, "{ 'string': 'c', 'integer': 41, 'boolean': true }");
visit_type_UserDefFlatUnion(v, &tmp, NULL, &err); visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
g_assert(err); error_free_or_abort(&err);
qapi_free_UserDefFlatUnion(tmp); qapi_free_UserDefFlatUnion(tmp);
} }
...@@ -302,7 +255,7 @@ static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData *data, ...@@ -302,7 +255,7 @@ static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'integer': 42, 'string': 'c', 'string1': 'd', 'string2': 'e' }"); v = validate_test_init(data, "{ 'integer': 42, 'string': 'c', 'string1': 'd', 'string2': 'e' }");
visit_type_UserDefFlatUnion2(v, &tmp, NULL, &err); visit_type_UserDefFlatUnion2(v, &tmp, NULL, &err);
g_assert(err); error_free_or_abort(&err);
qapi_free_UserDefFlatUnion2(tmp); qapi_free_UserDefFlatUnion2(tmp);
} }
...@@ -316,7 +269,7 @@ static void test_validate_fail_alternate(TestInputVisitorData *data, ...@@ -316,7 +269,7 @@ static void test_validate_fail_alternate(TestInputVisitorData *data,
v = validate_test_init(data, "3.14"); v = validate_test_init(data, "3.14");
visit_type_UserDefAlternate(v, &tmp, NULL, &err); visit_type_UserDefAlternate(v, &tmp, NULL, &err);
g_assert(err); error_free_or_abort(&err);
qapi_free_UserDefAlternate(tmp); qapi_free_UserDefAlternate(tmp);
} }
...@@ -324,16 +277,11 @@ static void do_test_validate_qmp_introspect(TestInputVisitorData *data, ...@@ -324,16 +277,11 @@ static void do_test_validate_qmp_introspect(TestInputVisitorData *data,
const char *schema_json) const char *schema_json)
{ {
SchemaInfoList *schema = NULL; SchemaInfoList *schema = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
v = validate_test_init_raw(data, schema_json); v = validate_test_init_raw(data, schema_json);
visit_type_SchemaInfoList(v, &schema, NULL, &err); visit_type_SchemaInfoList(v, &schema, NULL, &error_abort);
if (err) {
fprintf(stderr, "%s", error_get_pretty(err));
}
g_assert(!err);
g_assert(schema); g_assert(schema);
qapi_free_SchemaInfoList(schema); qapi_free_SchemaInfoList(schema);
......
...@@ -36,28 +36,39 @@ static void visitor_input_teardown(TestInputVisitorData *data, ...@@ -36,28 +36,39 @@ static void visitor_input_teardown(TestInputVisitorData *data,
} }
} }
/* This is provided instead of a test setup function so that the JSON /* The various test_init functions are provided instead of a test setup
string used by the tests are kept in the test functions (and not function so that the JSON string used by the tests are kept in the test
int main()) */ functions (and not in main()). */
static GCC_FMT_ATTR(2, 3) static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
Visitor *visitor_input_test_init(TestInputVisitorData *data, const char *json_string,
const char *json_string, ...) va_list *ap)
{ {
Visitor *v; Visitor *v;
va_list ap;
va_start(ap, json_string); visitor_input_teardown(data, NULL);
data->obj = qobject_from_jsonv(json_string, &ap);
va_end(ap);
g_assert(data->obj != NULL); data->obj = qobject_from_jsonv(json_string, ap);
g_assert(data->obj);
data->qiv = qmp_input_visitor_new(data->obj); data->qiv = qmp_input_visitor_new(data->obj);
g_assert(data->qiv != NULL); g_assert(data->qiv);
v = qmp_input_get_visitor(data->qiv); v = qmp_input_get_visitor(data->qiv);
g_assert(v != NULL); g_assert(v);
return v;
}
static GCC_FMT_ATTR(2, 3)
Visitor *visitor_input_test_init(TestInputVisitorData *data,
const char *json_string, ...)
{
Visitor *v;
va_list ap;
va_start(ap, json_string);
v = visitor_input_test_init_internal(data, json_string, &ap);
va_end(ap);
return v; return v;
} }
...@@ -71,32 +82,18 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data, ...@@ -71,32 +82,18 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data,
static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data, static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
const char *json_string) const char *json_string)
{ {
Visitor *v; return visitor_input_test_init_internal(data, json_string, NULL);
data->obj = qobject_from_json(json_string);
g_assert(data->obj != NULL);
data->qiv = qmp_input_visitor_new(data->obj);
g_assert(data->qiv != NULL);
v = qmp_input_get_visitor(data->qiv);
g_assert(v != NULL);
return v;
} }
static void test_visitor_in_int(TestInputVisitorData *data, static void test_visitor_in_int(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
int64_t res = 0, value = -42; int64_t res = 0, value = -42;
Error *err = NULL;
Visitor *v; Visitor *v;
v = visitor_input_test_init(data, "%" PRId64, value); v = visitor_input_test_init(data, "%" PRId64, value);
visit_type_int(v, &res, NULL, &err); visit_type_int(v, &res, NULL, &error_abort);
g_assert(!err);
g_assert_cmpint(res, ==, value); g_assert_cmpint(res, ==, value);
} }
...@@ -114,21 +111,18 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data, ...@@ -114,21 +111,18 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
v = visitor_input_test_init(data, "%f", DBL_MAX); v = visitor_input_test_init(data, "%f", DBL_MAX);
visit_type_int(v, &res, NULL, &err); visit_type_int(v, &res, NULL, &err);
g_assert(err); error_free_or_abort(&err);
error_free(err);
} }
static void test_visitor_in_bool(TestInputVisitorData *data, static void test_visitor_in_bool(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
Error *err = NULL;
bool res = false; bool res = false;
Visitor *v; Visitor *v;
v = visitor_input_test_init(data, "true"); v = visitor_input_test_init(data, "true");
visit_type_bool(v, &res, NULL, &err); visit_type_bool(v, &res, NULL, &error_abort);
g_assert(!err);
g_assert_cmpint(res, ==, true); g_assert_cmpint(res, ==, true);
} }
...@@ -136,13 +130,11 @@ static void test_visitor_in_number(TestInputVisitorData *data, ...@@ -136,13 +130,11 @@ static void test_visitor_in_number(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
double res = 0, value = 3.14; double res = 0, value = 3.14;
Error *err = NULL;
Visitor *v; Visitor *v;
v = visitor_input_test_init(data, "%f", value); v = visitor_input_test_init(data, "%f", value);
visit_type_number(v, &res, NULL, &err); visit_type_number(v, &res, NULL, &error_abort);
g_assert(!err);
g_assert_cmpfloat(res, ==, value); g_assert_cmpfloat(res, ==, value);
} }
...@@ -150,13 +142,11 @@ static void test_visitor_in_string(TestInputVisitorData *data, ...@@ -150,13 +142,11 @@ static void test_visitor_in_string(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
char *res = NULL, *value = (char *) "Q E M U"; char *res = NULL, *value = (char *) "Q E M U";
Error *err = NULL;
Visitor *v; Visitor *v;
v = visitor_input_test_init(data, "%s", value); v = visitor_input_test_init(data, "%s", value);
visit_type_str(v, &res, NULL, &err); visit_type_str(v, &res, NULL, &error_abort);
g_assert(!err);
g_assert_cmpstr(res, ==, value); g_assert_cmpstr(res, ==, value);
g_free(res); g_free(res);
...@@ -165,7 +155,6 @@ static void test_visitor_in_string(TestInputVisitorData *data, ...@@ -165,7 +155,6 @@ static void test_visitor_in_string(TestInputVisitorData *data,
static void test_visitor_in_enum(TestInputVisitorData *data, static void test_visitor_in_enum(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
Error *err = NULL;
Visitor *v; Visitor *v;
EnumOne i; EnumOne i;
...@@ -174,63 +163,21 @@ static void test_visitor_in_enum(TestInputVisitorData *data, ...@@ -174,63 +163,21 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]); v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
visit_type_EnumOne(v, &res, NULL, &err); visit_type_EnumOne(v, &res, NULL, &error_abort);
g_assert(!err);
g_assert_cmpint(i, ==, res); g_assert_cmpint(i, ==, res);
visitor_input_teardown(data, NULL);
} }
data->obj = NULL;
data->qiv = NULL;
} }
typedef struct TestStruct
{
int64_t integer;
bool boolean;
char *string;
} TestStruct;
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
const char *name, Error **errp)
{
Error *err = NULL;
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
&err);
if (err) {
goto out;
}
visit_type_int(v, &(*obj)->integer, "integer", &err);
if (err) {
goto out_end;
}
visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
if (err) {
goto out_end;
}
visit_type_str(v, &(*obj)->string, "string", &err);
out_end:
error_propagate(errp, err);
err = NULL;
visit_end_struct(v, &err);
out:
error_propagate(errp, err);
}
static void test_visitor_in_struct(TestInputVisitorData *data, static void test_visitor_in_struct(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
TestStruct *p = NULL; TestStruct *p = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }"); v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
visit_type_TestStruct(v, &p, NULL, &err); visit_type_TestStruct(v, &p, NULL, &error_abort);
g_assert(!err);
g_assert_cmpint(p->integer, ==, -42); g_assert_cmpint(p->integer, ==, -42);
g_assert(p->boolean == true); g_assert(p->boolean == true);
g_assert_cmpstr(p->string, ==, "foo"); g_assert_cmpstr(p->string, ==, "foo");
...@@ -239,17 +186,10 @@ static void test_visitor_in_struct(TestInputVisitorData *data, ...@@ -239,17 +186,10 @@ static void test_visitor_in_struct(TestInputVisitorData *data,
g_free(p); g_free(p);
} }
static void check_and_free_str(char *str, const char *cmp)
{
g_assert_cmpstr(str, ==, cmp);
g_free(str);
}
static void test_visitor_in_struct_nested(TestInputVisitorData *data, static void test_visitor_in_struct_nested(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
UserDefTwo *udp = NULL; UserDefTwo *udp = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
v = visitor_input_test_init(data, "{ 'string0': 'string0', " v = visitor_input_test_init(data, "{ 'string0': 'string0', "
...@@ -257,34 +197,28 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data, ...@@ -257,34 +197,28 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
"'dict2': { 'userdef': { 'integer': 42, " "'dict2': { 'userdef': { 'integer': 42, "
"'string': 'string' }, 'string': 'string2'}}}"); "'string': 'string' }, 'string': 'string2'}}}");
visit_type_UserDefTwo(v, &udp, NULL, &err); visit_type_UserDefTwo(v, &udp, NULL, &error_abort);
g_assert(!err);
check_and_free_str(udp->string0, "string0"); g_assert_cmpstr(udp->string0, ==, "string0");
check_and_free_str(udp->dict1->string1, "string1"); g_assert_cmpstr(udp->dict1->string1, ==, "string1");
g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42); g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
check_and_free_str(udp->dict1->dict2->userdef->string, "string"); g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
check_and_free_str(udp->dict1->dict2->string, "string2"); g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
g_assert(udp->dict1->has_dict3 == false); g_assert(udp->dict1->has_dict3 == false);
g_free(udp->dict1->dict2->userdef); qapi_free_UserDefTwo(udp);
g_free(udp->dict1->dict2);
g_free(udp->dict1);
g_free(udp);
} }
static void test_visitor_in_list(TestInputVisitorData *data, static void test_visitor_in_list(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
UserDefOneList *item, *head = NULL; UserDefOneList *item, *head = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
int i; int i;
v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]"); v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
visit_type_UserDefOneList(v, &head, NULL, &err); visit_type_UserDefOneList(v, &head, NULL, &error_abort);
g_assert(!err);
g_assert(head != NULL); g_assert(head != NULL);
for (i = 0, item = head; item; item = item->next, i++) { for (i = 0, item = head; item; item = item->next, i++) {
...@@ -296,13 +230,18 @@ static void test_visitor_in_list(TestInputVisitorData *data, ...@@ -296,13 +230,18 @@ static void test_visitor_in_list(TestInputVisitorData *data,
} }
qapi_free_UserDefOneList(head); qapi_free_UserDefOneList(head);
head = NULL;
/* An empty list is valid */
v = visitor_input_test_init(data, "[]");
visit_type_UserDefOneList(v, &head, NULL, &error_abort);
g_assert(!head);
} }
static void test_visitor_in_any(TestInputVisitorData *data, static void test_visitor_in_any(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
QObject *res = NULL; QObject *res = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
QInt *qint; QInt *qint;
QBool *qbool; QBool *qbool;
...@@ -311,16 +250,14 @@ static void test_visitor_in_any(TestInputVisitorData *data, ...@@ -311,16 +250,14 @@ static void test_visitor_in_any(TestInputVisitorData *data,
QObject *qobj; QObject *qobj;
v = visitor_input_test_init(data, "-42"); v = visitor_input_test_init(data, "-42");
visit_type_any(v, &res, NULL, &err); visit_type_any(v, &res, NULL, &error_abort);
g_assert(!err);
qint = qobject_to_qint(res); qint = qobject_to_qint(res);
g_assert(qint); g_assert(qint);
g_assert_cmpint(qint_get_int(qint), ==, -42); g_assert_cmpint(qint_get_int(qint), ==, -42);
qobject_decref(res); qobject_decref(res);
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }"); v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
visit_type_any(v, &res, NULL, &err); visit_type_any(v, &res, NULL, &error_abort);
g_assert(!err);
qdict = qobject_to_qdict(res); qdict = qobject_to_qdict(res);
g_assert(qdict && qdict_size(qdict) == 3); g_assert(qdict && qdict_size(qdict) == 3);
qobj = qdict_get(qdict, "integer"); qobj = qdict_get(qdict, "integer");
...@@ -345,7 +282,6 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, ...@@ -345,7 +282,6 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data,
const void *unused) const void *unused)
{ {
Visitor *v; Visitor *v;
Error *err = NULL;
UserDefFlatUnion *tmp; UserDefFlatUnion *tmp;
UserDefUnionBase *base; UserDefUnionBase *base;
...@@ -355,8 +291,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, ...@@ -355,8 +291,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data,
"'string': 'str', " "'string': 'str', "
"'boolean': true }"); "'boolean': true }");
visit_type_UserDefFlatUnion(v, &tmp, NULL, &err); visit_type_UserDefFlatUnion(v, &tmp, NULL, &error_abort);
g_assert(err == NULL);
g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1); g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
g_assert_cmpstr(tmp->string, ==, "str"); g_assert_cmpstr(tmp->string, ==, "str");
g_assert_cmpint(tmp->integer, ==, 41); g_assert_cmpint(tmp->integer, ==, 41);
...@@ -380,22 +315,17 @@ static void test_visitor_in_alternate(TestInputVisitorData *data, ...@@ -380,22 +315,17 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_I); g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_I);
g_assert_cmpint(tmp->u.i, ==, 42); g_assert_cmpint(tmp->u.i, ==, 42);
qapi_free_UserDefAlternate(tmp); qapi_free_UserDefAlternate(tmp);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "'string'"); v = visitor_input_test_init(data, "'string'");
visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort); visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_S); g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_S);
g_assert_cmpstr(tmp->u.s, ==, "string"); g_assert_cmpstr(tmp->u.s, ==, "string");
qapi_free_UserDefAlternate(tmp); qapi_free_UserDefAlternate(tmp);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "false"); v = visitor_input_test_init(data, "false");
visit_type_UserDefAlternate(v, &tmp, NULL, &err); visit_type_UserDefAlternate(v, &tmp, NULL, &err);
g_assert(err); error_free_or_abort(&err);
error_free(err);
err = NULL;
qapi_free_UserDefAlternate(tmp); qapi_free_UserDefAlternate(tmp);
visitor_input_teardown(data, NULL);
} }
static void test_visitor_in_alternate_number(TestInputVisitorData *data, static void test_visitor_in_alternate_number(TestInputVisitorData *data,
...@@ -414,11 +344,8 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data, ...@@ -414,11 +344,8 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
v = visitor_input_test_init(data, "42"); v = visitor_input_test_init(data, "42");
visit_type_AltStrBool(v, &asb, NULL, &err); visit_type_AltStrBool(v, &asb, NULL, &err);
g_assert(err); error_free_or_abort(&err);
error_free(err);
err = NULL;
qapi_free_AltStrBool(asb); qapi_free_AltStrBool(asb);
visitor_input_teardown(data, NULL);
/* FIXME: Order of alternate should not affect semantics; asn should /* FIXME: Order of alternate should not affect semantics; asn should
* parse the same as ans */ * parse the same as ans */
...@@ -426,85 +353,68 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data, ...@@ -426,85 +353,68 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
visit_type_AltStrNum(v, &asn, NULL, &err); visit_type_AltStrNum(v, &asn, NULL, &err);
/* FIXME g_assert_cmpint(asn->type, == ALT_STR_NUM_KIND_N); */ /* FIXME g_assert_cmpint(asn->type, == ALT_STR_NUM_KIND_N); */
/* FIXME g_assert_cmpfloat(asn->u.n, ==, 42); */ /* FIXME g_assert_cmpfloat(asn->u.n, ==, 42); */
g_assert(err); error_free_or_abort(&err);
error_free(err);
err = NULL;
qapi_free_AltStrNum(asn); qapi_free_AltStrNum(asn);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42"); v = visitor_input_test_init(data, "42");
visit_type_AltNumStr(v, &ans, NULL, &error_abort); visit_type_AltNumStr(v, &ans, NULL, &error_abort);
g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N); g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N);
g_assert_cmpfloat(ans->u.n, ==, 42); g_assert_cmpfloat(ans->u.n, ==, 42);
qapi_free_AltNumStr(ans); qapi_free_AltNumStr(ans);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42"); v = visitor_input_test_init(data, "42");
visit_type_AltStrInt(v, &asi, NULL, &error_abort); visit_type_AltStrInt(v, &asi, NULL, &error_abort);
g_assert_cmpint(asi->type, ==, ALT_STR_INT_KIND_I); g_assert_cmpint(asi->type, ==, ALT_STR_INT_KIND_I);
g_assert_cmpint(asi->u.i, ==, 42); g_assert_cmpint(asi->u.i, ==, 42);
qapi_free_AltStrInt(asi); qapi_free_AltStrInt(asi);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42"); v = visitor_input_test_init(data, "42");
visit_type_AltIntNum(v, &ain, NULL, &error_abort); visit_type_AltIntNum(v, &ain, NULL, &error_abort);
g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_I); g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_I);
g_assert_cmpint(ain->u.i, ==, 42); g_assert_cmpint(ain->u.i, ==, 42);
qapi_free_AltIntNum(ain); qapi_free_AltIntNum(ain);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42"); v = visitor_input_test_init(data, "42");
visit_type_AltNumInt(v, &ani, NULL, &error_abort); visit_type_AltNumInt(v, &ani, NULL, &error_abort);
g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_I); g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_I);
g_assert_cmpint(ani->u.i, ==, 42); g_assert_cmpint(ani->u.i, ==, 42);
qapi_free_AltNumInt(ani); qapi_free_AltNumInt(ani);
visitor_input_teardown(data, NULL);
/* Parsing a double */ /* Parsing a double */
v = visitor_input_test_init(data, "42.5"); v = visitor_input_test_init(data, "42.5");
visit_type_AltStrBool(v, &asb, NULL, &err); visit_type_AltStrBool(v, &asb, NULL, &err);
g_assert(err); error_free_or_abort(&err);
error_free(err);
err = NULL;
qapi_free_AltStrBool(asb); qapi_free_AltStrBool(asb);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5"); v = visitor_input_test_init(data, "42.5");
visit_type_AltStrNum(v, &asn, NULL, &error_abort); visit_type_AltStrNum(v, &asn, NULL, &error_abort);
g_assert_cmpint(asn->type, ==, ALT_STR_NUM_KIND_N); g_assert_cmpint(asn->type, ==, ALT_STR_NUM_KIND_N);
g_assert_cmpfloat(asn->u.n, ==, 42.5); g_assert_cmpfloat(asn->u.n, ==, 42.5);
qapi_free_AltStrNum(asn); qapi_free_AltStrNum(asn);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5"); v = visitor_input_test_init(data, "42.5");
visit_type_AltNumStr(v, &ans, NULL, &error_abort); visit_type_AltNumStr(v, &ans, NULL, &error_abort);
g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N); g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N);
g_assert_cmpfloat(ans->u.n, ==, 42.5); g_assert_cmpfloat(ans->u.n, ==, 42.5);
qapi_free_AltNumStr(ans); qapi_free_AltNumStr(ans);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5"); v = visitor_input_test_init(data, "42.5");
visit_type_AltStrInt(v, &asi, NULL, &err); visit_type_AltStrInt(v, &asi, NULL, &err);
g_assert(err); error_free_or_abort(&err);
error_free(err);
err = NULL;
qapi_free_AltStrInt(asi); qapi_free_AltStrInt(asi);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5"); v = visitor_input_test_init(data, "42.5");
visit_type_AltIntNum(v, &ain, NULL, &error_abort); visit_type_AltIntNum(v, &ain, NULL, &error_abort);
g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_N); g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_N);
g_assert_cmpfloat(ain->u.n, ==, 42.5); g_assert_cmpfloat(ain->u.n, ==, 42.5);
qapi_free_AltIntNum(ain); qapi_free_AltIntNum(ain);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, "42.5"); v = visitor_input_test_init(data, "42.5");
visit_type_AltNumInt(v, &ani, NULL, &error_abort); visit_type_AltNumInt(v, &ani, NULL, &error_abort);
g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_N); g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_N);
g_assert_cmpfloat(ani->u.n, ==, 42.5); g_assert_cmpfloat(ani->u.n, ==, 42.5);
qapi_free_AltNumInt(ani); qapi_free_AltNumInt(ani);
visitor_input_teardown(data, NULL);
} }
static void test_native_list_integer_helper(TestInputVisitorData *data, static void test_native_list_integer_helper(TestInputVisitorData *data,
...@@ -512,7 +422,6 @@ static void test_native_list_integer_helper(TestInputVisitorData *data, ...@@ -512,7 +422,6 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
UserDefNativeListUnionKind kind) UserDefNativeListUnionKind kind)
{ {
UserDefNativeListUnion *cvalue = NULL; UserDefNativeListUnion *cvalue = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
GString *gstr_list = g_string_new(""); GString *gstr_list = g_string_new("");
GString *gstr_union = g_string_new(""); GString *gstr_union = g_string_new("");
...@@ -529,8 +438,7 @@ static void test_native_list_integer_helper(TestInputVisitorData *data, ...@@ -529,8 +438,7 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
gstr_list->str); gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str); v = visitor_input_test_init_raw(data, gstr_union->str);
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
g_assert(err == NULL);
g_assert(cvalue != NULL); g_assert(cvalue != NULL);
g_assert_cmpint(cvalue->type, ==, kind); g_assert_cmpint(cvalue->type, ==, kind);
...@@ -675,7 +583,6 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data, ...@@ -675,7 +583,6 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
{ {
UserDefNativeListUnion *cvalue = NULL; UserDefNativeListUnion *cvalue = NULL;
boolList *elem = NULL; boolList *elem = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
GString *gstr_list = g_string_new(""); GString *gstr_list = g_string_new("");
GString *gstr_union = g_string_new(""); GString *gstr_union = g_string_new("");
...@@ -692,8 +599,7 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data, ...@@ -692,8 +599,7 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
gstr_list->str); gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str); v = visitor_input_test_init_raw(data, gstr_union->str);
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
g_assert(err == NULL);
g_assert(cvalue != NULL); g_assert(cvalue != NULL);
g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN); g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
...@@ -711,7 +617,6 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data, ...@@ -711,7 +617,6 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data,
{ {
UserDefNativeListUnion *cvalue = NULL; UserDefNativeListUnion *cvalue = NULL;
strList *elem = NULL; strList *elem = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
GString *gstr_list = g_string_new(""); GString *gstr_list = g_string_new("");
GString *gstr_union = g_string_new(""); GString *gstr_union = g_string_new("");
...@@ -727,8 +632,7 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data, ...@@ -727,8 +632,7 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data,
gstr_list->str); gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str); v = visitor_input_test_init_raw(data, gstr_union->str);
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
g_assert(err == NULL);
g_assert(cvalue != NULL); g_assert(cvalue != NULL);
g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING); g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
...@@ -750,7 +654,6 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data, ...@@ -750,7 +654,6 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data,
{ {
UserDefNativeListUnion *cvalue = NULL; UserDefNativeListUnion *cvalue = NULL;
numberList *elem = NULL; numberList *elem = NULL;
Error *err = NULL;
Visitor *v; Visitor *v;
GString *gstr_list = g_string_new(""); GString *gstr_list = g_string_new("");
GString *gstr_union = g_string_new(""); GString *gstr_union = g_string_new("");
...@@ -766,8 +669,7 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data, ...@@ -766,8 +669,7 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data,
gstr_list->str); gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str); v = visitor_input_test_init_raw(data, gstr_union->str);
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err); visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
g_assert(err == NULL);
g_assert(cvalue != NULL); g_assert(cvalue != NULL);
g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER); g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
...@@ -802,18 +704,69 @@ static void test_visitor_in_errors(TestInputVisitorData *data, ...@@ -802,18 +704,69 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
TestStruct *p = NULL; TestStruct *p = NULL;
Error *err = NULL; Error *err = NULL;
Visitor *v; Visitor *v;
strList *q = NULL;
v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }"); v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
"'string': -42 }");
visit_type_TestStruct(v, &p, NULL, &err); visit_type_TestStruct(v, &p, NULL, &err);
g_assert(err); error_free_or_abort(&err);
/* FIXME - a failed parse should not leave a partially-allocated p /* FIXME - a failed parse should not leave a partially-allocated p
* for us to clean up; this could cause callers to leak memory. */ * for us to clean up; this could cause callers to leak memory. */
g_assert(p->string == NULL); g_assert(p->string == NULL);
error_free(err);
g_free(p->string); g_free(p->string);
g_free(p); g_free(p);
v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
visit_type_strList(v, &q, NULL, &err);
error_free_or_abort(&err);
assert(q);
qapi_free_strList(q);
}
static void test_visitor_in_wrong_type(TestInputVisitorData *data,
const void *unused)
{
TestStruct *p = NULL;
Visitor *v;
strList *q = NULL;
int64_t i;
Error *err = NULL;
/* Make sure arrays and structs cannot be confused */
v = visitor_input_test_init(data, "[]");
visit_type_TestStruct(v, &p, NULL, &err);
error_free_or_abort(&err);
g_assert(!p);
v = visitor_input_test_init(data, "{}");
visit_type_strList(v, &q, NULL, &err);
error_free_or_abort(&err);
assert(!q);
/* Make sure primitives and struct cannot be confused */
v = visitor_input_test_init(data, "1");
visit_type_TestStruct(v, &p, NULL, &err);
error_free_or_abort(&err);
g_assert(!p);
v = visitor_input_test_init(data, "{}");
visit_type_int(v, &i, NULL, &err);
error_free_or_abort(&err);
/* Make sure primitives and arrays cannot be confused */
v = visitor_input_test_init(data, "1");
visit_type_strList(v, &q, NULL, &err);
error_free_or_abort(&err);
assert(!q);
v = visitor_input_test_init(data, "[]");
visit_type_int(v, &i, NULL, &err);
error_free_or_abort(&err);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
...@@ -848,6 +801,8 @@ int main(int argc, char **argv) ...@@ -848,6 +801,8 @@ int main(int argc, char **argv)
&in_visitor_data, test_visitor_in_alternate); &in_visitor_data, test_visitor_in_alternate);
input_visitor_test_add("/visitor/input/errors", input_visitor_test_add("/visitor/input/errors",
&in_visitor_data, test_visitor_in_errors); &in_visitor_data, test_visitor_in_errors);
input_visitor_test_add("/visitor/input/wrong-type",
&in_visitor_data, test_visitor_in_wrong_type);
input_visitor_test_add("/visitor/input/alternate-number", input_visitor_test_add("/visitor/input/alternate-number",
&in_visitor_data, test_visitor_in_alternate_number); &in_visitor_data, test_visitor_in_alternate_number);
input_visitor_test_add("/visitor/input/native_list/int", input_visitor_test_add("/visitor/input/native_list/int",
......
...@@ -45,11 +45,9 @@ static void test_visitor_out_int(TestOutputVisitorData *data, ...@@ -45,11 +45,9 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
int64_t value = -42; int64_t value = -42;
Error *err = NULL;
QObject *obj; QObject *obj;
visit_type_int(data->ov, &value, NULL, &err); visit_type_int(data->ov, &value, NULL, &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
...@@ -62,12 +60,10 @@ static void test_visitor_out_int(TestOutputVisitorData *data, ...@@ -62,12 +60,10 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
static void test_visitor_out_bool(TestOutputVisitorData *data, static void test_visitor_out_bool(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
Error *err = NULL;
bool value = true; bool value = true;
QObject *obj; QObject *obj;
visit_type_bool(data->ov, &value, NULL, &err); visit_type_bool(data->ov, &value, NULL, &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
...@@ -81,11 +77,9 @@ static void test_visitor_out_number(TestOutputVisitorData *data, ...@@ -81,11 +77,9 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
double value = 3.14; double value = 3.14;
Error *err = NULL;
QObject *obj; QObject *obj;
visit_type_number(data->ov, &value, NULL, &err); visit_type_number(data->ov, &value, NULL, &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
...@@ -99,11 +93,9 @@ static void test_visitor_out_string(TestOutputVisitorData *data, ...@@ -99,11 +93,9 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
char *string = (char *) "Q E M U"; char *string = (char *) "Q E M U";
Error *err = NULL;
QObject *obj; QObject *obj;
visit_type_str(data->ov, &string, NULL, &err); visit_type_str(data->ov, &string, NULL, &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
...@@ -117,12 +109,10 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data, ...@@ -117,12 +109,10 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
char *string = NULL; char *string = NULL;
Error *err = NULL;
QObject *obj; QObject *obj;
/* A null string should return "" */ /* A null string should return "" */
visit_type_str(data->ov, &string, NULL, &err); visit_type_str(data->ov, &string, NULL, &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
...@@ -135,13 +125,11 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data, ...@@ -135,13 +125,11 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
static void test_visitor_out_enum(TestOutputVisitorData *data, static void test_visitor_out_enum(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
Error *err = NULL;
QObject *obj; QObject *obj;
EnumOne i; EnumOne i;
for (i = 0; i < ENUM_ONE_MAX; i++) { for (i = 0; i < ENUM_ONE_MAX; i++) {
visit_type_EnumOne(data->ov, &i, "unused", &err); visit_type_EnumOne(data->ov, &i, "unused", &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
...@@ -166,41 +154,6 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data, ...@@ -166,41 +154,6 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
} }
} }
typedef struct TestStruct
{
int64_t integer;
bool boolean;
char *string;
} TestStruct;
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
const char *name, Error **errp)
{
Error *err = NULL;
visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
&err);
if (err) {
goto out;
}
visit_type_int(v, &(*obj)->integer, "integer", &err);
if (err) {
goto out_end;
}
visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
if (err) {
goto out_end;
}
visit_type_str(v, &(*obj)->string, "string", &err);
out_end:
error_propagate(errp, err);
err = NULL;
visit_end_struct(v, &err);
out:
error_propagate(errp, err);
}
static void test_visitor_out_struct(TestOutputVisitorData *data, static void test_visitor_out_struct(TestOutputVisitorData *data,
const void *unused) const void *unused)
...@@ -209,12 +162,10 @@ static void test_visitor_out_struct(TestOutputVisitorData *data, ...@@ -209,12 +162,10 @@ static void test_visitor_out_struct(TestOutputVisitorData *data,
.boolean = false, .boolean = false,
.string = (char *) "foo"}; .string = (char *) "foo"};
TestStruct *p = &test_struct; TestStruct *p = &test_struct;
Error *err = NULL;
QObject *obj; QObject *obj;
QDict *qdict; QDict *qdict;
visit_type_TestStruct(data->ov, &p, NULL, &err); visit_type_TestStruct(data->ov, &p, NULL, &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
...@@ -233,7 +184,6 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data, ...@@ -233,7 +184,6 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
int64_t value = 42; int64_t value = 42;
Error *err = NULL;
UserDefTwo *ud2; UserDefTwo *ud2;
QObject *obj; QObject *obj;
QDict *qdict, *dict1, *dict2, *dict3, *userdef; QDict *qdict, *dict1, *dict2, *dict3, *userdef;
...@@ -260,8 +210,7 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data, ...@@ -260,8 +210,7 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
ud2->dict1->dict3->userdef->integer = value; ud2->dict1->dict3->userdef->integer = value;
ud2->dict1->dict3->string = g_strdup(strings[3]); ud2->dict1->dict3->string = g_strdup(strings[3]);
visit_type_UserDefTwo(data->ov, &ud2, "unused", &err); visit_type_UserDefTwo(data->ov, &ud2, "unused", &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
...@@ -314,57 +263,33 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data, ...@@ -314,57 +263,33 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
} }
} }
typedef struct TestStructList
{
union {
TestStruct *value;
uint64_t padding;
};
struct TestStructList *next;
} TestStructList;
static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
const char *name, Error **errp)
{
GenericList *i, **head = (GenericList **)obj;
visit_start_list(v, name, errp);
for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
TestStructList *native_i = (TestStructList *)i;
visit_type_TestStruct(v, &native_i->value, NULL, errp);
}
visit_end_list(v, errp);
}
static void test_visitor_out_list(TestOutputVisitorData *data, static void test_visitor_out_list(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
char *value_str = (char *) "list value"; const char *value_str = "list value";
TestStructList *p, *head = NULL; TestStructList *p, *head = NULL;
const int max_items = 10; const int max_items = 10;
bool value_bool = true; bool value_bool = true;
int value_int = 10; int value_int = 10;
Error *err = NULL;
QListEntry *entry; QListEntry *entry;
QObject *obj; QObject *obj;
QList *qlist; QList *qlist;
int i; int i;
/* Build the list in reverse order... */
for (i = 0; i < max_items; i++) { for (i = 0; i < max_items; i++) {
p = g_malloc0(sizeof(*p)); p = g_malloc0(sizeof(*p));
p->value = g_malloc0(sizeof(*p->value)); p->value = g_malloc0(sizeof(*p->value));
p->value->integer = value_int; p->value->integer = value_int + (max_items - i - 1);
p->value->boolean = value_bool; p->value->boolean = value_bool;
p->value->string = value_str; p->value->string = g_strdup(value_str);
p->next = head; p->next = head;
head = p; head = p;
} }
visit_type_TestStructList(data->ov, &head, NULL, &err); visit_type_TestStructList(data->ov, &head, NULL, &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
...@@ -373,6 +298,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data, ...@@ -373,6 +298,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
qlist = qobject_to_qlist(obj); qlist = qobject_to_qlist(obj);
g_assert(!qlist_empty(qlist)); g_assert(!qlist_empty(qlist));
/* ...and ensure that the visitor sees it in order */
i = 0; i = 0;
QLIST_FOREACH_ENTRY(qlist, entry) { QLIST_FOREACH_ENTRY(qlist, entry) {
QDict *qdict; QDict *qdict;
...@@ -380,7 +306,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data, ...@@ -380,7 +306,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
g_assert(qobject_type(entry->value) == QTYPE_QDICT); g_assert(qobject_type(entry->value) == QTYPE_QDICT);
qdict = qobject_to_qdict(entry->value); qdict = qobject_to_qdict(entry->value);
g_assert_cmpint(qdict_size(qdict), ==, 3); g_assert_cmpint(qdict_size(qdict), ==, 3);
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int); g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int + i);
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool); g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str); g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
i++; i++;
...@@ -388,13 +314,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data, ...@@ -388,13 +314,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
g_assert_cmpint(i, ==, max_items); g_assert_cmpint(i, ==, max_items);
QDECREF(qlist); QDECREF(qlist);
qapi_free_TestStructList(head);
for (p = head; p;) {
TestStructList *tmp = p->next;
g_free(p->value);
g_free(p);
p = tmp;
}
} }
static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data, static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
...@@ -429,7 +349,6 @@ static void test_visitor_out_any(TestOutputVisitorData *data, ...@@ -429,7 +349,6 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
QObject *qobj; QObject *qobj;
Error *err = NULL;
QInt *qint; QInt *qint;
QBool *qbool; QBool *qbool;
QString *qstring; QString *qstring;
...@@ -437,8 +356,7 @@ static void test_visitor_out_any(TestOutputVisitorData *data, ...@@ -437,8 +356,7 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
QObject *obj; QObject *obj;
qobj = QOBJECT(qint_from_int(-42)); qobj = QOBJECT(qint_from_int(-42));
visit_type_any(data->ov, &qobj, NULL, &err); visit_type_any(data->ov, &qobj, NULL, &error_abort);
g_assert(!err);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
g_assert(qobject_type(obj) == QTYPE_QINT); g_assert(qobject_type(obj) == QTYPE_QINT);
...@@ -451,8 +369,8 @@ static void test_visitor_out_any(TestOutputVisitorData *data, ...@@ -451,8 +369,8 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
qdict_put(qdict, "boolean", qbool_from_bool(true)); qdict_put(qdict, "boolean", qbool_from_bool(true));
qdict_put(qdict, "string", qstring_from_str("foo")); qdict_put(qdict, "string", qstring_from_str("foo"));
qobj = QOBJECT(qdict); qobj = QOBJECT(qdict);
visit_type_any(data->ov, &qobj, NULL, &err); visit_type_any(data->ov, &qobj, NULL, &error_abort);
g_assert(!err); qobject_decref(qobj);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL); g_assert(obj != NULL);
qdict = qobject_to_qdict(obj); qdict = qobject_to_qdict(obj);
...@@ -473,7 +391,6 @@ static void test_visitor_out_any(TestOutputVisitorData *data, ...@@ -473,7 +391,6 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
g_assert(qstring); g_assert(qstring);
g_assert_cmpstr(qstring_get_str(qstring), ==, "foo"); g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
qobject_decref(obj); qobject_decref(obj);
qobject_decref(qobj);
} }
static void test_visitor_out_union_flat(TestOutputVisitorData *data, static void test_visitor_out_union_flat(TestOutputVisitorData *data,
...@@ -482,8 +399,6 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data, ...@@ -482,8 +399,6 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
QObject *arg; QObject *arg;
QDict *qdict; QDict *qdict;
Error *err = NULL;
UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion)); UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion));
tmp->enum1 = ENUM_ONE_VALUE1; tmp->enum1 = ENUM_ONE_VALUE1;
tmp->string = g_strdup("str"); tmp->string = g_strdup("str");
...@@ -491,8 +406,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data, ...@@ -491,8 +406,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
tmp->integer = 41; tmp->integer = 41;
tmp->u.value1->boolean = true; tmp->u.value1->boolean = true;
visit_type_UserDefFlatUnion(data->ov, &tmp, NULL, &err); visit_type_UserDefFlatUnion(data->ov, &tmp, NULL, &error_abort);
g_assert(err == NULL);
arg = qmp_output_get_qobject(data->qov); arg = qmp_output_get_qobject(data->qov);
g_assert(qobject_type(arg) == QTYPE_QDICT); g_assert(qobject_type(arg) == QTYPE_QDICT);
...@@ -511,20 +425,33 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data, ...@@ -511,20 +425,33 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
QObject *arg; QObject *arg;
Error *err = NULL; UserDefAlternate *tmp;
UserDefAlternate *tmp = g_malloc0(sizeof(UserDefAlternate)); tmp = g_new0(UserDefAlternate, 1);
tmp->type = USER_DEF_ALTERNATE_KIND_I; tmp->type = USER_DEF_ALTERNATE_KIND_I;
tmp->u.i = 42; tmp->u.i = 42;
visit_type_UserDefAlternate(data->ov, &tmp, NULL, &err); visit_type_UserDefAlternate(data->ov, &tmp, NULL, &error_abort);
g_assert(err == NULL);
arg = qmp_output_get_qobject(data->qov); arg = qmp_output_get_qobject(data->qov);
g_assert(qobject_type(arg) == QTYPE_QINT); g_assert(qobject_type(arg) == QTYPE_QINT);
g_assert_cmpint(qint_get_int(qobject_to_qint(arg)), ==, 42); g_assert_cmpint(qint_get_int(qobject_to_qint(arg)), ==, 42);
qapi_free_UserDefAlternate(tmp); qapi_free_UserDefAlternate(tmp);
qobject_decref(arg);
tmp = g_new0(UserDefAlternate, 1);
tmp->type = USER_DEF_ALTERNATE_KIND_S;
tmp->u.s = g_strdup("hello");
visit_type_UserDefAlternate(data->ov, &tmp, NULL, &error_abort);
arg = qmp_output_get_qobject(data->qov);
g_assert(qobject_type(arg) == QTYPE_QSTRING);
g_assert_cmpstr(qstring_get_str(qobject_to_qstring(arg)), ==, "hello");
qapi_free_UserDefAlternate(tmp);
qobject_decref(arg);
} }
static void test_visitor_out_empty(TestOutputVisitorData *data, static void test_visitor_out_empty(TestOutputVisitorData *data,
...@@ -758,14 +685,12 @@ static void test_native_list(TestOutputVisitorData *data, ...@@ -758,14 +685,12 @@ static void test_native_list(TestOutputVisitorData *data,
UserDefNativeListUnionKind kind) UserDefNativeListUnionKind kind)
{ {
UserDefNativeListUnion *cvalue = g_new0(UserDefNativeListUnion, 1); UserDefNativeListUnion *cvalue = g_new0(UserDefNativeListUnion, 1);
Error *err = NULL;
QObject *obj; QObject *obj;
cvalue->type = kind; cvalue->type = kind;
init_native_list(cvalue); init_native_list(cvalue);
visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &err); visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &error_abort);
g_assert(err == NULL);
obj = qmp_output_get_qobject(data->qov); obj = qmp_output_get_qobject(data->qov);
check_native_list(obj, cvalue->type); check_native_list(obj, cvalue->type);
......
...@@ -186,40 +186,6 @@ static void visit_primitive_list(Visitor *v, void **native, Error **errp) ...@@ -186,40 +186,6 @@ static void visit_primitive_list(Visitor *v, void **native, Error **errp)
} }
} }
typedef struct TestStruct
{
int64_t integer;
bool boolean;
char *string;
} TestStruct;
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
const char *name, Error **errp)
{
Error *err = NULL;
visit_start_struct(v, (void **)obj, NULL, name, sizeof(TestStruct), &err);
if (err) {
goto out;
}
visit_type_int(v, &(*obj)->integer, "integer", &err);
if (err) {
goto out_end;
}
visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
if (err) {
goto out_end;
}
visit_type_str(v, &(*obj)->string, "string", &err);
out_end:
error_propagate(errp, err);
err = NULL;
visit_end_struct(v, &err);
out:
error_propagate(errp, err);
}
static TestStruct *struct_create(void) static TestStruct *struct_create(void)
{ {
...@@ -336,14 +302,13 @@ static void test_primitives(gconstpointer opaque) ...@@ -336,14 +302,13 @@ static void test_primitives(gconstpointer opaque)
const SerializeOps *ops = args->ops; const SerializeOps *ops = args->ops;
PrimitiveType *pt = args->test_data; PrimitiveType *pt = args->test_data;
PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy)); PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
Error *err = NULL;
void *serialize_data; void *serialize_data;
pt_copy->type = pt->type; pt_copy->type = pt->type;
ops->serialize(pt, &serialize_data, visit_primitive_type, &err); ops->serialize(pt, &serialize_data, visit_primitive_type, &error_abort);
ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type, &err); ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type,
&error_abort);
g_assert(err == NULL);
g_assert(pt_copy != NULL); g_assert(pt_copy != NULL);
if (pt->type == PTYPE_STRING) { if (pt->type == PTYPE_STRING) {
g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string); g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
...@@ -379,7 +344,6 @@ static void test_primitive_lists(gconstpointer opaque) ...@@ -379,7 +344,6 @@ static void test_primitive_lists(gconstpointer opaque)
PrimitiveList pl = { .value = { NULL } }; PrimitiveList pl = { .value = { NULL } };
PrimitiveList pl_copy = { .value = { NULL } }; PrimitiveList pl_copy = { .value = { NULL } };
PrimitiveList *pl_copy_ptr = &pl_copy; PrimitiveList *pl_copy_ptr = &pl_copy;
Error *err = NULL;
void *serialize_data; void *serialize_data;
void *cur_head = NULL; void *cur_head = NULL;
int i; int i;
...@@ -526,10 +490,11 @@ static void test_primitive_lists(gconstpointer opaque) ...@@ -526,10 +490,11 @@ static void test_primitive_lists(gconstpointer opaque)
} }
} }
ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, &err); ops->serialize((void **)&pl, &serialize_data, visit_primitive_list,
ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &err); &error_abort);
ops->deserialize((void **)&pl_copy_ptr, serialize_data,
visit_primitive_list, &error_abort);
g_assert(err == NULL);
i = 0; i = 0;
/* compare our deserialized list of primitives to the original */ /* compare our deserialized list of primitives to the original */
...@@ -686,10 +651,8 @@ static void test_primitive_lists(gconstpointer opaque) ...@@ -686,10 +651,8 @@ static void test_primitive_lists(gconstpointer opaque)
g_assert_cmpint(i, ==, 33); g_assert_cmpint(i, ==, 33);
ops->cleanup(serialize_data); ops->cleanup(serialize_data);
dealloc_helper(&pl, visit_primitive_list, &err); dealloc_helper(&pl, visit_primitive_list, &error_abort);
g_assert(!err); dealloc_helper(&pl_copy, visit_primitive_list, &error_abort);
dealloc_helper(&pl_copy, visit_primitive_list, &err);
g_assert(!err);
g_free(args); g_free(args);
} }
...@@ -699,13 +662,12 @@ static void test_struct(gconstpointer opaque) ...@@ -699,13 +662,12 @@ static void test_struct(gconstpointer opaque)
const SerializeOps *ops = args->ops; const SerializeOps *ops = args->ops;
TestStruct *ts = struct_create(); TestStruct *ts = struct_create();
TestStruct *ts_copy = NULL; TestStruct *ts_copy = NULL;
Error *err = NULL;
void *serialize_data; void *serialize_data;
ops->serialize(ts, &serialize_data, visit_struct, &err); ops->serialize(ts, &serialize_data, visit_struct, &error_abort);
ops->deserialize((void **)&ts_copy, serialize_data, visit_struct, &err); ops->deserialize((void **)&ts_copy, serialize_data, visit_struct,
&error_abort);
g_assert(err == NULL);
struct_compare(ts, ts_copy); struct_compare(ts, ts_copy);
struct_cleanup(ts); struct_cleanup(ts);
...@@ -721,14 +683,12 @@ static void test_nested_struct(gconstpointer opaque) ...@@ -721,14 +683,12 @@ static void test_nested_struct(gconstpointer opaque)
const SerializeOps *ops = args->ops; const SerializeOps *ops = args->ops;
UserDefTwo *udnp = nested_struct_create(); UserDefTwo *udnp = nested_struct_create();
UserDefTwo *udnp_copy = NULL; UserDefTwo *udnp_copy = NULL;
Error *err = NULL;
void *serialize_data; void *serialize_data;
ops->serialize(udnp, &serialize_data, visit_nested_struct, &err); ops->serialize(udnp, &serialize_data, visit_nested_struct, &error_abort);
ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct, ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct,
&err); &error_abort);
g_assert(err == NULL);
nested_struct_compare(udnp, udnp_copy); nested_struct_compare(udnp, udnp_copy);
nested_struct_cleanup(udnp); nested_struct_cleanup(udnp);
...@@ -743,7 +703,6 @@ static void test_nested_struct_list(gconstpointer opaque) ...@@ -743,7 +703,6 @@ static void test_nested_struct_list(gconstpointer opaque)
TestArgs *args = (TestArgs *) opaque; TestArgs *args = (TestArgs *) opaque;
const SerializeOps *ops = args->ops; const SerializeOps *ops = args->ops;
UserDefTwoList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL; UserDefTwoList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
Error *err = NULL;
void *serialize_data; void *serialize_data;
int i = 0; int i = 0;
...@@ -754,11 +713,10 @@ static void test_nested_struct_list(gconstpointer opaque) ...@@ -754,11 +713,10 @@ static void test_nested_struct_list(gconstpointer opaque)
listp = tmp; listp = tmp;
} }
ops->serialize(listp, &serialize_data, visit_nested_struct_list, &err); ops->serialize(listp, &serialize_data, visit_nested_struct_list,
&error_abort);
ops->deserialize((void **)&listp_copy, serialize_data, ops->deserialize((void **)&listp_copy, serialize_data,
visit_nested_struct_list, &err); visit_nested_struct_list, &error_abort);
g_assert(err == NULL);
tmp = listp; tmp = listp;
tmp_copy = listp_copy; tmp_copy = listp_copy;
......
...@@ -220,6 +220,13 @@ void error_free(Error *err) ...@@ -220,6 +220,13 @@ void error_free(Error *err)
} }
} }
void error_free_or_abort(Error **errp)
{
assert(errp && *errp);
error_free(*errp);
*errp = NULL;
}
void error_propagate(Error **dst_errp, Error *local_err) void error_propagate(Error **dst_errp, Error *local_err)
{ {
if (!local_err) { if (!local_err) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册