mirror of https://github.com/xemu-project/xemu.git
QAPI patches
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWQZjZAAoJEDhwtADrkYZTHLsP/i9cxhRgaZmOdOkOzrD/nUru IBTtYHC1si2FqpKB4bbrJDCEv6VkZNIkyr2TMgoawfFQT2J5qpN/E08XsAc4J6hk jysAajXQmtrNpZezmVTD2UJYXfe5eW3hq9XoEy1eM1MPGudAxTWXw9NwcBsILtol PL/zC027tib3RyDIbLBWABdpeTp242YAAIRn5xIoqefcDqOQUmKhBte6beHioIbG YLezjZBreNUFD/R/PoimDCZoeL5A+hNZej297SHik5WVQPf30R5XHn40aa/njO/6 W/x9T+OzhQgt4Ruh7NFQtOuJ7sYl7tKyjhTr4Ks0BOvRFIgyeTj2UrmveFohNhb1 7IuGX7jSZ1XVMMJX0kV3HE2k2tm6TAJdi+U2Hc75L8RvkUQv9bOeKmh1jH0DkVz2 kzauV3TdSxQQ/c5tko3PCoAfLI9/lrRR4mHAUgn+s63TOl6Dr17w4uwEWVN/apF5 Tn3icKI3aR+Lgc88QxWkiSeYMTLGQNpag52kmR8RiB5zC9Ayh+V4XjN+0QyD5F4u BKV8X3erDm8Cf2/C2GgETVNKl+QKzmPGXSlI1ZsFG37PGud8psos0niYk0uAwtr2 YvOpVe2G6GRZQCiUE7c4HeERHS0Gd4RwOVUcP9Uj2eaxEspwbkcCEPOELfMEuQV0 CPChR3sb/nYbjCLZWEFJ =wFCY -----END PGP SIGNATURE----- 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: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a8b4f9585a
|
@ -516,6 +516,10 @@ query-qmp-schema. QGA currently doesn't support introspection.
|
|||
|
||||
query-qmp-schema returns a JSON array of SchemaInfo objects. These
|
||||
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
|
||||
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
|
|||
name), "type" (the name of its type), and optionally "default". The
|
||||
member is optional if "default" is present. Currently, "default" can
|
||||
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
|
||||
|
||||
|
@ -610,7 +616,9 @@ Example: the SchemaInfo for MyType from section Struct types
|
|||
"variants" is a JSON array describing the object's variant members.
|
||||
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
|
||||
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
|
||||
Union types
|
||||
|
@ -651,7 +659,8 @@ Union types
|
|||
The SchemaInfo for an alternate type has meta-type "alternate", and
|
||||
variant member "members". "members" is a JSON array. Each element is
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
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']
|
||||
|
||||
{ "name": "strList", "meta-type": "array",
|
||||
{ "name": "[str]", "meta-type": "array",
|
||||
"element-type": "str" }
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
* Handle an error without reporting it (just for completeness):
|
||||
* 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:
|
||||
* error_propagate(errp, err);
|
||||
* where Error **errp is a parameter, by convention the last one.
|
||||
|
@ -189,6 +193,11 @@ Error *error_copy(const 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.
|
||||
*/
|
||||
|
|
|
@ -90,6 +90,7 @@ static inline void qobject_incref(QObject *obj)
|
|||
*/
|
||||
static inline void qobject_decref(QObject *obj)
|
||||
{
|
||||
assert(!obj || obj->refcnt);
|
||||
if (obj && --obj->refcnt == 0) {
|
||||
assert(obj->type != NULL);
|
||||
assert(obj->type->destroy != NULL);
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
# Returns: array of @SchemaInfo, where each element describes an
|
||||
# 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*
|
||||
# interfaces, by defining QAPI types. These are not part of the QMP
|
||||
# wire ABI, and therefore not returned by this command.
|
||||
|
@ -78,7 +82,8 @@
|
|||
# Commands and events have the name defined in the QAPI schema.
|
||||
# Unlike command and event names, type names are not part of
|
||||
# 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.
|
||||
#
|
||||
|
@ -130,7 +135,7 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
@ -158,14 +163,16 @@
|
|||
#
|
||||
# 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.
|
||||
# An element of @members with this name must exist.
|
||||
#
|
||||
# @variants: #optional variant members, i.e. additional members that
|
||||
# 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.
|
||||
#
|
||||
|
@ -219,7 +226,7 @@
|
|||
#
|
||||
# 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
|
||||
# docs/qapi-code-gen.txt section Alternate types.
|
||||
#
|
||||
|
|
|
@ -107,10 +107,12 @@ const char %(c_name)s[] = %(c_string)s;
|
|||
# characters.
|
||||
if isinstance(typ, QAPISchemaBuiltinType):
|
||||
return typ.name
|
||||
if isinstance(typ, QAPISchemaArrayType):
|
||||
return '[' + self._use_type(typ.element_type) + ']'
|
||||
return self._name(typ.name)
|
||||
|
||||
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)
|
||||
obj['name'] = name
|
||||
obj['meta-type'] = mtype
|
||||
|
@ -136,8 +138,8 @@ const char %(c_name)s[] = %(c_string)s;
|
|||
self._gen_json(name, 'enum', {'values': values})
|
||||
|
||||
def visit_array_type(self, name, info, element_type):
|
||||
self._gen_json(name, 'array',
|
||||
{'element-type': self._use_type(element_type)})
|
||||
element = self._use_type(element_type)
|
||||
self._gen_json('[' + element + ']', 'array', {'element-type': element})
|
||||
|
||||
def visit_object_type_flat(self, name, info, members, variants):
|
||||
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
|
|||
|
||||
|
||||
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('''
|
||||
|
||||
void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
# This file is a stress test of supported qapi constructs that must
|
||||
# parse and compile correctly.
|
||||
|
||||
{ 'struct': 'TestStruct',
|
||||
'data': { 'integer': 'int', 'boolean': 'bool', 'string': 'str' } }
|
||||
|
||||
# for testing enums
|
||||
{ 'struct': 'NestedEnumsOne',
|
||||
'data': { 'enum1': 'EnumOne', # Intentional forward reference
|
||||
|
@ -46,7 +49,8 @@
|
|||
|
||||
# dummy struct to force generation of array types not otherwise mentioned
|
||||
{ 'struct': 'ForceArrays',
|
||||
'data': { 'unused1':['UserDefOne'], 'unused2':['UserDefTwo'] } }
|
||||
'data': { 'unused1':['UserDefOne'], 'unused2':['UserDefTwo'],
|
||||
'unused3':['TestStruct'] } }
|
||||
|
||||
# for testing unions
|
||||
# Among other things, test that a name collision between branches does
|
||||
|
|
|
@ -92,6 +92,7 @@ object EventStructOne
|
|||
object ForceArrays
|
||||
member unused1: UserDefOneList optional=False
|
||||
member unused2: UserDefTwoList optional=False
|
||||
member unused3: TestStructList optional=False
|
||||
enum MyEnum []
|
||||
object NestedEnumsOne
|
||||
member enum1: EnumOne optional=False
|
||||
|
@ -100,6 +101,10 @@ object NestedEnumsOne
|
|||
member enum4: EnumOne optional=True
|
||||
enum QEnumTwo ['value1', 'value2']
|
||||
prefix QENUM_TWO
|
||||
object TestStruct
|
||||
member integer: int optional=False
|
||||
member boolean: bool optional=False
|
||||
member string: str optional=False
|
||||
object UserDefA
|
||||
member boolean: bool optional=False
|
||||
member a_b: int optional=True
|
||||
|
|
|
@ -225,8 +225,7 @@ static void test_dealloc_partial(void)
|
|||
assert(ud2->dict1 == NULL);
|
||||
|
||||
/* confirm & release construction error */
|
||||
assert(err != NULL);
|
||||
error_free(err);
|
||||
error_free_or_abort(&err);
|
||||
|
||||
/* tear down partial object */
|
||||
qapi_free_UserDefTwo(ud2);
|
||||
|
|
|
@ -40,9 +40,29 @@ static void validate_teardown(TestInputVisitorData *data,
|
|||
}
|
||||
}
|
||||
|
||||
/* This is provided instead of a test setup function so that the JSON
|
||||
string used by the tests are kept in the test functions (and not
|
||||
int main()) */
|
||||
/* The various test_init functions are provided instead of a test setup
|
||||
function so that the JSON string used by the tests are kept in the test
|
||||
functions (and not in main()). */
|
||||
static Visitor *validate_test_init_internal(TestInputVisitorData *data,
|
||||
const char *json_string,
|
||||
va_list *ap)
|
||||
{
|
||||
Visitor *v;
|
||||
|
||||
validate_teardown(data, NULL);
|
||||
|
||||
data->obj = qobject_from_jsonv(json_string, ap);
|
||||
g_assert(data->obj);
|
||||
|
||||
data->qiv = qmp_input_visitor_new_strict(data->obj);
|
||||
g_assert(data->qiv);
|
||||
|
||||
v = qmp_input_get_visitor(data->qiv);
|
||||
g_assert(v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static GCC_FMT_ATTR(2, 3)
|
||||
Visitor *validate_test_init(TestInputVisitorData *data,
|
||||
const char *json_string, ...)
|
||||
|
@ -51,17 +71,8 @@ Visitor *validate_test_init(TestInputVisitorData *data,
|
|||
va_list ap;
|
||||
|
||||
va_start(ap, json_string);
|
||||
data->obj = qobject_from_jsonv(json_string, &ap);
|
||||
v = validate_test_init_internal(data, json_string, &ap);
|
||||
va_end(ap);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -75,67 +86,19 @@ Visitor *validate_test_init(TestInputVisitorData *data,
|
|||
static Visitor *validate_test_init_raw(TestInputVisitorData *data,
|
||||
const char *json_string)
|
||||
{
|
||||
Visitor *v;
|
||||
|
||||
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;
|
||||
return validate_test_init_internal(data, json_string, 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_validate_struct(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
TestStruct *p = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
|
||||
|
||||
visit_type_TestStruct(v, &p, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_TestStruct(v, &p, NULL, &error_abort);
|
||||
g_free(p->string);
|
||||
g_free(p);
|
||||
}
|
||||
|
@ -144,7 +107,6 @@ static void test_validate_struct_nested(TestInputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
UserDefTwo *udp = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "{ 'string0': 'string0', "
|
||||
|
@ -152,8 +114,7 @@ static void test_validate_struct_nested(TestInputVisitorData *data,
|
|||
"'dict2': { 'userdef': { 'integer': 42, "
|
||||
"'string': 'string' }, 'string': 'string2'}}}");
|
||||
|
||||
visit_type_UserDefTwo(v, &udp, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_UserDefTwo(v, &udp, NULL, &error_abort);
|
||||
qapi_free_UserDefTwo(udp);
|
||||
}
|
||||
|
||||
|
@ -161,13 +122,11 @@ static void test_validate_list(TestInputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
UserDefOneList *head = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
|
||||
|
||||
visit_type_UserDefOneList(v, &head, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_UserDefOneList(v, &head, NULL, &error_abort);
|
||||
qapi_free_UserDefOneList(head);
|
||||
}
|
||||
|
||||
|
@ -176,12 +135,10 @@ static void test_validate_union_native_list(TestInputVisitorData *data,
|
|||
{
|
||||
UserDefNativeListUnion *tmp = NULL;
|
||||
Visitor *v;
|
||||
Error *err = NULL;
|
||||
|
||||
v = validate_test_init(data, "{ 'type': 'integer', 'data' : [ 1, 2 ] }");
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &tmp, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_UserDefNativeListUnion(v, &tmp, NULL, &error_abort);
|
||||
qapi_free_UserDefNativeListUnion(tmp);
|
||||
}
|
||||
|
||||
|
@ -190,7 +147,6 @@ static void test_validate_union_flat(TestInputVisitorData *data,
|
|||
{
|
||||
UserDefFlatUnion *tmp = NULL;
|
||||
Visitor *v;
|
||||
Error *err = NULL;
|
||||
|
||||
v = validate_test_init(data,
|
||||
"{ 'enum1': 'value1', "
|
||||
|
@ -198,8 +154,7 @@ static void test_validate_union_flat(TestInputVisitorData *data,
|
|||
"'string': 'str', "
|
||||
"'boolean': true }");
|
||||
|
||||
visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_UserDefFlatUnion(v, &tmp, NULL, &error_abort);
|
||||
qapi_free_UserDefFlatUnion(tmp);
|
||||
}
|
||||
|
||||
|
@ -208,12 +163,10 @@ static void test_validate_alternate(TestInputVisitorData *data,
|
|||
{
|
||||
UserDefAlternate *tmp = NULL;
|
||||
Visitor *v;
|
||||
Error *err = NULL;
|
||||
|
||||
v = validate_test_init(data, "42");
|
||||
|
||||
visit_type_UserDefAlternate(v, &tmp, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
|
||||
qapi_free_UserDefAlternate(tmp);
|
||||
}
|
||||
|
||||
|
@ -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 }");
|
||||
|
||||
visit_type_TestStruct(v, &p, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free_or_abort(&err);
|
||||
if (p) {
|
||||
g_free(p->string);
|
||||
}
|
||||
|
@ -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'}}}");
|
||||
|
||||
visit_type_UserDefTwo(v, &udp, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_UserDefTwo(udp);
|
||||
}
|
||||
|
||||
|
@ -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' } ]");
|
||||
|
||||
visit_type_UserDefOneList(v, &head, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_UserDefOneList(head);
|
||||
}
|
||||
|
||||
|
@ -273,7 +226,7 @@ static void test_validate_fail_union_native_list(TestInputVisitorData *data,
|
|||
"{ 'type': 'integer', 'data' : [ 'string' ] }");
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &tmp, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_UserDefNativeListUnion(tmp);
|
||||
}
|
||||
|
||||
|
@ -287,7 +240,7 @@ static void test_validate_fail_union_flat(TestInputVisitorData *data,
|
|||
v = validate_test_init(data, "{ 'string': 'c', 'integer': 41, 'boolean': true }");
|
||||
|
||||
visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_UserDefFlatUnion(tmp);
|
||||
}
|
||||
|
||||
|
@ -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' }");
|
||||
|
||||
visit_type_UserDefFlatUnion2(v, &tmp, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_UserDefFlatUnion2(tmp);
|
||||
}
|
||||
|
||||
|
@ -316,7 +269,7 @@ static void test_validate_fail_alternate(TestInputVisitorData *data,
|
|||
v = validate_test_init(data, "3.14");
|
||||
|
||||
visit_type_UserDefAlternate(v, &tmp, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_UserDefAlternate(tmp);
|
||||
}
|
||||
|
||||
|
@ -324,16 +277,11 @@ static void do_test_validate_qmp_introspect(TestInputVisitorData *data,
|
|||
const char *schema_json)
|
||||
{
|
||||
SchemaInfoList *schema = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = validate_test_init_raw(data, schema_json);
|
||||
|
||||
visit_type_SchemaInfoList(v, &schema, NULL, &err);
|
||||
if (err) {
|
||||
fprintf(stderr, "%s", error_get_pretty(err));
|
||||
}
|
||||
g_assert(!err);
|
||||
visit_type_SchemaInfoList(v, &schema, NULL, &error_abort);
|
||||
g_assert(schema);
|
||||
|
||||
qapi_free_SchemaInfoList(schema);
|
||||
|
|
|
@ -36,9 +36,29 @@ static void visitor_input_teardown(TestInputVisitorData *data,
|
|||
}
|
||||
}
|
||||
|
||||
/* This is provided instead of a test setup function so that the JSON
|
||||
string used by the tests are kept in the test functions (and not
|
||||
int main()) */
|
||||
/* The various test_init functions are provided instead of a test setup
|
||||
function so that the JSON string used by the tests are kept in the test
|
||||
functions (and not in main()). */
|
||||
static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
|
||||
const char *json_string,
|
||||
va_list *ap)
|
||||
{
|
||||
Visitor *v;
|
||||
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
data->obj = qobject_from_jsonv(json_string, ap);
|
||||
g_assert(data->obj);
|
||||
|
||||
data->qiv = qmp_input_visitor_new(data->obj);
|
||||
g_assert(data->qiv);
|
||||
|
||||
v = qmp_input_get_visitor(data->qiv);
|
||||
g_assert(v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static GCC_FMT_ATTR(2, 3)
|
||||
Visitor *visitor_input_test_init(TestInputVisitorData *data,
|
||||
const char *json_string, ...)
|
||||
|
@ -47,17 +67,8 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data,
|
|||
va_list ap;
|
||||
|
||||
va_start(ap, json_string);
|
||||
data->obj = qobject_from_jsonv(json_string, &ap);
|
||||
v = visitor_input_test_init_internal(data, json_string, &ap);
|
||||
va_end(ap);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -71,32 +82,18 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data,
|
|||
static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
|
||||
const char *json_string)
|
||||
{
|
||||
Visitor *v;
|
||||
|
||||
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;
|
||||
return visitor_input_test_init_internal(data, json_string, NULL);
|
||||
}
|
||||
|
||||
static void test_visitor_in_int(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
int64_t res = 0, value = -42;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "%" PRId64, value);
|
||||
|
||||
visit_type_int(v, &res, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_int(v, &res, NULL, &error_abort);
|
||||
g_assert_cmpint(res, ==, value);
|
||||
}
|
||||
|
||||
|
@ -114,21 +111,18 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
|
|||
v = visitor_input_test_init(data, "%f", DBL_MAX);
|
||||
|
||||
visit_type_int(v, &res, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free(err);
|
||||
error_free_or_abort(&err);
|
||||
}
|
||||
|
||||
static void test_visitor_in_bool(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *err = NULL;
|
||||
bool res = false;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "true");
|
||||
|
||||
visit_type_bool(v, &res, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_bool(v, &res, NULL, &error_abort);
|
||||
g_assert_cmpint(res, ==, true);
|
||||
}
|
||||
|
||||
|
@ -136,13 +130,11 @@ static void test_visitor_in_number(TestInputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
double res = 0, value = 3.14;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "%f", value);
|
||||
|
||||
visit_type_number(v, &res, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_number(v, &res, NULL, &error_abort);
|
||||
g_assert_cmpfloat(res, ==, value);
|
||||
}
|
||||
|
||||
|
@ -150,13 +142,11 @@ static void test_visitor_in_string(TestInputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
char *res = NULL, *value = (char *) "Q E M U";
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "%s", value);
|
||||
|
||||
visit_type_str(v, &res, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_str(v, &res, NULL, &error_abort);
|
||||
g_assert_cmpstr(res, ==, value);
|
||||
|
||||
g_free(res);
|
||||
|
@ -165,7 +155,6 @@ static void test_visitor_in_string(TestInputVisitorData *data,
|
|||
static void test_visitor_in_enum(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
EnumOne i;
|
||||
|
||||
|
@ -174,63 +163,21 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
|
|||
|
||||
v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
|
||||
|
||||
visit_type_EnumOne(v, &res, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_EnumOne(v, &res, NULL, &error_abort);
|
||||
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,
|
||||
const void *unused)
|
||||
{
|
||||
TestStruct *p = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
|
||||
|
||||
visit_type_TestStruct(v, &p, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_TestStruct(v, &p, NULL, &error_abort);
|
||||
g_assert_cmpint(p->integer, ==, -42);
|
||||
g_assert(p->boolean == true);
|
||||
g_assert_cmpstr(p->string, ==, "foo");
|
||||
|
@ -239,17 +186,10 @@ static void test_visitor_in_struct(TestInputVisitorData *data,
|
|||
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,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefTwo *udp = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
|
||||
v = visitor_input_test_init(data, "{ 'string0': 'string0', "
|
||||
|
@ -257,34 +197,28 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
|
|||
"'dict2': { 'userdef': { 'integer': 42, "
|
||||
"'string': 'string' }, 'string': 'string2'}}}");
|
||||
|
||||
visit_type_UserDefTwo(v, &udp, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_UserDefTwo(v, &udp, NULL, &error_abort);
|
||||
|
||||
check_and_free_str(udp->string0, "string0");
|
||||
check_and_free_str(udp->dict1->string1, "string1");
|
||||
g_assert_cmpstr(udp->string0, ==, "string0");
|
||||
g_assert_cmpstr(udp->dict1->string1, ==, "string1");
|
||||
g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
|
||||
check_and_free_str(udp->dict1->dict2->userdef->string, "string");
|
||||
check_and_free_str(udp->dict1->dict2->string, "string2");
|
||||
g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
|
||||
g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
|
||||
g_assert(udp->dict1->has_dict3 == false);
|
||||
|
||||
g_free(udp->dict1->dict2->userdef);
|
||||
g_free(udp->dict1->dict2);
|
||||
g_free(udp->dict1);
|
||||
g_free(udp);
|
||||
qapi_free_UserDefTwo(udp);
|
||||
}
|
||||
|
||||
static void test_visitor_in_list(TestInputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefOneList *item, *head = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
int i;
|
||||
|
||||
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);
|
||||
g_assert(!err);
|
||||
visit_type_UserDefOneList(v, &head, NULL, &error_abort);
|
||||
g_assert(head != NULL);
|
||||
|
||||
for (i = 0, item = head; item; item = item->next, i++) {
|
||||
|
@ -296,13 +230,18 @@ static void test_visitor_in_list(TestInputVisitorData *data,
|
|||
}
|
||||
|
||||
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,
|
||||
const void *unused)
|
||||
{
|
||||
QObject *res = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
QInt *qint;
|
||||
QBool *qbool;
|
||||
|
@ -311,16 +250,14 @@ static void test_visitor_in_any(TestInputVisitorData *data,
|
|||
QObject *qobj;
|
||||
|
||||
v = visitor_input_test_init(data, "-42");
|
||||
visit_type_any(v, &res, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_any(v, &res, NULL, &error_abort);
|
||||
qint = qobject_to_qint(res);
|
||||
g_assert(qint);
|
||||
g_assert_cmpint(qint_get_int(qint), ==, -42);
|
||||
qobject_decref(res);
|
||||
|
||||
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
|
||||
visit_type_any(v, &res, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_any(v, &res, NULL, &error_abort);
|
||||
qdict = qobject_to_qdict(res);
|
||||
g_assert(qdict && qdict_size(qdict) == 3);
|
||||
qobj = qdict_get(qdict, "integer");
|
||||
|
@ -345,7 +282,6 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
Visitor *v;
|
||||
Error *err = NULL;
|
||||
UserDefFlatUnion *tmp;
|
||||
UserDefUnionBase *base;
|
||||
|
||||
|
@ -355,8 +291,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data,
|
|||
"'string': 'str', "
|
||||
"'boolean': true }");
|
||||
|
||||
visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
visit_type_UserDefFlatUnion(v, &tmp, NULL, &error_abort);
|
||||
g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
|
||||
g_assert_cmpstr(tmp->string, ==, "str");
|
||||
g_assert_cmpint(tmp->integer, ==, 41);
|
||||
|
@ -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->u.i, ==, 42);
|
||||
qapi_free_UserDefAlternate(tmp);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "'string'");
|
||||
visit_type_UserDefAlternate(v, &tmp, NULL, &error_abort);
|
||||
g_assert_cmpint(tmp->type, ==, USER_DEF_ALTERNATE_KIND_S);
|
||||
g_assert_cmpstr(tmp->u.s, ==, "string");
|
||||
qapi_free_UserDefAlternate(tmp);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "false");
|
||||
visit_type_UserDefAlternate(v, &tmp, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free(err);
|
||||
err = NULL;
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_UserDefAlternate(tmp);
|
||||
visitor_input_teardown(data, NULL);
|
||||
}
|
||||
|
||||
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");
|
||||
visit_type_AltStrBool(v, &asb, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free(err);
|
||||
err = NULL;
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_AltStrBool(asb);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
/* FIXME: Order of alternate should not affect semantics; asn should
|
||||
* parse the same as ans */
|
||||
|
@ -426,85 +353,68 @@ static void test_visitor_in_alternate_number(TestInputVisitorData *data,
|
|||
visit_type_AltStrNum(v, &asn, NULL, &err);
|
||||
/* FIXME g_assert_cmpint(asn->type, == ALT_STR_NUM_KIND_N); */
|
||||
/* FIXME g_assert_cmpfloat(asn->u.n, ==, 42); */
|
||||
g_assert(err);
|
||||
error_free(err);
|
||||
err = NULL;
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_AltStrNum(asn);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "42");
|
||||
visit_type_AltNumStr(v, &ans, NULL, &error_abort);
|
||||
g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N);
|
||||
g_assert_cmpfloat(ans->u.n, ==, 42);
|
||||
qapi_free_AltNumStr(ans);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "42");
|
||||
visit_type_AltStrInt(v, &asi, NULL, &error_abort);
|
||||
g_assert_cmpint(asi->type, ==, ALT_STR_INT_KIND_I);
|
||||
g_assert_cmpint(asi->u.i, ==, 42);
|
||||
qapi_free_AltStrInt(asi);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "42");
|
||||
visit_type_AltIntNum(v, &ain, NULL, &error_abort);
|
||||
g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_I);
|
||||
g_assert_cmpint(ain->u.i, ==, 42);
|
||||
qapi_free_AltIntNum(ain);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "42");
|
||||
visit_type_AltNumInt(v, &ani, NULL, &error_abort);
|
||||
g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_I);
|
||||
g_assert_cmpint(ani->u.i, ==, 42);
|
||||
qapi_free_AltNumInt(ani);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
/* Parsing a double */
|
||||
|
||||
v = visitor_input_test_init(data, "42.5");
|
||||
visit_type_AltStrBool(v, &asb, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free(err);
|
||||
err = NULL;
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_AltStrBool(asb);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "42.5");
|
||||
visit_type_AltStrNum(v, &asn, NULL, &error_abort);
|
||||
g_assert_cmpint(asn->type, ==, ALT_STR_NUM_KIND_N);
|
||||
g_assert_cmpfloat(asn->u.n, ==, 42.5);
|
||||
qapi_free_AltStrNum(asn);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "42.5");
|
||||
visit_type_AltNumStr(v, &ans, NULL, &error_abort);
|
||||
g_assert_cmpint(ans->type, ==, ALT_NUM_STR_KIND_N);
|
||||
g_assert_cmpfloat(ans->u.n, ==, 42.5);
|
||||
qapi_free_AltNumStr(ans);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "42.5");
|
||||
visit_type_AltStrInt(v, &asi, NULL, &err);
|
||||
g_assert(err);
|
||||
error_free(err);
|
||||
err = NULL;
|
||||
error_free_or_abort(&err);
|
||||
qapi_free_AltStrInt(asi);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "42.5");
|
||||
visit_type_AltIntNum(v, &ain, NULL, &error_abort);
|
||||
g_assert_cmpint(ain->type, ==, ALT_INT_NUM_KIND_N);
|
||||
g_assert_cmpfloat(ain->u.n, ==, 42.5);
|
||||
qapi_free_AltIntNum(ain);
|
||||
visitor_input_teardown(data, NULL);
|
||||
|
||||
v = visitor_input_test_init(data, "42.5");
|
||||
visit_type_AltNumInt(v, &ani, NULL, &error_abort);
|
||||
g_assert_cmpint(ani->type, ==, ALT_NUM_INT_KIND_N);
|
||||
g_assert_cmpfloat(ani->u.n, ==, 42.5);
|
||||
qapi_free_AltNumInt(ani);
|
||||
visitor_input_teardown(data, NULL);
|
||||
}
|
||||
|
||||
static void test_native_list_integer_helper(TestInputVisitorData *data,
|
||||
|
@ -512,7 +422,6 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
|
|||
UserDefNativeListUnionKind kind)
|
||||
{
|
||||
UserDefNativeListUnion *cvalue = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
GString *gstr_list = g_string_new("");
|
||||
GString *gstr_union = g_string_new("");
|
||||
|
@ -529,8 +438,7 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
|
|||
gstr_list->str);
|
||||
v = visitor_input_test_init_raw(data, gstr_union->str);
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
|
||||
g_assert(cvalue != NULL);
|
||||
g_assert_cmpint(cvalue->type, ==, kind);
|
||||
|
||||
|
@ -675,7 +583,6 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
|
|||
{
|
||||
UserDefNativeListUnion *cvalue = NULL;
|
||||
boolList *elem = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
GString *gstr_list = g_string_new("");
|
||||
GString *gstr_union = g_string_new("");
|
||||
|
@ -692,8 +599,7 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
|
|||
gstr_list->str);
|
||||
v = visitor_input_test_init_raw(data, gstr_union->str);
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
|
||||
g_assert(cvalue != NULL);
|
||||
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,
|
|||
{
|
||||
UserDefNativeListUnion *cvalue = NULL;
|
||||
strList *elem = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
GString *gstr_list = g_string_new("");
|
||||
GString *gstr_union = g_string_new("");
|
||||
|
@ -727,8 +632,7 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data,
|
|||
gstr_list->str);
|
||||
v = visitor_input_test_init_raw(data, gstr_union->str);
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
|
||||
g_assert(cvalue != NULL);
|
||||
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,
|
|||
{
|
||||
UserDefNativeListUnion *cvalue = NULL;
|
||||
numberList *elem = NULL;
|
||||
Error *err = NULL;
|
||||
Visitor *v;
|
||||
GString *gstr_list = g_string_new("");
|
||||
GString *gstr_union = g_string_new("");
|
||||
|
@ -766,8 +669,7 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data,
|
|||
gstr_list->str);
|
||||
v = visitor_input_test_init_raw(data, gstr_union->str);
|
||||
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &error_abort);
|
||||
g_assert(cvalue != NULL);
|
||||
g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
|
||||
|
||||
|
@ -802,18 +704,69 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
|
|||
TestStruct *p = NULL;
|
||||
Error *err = NULL;
|
||||
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);
|
||||
g_assert(err);
|
||||
error_free_or_abort(&err);
|
||||
/* FIXME - a failed parse should not leave a partially-allocated p
|
||||
* for us to clean up; this could cause callers to leak memory. */
|
||||
g_assert(p->string == NULL);
|
||||
|
||||
error_free(err);
|
||||
g_free(p->string);
|
||||
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)
|
||||
|
@ -848,6 +801,8 @@ int main(int argc, char **argv)
|
|||
&in_visitor_data, test_visitor_in_alternate);
|
||||
input_visitor_test_add("/visitor/input/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",
|
||||
&in_visitor_data, test_visitor_in_alternate_number);
|
||||
input_visitor_test_add("/visitor/input/native_list/int",
|
||||
|
|
|
@ -45,11 +45,9 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
int64_t value = -42;
|
||||
Error *err = NULL;
|
||||
QObject *obj;
|
||||
|
||||
visit_type_int(data->ov, &value, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_int(data->ov, &value, NULL, &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
|
@ -62,12 +60,10 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
|
|||
static void test_visitor_out_bool(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *err = NULL;
|
||||
bool value = true;
|
||||
QObject *obj;
|
||||
|
||||
visit_type_bool(data->ov, &value, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_bool(data->ov, &value, NULL, &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
|
@ -81,11 +77,9 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
double value = 3.14;
|
||||
Error *err = NULL;
|
||||
QObject *obj;
|
||||
|
||||
visit_type_number(data->ov, &value, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_number(data->ov, &value, NULL, &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
|
@ -99,11 +93,9 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
char *string = (char *) "Q E M U";
|
||||
Error *err = NULL;
|
||||
QObject *obj;
|
||||
|
||||
visit_type_str(data->ov, &string, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_str(data->ov, &string, NULL, &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
|
@ -117,12 +109,10 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
char *string = NULL;
|
||||
Error *err = NULL;
|
||||
QObject *obj;
|
||||
|
||||
/* A null string should return "" */
|
||||
visit_type_str(data->ov, &string, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_str(data->ov, &string, NULL, &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
|
@ -135,13 +125,11 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
|
|||
static void test_visitor_out_enum(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
Error *err = NULL;
|
||||
QObject *obj;
|
||||
EnumOne i;
|
||||
|
||||
for (i = 0; i < ENUM_ONE_MAX; i++) {
|
||||
visit_type_EnumOne(data->ov, &i, "unused", &err);
|
||||
g_assert(!err);
|
||||
visit_type_EnumOne(data->ov, &i, "unused", &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
|
@ -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,
|
||||
const void *unused)
|
||||
|
@ -209,12 +162,10 @@ static void test_visitor_out_struct(TestOutputVisitorData *data,
|
|||
.boolean = false,
|
||||
.string = (char *) "foo"};
|
||||
TestStruct *p = &test_struct;
|
||||
Error *err = NULL;
|
||||
QObject *obj;
|
||||
QDict *qdict;
|
||||
|
||||
visit_type_TestStruct(data->ov, &p, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_TestStruct(data->ov, &p, NULL, &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
|
@ -233,7 +184,6 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
int64_t value = 42;
|
||||
Error *err = NULL;
|
||||
UserDefTwo *ud2;
|
||||
QObject *obj;
|
||||
QDict *qdict, *dict1, *dict2, *dict3, *userdef;
|
||||
|
@ -260,8 +210,7 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
|
|||
ud2->dict1->dict3->userdef->integer = value;
|
||||
ud2->dict1->dict3->string = g_strdup(strings[3]);
|
||||
|
||||
visit_type_UserDefTwo(data->ov, &ud2, "unused", &err);
|
||||
g_assert(!err);
|
||||
visit_type_UserDefTwo(data->ov, &ud2, "unused", &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
|
@ -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,
|
||||
const void *unused)
|
||||
{
|
||||
char *value_str = (char *) "list value";
|
||||
const char *value_str = "list value";
|
||||
TestStructList *p, *head = NULL;
|
||||
const int max_items = 10;
|
||||
bool value_bool = true;
|
||||
int value_int = 10;
|
||||
Error *err = NULL;
|
||||
QListEntry *entry;
|
||||
QObject *obj;
|
||||
QList *qlist;
|
||||
int i;
|
||||
|
||||
/* Build the list in reverse order... */
|
||||
for (i = 0; i < max_items; i++) {
|
||||
p = g_malloc0(sizeof(*p));
|
||||
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->string = value_str;
|
||||
p->value->string = g_strdup(value_str);
|
||||
|
||||
p->next = head;
|
||||
head = p;
|
||||
}
|
||||
|
||||
visit_type_TestStructList(data->ov, &head, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_TestStructList(data->ov, &head, NULL, &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
|
@ -373,6 +298,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
|
|||
qlist = qobject_to_qlist(obj);
|
||||
g_assert(!qlist_empty(qlist));
|
||||
|
||||
/* ...and ensure that the visitor sees it in order */
|
||||
i = 0;
|
||||
QLIST_FOREACH_ENTRY(qlist, entry) {
|
||||
QDict *qdict;
|
||||
|
@ -380,7 +306,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
|
|||
g_assert(qobject_type(entry->value) == QTYPE_QDICT);
|
||||
qdict = qobject_to_qdict(entry->value);
|
||||
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_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
|
||||
i++;
|
||||
|
@ -388,13 +314,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
|
|||
g_assert_cmpint(i, ==, max_items);
|
||||
|
||||
QDECREF(qlist);
|
||||
|
||||
for (p = head; p;) {
|
||||
TestStructList *tmp = p->next;
|
||||
g_free(p->value);
|
||||
g_free(p);
|
||||
p = tmp;
|
||||
}
|
||||
qapi_free_TestStructList(head);
|
||||
}
|
||||
|
||||
static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
|
||||
|
@ -429,7 +349,6 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
QObject *qobj;
|
||||
Error *err = NULL;
|
||||
QInt *qint;
|
||||
QBool *qbool;
|
||||
QString *qstring;
|
||||
|
@ -437,8 +356,7 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
|
|||
QObject *obj;
|
||||
|
||||
qobj = QOBJECT(qint_from_int(-42));
|
||||
visit_type_any(data->ov, &qobj, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_any(data->ov, &qobj, NULL, &error_abort);
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
g_assert(qobject_type(obj) == QTYPE_QINT);
|
||||
|
@ -451,8 +369,8 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
|
|||
qdict_put(qdict, "boolean", qbool_from_bool(true));
|
||||
qdict_put(qdict, "string", qstring_from_str("foo"));
|
||||
qobj = QOBJECT(qdict);
|
||||
visit_type_any(data->ov, &qobj, NULL, &err);
|
||||
g_assert(!err);
|
||||
visit_type_any(data->ov, &qobj, NULL, &error_abort);
|
||||
qobject_decref(qobj);
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
g_assert(obj != NULL);
|
||||
qdict = qobject_to_qdict(obj);
|
||||
|
@ -473,7 +391,6 @@ static void test_visitor_out_any(TestOutputVisitorData *data,
|
|||
g_assert(qstring);
|
||||
g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
|
||||
qobject_decref(obj);
|
||||
qobject_decref(qobj);
|
||||
}
|
||||
|
||||
static void test_visitor_out_union_flat(TestOutputVisitorData *data,
|
||||
|
@ -482,8 +399,6 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
|
|||
QObject *arg;
|
||||
QDict *qdict;
|
||||
|
||||
Error *err = NULL;
|
||||
|
||||
UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion));
|
||||
tmp->enum1 = ENUM_ONE_VALUE1;
|
||||
tmp->string = g_strdup("str");
|
||||
|
@ -491,8 +406,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
|
|||
tmp->integer = 41;
|
||||
tmp->u.value1->boolean = true;
|
||||
|
||||
visit_type_UserDefFlatUnion(data->ov, &tmp, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
visit_type_UserDefFlatUnion(data->ov, &tmp, NULL, &error_abort);
|
||||
arg = qmp_output_get_qobject(data->qov);
|
||||
|
||||
g_assert(qobject_type(arg) == QTYPE_QDICT);
|
||||
|
@ -511,20 +425,33 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
|
|||
const void *unused)
|
||||
{
|
||||
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->u.i = 42;
|
||||
|
||||
visit_type_UserDefAlternate(data->ov, &tmp, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
visit_type_UserDefAlternate(data->ov, &tmp, NULL, &error_abort);
|
||||
arg = qmp_output_get_qobject(data->qov);
|
||||
|
||||
g_assert(qobject_type(arg) == QTYPE_QINT);
|
||||
g_assert_cmpint(qint_get_int(qobject_to_qint(arg)), ==, 42);
|
||||
|
||||
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,
|
||||
|
@ -758,14 +685,12 @@ static void test_native_list(TestOutputVisitorData *data,
|
|||
UserDefNativeListUnionKind kind)
|
||||
{
|
||||
UserDefNativeListUnion *cvalue = g_new0(UserDefNativeListUnion, 1);
|
||||
Error *err = NULL;
|
||||
QObject *obj;
|
||||
|
||||
cvalue->type = kind;
|
||||
init_native_list(cvalue);
|
||||
|
||||
visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &error_abort);
|
||||
|
||||
obj = qmp_output_get_qobject(data->qov);
|
||||
check_native_list(obj, cvalue->type);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -336,14 +302,13 @@ static void test_primitives(gconstpointer opaque)
|
|||
const SerializeOps *ops = args->ops;
|
||||
PrimitiveType *pt = args->test_data;
|
||||
PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
|
||||
Error *err = NULL;
|
||||
void *serialize_data;
|
||||
|
||||
pt_copy->type = pt->type;
|
||||
ops->serialize(pt, &serialize_data, visit_primitive_type, &err);
|
||||
ops->deserialize((void **)&pt_copy, 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,
|
||||
&error_abort);
|
||||
|
||||
g_assert(err == NULL);
|
||||
g_assert(pt_copy != NULL);
|
||||
if (pt->type == PTYPE_STRING) {
|
||||
g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
|
||||
|
@ -379,7 +344,6 @@ static void test_primitive_lists(gconstpointer opaque)
|
|||
PrimitiveList pl = { .value = { NULL } };
|
||||
PrimitiveList pl_copy = { .value = { NULL } };
|
||||
PrimitiveList *pl_copy_ptr = &pl_copy;
|
||||
Error *err = NULL;
|
||||
void *serialize_data;
|
||||
void *cur_head = NULL;
|
||||
int i;
|
||||
|
@ -526,10 +490,11 @@ static void test_primitive_lists(gconstpointer opaque)
|
|||
}
|
||||
}
|
||||
|
||||
ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, &err);
|
||||
ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &err);
|
||||
ops->serialize((void **)&pl, &serialize_data, visit_primitive_list,
|
||||
&error_abort);
|
||||
ops->deserialize((void **)&pl_copy_ptr, serialize_data,
|
||||
visit_primitive_list, &error_abort);
|
||||
|
||||
g_assert(err == NULL);
|
||||
i = 0;
|
||||
|
||||
/* compare our deserialized list of primitives to the original */
|
||||
|
@ -686,10 +651,8 @@ static void test_primitive_lists(gconstpointer opaque)
|
|||
g_assert_cmpint(i, ==, 33);
|
||||
|
||||
ops->cleanup(serialize_data);
|
||||
dealloc_helper(&pl, visit_primitive_list, &err);
|
||||
g_assert(!err);
|
||||
dealloc_helper(&pl_copy, visit_primitive_list, &err);
|
||||
g_assert(!err);
|
||||
dealloc_helper(&pl, visit_primitive_list, &error_abort);
|
||||
dealloc_helper(&pl_copy, visit_primitive_list, &error_abort);
|
||||
g_free(args);
|
||||
}
|
||||
|
||||
|
@ -699,13 +662,12 @@ static void test_struct(gconstpointer opaque)
|
|||
const SerializeOps *ops = args->ops;
|
||||
TestStruct *ts = struct_create();
|
||||
TestStruct *ts_copy = NULL;
|
||||
Error *err = NULL;
|
||||
void *serialize_data;
|
||||
|
||||
ops->serialize(ts, &serialize_data, visit_struct, &err);
|
||||
ops->deserialize((void **)&ts_copy, serialize_data, visit_struct, &err);
|
||||
ops->serialize(ts, &serialize_data, visit_struct, &error_abort);
|
||||
ops->deserialize((void **)&ts_copy, serialize_data, visit_struct,
|
||||
&error_abort);
|
||||
|
||||
g_assert(err == NULL);
|
||||
struct_compare(ts, ts_copy);
|
||||
|
||||
struct_cleanup(ts);
|
||||
|
@ -721,14 +683,12 @@ static void test_nested_struct(gconstpointer opaque)
|
|||
const SerializeOps *ops = args->ops;
|
||||
UserDefTwo *udnp = nested_struct_create();
|
||||
UserDefTwo *udnp_copy = NULL;
|
||||
Error *err = NULL;
|
||||
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,
|
||||
&err);
|
||||
&error_abort);
|
||||
|
||||
g_assert(err == NULL);
|
||||
nested_struct_compare(udnp, udnp_copy);
|
||||
|
||||
nested_struct_cleanup(udnp);
|
||||
|
@ -743,7 +703,6 @@ static void test_nested_struct_list(gconstpointer opaque)
|
|||
TestArgs *args = (TestArgs *) opaque;
|
||||
const SerializeOps *ops = args->ops;
|
||||
UserDefTwoList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
|
||||
Error *err = NULL;
|
||||
void *serialize_data;
|
||||
int i = 0;
|
||||
|
||||
|
@ -754,11 +713,10 @@ static void test_nested_struct_list(gconstpointer opaque)
|
|||
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,
|
||||
visit_nested_struct_list, &err);
|
||||
|
||||
g_assert(err == NULL);
|
||||
visit_nested_struct_list, &error_abort);
|
||||
|
||||
tmp = listp;
|
||||
tmp_copy = listp_copy;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
if (!local_err) {
|
||||
|
|
Loading…
Reference in New Issue