QAPI patches

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJWH0puAAoJEDhwtADrkYZT6/cP/3EfS/0TVI6tiU1pz/qm6SMy
 yFYeYw1WIHw9/x7esRMGZ977QfmuL1YhZ0sD4lmpIMcXwuzTd0/tuO0AydH7ffZj
 daL/rKSiQjdPCbebHol6rAFWHOxRBqz1g2jDgIM9FB4dEjqzbUydV7/9Mmo5b44v
 Hss0/neKn6zVHognv4aB/FMmjjsbzqgvHcour7T+rVIF9qial/hA2I6ioM2kCnt4
 jbkLUYYhb/rPNTlxjvT4vNsDfTiHScTeow6gRzd5LL5f1K7nTmRzqalsyZpRgpl+
 mDIrbPExN4O6gDZkKDk3pmwAI+vPTVNP868tSjqNJmUeCdUmT9EQ8LagZCbt0b/e
 aViwkRmuDv+FNPfkmgmhXY0RTaX9QDT3vwWSjOzLGvrFj66UfbepXfBWlOZnl7DQ
 KJU33CnEjkbu/viiCat4HjCGt1kF11s+YPlYWGXgyo1QkF54o8OmKGTjZOaEze+R
 gvIdtbBKYSwnyMbPo26OrwvTDBYfZ+F5j2MCpuDEgwE0CtKbtAOCc87PMRtunDoh
 xloQ3F6fuItC9dPUGDcDxvN9RG3uPNcOUU4aoS0/y7CHlHqlxOJz6AIlm57vO67B
 T/PAd1uW6T/yFJWCub0iAHCkvmui639eIz2VyPfuJJb2YAiWivULsLplOzS1cYE4
 N7J7BPGEATvaCCmmRPjd
 =CoJX
 -----END PGP SIGNATURE-----

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

QAPI patches

# gpg: Signature made Thu 15 Oct 2015 07:40:46 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-10-15:
  qapi: Track location that created an implicit type
  qapi: Create simple union type member earlier
  qapi: Lazy creation of array types
  qapi: Don't use info as witness of implicit object type
  qapi: Drop redundant args-member-array test
  qapi: Drop redundant flat-union-reverse-define test
  qapi: Drop redundant returns-int test
  qapi: Move empty-enum to compile-time test
  qapi: Drop redundant alternate-good test
  qapi: Prepare for errors during check()
  qapi: Use predicate callback to determine visit filtering
  qapi: Fix regression with '-netdev help'

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-10-16 17:13:05 +01:00
commit 61f7901bb8
29 changed files with 162 additions and 171 deletions

View File

@ -3415,6 +3415,17 @@
'cpuid-register': 'X86CPURegister32',
'features': 'int' } }
##
# @DummyForceArrays
#
# Not used by QMP; hack to let us use X86CPUFeatureWordInfoList internally
#
# Since 2.5
##
{ 'struct': 'DummyForceArrays',
'data': { 'unused': ['X86CPUFeatureWordInfo'] } }
##
# @RxState:
#

View File

@ -54,7 +54,6 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor):
self._jsons = []
self._used_types = []
self._name_map = {}
return QAPISchemaType # don't visit types for now
def visit_end(self):
# visit the types that are actually used
@ -82,6 +81,10 @@ const char %(c_name)s[] = %(c_string)s;
self._used_types = None
self._name_map = None
def visit_needed(self, entity):
# Ignore types on first pass; visit_end() will pick up used types
return not isinstance(entity, QAPISchemaType)
def _name(self, name):
if self._unmask:
return name

View File

@ -233,6 +233,11 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
self.decl = self._btin + self.decl
self._btin = None
def visit_needed(self, entity):
# Visit everything except implicit objects
return not (entity.is_implicit() and
isinstance(entity, QAPISchemaObjectType))
def _gen_type_cleanup(self, name):
self.decl += gen_type_cleanup_decl(name)
self.defn += gen_type_cleanup(name)
@ -254,14 +259,13 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
self._gen_type_cleanup(name)
def visit_object_type(self, name, info, base, members, variants):
if info:
self._fwdecl += gen_fwd_object_or_array(name)
if variants:
assert not members # not implemented
self.decl += gen_union(name, base, variants)
else:
self.decl += gen_struct(name, base, members)
self._gen_type_cleanup(name)
self._fwdecl += gen_fwd_object_or_array(name)
if variants:
assert not members # not implemented
self.decl += gen_union(name, base, variants)
else:
self.decl += gen_struct(name, base, members)
self._gen_type_cleanup(name)
def visit_alternate_type(self, name, info, variants):
self._fwdecl += gen_fwd_object_or_array(name)

View File

@ -301,7 +301,9 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error
out_obj:
error_propagate(errp, err);
err = NULL;
visit_end_union(v, !!(*obj)->data, &err);
if (*obj) {
visit_end_union(v, !!(*obj)->data, &err);
}
error_propagate(errp, err);
err = NULL;
visit_end_struct(v, &err);
@ -333,6 +335,11 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
self.decl = self._btin + self.decl
self._btin = None
def visit_needed(self, entity):
# Visit everything except implicit objects
return not (entity.is_implicit() and
isinstance(entity, QAPISchemaObjectType))
def visit_enum_type(self, name, info, values, prefix):
self.decl += gen_visit_decl(name, scalar=True)
self.defn += gen_visit_enum(name)
@ -349,13 +356,12 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
self.defn += defn
def visit_object_type(self, name, info, base, members, variants):
if info:
self.decl += gen_visit_decl(name)
if variants:
assert not members # not implemented
self.defn += gen_visit_union(name, base, variants)
else:
self.defn += gen_visit_struct(name, base, members)
self.decl += gen_visit_decl(name)
if variants:
assert not members # not implemented
self.defn += gen_visit_union(name, base, variants)
else:
self.defn += gen_visit_struct(name, base, members)
def visit_alternate_type(self, name, info, variants):
self.decl += gen_visit_decl(name)

View File

@ -56,9 +56,6 @@ returns_whitelist = [
'guest-set-vcpus',
'guest-sync',
'guest-sync-delimited',
# From qapi-schema-test:
'user_def_cmd3',
]
enum_types = []
@ -103,6 +100,7 @@ class QAPISchemaError(Exception):
class QAPIExprError(Exception):
def __init__(self, expr_info, msg):
Exception.__init__(self)
assert expr_info
self.info = expr_info
self.msg = msg
@ -792,6 +790,11 @@ class QAPISchemaEntity(object):
def __init__(self, name, info):
assert isinstance(name, str)
self.name = name
# For explicitly defined entities, info points to the (explicit)
# definition. For builtins (and their arrays), info is None.
# For implicitly defined entities, info points to a place that
# triggered the implicit definition (there may be more than one
# such place).
self.info = info
def c_name(self):
@ -800,6 +803,9 @@ class QAPISchemaEntity(object):
def check(self, schema):
pass
def is_implicit(self):
return not self.info
def visit(self, visitor):
pass
@ -811,6 +817,10 @@ class QAPISchemaVisitor(object):
def visit_end(self):
pass
def visit_needed(self, entity):
# Default to visiting everything
return True
def visit_builtin_type(self, name, info, json_type):
pass
@ -898,6 +908,10 @@ class QAPISchemaEnumType(QAPISchemaType):
def check(self, schema):
assert len(set(self.values)) == len(self.values)
def is_implicit(self):
# See QAPISchema._make_implicit_enum_type()
return self.name[-4:] == 'Kind'
def c_type(self, is_param=False):
return c_name(self.name)
@ -924,6 +938,9 @@ class QAPISchemaArrayType(QAPISchemaType):
self.element_type = schema.lookup_type(self._element_type_name)
assert self.element_type
def is_implicit(self):
return True
def json_type(self):
return 'array'
@ -960,6 +977,7 @@ class QAPISchemaObjectType(QAPISchemaType):
members = []
seen = {}
for m in members:
assert c_name(m.name) not in seen
seen[m.name] = m
for m in self.local_members:
m.check(schema, members, seen)
@ -967,12 +985,16 @@ class QAPISchemaObjectType(QAPISchemaType):
self.variants.check(schema, members, seen)
self.members = members
def is_implicit(self):
# See QAPISchema._make_implicit_object_type()
return self.name[0] == ':'
def c_name(self):
assert self.info
assert not self.is_implicit()
return QAPISchemaType.c_name(self)
def c_type(self, is_param=False):
assert self.info
assert not self.is_implicit()
return QAPISchemaType.c_type(self)
def json_type(self):
@ -1004,18 +1026,18 @@ class QAPISchemaObjectTypeMember(object):
class QAPISchemaObjectTypeVariants(object):
def __init__(self, tag_name, tag_enum, variants):
assert tag_name is None or isinstance(tag_name, str)
assert tag_enum is None or isinstance(tag_enum, str)
def __init__(self, tag_name, tag_member, variants):
# Flat unions pass tag_name but not tag_member.
# Simple unions and alternates pass tag_member but not tag_name.
# After check(), tag_member is always set, and tag_name remains
# a reliable witness of being used by a flat union.
assert bool(tag_member) != bool(tag_name)
assert (isinstance(tag_name, str) or
isinstance(tag_member, QAPISchemaObjectTypeMember))
for v in variants:
assert isinstance(v, QAPISchemaObjectTypeVariant)
self.tag_name = tag_name
if tag_name:
assert not tag_enum
self.tag_member = None
else:
self.tag_member = QAPISchemaObjectTypeMember('type', tag_enum,
False)
self.tag_member = tag_member
self.variants = variants
def check(self, schema, members, seen):
@ -1040,7 +1062,8 @@ class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
# This function exists to support ugly simple union special cases
# TODO get rid of them, and drop the function
def simple_union_type(self):
if isinstance(self.type, QAPISchemaObjectType) and not self.type.info:
if (self.type.is_implicit() and
isinstance(self.type, QAPISchemaObjectType)):
assert len(self.type.members) == 1
assert not self.type.variants
return self.type.members[0].type
@ -1112,15 +1135,19 @@ class QAPISchema(object):
def __init__(self, fname):
try:
self.exprs = check_exprs(QAPISchemaParser(open(fname, "r")).exprs)
self._entity_dict = {}
self._predefining = True
self._def_predefineds()
self._predefining = False
self._def_exprs()
self.check()
except (QAPISchemaError, QAPIExprError), err:
print >>sys.stderr, err
exit(1)
self._entity_dict = {}
self._def_predefineds()
self._def_exprs()
self.check()
def _def_entity(self, ent):
# Only the predefined types are allowed to not have info
assert ent.info or self._predefining
assert ent.name not in self._entity_dict
self._entity_dict[ent.name] = ent
@ -1136,7 +1163,12 @@ class QAPISchema(object):
def _def_builtin_type(self, name, json_type, c_type, c_null):
self._def_entity(QAPISchemaBuiltinType(name, json_type,
c_type, c_null))
self._make_array_type(name) # TODO really needed?
# TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
# qapi-types.h from a single .c, all arrays of builtins must be
# declared in the first file whether or not they are used. Nicer
# would be to use lazy instantiation, while figuring out how to
# avoid compilation issues with multiple qapi-types.h.
self._make_array_type(name, None)
def _def_predefineds(self):
for t in [('str', 'string', 'char' + pointer_suffix, 'NULL'),
@ -1158,23 +1190,25 @@ class QAPISchema(object):
[], None)
self._def_entity(self.the_empty_object_type)
def _make_implicit_enum_type(self, name, values):
name = name + 'Kind'
self._def_entity(QAPISchemaEnumType(name, None, values, None))
def _make_implicit_enum_type(self, name, info, values):
name = name + 'Kind' # Use namespace reserved by add_name()
self._def_entity(QAPISchemaEnumType(name, info, values, None))
return name
def _make_array_type(self, element_type):
def _make_array_type(self, element_type, info):
# TODO fooList namespace is not reserved; user can create collisions,
# or abuse our type system with ['fooList'] for 2D array
name = element_type + 'List'
if not self.lookup_type(name):
self._def_entity(QAPISchemaArrayType(name, None, element_type))
self._def_entity(QAPISchemaArrayType(name, info, element_type))
return name
def _make_implicit_object_type(self, name, role, members):
def _make_implicit_object_type(self, name, info, role, members):
if not members:
return None
name = ':obj-%s-%s' % (name, role)
if not self.lookup_entity(name, QAPISchemaObjectType):
self._def_entity(QAPISchemaObjectType(name, None, None,
self._def_entity(QAPISchemaObjectType(name, info, None,
members, None))
return name
@ -1183,20 +1217,19 @@ class QAPISchema(object):
data = expr['data']
prefix = expr.get('prefix')
self._def_entity(QAPISchemaEnumType(name, info, data, prefix))
self._make_array_type(name) # TODO really needed?
def _make_member(self, name, typ):
def _make_member(self, name, typ, info):
optional = False
if name.startswith('*'):
name = name[1:]
optional = True
if isinstance(typ, list):
assert len(typ) == 1
typ = self._make_array_type(typ[0])
typ = self._make_array_type(typ[0], info)
return QAPISchemaObjectTypeMember(name, typ, optional)
def _make_members(self, data):
return [self._make_member(key, value)
def _make_members(self, data, info):
return [self._make_member(key, value, info)
for (key, value) in data.iteritems()]
def _def_struct_type(self, expr, info):
@ -1204,58 +1237,56 @@ class QAPISchema(object):
base = expr.get('base')
data = expr['data']
self._def_entity(QAPISchemaObjectType(name, info, base,
self._make_members(data),
self._make_members(data, info),
None))
self._make_array_type(name) # TODO really needed?
def _make_variant(self, case, typ):
return QAPISchemaObjectTypeVariant(case, typ)
def _make_simple_variant(self, case, typ):
def _make_simple_variant(self, case, typ, info):
if isinstance(typ, list):
assert len(typ) == 1
typ = self._make_array_type(typ[0])
typ = self._make_implicit_object_type(typ, 'wrapper',
[self._make_member('data', typ)])
typ = self._make_array_type(typ[0], info)
typ = self._make_implicit_object_type(
typ, info, 'wrapper', [self._make_member('data', typ, info)])
return QAPISchemaObjectTypeVariant(case, typ)
def _make_tag_enum(self, type_name, variants):
return self._make_implicit_enum_type(type_name,
[v.name for v in variants])
def _make_implicit_tag(self, type_name, info, variants):
typ = self._make_implicit_enum_type(type_name, info,
[v.name for v in variants])
return QAPISchemaObjectTypeMember('type', typ, False)
def _def_union_type(self, expr, info):
name = expr['union']
data = expr['data']
base = expr.get('base')
tag_name = expr.get('discriminator')
tag_enum = None
tag_member = None
if tag_name:
variants = [self._make_variant(key, value)
for (key, value) in data.iteritems()]
else:
variants = [self._make_simple_variant(key, value)
variants = [self._make_simple_variant(key, value, info)
for (key, value) in data.iteritems()]
tag_enum = self._make_tag_enum(name, variants)
tag_member = self._make_implicit_tag(name, info, variants)
self._def_entity(
QAPISchemaObjectType(name, info, base,
self._make_members(OrderedDict()),
self._make_members(OrderedDict(), info),
QAPISchemaObjectTypeVariants(tag_name,
tag_enum,
tag_member,
variants)))
self._make_array_type(name) # TODO really needed?
def _def_alternate_type(self, expr, info):
name = expr['alternate']
data = expr['data']
variants = [self._make_variant(key, value)
for (key, value) in data.iteritems()]
tag_enum = self._make_tag_enum(name, variants)
tag_member = self._make_implicit_tag(name, info, variants)
self._def_entity(
QAPISchemaAlternateType(name, info,
QAPISchemaObjectTypeVariants(None,
tag_enum,
tag_member,
variants)))
self._make_array_type(name) # TODO really needed?
def _def_command(self, expr, info):
name = expr['command']
@ -1264,11 +1295,11 @@ class QAPISchema(object):
gen = expr.get('gen', True)
success_response = expr.get('success-response', True)
if isinstance(data, OrderedDict):
data = self._make_implicit_object_type(name, 'arg',
self._make_members(data))
data = self._make_implicit_object_type(
name, info, 'arg', self._make_members(data, info))
if isinstance(rets, list):
assert len(rets) == 1
rets = self._make_array_type(rets[0])
rets = self._make_array_type(rets[0], info)
self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
success_response))
@ -1276,8 +1307,8 @@ class QAPISchema(object):
name = expr['event']
data = expr.get('data')
if isinstance(data, OrderedDict):
data = self._make_implicit_object_type(name, 'arg',
self._make_members(data))
data = self._make_implicit_object_type(
name, info, 'arg', self._make_members(data, info))
self._def_entity(QAPISchemaEvent(name, info, data))
def _def_exprs(self):
@ -1304,10 +1335,10 @@ class QAPISchema(object):
ent.check(self)
def visit(self, visitor):
ignore = visitor.visit_begin(self)
for name in sorted(self._entity_dict.keys()):
if not ignore or not isinstance(self._entity_dict[name], ignore):
self._entity_dict[name].visit(visitor)
visitor.visit_begin(self)
for (name, entity) in sorted(self._entity_dict.items()):
if visitor.visit_needed(entity):
entity.visit(visitor)
visitor.visit_end()

View File

@ -230,7 +230,6 @@ qapi-schema += alternate-clash.json
qapi-schema += alternate-conflict-dict.json
qapi-schema += alternate-conflict-string.json
qapi-schema += alternate-empty.json
qapi-schema += alternate-good.json
qapi-schema += alternate-nested.json
qapi-schema += alternate-unknown.json
qapi-schema += args-alternate.json
@ -240,7 +239,6 @@ qapi-schema += args-array-unknown.json
qapi-schema += args-int.json
qapi-schema += args-invalid.json
qapi-schema += args-member-array-bad.json
qapi-schema += args-member-array.json
qapi-schema += args-member-unknown.json
qapi-schema += args-name-clash.json
qapi-schema += args-union.json
@ -261,7 +259,6 @@ qapi-schema += enum-bad-name.json
qapi-schema += enum-bad-prefix.json
qapi-schema += enum-clash-member.json
qapi-schema += enum-dict-member.json
qapi-schema += enum-empty.json
qapi-schema += enum-int-member.json
qapi-schema += enum-max-member.json
qapi-schema += enum-missing-data.json
@ -288,7 +285,6 @@ qapi-schema += flat-union-invalid-branch-key.json
qapi-schema += flat-union-invalid-discriminator.json
qapi-schema += flat-union-no-base.json
qapi-schema += flat-union-optional-discriminator.json
qapi-schema += flat-union-reverse-define.json
qapi-schema += flat-union-string-discriminator.json
qapi-schema += funny-char.json
qapi-schema += ident-with-escape.json
@ -320,7 +316,6 @@ qapi-schema += redefined-type.json
qapi-schema += returns-alternate.json
qapi-schema += returns-array-bad.json
qapi-schema += returns-dict.json
qapi-schema += returns-int.json
qapi-schema += returns-unknown.json
qapi-schema += returns-whitelist.json
qapi-schema += struct-base-clash-base.json

View File

@ -1 +0,0 @@
0

View File

@ -1,9 +0,0 @@
# Working example of alternate
{ 'struct': 'Data',
'data': { '*number': 'int', '*name': 'str' } }
{ 'enum': 'Enum',
'data': [ 'hello', 'world' ] }
{ 'alternate': 'Alt',
'data': { 'value': 'int',
'string': 'Enum',
'struct': 'Data' } }

View File

@ -1,10 +0,0 @@
object :empty
alternate Alt
case value: int
case string: Enum
case struct: Data
enum AltKind ['value', 'string', 'struct']
object Data
member number: int optional=True
member name: str optional=True
enum Enum ['hello', 'world']

View File

@ -1 +0,0 @@
0

View File

@ -1,4 +0,0 @@
# valid array members
{ 'enum': 'abc', 'data': [ 'a', 'b', 'c' ] }
{ 'struct': 'def', 'data': { 'array': [ 'abc' ] } }
{ 'command': 'okay', 'data': { 'member1': [ 'int' ], 'member2': [ 'def' ] } }

View File

@ -1,9 +0,0 @@
object :empty
object :obj-okay-arg
member member1: intList optional=False
member member2: defList optional=False
enum abc ['a', 'b', 'c']
object def
member array: abcList optional=False
command okay :obj-okay-arg -> None
gen=True success_response=True

View File

@ -1 +0,0 @@
0

View File

@ -1,2 +0,0 @@
# An empty enum, although unusual, is currently acceptable
{ 'enum': 'MyEnum', 'data': [ ] }

View File

@ -1,2 +0,0 @@
object :empty
enum MyEnum []

View File

@ -1,17 +0,0 @@
{ 'union': 'TestUnion',
'base': 'TestBase',
'discriminator': 'enum1',
'data': { 'value1': 'TestTypeA',
'value2': 'TestTypeB' } }
{ 'struct': 'TestBase',
'data': { 'enum1': 'TestEnum' } }
{ 'enum': 'TestEnum',
'data': [ 'value1', 'value2' ] }
{ 'struct': 'TestTypeA',
'data': { 'string': 'str' } }
{ 'struct': 'TestTypeB',
'data': { 'integer': 'int' } }

View File

@ -1,13 +0,0 @@
object :empty
object TestBase
member enum1: TestEnum optional=False
enum TestEnum ['value1', 'value2']
object TestTypeA
member string: str optional=False
object TestTypeB
member integer: int optional=False
object TestUnion
base TestBase
tag enum1
case value1: TestTypeA
case value2: TestTypeB

View File

@ -1,10 +1,15 @@
# *-*- Mode: Python -*-*
# This file is a stress test of supported qapi constructs that must
# parse and compile correctly.
# for testing enums
{ 'enum': 'EnumOne',
'data': [ 'value1', 'value2', 'value3' ] }
{ 'struct': 'NestedEnumsOne',
'data': { 'enum1': 'EnumOne', '*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } }
'data': { 'enum1': 'EnumOne', # Intentional forward reference
'*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } }
# An empty enum, although unusual, is currently acceptable
{ 'enum': 'MyEnum', 'data': [ ] }
# for testing override of default naming heuristic
{ 'enum': 'QEnumTwo',
@ -14,7 +19,11 @@
# for testing nested structs
{ 'struct': 'UserDefOne',
'base': 'UserDefZero', # intentional forward reference
'data': { 'string': 'str', '*enum1': 'EnumOne' } }
'data': { 'string': 'str',
'*enum1': 'EnumOne' } } # intentional forward reference
{ 'enum': 'EnumOne',
'data': [ 'value1', 'value2', 'value3' ] }
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
@ -31,6 +40,10 @@
'data': { 'string0': 'str',
'dict1': 'UserDefTwoDict' } }
# dummy struct to force generation of array types not otherwise mentioned
{ 'struct': 'ForceArrays',
'data': { 'unused1':['UserDefOne'], 'unused2':['UserDefTwo'] } }
# for testing unions
# Among other things, test that a name collision between branches does
# not cause any problems (since only one branch can be in use at a time),
@ -98,9 +111,10 @@
{ 'command': 'user_def_cmd2',
'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'},
'returns': 'UserDefTwo' }
{ 'command': 'user_def_cmd3', 'data': {'a': 'int', '*b': 'int' },
# Returning a non-dictionary requires a name from the whitelist
{ 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' },
'returns': 'int' }
# note: command name 'guest-sync' chosen to avoid "cannot use built-in" error
{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
# For testing integer range flattening in opts-visitor. The following schema

View File

@ -17,6 +17,9 @@ object :obj-anyList-wrapper
member data: anyList optional=False
object :obj-boolList-wrapper
member data: boolList optional=False
object :obj-guest-get-time-arg
member a: int optional=False
member b: int optional=True
object :obj-guest-sync-arg
member arg: any optional=False
object :obj-int16List-wrapper
@ -50,9 +53,6 @@ object :obj-user_def_cmd1-arg
object :obj-user_def_cmd2-arg
member ud1a: UserDefOne optional=False
member ud1b: UserDefOne optional=True
object :obj-user_def_cmd3-arg
member a: int optional=False
member b: int optional=True
alternate AltIntNum
case i: int
case n: number
@ -86,6 +86,10 @@ object EventStructOne
member struct1: UserDefOne optional=False
member string: str optional=False
member enum2: EnumOne optional=True
object ForceArrays
member unused1: UserDefOneList optional=False
member unused2: UserDefTwoList optional=False
enum MyEnum []
object NestedEnumsOne
member enum1: EnumOne optional=False
member enum2: EnumOne optional=True
@ -183,6 +187,8 @@ object __org.qemu_x-Union2
case __org.qemu_x-value: __org.qemu_x-Struct2
command __org.qemu_x-command :obj-__org.qemu_x-command-arg -> __org.qemu_x-Union1
gen=True success_response=True
command guest-get-time :obj-guest-get-time-arg -> int
gen=True success_response=True
command guest-sync :obj-guest-sync-arg -> any
gen=True success_response=True
command user_def_cmd None -> None
@ -191,5 +197,3 @@ command user_def_cmd1 :obj-user_def_cmd1-arg -> None
gen=True success_response=True
command user_def_cmd2 :obj-user_def_cmd2-arg -> UserDefTwo
gen=True success_response=True
command user_def_cmd3 :obj-user_def_cmd3-arg -> int
gen=True success_response=True

View File

@ -1 +0,0 @@
0

View File

@ -1,3 +0,0 @@
# It is okay (although not extensible) to return a non-dictionary
# But to make it work, the name must be in a whitelist
{ 'command': 'guest-get-time', 'returns': 'int' }

View File

@ -1,3 +0,0 @@
object :empty
command guest-get-time None -> int
gen=True success_response=True

View File

@ -46,7 +46,7 @@ UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
return ret;
}
int64_t qmp_user_def_cmd3(int64_t a, bool has_b, int64_t b, Error **errp)
int64_t qmp_guest_get_time(int64_t a, bool has_b, int64_t b, Error **errp)
{
return a + (has_b ? b : 0);
}
@ -160,7 +160,7 @@ static void test_dispatch_cmd_io(void)
qdict_put(args3, "a", qint_from_int(66));
qdict_put(req, "arguments", args3);
qdict_put(req, "execute", qstring_from_str("user_def_cmd3"));
qdict_put(req, "execute", qstring_from_str("guest-get-time"));
ret3 = qobject_to_qint(test_qmp_dispatch(req));
assert(qint_get_int(ret3) == 66);