diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-09-04 15:53:48 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-09-04 15:53:48 +0100 |
commit | b5bff7518d8e4feda95f5c523cb24f72863c1df6 (patch) | |
tree | 28406ac68a1d1b57eb2e664432e8a3186db8bc87 | |
parent | b041066421e8dcc7d080dfcfd83551c9c9f24ade (diff) | |
parent | c4f498fe8532cdacc609262b104322911108df54 (diff) | |
download | hqemu-b5bff7518d8e4feda95f5c523cb24f72863c1df6.zip hqemu-b5bff7518d8e4feda95f5c523cb24f72863c1df6.tar.gz |
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2015-09-04' into staging
qapi: Another round of fixes and cleanups
# gpg: Signature made Fri 04 Sep 2015 14:48:54 BST 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-09-04: (33 commits)
qapi: Generators crash when --output-dir isn't given, fix
docs/qapi-code-gen.txt: Fix QAPI schema examples
qapi: Simplify error reporting for array types
qapi: Fix errors for non-string, non-dictionary members
tests/qapi-schema: Cover non-string, non-dictionary members
tests/qapi-schema: Cover two more syntax errors
qapi: Drop one of two "simple union must not have base" checks
qapi: Generated code cleanup
qapi-commands: Drop useless initialization
qapi-commands: Don't feed output of mcgen() to mcgen() again
qapi-commands: Inline gen_marshal_output_call()
qapi-commands: Fix gen_err_check(e) for e and e != 'local_err'
qapi: Command returning anonymous type doesn't work, outlaw
qapi: Fix to reject union command and event arguments
qapi-tests: New tests for union, alternate command arguments
tests/qapi-schema: Rename tests from data- to args-
tests/qapi-schema: Restore test case for flat union base bug
qapi: Document flaws in checking of names
qapi: Document shortcoming with union 'data' branch
qapi: Document that input visitor semantics are prone to leaks
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
82 files changed, 316 insertions, 267 deletions
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 61b5be4..ff16df2 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -163,7 +163,7 @@ The QAPI schema definitions can be modularized using the 'include' directive: The directive is evaluated recursively, and include paths are relative to the file using the directive. Multiple includes of the same file are -safe. No other keys should appear in the expression, and the include +idempotent. No other keys should appear in the expression, and the include value should be a string. As a matter of style, it is a good idea to have all files be @@ -300,7 +300,6 @@ an implicit C enum 'NameKind' is created, corresponding to the union the union can be named 'max', as this would collide with the implicit enum. The value for each branch can be of any type. - A flat union definition specifies a struct as its base, and avoids nesting on the wire. All branches of the union must be complex types, and the top-level fields of the union dictionary on @@ -314,7 +313,7 @@ adding a common field 'readonly', renaming the discriminator to something more applicable, and reducing the number of {} required on the wire: - { 'enum': 'BlockdevDriver', 'data': [ 'raw', 'qcow2' ] } + { 'enum': 'BlockdevDriver', 'data': [ 'file', 'qcow2' ] } { 'struct': 'BlockdevCommonOptions', 'data': { 'driver': 'BlockdevDriver', 'readonly': 'bool' } } { 'union': 'BlockdevOptions', @@ -350,7 +349,7 @@ is identical on the wire to: { 'struct': 'Base', 'data': { 'type': 'Enum' } } { 'struct': 'Branch1', 'data': { 'data': 'str' } } { 'struct': 'Branch2', 'data': { 'data': 'int' } } - { 'union': 'Flat': 'base': 'Base', 'discriminator': 'type', + { 'union': 'Flat', 'base': 'Base', 'discriminator': 'type', 'data': { 'one': 'Branch1', 'two': 'Branch2' } } @@ -394,7 +393,7 @@ following example objects: === Commands === Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT, - '*returns': TYPE-NAME-OR-DICT, + '*returns': TYPE-NAME, '*gen': false, '*success-response': false } Commands are defined by using a dictionary containing several members, @@ -405,10 +404,9 @@ Client JSON Protocol command exchange. The 'data' argument maps to the "arguments" dictionary passed in as part of a Client JSON Protocol command. The 'data' member is optional and defaults to {} (an empty dictionary). If present, it must be the -string name of a complex type, a one-element array containing the name -of a complex type, or a dictionary that declares an anonymous type -with the same semantics as a 'struct' expression, with one exception -noted below when 'gen' is used. +string name of a complex type, or a dictionary that declares an +anonymous type with the same semantics as a 'struct' expression, with +one exception noted below when 'gen' is used. The 'returns' member describes what will appear in the "return" field of a Client JSON Protocol reply on successful completion of a command. @@ -416,14 +414,13 @@ The member is optional from the command declaration; if absent, the "return" field will be an empty dictionary. If 'returns' is present, it must be the string name of a complex or built-in type, a one-element array containing the name of a complex or built-in type, -or a dictionary that declares an anonymous type with the same -semantics as a 'struct' expression, with one exception noted below -when 'gen' is used. Although it is permitted to have the 'returns' -member name a built-in type or an array of built-in types, any command -that does this cannot be extended to return additional information in -the future; thus, new commands should strongly consider returning a -dictionary-based type or an array of dictionaries, even if the -dictionary only contains one field at the present. +with one exception noted below when 'gen' is used. Although it is +permitted to have the 'returns' member name a built-in type or an +array of built-in types, any command that does this cannot be extended +to return additional information in the future; thus, new commands +should strongly consider returning a dictionary-based type or an array +of dictionaries, even if the dictionary only contains one field at the +present. All commands in Client JSON Protocol use a dictionary to report failure, with no way to specify that in QAPI. Where the error return @@ -555,6 +552,7 @@ Example: qapi_dealloc_visitor_cleanup(md); } + void qapi_free_UserDefOne(UserDefOne *obj) { QapiDeallocVisitor *md; @@ -569,7 +567,6 @@ Example: visit_type_UserDefOne(v, &obj, NULL, NULL); qapi_dealloc_visitor_cleanup(md); } - $ cat qapi-generated/example-qapi-types.h [Uninteresting stuff omitted...] @@ -580,8 +577,7 @@ Example: typedef struct UserDefOne UserDefOne; - typedef struct UserDefOneList - { + typedef struct UserDefOneList { union { UserDefOne *value; uint64_t padding; @@ -589,10 +585,10 @@ Example: struct UserDefOneList *next; } UserDefOneList; + [Functions on built-in types omitted...] - struct UserDefOne - { + struct UserDefOne { int64_t integer; char *string; }; @@ -630,6 +626,7 @@ Example: static void visit_type_UserDefOne_fields(Visitor *m, UserDefOne **obj, Error **errp) { Error *err = NULL; + visit_type_int(m, &(*obj)->integer, "integer", &err); if (err) { goto out; @@ -743,7 +740,7 @@ Example: static void qmp_marshal_input_my_command(QDict *args, QObject **ret, Error **errp) { Error *local_err = NULL; - UserDefOne *retval = NULL; + UserDefOne *retval; QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args)); QapiDeallocVisitor *md; Visitor *v; @@ -769,7 +766,6 @@ Example: v = qapi_dealloc_get_visitor(md); visit_type_UserDefOne(v, &arg1, "arg1", NULL); qapi_dealloc_visitor_cleanup(md); - return; } static void qmp_init_marshal(void) @@ -826,7 +822,7 @@ Example: QDECREF(qmp); } - const char *EXAMPLE_QAPIEvent_lookup[] = { + const char *example_QAPIEvent_lookup[] = { "MY_EVENT", NULL, }; @@ -843,11 +839,10 @@ Example: void qapi_event_send_my_event(Error **errp); - extern const char *EXAMPLE_QAPIEvent_lookup[]; - typedef enum EXAMPLE_QAPIEvent - { + extern const char *example_QAPIEvent_lookup[]; + typedef enum example_QAPIEvent { EXAMPLE_QAPI_EVENT_MY_EVENT = 0, EXAMPLE_QAPI_EVENT_MAX = 1, - } EXAMPLE_QAPIEvent; + } example_QAPIEvent; #endif diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index ca22acc..890ce5d 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -27,18 +27,19 @@ def generate_command_decl(name, args, ret_type): %(ret_type)s qmp_%(name)s(%(args)sError **errp); ''', ret_type=c_type(ret_type), name=c_name(name), - args=arglist).strip() + args=arglist) -def gen_err_check(errvar): - if errvar: - return mcgen(''' -if (local_err) { +def gen_err_check(err): + if not err: + return '' + return mcgen(''' +if (%(err)s) { goto out; } -''') - return '' +''', + err=err) -def gen_sync_call(name, args, ret_type, indent=0): +def gen_sync_call(name, args, ret_type): ret = "" arglist="" retval="" @@ -48,41 +49,34 @@ def gen_sync_call(name, args, ret_type, indent=0): if optional: arglist += "has_%s, " % c_name(argname) arglist += "%s, " % (c_name(argname)) - push_indent(indent) + push_indent() ret = mcgen(''' %(retval)sqmp_%(name)s(%(args)s&local_err); - ''', - name=c_name(name), args=arglist, retval=retval).rstrip() + name=c_name(name), args=arglist, retval=retval) if ret_type: - ret += "\n" + gen_err_check('local_err') - ret += "\n" + mcgen('''' -%(marshal_output_call)s -''', - marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip() - pop_indent(indent) - return ret.rstrip() - + ret += gen_err_check('local_err') + ret += mcgen(''' -def gen_marshal_output_call(name, ret_type): - if not ret_type: - return "" - return "qmp_marshal_output_%s(retval, ret, &local_err);" % c_name(name) +qmp_marshal_output_%(c_name)s(retval, ret, &local_err); +''', + c_name=c_name(name)) + pop_indent() + return ret -def gen_visitor_input_containers_decl(args, obj): +def gen_visitor_input_containers_decl(args): ret = "" push_indent() if len(args) > 0: ret += mcgen(''' -QmpInputVisitor *mi = qmp_input_visitor_new_strict(%(obj)s); +QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args)); QapiDeallocVisitor *md; Visitor *v; -''', - obj=obj) +''') pop_indent() - return ret.rstrip() + return ret def gen_visitor_input_vars_decl(args): ret = "" @@ -105,7 +99,7 @@ bool has_%(argname)s = false; argname=c_name(argname), argtype=c_type(argtype)) pop_indent() - return ret.rstrip() + return ret def gen_visitor_input_block(args, dealloc=False): ret = "" @@ -159,9 +153,9 @@ visit_type_%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s); qapi_dealloc_visitor_cleanup(md); ''') pop_indent() - return ret.rstrip() + return ret -def gen_marshal_output(name, args, ret_type, middle_mode): +def gen_marshal_output(name, ret_type): if not ret_type: return "" @@ -194,14 +188,14 @@ out: return ret -def gen_marshal_input_decl(name, args, ret_type, middle_mode): +def gen_marshal_input_decl(name, middle_mode): ret = 'void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name) if not middle_mode: ret = "static " + ret return ret def gen_marshal_input(name, args, ret_type, middle_mode): - hdr = gen_marshal_input_decl(name, args, ret_type, middle_mode) + hdr = gen_marshal_input_decl(name, middle_mode) ret = mcgen(''' %(header)s @@ -211,36 +205,24 @@ def gen_marshal_input(name, args, ret_type, middle_mode): header=hdr) if ret_type: - if is_c_ptr(ret_type): - retval = " %s retval = NULL;" % c_type(ret_type) - else: - retval = " %s retval;" % c_type(ret_type) ret += mcgen(''' -%(retval)s + %(c_type)s retval; ''', - retval=retval) + c_type=c_type(ret_type)) if len(args) > 0: - ret += mcgen(''' -%(visitor_input_containers_decl)s -%(visitor_input_vars_decl)s - -%(visitor_input_block)s - -''', - visitor_input_containers_decl=gen_visitor_input_containers_decl(args, "QOBJECT(args)"), - visitor_input_vars_decl=gen_visitor_input_vars_decl(args), - visitor_input_block=gen_visitor_input_block(args)) + ret += gen_visitor_input_containers_decl(args) + ret += gen_visitor_input_vars_decl(args) + '\n' + ret += gen_visitor_input_block(args) + '\n' else: ret += mcgen(''' (void)args; + ''') - ret += mcgen(''' -%(sync_call)s -''', - sync_call=gen_sync_call(name, args, ret_type, indent=4)) + ret += gen_sync_call(name, args, ret_type) + if re.search('^ *goto out\\;', ret, re.MULTILINE): ret += mcgen(''' @@ -248,11 +230,11 @@ out: ''') ret += mcgen(''' error_propagate(errp, local_err); -%(visitor_input_block_cleanup)s +''') + ret += gen_visitor_input_block(args, dealloc=True) + ret += mcgen(''' } -''', - visitor_input_block_cleanup=gen_visitor_input_block(args, - dealloc=True)) +''') return ret def gen_registry(commands): @@ -272,12 +254,13 @@ qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s); ret = mcgen(''' static void qmp_init_marshal(void) { -%(registry)s +''') + ret += registry + ret += mcgen(''' } qapi_init(qmp_init_marshal); -''', - registry=registry.rstrip()) +''') return ret middle_mode = False @@ -357,14 +340,14 @@ for cmd in commands: arglist = cmd['data'] if cmd.has_key('returns'): ret_type = cmd['returns'] - ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n" + ret = generate_command_decl(cmd['command'], arglist, ret_type) fdecl.write(ret) if ret_type: - ret = gen_marshal_output(cmd['command'], arglist, ret_type, middle_mode) + "\n" + ret = gen_marshal_output(cmd['command'], ret_type) + "\n" fdef.write(ret) if middle_mode: - fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], arglist, ret_type, middle_mode)) + fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], middle_mode)) ret = gen_marshal_input(cmd['command'], arglist, ret_type, middle_mode) + "\n" fdef.write(ret) diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index 56bc602..7f238df 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -167,8 +167,7 @@ extern const char *%(event_enum_name)s_lookup[]; event_enum_name = event_enum_name) enum_decl = mcgen(''' -typedef enum %(event_enum_name)s -{ +typedef enum %(event_enum_name)s { ''', event_enum_name = event_enum_name) @@ -199,7 +198,6 @@ const char *%(event_enum_name)s_lookup[] = { ''', event_enum_name = event_enum_name) - i = 0 for string in event_enum_strings: ret += mcgen(''' "%(string)s", @@ -267,7 +265,7 @@ fdecl.write(mcgen(''' exprs = parse_schema(input_file) -event_enum_name = prefix.upper().replace('-', '_') + "QAPIEvent" +event_enum_name = c_name(prefix + "QAPIEvent", protect=False) event_enum_values = [] event_enum_strings = [] diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index e6eb4b6..f2428f3 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -15,8 +15,7 @@ from qapi import * def generate_fwd_builtin(name): return mcgen(''' -typedef struct %(name)sList -{ +typedef struct %(name)sList { union { %(type)s value; uint64_t padding; @@ -32,8 +31,7 @@ def generate_fwd_struct(name): typedef struct %(name)s %(name)s; -typedef struct %(name)sList -{ +typedef struct %(name)sList { union { %(name)s *value; uint64_t padding; @@ -45,8 +43,8 @@ typedef struct %(name)sList def generate_fwd_enum_struct(name): return mcgen(''' -typedef struct %(name)sList -{ + +typedef struct %(name)sList { union { %(name)s value; uint64_t padding; @@ -79,8 +77,8 @@ def generate_struct(expr): base = expr.get('base') ret = mcgen(''' -struct %(name)s -{ + +struct %(name)s { ''', name=c_name(structname)) @@ -105,10 +103,10 @@ struct %(name)s def generate_enum_lookup(name, values): ret = mcgen(''' -const char * const %(name)s_lookup[] = { + +const char *const %(name)s_lookup[] = { ''', name=c_name(name)) - i = 0 for value in values: index = c_enum_const(name, value) ret += mcgen(''' @@ -120,7 +118,6 @@ const char * const %(name)s_lookup[] = { ret += mcgen(''' [%(max_index)s] = NULL, }; - ''', max_index=max_index) return ret @@ -128,13 +125,14 @@ const char * const %(name)s_lookup[] = { def generate_enum(name, values): name = c_name(name) lookup_decl = mcgen(''' -extern const char * const %(name)s_lookup[]; + +extern const char *const %(name)s_lookup[]; ''', name=name) enum_decl = mcgen(''' -typedef enum %(name)s -{ + +typedef enum %(name)s { ''', name=name) @@ -156,7 +154,7 @@ typedef enum %(name)s ''', name=name) - return lookup_decl + enum_decl + return enum_decl + lookup_decl def generate_alternate_qtypes(expr): @@ -164,6 +162,7 @@ def generate_alternate_qtypes(expr): members = expr['data'] ret = mcgen(''' + const int %(name)s_qtypes[QTYPE_MAX] = { ''', name=c_name(name)) @@ -199,14 +198,40 @@ def generate_union(expr, meta): discriminator_type_name = '%sKind' % (name) ret = mcgen(''' -struct %(name)s -{ + +struct %(name)s { +''', + name=name) + if base: + ret += mcgen(''' + /* Members inherited from %(c_name)s: */ +''', + c_name=c_name(base)) + base_fields = find_struct(base)['data'] + ret += generate_struct_fields(base_fields) + ret += mcgen(''' + /* Own members: */ +''') + else: + assert not discriminator + ret += mcgen(''' %(discriminator_type_name)s kind; - union { +''', + discriminator_type_name=c_name(discriminator_type_name)) + + # FIXME: What purpose does data serve, besides preventing a union that + # has a branch named 'data'? We use it in qapi-visit.py to decide + # whether to bypass the switch statement if visiting the discriminator + # failed; but since we 0-initialize structs, and cannot tell what + # branch of the union is in use if the discriminator is invalid, there + # should not be any data leaks even without a data pointer. Or, if + # 'data' is merely added to guarantee we don't have an empty union, + # shouldn't we enforce that at .json parse time? + ret += mcgen(''' + union { /* union tag is @%(c_name)s */ void *data; ''', - name=name, - discriminator_type_name=c_name(discriminator_type_name)) + c_name=c_name(discriminator or 'kind')) for key in typeinfo: ret += mcgen(''' @@ -217,17 +242,6 @@ struct %(name)s ret += mcgen(''' }; -''') - - if base: - assert discriminator - base_fields = find_struct(base)['data'].copy() - del base_fields[discriminator] - ret += generate_struct_fields(base_fields) - else: - assert not discriminator - - ret += mcgen(''' }; ''') if meta == 'alternate': @@ -314,14 +328,12 @@ fdef.write(mcgen(''' #include "qapi/dealloc-visitor.h" #include "%(prefix)sqapi-types.h" #include "%(prefix)sqapi-visit.h" - ''', prefix=prefix)) fdecl.write(mcgen(''' #include <stdbool.h> #include <stdint.h> - ''')) exprs = parse_schema(input_file) @@ -332,22 +344,22 @@ for typename in builtin_types.keys(): fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL")) for expr in exprs: - ret = "\n" + ret = "" if expr.has_key('struct'): ret += generate_fwd_struct(expr['struct']) elif expr.has_key('enum'): - ret += generate_enum(expr['enum'], expr['data']) + "\n" + ret += generate_enum(expr['enum'], expr['data']) ret += generate_fwd_enum_struct(expr['enum']) fdef.write(generate_enum_lookup(expr['enum'], expr['data'])) elif expr.has_key('union'): - ret += generate_fwd_struct(expr['union']) + "\n" + ret += generate_fwd_struct(expr['union']) enum_define = discriminator_find_enum_define(expr) if not enum_define: ret += generate_enum('%sKind' % expr['union'], expr['data'].keys()) fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys())) elif expr.has_key('alternate'): - ret += generate_fwd_struct(expr['alternate']) + "\n" + ret += generate_fwd_struct(expr['alternate']) ret += generate_enum('%sKind' % expr['alternate'], expr['data'].keys()) fdef.write(generate_enum_lookup('%sKind' % expr['alternate'], expr['data'].keys())) @@ -367,34 +379,32 @@ fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL")) # have the functions defined, so we use -b option to provide control # over these cases if do_builtins: - fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF")) for typename in builtin_types.keys(): fdef.write(generate_type_cleanup(typename + "List")) - fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF")) for expr in exprs: - ret = "\n" + ret = "" if expr.has_key('struct'): ret += generate_struct(expr) + "\n" ret += generate_type_cleanup_decl(expr['struct'] + "List") - fdef.write(generate_type_cleanup(expr['struct'] + "List") + "\n") + fdef.write(generate_type_cleanup(expr['struct'] + "List")) ret += generate_type_cleanup_decl(expr['struct']) - fdef.write(generate_type_cleanup(expr['struct']) + "\n") + fdef.write(generate_type_cleanup(expr['struct'])) elif expr.has_key('union'): - ret += generate_union(expr, 'union') + ret += generate_union(expr, 'union') + "\n" ret += generate_type_cleanup_decl(expr['union'] + "List") - fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n") + fdef.write(generate_type_cleanup(expr['union'] + "List")) ret += generate_type_cleanup_decl(expr['union']) - fdef.write(generate_type_cleanup(expr['union']) + "\n") + fdef.write(generate_type_cleanup(expr['union'])) elif expr.has_key('alternate'): - ret += generate_union(expr, 'alternate') + ret += generate_union(expr, 'alternate') + "\n" ret += generate_type_cleanup_decl(expr['alternate'] + "List") - fdef.write(generate_type_cleanup(expr['alternate'] + "List") + "\n") + fdef.write(generate_type_cleanup(expr['alternate'] + "List")) ret += generate_type_cleanup_decl(expr['alternate']) - fdef.write(generate_type_cleanup(expr['alternate']) + "\n") + fdef.write(generate_type_cleanup(expr['alternate'])) elif expr.has_key('enum'): - ret += generate_type_cleanup_decl(expr['enum'] + "List") - fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n") + ret += "\n" + generate_type_cleanup_decl(expr['enum'] + "List") + fdef.write(generate_type_cleanup(expr['enum'] + "List")) else: continue fdecl.write(ret) diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 5b99336..3cd662b 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -16,14 +16,23 @@ from ordereddict import OrderedDict from qapi import * import re -implicit_structs = [] +implicit_structs_seen = set() +struct_fields_seen = set() def generate_visit_implicit_struct(type): - global implicit_structs - if type in implicit_structs: + if type in implicit_structs_seen: return '' - implicit_structs.append(type) - return mcgen(''' + implicit_structs_seen.add(type) + ret = '' + if type not in struct_fields_seen: + # Need a forward declaration + ret += mcgen(''' + +static void visit_type_%(c_type)s_fields(Visitor *m, %(c_type)s **obj, Error **errp); +''', + c_type=type_name(type)) + + ret += mcgen(''' static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error **errp) { @@ -38,9 +47,11 @@ static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error * } ''', c_type=type_name(type)) + return ret def generate_visit_struct_fields(name, members, base = None): - substructs = [] + struct_fields_seen.add(name) + ret = '' if base: @@ -51,6 +62,7 @@ def generate_visit_struct_fields(name, members, base = None): static void visit_type_%(name)s_fields(Visitor *m, %(name)s **obj, Error **errp) { Error *err = NULL; + ''', name=c_name(name)) push_indent() @@ -103,7 +115,11 @@ out: return ret -def generate_visit_struct_body(name, members): +def generate_visit_struct_body(name): + # FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to + # *obj, but then visit_type_FOO_fields() fails, we should clean up *obj + # rather than leaving it non-NULL. As currently written, the caller must + # call qapi_free_FOO() to avoid a memory leak of the partial FOO. ret = mcgen(''' Error *err = NULL; @@ -135,14 +151,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e ''', name=c_name(name)) - ret += generate_visit_struct_body(name, members) + ret += generate_visit_struct_body(name) ret += mcgen(''' } ''') return ret -def generate_visit_list(name, members): +def generate_visit_list(name): return mcgen(''' void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp) @@ -171,15 +187,15 @@ out: ''', name=type_name(name)) -def generate_visit_enum(name, members): +def generate_visit_enum(name): return mcgen(''' -void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp) +void visit_type_%(c_name)s(Visitor *m, %(c_name)s *obj, const char *name, Error **errp) { - visit_type_enum(m, (int *)obj, %(name)s_lookup, "%(name)s", name, errp); + visit_type_enum(m, (int *)obj, %(c_name)s_lookup, "%(name)s", name, errp); } ''', - name=c_name(name)) + c_name=c_name(name), name=name) def generate_visit_alternate(name, members): ret = mcgen(''' @@ -252,7 +268,7 @@ def generate_visit_union(expr): else: # There will always be a discriminator in the C switch code, by default # it is an enum type generated silently - ret = generate_visit_enum(name + 'Kind', members.keys()) + ret = generate_visit_enum(name + 'Kind') disc_type = c_name(name) + 'Kind' if base: @@ -267,17 +283,17 @@ def generate_visit_union(expr): ret += mcgen(''' -void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp) +void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp) { Error *err = NULL; - visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); + visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err); if (err) { goto out; } if (*obj) { ''', - name=c_name(name)) + c_name=c_name(name), name=name) if base: ret += mcgen(''' @@ -289,20 +305,23 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e name=c_name(name)) if not discriminator: + tag = 'kind' disc_key = "type" else: + tag = discriminator disc_key = discriminator ret += mcgen(''' - visit_type_%(disc_type)s(m, &(*obj)->kind, "%(disc_key)s", &err); + visit_type_%(disc_type)s(m, &(*obj)->%(c_tag)s, "%(disc_key)s", &err); if (err) { goto out_obj; } if (!visit_start_union(m, !!(*obj)->data, &err) || err) { goto out_obj; } - switch ((*obj)->kind) { + switch ((*obj)->%(c_tag)s) { ''', disc_type = disc_type, + c_tag=c_name(tag), disc_key = disc_key) for key in members: @@ -340,7 +359,7 @@ out: return ret -def generate_declaration(name, members, builtin_type=False): +def generate_declaration(name, builtin_type=False): ret = "" if not builtin_type: name = c_name(name) @@ -357,7 +376,7 @@ void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, E return ret -def generate_enum_declaration(name, members): +def generate_enum_declaration(name): ret = mcgen(''' void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp); ''', @@ -365,7 +384,7 @@ void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, E return ret -def generate_decl_enum(name, members): +def generate_decl_enum(name): return mcgen(''' void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp); @@ -433,7 +452,7 @@ exprs = parse_schema(input_file) # for built-in types in our header files and simply guard them fdecl.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DECL")) for typename in builtin_types.keys(): - fdecl.write(generate_declaration(typename, None, builtin_type=True)) + fdecl.write(generate_declaration(typename, builtin_type=True)) fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL")) # ...this doesn't work for cases where we link in multiple objects that @@ -441,44 +460,42 @@ fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL")) # over these cases if do_builtins: for typename in builtin_types.keys(): - fdef.write(generate_visit_list(typename, None)) + fdef.write(generate_visit_list(typename)) for expr in exprs: if expr.has_key('struct'): ret = generate_visit_struct(expr) - ret += generate_visit_list(expr['struct'], expr['data']) + ret += generate_visit_list(expr['struct']) fdef.write(ret) - ret = generate_declaration(expr['struct'], expr['data']) + ret = generate_declaration(expr['struct']) fdecl.write(ret) elif expr.has_key('union'): ret = generate_visit_union(expr) - ret += generate_visit_list(expr['union'], expr['data']) + ret += generate_visit_list(expr['union']) fdef.write(ret) enum_define = discriminator_find_enum_define(expr) ret = "" if not enum_define: - ret = generate_decl_enum('%sKind' % expr['union'], - expr['data'].keys()) - ret += generate_declaration(expr['union'], expr['data']) + ret = generate_decl_enum('%sKind' % expr['union']) + ret += generate_declaration(expr['union']) fdecl.write(ret) elif expr.has_key('alternate'): ret = generate_visit_alternate(expr['alternate'], expr['data']) - ret += generate_visit_list(expr['alternate'], expr['data']) + ret += generate_visit_list(expr['alternate']) fdef.write(ret) - ret = generate_decl_enum('%sKind' % expr['alternate'], - expr['data'].keys()) - ret += generate_declaration(expr['alternate'], expr['data']) + ret = generate_decl_enum('%sKind' % expr['alternate']) + ret += generate_declaration(expr['alternate']) fdecl.write(ret) elif expr.has_key('enum'): - ret = generate_visit_list(expr['enum'], expr['data']) - ret += generate_visit_enum(expr['enum'], expr['data']) + ret = generate_visit_list(expr['enum']) + ret += generate_visit_enum(expr['enum']) fdef.write(ret) - ret = generate_decl_enum(expr['enum'], expr['data']) - ret += generate_enum_declaration(expr['enum'], expr['data']) + ret = generate_decl_enum(expr['enum']) + ret += generate_enum_declaration(expr['enum']) fdecl.write(ret) close_output(fdef, fdecl) diff --git a/scripts/qapi.py b/scripts/qapi.py index 06d7fc2..817d824 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -341,6 +341,8 @@ def discriminator_find_enum_define(expr): return find_enum(discriminator_type) +# FIXME should enforce "other than downstream extensions [...], all +# names should begin with a letter". valid_name = re.compile('^[a-zA-Z_][a-zA-Z0-9_.-]*$') def check_name(expr_info, source, name, allow_optional = False, enum_member = False): @@ -367,6 +369,8 @@ def check_name(expr_info, source, name, allow_optional = False, def add_name(name, info, meta, implicit = False): global all_names check_name(info, "'%s'" % meta, name) + # FIXME should reject names that differ only in '_' vs. '.' + # vs. '-', because they're liable to clash in generated C. if name in all_names: raise QAPIExprError(info, "%s '%s' is already defined" @@ -422,7 +426,6 @@ def check_type(expr_info, source, value, allow_array = False, allow_dict = False, allow_optional = False, allow_star = False, allow_metas = []): global all_names - orig_value = value if value is None: return @@ -440,7 +443,6 @@ def check_type(expr_info, source, value, allow_array = False, "%s: array type must contain single type name" % source) value = value[0] - orig_value = "array of %s" %value # Check if type name for value is okay if isinstance(value, str): @@ -451,20 +453,22 @@ def check_type(expr_info, source, value, allow_array = False, if not value in all_names: raise QAPIExprError(expr_info, "%s uses unknown type '%s'" - % (source, orig_value)) + % (source, value)) if not all_names[value] in allow_metas: raise QAPIExprError(expr_info, "%s cannot use %s type '%s'" - % (source, all_names[value], orig_value)) + % (source, all_names[value], value)) return - # value is a dictionary, check that each member is okay - if not isinstance(value, OrderedDict): - raise QAPIExprError(expr_info, - "%s should be a dictionary" % source) if not allow_dict: raise QAPIExprError(expr_info, "%s should be a type name" % source) + + if not isinstance(value, OrderedDict): + raise QAPIExprError(expr_info, + "%s should be a dictionary or type name" % source) + + # value is a dictionary, check that each member is okay for (key, arg) in value.items(): check_name(expr_info, "Member of %s" % source, key, allow_optional=allow_optional) @@ -495,26 +499,25 @@ def check_command(expr, expr_info): check_type(expr_info, "'data' for command '%s'" % name, expr.get('data'), allow_dict=True, allow_optional=True, - allow_metas=['union', 'struct'], allow_star=allow_star) + allow_metas=['struct'], allow_star=allow_star) returns_meta = ['union', 'struct'] if name in returns_whitelist: returns_meta += ['built-in', 'alternate', 'enum'] check_type(expr_info, "'returns' for command '%s'" % name, - expr.get('returns'), allow_array=True, allow_dict=True, + expr.get('returns'), allow_array=True, allow_optional=True, allow_metas=returns_meta, allow_star=allow_star) def check_event(expr, expr_info): global events name = expr['event'] - params = expr.get('data') if name.upper() == 'MAX': raise QAPIExprError(expr_info, "Event name 'MAX' cannot be created") events.append(name) check_type(expr_info, "'data' for event '%s'" % name, expr.get('data'), allow_dict=True, allow_optional=True, - allow_metas=['union', 'struct']) + allow_metas=['struct']) def check_union(expr, expr_info): name = expr['union'] @@ -523,14 +526,6 @@ def check_union(expr, expr_info): members = expr['data'] values = { 'MAX': '(automatic)' } - # If the object has a member 'base', its value must name a struct, - # and there must be a discriminator. - if base is not None: - if discriminator is None: - raise QAPIExprError(expr_info, - "Union '%s' requires a discriminator to go " - "along with base" %name) - # Two types of unions, determined by discriminator. # With no discriminator it is a simple union. @@ -943,24 +938,24 @@ def pop_indent(indent_amount=4): global indent_level indent_level -= indent_amount +# Generate @code with @kwds interpolated. +# Obey indent_level, and strip eatspace. def cgen(code, **kwds): - indent = genindent(indent_level) - lines = code.split('\n') - lines = map(lambda x: indent + x, lines) - return '\n'.join(lines) % kwds + '\n' + raw = code % kwds + if indent_level: + indent = genindent(indent_level) + raw = re.subn("^.", indent + r'\g<0>', raw, 0, re.MULTILINE) + raw = raw[0] + return re.sub(re.escape(eatspace) + ' *', '', raw) def mcgen(code, **kwds): - raw = cgen('\n'.join(code.split('\n')[1:-1]), **kwds) - return re.sub(re.escape(eatspace) + ' *', '', raw) + if code[0] == '\n': + code = code[1:] + return cgen(code, **kwds) -def basename(filename): - return filename.split("/")[-1] def guardname(filename): - guard = basename(filename).rsplit(".", 1)[0] - for substr in [".", " ", "-"]: - guard = guard.replace(substr, "_") - return guard.upper() + '_H' + return c_name(filename, protect=False).upper() def guardstart(name): return mcgen(''' @@ -1003,6 +998,12 @@ def parse_command_line(extra_options = "", extra_long_options = []): for oa in opts: o, a = oa if o in ("-p", "--prefix"): + match = re.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a) + if match.end() != len(a): + print >>sys.stderr, \ + "%s: 'funny character '%s' in argument of --prefix" \ + % (sys.argv[0], a[match.end()]) + sys.exit(1) prefix = a elif o in ("-o", "--output-dir"): output_dir = a + "/" @@ -1030,14 +1031,16 @@ def parse_command_line(extra_options = "", extra_long_options = []): def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, c_comment, h_comment): + guard = guardname(prefix + h_file) c_file = output_dir + prefix + c_file h_file = output_dir + prefix + h_file - try: - os.makedirs(output_dir) - except os.error, e: - if e.errno != errno.EEXIST: - raise + if output_dir: + try: + os.makedirs(output_dir) + except os.error, e: + if e.errno != errno.EEXIST: + raise def maybe_open(really, name, opt): if really: @@ -1062,7 +1065,7 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, #define %(guard)s ''', - comment = h_comment, guard = guardname(h_file))) + comment = h_comment, guard = guard)) return (fdef, fdecl) diff --git a/tests/Makefile b/tests/Makefile index 5271123..b128e28 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -229,13 +229,17 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \ redefined-type.json redefined-command.json redefined-builtin.json \ redefined-event.json command-int.json bad-data.json event-max.json \ type-bypass.json type-bypass-no-gen.json type-bypass-bad-gen.json \ - data-array-empty.json data-array-unknown.json data-int.json \ - data-unknown.json data-member-unknown.json data-member-array.json \ - data-member-array-bad.json returns-array-bad.json returns-int.json \ + args-invalid.json \ + args-array-empty.json args-array-unknown.json args-int.json \ + args-unknown.json args-member-unknown.json args-member-array.json \ + args-member-array-bad.json args-alternate.json args-union.json \ + returns-array-bad.json returns-int.json returns-dict.json \ returns-unknown.json returns-alternate.json returns-whitelist.json \ missing-colon.json missing-comma-list.json missing-comma-object.json \ - nested-struct-data.json nested-struct-returns.json non-objects.json \ + struct-data-invalid.json struct-member-invalid.json \ + nested-struct-data.json non-objects.json \ qapi-schema-test.json quoted-structural-chars.json \ + leading-comma-list.json leading-comma-object.json \ trailing-comma-list.json trailing-comma-object.json \ unclosed-list.json unclosed-object.json unclosed-string.json \ duplicate-key.json union-invalid-base.json union-bad-branch.json \ diff --git a/tests/qapi-schema/args-alternate.err b/tests/qapi-schema/args-alternate.err new file mode 100644 index 0000000..3086eae --- /dev/null +++ b/tests/qapi-schema/args-alternate.err @@ -0,0 +1 @@ +tests/qapi-schema/args-alternate.json:3: 'data' for command 'oops' cannot use alternate type 'Alt' diff --git a/tests/qapi-schema/data-array-empty.exit b/tests/qapi-schema/args-alternate.exit index d00491f..d00491f 100644 --- a/tests/qapi-schema/data-array-empty.exit +++ b/tests/qapi-schema/args-alternate.exit diff --git a/tests/qapi-schema/args-alternate.json b/tests/qapi-schema/args-alternate.json new file mode 100644 index 0000000..69e94d4 --- /dev/null +++ b/tests/qapi-schema/args-alternate.json @@ -0,0 +1,3 @@ +# we do not allow alternate arguments +{ 'alternate': 'Alt', 'data': { 'case1': 'int', 'case2': 'str' } } +{ 'command': 'oops', 'data': 'Alt' } diff --git a/tests/qapi-schema/data-array-empty.out b/tests/qapi-schema/args-alternate.out index e69de29..e69de29 100644 --- a/tests/qapi-schema/data-array-empty.out +++ b/tests/qapi-schema/args-alternate.out diff --git a/tests/qapi-schema/data-array-empty.err b/tests/qapi-schema/args-array-empty.err index f713f14..cb7ed33 100644 --- a/tests/qapi-schema/data-array-empty.err +++ b/tests/qapi-schema/args-array-empty.err @@ -1 +1 @@ -tests/qapi-schema/data-array-empty.json:2: Member 'empty' of 'data' for command 'oops': array type must contain single type name +tests/qapi-schema/args-array-empty.json:2: Member 'empty' of 'data' for command 'oops': array type must contain single type name diff --git a/tests/qapi-schema/data-array-unknown.exit b/tests/qapi-schema/args-array-empty.exit index d00491f..d00491f 100644 --- a/tests/qapi-schema/data-array-unknown.exit +++ b/tests/qapi-schema/args-array-empty.exit diff --git a/tests/qapi-schema/data-array-empty.json b/tests/qapi-schema/args-array-empty.json index 652dcfb..652dcfb 100644 --- a/tests/qapi-schema/data-array-empty.json +++ b/tests/qapi-schema/args-array-empty.json diff --git a/tests/qapi-schema/data-array-unknown.out b/tests/qapi-schema/args-array-empty.out index e69de29..e69de29 100644 --- a/tests/qapi-schema/data-array-unknown.out +++ b/tests/qapi-schema/args-array-empty.out diff --git a/tests/qapi-schema/args-array-unknown.err b/tests/qapi-schema/args-array-unknown.err new file mode 100644 index 0000000..cd7a0f9 --- /dev/null +++ b/tests/qapi-schema/args-array-unknown.err @@ -0,0 +1 @@ +tests/qapi-schema/args-array-unknown.json:2: Member 'array' of 'data' for command 'oops' uses unknown type 'NoSuchType' diff --git a/tests/qapi-schema/data-int.exit b/tests/qapi-schema/args-array-unknown.exit index d00491f..d00491f 100644 --- a/tests/qapi-schema/data-int.exit +++ b/tests/qapi-schema/args-array-unknown.exit diff --git a/tests/qapi-schema/data-array-unknown.json b/tests/qapi-schema/args-array-unknown.json index 6f3e883..6f3e883 100644 --- a/tests/qapi-schema/data-array-unknown.json +++ b/tests/qapi-schema/args-array-unknown.json diff --git a/tests/qapi-schema/data-int.out b/tests/qapi-schema/args-array-unknown.out index e69de29..e69de29 100644 --- a/tests/qapi-schema/data-int.out +++ b/tests/qapi-schema/args-array-unknown.out diff --git a/tests/qapi-schema/args-int.err b/tests/qapi-schema/args-int.err new file mode 100644 index 0000000..dc1d250 --- /dev/null +++ b/tests/qapi-schema/args-int.err @@ -0,0 +1 @@ +tests/qapi-schema/args-int.json:2: 'data' for command 'oops' cannot use built-in type 'int' diff --git a/tests/qapi-schema/data-member-array-bad.exit b/tests/qapi-schema/args-int.exit index d00491f..d00491f 100644 --- a/tests/qapi-schema/data-member-array-bad.exit +++ b/tests/qapi-schema/args-int.exit diff --git a/tests/qapi-schema/data-int.json b/tests/qapi-schema/args-int.json index a334d92..a334d92 100644 --- a/tests/qapi-schema/data-int.json +++ b/tests/qapi-schema/args-int.json diff --git a/tests/qapi-schema/data-member-array-bad.out b/tests/qapi-schema/args-int.out index e69de29..e69de29 100644 --- a/tests/qapi-schema/data-member-array-bad.out +++ b/tests/qapi-schema/args-int.out diff --git a/tests/qapi-schema/args-invalid.err b/tests/qapi-schema/args-invalid.err new file mode 100644 index 0000000..fe1e949 --- /dev/null +++ b/tests/qapi-schema/args-invalid.err @@ -0,0 +1 @@ +tests/qapi-schema/args-invalid.json:1: 'data' for command 'foo' should be a dictionary or type name diff --git a/tests/qapi-schema/data-member-unknown.exit b/tests/qapi-schema/args-invalid.exit index d00491f..d00491f 100644 --- a/tests/qapi-schema/data-member-unknown.exit +++ b/tests/qapi-schema/args-invalid.exit diff --git a/tests/qapi-schema/args-invalid.json b/tests/qapi-schema/args-invalid.json new file mode 100644 index 0000000..db09813 --- /dev/null +++ b/tests/qapi-schema/args-invalid.json @@ -0,0 +1,2 @@ +{ 'command': 'foo', + 'data': false } diff --git a/tests/qapi-schema/data-member-array.err b/tests/qapi-schema/args-invalid.out index e69de29..e69de29 100644 --- a/tests/qapi-schema/data-member-array.err +++ b/tests/qapi-schema/args-invalid.out diff --git a/tests/qapi-schema/data-member-array-bad.err b/tests/qapi-schema/args-member-array-bad.err index 2c072d5..881b4d9 100644 --- a/tests/qapi-schema/data-member-array-bad.err +++ b/tests/qapi-schema/args-member-array-bad.err @@ -1 +1 @@ -tests/qapi-schema/data-member-array-bad.json:2: Member 'member' of 'data' for command 'oops': array type must contain single type name +tests/qapi-schema/args-member-array-bad.json:2: Member 'member' of 'data' for command 'oops': array type must contain single type name diff --git a/tests/qapi-schema/data-unknown.exit b/tests/qapi-schema/args-member-array-bad.exit index d00491f..d00491f 100644 --- a/tests/qapi-schema/data-unknown.exit +++ b/tests/qapi-schema/args-member-array-bad.exit diff --git a/tests/qapi-schema/data-member-array-bad.json b/tests/qapi-schema/args-member-array-bad.json index b2ff144..b2ff144 100644 --- a/tests/qapi-schema/data-member-array-bad.json +++ b/tests/qapi-schema/args-member-array-bad.json diff --git a/tests/qapi-schema/data-member-unknown.out b/tests/qapi-schema/args-member-array-bad.out index e69de29..e69de29 100644 --- a/tests/qapi-schema/data-member-unknown.out +++ b/tests/qapi-schema/args-member-array-bad.out diff --git a/tests/qapi-schema/data-unknown.out b/tests/qapi-schema/args-member-array.err index e69de29..e69de29 100644 --- a/tests/qapi-schema/data-unknown.out +++ b/tests/qapi-schema/args-member-array.err diff --git a/tests/qapi-schema/data-member-array.exit b/tests/qapi-schema/args-member-array.exit index 573541a..573541a 100644 --- a/tests/qapi-schema/data-member-array.exit +++ b/tests/qapi-schema/args-member-array.exit diff --git a/tests/qapi-schema/data-member-array.json b/tests/qapi-schema/args-member-array.json index e6f7f5d..e6f7f5d 100644 --- a/tests/qapi-schema/data-member-array.json +++ b/tests/qapi-schema/args-member-array.json diff --git a/tests/qapi-schema/data-member-array.out b/tests/qapi-schema/args-member-array.out index c39fa25..c39fa25 100644 --- a/tests/qapi-schema/data-member-array.out +++ b/tests/qapi-schema/args-member-array.out diff --git a/tests/qapi-schema/args-member-unknown.err b/tests/qapi-schema/args-member-unknown.err new file mode 100644 index 0000000..f6f8282 --- /dev/null +++ b/tests/qapi-schema/args-member-unknown.err @@ -0,0 +1 @@ +tests/qapi-schema/args-member-unknown.json:2: Member 'member' of 'data' for command 'oops' uses unknown type 'NoSuchType' diff --git a/tests/qapi-schema/nested-struct-returns.exit b/tests/qapi-schema/args-member-unknown.exit index d00491f..d00491f 100644 --- a/tests/qapi-schema/nested-struct-returns.exit +++ b/tests/qapi-schema/args-member-unknown.exit diff --git a/tests/qapi-schema/data-member-unknown.json b/tests/qapi-schema/args-member-unknown.json index 342a41e..342a41e 100644 --- a/tests/qapi-schema/data-member-unknown.json +++ b/tests/qapi-schema/args-member-unknown.json diff --git a/tests/qapi-schema/nested-struct-returns.out b/tests/qapi-schema/args-member-unknown.out index e69de29..e69de29 100644 --- a/tests/qapi-schema/nested-struct-returns.out +++ b/tests/qapi-schema/args-member-unknown.out diff --git a/tests/qapi-schema/args-union.err b/tests/qapi-schema/args-union.err new file mode 100644 index 0000000..1d693d7 --- /dev/null +++ b/tests/qapi-schema/args-union.err @@ -0,0 +1 @@ +tests/qapi-schema/args-union.json:4: 'data' for command 'oops' cannot use union type 'Uni' diff --git a/tests/qapi-schema/args-union.exit b/tests/qapi-schema/args-union.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/args-union.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/args-union.json b/tests/qapi-schema/args-union.json new file mode 100644 index 0000000..7bdcbb7 --- /dev/null +++ b/tests/qapi-schema/args-union.json @@ -0,0 +1,4 @@ +# we do not allow union arguments +# TODO should we support this? +{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } } +{ 'command': 'oops', 'data': 'Uni' } diff --git a/tests/qapi-schema/args-union.out b/tests/qapi-schema/args-union.out new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/qapi-schema/args-union.out diff --git a/tests/qapi-schema/args-unknown.err b/tests/qapi-schema/args-unknown.err new file mode 100644 index 0000000..4d91ec8 --- /dev/null +++ b/tests/qapi-schema/args-unknown.err @@ -0,0 +1 @@ +tests/qapi-schema/args-unknown.json:2: 'data' for command 'oops' uses unknown type 'NoSuchType' diff --git a/tests/qapi-schema/args-unknown.exit b/tests/qapi-schema/args-unknown.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/args-unknown.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/data-unknown.json b/tests/qapi-schema/args-unknown.json index 32aba43..32aba43 100644 --- a/tests/qapi-schema/data-unknown.json +++ b/tests/qapi-schema/args-unknown.json diff --git a/tests/qapi-schema/args-unknown.out b/tests/qapi-schema/args-unknown.out new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/qapi-schema/args-unknown.out diff --git a/tests/qapi-schema/command-int.json b/tests/qapi-schema/command-int.json index c90d408..9a62554 100644 --- a/tests/qapi-schema/command-int.json +++ b/tests/qapi-schema/command-int.json @@ -1,3 +1,2 @@ # we reject collisions between commands and types -{ 'command': 'int', 'data': { 'character': 'str' }, - 'returns': { 'value': 'int' } } +{ 'command': 'int', 'data': { 'character': 'str' } } diff --git a/tests/qapi-schema/data-array-unknown.err b/tests/qapi-schema/data-array-unknown.err deleted file mode 100644 index 8b731bb..0000000 --- a/tests/qapi-schema/data-array-unknown.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/data-array-unknown.json:2: Member 'array' of 'data' for command 'oops' uses unknown type 'array of NoSuchType' diff --git a/tests/qapi-schema/data-int.err b/tests/qapi-schema/data-int.err deleted file mode 100644 index 1a9b077..0000000 --- a/tests/qapi-schema/data-int.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/data-int.json:2: 'data' for command 'oops' cannot use built-in type 'int' diff --git a/tests/qapi-schema/data-member-unknown.err b/tests/qapi-schema/data-member-unknown.err deleted file mode 100644 index ab905db..0000000 --- a/tests/qapi-schema/data-member-unknown.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/data-member-unknown.json:2: Member 'member' of 'data' for command 'oops' uses unknown type 'NoSuchType' diff --git a/tests/qapi-schema/data-unknown.err b/tests/qapi-schema/data-unknown.err deleted file mode 100644 index 5b07277..0000000 --- a/tests/qapi-schema/data-unknown.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/data-unknown.json:2: 'data' for command 'oops' uses unknown type 'NoSuchType' diff --git a/tests/qapi-schema/leading-comma-list.err b/tests/qapi-schema/leading-comma-list.err new file mode 100644 index 0000000..f5c870b --- /dev/null +++ b/tests/qapi-schema/leading-comma-list.err @@ -0,0 +1 @@ +tests/qapi-schema/leading-comma-list.json:2:13: Expected "{", "[", "]", string, boolean or "null" diff --git a/tests/qapi-schema/leading-comma-list.exit b/tests/qapi-schema/leading-comma-list.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/leading-comma-list.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/leading-comma-list.json b/tests/qapi-schema/leading-comma-list.json new file mode 100644 index 0000000..c5ba501 --- /dev/null +++ b/tests/qapi-schema/leading-comma-list.json @@ -0,0 +1,2 @@ +{ 'enum': 'Status', + 'data': [ , 'good', 'bad', 'ugly' ] } diff --git a/tests/qapi-schema/leading-comma-list.out b/tests/qapi-schema/leading-comma-list.out new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/qapi-schema/leading-comma-list.out diff --git a/tests/qapi-schema/leading-comma-object.err b/tests/qapi-schema/leading-comma-object.err new file mode 100644 index 0000000..f767b95 --- /dev/null +++ b/tests/qapi-schema/leading-comma-object.err @@ -0,0 +1 @@ +tests/qapi-schema/leading-comma-object.json:1:3: Expected string or "}" diff --git a/tests/qapi-schema/leading-comma-object.exit b/tests/qapi-schema/leading-comma-object.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/leading-comma-object.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/leading-comma-object.json b/tests/qapi-schema/leading-comma-object.json new file mode 100644 index 0000000..c89023f --- /dev/null +++ b/tests/qapi-schema/leading-comma-object.json @@ -0,0 +1,2 @@ +{ , 'enum': 'Status', + 'data': [ 'good', 'bad', 'ugly' ] } diff --git a/tests/qapi-schema/leading-comma-object.out b/tests/qapi-schema/leading-comma-object.out new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/qapi-schema/leading-comma-object.out diff --git a/tests/qapi-schema/nested-struct-data.json b/tests/qapi-schema/nested-struct-data.json index 3d52d2b..efbe773 100644 --- a/tests/qapi-schema/nested-struct-data.json +++ b/tests/qapi-schema/nested-struct-data.json @@ -1,4 +1,3 @@ # inline subtypes collide with our desired future use of defaults { 'command': 'foo', - 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' }, - 'returns': {} } + 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } } diff --git a/tests/qapi-schema/nested-struct-returns.err b/tests/qapi-schema/nested-struct-returns.err deleted file mode 100644 index 5238d07..0000000 --- a/tests/qapi-schema/nested-struct-returns.err +++ /dev/null @@ -1 +0,0 @@ -tests/qapi-schema/nested-struct-returns.json:2: Member 'a' of 'returns' for command 'foo' should be a type name diff --git a/tests/qapi-schema/nested-struct-returns.json b/tests/qapi-schema/nested-struct-returns.json deleted file mode 100644 index d2cd047..0000000 --- a/tests/qapi-schema/nested-struct-returns.json +++ /dev/null @@ -1,3 +0,0 @@ -# inline subtypes collide with our desired future use of defaults -{ 'command': 'foo', - 'returns': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } } diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index c7eaa86..a9e5aab 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -7,13 +7,13 @@ 'data': { 'enum1': 'EnumOne', '*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } } # for testing nested structs -{ 'struct': 'UserDefZero', - 'data': { 'integer': 'int' } } - { 'struct': 'UserDefOne', - 'base': 'UserDefZero', + 'base': 'UserDefZero', # intentional forward reference 'data': { 'string': 'str', '*enum1': 'EnumOne' } } +{ 'struct': 'UserDefZero', + 'data': { 'integer': 'int' } } + { 'struct': 'UserDefTwoDictDict', 'data': { 'userdef': 'UserDefOne', 'string': 'str' } } @@ -31,30 +31,36 @@ 'data': { 'boolean': 'bool' } } { 'struct': 'UserDefB', - 'data': { 'integer': 'int' } } - -{ 'struct': 'UserDefC', - 'data': { 'string1': 'str', 'string2': 'str' } } - -{ 'struct': 'UserDefUnionBase', - 'data': { 'string': 'str', 'enum1': 'EnumOne' } } + 'data': { 'intb': 'int' } } { 'union': 'UserDefFlatUnion', - 'base': 'UserDefUnionBase', + 'base': 'UserDefUnionBase', # intentional forward reference 'discriminator': 'enum1', - 'data': { 'value1' : 'UserDefA', 'value2' : 'UserDefB', 'value3' : 'UserDefB' } } + 'data': { 'value1' : 'UserDefA', + 'value2' : 'UserDefB', + 'value3' : 'UserDefB' } } # FIXME generated struct UserDefFlatUnion has members for direct base -# UserDefOne, but lacks members for indirect base UserDefZero +# UserDefUnionBase, but lacks members for indirect base UserDefZero + +{ 'struct': 'UserDefUnionBase', + 'base': 'UserDefZero', + 'data': { 'string': 'str', 'enum1': 'EnumOne' } } # this variant of UserDefFlatUnion defaults to a union that uses fields with # allocated types to test corner cases in the cleanup/dealloc visitor { 'union': 'UserDefFlatUnion2', 'base': 'UserDefUnionBase', 'discriminator': 'enum1', - 'data': { 'value1' : 'UserDefC', 'value2' : 'UserDefB', 'value3' : 'UserDefA' } } + 'data': { 'value1' : 'UserDefC', # intentional forward reference + 'value2' : 'UserDefB', + 'value3' : 'UserDefA' } } { 'alternate': 'UserDefAlternate', 'data': { 'uda': 'UserDefA', 's': 'str', 'i': 'int' } } +# FIXME only a declaration of visit_type_UserDefAlternateKind() generated + +{ 'struct': 'UserDefC', + 'data': { 'string1': 'str', 'string2': 'str' } } # for testing native lists { 'union': 'UserDefNativeListUnion', @@ -123,6 +129,9 @@ { 'alternate': '__org.qemu_x-Alt', 'data': { '__org.qemu_x-branch': 'str', 'b': '__org.qemu_x-Base' } } { 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' } +# FIXME generated qapi_event_send___org_qemu_x_event() has only a +# parameter for data's member __org_qemu_x_member2, none for its base +# __org.qemu_x-Base's member __org_qemu_x_member1 { 'command': '__org.qemu_x-command', 'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'], 'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' }, diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index cf0ccc4..b0b7187 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -1,17 +1,17 @@ [OrderedDict([('enum', 'EnumOne'), ('data', ['value1', 'value2', 'value3'])]), OrderedDict([('struct', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]), - OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('struct', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]), + OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('struct', 'UserDefTwoDictDict'), ('data', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]), OrderedDict([('struct', 'UserDefTwoDict'), ('data', OrderedDict([('string1', 'str'), ('dict2', 'UserDefTwoDictDict'), ('*dict3', 'UserDefTwoDictDict')]))]), OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', 'UserDefTwoDict')]))]), OrderedDict([('struct', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]), - OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]), - OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]), - OrderedDict([('struct', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]), + OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('intb', 'int')]))]), OrderedDict([('union', 'UserDefFlatUnion'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefA'), ('value2', 'UserDefB'), ('value3', 'UserDefB')]))]), + OrderedDict([('struct', 'UserDefUnionBase'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]), OrderedDict([('union', 'UserDefFlatUnion2'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefC'), ('value2', 'UserDefB'), ('value3', 'UserDefA')]))]), OrderedDict([('alternate', 'UserDefAlternate'), ('data', OrderedDict([('uda', 'UserDefA'), ('s', 'str'), ('i', 'int')]))]), + OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]), OrderedDict([('union', 'UserDefNativeListUnion'), ('data', OrderedDict([('integer', ['int']), ('s8', ['int8']), ('s16', ['int16']), ('s32', ['int32']), ('s64', ['int64']), ('u8', ['uint8']), ('u16', ['uint16']), ('u32', ['uint32']), ('u64', ['uint64']), ('number', ['number']), ('boolean', ['bool']), ('string', ['str']), ('sizes', ['size'])]))]), OrderedDict([('command', 'user_def_cmd'), ('data', OrderedDict())]), OrderedDict([('command', 'user_def_cmd1'), ('data', OrderedDict([('ud1a', 'UserDefOne')]))]), @@ -39,15 +39,15 @@ {'enum_name': '__org.qemu_x-Union1Kind', 'enum_values': None}, {'enum_name': '__org.qemu_x-AltKind', 'enum_values': None}] [OrderedDict([('struct', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]), - OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('struct', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]), + OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('struct', 'UserDefTwoDictDict'), ('data', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]), OrderedDict([('struct', 'UserDefTwoDict'), ('data', OrderedDict([('string1', 'str'), ('dict2', 'UserDefTwoDictDict'), ('*dict3', 'UserDefTwoDictDict')]))]), OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', 'UserDefTwoDict')]))]), OrderedDict([('struct', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]), - OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]), + OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('intb', 'int')]))]), + OrderedDict([('struct', 'UserDefUnionBase'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]), OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]), - OrderedDict([('struct', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]), OrderedDict([('struct', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]), OrderedDict([('struct', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))]), OrderedDict([('struct', '__org.qemu_x-Base'), ('data', OrderedDict([('__org.qemu_x-member1', '__org.qemu_x-Enum')]))]), diff --git a/tests/qapi-schema/returns-dict.err b/tests/qapi-schema/returns-dict.err new file mode 100644 index 0000000..eb2d0c4 --- /dev/null +++ b/tests/qapi-schema/returns-dict.err @@ -0,0 +1 @@ +tests/qapi-schema/returns-dict.json:2: 'returns' for command 'oops' should be a type name diff --git a/tests/qapi-schema/returns-dict.exit b/tests/qapi-schema/returns-dict.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/returns-dict.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/returns-dict.json b/tests/qapi-schema/returns-dict.json new file mode 100644 index 0000000..1cfef3e --- /dev/null +++ b/tests/qapi-schema/returns-dict.json @@ -0,0 +1,2 @@ +# we reject inline struct return type +{ 'command': 'oops', 'returns': { 'a': 'str' } } diff --git a/tests/qapi-schema/returns-dict.out b/tests/qapi-schema/returns-dict.out new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/qapi-schema/returns-dict.out diff --git a/tests/qapi-schema/returns-whitelist.err b/tests/qapi-schema/returns-whitelist.err index a41f019..f47c1ee 100644 --- a/tests/qapi-schema/returns-whitelist.err +++ b/tests/qapi-schema/returns-whitelist.err @@ -1 +1 @@ -tests/qapi-schema/returns-whitelist.json:10: 'returns' for command 'no-way-this-will-get-whitelisted' cannot use built-in type 'array of int' +tests/qapi-schema/returns-whitelist.json:10: 'returns' for command 'no-way-this-will-get-whitelisted' cannot use built-in type 'int' diff --git a/tests/qapi-schema/struct-data-invalid.err b/tests/qapi-schema/struct-data-invalid.err new file mode 100644 index 0000000..6644f4c --- /dev/null +++ b/tests/qapi-schema/struct-data-invalid.err @@ -0,0 +1 @@ +tests/qapi-schema/struct-data-invalid.json:1: 'data' for struct 'foo' should be a dictionary or type name diff --git a/tests/qapi-schema/struct-data-invalid.exit b/tests/qapi-schema/struct-data-invalid.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/struct-data-invalid.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/struct-data-invalid.json b/tests/qapi-schema/struct-data-invalid.json new file mode 100644 index 0000000..9adbc3b --- /dev/null +++ b/tests/qapi-schema/struct-data-invalid.json @@ -0,0 +1,2 @@ +{ 'struct': 'foo', + 'data': false } diff --git a/tests/qapi-schema/struct-data-invalid.out b/tests/qapi-schema/struct-data-invalid.out new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/qapi-schema/struct-data-invalid.out diff --git a/tests/qapi-schema/struct-member-invalid.err b/tests/qapi-schema/struct-member-invalid.err new file mode 100644 index 0000000..69a326d --- /dev/null +++ b/tests/qapi-schema/struct-member-invalid.err @@ -0,0 +1 @@ +tests/qapi-schema/struct-member-invalid.json:1: Member 'a' of 'data' for struct 'foo' should be a type name diff --git a/tests/qapi-schema/struct-member-invalid.exit b/tests/qapi-schema/struct-member-invalid.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/struct-member-invalid.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/struct-member-invalid.json b/tests/qapi-schema/struct-member-invalid.json new file mode 100644 index 0000000..8f172f7 --- /dev/null +++ b/tests/qapi-schema/struct-member-invalid.json @@ -0,0 +1,2 @@ +{ 'struct': 'foo', + 'data': { 'a': false } } diff --git a/tests/qapi-schema/struct-member-invalid.out b/tests/qapi-schema/struct-member-invalid.out new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/qapi-schema/struct-member-invalid.out diff --git a/tests/qapi-schema/union-base-no-discriminator.err b/tests/qapi-schema/union-base-no-discriminator.err index fc8b79c..8b7a242 100644 --- a/tests/qapi-schema/union-base-no-discriminator.err +++ b/tests/qapi-schema/union-base-no-discriminator.err @@ -1 +1 @@ -tests/qapi-schema/union-base-no-discriminator.json:11: Union 'TestUnion' requires a discriminator to go along with base +tests/qapi-schema/union-base-no-discriminator.json:11: Simple union 'TestUnion' must not have a base diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c index 1ee40e1..28f146d 100644 --- a/tests/test-qmp-event.c +++ b/tests/test-qmp-event.c @@ -94,7 +94,7 @@ static bool qdict_cmp_simple(QDict *a, QDict *b) /* This function is hooked as final emit function, which can verify the correctness. */ -static void event_test_emit(TEST_QAPIEvent event, QDict *d, Error **errp) +static void event_test_emit(test_QAPIEvent event, QDict *d, Error **errp) { QObject *obj; QDict *t; diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index b961953..a5cfefa 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -313,7 +313,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data, visit_type_UserDefFlatUnion(v, &tmp, NULL, &err); g_assert(err == NULL); - g_assert_cmpint(tmp->kind, ==, ENUM_ONE_VALUE1); + g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1); g_assert_cmpstr(tmp->string, ==, "str"); /* TODO g_assert_cmpint(tmp->integer, ==, 41); */ g_assert_cmpint(tmp->value1->boolean, ==, true); @@ -636,6 +636,8 @@ static void test_visitor_in_errors(TestInputVisitorData *data, visit_type_TestStruct(v, &p, NULL, &err); g_assert(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); diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c index 87ba350..338ada0 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -437,7 +437,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data, Error *err = NULL; UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion)); - tmp->kind = ENUM_ONE_VALUE1; + tmp->enum1 = ENUM_ONE_VALUE1; tmp->string = g_strdup("str"); tmp->value1 = g_malloc0(sizeof(UserDefA)); /* TODO when generator bug is fixed: tmp->integer = 41; */ |