[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v6 38/36] qapi: Check for member name conflicts with
From: |
Eric Blake |
Subject: |
[Qemu-devel] [PATCH v6 38/36] qapi: Check for member name conflicts with a base class |
Date: |
Fri, 10 Apr 2015 14:28:21 -0600 |
Our type inheritance for both 'struct' and for flat 'union' merges
key/value pairs from the base class with those from the type in
question. Although the C code currently boxes things so that there
is a distinction between which member is referred to, the QMP wire
format does not allow passing a key more than once in a single
object. Besides, if we ever change the generated C code to not be
quite so boxy, we'd want to avoid duplicate member names there,
too.
Fix a testsuite entry added in an earlier patch, as well as adding
a couple more tests to ensure we have appropriate coverage.
Signed-off-by: Eric Blake <address@hidden>
---
v6: new patch
---
scripts/qapi.py | 21 ++++++++++++++++++++-
tests/Makefile | 3 ++-
tests/qapi-schema/flat-union-branch-clash.err | 1 +
tests/qapi-schema/flat-union-branch-clash.exit | 2 +-
tests/qapi-schema/flat-union-branch-clash.json | 2 +-
tests/qapi-schema/flat-union-branch-clash.out | 9 ---------
tests/qapi-schema/struct-base-clash-deep.err | 1 +
tests/qapi-schema/struct-base-clash-deep.exit | 1 +
tests/qapi-schema/struct-base-clash-deep.json | 9 +++++++++
tests/qapi-schema/struct-base-clash-deep.out | 0
tests/qapi-schema/struct-base-clash.err | 1 +
tests/qapi-schema/struct-base-clash.exit | 1 +
tests/qapi-schema/struct-base-clash.json | 6 ++++++
tests/qapi-schema/struct-base-clash.out | 0
14 files changed, 44 insertions(+), 13 deletions(-)
create mode 100644 tests/qapi-schema/struct-base-clash-deep.err
create mode 100644 tests/qapi-schema/struct-base-clash-deep.exit
create mode 100644 tests/qapi-schema/struct-base-clash-deep.json
create mode 100644 tests/qapi-schema/struct-base-clash-deep.out
create mode 100644 tests/qapi-schema/struct-base-clash.err
create mode 100644 tests/qapi-schema/struct-base-clash.exit
create mode 100644 tests/qapi-schema/struct-base-clash.json
create mode 100644 tests/qapi-schema/struct-base-clash.out
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 853f9a3..281e762 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -429,6 +429,18 @@ def check_type(expr_info, source, value, allow_array =
False,
allow_metas=['built-in', 'union', 'alternate', 'struct',
'enum'])
+def check_member_clash(expr_info, base_name, data, source = ""):
+ base = find_struct(base_name)
+ assert base
+ base_members = base['data']
+ for key in data.keys():
+ if key in base_members:
+ raise QAPIExprError(expr_info,
+ "Member name '%s'%s clashes with base '%s'"
+ %(key, source, base_name))
+ if base.get('base'):
+ check_member_clash(expr_info, base['base'], data, source)
+
def check_command(expr, expr_info):
name = expr['command']
allow_star = expr.has_key('gen')
@@ -518,9 +530,14 @@ def check_union(expr, expr_info):
check_name(expr_info, "Member of union '%s'" % name, key)
# Each value must name a known type; futhermore, in flat unions,
- # branches must be a struct
+ # branches must be a struct with no overlapping member names
check_type(expr_info, "Member '%s' of union '%s'" % (key, name),
value, allow_array=True, allow_metas=allow_metas)
+ if base:
+ branch_struct = find_struct(value)
+ assert branch_struct
+ check_member_clash(expr_info, expr['base'], branch_struct['data'],
+ " of branch '%s'" %key)
# If the discriminator names an enum type, then all members
# of 'data' must also be members of the enum type.
@@ -597,6 +614,8 @@ def check_struct(expr, expr_info):
allow_dict=True, allow_optional=True)
check_type(expr_info, "'base' for type '%s'" % name, expr.get('base'),
allow_metas=['struct'])
+ if expr.get('base'):
+ check_member_clash(expr_info, expr['base'], expr['data'])
def check_exprs(schema):
for expr_elem in schema.exprs:
diff --git a/tests/Makefile b/tests/Makefile
index 0cd114f..eb5655e 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -242,7 +242,8 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
include-simple.json include-relpath.json include-format-err.json \
include-non-file.json include-no-file.json include-before-err.json \
include-nested-err.json include-self-cycle.json include-cycle.json \
- include-repetition.json event-nest-struct.json event-case.json)
+ include-repetition.json event-nest-struct.json event-case.json \
+ struct-base-clash.json struct-base-clash-deep.json )
GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h \
tests/test-qmp-commands.h tests/test-qapi-event.h
diff --git a/tests/qapi-schema/flat-union-branch-clash.err
b/tests/qapi-schema/flat-union-branch-clash.err
index e69de29..f112766 100644
--- a/tests/qapi-schema/flat-union-branch-clash.err
+++ b/tests/qapi-schema/flat-union-branch-clash.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-branch-clash.json:10: Member name 'name' of
branch 'value1' clashes with base 'Base'
diff --git a/tests/qapi-schema/flat-union-branch-clash.exit
b/tests/qapi-schema/flat-union-branch-clash.exit
index 573541a..d00491f 100644
--- a/tests/qapi-schema/flat-union-branch-clash.exit
+++ b/tests/qapi-schema/flat-union-branch-clash.exit
@@ -1 +1 @@
-0
+1
diff --git a/tests/qapi-schema/flat-union-branch-clash.json
b/tests/qapi-schema/flat-union-branch-clash.json
index 8b0b807..b3c6ffe 100644
--- a/tests/qapi-schema/flat-union-branch-clash.json
+++ b/tests/qapi-schema/flat-union-branch-clash.json
@@ -1,4 +1,4 @@
-# FIXME: we should check for no duplicate keys between branches and base
+# we check for no duplicate keys between branches and base
{ 'enum': 'TestEnum',
'data': [ 'value1', 'value2' ] }
{ 'struct': 'Base',
diff --git a/tests/qapi-schema/flat-union-branch-clash.out
b/tests/qapi-schema/flat-union-branch-clash.out
index 04c2395..e69de29 100644
--- a/tests/qapi-schema/flat-union-branch-clash.out
+++ b/tests/qapi-schema/flat-union-branch-clash.out
@@ -1,9 +0,0 @@
-[OrderedDict([('enum', 'TestEnum'), ('data', ['value1', 'value2'])]),
- OrderedDict([('struct', 'Base'), ('data', OrderedDict([('enum1', 'TestEnum'),
('name', 'str')]))]),
- OrderedDict([('struct', 'Branch1'), ('data', OrderedDict([('name',
'str')]))]),
- OrderedDict([('struct', 'Branch2'), ('data', OrderedDict([('value',
'int')]))]),
- OrderedDict([('union', 'TestUnion'), ('base', 'Base'), ('discriminator',
'enum1'), ('data', OrderedDict([('value1', 'Branch1'), ('value2',
'Branch2')]))])]
-[{'enum_name': 'TestEnum', 'enum_values': ['value1', 'value2']}]
-[OrderedDict([('struct', 'Base'), ('data', OrderedDict([('enum1', 'TestEnum'),
('name', 'str')]))]),
- OrderedDict([('struct', 'Branch1'), ('data', OrderedDict([('name',
'str')]))]),
- OrderedDict([('struct', 'Branch2'), ('data', OrderedDict([('value',
'int')]))])]
diff --git a/tests/qapi-schema/struct-base-clash-deep.err
b/tests/qapi-schema/struct-base-clash-deep.err
new file mode 100644
index 0000000..e3e9f8d
--- /dev/null
+++ b/tests/qapi-schema/struct-base-clash-deep.err
@@ -0,0 +1 @@
+tests/qapi-schema/struct-base-clash-deep.json:7: Member name 'name' clashes
with base 'Base'
diff --git a/tests/qapi-schema/struct-base-clash-deep.exit
b/tests/qapi-schema/struct-base-clash-deep.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/struct-base-clash-deep.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/struct-base-clash-deep.json
b/tests/qapi-schema/struct-base-clash-deep.json
new file mode 100644
index 0000000..08c8c9c
--- /dev/null
+++ b/tests/qapi-schema/struct-base-clash-deep.json
@@ -0,0 +1,9 @@
+# we check for no duplicate keys with indirect base
+{ 'struct': 'Base',
+ 'data': { 'name': 'str' } }
+{ 'struct': 'Mid',
+ 'base': 'Base',
+ 'data': { 'value': 'int' } }
+{ 'struct': 'Sub',
+ 'base': 'Mid',
+ 'data': { 'name': 'str' } }
diff --git a/tests/qapi-schema/struct-base-clash-deep.out
b/tests/qapi-schema/struct-base-clash-deep.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/struct-base-clash.err
b/tests/qapi-schema/struct-base-clash.err
new file mode 100644
index 0000000..3ac37fb
--- /dev/null
+++ b/tests/qapi-schema/struct-base-clash.err
@@ -0,0 +1 @@
+tests/qapi-schema/struct-base-clash.json:4: Member name 'name' clashes with
base 'Base'
diff --git a/tests/qapi-schema/struct-base-clash.exit
b/tests/qapi-schema/struct-base-clash.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/struct-base-clash.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/struct-base-clash.json
b/tests/qapi-schema/struct-base-clash.json
new file mode 100644
index 0000000..f2afc9b
--- /dev/null
+++ b/tests/qapi-schema/struct-base-clash.json
@@ -0,0 +1,6 @@
+# we check for no duplicate keys with base
+{ 'struct': 'Base',
+ 'data': { 'name': 'str' } }
+{ 'struct': 'Sub',
+ 'base': 'Base',
+ 'data': { 'name': 'str' } }
diff --git a/tests/qapi-schema/struct-base-clash.out
b/tests/qapi-schema/struct-base-clash.out
new file mode 100644
index 0000000..e69de29
--
2.1.0
- [Qemu-devel] [PATCH v6 33/36] qapi: Drop inline nested struct in query-version, (continued)
- [Qemu-devel] [PATCH v6 33/36] qapi: Drop inline nested struct in query-version, Eric Blake, 2015/04/05
- [Qemu-devel] [PATCH v6 35/36] qapi: Drop support for inline nested types, Eric Blake, 2015/04/05
- [Qemu-devel] [PATCH v6 36/36] qapi: Tweak doc references to QMP when QGA is also meant, Eric Blake, 2015/04/05
- [Qemu-devel] [PATCH v6 32/36] qapi: Drop tests for inline nested structs, Eric Blake, 2015/04/05
- [Qemu-devel] [PATCH v6 30/36] qapi: Use 'struct' instead of 'type' in schema, Eric Blake, 2015/04/05
- Re: [Qemu-devel] [PATCH v6 00/36] drop qapi nested structs, Eric Blake, 2015/04/06
- [Qemu-devel] [PATCH v6 38/36] qapi: Check for member name conflicts with a base class,
Eric Blake <=
- [Qemu-devel] [PATCH v6 37/36] qapi: Support (subset of) \u escapes in strings, Eric Blake, 2015/04/10
- Re: [Qemu-devel] [PATCH v6 00/36] drop qapi nested structs, Markus Armbruster, 2015/04/28