QAPI patches patches for 2021-09-25

-----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmFRvKcSHGFybWJydUBy
 ZWRoYXQuY29tAAoJEDhwtADrkYZTSRIQAJcuW3eCoQ3moFa8e/nDoWnkW75eSfO4
 4T3EuW5Y9ODzfShtagKEeCX0oWAVDJM+vfbLNYk+e12kPiDVUmmiMw1urWmFI658
 la4KgKnV55BJ1xCvl58F1WAfQ7UMIFDEMksq61qZUOnYwj3JEKhqkn7ztUC+HaGi
 uMR2EzTa89+RzDavSXpGfONAnV5pzKtEh5WnkSM+dIRD4HjsaYDa77j1d5D5TGIR
 hiD/YT/QFo0eSF0sFyIbuRrPfMkUiqymaEFBS7OB5vOM4nSPrjoEpTWCOFVdD78D
 iruN90xvQFAj8mD5N3GZsq5jcv2JLVExNPs23qNNXzHgOmGWdCWZ8RC857bLJpl3
 ToF2SYQqQiv/pdXnOg9ODaEUuepyGxWsr98H2zCKYi19lTamZFr6KZO80UgoTFMi
 2FfBJTM0z0uR1aFNl0BcR/qRZlCuPWTrjwdHqXjtzgs6y0Ycfvy1EDmwkndS43uk
 NH3IEScsf5pL8I2YYSIROfcrhNKO/KHMeWtXZFEVLVHCRi4waOb523lFEqm3YgYl
 Wsa8VgxWt7XoXqp3/nQhvg/OmMw5eZuFgEgQEN7h9gvJHbXQqy/Du40UVuTVxDiH
 InjDe3A24BiIBf2mA/b8wEwd2u/bTWcl2vysq0nXB0oipfnnksjafvLkOTP+ebTs
 LQ3u2NyptUTz
 =ApRW
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2021-09-25-v2' into staging

QAPI patches patches for 2021-09-25

# gpg: Signature made Mon 27 Sep 2021 13:44:23 BST
# gpg:                using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653
# gpg:                issuer "armbru@redhat.com"
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full]
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>" [full]
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867  4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-qapi-2021-09-25-v2: (25 commits)
  tests/qapi-schema: Make test-qapi.py -u work when files are absent
  tests/qapi-schema: Use Python OSError instead of outmoded IOError
  test-clone-visitor: Correct an accidental rename
  tests/qapi-schema: Rename flat-union-* test cases to union-*
  qapi: Drop simple unions
  tests/qapi-schema: Purge simple unions from tests
  tests/qapi-schema: Drop simple union __org.qemu_x-Union1
  test-clone-visitor: Wean off __org.qemu_x-Union1
  tests/qapi-schema: Rewrite simple union TestIfUnion to be flat
  tests/qapi-schema: Simple union UserDefListUnion is now unused, drop
  tests/qapi-schema: Wean off UserDefListUnion
  test-clone-visitor: Wean off UserDefListUnion
  test-qobject-output-visitor: Wean off UserDefListUnion
  test-qobject-input-visitor: Wean off UserDefListUnion
  tests/qapi-schema: Prepare for simple union UserDefListUnion removal
  qapi: Convert simple union TransactionAction to flat one
  qapi: Convert simple union ImageInfoSpecific to flat one
  qapi: Convert simple union SocketAddressLegacy to flat one
  qapi: Convert simple union ChardevBackend to flat one
  qapi: Convert simple union MemoryDeviceInfo to flat one
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-09-27 15:03:42 +01:00
commit de8ed1055c
118 changed files with 1038 additions and 1228 deletions

View file

@ -623,7 +623,7 @@ static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
options->type = TPM_TYPE_OPTIONS_KIND_EMULATOR;
options->type = TPM_TYPE_EMULATOR;
options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu->options);
return options;

View file

@ -321,7 +321,7 @@ static TpmTypeOptions *tpm_passthrough_get_tpm_options(TPMBackend *tb)
{
TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
options->type = TPM_TYPE_PASSTHROUGH;
options->u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions,
TPM_PASSTHROUGH(tb)->options);

View file

@ -1520,7 +1520,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
addr = g_new0(SocketAddressLegacy, 1);
if (path) {
UnixSocketAddress *q_unix;
addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
addr->type = SOCKET_ADDRESS_TYPE_UNIX;
q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
q_unix->path = g_strdup(path);
#ifdef CONFIG_LINUX
@ -1530,7 +1530,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
q_unix->abstract = abstract;
#endif
} else if (host) {
addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
addr->type = SOCKET_ADDRESS_TYPE_INET;
addr->u.inet.data = g_new(InetSocketAddress, 1);
*addr->u.inet.data = (InetSocketAddress) {
.host = g_strdup(host),
@ -1543,7 +1543,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
.ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
};
} else if (fd) {
addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD;
addr->type = SOCKET_ADDRESS_TYPE_FD;
addr->u.fd.data = g_new(String, 1);
addr->u.fd.data->str = g_strdup(fd);
} else {

View file

@ -165,7 +165,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp));
addr = g_new0(SocketAddressLegacy, 1);
addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
addr->type = SOCKET_ADDRESS_TYPE_INET;
addr->u.inet.data = g_new(InetSocketAddress, 1);
*addr->u.inet.data = (InetSocketAddress) {
.host = g_strdup(host),
@ -180,7 +180,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
if (has_local) {
udp->has_local = true;
addr = g_new0(SocketAddressLegacy, 1);
addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
addr->type = SOCKET_ADDRESS_TYPE_INET;
addr->u.inet.data = g_new(InetSocketAddress, 1);
*addr->u.inet.data = (InetSocketAddress) {
.host = g_strdup(localaddr),

View file

@ -319,13 +319,9 @@ Union types
Syntax::
UNION = { 'union': STRING,
'data': BRANCHES,
'*if': COND,
'*features': FEATURES }
| { 'union': STRING,
'data': BRANCHES,
'base': ( MEMBERS | STRING ),
'discriminator': STRING,
'data': BRANCHES,
'*if': COND,
'*features': FEATURES }
BRANCHES = { BRANCH, ... }
@ -334,63 +330,30 @@ Syntax::
Member 'union' names the union type.
There are two flavors of union types: simple (no discriminator or
base), and flat (both discriminator and base).
Each BRANCH of the 'data' object defines a branch of the union. A
union must have at least one branch.
The BRANCH's STRING name is the branch name.
The BRANCH's value defines the branch's properties, in particular its
type. The form TYPE-REF_ is shorthand for :code:`{ 'type': TYPE-REF }`.
A simple union type defines a mapping from automatic discriminator
values to data types like in this example::
{ 'struct': 'BlockdevOptionsFile', 'data': { 'filename': 'str' } }
{ 'struct': 'BlockdevOptionsQcow2',
'data': { 'backing': 'str', '*lazy-refcounts': 'bool' } }
{ 'union': 'BlockdevOptionsSimple',
'data': { 'file': 'BlockdevOptionsFile',
'qcow2': 'BlockdevOptionsQcow2' } }
In the Client JSON Protocol, a simple union is represented by an
object that contains the 'type' member as a discriminator, and a
'data' member that is of the specified data type corresponding to the
discriminator value, as in these examples::
{ "type": "file", "data": { "filename": "/some/place/my-image" } }
{ "type": "qcow2", "data": { "backing": "/some/place/my-image",
"lazy-refcounts": true } }
The generated C code uses a struct containing a union. Additionally,
an implicit C enum 'NameKind' is created, corresponding to the union
'Name', for accessing the various branches of the union. The value
for each branch can be of any type.
Flat unions permit arbitrary common members that occur in all variants
of the union, not just a discriminator. Their discriminators need not
be named 'type'. They also avoid nesting on the wire.
The 'base' member defines the common members. If it is a MEMBERS_
object, it defines common members just like a struct type's 'data'
member defines struct type members. If it is a STRING, it names a
struct type whose members are the common members.
All flat union branches must be `Struct types`_.
Member 'discriminator' must name a non-optional enum-typed member of
the base struct. That member's value selects a branch by its name.
If no such branch exists, an empty branch is assumed.
In the Client JSON Protocol, a flat union is represented by an object
with the common members (from the base type) and the selected branch's
members. The two sets of member names must be disjoint. Member
'discriminator' must name a non-optional enum-typed member of the base
struct.
Each BRANCH of the 'data' object defines a branch of the union. A
union must have at least one branch.
The following example enhances the above simple union example by
adding an optional common member 'read-only', renaming the
discriminator to something more applicable than the simple union's
default of 'type', and reducing the number of ``{}`` required on the wire::
The BRANCH's STRING name is the branch name. It must be a value of
the discriminator enum type.
The BRANCH's value defines the branch's properties, in particular its
type. The type must a struct type. The form TYPE-REF_ is shorthand
for :code:`{ 'type': TYPE-REF }`.
In the Client JSON Protocol, a union is represented by an object with
the common members (from the base type) and the selected branch's
members. The two sets of member names must be disjoint.
Example::
{ 'enum': 'BlockdevDriver', 'data': [ 'file', 'qcow2' ] }
{ 'union': 'BlockdevOptions',
@ -406,30 +369,11 @@ Resulting in these JSON objects::
{ "driver": "qcow2", "read-only": false,
"backing": "/some/place/my-image", "lazy-refcounts": true }
Notice that in a flat union, the discriminator name is controlled by
the user, but because it must map to a base member with enum type, the
code generator ensures that branches match the existing values of the
enum. The order of branches need not match the order of the enum
values. The branches need not cover all possible enum values.
Omitted enum values are still valid branches that add no additional
members to the data type. In the resulting generated C data types, a
flat union is represented as a struct with the base members in QAPI
schema order, and then a union of structures for each branch of the
struct.
A simple union can always be re-written as a flat union where the base
class has a single member named 'type', and where each branch of the
union has a struct with a single member named 'data'. That is, ::
{ 'union': 'Simple', 'data': { 'one': 'str', 'two': 'int' } }
is identical on the wire to::
{ 'enum': 'Enum', 'data': ['one', 'two'] }
{ 'struct': 'Branch1', 'data': { 'data': 'str' } }
{ 'struct': 'Branch2', 'data': { 'data': 'int' } }
{ 'union': 'Flat', 'base': { 'type': 'Enum' }, 'discriminator': 'type',
'data': { 'one': 'Branch1', 'two': 'Branch2' } }
The order of branches need not match the order of the enum values.
The branches need not cover all possible enum values. In the
resulting generated C data types, a union is represented as a struct
with the base members in QAPI schema order, and then a union of
structures for each branch of the struct.
The optional 'if' member specifies a conditional. See `Configuring
the schema`_ below for more on this.
@ -859,9 +803,9 @@ longhand form of MEMBER.
Example: a struct type with unconditional member 'foo' and conditional
member 'bar' ::
{ 'struct': 'IfStruct', 'data':
{ 'foo': 'int',
'bar': { 'type': 'int', 'if': 'IFCOND'} } }
{ 'struct': 'IfStruct',
'data': { 'foo': 'int',
'bar': { 'type': 'int', 'if': 'IFCOND'} } }
A union's discriminator may not be conditional.
@ -871,9 +815,9 @@ the longhand form of ENUM-VALUE_.
Example: an enum type with unconditional value 'foo' and conditional
value 'bar' ::
{ 'enum': 'IfEnum', 'data':
[ 'foo',
{ 'name' : 'bar', 'if': 'IFCOND' } ] }
{ 'enum': 'IfEnum',
'data': [ 'foo',
{ 'name' : 'bar', 'if': 'IFCOND' } ] }
Likewise, features can be conditional. This requires the longhand
form of FEATURE_.
@ -1246,7 +1190,7 @@ that provides the variant members for this type tag value). The
"variants" array is in no particular order, and is not guaranteed to
list cases in the same order as the corresponding "tag" enum type.
Example: the SchemaInfo for flat union BlockdevOptions from section
Example: the SchemaInfo for union BlockdevOptions from section
`Union types`_ ::
{ "name": "BlockdevOptions", "meta-type": "object",
@ -1261,27 +1205,6 @@ Example: the SchemaInfo for flat union BlockdevOptions from section
Note that base types are "flattened": its members are included in the
"members" array.
A simple union implicitly defines an enumeration type for its implicit
discriminator (called "type" on the wire, see section `Union types`_).
A simple union implicitly defines an object type for each of its
variants.
Example: the SchemaInfo for simple union BlockdevOptionsSimple from section
`Union types`_ ::
{ "name": "BlockdevOptionsSimple", "meta-type": "object",
"members": [
{ "name": "type", "type": "BlockdevOptionsSimpleKind" } ],
"tag": "type",
"variants": [
{ "case": "file", "type": "q_obj-BlockdevOptionsFile-wrapper" },
{ "case": "qcow2", "type": "q_obj-BlockdevOptionsQcow2-wrapper" } ] }
Enumeration type "BlockdevOptionsSimpleKind" and the object types
"q_obj-BlockdevOptionsFile-wrapper", "q_obj-BlockdevOptionsQcow2-wrapper"
are implicitly defined.
The SchemaInfo for an alternate type has meta-type "alternate", and
variant member "members". "members" is a JSON array. Each element is
a JSON object with member "type", which names a type. Values of the

View file

@ -925,10 +925,10 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
c, TpmModel_str(ti->model));
monitor_printf(mon, " \\ %s: type=%s",
ti->id, TpmTypeOptionsKind_str(ti->options->type));
ti->id, TpmType_str(ti->options->type));
switch (ti->options->type) {
case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
case TPM_TYPE_PASSTHROUGH:
tpo = ti->options->u.passthrough.data;
monitor_printf(mon, "%s%s%s%s",
tpo->has_path ? ",path=" : "",
@ -936,11 +936,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
tpo->has_cancel_path ? ",cancel-path=" : "",
tpo->has_cancel_path ? tpo->cancel_path : "");
break;
case TPM_TYPE_OPTIONS_KIND_EMULATOR:
case TPM_TYPE_EMULATOR:
teo = ti->options->u.emulator.data;
monitor_printf(mon, ",chardev=%s", teo->chardev);
break;
case TPM_TYPE_OPTIONS_KIND__MAX:
case TPM_TYPE__MAX:
break;
}
monitor_printf(mon, "\n");

View file

@ -139,6 +139,52 @@
'*encryption-format': 'RbdImageEncryptionFormat'
} }
##
# @ImageInfoSpecificKind:
#
# @luks: Since 2.7
# @rbd: Since 6.1
#
# Since: 1.7
##
{ 'enum': 'ImageInfoSpecificKind',
'data': [ 'qcow2', 'vmdk', 'luks', 'rbd' ] }
##
# @ImageInfoSpecificQCow2Wrapper:
#
# Since: 1.7
##
{ 'struct': 'ImageInfoSpecificQCow2Wrapper',
'data': { 'data': 'ImageInfoSpecificQCow2' } }
##
# @ImageInfoSpecificVmdkWrapper:
#
# Since: 6.1
##
{ 'struct': 'ImageInfoSpecificVmdkWrapper',
'data': { 'data': 'ImageInfoSpecificVmdk' } }
##
# @ImageInfoSpecificLUKSWrapper:
#
# Since: 2.7
##
{ 'struct': 'ImageInfoSpecificLUKSWrapper',
'data': { 'data': 'QCryptoBlockInfoLUKS' } }
# If we need to add block driver specific parameters for
# LUKS in future, then we'll subclass QCryptoBlockInfoLUKS
# to define a ImageInfoSpecificLUKS
##
# @ImageInfoSpecificRbdWrapper:
#
# Since: 6.1
##
{ 'struct': 'ImageInfoSpecificRbdWrapper',
'data': { 'data': 'ImageInfoSpecificRbd' } }
##
# @ImageInfoSpecific:
#
@ -147,14 +193,13 @@
# Since: 1.7
##
{ 'union': 'ImageInfoSpecific',
'base': { 'type': 'ImageInfoSpecificKind' },
'discriminator': 'type',
'data': {
'qcow2': 'ImageInfoSpecificQCow2',
'vmdk': 'ImageInfoSpecificVmdk',
# If we need to add block driver specific parameters for
# LUKS in future, then we'll subclass QCryptoBlockInfoLUKS
# to define a ImageInfoSpecificLUKS
'luks': 'QCryptoBlockInfoLUKS',
'rbd': 'ImageInfoSpecificRbd'
'qcow2': 'ImageInfoSpecificQCow2Wrapper',
'vmdk': 'ImageInfoSpecificVmdkWrapper',
'luks': 'ImageInfoSpecificLUKSWrapper',
'rbd': 'ImageInfoSpecificRbdWrapper'
} }
##

View file

@ -407,39 +407,185 @@
'base': 'ChardevCommon',
'if': 'CONFIG_SPICE_PROTOCOL' }
##
# @ChardevBackendKind:
#
# @pipe: Since 1.5
# @udp: Since 1.5
# @mux: Since 1.5
# @msmouse: Since 1.5
# @wctablet: Since 2.9
# @braille: Since 1.5
# @testdev: Since 2.2
# @stdio: Since 1.5
# @console: Since 1.5
# @spicevmc: Since 1.5
# @spiceport: Since 1.5
# @qemu-vdagent: Since 6.1
# @vc: v1.5
# @ringbuf: Since 1.6
# @memory: Since 1.5
#
# Since: 1.4
##
{ 'enum': 'ChardevBackendKind',
'data': [ 'file',
'serial',
'parallel',
'pipe',
'socket',
'udp',
'pty',
'null',
'mux',
'msmouse',
'wctablet',
'braille',
'testdev',
'stdio',
'console',
{ 'name': 'spicevmc', 'if': 'CONFIG_SPICE' },
{ 'name': 'spiceport', 'if': 'CONFIG_SPICE' },
{ 'name': 'qemu-vdagent', 'if': 'CONFIG_SPICE_PROTOCOL' },
'vc',
'ringbuf',
# next one is just for compatibility
'memory' ] }
##
# @ChardevFileWrapper:
#
# Since: 1.4
##
{ 'struct': 'ChardevFileWrapper',
'data': { 'data': 'ChardevFile' } }
##
# @ChardevHostdevWrapper:
#
# Since: 1.4
##
{ 'struct': 'ChardevHostdevWrapper',
'data': { 'data': 'ChardevHostdev' } }
##
# @ChardevSocketWrapper:
#
# Since: 1.4
##
{ 'struct': 'ChardevSocketWrapper',
'data': { 'data': 'ChardevSocket' } }
##
# @ChardevUdpWrapper:
#
# Since: 1.5
##
{ 'struct': 'ChardevUdpWrapper',
'data': { 'data': 'ChardevUdp' } }
##
# @ChardevCommonWrapper:
#
# Since: 2.6
##
{ 'struct': 'ChardevCommonWrapper',
'data': { 'data': 'ChardevCommon' } }
##
# @ChardevMuxWrapper:
#
# Since: 1.5
##
{ 'struct': 'ChardevMuxWrapper',
'data': { 'data': 'ChardevMux' } }
##
# @ChardevStdioWrapper:
#
# Since: 1.5
##
{ 'struct': 'ChardevStdioWrapper',
'data': { 'data': 'ChardevStdio' } }
##
# @ChardevSpiceChannelWrapper:
#
# Since: 1.5
##
{ 'struct': 'ChardevSpiceChannelWrapper',
'data': { 'data': 'ChardevSpiceChannel' },
'if': 'CONFIG_SPICE' }
##
# @ChardevSpicePortWrapper:
#
# Since: 1.5
##
{ 'struct': 'ChardevSpicePortWrapper',
'data': { 'data': 'ChardevSpicePort' },
'if': 'CONFIG_SPICE' }
##
# @ChardevQemuVDAgentWrapper:
#
# Since: 6.1
##
{ 'struct': 'ChardevQemuVDAgentWrapper',
'data': { 'data': 'ChardevQemuVDAgent' },
'if': 'CONFIG_SPICE_PROTOCOL' }
##
# @ChardevVCWrapper:
#
# Since: 1.5
##
{ 'struct': 'ChardevVCWrapper',
'data': { 'data': 'ChardevVC' } }
##
# @ChardevRingbufWrapper:
#
# Since: 1.5
##
{ 'struct': 'ChardevRingbufWrapper',
'data': { 'data': 'ChardevRingbuf' } }
##
# @ChardevBackend:
#
# Configuration info for the new chardev backend.
#
# Since: 1.4 (testdev since 2.2, wctablet since 2.9, vdagent since 6.1)
# Since: 1.4
##
{ 'union': 'ChardevBackend',
'data': { 'file': 'ChardevFile',
'serial': 'ChardevHostdev',
'parallel': 'ChardevHostdev',
'pipe': 'ChardevHostdev',
'socket': 'ChardevSocket',
'udp': 'ChardevUdp',
'pty': 'ChardevCommon',
'null': 'ChardevCommon',
'mux': 'ChardevMux',
'msmouse': 'ChardevCommon',
'wctablet': 'ChardevCommon',
'braille': 'ChardevCommon',
'testdev': 'ChardevCommon',
'stdio': 'ChardevStdio',
'console': 'ChardevCommon',
'spicevmc': { 'type': 'ChardevSpiceChannel',
'base': { 'type': 'ChardevBackendKind' },
'discriminator': 'type',
'data': { 'file': 'ChardevFileWrapper',
'serial': 'ChardevHostdevWrapper',
'parallel': 'ChardevHostdevWrapper',
'pipe': 'ChardevHostdevWrapper',
'socket': 'ChardevSocketWrapper',
'udp': 'ChardevUdpWrapper',
'pty': 'ChardevCommonWrapper',
'null': 'ChardevCommonWrapper',
'mux': 'ChardevMuxWrapper',
'msmouse': 'ChardevCommonWrapper',
'wctablet': 'ChardevCommonWrapper',
'braille': 'ChardevCommonWrapper',
'testdev': 'ChardevCommonWrapper',
'stdio': 'ChardevStdioWrapper',
'console': 'ChardevCommonWrapper',
'spicevmc': { 'type': 'ChardevSpiceChannelWrapper',
'if': 'CONFIG_SPICE' },
'spiceport': { 'type': 'ChardevSpicePort',
'spiceport': { 'type': 'ChardevSpicePortWrapper',
'if': 'CONFIG_SPICE' },
'qemu-vdagent': { 'type': 'ChardevQemuVDAgent',
'qemu-vdagent': { 'type': 'ChardevQemuVDAgentWrapper',
'if': 'CONFIG_SPICE_PROTOCOL' },
'vc': 'ChardevVC',
'ringbuf': 'ChardevRingbuf',
'vc': 'ChardevVCWrapper',
'ringbuf': 'ChardevRingbufWrapper',
# next one is just for compatibility
'memory': 'ChardevRingbuf' } }
'memory': 'ChardevRingbufWrapper' } }
##
# @ChardevReturn:

View file

@ -1194,6 +1194,38 @@
}
}
##
# @MemoryDeviceInfoKind:
#
# Since: 2.1
##
{ 'enum': 'MemoryDeviceInfoKind',
'data': [ 'dimm', 'nvdimm', 'virtio-pmem', 'virtio-mem' ] }
##
# @PCDIMMDeviceInfoWrapper:
#
# Since: 2.1
##
{ 'struct': 'PCDIMMDeviceInfoWrapper',
'data': { 'data': 'PCDIMMDeviceInfo' } }
##
# @VirtioPMEMDeviceInfoWrapper:
#
# Since: 2.1
##
{ 'struct': 'VirtioPMEMDeviceInfoWrapper',
'data': { 'data': 'VirtioPMEMDeviceInfo' } }
##
# @VirtioMEMDeviceInfoWrapper:
#
# Since: 2.1
##
{ 'struct': 'VirtioMEMDeviceInfoWrapper',
'data': { 'data': 'VirtioMEMDeviceInfo' } }
##
# @MemoryDeviceInfo:
#
@ -1205,10 +1237,12 @@
# Since: 2.1
##
{ 'union': 'MemoryDeviceInfo',
'data': { 'dimm': 'PCDIMMDeviceInfo',
'nvdimm': 'PCDIMMDeviceInfo',
'virtio-pmem': 'VirtioPMEMDeviceInfo',
'virtio-mem': 'VirtioMEMDeviceInfo'
'base': { 'type': 'MemoryDeviceInfoKind' },
'discriminator': 'type',
'data': { 'dimm': 'PCDIMMDeviceInfoWrapper',
'nvdimm': 'PCDIMMDeviceInfoWrapper',
'virtio-pmem': 'VirtioPMEMDeviceInfoWrapper',
'virtio-mem': 'VirtioMEMDeviceInfoWrapper'
}
}

View file

@ -110,6 +110,38 @@
'cid': 'str',
'port': 'str' } }
##
# @InetSocketAddressWrapper:
#
# Since: 1.3
##
{ 'struct': 'InetSocketAddressWrapper',
'data': { 'data': 'InetSocketAddress' } }
##
# @UnixSocketAddressWrapper:
#
# Since: 1.3
##
{ 'struct': 'UnixSocketAddressWrapper',
'data': { 'data': 'UnixSocketAddress' } }
##
# @VsockSocketAddressWrapper:
#
# Since: 2.8
##
{ 'struct': 'VsockSocketAddressWrapper',
'data': { 'data': 'VsockSocketAddress' } }
##
# @StringWrapper:
#
# Since: 1.3
##
{ 'struct': 'StringWrapper',
'data': { 'data': 'String' } }
##
# @SocketAddressLegacy:
#
@ -117,18 +149,18 @@
#
# Note: This type is deprecated in favor of SocketAddress. The
# difference between SocketAddressLegacy and SocketAddress is that the
# latter is a flat union rather than a simple union. Flat is nicer
# because it avoids nesting on the wire, i.e. that form has fewer {}.
# latter is has fewer {} on the wire.
#
# Since: 1.3
##
{ 'union': 'SocketAddressLegacy',
'base': { 'type': 'SocketAddressType' },
'discriminator': 'type',
'data': {
'inet': 'InetSocketAddress',
'unix': 'UnixSocketAddress',
'vsock': 'VsockSocketAddress',
'fd': 'String' } }
'inet': 'InetSocketAddressWrapper',
'unix': 'UnixSocketAddressWrapper',
'vsock': 'VsockSocketAddressWrapper',
'fd': 'StringWrapper' } }
##
# @SocketAddressType:

View file

@ -99,6 +99,24 @@
{ 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' },
'if': 'CONFIG_TPM' }
##
# @TPMPassthroughOptionsWrapper:
#
# Since: 1.5
##
{ 'struct': 'TPMPassthroughOptionsWrapper',
'data': { 'data': 'TPMPassthroughOptions' },
'if': 'CONFIG_TPM' }
##
# @TPMEmulatorOptionsWrapper:
#
# Since: 2.11
##
{ 'struct': 'TPMEmulatorOptionsWrapper',
'data': { 'data': 'TPMEmulatorOptions' },
'if': 'CONFIG_TPM' }
##
# @TpmTypeOptions:
#
@ -110,8 +128,10 @@
# Since: 1.5
##
{ 'union': 'TpmTypeOptions',
'data': { 'passthrough' : 'TPMPassthroughOptions',
'emulator': 'TPMEmulatorOptions' },
'base': { 'type': 'TpmType' },
'discriminator': 'type',
'data': { 'passthrough' : 'TPMPassthroughOptionsWrapper',
'emulator': 'TPMEmulatorOptionsWrapper' },
'if': 'CONFIG_TPM' }
##

View file

@ -38,41 +38,128 @@
{ 'enum': 'ActionCompletionMode',
'data': [ 'individual', 'grouped' ] }
##
# @TransactionActionKind:
#
# @abort: Since 1.6
# @block-dirty-bitmap-add: Since 2.5
# @block-dirty-bitmap-remove: Since 4.2
# @block-dirty-bitmap-clear: Since 2.5
# @block-dirty-bitmap-enable: Since 4.0
# @block-dirty-bitmap-disable: Since 4.0
# @block-dirty-bitmap-merge: Since 4.0
# @blockdev-backup: Since 2.3
# @blockdev-snapshot: Since 2.5
# @blockdev-snapshot-internal-sync: Since 1.7
# @blockdev-snapshot-sync: since 1.1
# @drive-backup: Since 1.6
#
# Since: 1.1
##
{ 'enum': 'TransactionActionKind',
'data': [ 'abort', 'block-dirty-bitmap-add', 'block-dirty-bitmap-remove',
'block-dirty-bitmap-clear', 'block-dirty-bitmap-enable',
'block-dirty-bitmap-disable', 'block-dirty-bitmap-merge',
'blockdev-backup', 'blockdev-snapshot',
'blockdev-snapshot-internal-sync', 'blockdev-snapshot-sync',
'drive-backup' ] }
##
# @AbortWrapper:
#
# Since: 1.6
##
{ 'struct': 'AbortWrapper',
'data': { 'data': 'Abort' } }
##
# @BlockDirtyBitmapAddWrapper:
#
# Since: 2.5
##
{ 'struct': 'BlockDirtyBitmapAddWrapper',
'data': { 'data': 'BlockDirtyBitmapAdd' } }
##
# @BlockDirtyBitmapWrapper:
#
# Since: 2.5
##
{ 'struct': 'BlockDirtyBitmapWrapper',
'data': { 'data': 'BlockDirtyBitmap' } }
##
# @BlockDirtyBitmapMergeWrapper:
#
# Since: 4.0
##
{ 'struct': 'BlockDirtyBitmapMergeWrapper',
'data': { 'data': 'BlockDirtyBitmapMerge' } }
##
# @BlockdevBackupWrapper:
#
# Since: 2.3
##
{ 'struct': 'BlockdevBackupWrapper',
'data': { 'data': 'BlockdevBackup' } }
##
# @BlockdevSnapshotWrapper:
#
# Since: 2.5
##
{ 'struct': 'BlockdevSnapshotWrapper',
'data': { 'data': 'BlockdevSnapshot' } }
##
# @BlockdevSnapshotInternalWrapper:
#
# Since: 1.7
##
{ 'struct': 'BlockdevSnapshotInternalWrapper',
'data': { 'data': 'BlockdevSnapshotInternal' } }
##
# @BlockdevSnapshotSyncWrapper:
#
# Since: 1.1
##
{ 'struct': 'BlockdevSnapshotSyncWrapper',
'data': { 'data': 'BlockdevSnapshotSync' } }
##
# @DriveBackupWrapper:
#
# Since: 1.6
##
{ 'struct': 'DriveBackupWrapper',
'data': { 'data': 'DriveBackup' } }
##
# @TransactionAction:
#
# A discriminated record of operations that can be performed with
# @transaction. Action @type can be:
#
# - @abort: since 1.6
# - @block-dirty-bitmap-add: since 2.5
# - @block-dirty-bitmap-remove: since 4.2
# - @block-dirty-bitmap-clear: since 2.5
# - @block-dirty-bitmap-enable: since 4.0
# - @block-dirty-bitmap-disable: since 4.0
# - @block-dirty-bitmap-merge: since 4.0
# - @blockdev-backup: since 2.3
# - @blockdev-snapshot: since 2.5
# - @blockdev-snapshot-internal-sync: since 1.7
# - @blockdev-snapshot-sync: since 1.1
# - @drive-backup: since 1.6
# @transaction.
#
# Since: 1.1
##
{ 'union': 'TransactionAction',
'base': { 'type': 'TransactionActionKind' },
'discriminator': 'type',
'data': {
'abort': 'Abort',
'block-dirty-bitmap-add': 'BlockDirtyBitmapAdd',
'block-dirty-bitmap-remove': 'BlockDirtyBitmap',
'block-dirty-bitmap-clear': 'BlockDirtyBitmap',
'block-dirty-bitmap-enable': 'BlockDirtyBitmap',
'block-dirty-bitmap-disable': 'BlockDirtyBitmap',
'block-dirty-bitmap-merge': 'BlockDirtyBitmapMerge',
'blockdev-backup': 'BlockdevBackup',
'blockdev-snapshot': 'BlockdevSnapshot',
'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternal',
'blockdev-snapshot-sync': 'BlockdevSnapshotSync',
'drive-backup': 'DriveBackup'
'abort': 'AbortWrapper',
'block-dirty-bitmap-add': 'BlockDirtyBitmapAddWrapper',
'block-dirty-bitmap-remove': 'BlockDirtyBitmapWrapper',
'block-dirty-bitmap-clear': 'BlockDirtyBitmapWrapper',
'block-dirty-bitmap-enable': 'BlockDirtyBitmapWrapper',
'block-dirty-bitmap-disable': 'BlockDirtyBitmapWrapper',
'block-dirty-bitmap-merge': 'BlockDirtyBitmapMergeWrapper',
'blockdev-backup': 'BlockdevBackupWrapper',
'blockdev-snapshot': 'BlockdevSnapshotWrapper',
'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternalWrapper',
'blockdev-snapshot-sync': 'BlockdevSnapshotSyncWrapper',
'drive-backup': 'DriveBackupWrapper'
} }
##

View file

@ -824,6 +824,30 @@
'ac_home', 'ac_back', 'ac_forward', 'ac_refresh', 'ac_bookmarks',
'lang1', 'lang2' ] }
##
# @KeyValueKind:
#
# Since: 1.3
##
{ 'enum': 'KeyValueKind',
'data': [ 'number', 'qcode' ] }
##
# @IntWrapper:
#
# Since: 1.3
##
{ 'struct': 'IntWrapper',
'data': { 'data': 'int' } }
##
# @QKeyCodeWrapper:
#
# Since: 1.3
##
{ 'struct': 'QKeyCodeWrapper',
'data': { 'data': 'QKeyCode' } }
##
# @KeyValue:
#
@ -832,9 +856,11 @@
# Since: 1.3
##
{ 'union': 'KeyValue',
'base': { 'type': 'KeyValueKind' },
'discriminator': 'type',
'data': {
'number': 'int',
'qcode': 'QKeyCode' } }
'number': 'IntWrapper',
'qcode': 'QKeyCodeWrapper' } }
##
# @send-key:
@ -934,6 +960,38 @@
'data' : { 'axis' : 'InputAxis',
'value' : 'int' } }
##
# @InputEventKind:
#
# Since: 2.0
##
{ 'enum': 'InputEventKind',
'data': [ 'key', 'btn', 'rel', 'abs' ] }
##
# @InputKeyEventWrapper:
#
# Since: 2.0
##
{ 'struct': 'InputKeyEventWrapper',
'data': { 'data': 'InputKeyEvent' } }
##
# @InputBtnEventWrapper:
#
# Since: 2.0
##
{ 'struct': 'InputBtnEventWrapper',
'data': { 'data': 'InputBtnEvent' } }
##
# @InputMoveEventWrapper:
#
# Since: 2.0
##
{ 'struct': 'InputMoveEventWrapper',
'data': { 'data': 'InputMoveEvent' } }
##
# @InputEvent:
#
@ -949,10 +1007,12 @@
# Since: 2.0
##
{ 'union' : 'InputEvent',
'data' : { 'key' : 'InputKeyEvent',
'btn' : 'InputBtnEvent',
'rel' : 'InputMoveEvent',
'abs' : 'InputMoveEvent' } }
'base': { 'type': 'InputEventKind' },
'discriminator': 'type',
'data' : { 'key' : 'InputKeyEventWrapper',
'btn' : 'InputBtnEventWrapper',
'rel' : 'InputMoveEventWrapper',
'abs' : 'InputMoveEventWrapper' } }
##
# @input-send-event:

View file

@ -171,7 +171,7 @@ def check_defn_name_str(name: str, info: QAPISourceInfo, meta: str) -> None:
- 'event' names adhere to `check_name_upper()`.
- 'command' names adhere to `check_name_lower()`.
- Else, meta is a type, and must pass `check_name_camel()`.
These names must not end with ``Kind`` nor ``List``.
These names must not end with ``List``.
:param name: Name to check.
:param info: QAPI schema source file information.
@ -187,9 +187,9 @@ def check_defn_name_str(name: str, info: QAPISourceInfo, meta: str) -> None:
permit_underscore=name in info.pragma.command_name_exceptions)
else:
check_name_camel(name, info, meta)
if name.endswith('Kind') or name.endswith('List'):
if name.endswith('List'):
raise QAPISemError(
info, "%s name should not end in '%s'" % (meta, name[-4:]))
info, "%s name should not end in 'List'" % meta)
def check_keys(value: _JSONObject,
@ -513,27 +513,18 @@ def check_union(expr: _JSONObject, info: QAPISourceInfo) -> None:
:return: None, ``expr`` is normalized in-place as needed.
"""
name = cast(str, expr['union']) # Checked in check_exprs
base = expr.get('base')
discriminator = expr.get('discriminator')
base = expr['base']
discriminator = expr['discriminator']
members = expr['data']
if discriminator is None: # simple union
if base is not None:
raise QAPISemError(info, "'base' requires 'discriminator'")
else: # flat union
check_type(base, info, "'base'", allow_dict=name)
if not base:
raise QAPISemError(info, "'discriminator' requires 'base'")
check_name_is_str(discriminator, info, "'discriminator'")
check_type(base, info, "'base'", allow_dict=name)
check_name_is_str(discriminator, info, "'discriminator'")
if not isinstance(members, dict):
raise QAPISemError(info, "'data' must be an object")
for (key, value) in members.items():
source = "'data' member '%s'" % key
if discriminator is None:
check_name_lower(key, info, source)
# else: name is in discriminator enum, which gets checked
check_keys(value, info, source, ['type'], ['if'])
check_if(value, info, source)
check_type(value['type'], info, source, allow_array=not base)
@ -664,8 +655,8 @@ def check_exprs(exprs: List[_JSONObject]) -> List[_JSONObject]:
check_enum(expr, info)
elif meta == 'union':
check_keys(expr, info, meta,
['union', 'data'],
['base', 'discriminator', 'if', 'features'])
['union', 'base', 'discriminator', 'data'],
['if', 'features'])
normalize_members(expr.get('base'))
normalize_members(expr['data'])
check_union(expr, info)

View file

@ -321,8 +321,8 @@ def connect_doc(self, doc=None):
m.connect_doc(doc)
def is_implicit(self):
# See QAPISchema._make_implicit_enum_type() and ._def_predefineds()
return self.name.endswith('Kind') or self.name == 'QType'
# See QAPISchema._def_predefineds()
return self.name == 'QType'
def c_type(self):
return c_name(self.name)
@ -393,8 +393,7 @@ class QAPISchemaObjectType(QAPISchemaType):
def __init__(self, name, info, doc, ifcond, features,
base, local_members, variants):
# struct has local_members, optional base, and no variants
# flat union has base, variants, and no local_members
# simple union has local_members, variants, and no base
# union has base, variants, and no local_members
super().__init__(name, info, doc, ifcond, features)
self.meta = 'union' if variants else 'struct'
assert base is None or isinstance(base, str)
@ -465,15 +464,6 @@ def connect_doc(self, doc=None):
for m in self.local_members:
m.connect_doc(doc)
@property
def ifcond(self):
assert self._checked
if isinstance(self._ifcond, QAPISchemaType):
# Simple union wrapper type inherits from wrapped type;
# see _make_implicit_object_type()
return self._ifcond.ifcond
return self._ifcond
def is_implicit(self):
# See QAPISchema._make_implicit_object_type(), as well as
# _def_predefineds()
@ -576,10 +566,9 @@ def visit(self, visitor):
class QAPISchemaVariants:
def __init__(self, tag_name, info, 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.
# Unions pass tag_name but not tag_member.
# Alternates pass tag_member but not tag_name.
# After check(), tag_member is always set.
assert bool(tag_member) != bool(tag_name)
assert (isinstance(tag_name, str) or
isinstance(tag_member, QAPISchemaObjectTypeMember))
@ -595,7 +584,7 @@ def set_defined_in(self, name):
v.set_defined_in(name)
def check(self, schema, seen):
if not self.tag_member: # flat union
if self._tag_name: # union
self.tag_member = seen.get(c_name(self._tag_name))
base = "'base'"
# Pointing to the base type when not implicit would be
@ -625,11 +614,11 @@ def check(self, schema, seen):
self.info,
"discriminator member '%s' of %s must not be conditional"
% (self._tag_name, base))
else: # simple union
else: # alternate
assert isinstance(self.tag_member.type, QAPISchemaEnumType)
assert not self.tag_member.optional
assert not self.tag_member.ifcond.is_present()
if self._tag_name: # flat union
if self._tag_name: # union
# branches that are not explicitly covered get an empty type
cases = {v.name for v in self.variants}
for m in self.tag_member.type.members:
@ -707,18 +696,10 @@ def describe(self, info):
assert role == 'member'
role = 'parameter'
elif defined_in.endswith('-base'):
# Implicit type created for a flat union's dict 'base'
# Implicit type created for a union's dict 'base'
role = 'base ' + role
else:
# Implicit type created for a simple union's branch
assert defined_in.endswith('-wrapper')
# Unreachable and not implemented
assert False
elif defined_in.endswith('Kind'):
# See QAPISchema._make_implicit_enum_type()
# Implicit enum created for simple union's branches
assert role == 'value'
role = 'branch'
elif defined_in != info.defn_name:
return "%s '%s' of type '%s'" % (role, self.name, defined_in)
return "%s '%s'" % (role, self.name)
@ -1004,15 +985,6 @@ def _make_enum_members(self, values, info):
QAPISchemaIfCond(v.get('if')))
for v in values]
def _make_implicit_enum_type(self, name, info, ifcond, values):
# See also QAPISchemaObjectTypeMember.describe()
name = name + 'Kind' # reserved by check_defn_name_str()
self._def_entity(QAPISchemaEnumType(
name, info, None, ifcond, None,
self._make_enum_members(values, info),
None))
return name
def _make_array_type(self, element_type, info):
name = element_type + 'List' # reserved by check_defn_name_str()
if not self.lookup_type(name):
@ -1026,17 +998,9 @@ def _make_implicit_object_type(self, name, info, ifcond, role, members):
name = 'q_obj_%s-%s' % (name, role)
typ = self.lookup_entity(name, QAPISchemaObjectType)
if typ:
# The implicit object type has multiple users. This is
# either a duplicate definition (which will be flagged
# later), or an implicit wrapper type used for multiple
# simple unions. In the latter case, ifcond should be the
# disjunction of its user's ifconds. Not implemented.
# Instead, we always pass the wrapped type's ifcond, which
# is trivially the same for all users. It's also
# necessary for the wrapper to compile. But it's not
# tight: the disjunction need not imply it. We may end up
# compiling useless wrapper types.
# TODO kill simple unions or implement the disjunction
# The implicit object type has multiple users. This can
# only be a duplicate definition, which will be flagged
# later.
pass
else:
self._def_entity(QAPISchemaObjectType(
@ -1084,49 +1048,28 @@ def _def_struct_type(self, expr, info, doc):
def _make_variant(self, case, typ, ifcond, info):
return QAPISchemaVariant(case, info, typ, ifcond)
def _make_simple_variant(self, case, typ, ifcond, info):
if isinstance(typ, list):
assert len(typ) == 1
typ = self._make_array_type(typ[0], info)
typ = self._make_implicit_object_type(
typ, info, self.lookup_type(typ),
'wrapper', [self._make_member('data', typ, None, None, info)])
return QAPISchemaVariant(case, info, typ, ifcond)
def _def_union_type(self, expr, info, doc):
name = expr['union']
base = expr['base']
tag_name = expr['discriminator']
data = expr['data']
base = expr.get('base')
ifcond = QAPISchemaIfCond(expr.get('if'))
features = self._make_features(expr.get('features'), info)
tag_name = expr.get('discriminator')
tag_member = None
if isinstance(base, dict):
base = self._make_implicit_object_type(
name, info, ifcond,
'base', self._make_members(base, info))
if tag_name:
variants = [
self._make_variant(key, value['type'],
QAPISchemaIfCond(value.get('if')),
info)
for (key, value) in data.items()]
members = []
else:
variants = [
self._make_simple_variant(key, value['type'],
QAPISchemaIfCond(value.get('if')),
info)
for (key, value) in data.items()]
enum = [{'name': v.name, 'if': v.ifcond.ifcond} for v in variants]
typ = self._make_implicit_enum_type(name, info, ifcond, enum)
tag_member = QAPISchemaObjectTypeMember('type', info, typ, False)
members = [tag_member]
variants = [
self._make_variant(key, value['type'],
QAPISchemaIfCond(value.get('if')),
info)
for (key, value) in data.items()]
members = []
self._def_entity(
QAPISchemaObjectType(name, info, doc, ifcond, features,
base, members,
QAPISchemaVariants(
tag_name, info, tag_member, variants)))
tag_name, info, None, variants)))
def _def_alternate_type(self, expr, info, doc):
name = expr['alternate']

View file

@ -1,2 +1,2 @@
args-union.json: In command 'oops':
args-union.json:3: command's 'data' can take union type 'Uni' only with 'boxed': true
args-union.json:9: command's 'data' can take union type 'Uni' only with 'boxed': true

View file

@ -1,3 +1,9 @@
# use of union arguments requires 'boxed':true
{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } }
{ 'enum': 'Enum', 'data': [ 'case1', 'case2' ] }
{ 'struct': 'Case1', 'data': { 'data': 'int' } }
{ 'struct': 'Case2', 'data': { 'data': 'str' } }
{ 'union': 'Uni',
'base': { 'type': 'Enum' },
'discriminator': 'type',
'data': { 'case1': 'Case1', 'case2': 'Case2' } }
{ 'command': 'oops', 'data': 'Uni' }

View file

@ -1,2 +1,2 @@
bad-base.json: In struct 'MyType':
bad-base.json:3: 'base' requires a struct type, union type 'Union' isn't
bad-base.json:9: 'base' requires a struct type, union type 'Union' isn't

View file

@ -1,3 +1,9 @@
# we reject a base that is not a struct
{ 'union': 'Union', 'data': { 'a': 'int', 'b': 'str' } }
{ 'enum': 'Enum', 'data': [ 'a', 'b' ] }
{ 'struct': 'Int', 'data': { 'data': 'int' } }
{ 'struct': 'Str', 'data': { 'data': 'str' } }
{ 'union': 'Union',
'base': { 'type': 'Enum' },
'discriminator': 'type',
'data': { 'a': 'Int', 'b': 'Str' } }
{ 'struct': 'MyType', 'base': 'Union', 'data': { 'c': 'int' } }

View file

@ -60,8 +60,8 @@
#
# @two is undocumented
##
{ 'enum': 'Enum', 'data':
[ { 'name': 'one', 'if': 'IFONE' }, 'two' ],
{ 'enum': 'Enum',
'data': [ { 'name': 'one', 'if': 'IFONE' }, 'two' ],
'features': [ 'enum-feat' ],
'if': 'IFCOND' }
@ -107,15 +107,6 @@
'two': { 'type': 'Variant2',
'if': { 'any': ['IFONE', 'IFTWO'] } } } }
##
# @SugaredUnion:
# Features:
# @union-feat2: a feature
##
{ 'union': 'SugaredUnion',
'features': [ 'union-feat2' ],
'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
##
# @Alternate:
# @i: an integer

View file

@ -32,21 +32,6 @@ object Object
case two: Variant2
if {'any': ['IFONE', 'IFTWO']}
feature union-feat1
object q_obj_Variant1-wrapper
member data: Variant1 optional=False
object q_obj_Variant2-wrapper
member data: Variant2 optional=False
enum SugaredUnionKind
member one
member two
if IFTWO
object SugaredUnion
member type: SugaredUnionKind optional=False
tag type
case one: q_obj_Variant1-wrapper
case two: q_obj_Variant2-wrapper
if IFTWO
feature union-feat2
alternate Alternate
tag type
case i: int
@ -149,13 +134,6 @@ doc symbol=Object
feature=union-feat1
a feature
doc symbol=SugaredUnion
body=
arg=type
feature=union-feat2
a feature
doc symbol=Alternate
body=

View file

@ -130,26 +130,6 @@ Features
a feature
"SugaredUnion" (Object)
-----------------------
Members
~~~~~~~
"type"
One of "one", "two"
"data": "Variant1" when "type" is ""one""
"data": "Variant2" when "type" is ""two"" (**If: **"IFTWO")
Features
~~~~~~~~
"union-feat2"
a feature
"Alternate" (Alternate)
-----------------------

View file

@ -1,3 +1,3 @@
# check invalid 'if' type
{ 'enum': 'TestIfEnum', 'data':
[ 'foo', { 'name' : 'bar', 'if': { 'val': 'foo' } } ] }
{ 'enum': 'TestIfEnum',
'data': [ 'foo', { 'name' : 'bar', 'if': { 'val': 'foo' } } ] }

View file

@ -1,2 +0,0 @@
flat-union-array-branch.json: In union 'TestUnion':
flat-union-array-branch.json:8: 'data' member 'value1' cannot be an array

View file

@ -1,2 +0,0 @@
flat-union-bad-base.json: In union 'TestUnion':
flat-union-bad-base.json:8: member 'string' of type 'TestTypeA' collides with base member 'string'

View file

@ -1,2 +0,0 @@
flat-union-bad-discriminator.json: In union 'TestUnion':
flat-union-bad-discriminator.json:11: 'discriminator' requires a string name

View file

@ -1,2 +0,0 @@
flat-union-base-any.json: In union 'TestUnion':
flat-union-base-any.json:8: 'base' requires a struct type, built-in type 'any' isn't

View file

@ -1,2 +0,0 @@
flat-union-base-union.json: In union 'TestUnion':
flat-union-base-union.json:14: 'base' requires a struct type, union type 'UnionBase' isn't

View file

@ -1,2 +0,0 @@
flat-union-clash-member.json: In union 'TestUnion':
flat-union-clash-member.json:11: member 'name' of type 'Branch1' collides with member 'name' of type 'Base'

View file

@ -1,2 +0,0 @@
flat-union-discriminator-bad-name.json: In union 'MyUnion':
flat-union-discriminator-bad-name.json:6: discriminator '*switch' is not a member of 'base'

View file

@ -1,2 +0,0 @@
flat-union-empty.json: In union 'Union':
flat-union-empty.json:4: union has no branches

View file

@ -1,4 +0,0 @@
# flat union discriminator cannot be empty
{ 'enum': 'Empty', 'data': [ ] }
{ 'struct': 'Base', 'data': { 'type': 'Empty' } }
{ 'union': 'Union', 'base': 'Base', 'discriminator': 'type', 'data': { } }

View file

@ -1,2 +0,0 @@
flat-union-inline-invalid-dict.json: In union 'TestUnion':
flat-union-inline-invalid-dict.json:7: 'data' member 'value1' misses key 'type'

View file

@ -1,2 +0,0 @@
flat-union-int-branch.json: In union 'TestUnion':
flat-union-int-branch.json:8: branch 'value1' cannot use built-in type 'int'

View file

@ -1,2 +0,0 @@
flat-union-invalid-branch-key.json: In union 'TestUnion':
flat-union-invalid-branch-key.json:13: branch 'value_wrong' is not a value of enum type 'TestEnum'

View file

@ -1,2 +0,0 @@
flat-union-invalid-discriminator.json: In union 'TestUnion':
flat-union-invalid-discriminator.json:10: discriminator 'enum_wrong' is not a member of 'base'

View file

@ -1,2 +0,0 @@
flat-union-invalid-if-discriminator.json: In union 'TestUnion':
flat-union-invalid-if-discriminator.json:10: discriminator member 'enum1' of 'base' must not be conditional

View file

@ -1,2 +0,0 @@
flat-union-no-base.json: In union 'TestUnion':
flat-union-no-base.json:8: 'discriminator' requires 'base'

View file

@ -1,2 +0,0 @@
flat-union-optional-discriminator.json: In union 'MyUnion':
flat-union-optional-discriminator.json:6: discriminator member 'switch' of base type 'Base' must not be optional

View file

@ -1,2 +0,0 @@
flat-union-string-discriminator.json: In union 'TestUnion':
flat-union-string-discriminator.json:13: discriminator member 'kind' of base type 'TestBase' must be of enum type

View file

@ -107,22 +107,6 @@ schemas = [
'features-name-bad-type.json',
'features-no-list.json',
'features-unknown-key.json',
'flat-union-array-branch.json',
'flat-union-bad-base.json',
'flat-union-bad-discriminator.json',
'flat-union-base-any.json',
'flat-union-base-union.json',
'flat-union-clash-member.json',
'flat-union-discriminator-bad-name.json',
'flat-union-empty.json',
'flat-union-inline-invalid-dict.json',
'flat-union-int-branch.json',
'flat-union-invalid-branch-key.json',
'flat-union-invalid-discriminator.json',
'flat-union-invalid-if-discriminator.json',
'flat-union-no-base.json',
'flat-union-optional-discriminator.json',
'flat-union-string-discriminator.json',
'funny-char.json',
'funny-word.json',
'ident-with-escape.json',
@ -168,7 +152,6 @@ schemas = [
'reserved-member-q.json',
'reserved-member-u.json',
'reserved-member-underscore.json',
'reserved-type-kind.json',
'reserved-type-list.json',
'returns-alternate.json',
'returns-array-bad.json',
@ -191,16 +174,28 @@ schemas = [
'unclosed-list.json',
'unclosed-object.json',
'unclosed-string.json',
'union-array-branch.json',
'union-bad-base.json',
'union-bad-discriminator.json',
'union-base-any.json',
'union-base-empty.json',
'union-base-no-discriminator.json',
'union-branch-case.json',
'union-base-union.json',
'union-branch-if-invalid.json',
'union-branch-invalid-dict.json',
'union-clash-branches.json',
'union-clash-member.json',
'union-discriminator-bad-name.json',
'union-empty.json',
'union-inline-invalid-dict.json',
'union-int-branch.json',
'union-invalid-base.json',
'union-invalid-branch-key.json',
'union-invalid-data.json',
'union-optional-branch.json',
'union-invalid-discriminator.json',
'union-invalid-if-discriminator.json',
'union-no-base.json',
'union-optional-discriminator.json',
'union-string-discriminator.json',
'union-unknown.json',
'unknown-escape.json',
'unknown-expr-key.json',

View file

@ -30,7 +30,7 @@
{ 'struct': 'Empty1', 'data': { } }
{ 'struct': 'Empty2', 'base': 'Empty1', 'data': { } }
# Likewise for an empty flat union
# Likewise for an empty union
{ 'union': 'Union',
'base': { 'type': 'EnumOne' }, 'discriminator': 'type',
'data': { } }
@ -123,8 +123,7 @@
# for testing use of 'str' within alternates
{ 'alternate': 'AltStrObj', 'data': { 's': 'str', 'o': 'TestStruct' } }
# for testing lists
{ 'union': 'UserDefListUnion',
{ 'struct': 'ArrayStruct',
'data': { 'integer': ['int'],
's8': ['int8'],
's16': ['int16'],
@ -137,9 +136,9 @@
'number': ['number'],
'boolean': ['bool'],
'string': ['str'],
'sizes': ['size'],
'any': ['any'],
'user': ['Status'] } } # intentional forward ref. to sub-module
'*sz': ['size'],
'*any': ['any'],
'*user': ['Status'] } } # intentional forward ref. to sub-module
# for testing sub-modules
{ 'include': 'include/sub-module.json' }
@ -159,7 +158,7 @@
'returns': 'int' }
{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
{ 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
{ 'command': 'boxed-union', 'data': 'UserDefListUnion', 'boxed': true }
{ 'command': 'boxed-union', 'data': 'UserDefFlatUnion', 'boxed': true }
{ 'command': 'boxed-empty', 'boxed': true, 'data': 'Empty1' }
# Smoke test on out-of-band and allow-preconfig-test
@ -203,11 +202,10 @@
'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
{ 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member2': 'str', '*wchar-t': 'int' } }
{ 'union': '__org.qemu_x-Union1', 'data': { '__org.qemu_x-branch': 'str' } }
{ 'alternate': '__org.qemu_x-Alt1', 'data': { '__org.qemu_x-branch': 'str' } }
{ 'struct': '__org.qemu_x-Struct2',
'data': { 'array': ['__org.qemu_x-Union1'] } }
{ 'union': '__org.qemu_x-Union2', 'base': '__org.qemu_x-Base',
'data': { 'array': ['__org.qemu_x-Union'] } }
{ 'union': '__org.qemu_x-Union', 'base': '__org.qemu_x-Base',
'discriminator': '__org.qemu_x-member1',
'data': { '__org.qemu_x-value': '__org.qemu_x-Struct2' } }
{ 'alternate': '__org.qemu_x-Alt',
@ -215,32 +213,33 @@
{ 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
{ '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' },
'returns': '__org.qemu_x-Union1' }
'c': '__org.qemu_x-Union', 'd': '__org.qemu_x-Alt' } }
# test 'if' condition handling
{ 'struct': 'TestIfStruct', 'data':
{ 'foo': 'int',
'bar': { 'type': 'int', 'if': 'TEST_IF_STRUCT_BAR'} },
{ 'struct': 'TestIfStruct',
'data': { 'foo': 'int',
'bar': { 'type': 'int', 'if': 'TEST_IF_STRUCT_BAR'} },
'if': 'TEST_IF_STRUCT' }
{ 'enum': 'TestIfEnum', 'data':
[ 'foo', { 'name' : 'bar', 'if': 'TEST_IF_ENUM_BAR' } ],
{ 'enum': 'TestIfEnum',
'data': [ 'foo', { 'name' : 'bar', 'if': 'TEST_IF_ENUM_BAR' } ],
'if': 'TEST_IF_ENUM' }
{ 'union': 'TestIfUnion', 'data':
{ 'foo': 'TestStruct',
'bar': { 'type': 'str', 'if': 'TEST_IF_UNION_BAR'} },
{ 'union': 'TestIfUnion',
'base': { 'type': 'TestIfEnum' },
'discriminator': 'type',
'data': { 'foo': 'TestStruct',
'bar': { 'type': 'UserDefZero', 'if': 'TEST_IF_ENUM_BAR'} },
'if': { 'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT'] } }
{ 'command': 'test-if-union-cmd',
'data': { 'union-cmd-arg': 'TestIfUnion' },
'if': { 'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT'] } }
{ 'alternate': 'TestIfAlternate', 'data':
{ 'foo': 'int',
'bar': { 'type': 'TestStruct', 'if': 'TEST_IF_ALT_BAR'} },
{ 'alternate': 'TestIfAlternate',
'data': { 'foo': 'int',
'bar': { 'type': 'TestStruct', 'if': 'TEST_IF_ALT_BAR'} },
'if': { 'all': ['TEST_IF_ALT', 'TEST_IF_STRUCT'] } }
{ 'command': 'test-if-alternate-cmd',
@ -256,9 +255,9 @@
{ 'command': 'test-cmd-return-def-three', 'returns': 'UserDefThree' }
{ 'event': 'TEST_IF_EVENT', 'data':
{ 'foo': 'TestIfStruct',
'bar': { 'type': ['TestIfEnum'], 'if': 'TEST_IF_EVT_BAR' } },
{ 'event': 'TEST_IF_EVENT',
'data': { 'foo': 'TestIfStruct',
'bar': { 'type': ['TestIfEnum'], 'if': 'TEST_IF_EVT_BAR' } },
'if': { 'all': ['TEST_IF_EVT', 'TEST_IF_STRUCT'] } }
{ 'event': 'TEST_IF_EVENT2', 'data': {},

View file

@ -125,70 +125,22 @@ alternate AltStrObj
tag type
case s: str
case o: TestStruct
object q_obj_intList-wrapper
member data: intList optional=False
object q_obj_int8List-wrapper
member data: int8List optional=False
object q_obj_int16List-wrapper
member data: int16List optional=False
object q_obj_int32List-wrapper
member data: int32List optional=False
object q_obj_int64List-wrapper
member data: int64List optional=False
object q_obj_uint8List-wrapper
member data: uint8List optional=False
object q_obj_uint16List-wrapper
member data: uint16List optional=False
object q_obj_uint32List-wrapper
member data: uint32List optional=False
object q_obj_uint64List-wrapper
member data: uint64List optional=False
object q_obj_numberList-wrapper
member data: numberList optional=False
object q_obj_boolList-wrapper
member data: boolList optional=False
object q_obj_strList-wrapper
member data: strList optional=False
object q_obj_sizeList-wrapper
member data: sizeList optional=False
object q_obj_anyList-wrapper
member data: anyList optional=False
object q_obj_StatusList-wrapper
member data: StatusList optional=False
enum UserDefListUnionKind
member integer
member s8
member s16
member s32
member s64
member u8
member u16
member u32
member u64
member number
member boolean
member string
member sizes
member any
member user
object UserDefListUnion
member type: UserDefListUnionKind optional=False
tag type
case integer: q_obj_intList-wrapper
case s8: q_obj_int8List-wrapper
case s16: q_obj_int16List-wrapper
case s32: q_obj_int32List-wrapper
case s64: q_obj_int64List-wrapper
case u8: q_obj_uint8List-wrapper
case u16: q_obj_uint16List-wrapper
case u32: q_obj_uint32List-wrapper
case u64: q_obj_uint64List-wrapper
case number: q_obj_numberList-wrapper
case boolean: q_obj_boolList-wrapper
case string: q_obj_strList-wrapper
case sizes: q_obj_sizeList-wrapper
case any: q_obj_anyList-wrapper
case user: q_obj_StatusList-wrapper
object ArrayStruct
member integer: intList optional=False
member s8: int8List optional=False
member s16: int16List optional=False
member s32: int32List optional=False
member s64: int64List optional=False
member u8: uint8List optional=False
member u16: uint16List optional=False
member u32: uint32List optional=False
member u64: uint64List optional=False
member number: numberList optional=False
member boolean: boolList optional=False
member string: strList optional=False
member sz: sizeList optional=True
member any: anyList optional=True
member user: StatusList optional=True
include include/sub-module.json
command user-def-cmd None -> None
gen=True success_response=True boxed=False oob=False preconfig=False
@ -216,7 +168,7 @@ command guest-sync q_obj_guest-sync-arg -> any
gen=True success_response=True boxed=False oob=False preconfig=False
command boxed-struct UserDefZero -> None
gen=True success_response=True boxed=True oob=False preconfig=False
command boxed-union UserDefListUnion -> None
command boxed-union UserDefFlatUnion -> None
gen=True success_response=True boxed=True oob=False preconfig=False
command boxed-empty Empty1 -> None
gen=True success_response=True boxed=True oob=False preconfig=False
@ -263,21 +215,13 @@ object __org.qemu_x-Struct
base __org.qemu_x-Base
member __org.qemu_x-member2: str optional=False
member wchar-t: int optional=True
object q_obj_str-wrapper
member data: str optional=False
enum __org.qemu_x-Union1Kind
member __org.qemu_x-branch
object __org.qemu_x-Union1
member type: __org.qemu_x-Union1Kind optional=False
tag type
case __org.qemu_x-branch: q_obj_str-wrapper
alternate __org.qemu_x-Alt1
tag type
case __org.qemu_x-branch: str
array __org.qemu_x-Union1List __org.qemu_x-Union1
array __org.qemu_x-UnionList __org.qemu_x-Union
object __org.qemu_x-Struct2
member array: __org.qemu_x-Union1List optional=False
object __org.qemu_x-Union2
member array: __org.qemu_x-UnionList optional=False
object __org.qemu_x-Union
base __org.qemu_x-Base
tag __org.qemu_x-member1
case __org.qemu_x-value: __org.qemu_x-Struct2
@ -291,9 +235,9 @@ array __org.qemu_x-StructList __org.qemu_x-Struct
object q_obj___org.qemu_x-command-arg
member a: __org.qemu_x-EnumList optional=False
member b: __org.qemu_x-StructList optional=False
member c: __org.qemu_x-Union2 optional=False
member c: __org.qemu_x-Union optional=False
member d: __org.qemu_x-Alt optional=False
command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> None
gen=True success_response=True boxed=False oob=False preconfig=False
object TestIfStruct
member foo: int optional=False
@ -305,19 +249,15 @@ enum TestIfEnum
member bar
if TEST_IF_ENUM_BAR
if TEST_IF_ENUM
object q_obj_TestStruct-wrapper
member data: TestStruct optional=False
enum TestIfUnionKind
member foo
member bar
if TEST_IF_UNION_BAR
object q_obj_TestIfUnion-base
member type: TestIfEnum optional=False
if {'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT']}
object TestIfUnion
member type: TestIfUnionKind optional=False
base q_obj_TestIfUnion-base
tag type
case foo: q_obj_TestStruct-wrapper
case bar: q_obj_str-wrapper
if TEST_IF_UNION_BAR
case foo: TestStruct
case bar: UserDefZero
if TEST_IF_ENUM_BAR
if {'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT']}
object q_obj_test-if-union-cmd-arg
member union-cmd-arg: TestIfUnion optional=False

View file

@ -2,6 +2,6 @@
# We reject use of 'u' as a member name, to allow it for internal use in
# putting union branch members in a separate namespace from QMP members.
# This is true even for non-unions, because it is possible to convert a
# struct to flat union while remaining backwards compatible in QMP.
# struct to union while remaining backwards compatible in QMP.
# TODO - we could munge the member name to 'q_u' to avoid the collision
{ 'struct': 'Oops', 'data': { '*u': 'str' } }

View file

@ -1,2 +0,0 @@
reserved-type-kind.json: In enum 'UnionKind':
reserved-type-kind.json:2: enum name should not end in 'Kind'

View file

@ -1,2 +0,0 @@
# we reject types that would conflict with implicit union enum
{ 'enum': 'UnionKind', 'data': [ 'oops' ] }

View file

@ -132,6 +132,17 @@ def test_frontend(fname):
print(' section=%s\n%s' % (section.name, section.text))
def open_test_result(dir_name, file_name, update):
mode = 'r+' if update else 'r'
try:
fp = open(os.path.join(dir_name, file_name), mode)
except FileNotFoundError:
if not update:
raise
fp = open(os.path.join(dir_name, file_name), 'w+')
return fp
def test_and_diff(test_name, dir_name, update):
sys.stdout = StringIO()
try:
@ -148,13 +159,12 @@ def test_and_diff(test_name, dir_name, update):
sys.stdout.close()
sys.stdout = sys.__stdout__
mode = 'r+' if update else 'r'
try:
outfp = open(os.path.join(dir_name, test_name + '.out'), mode)
errfp = open(os.path.join(dir_name, test_name + '.err'), mode)
outfp = open_test_result(dir_name, test_name + '.out', update)
errfp = open_test_result(dir_name, test_name + '.err', update)
expected_out = outfp.readlines()
expected_err = errfp.readlines()
except IOError as err:
except OSError as err:
print("%s: can't open '%s': %s"
% (sys.argv[0], err.filename, err.strerror),
file=sys.stderr)
@ -180,7 +190,7 @@ def test_and_diff(test_name, dir_name, update):
errfp.truncate(0)
errfp.seek(0)
errfp.writelines(actual_err)
except IOError as err:
except OSError as err:
print("%s: can't write '%s': %s"
% (sys.argv[0], err.filename, err.strerror),
file=sys.stderr)

View file

@ -0,0 +1,2 @@
union-array-branch.json: In union 'TestUnion':
union-array-branch.json:8: 'data' member 'value1' cannot be an array

View file

@ -1,4 +1,4 @@
# we require flat union branches to be a struct
# we require union branches to be a struct
{ 'enum': 'TestEnum',
'data': [ 'value1', 'value2' ] }
{ 'struct': 'Base',

View file

@ -0,0 +1,2 @@
union-bad-base.json: In union 'TestUnion':
union-bad-base.json:8: member 'string' of type 'TestTypeA' collides with base member 'string'

View file

@ -0,0 +1,2 @@
union-bad-discriminator.json: In union 'TestUnion':
union-bad-discriminator.json:11: 'discriminator' requires a string name

View file

@ -0,0 +1,2 @@
union-base-any.json: In union 'TestUnion':
union-base-any.json:8: 'base' requires a struct type, built-in type 'any' isn't

View file

@ -1,4 +1,4 @@
# Flat union with empty base and therefore without discriminator
# Union with empty base and therefore without discriminator
{ 'struct': 'Empty', 'data': { } }

View file

@ -1,2 +1,2 @@
union-base-no-discriminator.json: In union 'TestUnion':
union-base-no-discriminator.json:11: 'base' requires 'discriminator'
union-base-no-discriminator.json:11: union misses key 'discriminator'

View file

@ -1,4 +1,4 @@
# we reject simple unions with a base (or flat unions without discriminator)
# we reject unions without discriminator
{ 'struct': 'TestTypeA',
'data': { 'string': 'str' } }

View file

@ -0,0 +1,2 @@
union-base-union.json: In union 'TestUnion':
union-base-union.json:17: 'base' requires a struct type, union type 'UnionBase' isn't

View file

@ -8,7 +8,10 @@
'data': { 'string': 'str' } }
{ 'struct': 'TestTypeB',
'data': { 'integer': 'int' } }
{ 'enum': 'Enum', 'data': [ 'kind1', 'kind2' ] }
{ 'union': 'UnionBase',
'base': { 'type': 'Enum' },
'discriminator': 'type',
'data': { 'kind1': 'TestTypeA',
'kind2': 'TestTypeB' } }
{ 'union': 'TestUnion',

View file

@ -1,2 +0,0 @@
union-branch-case.json: In union 'Uni':
union-branch-case.json:2: name of 'data' member 'Branch' must not use uppercase or '_'

View file

@ -1,2 +0,0 @@
# Branch names should be 'lower-case'
{ 'union': 'Uni', 'data': { 'Branch': 'int' } }

View file

@ -1,2 +1,2 @@
union-branch-invalid-dict.json: In union 'UnionInvalidBranch':
union-branch-invalid-dict.json:2: 'data' member 'integer' misses key 'type'
union-branch-invalid-dict.json:4: 'data' member 'integer' misses key 'type'

View file

@ -1,4 +1,8 @@
# Long form of member must have a value member 'type'
{ 'enum': 'TestEnum',
'data': [ 'integer', 's8' ] }
{ 'union': 'UnionInvalidBranch',
'base': { 'type': 'TestEnum' },
'discriminator': 'type',
'data': { 'integer': { 'if': 'foo'},
's8': 'int8' } }

View file

@ -1,2 +0,0 @@
union-clash-branches.json: In union 'TestUnion':
union-clash-branches.json:6: name of 'data' member 'a_b' must not use uppercase or '_'

View file

@ -1,7 +0,0 @@
# Union branch name collision
# Naming rules make collision impossible (even with the pragma). If
# that wasn't the case, then we'd get collisions in generated C: two
# union members a_b, and two enum members TEST_UNION_A_B.
{ 'pragma': { 'member-name-exceptions': [ 'TestUnion' ] } }
{ 'union': 'TestUnion',
'data': { 'a-b': 'int', 'a_b': 'str' } }

View file

@ -0,0 +1,2 @@
union-clash-member.json: In union 'TestUnion':
union-clash-member.json:11: member 'name' of type 'Branch1' collides with member 'name' of type 'Base'

View file

@ -0,0 +1,2 @@
union-discriminator-bad-name.json: In union 'MyUnion':
union-discriminator-bad-name.json:6: discriminator '*switch' is not a member of 'base'

View file

@ -1,2 +1,2 @@
union-empty.json: In union 'Union':
union-empty.json:2: union has no branches
union-empty.json:4: union has no branches

View file

@ -1,2 +1,4 @@
# simple unions cannot be empty
{ 'union': 'Union', 'data': { } }
# union discriminator enum cannot be empty
{ 'enum': 'Empty', 'data': [ ] }
{ 'struct': 'Base', 'data': { 'type': 'Empty' } }
{ 'union': 'Union', 'base': 'Base', 'discriminator': 'type', 'data': { } }

View file

@ -0,0 +1,2 @@
union-inline-invalid-dict.json: In union 'TestUnion':
union-inline-invalid-dict.json:7: 'data' member 'value1' misses key 'type'

View file

@ -0,0 +1,2 @@
union-int-branch.json: In union 'TestUnion':
union-int-branch.json:8: branch 'value1' cannot use built-in type 'int'

View file

@ -1,4 +1,4 @@
# we require flat union branches to be a struct
# we require union branches to be a struct
{ 'enum': 'TestEnum',
'data': [ 'value1', 'value2' ] }
{ 'struct': 'Base',

View file

@ -0,0 +1,2 @@
union-invalid-branch-key.json: In union 'TestUnion':
union-invalid-branch-key.json:13: branch 'value_wrong' is not a value of enum type 'TestEnum'

View file

@ -0,0 +1,2 @@
union-invalid-discriminator.json: In union 'TestUnion':
union-invalid-discriminator.json:10: discriminator 'enum_wrong' is not a member of 'base'

View file

@ -0,0 +1,2 @@
union-invalid-if-discriminator.json: In union 'TestUnion':
union-invalid-if-discriminator.json:10: discriminator member 'enum1' of 'base' must not be conditional

View file

@ -0,0 +1,2 @@
union-no-base.json: In union 'TestUnion':
union-no-base.json:8: union misses key 'base'

View file

@ -1,4 +1,4 @@
# flat unions require a base
# unions require a base
{ 'struct': 'TestTypeA',
'data': { 'string': 'str' } }
{ 'struct': 'TestTypeB',

Some files were not shown because too many files have changed in this diff Show more