Merge remote-tracking branch 'remotes/qmp-unstable/queue/qmp' into staging

* remotes/qmp-unstable/queue/qmp: (32 commits)
  qapi: Add missing null check to opts_start_struct()
  qapi: Clean up superfluous null check in qapi_dealloc_type_str()
  qapi: Clean up null checking in generated visitors
  qapi: Drop unused code in qapi-commands.py
  qapi: Drop nonsensical header guard in generated qapi-visit.c
  qapi: Fix licensing of scripts
  tests/qapi-schema: Cover flat union types
  tests/qapi-schema: Cover union types with base
  tests/qapi-schema: Cover complex types with base
  tests/qapi-schema: Cover anonymous union types
  tests/qapi-schema: Cover simple argument types
  tests/qapi-schema: Cover optional command arguments
  tests/qapi-schema: Actually check successful QMP command response
  monitor: Remove left-over code in do_info_profile.
  qerror: Improve QERR_DEVICE_NOT_ACTIVE message
  qmp: Check for returned data from __json_read in get_events
  dump: add 'query-dump-guest-memory-capability' command
  Define the architecture for compressed dump format
  dump: make kdump-compressed format available for 'dump-guest-memory'
  dump: add API to write dump pages
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-03-04 17:01:07 +00:00
commit e00ef747f0
27 changed files with 1546 additions and 108 deletions

View File

@ -726,7 +726,7 @@ F: vl.c
Human Monitor (HMP)
M: Luiz Capitulino <lcapitulino@redhat.com>
S: Supported
S: Maintained
F: monitor.c
F: hmp.c
F: hmp-commands.hx
@ -758,7 +758,7 @@ T: git git://github.com/bonzini/qemu.git nbd-next
QAPI
M: Luiz Capitulino <lcapitulino@redhat.com>
M: Michael Roth <mdroth@linux.vnet.ibm.com>
S: Supported
S: Maintained
F: qapi/
T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
@ -772,7 +772,7 @@ T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
QMP
M: Luiz Capitulino <lcapitulino@redhat.com>
S: Supported
S: Maintained
F: qmp.c
F: monitor.c
F: qmp-commands.hx

54
configure vendored
View File

@ -283,6 +283,8 @@ libusb=""
usb_redir=""
glx=""
zlib="yes"
lzo="no"
snappy="no"
guest_agent=""
guest_agent_with_vss="no"
vss_win32_sdk=""
@ -995,6 +997,10 @@ for opt do
;;
--disable-zlib-test) zlib="no"
;;
--enable-lzo) lzo="yes"
;;
--enable-snappy) snappy="yes"
;;
--enable-guest-agent) guest_agent="yes"
;;
--disable-guest-agent) guest_agent="no"
@ -1289,6 +1295,8 @@ Advanced options (experts only):
--enable-libusb enable libusb (for usb passthrough)
--disable-usb-redir disable usb network redirection support
--enable-usb-redir enable usb network redirection support
--enable-lzo enable the support of lzo compression library
--enable-snappy enable the support of snappy compression library
--disable-guest-agent disable building of the QEMU Guest Agent
--enable-guest-agent enable building of the QEMU Guest Agent
--with-vss-sdk=SDK-path enable Windows VSS support in QEMU Guest Agent
@ -1659,6 +1667,42 @@ EOF
fi
LIBS="$LIBS -lz"
##########################################
# lzo check
if test "$lzo" != "no" ; then
cat > $TMPC << EOF
#include <lzo/lzo1x.h>
int main(void) { lzo_version(); return 0; }
EOF
if compile_prog "" "-llzo2" ; then
:
else
error_exit "lzo check failed" \
"Make sure to have the lzo libs and headers installed."
fi
libs_softmmu="$libs_softmmu -llzo2"
fi
##########################################
# snappy check
if test "$snappy" != "no" ; then
cat > $TMPC << EOF
#include <snappy-c.h>
int main(void) { snappy_max_compressed_length(4096); return 0; }
EOF
if compile_prog "" "-lsnappy" ; then
:
else
error_exit "snappy check failed" \
"Make sure to have the snappy libs and headers installed."
fi
libs_softmmu="$libs_softmmu -lsnappy"
fi
##########################################
# libseccomp check
@ -4045,6 +4089,8 @@ echo "TPM passthrough $tpm_passthrough"
echo "QOM debugging $qom_cast_debug"
echo "vhdx $vhdx"
echo "Quorum $quorum"
echo "lzo support $lzo"
echo "snappy support $snappy"
if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@ -4368,6 +4414,14 @@ if test "$glx" = "yes" ; then
echo "GLX_LIBS=$glx_libs" >> $config_host_mak
fi
if test "$lzo" = "yes" ; then
echo "CONFIG_LZO=y" >> $config_host_mak
fi
if test "$snappy" = "yes" ; then
echo "CONFIG_SNAPPY=y" >> $config_host_mak
fi
if test "$libiscsi" = "yes" ; then
echo "CONFIG_LIBISCSI=m" >> $config_host_mak
if test "$libiscsi_version" = "1.4.0"; then

960
dump.c

File diff suppressed because it is too large Load Diff

5
hmp.c
View File

@ -1311,8 +1311,11 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
const char *file = qdict_get_str(qdict, "filename");
bool has_begin = qdict_haskey(qdict, "begin");
bool has_length = qdict_haskey(qdict, "length");
/* kdump-compressed format is not supported for HMP */
bool has_format = false;
int64_t begin = 0;
int64_t length = 0;
enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
char *prot;
if (has_begin) {
@ -1325,7 +1328,7 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
prot = g_strconcat("file:", file, NULL);
qmp_dump_guest_memory(paging, prot, has_begin, begin, has_length, length,
&errp);
has_format, dump_format, &errp);
hmp_handle_error(mon, &errp);
g_free(prot);
}

View File

@ -105,7 +105,7 @@ void qerror_report_err(Error *err);
ERROR_CLASS_GENERIC_ERROR, "Device '%s' does not support hotplugging"
#define QERR_DEVICE_NOT_ACTIVE \
ERROR_CLASS_DEVICE_NOT_ACTIVE, "Device '%s' has not been activated"
ERROR_CLASS_DEVICE_NOT_ACTIVE, "No %s device has been activated"
#define QERR_DEVICE_NOT_ENCRYPTED \
ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not encrypted"

View File

@ -28,7 +28,8 @@
#include "qemu/tls.h"
#include "qemu/typedefs.h"
typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque);
typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
void *opaque);
/**
* vaddr:

View File

@ -14,12 +14,150 @@
#ifndef DUMP_H
#define DUMP_H
#define MAKEDUMPFILE_SIGNATURE "makedumpfile"
#define MAX_SIZE_MDF_HEADER (4096) /* max size of makedumpfile_header */
#define TYPE_FLAT_HEADER (1) /* type of flattened format */
#define VERSION_FLAT_HEADER (1) /* version of flattened format */
#define END_FLAG_FLAT_HEADER (-1)
#define ARCH_PFN_OFFSET (0)
#define paddr_to_pfn(X, page_shift) \
(((unsigned long long)(X) >> (page_shift)) - ARCH_PFN_OFFSET)
#define pfn_to_paddr(X, page_shift) \
(((unsigned long long)(X) + ARCH_PFN_OFFSET) << (page_shift))
/*
* flag for compressed format
*/
#define DUMP_DH_COMPRESSED_ZLIB (0x1)
#define DUMP_DH_COMPRESSED_LZO (0x2)
#define DUMP_DH_COMPRESSED_SNAPPY (0x4)
#define KDUMP_SIGNATURE "KDUMP "
#define SIG_LEN (sizeof(KDUMP_SIGNATURE) - 1)
#define PHYS_BASE (0)
#define DUMP_LEVEL (1)
#define DISKDUMP_HEADER_BLOCKS (1)
#define BUFSIZE_BITMAP (TARGET_PAGE_SIZE)
#define PFN_BUFBITMAP (CHAR_BIT * BUFSIZE_BITMAP)
#define BUFSIZE_DATA_CACHE (TARGET_PAGE_SIZE * 4)
typedef struct ArchDumpInfo {
int d_machine; /* Architecture */
int d_endian; /* ELFDATA2LSB or ELFDATA2MSB */
int d_class; /* ELFCLASS32 or ELFCLASS64 */
} ArchDumpInfo;
typedef struct QEMU_PACKED MakedumpfileHeader {
char signature[16]; /* = "makedumpfile" */
int64_t type;
int64_t version;
} MakedumpfileHeader;
typedef struct QEMU_PACKED MakedumpfileDataHeader {
int64_t offset;
int64_t buf_size;
} MakedumpfileDataHeader;
typedef struct QEMU_PACKED NewUtsname {
char sysname[65];
char nodename[65];
char release[65];
char version[65];
char machine[65];
char domainname[65];
} NewUtsname;
typedef struct QEMU_PACKED DiskDumpHeader32 {
char signature[SIG_LEN]; /* = "KDUMP " */
uint32_t header_version; /* Dump header version */
NewUtsname utsname; /* copy of system_utsname */
char timestamp[10]; /* Time stamp */
uint32_t status; /* Above flags */
uint32_t block_size; /* Size of a block in byte */
uint32_t sub_hdr_size; /* Size of arch dependent header in block */
uint32_t bitmap_blocks; /* Size of Memory bitmap in block */
uint32_t max_mapnr; /* = max_mapnr ,
obsoleted in header_version 6 */
uint32_t total_ram_blocks; /* Number of blocks should be written */
uint32_t device_blocks; /* Number of total blocks in dump device */
uint32_t written_blocks; /* Number of written blocks */
uint32_t current_cpu; /* CPU# which handles dump */
uint32_t nr_cpus; /* Number of CPUs */
} DiskDumpHeader32;
typedef struct QEMU_PACKED DiskDumpHeader64 {
char signature[SIG_LEN]; /* = "KDUMP " */
uint32_t header_version; /* Dump header version */
NewUtsname utsname; /* copy of system_utsname */
char timestamp[22]; /* Time stamp */
uint32_t status; /* Above flags */
uint32_t block_size; /* Size of a block in byte */
uint32_t sub_hdr_size; /* Size of arch dependent header in block */
uint32_t bitmap_blocks; /* Size of Memory bitmap in block */
uint32_t max_mapnr; /* = max_mapnr,
obsoleted in header_version 6 */
uint32_t total_ram_blocks; /* Number of blocks should be written */
uint32_t device_blocks; /* Number of total blocks in dump device */
uint32_t written_blocks; /* Number of written blocks */
uint32_t current_cpu; /* CPU# which handles dump */
uint32_t nr_cpus; /* Number of CPUs */
} DiskDumpHeader64;
typedef struct QEMU_PACKED KdumpSubHeader32 {
uint32_t phys_base;
uint32_t dump_level; /* header_version 1 and later */
uint32_t split; /* header_version 2 and later */
uint32_t start_pfn; /* header_version 2 and later,
obsoleted in header_version 6 */
uint32_t end_pfn; /* header_version 2 and later,
obsoleted in header_version 6 */
uint64_t offset_vmcoreinfo; /* header_version 3 and later */
uint32_t size_vmcoreinfo; /* header_version 3 and later */
uint64_t offset_note; /* header_version 4 and later */
uint32_t note_size; /* header_version 4 and later */
uint64_t offset_eraseinfo; /* header_version 5 and later */
uint32_t size_eraseinfo; /* header_version 5 and later */
uint64_t start_pfn_64; /* header_version 6 and later */
uint64_t end_pfn_64; /* header_version 6 and later */
uint64_t max_mapnr_64; /* header_version 6 and later */
} KdumpSubHeader32;
typedef struct QEMU_PACKED KdumpSubHeader64 {
uint64_t phys_base;
uint32_t dump_level; /* header_version 1 and later */
uint32_t split; /* header_version 2 and later */
uint64_t start_pfn; /* header_version 2 and later,
obsoleted in header_version 6 */
uint64_t end_pfn; /* header_version 2 and later,
obsoleted in header_version 6 */
uint64_t offset_vmcoreinfo; /* header_version 3 and later */
uint64_t size_vmcoreinfo; /* header_version 3 and later */
uint64_t offset_note; /* header_version 4 and later */
uint64_t note_size; /* header_version 4 and later */
uint64_t offset_eraseinfo; /* header_version 5 and later */
uint64_t size_eraseinfo; /* header_version 5 and later */
uint64_t start_pfn_64; /* header_version 6 and later */
uint64_t end_pfn_64; /* header_version 6 and later */
uint64_t max_mapnr_64; /* header_version 6 and later */
} KdumpSubHeader64;
typedef struct DataCache {
int fd; /* fd of the file where to write the cached data */
uint8_t *buf; /* buffer for cached data */
size_t buf_size; /* size of the buf */
size_t data_size; /* size of cached data in buf */
off_t offset; /* offset of the file */
} DataCache;
typedef struct QEMU_PACKED PageDescriptor {
uint64_t offset; /* the offset of the page data*/
uint32_t size; /* the size of this dump page */
uint32_t flags; /* flags */
uint64_t page_flags; /* page flags */
} PageDescriptor;
struct GuestPhysBlockList; /* memory_mapping.h */
int cpu_get_dump_info(ArchDumpInfo *info,
const struct GuestPhysBlockList *guest_phys_blocks);

View File

@ -2021,10 +2021,6 @@ int64_t dev_time;
static void do_info_profile(Monitor *mon, const QDict *qdict)
{
int64_t total;
total = qemu_time;
if (total == 0)
total = 1;
monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n",
dev_time, dev_time / (double)get_ticks_per_sec());
monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n",

View File

@ -2794,6 +2794,24 @@
##
{ 'command': 'device_del', 'data': {'id': 'str'} }
##
# @DumpGuestMemoryFormat:
#
# An enumeration of guest-memory-dump's format.
#
# @elf: elf format
#
# @kdump-zlib: kdump-compressed format with zlib-compressed
#
# @kdump-lzo: kdump-compressed format with lzo-compressed
#
# @kdump-snappy: kdump-compressed format with snappy-compressed
#
# Since: 2.0
##
{ 'enum': 'DumpGuestMemoryFormat',
'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy' ] }
##
# @dump-guest-memory
#
@ -2830,13 +2848,42 @@
# want to dump all guest's memory, please specify the start @begin
# and @length
#
# @format: #optional if specified, the format of guest memory dump. But non-elf
# format is conflict with paging and filter, ie. @paging, @begin and
# @length is not allowed to be specified with non-elf @format at the
# same time (since 2.0)
#
# Returns: nothing on success
#
# Since: 1.2
##
{ 'command': 'dump-guest-memory',
'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
'*length': 'int' } }
'*length': 'int', '*format': 'DumpGuestMemoryFormat' } }
##
# @DumpGuestMemoryCapability:
#
# A list of the available formats for dump-guest-memory
#
# Since: 2.0
##
{ 'type': 'DumpGuestMemoryCapability',
'data': {
'formats': ['DumpGuestMemoryFormat'] } }
##
# @query-dump-guest-memory-capability:
#
# Returns the available formats for dump-guest-memory
#
# Returns: A @DumpGuestMemoryCapability object listing available formats for
# dump-guest-memory
#
# Since: 2.0
##
{ 'command': 'query-dump-guest-memory-capability',
'returns': 'DumpGuestMemoryCapability' }
##
# @netdev_add:

View File

@ -124,7 +124,9 @@ opts_start_struct(Visitor *v, void **obj, const char *kind,
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
const QemuOpt *opt;
*obj = g_malloc0(size > 0 ? size : 1);
if (obj) {
*obj = g_malloc0(size > 0 ? size : 1);
}
if (ov->depth++ > 0) {
return;
}

View File

@ -131,9 +131,7 @@ static void qapi_dealloc_end_list(Visitor *v, Error **errp)
static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
Error **errp)
{
if (obj) {
g_free(*obj);
}
g_free(*obj);
}
static void qapi_dealloc_type_int(Visitor *v, int64_t *obj, const char *name,

View File

@ -791,8 +791,8 @@ EQMP
{
.name = "dump-guest-memory",
.args_type = "paging:b,protocol:s,begin:i?,end:i?",
.params = "-p protocol [begin] [length]",
.args_type = "paging:b,protocol:s,begin:i?,end:i?,format:s?",
.params = "-p protocol [begin] [length] [format]",
.help = "dump guest memory to file",
.user_print = monitor_user_noop,
.mhandler.cmd_new = qmp_marshal_input_dump_guest_memory,
@ -813,6 +813,9 @@ Arguments:
with length together (json-int)
- "length": the memory size, in bytes. It's optional, and should be specified
with begin together (json-int)
- "format": the format of guest memory dump. It's optional, and can be
elf|kdump-zlib|kdump-lzo|kdump-snappy, but non-elf formats will
conflict with paging and filter, ie. begin and length (json-string)
Example:
@ -823,6 +826,26 @@ Notes:
(1) All boolean arguments default to false
EQMP
{
.name = "query-dump-guest-memory-capability",
.args_type = "",
.mhandler.cmd_new = qmp_marshal_input_query_dump_guest_memory_capability,
},
SQMP
query-dump-guest-memory-capability
----------
Show available formats for 'dump-guest-memory'
Example:
-> { "execute": "query-dump-guest-memory-capability" }
<- { "return": { "formats":
["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] }
EQMP
{

View File

@ -7,8 +7,8 @@
# Anthony Liguori <aliguori@us.ibm.com>
# Michael Roth <mdroth@linux.vnet.ibm.com>
#
# This work is licensed under the terms of the GNU GPLv2.
# See the COPYING.LIB file in the top-level directory.
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
from ordereddict import OrderedDict
from qapi import *
@ -23,13 +23,6 @@ def type_visitor(name):
else:
return 'visit_type_%s' % name
def generate_decl_enum(name, members, genlist=True):
return mcgen('''
void %(visitor)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
''',
visitor=type_visitor(name))
def generate_command_decl(name, args, ret_type):
arglist=""
for argname, argtype, optional, structured in parse_args(args):
@ -76,19 +69,6 @@ def gen_marshal_output_call(name, ret_type):
return ""
return "qmp_marshal_output_%s(retval, ret, errp);" % c_fun(name)
def gen_visitor_output_containers_decl(ret_type):
ret = ""
push_indent()
if ret_type:
ret += mcgen('''
QmpOutputVisitor *mo;
QapiDeallocVisitor *md;
Visitor *v;
''')
pop_indent()
return ret
def gen_visitor_input_containers_decl(args):
ret = ""

View File

@ -6,8 +6,8 @@
# Authors:
# Anthony Liguori <aliguori@us.ibm.com>
#
# This work is licensed under the terms of the GNU GPLv2.
# See the COPYING.LIB file in the top-level directory.
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
from ordereddict import OrderedDict
from qapi import *

View File

@ -7,8 +7,8 @@
# Anthony Liguori <aliguori@us.ibm.com>
# Michael Roth <mdroth@linux.vnet.ibm.com>
#
# This work is licensed under the terms of the GNU GPLv2.
# See the COPYING.LIB file in the top-level directory.
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
from ordereddict import OrderedDict
from qapi import *
@ -47,9 +47,9 @@ static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error *
if base:
ret += mcgen('''
visit_start_implicit_struct(m, obj ? (void**) &(*obj)->%(c_name)s : NULL, sizeof(%(type)s), &err);
visit_start_implicit_struct(m, (void**) &(*obj)->%(c_name)s, sizeof(%(type)s), &err);
if (!err) {
visit_type_%(type)s_fields(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, &err);
visit_type_%(type)s_fields(m, &(*obj)->%(c_prefix)s%(c_name)s, &err);
error_propagate(errp, err);
err = NULL;
visit_end_implicit_struct(m, &err);
@ -61,8 +61,8 @@ if (!err) {
for argname, argentry, optional, structured in parse_args(members):
if optional:
ret += mcgen('''
visit_start_optional(m, obj ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", &err);
if (obj && (*obj)->%(prefix)shas_%(c_name)s) {
visit_start_optional(m, &(*obj)->%(c_prefix)shas_%(c_name)s, "%(name)s", &err);
if ((*obj)->%(prefix)shas_%(c_name)s) {
''',
c_prefix=c_var(field_prefix), prefix=field_prefix,
c_name=c_var(argname), name=argname)
@ -72,7 +72,7 @@ if (obj && (*obj)->%(prefix)shas_%(c_name)s) {
ret += generate_visit_struct_body(full_name, argname, argentry)
else:
ret += mcgen('''
visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", &err);
visit_type_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, "%(name)s", &err);
''',
c_prefix=c_var(field_prefix), prefix=field_prefix,
type=type_name(argentry), c_name=c_var(argname),
@ -121,7 +121,7 @@ visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
ret += mcgen('''
if (!err) {
if (!obj || *obj) {
if (*obj) {
visit_type_%(name)s_fields(m, obj, &err);
error_propagate(errp, err);
err = NULL;
@ -273,7 +273,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
if (!error_is_set(errp)) {
visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
if (!err) {
if (obj && *obj) {
if (*obj) {
''',
name=name)
@ -494,10 +494,8 @@ fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
# have the functions defined, so we use -b option to provide control
# over these cases
if do_builtins:
fdef.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DEF"))
for typename in builtin_types:
fdef.write(generate_visit_list(typename, None))
fdef.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DEF"))
for expr in exprs:
if expr.has_key('type'):

View File

@ -8,8 +8,8 @@
# Anthony Liguori <aliguori@us.ibm.com>
# Markus Armbruster <armbru@redhat.com>
#
# This work is licensed under the terms of the GNU GPLv2.
# See the COPYING.LIB file in the top-level directory.
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
from ordereddict import OrderedDict
import sys

View File

@ -112,13 +112,29 @@ class QMPShell(qmp.QEMUMonitorProtocol):
value = json.loads(opt[1])
else:
value = opt[1]
qmpcmd['arguments'][opt[0]] = value
optpath = opt[0].split('.')
parent = qmpcmd['arguments']
curpath = []
for p in optpath[:-1]:
curpath.append(p)
d = parent.get(p, {})
if type(d) is not dict:
raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath))
parent[p] = d
parent = d
if optpath[-1] in parent:
if type(parent[optpath[-1]]) is dict:
raise QMPShellError('Cannot use "%s" as both leaf and non-leaf key' % '.'.join(curpath))
else:
raise QMPShellError('Cannot set "%s" multiple times' % opt[0])
parent[optpath[-1]] = value
return qmpcmd
def _execute_cmd(self, cmdline):
try:
qmpcmd = self.__build_cmd(cmdline)
except:
except Exception, e:
print 'Error while parsing command line: %s' % e
print 'command format: <command-name> ',
print '[arg-name1=arg1] ... [arg-nameN=argN]'
return True

View File

@ -171,7 +171,12 @@ class QEMUMonitorProtocol:
pass
self.__sock.setblocking(1)
if not self.__events and wait:
self.__json_read(only_event=True)
ret = self.__json_read(only_event=True)
if ret == None:
# We are in blocking mode, if don't get anything, something
# went wrong
raise QMPConnectError("Error while reading from socket")
return self.__events
def clear_events(self):

View File

@ -38,8 +38,10 @@
#ifdef TARGET_X86_64
#define ELF_MACHINE EM_X86_64
#define ELF_MACHINE_UNAME "x86_64"
#else
#define ELF_MACHINE EM_386
#define ELF_MACHINE_UNAME "i686"
#endif
#define CPUArchState struct CPUX86State

View File

@ -28,6 +28,7 @@
#define TARGET_LONG_BITS 64
#define ELF_MACHINE EM_S390
#define ELF_MACHINE_UNAME "S390X"
#define CPUArchState struct CPUS390XState

View File

@ -7,8 +7,12 @@
'data': { 'enum1': 'EnumOne', '*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } }
# for testing nested structs
{ 'type': 'UserDefZero',
'data': { 'integer': 'int' } }
{ 'type': 'UserDefOne',
'data': { 'integer': 'int', 'string': 'str', '*enum1': 'EnumOne' } }
'base': 'UserDefZero',
'data': { 'string': 'str', '*enum1': 'EnumOne' } }
{ 'type': 'UserDefTwo',
'data': { 'string': 'str',
@ -30,8 +34,20 @@
'data': { 'integer': 'int' } }
{ 'union': 'UserDefUnion',
'base': 'UserDefZero',
'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } }
{ 'union': 'UserDefFlatUnion',
'base': 'UserDefOne',
'discriminator': 'string',
'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } }
# FIXME generated struct UserDefFlatUnion has members for direct base
# UserDefOne, but lacks members for indirect base UserDefZero
{ 'union': 'UserDefAnonUnion',
'discriminator': {},
'data': { 'uda': 'UserDefA', 's': 'str', 'i': 'int' } }
# for testing native lists
{ 'union': 'UserDefNativeListUnion',
'data': { 'integer': ['int'],
@ -50,7 +66,11 @@
# testing commands
{ 'command': 'user_def_cmd', 'data': {} }
{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
{ 'command': 'user_def_cmd2', 'data': {'ud1a': 'UserDefOne', 'ud1b': 'UserDefOne'}, 'returns': 'UserDefTwo' }
{ 'command': 'user_def_cmd2',
'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'},
'returns': 'UserDefTwo' }
{ 'command': 'user_def_cmd3', 'data': {'a': 'int', '*b': 'int' },
'returns': 'int' }
# For testing integer range flattening in opts-visitor. The following schema
# corresponds to the option format:

View File

@ -1,19 +1,28 @@
[OrderedDict([('enum', 'EnumOne'), ('data', ['value1', 'value2', 'value3'])]),
OrderedDict([('type', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]),
OrderedDict([('type', 'UserDefOne'), ('data', OrderedDict([('integer', 'int'), ('string', 'str'), ('*enum1', 'EnumOne')]))]),
OrderedDict([('type', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]),
OrderedDict([('type', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]),
OrderedDict([('type', 'UserDefTwo'), ('data', OrderedDict([('string', 'str'), ('dict', OrderedDict([('string', 'str'), ('dict', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')])), ('*dict2', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]))]))]),
OrderedDict([('type', 'UserDefNested'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef1', 'UserDefOne'), ('string2', 'str')])), ('*dict3', OrderedDict([('userdef2', 'UserDefOne'), ('string3', 'str')]))]))]))]),
OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
OrderedDict([('union', 'UserDefUnion'), ('data', OrderedDict([('a', 'UserDefA'), ('b', 'UserDefB')]))]),
OrderedDict([('union', 'UserDefUnion'), ('base', 'UserDefZero'), ('data', OrderedDict([('a', 'UserDefA'), ('b', 'UserDefB')]))]),
OrderedDict([('union', 'UserDefFlatUnion'), ('base', 'UserDefOne'), ('discriminator', 'string'), ('data', OrderedDict([('a', 'UserDefA'), ('b', 'UserDefB')]))]),
OrderedDict([('union', 'UserDefAnonUnion'), ('discriminator', OrderedDict()), ('data', OrderedDict([('uda', 'UserDefA'), ('s', 'str'), ('i', 'int')]))]),
OrderedDict([('union', 'UserDefNativeListUnion'), ('data', OrderedDict([('integer', ['int']), ('s8', ['int8']), ('s16', ['int16']), ('s32', ['int32']), ('s64', ['int64']), ('u8', ['uint8']), ('u16', ['uint16']), ('u32', ['uint32']), ('u64', ['uint64']), ('number', ['number']), ('boolean', ['bool']), ('string', ['str'])]))]),
OrderedDict([('command', 'user_def_cmd'), ('data', OrderedDict())]),
OrderedDict([('command', 'user_def_cmd1'), ('data', OrderedDict([('ud1a', 'UserDefOne')]))]),
OrderedDict([('command', 'user_def_cmd2'), ('data', OrderedDict([('ud1a', 'UserDefOne'), ('ud1b', 'UserDefOne')])), ('returns', 'UserDefTwo')]),
OrderedDict([('command', 'user_def_cmd2'), ('data', OrderedDict([('ud1a', 'UserDefOne'), ('*ud1b', 'UserDefOne')])), ('returns', 'UserDefTwo')]),
OrderedDict([('command', 'user_def_cmd3'), ('data', OrderedDict([('a', 'int'), ('*b', 'int')])), ('returns', 'int')]),
OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])]
['EnumOne', 'UserDefUnionKind', 'UserDefNativeListUnionKind']
['EnumOne',
'UserDefUnionKind',
'UserDefFlatUnionKind',
'UserDefAnonUnionKind',
'UserDefNativeListUnionKind']
[OrderedDict([('type', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]),
OrderedDict([('type', 'UserDefOne'), ('data', OrderedDict([('integer', 'int'), ('string', 'str'), ('*enum1', 'EnumOne')]))]),
OrderedDict([('type', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]),
OrderedDict([('type', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]),
OrderedDict([('type', 'UserDefTwo'), ('data', OrderedDict([('string', 'str'), ('dict', OrderedDict([('string', 'str'), ('dict', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')])), ('*dict2', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]))]))]),
OrderedDict([('type', 'UserDefNested'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef1', 'UserDefOne'), ('string2', 'str')])), ('*dict3', OrderedDict([('userdef2', 'UserDefOne'), ('string3', 'str')]))]))]))]),
OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),

View File

@ -16,16 +16,20 @@ void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
{
}
UserDefTwo * qmp_user_def_cmd2(UserDefOne * ud1a, UserDefOne * ud1b, Error **errp)
UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
bool has_udb1, UserDefOne *ud1b,
Error **errp)
{
UserDefTwo *ret;
UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
ud1c->string = strdup(ud1a->string);
ud1c->integer = ud1a->integer;
ud1d->string = strdup(ud1b->string);
ud1d->integer = ud1b->integer;
ud1c->base = g_new0(UserDefZero, 1);
ud1c->base->integer = ud1a->base->integer;
ud1d->string = strdup(has_udb1 ? ud1b->string : "blah0");
ud1d->base = g_new0(UserDefZero, 1);
ud1d->base->integer = has_udb1 ? ud1b->base->integer : 0;
ret = g_malloc0(sizeof(UserDefTwo));
ret->string = strdup("blah1");
@ -39,6 +43,11 @@ UserDefTwo * qmp_user_def_cmd2(UserDefOne * ud1a, UserDefOne * ud1b, Error **err
return ret;
}
int64_t qmp_user_def_cmd3(int64_t a, bool has_b, int64_t b, Error **errp)
{
return a + (has_b ? b : 0);
}
/* test commands with no input and no return value */
static void test_dispatch_cmd(void)
{
@ -71,14 +80,34 @@ static void test_dispatch_cmd_error(void)
QDECREF(req);
}
static QObject *test_qmp_dispatch(QDict *req)
{
QObject *resp_obj;
QDict *resp;
QObject *ret;
resp_obj = qmp_dispatch(QOBJECT(req));
assert(resp_obj);
resp = qobject_to_qdict(resp_obj);
assert(resp && !qdict_haskey(resp, "error"));
ret = qdict_get(resp, "return");
assert(ret);
qobject_incref(ret);
qobject_decref(resp_obj);
return ret;
}
/* test commands that involve both input parameters and return values */
static void test_dispatch_cmd_io(void)
{
QDict *req = qdict_new();
QDict *args = qdict_new();
QDict *args3 = qdict_new();
QDict *ud1a = qdict_new();
QDict *ud1b = qdict_new();
QObject *resp;
QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
QInt *ret3;
qdict_put_obj(ud1a, "integer", QOBJECT(qint_from_int(42)));
qdict_put_obj(ud1a, "string", QOBJECT(qstring_from_str("hello")));
@ -87,15 +116,33 @@ static void test_dispatch_cmd_io(void)
qdict_put_obj(args, "ud1a", QOBJECT(ud1a));
qdict_put_obj(args, "ud1b", QOBJECT(ud1b));
qdict_put_obj(req, "arguments", QOBJECT(args));
qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
/* TODO: put in full payload and check for errors */
resp = qmp_dispatch(QOBJECT(req));
assert(resp != NULL);
assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
ret = qobject_to_qdict(test_qmp_dispatch(req));
assert(!strcmp(qdict_get_str(ret, "string"), "blah1"));
ret_dict = qdict_get_qdict(ret, "dict");
assert(!strcmp(qdict_get_str(ret_dict, "string"), "blah2"));
ret_dict_dict = qdict_get_qdict(ret_dict, "dict");
ret_dict_dict_userdef = qdict_get_qdict(ret_dict_dict, "userdef");
assert(qdict_get_int(ret_dict_dict_userdef, "integer") == 42);
assert(!strcmp(qdict_get_str(ret_dict_dict_userdef, "string"), "hello"));
assert(!strcmp(qdict_get_str(ret_dict_dict, "string"), "blah3"));
ret_dict_dict2 = qdict_get_qdict(ret_dict, "dict2");
ret_dict_dict2_userdef = qdict_get_qdict(ret_dict_dict2, "userdef");
assert(qdict_get_int(ret_dict_dict2_userdef, "integer") == 422);
assert(!strcmp(qdict_get_str(ret_dict_dict2_userdef, "string"), "hello2"));
assert(!strcmp(qdict_get_str(ret_dict_dict2, "string"), "blah4"));
QDECREF(ret);
qdict_put(args3, "a", qint_from_int(66));
qdict_put(req, "arguments", args3);
qdict_put(req, "execute", qstring_from_str("user_def_cmd3"));
ret3 = qobject_to_qint(test_qmp_dispatch(req));
assert(qint_get_int(ret3) == 66);
QDECREF(ret);
qobject_decref(resp);
QDECREF(req);
}
@ -106,17 +153,20 @@ static void test_dealloc_types(void)
UserDefOneList *ud1list;
ud1test = g_malloc0(sizeof(UserDefOne));
ud1test->integer = 42;
ud1test->base = g_new0(UserDefZero, 1);
ud1test->base->integer = 42;
ud1test->string = g_strdup("hi there 42");
qapi_free_UserDefOne(ud1test);
ud1a = g_malloc0(sizeof(UserDefOne));
ud1a->integer = 43;
ud1a->base = g_new0(UserDefZero, 1);
ud1a->base->integer = 43;
ud1a->string = g_strdup("hi there 43");
ud1b = g_malloc0(sizeof(UserDefOne));
ud1b->integer = 44;
ud1b->base = g_new0(UserDefZero, 1);
ud1b->base->integer = 44;
ud1b->string = g_strdup("hi there 44");
ud1list = g_malloc0(sizeof(UserDefOneList));

View File

@ -132,13 +132,42 @@ static void test_validate_union(TestInputVisitorData *data,
Visitor *v;
Error *errp = NULL;
v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
v = validate_test_init(data, "{ 'type': 'b', 'integer': 41, 'data' : { 'integer': 42 } }");
visit_type_UserDefUnion(v, &tmp, NULL, &errp);
g_assert(!errp);
qapi_free_UserDefUnion(tmp);
}
static void test_validate_union_flat(TestInputVisitorData *data,
const void *unused)
{
UserDefFlatUnion *tmp = NULL;
Visitor *v;
Error *errp = NULL;
v = validate_test_init(data, "{ 'string': 'a', 'boolean': true }");
/* TODO when generator bug is fixed, add 'integer': 41 */
visit_type_UserDefFlatUnion(v, &tmp, NULL, &errp);
g_assert(!error_is_set(&errp));
qapi_free_UserDefFlatUnion(tmp);
}
static void test_validate_union_anon(TestInputVisitorData *data,
const void *unused)
{
UserDefAnonUnion *tmp = NULL;
Visitor *v;
Error *errp = NULL;
v = validate_test_init(data, "42");
visit_type_UserDefAnonUnion(v, &tmp, NULL, &errp);
g_assert(!error_is_set(&errp));
qapi_free_UserDefAnonUnion(tmp);
}
static void test_validate_fail_struct(TestInputVisitorData *data,
const void *unused)
{
@ -191,13 +220,41 @@ static void test_validate_fail_union(TestInputVisitorData *data,
Error *errp = NULL;
Visitor *v;
v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }");
v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
visit_type_UserDefUnion(v, &tmp, NULL, &errp);
g_assert(errp);
qapi_free_UserDefUnion(tmp);
}
static void test_validate_fail_union_flat(TestInputVisitorData *data,
const void *unused)
{
UserDefFlatUnion *tmp = NULL;
Error *errp = NULL;
Visitor *v;
v = validate_test_init(data, "{ 'string': 'c', 'integer': 41, 'boolean': true }");
visit_type_UserDefFlatUnion(v, &tmp, NULL, &errp);
g_assert(error_is_set(&errp));
qapi_free_UserDefFlatUnion(tmp);
}
static void test_validate_fail_union_anon(TestInputVisitorData *data,
const void *unused)
{
UserDefAnonUnion *tmp = NULL;
Visitor *v;
Error *errp = NULL;
v = validate_test_init(data, "3.14");
visit_type_UserDefAnonUnion(v, &tmp, NULL, &errp);
g_assert(error_is_set(&errp));
qapi_free_UserDefAnonUnion(tmp);
}
static void validate_test_add(const char *testpath,
TestInputVisitorData *data,
void (*test_func)(TestInputVisitorData *data, const void *user_data))
@ -220,6 +277,10 @@ int main(int argc, char **argv)
&testdata, test_validate_list);
validate_test_add("/visitor/input-strict/pass/union",
&testdata, test_validate_union);
validate_test_add("/visitor/input-strict/pass/union-flat",
&testdata, test_validate_union_flat);
validate_test_add("/visitor/input-strict/pass/union-anon",
&testdata, test_validate_union_anon);
validate_test_add("/visitor/input-strict/fail/struct",
&testdata, test_validate_fail_struct);
validate_test_add("/visitor/input-strict/fail/struct-nested",
@ -228,6 +289,10 @@ int main(int argc, char **argv)
&testdata, test_validate_fail_list);
validate_test_add("/visitor/input-strict/fail/union",
&testdata, test_validate_fail_union);
validate_test_add("/visitor/input-strict/fail/union-flat",
&testdata, test_validate_fail_union_flat);
validate_test_add("/visitor/input-strict/fail/union-anon",
&testdata, test_validate_fail_union_anon);
g_test_run();

View File

@ -252,7 +252,7 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
check_and_free_str(udp->string0, "string0");
check_and_free_str(udp->dict1.string1, "string1");
g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
g_assert_cmpint(udp->dict1.dict2.userdef1->base->integer, ==, 42);
check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
check_and_free_str(udp->dict1.dict2.string2, "string2");
g_assert(udp->dict1.has_dict3 == false);
@ -280,7 +280,7 @@ static void test_visitor_in_list(TestInputVisitorData *data,
snprintf(string, sizeof(string), "string%d", i);
g_assert_cmpstr(item->value->string, ==, string);
g_assert_cmpint(item->value->integer, ==, 42 + i);
g_assert_cmpint(item->value->base->integer, ==, 42 + i);
}
qapi_free_UserDefOneList(head);
@ -293,15 +293,50 @@ static void test_visitor_in_union(TestInputVisitorData *data,
Error *err = NULL;
UserDefUnion *tmp;
v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
v = visitor_input_test_init(data, "{ 'type': 'b', 'integer': 41, 'data' : { 'integer': 42 } }");
visit_type_UserDefUnion(v, &tmp, NULL, &err);
g_assert(err == NULL);
g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B);
g_assert_cmpint(tmp->integer, ==, 41);
g_assert_cmpint(tmp->b->integer, ==, 42);
qapi_free_UserDefUnion(tmp);
}
static void test_visitor_in_union_flat(TestInputVisitorData *data,
const void *unused)
{
Visitor *v;
Error *err = NULL;
UserDefFlatUnion *tmp;
v = visitor_input_test_init(data, "{ 'string': 'a', 'boolean': true }");
/* TODO when generator bug is fixed, add 'integer': 41 */
visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
g_assert(err == NULL);
g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_A);
/* TODO g_assert_cmpint(tmp->integer, ==, 41); */
g_assert_cmpint(tmp->a->boolean, ==, true);
qapi_free_UserDefFlatUnion(tmp);
}
static void test_visitor_in_union_anon(TestInputVisitorData *data,
const void *unused)
{
Visitor *v;
Error *err = NULL;
UserDefAnonUnion *tmp;
v = visitor_input_test_init(data, "42");
visit_type_UserDefAnonUnion(v, &tmp, NULL, &err);
g_assert(err == NULL);
g_assert_cmpint(tmp->kind, ==, USER_DEF_ANON_UNION_KIND_I);
g_assert_cmpint(tmp->i, ==, 42);
qapi_free_UserDefAnonUnion(tmp);
}
static void test_native_list_integer_helper(TestInputVisitorData *data,
const void *unused,
UserDefNativeListUnionKind kind)
@ -635,6 +670,10 @@ int main(int argc, char **argv)
&in_visitor_data, test_visitor_in_list);
input_visitor_test_add("/visitor/input/union",
&in_visitor_data, test_visitor_in_union);
input_visitor_test_add("/visitor/input/union-flat",
&in_visitor_data, test_visitor_in_union_flat);
input_visitor_test_add("/visitor/input/union-anon",
&in_visitor_data, test_visitor_in_union_anon);
input_visitor_test_add("/visitor/input/errors",
&in_visitor_data, test_visitor_in_errors);
input_visitor_test_add("/visitor/input/native_list/int",

View File

@ -231,13 +231,15 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
ud2->dict1.string1 = g_strdup(strings[1]);
ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
ud2->dict1.dict2.userdef1->string = g_strdup(string);
ud2->dict1.dict2.userdef1->integer = value;
ud2->dict1.dict2.userdef1->base = g_new0(UserDefZero, 1);
ud2->dict1.dict2.userdef1->base->integer = value;
ud2->dict1.dict2.string2 = g_strdup(strings[2]);
ud2->dict1.has_dict3 = true;
ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
ud2->dict1.dict3.userdef2->string = g_strdup(string);
ud2->dict1.dict3.userdef2->integer = value;
ud2->dict1.dict3.userdef2->base = g_new0(UserDefZero, 1);
ud2->dict1.dict3.userdef2->base->integer = value;
ud2->dict1.dict3.string3 = g_strdup(strings[3]);
visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
@ -279,7 +281,8 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
const void *unused)
{
EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
UserDefOne u = { 0 }, *pu = &u;
UserDefZero b;
UserDefOne u = { .base = &b }, *pu = &u;
Error *errp;
int i;
@ -391,7 +394,8 @@ static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
p->value->dict1.string1 = g_strdup(string);
p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
p->value->dict1.dict2.userdef1->string = g_strdup(string);
p->value->dict1.dict2.userdef1->integer = 42;
p->value->dict1.dict2.userdef1->base = g_new0(UserDefZero, 1);
p->value->dict1.dict2.userdef1->base->integer = 42;
p->value->dict1.dict2.string2 = g_strdup(string);
p->value->dict1.has_dict3 = false;
@ -412,6 +416,7 @@ static void test_visitor_out_union(TestOutputVisitorData *data,
UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion));
tmp->kind = USER_DEF_UNION_KIND_A;
tmp->integer = 41;
tmp->a = g_malloc0(sizeof(UserDefA));
tmp->a->boolean = true;
@ -423,6 +428,7 @@ static void test_visitor_out_union(TestOutputVisitorData *data,
qdict = qobject_to_qdict(arg);
g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a");
g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41);
qvalue = qdict_get(qdict, "data");
g_assert(data != NULL);
@ -434,6 +440,55 @@ static void test_visitor_out_union(TestOutputVisitorData *data,
QDECREF(qdict);
}
static void test_visitor_out_union_flat(TestOutputVisitorData *data,
const void *unused)
{
QObject *arg;
QDict *qdict;
Error *err = NULL;
UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion));
tmp->kind = USER_DEF_UNION_KIND_A;
tmp->a = g_malloc0(sizeof(UserDefA));
/* TODO when generator bug is fixed: tmp->integer = 41; */
tmp->a->boolean = true;
visit_type_UserDefFlatUnion(data->ov, &tmp, NULL, &err);
g_assert(err == NULL);
arg = qmp_output_get_qobject(data->qov);
g_assert(qobject_type(arg) == QTYPE_QDICT);
qdict = qobject_to_qdict(arg);
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "a");
/* TODO g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41); */
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
qapi_free_UserDefFlatUnion(tmp);
QDECREF(qdict);
}
static void test_visitor_out_union_anon(TestOutputVisitorData *data,
const void *unused)
{
QObject *arg;
Error *err = NULL;
UserDefAnonUnion *tmp = g_malloc0(sizeof(UserDefAnonUnion));
tmp->kind = USER_DEF_ANON_UNION_KIND_I;
tmp->i = 42;
visit_type_UserDefAnonUnion(data->ov, &tmp, NULL, &err);
g_assert(err == NULL);
arg = qmp_output_get_qobject(data->qov);
g_assert(qobject_type(arg) == QTYPE_QINT);
g_assert_cmpint(qint_get_int(qobject_to_qint(arg)), ==, 42);
qapi_free_UserDefAnonUnion(tmp);
}
static void init_native_list(UserDefNativeListUnion *cvalue)
{
int i;
@ -782,6 +837,10 @@ int main(int argc, char **argv)
&out_visitor_data, test_visitor_out_list_qapi_free);
output_visitor_test_add("/visitor/output/union",
&out_visitor_data, test_visitor_out_union);
output_visitor_test_add("/visitor/output/union-flat",
&out_visitor_data, test_visitor_out_union_flat);
output_visitor_test_add("/visitor/output/union-anon",
&out_visitor_data, test_visitor_out_union_anon);
output_visitor_test_add("/visitor/output/native_list/int",
&out_visitor_data, test_visitor_out_native_list_int);
output_visitor_test_add("/visitor/output/native_list/int8",

View File

@ -239,12 +239,14 @@ static UserDefNested *nested_struct_create(void)
udnp->string0 = strdup("test_string0");
udnp->dict1.string1 = strdup("test_string1");
udnp->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
udnp->dict1.dict2.userdef1->integer = 42;
udnp->dict1.dict2.userdef1->base = g_new0(UserDefZero, 1);
udnp->dict1.dict2.userdef1->base->integer = 42;
udnp->dict1.dict2.userdef1->string = strdup("test_string");
udnp->dict1.dict2.string2 = strdup("test_string2");
udnp->dict1.has_dict3 = true;
udnp->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
udnp->dict1.dict3.userdef2->integer = 43;
udnp->dict1.dict3.userdef2->base = g_new0(UserDefZero, 1);
udnp->dict1.dict3.userdef2->base->integer = 43;
udnp->dict1.dict3.userdef2->string = strdup("test_string");
udnp->dict1.dict3.string3 = strdup("test_string3");
return udnp;
@ -256,14 +258,14 @@ static void nested_struct_compare(UserDefNested *udnp1, UserDefNested *udnp2)
g_assert(udnp2);
g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
g_assert_cmpstr(udnp1->dict1.string1, ==, udnp2->dict1.string1);
g_assert_cmpint(udnp1->dict1.dict2.userdef1->integer, ==,
udnp2->dict1.dict2.userdef1->integer);
g_assert_cmpint(udnp1->dict1.dict2.userdef1->base->integer, ==,
udnp2->dict1.dict2.userdef1->base->integer);
g_assert_cmpstr(udnp1->dict1.dict2.userdef1->string, ==,
udnp2->dict1.dict2.userdef1->string);
g_assert_cmpstr(udnp1->dict1.dict2.string2, ==, udnp2->dict1.dict2.string2);
g_assert(udnp1->dict1.has_dict3 == udnp2->dict1.has_dict3);
g_assert_cmpint(udnp1->dict1.dict3.userdef2->integer, ==,
udnp2->dict1.dict3.userdef2->integer);
g_assert_cmpint(udnp1->dict1.dict3.userdef2->base->integer, ==,
udnp2->dict1.dict3.userdef2->base->integer);
g_assert_cmpstr(udnp1->dict1.dict3.userdef2->string, ==,
udnp2->dict1.dict3.userdef2->string);
g_assert_cmpstr(udnp1->dict1.dict3.string3, ==, udnp2->dict1.dict3.string3);