mirror of https://github.com/xemu-project/xemu.git
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:
commit
e00ef747f0
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
5
hmp.c
5
hmp.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
{
|
||||
|
|
|
@ -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 = ""
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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'):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define TARGET_LONG_BITS 64
|
||||
|
||||
#define ELF_MACHINE EM_S390
|
||||
#define ELF_MACHINE_UNAME "S390X"
|
||||
|
||||
#define CPUArchState struct CPUS390XState
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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')]))]),
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue