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>
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 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 @@
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 @@
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 @@
{ '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 @@
=== 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 @@
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 @@
"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 @@
qapi_dealloc_visitor_cleanup(md);
}
+
void qapi_free_UserDefOne(UserDefOne *obj)
{
QapiDeallocVisitor *md;
@@ -569,7 +567,6 @@
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 @@
typedef struct UserDefOne UserDefOne;
- typedef struct UserDefOneList
- {
+ typedef struct UserDefOneList {
union {
UserDefOne *value;
uint64_t padding;
@@ -589,10 +585,10 @@
struct UserDefOneList *next;
} UserDefOneList;
+
[Functions on built-in types omitted...]
- struct UserDefOne
- {
+ struct UserDefOne {
int64_t integer;
char *string;
};
@@ -630,6 +626,7 @@
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 @@
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 @@
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 @@
QDECREF(qmp);
}
- const char *EXAMPLE_QAPIEvent_lookup[] = {
+ const char *example_QAPIEvent_lookup[] = {
"MY_EVENT",
NULL,
};
@@ -843,11 +839,10 @@
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 @@
%(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 @@
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
+ ret += gen_err_check('local_err')
+ ret += mcgen('''
+
+qmp_marshal_output_%(c_name)s(retval, ret, &local_err);
''',
- marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip()
- pop_indent(indent)
- return ret.rstrip()
+ c_name=c_name(name))
+ pop_indent()
+ return ret
-
-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)
-
-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 @@
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 @@
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 @@
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 @@
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 @@
''')
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 @@
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 @@
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 @@
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 @@
''',
event_enum_name = event_enum_name)
- i = 0
for string in event_enum_strings:
ret += mcgen('''
"%(string)s",
@@ -267,7 +265,7 @@
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 @@
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 @@
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 @@
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 @@
base = expr.get('base')
ret = mcgen('''
-struct %(name)s
-{
+
+struct %(name)s {
''',
name=c_name(structname))
@@ -105,10 +103,10 @@
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 @@
ret += mcgen('''
[%(max_index)s] = NULL,
};
-
''',
max_index=max_index)
return ret
@@ -128,13 +125,14 @@
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 @@
''',
name=name)
- return lookup_decl + enum_decl
+ return enum_decl + lookup_decl
def generate_alternate_qtypes(expr):
@@ -164,6 +162,7 @@
members = expr['data']
ret = mcgen('''
+
const int %(name)s_qtypes[QTYPE_MAX] = {
''',
name=c_name(name))
@@ -199,14 +198,40 @@
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 @@
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 @@
#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 @@
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 @@
# 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 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 @@
}
''',
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 @@
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 @@
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 @@
''',
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 @@
''',
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
# 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 @@
# 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 @@
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 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 @@
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 @@
"%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 @@
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 @@
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 @@
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 @@
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'
-
-def mcgen(code, **kwds):
- raw = cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
+ 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 basename(filename):
- return filename.split("/")[-1]
+def mcgen(code, **kwds):
+ if code[0] == '\n':
+ code = code[1:]
+ return cgen(code, **kwds)
+
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 @@
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 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 @@
#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 @@
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-int.exit b/tests/qapi-schema/args-alternate.exit
similarity index 100%
copy from tests/qapi-schema/data-int.exit
copy to 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-int.out b/tests/qapi-schema/args-alternate.out
similarity index 100%
copy from tests/qapi-schema/data-int.out
copy to tests/qapi-schema/args-alternate.out
diff --git a/tests/qapi-schema/args-array-empty.err b/tests/qapi-schema/args-array-empty.err
new file mode 100644
index 0000000..cb7ed33
--- /dev/null
+++ b/tests/qapi-schema/args-array-empty.err
@@ -0,0 +1 @@
+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-empty.exit b/tests/qapi-schema/args-array-empty.exit
similarity index 100%
rename from tests/qapi-schema/data-array-empty.exit
rename to 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
similarity index 100%
rename from tests/qapi-schema/data-array-empty.json
rename to tests/qapi-schema/args-array-empty.json
diff --git a/tests/qapi-schema/data-array-empty.out b/tests/qapi-schema/args-array-empty.out
similarity index 100%
rename from tests/qapi-schema/data-array-empty.out
rename to 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-array-unknown.exit b/tests/qapi-schema/args-array-unknown.exit
similarity index 100%
rename from tests/qapi-schema/data-array-unknown.exit
rename to 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
similarity index 100%
rename from tests/qapi-schema/data-array-unknown.json
rename to tests/qapi-schema/args-array-unknown.json
diff --git a/tests/qapi-schema/data-array-unknown.out b/tests/qapi-schema/args-array-unknown.out
similarity index 100%
rename from tests/qapi-schema/data-array-unknown.out
rename to 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-int.exit b/tests/qapi-schema/args-int.exit
similarity index 100%
rename from tests/qapi-schema/data-int.exit
rename to tests/qapi-schema/args-int.exit
diff --git a/tests/qapi-schema/data-int.json b/tests/qapi-schema/args-int.json
similarity index 100%
rename from tests/qapi-schema/data-int.json
rename to tests/qapi-schema/args-int.json
diff --git a/tests/qapi-schema/data-int.out b/tests/qapi-schema/args-int.out
similarity index 100%
rename from tests/qapi-schema/data-int.out
rename to 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-int.exit b/tests/qapi-schema/args-invalid.exit
similarity index 100%
copy from tests/qapi-schema/data-int.exit
copy to 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-int.out b/tests/qapi-schema/args-invalid.out
similarity index 100%
copy from tests/qapi-schema/data-int.out
copy to tests/qapi-schema/args-invalid.out
diff --git a/tests/qapi-schema/args-member-array-bad.err b/tests/qapi-schema/args-member-array-bad.err
new file mode 100644
index 0000000..881b4d9
--- /dev/null
+++ b/tests/qapi-schema/args-member-array-bad.err
@@ -0,0 +1 @@
+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-member-array-bad.exit b/tests/qapi-schema/args-member-array-bad.exit
similarity index 100%
rename from tests/qapi-schema/data-member-array-bad.exit
rename to 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
similarity index 100%
rename from tests/qapi-schema/data-member-array-bad.json
rename to tests/qapi-schema/args-member-array-bad.json
diff --git a/tests/qapi-schema/data-member-array-bad.out b/tests/qapi-schema/args-member-array-bad.out
similarity index 100%
rename from tests/qapi-schema/data-member-array-bad.out
rename to tests/qapi-schema/args-member-array-bad.out
diff --git a/tests/qapi-schema/data-member-array.err b/tests/qapi-schema/args-member-array.err
similarity index 100%
rename from tests/qapi-schema/data-member-array.err
rename to 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
similarity index 100%
rename from tests/qapi-schema/data-member-array.exit
rename to 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
similarity index 100%
rename from tests/qapi-schema/data-member-array.json
rename to 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
similarity index 100%
rename from tests/qapi-schema/data-member-array.out
rename to 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/data-member-unknown.exit b/tests/qapi-schema/args-member-unknown.exit
similarity index 100%
rename from tests/qapi-schema/data-member-unknown.exit
rename to 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
similarity index 100%
rename from tests/qapi-schema/data-member-unknown.json
rename to tests/qapi-schema/args-member-unknown.json
diff --git a/tests/qapi-schema/data-member-unknown.out b/tests/qapi-schema/args-member-unknown.out
similarity index 100%
rename from tests/qapi-schema/data-member-unknown.out
rename to 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/data-unknown.exit b/tests/qapi-schema/args-union.exit
similarity index 100%
copy from tests/qapi-schema/data-unknown.exit
copy to tests/qapi-schema/args-union.exit
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/data-unknown.out b/tests/qapi-schema/args-union.out
similarity index 100%
copy from tests/qapi-schema/data-unknown.out
copy to 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/data-unknown.exit b/tests/qapi-schema/args-unknown.exit
similarity index 100%
rename from tests/qapi-schema/data-unknown.exit
rename to tests/qapi-schema/args-unknown.exit
diff --git a/tests/qapi-schema/data-unknown.json b/tests/qapi-schema/args-unknown.json
similarity index 100%
rename from tests/qapi-schema/data-unknown.json
rename to tests/qapi-schema/args-unknown.json
diff --git a/tests/qapi-schema/data-unknown.out b/tests/qapi-schema/args-unknown.out
similarity index 100%
rename from tests/qapi-schema/data-unknown.out
rename to 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-empty.err b/tests/qapi-schema/data-array-empty.err
deleted file mode 100644
index f713f14..0000000
--- a/tests/qapi-schema/data-array-empty.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/data-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.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-array-bad.err b/tests/qapi-schema/data-member-array-bad.err
deleted file mode 100644
index 2c072d5..0000000
--- a/tests/qapi-schema/data-member-array-bad.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/data-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-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/data-int.exit b/tests/qapi-schema/leading-comma-list.exit
similarity index 100%
copy from tests/qapi-schema/data-int.exit
copy to tests/qapi-schema/leading-comma-list.exit
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/data-int.out b/tests/qapi-schema/leading-comma-list.out
similarity index 100%
copy from tests/qapi-schema/data-int.out
copy to 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/data-int.exit b/tests/qapi-schema/leading-comma-object.exit
similarity index 100%
copy from tests/qapi-schema/data-int.exit
copy to tests/qapi-schema/leading-comma-object.exit
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/data-int.out b/tests/qapi-schema/leading-comma-object.out
similarity index 100%
copy from tests/qapi-schema/data-int.out
copy to 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.exit b/tests/qapi-schema/nested-struct-returns.exit
deleted file mode 100644
index d00491f..0000000
--- a/tests/qapi-schema/nested-struct-returns.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
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/nested-struct-returns.out b/tests/qapi-schema/nested-struct-returns.out
deleted file mode 100644
index e69de29..0000000
--- a/tests/qapi-schema/nested-struct-returns.out
+++ /dev/null
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': 'UserDefOne',
+ 'base': 'UserDefZero', # intentional forward reference
+ 'data': { 'string': 'str', '*enum1': 'EnumOne' } }
+
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
-{ 'struct': 'UserDefOne',
- 'base': 'UserDefZero',
- 'data': { 'string': 'str', '*enum1': 'EnumOne' } }
-
{ '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/data-int.exit b/tests/qapi-schema/returns-dict.exit
similarity index 100%
copy from tests/qapi-schema/data-int.exit
copy to tests/qapi-schema/returns-dict.exit
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/data-int.out b/tests/qapi-schema/returns-dict.out
similarity index 100%
copy from tests/qapi-schema/data-int.out
copy to 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/data-member-array-bad.exit b/tests/qapi-schema/struct-data-invalid.exit
similarity index 100%
copy from tests/qapi-schema/data-member-array-bad.exit
copy to tests/qapi-schema/struct-data-invalid.exit
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/data-member-array-bad.out b/tests/qapi-schema/struct-data-invalid.out
similarity index 100%
copy from tests/qapi-schema/data-member-array-bad.out
copy to 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/data-member-array-bad.exit b/tests/qapi-schema/struct-member-invalid.exit
similarity index 100%
copy from tests/qapi-schema/data-member-array-bad.exit
copy to tests/qapi-schema/struct-member-invalid.exit
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/data-member-array-bad.out b/tests/qapi-schema/struct-member-invalid.out
similarity index 100%
copy from tests/qapi-schema/data-member-array-bad.out
copy to 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 @@
/* 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 @@
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 @@
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 @@
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; */