mirror of https://github.com/xemu-project/xemu.git
qapi patches for 2018-03-27, 2.12-rc1
- Marc-André Lureau: qmp-test: fix response leak - Eric Blake: tests: Silence false positive warning on generated test name - Laurent Vivier: 0/4 (partial) coccinelle: re-run scripts from scripst/coccinelle - Peter Xu: 0/8 Monitor: some oob related patches (fixes, new param, tests) - Satheesh Rajendran: hmp.c: Revert hmp_info_cpus output format change -----BEGIN PGP SIGNATURE----- Comment: Public key at http://people.redhat.com/eblake/eblake.gpg iQEcBAABCAAGBQJaumDMAAoJEKeha0olJ0NqY34IAJ1AJLZeqtb9HIPDrL/iydXQ qrMPxfz/fbcjMbomYvltvCYB3GMQw88YVtTuu2kS5aZsr6vLhpw2ZjGrb+a0llFM lF6oERg/6VmfQNaeqcHEzORIdG6/GEctxoWS07f+NgSrjdxNNHyU+i/LGvvA5K4m x7akPw3DZIF/oBLDlFgtl80KtOf8vQ8QitCIp2nsURQFLHvjVSoXHGUfhoiUUgNA 89rF62Repq9xZXSsFr+Jpp4/bPGxA717sixXSxFUDuTVIZGnffbt4wVxLi4TKSx1 1Ho6psPK3d82rQ9OeIc6CqulElLMPGn7aNwR1VR6ig0sB409K5PQJybJDqQD/C4= =ld/c -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ericb/tags/pull-qapi-2018-03-27-v2' into staging qapi patches for 2018-03-27, 2.12-rc1 - Marc-André Lureau: qmp-test: fix response leak - Eric Blake: tests: Silence false positive warning on generated test name - Laurent Vivier: 0/4 (partial) coccinelle: re-run scripts from scripst/coccinelle - Peter Xu: 0/8 Monitor: some oob related patches (fixes, new param, tests) - Satheesh Rajendran: hmp.c: Revert hmp_info_cpus output format change # gpg: Signature made Tue 27 Mar 2018 16:18:36 BST # gpg: using RSA key A7A16B4A2527436A # gpg: Good signature from "Eric Blake <eblake@redhat.com>" # gpg: aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" # gpg: aka "[jpeg image of size 6874]" # Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2 F3AA A7A1 6B4A 2527 436A * remotes/ericb/tags/pull-qapi-2018-03-27-v2: hmp.c: Revert hmp_info_cpus output format change tests: qmp-test: add test for new "x-oob" tests: Add parameter to qtest_init_without_qmp_handshake monitor: new parameter "x-oob" qmp: cleanup qmp queues properly tests: add oob-test for qapi-schema tests: let qapi-schema tests detect oob qapi: restrict allow-oob value to be "true" qmp: fix qmp_capabilities error regression qdict: remove useless cast error: Remove NULL checks on error_propagate() calls error: Strip trailing '\n' from error string arguments (again again) tests: Silence false positive warning on generated test name qmp-test: fix response leak Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
f55e88f2ab
11
block/nvme.c
11
block/nvme.c
|
@ -695,12 +695,11 @@ static void nvme_parse_filename(const char *filename, QDict *options,
|
|||
unsigned long ns;
|
||||
const char *slash = strchr(tmp, '/');
|
||||
if (!slash) {
|
||||
qdict_put(options, NVME_BLOCK_OPT_DEVICE,
|
||||
qstring_from_str(tmp));
|
||||
qdict_put_str(options, NVME_BLOCK_OPT_DEVICE, tmp);
|
||||
return;
|
||||
}
|
||||
device = g_strndup(tmp, slash - tmp);
|
||||
qdict_put(options, NVME_BLOCK_OPT_DEVICE, qstring_from_str(device));
|
||||
qdict_put_str(options, NVME_BLOCK_OPT_DEVICE, device);
|
||||
g_free(device);
|
||||
namespace = slash + 1;
|
||||
if (*namespace && qemu_strtoul(namespace, NULL, 10, &ns)) {
|
||||
|
@ -708,8 +707,8 @@ static void nvme_parse_filename(const char *filename, QDict *options,
|
|||
namespace);
|
||||
return;
|
||||
}
|
||||
qdict_put(options, NVME_BLOCK_OPT_NAMESPACE,
|
||||
qstring_from_str(*namespace ? namespace : "1"));
|
||||
qdict_put_str(options, NVME_BLOCK_OPT_NAMESPACE,
|
||||
*namespace ? namespace : "1");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1082,7 +1081,7 @@ static void nvme_refresh_filename(BlockDriverState *bs, QDict *opts)
|
|||
bs->drv->format_name);
|
||||
}
|
||||
|
||||
qdict_put(opts, "driver", qstring_from_str(bs->drv->format_name));
|
||||
qdict_put_str(opts, "driver", bs->drv->format_name);
|
||||
bs->full_open_options = opts;
|
||||
}
|
||||
|
||||
|
|
2
hmp.c
2
hmp.c
|
@ -381,7 +381,7 @@ void hmp_info_cpus(Monitor *mon, const QDict *qdict)
|
|||
|
||||
monitor_printf(mon, "%c CPU #%" PRId64 ":", active,
|
||||
cpu->value->cpu_index);
|
||||
monitor_printf(mon, " thread-id=%" PRId64 "\n", cpu->value->thread_id);
|
||||
monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id);
|
||||
}
|
||||
|
||||
qapi_free_CpuInfoFastList(cpu_list);
|
||||
|
|
|
@ -13,6 +13,7 @@ extern Monitor *cur_mon;
|
|||
#define MONITOR_USE_READLINE 0x02
|
||||
#define MONITOR_USE_CONTROL 0x04
|
||||
#define MONITOR_USE_PRETTY 0x08
|
||||
#define MONITOR_USE_OOB 0x10
|
||||
|
||||
bool monitor_cur_is_qmp(void);
|
||||
|
||||
|
|
|
@ -586,9 +586,7 @@ static gboolean qio_channel_websock_handshake_io(QIOChannel *ioc,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
error_propagate(&wioc->io_err, err);
|
||||
}
|
||||
error_propagate(&wioc->io_err, err);
|
||||
|
||||
trace_qio_channel_websock_handshake_reply(ioc);
|
||||
qio_channel_add_watch(
|
||||
|
|
118
monitor.c
118
monitor.c
|
@ -36,6 +36,7 @@
|
|||
#include "net/slirp.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "chardev/char-io.h"
|
||||
#include "chardev/char-mux.h"
|
||||
#include "ui/qemu-spice.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
@ -234,6 +235,22 @@ static struct {
|
|||
QEMUBH *qmp_respond_bh;
|
||||
} mon_global;
|
||||
|
||||
struct QMPRequest {
|
||||
/* Owner of the request */
|
||||
Monitor *mon;
|
||||
/* "id" field of the request */
|
||||
QObject *id;
|
||||
/* Request object to be handled */
|
||||
QObject *req;
|
||||
/*
|
||||
* Whether we need to resume the monitor afterward. This flag is
|
||||
* used to emulate the old QMP server behavior that the current
|
||||
* command must be completed before execution of the next one.
|
||||
*/
|
||||
bool need_resume;
|
||||
};
|
||||
typedef struct QMPRequest QMPRequest;
|
||||
|
||||
/* QMP checker flags */
|
||||
#define QMP_ACCEPT_UNKNOWNS 1
|
||||
|
||||
|
@ -310,6 +327,38 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
|
|||
}
|
||||
}
|
||||
|
||||
static void qmp_request_free(QMPRequest *req)
|
||||
{
|
||||
qobject_decref(req->id);
|
||||
qobject_decref(req->req);
|
||||
g_free(req);
|
||||
}
|
||||
|
||||
/* Must with the mon->qmp.qmp_queue_lock held */
|
||||
static void monitor_qmp_cleanup_req_queue_locked(Monitor *mon)
|
||||
{
|
||||
while (!g_queue_is_empty(mon->qmp.qmp_requests)) {
|
||||
qmp_request_free(g_queue_pop_head(mon->qmp.qmp_requests));
|
||||
}
|
||||
}
|
||||
|
||||
/* Must with the mon->qmp.qmp_queue_lock held */
|
||||
static void monitor_qmp_cleanup_resp_queue_locked(Monitor *mon)
|
||||
{
|
||||
while (!g_queue_is_empty(mon->qmp.qmp_responses)) {
|
||||
qobject_decref(g_queue_pop_head(mon->qmp.qmp_responses));
|
||||
}
|
||||
}
|
||||
|
||||
static void monitor_qmp_cleanup_queues(Monitor *mon)
|
||||
{
|
||||
qemu_mutex_lock(&mon->qmp.qmp_queue_lock);
|
||||
monitor_qmp_cleanup_req_queue_locked(mon);
|
||||
monitor_qmp_cleanup_resp_queue_locked(mon);
|
||||
qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
|
||||
}
|
||||
|
||||
|
||||
static void monitor_flush_locked(Monitor *mon);
|
||||
|
||||
static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
|
||||
|
@ -701,6 +750,8 @@ static void monitor_data_destroy(Monitor *mon)
|
|||
QDECREF(mon->outbuf);
|
||||
qemu_mutex_destroy(&mon->out_lock);
|
||||
qemu_mutex_destroy(&mon->qmp.qmp_queue_lock);
|
||||
monitor_qmp_cleanup_req_queue_locked(mon);
|
||||
monitor_qmp_cleanup_resp_queue_locked(mon);
|
||||
g_queue_free(mon->qmp.qmp_requests);
|
||||
g_queue_free(mon->qmp.qmp_responses);
|
||||
}
|
||||
|
@ -1203,8 +1254,14 @@ static bool qmp_cmd_oob_check(Monitor *mon, QDict *req, Error **errp)
|
|||
|
||||
cmd = qmp_find_command(mon->qmp.commands, command);
|
||||
if (!cmd) {
|
||||
error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
|
||||
"The command %s has not been found", command);
|
||||
if (mon->qmp.commands == &qmp_cap_negotiation_commands) {
|
||||
error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
|
||||
"Expecting capabilities negotiation "
|
||||
"with 'qmp_capabilities'");
|
||||
} else {
|
||||
error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
|
||||
"The command %s has not been found", command);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4003,22 +4060,6 @@ static void monitor_qmp_respond(Monitor *mon, QObject *rsp,
|
|||
qobject_decref(rsp);
|
||||
}
|
||||
|
||||
struct QMPRequest {
|
||||
/* Owner of the request */
|
||||
Monitor *mon;
|
||||
/* "id" field of the request */
|
||||
QObject *id;
|
||||
/* Request object to be handled */
|
||||
QObject *req;
|
||||
/*
|
||||
* Whether we need to resume the monitor afterward. This flag is
|
||||
* used to emulate the old QMP server behavior that the current
|
||||
* command must be completed before execution of the next one.
|
||||
*/
|
||||
bool need_resume;
|
||||
};
|
||||
typedef struct QMPRequest QMPRequest;
|
||||
|
||||
/*
|
||||
* Dispatch one single QMP request. The function will free the req_obj
|
||||
* and objects inside it before return.
|
||||
|
@ -4027,7 +4068,6 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj)
|
|||
{
|
||||
Monitor *mon, *old_mon;
|
||||
QObject *req, *rsp = NULL, *id;
|
||||
QDict *qdict = NULL;
|
||||
bool need_resume;
|
||||
|
||||
req = req_obj->req;
|
||||
|
@ -4050,18 +4090,6 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj)
|
|||
|
||||
cur_mon = old_mon;
|
||||
|
||||
if (mon->qmp.commands == &qmp_cap_negotiation_commands) {
|
||||
qdict = qdict_get_qdict(qobject_to(QDict, rsp), "error");
|
||||
if (qdict
|
||||
&& !g_strcmp0(qdict_get_try_str(qdict, "class"),
|
||||
QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) {
|
||||
/* Provide a more useful error message */
|
||||
qdict_del(qdict, "desc");
|
||||
qdict_put_str(qdict, "desc", "Expecting capabilities negotiation"
|
||||
" with 'qmp_capabilities'");
|
||||
}
|
||||
}
|
||||
|
||||
/* Respond if necessary */
|
||||
monitor_qmp_respond(mon, rsp, NULL, id);
|
||||
|
||||
|
@ -4198,9 +4226,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
|
|||
qapi_event_send_command_dropped(id,
|
||||
COMMAND_DROP_REASON_QUEUE_FULL,
|
||||
&error_abort);
|
||||
qobject_decref(id);
|
||||
qobject_decref(req);
|
||||
g_free(req_obj);
|
||||
qmp_request_free(req_obj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -4315,7 +4341,7 @@ static QObject *get_qmp_greeting(Monitor *mon)
|
|||
/* Monitors that are not using IOThread won't support OOB */
|
||||
continue;
|
||||
}
|
||||
qlist_append(cap_list, qstring_from_str(QMPCapability_str(cap)));
|
||||
qlist_append_str(cap_list, QMPCapability_str(cap));
|
||||
}
|
||||
|
||||
return qobject_from_jsonf("{'QMP': {'version': %p, 'capabilities': %p}}",
|
||||
|
@ -4342,6 +4368,7 @@ static void monitor_qmp_event(void *opaque, int event)
|
|||
mon_refcount++;
|
||||
break;
|
||||
case CHR_EVENT_CLOSED:
|
||||
monitor_qmp_cleanup_queues(mon);
|
||||
json_message_parser_destroy(&mon->qmp.parser);
|
||||
json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
|
||||
mon_refcount--;
|
||||
|
@ -4536,12 +4563,26 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
|
|||
void monitor_init(Chardev *chr, int flags)
|
||||
{
|
||||
Monitor *mon = g_malloc(sizeof(*mon));
|
||||
bool use_readline = flags & MONITOR_USE_READLINE;
|
||||
bool use_oob = flags & MONITOR_USE_OOB;
|
||||
|
||||
monitor_data_init(mon, false, false);
|
||||
if (use_oob) {
|
||||
if (CHARDEV_IS_MUX(chr)) {
|
||||
error_report("Monitor Out-Of-Band is not supported with "
|
||||
"MUX typed chardev backend");
|
||||
exit(1);
|
||||
}
|
||||
if (use_readline) {
|
||||
error_report("Monitor Out-Of-band is only supported by QMP");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
monitor_data_init(mon, false, use_oob);
|
||||
|
||||
qemu_chr_fe_init(&mon->chr, chr, &error_abort);
|
||||
mon->flags = flags;
|
||||
if (flags & MONITOR_USE_READLINE) {
|
||||
if (use_readline) {
|
||||
mon->rs = readline_init(monitor_readline_printf,
|
||||
monitor_readline_flush,
|
||||
mon,
|
||||
|
@ -4637,6 +4678,9 @@ QemuOptsList qemu_mon_opts = {
|
|||
},{
|
||||
.name = "pretty",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},{
|
||||
.name = "x-oob",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
|
|
|
@ -872,7 +872,7 @@ def check_keys(expr_elem, meta, required, optional=[]):
|
|||
raise QAPISemError(info,
|
||||
"'%s' of %s '%s' should only use false value"
|
||||
% (key, meta, name))
|
||||
if key == 'boxed' and value is not True:
|
||||
if (key == 'boxed' or key == 'allow-oob') and value is not True:
|
||||
raise QAPISemError(info,
|
||||
"'%s' of %s '%s' should only use true value"
|
||||
% (key, meta, name))
|
||||
|
|
|
@ -86,25 +86,25 @@ static void assert_hvf_ok(hv_return_t ret)
|
|||
|
||||
switch (ret) {
|
||||
case HV_ERROR:
|
||||
error_report("Error: HV_ERROR\n");
|
||||
error_report("Error: HV_ERROR");
|
||||
break;
|
||||
case HV_BUSY:
|
||||
error_report("Error: HV_BUSY\n");
|
||||
error_report("Error: HV_BUSY");
|
||||
break;
|
||||
case HV_BAD_ARGUMENT:
|
||||
error_report("Error: HV_BAD_ARGUMENT\n");
|
||||
error_report("Error: HV_BAD_ARGUMENT");
|
||||
break;
|
||||
case HV_NO_RESOURCES:
|
||||
error_report("Error: HV_NO_RESOURCES\n");
|
||||
error_report("Error: HV_NO_RESOURCES");
|
||||
break;
|
||||
case HV_NO_DEVICE:
|
||||
error_report("Error: HV_NO_DEVICE\n");
|
||||
error_report("Error: HV_NO_DEVICE");
|
||||
break;
|
||||
case HV_UNSUPPORTED:
|
||||
error_report("Error: HV_UNSUPPORTED\n");
|
||||
error_report("Error: HV_UNSUPPORTED");
|
||||
break;
|
||||
default:
|
||||
error_report("Unknown Error\n");
|
||||
error_report("Unknown Error");
|
||||
}
|
||||
|
||||
abort();
|
||||
|
@ -191,7 +191,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
|||
if (mem) {
|
||||
mem->size = 0;
|
||||
if (do_hvf_set_memory(mem)) {
|
||||
error_report("Failed to reset overlapping slot\n");
|
||||
error_report("Failed to reset overlapping slot");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
|||
}
|
||||
|
||||
if (x == hvf_state->num_slots) {
|
||||
error_report("No free slots\n");
|
||||
error_report("No free slots");
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -221,7 +221,7 @@ void hvf_set_phys_mem(MemoryRegionSection *section, bool add)
|
|||
mem->region = area;
|
||||
|
||||
if (do_hvf_set_memory(mem)) {
|
||||
error_report("Error registering new memory slot\n");
|
||||
error_report("Error registering new memory slot");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
@ -884,7 +884,7 @@ int hvf_vcpu_exec(CPUState *cpu)
|
|||
break;
|
||||
}
|
||||
default:
|
||||
error_report("Unrecognized CR %d\n", cr);
|
||||
error_report("Unrecognized CR %d", cr);
|
||||
abort();
|
||||
}
|
||||
RIP(env) += ins_len;
|
||||
|
@ -930,7 +930,7 @@ int hvf_vcpu_exec(CPUState *cpu)
|
|||
env->error_code = 0;
|
||||
break;
|
||||
default:
|
||||
error_report("%llx: unhandled exit %llx\n", rip, exit_reason);
|
||||
error_report("%llx: unhandled exit %llx", rip, exit_reason);
|
||||
}
|
||||
} while (ret == 0);
|
||||
|
||||
|
|
|
@ -523,6 +523,7 @@ qapi-schema += missing-comma-object.json
|
|||
qapi-schema += missing-type.json
|
||||
qapi-schema += nested-struct-data.json
|
||||
qapi-schema += non-objects.json
|
||||
qapi-schema += oob-test.json
|
||||
qapi-schema += pragma-doc-required-crap.json
|
||||
qapi-schema += pragma-extra-junk.json
|
||||
qapi-schema += pragma-name-case-whitelist-crap.json
|
||||
|
|
|
@ -166,7 +166,8 @@ static const char *qtest_qemu_binary(void)
|
|||
return qemu_bin;
|
||||
}
|
||||
|
||||
QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
|
||||
QTestState *qtest_init_without_qmp_handshake(bool use_oob,
|
||||
const char *extra_args)
|
||||
{
|
||||
QTestState *s;
|
||||
int sock, qmpsock, i;
|
||||
|
@ -199,12 +200,13 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
|
|||
command = g_strdup_printf("exec %s "
|
||||
"-qtest unix:%s,nowait "
|
||||
"-qtest-log %s "
|
||||
"-qmp unix:%s,nowait "
|
||||
"-chardev socket,path=%s,nowait,id=char0 "
|
||||
"-mon chardev=char0,mode=control%s "
|
||||
"-machine accel=qtest "
|
||||
"-display none "
|
||||
"%s", qemu_binary, socket_path,
|
||||
getenv("QTEST_LOG") ? "/dev/fd/2" : "/dev/null",
|
||||
qmp_socket_path,
|
||||
qmp_socket_path, use_oob ? ",x-oob=on" : "",
|
||||
extra_args ?: "");
|
||||
execlp("/bin/sh", "sh", "-c", command, NULL);
|
||||
exit(1);
|
||||
|
@ -239,7 +241,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
|
|||
|
||||
QTestState *qtest_init(const char *extra_args)
|
||||
{
|
||||
QTestState *s = qtest_init_without_qmp_handshake(extra_args);
|
||||
QTestState *s = qtest_init_without_qmp_handshake(false, extra_args);
|
||||
|
||||
/* Read the QMP greeting and then do the handshake */
|
||||
qtest_qmp_discard_response(s, "");
|
||||
|
|
|
@ -56,11 +56,14 @@ QTestState *qtest_init(const char *extra_args);
|
|||
|
||||
/**
|
||||
* qtest_init_without_qmp_handshake:
|
||||
* @extra_args: other arguments to pass to QEMU.
|
||||
* @use_oob: true to have the server advertise OOB support
|
||||
* @extra_args: other arguments to pass to QEMU. CAUTION: these
|
||||
* arguments are subject to word splitting and shell evaluation.
|
||||
*
|
||||
* Returns: #QTestState instance.
|
||||
*/
|
||||
QTestState *qtest_init_without_qmp_handshake(const char *extra_args);
|
||||
QTestState *qtest_init_without_qmp_handshake(bool use_oob,
|
||||
const char *extra_args);
|
||||
|
||||
/**
|
||||
* qtest_quit:
|
||||
|
|
|
@ -28,9 +28,9 @@ object q_obj_cmd-arg
|
|||
member arg2: str optional=True
|
||||
member arg3: bool optional=False
|
||||
command cmd q_obj_cmd-arg -> Object
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
command cmd-boxed Object -> None
|
||||
gen=True success_response=True boxed=True
|
||||
gen=True success_response=True boxed=True oob=False
|
||||
doc freeform
|
||||
body=
|
||||
= Section
|
||||
|
|
|
@ -5,4 +5,4 @@ module ident-with-escape.json
|
|||
object q_obj_fooA-arg
|
||||
member bar1: str optional=False
|
||||
command fooA q_obj_fooA-arg -> None
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
|
|
|
@ -3,6 +3,6 @@ enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool']
|
|||
prefix QTYPE
|
||||
module indented-expr.json
|
||||
command eins None -> None
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
command zwei None -> None
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/oob-test.json:2: 'allow-oob' of command 'oob-command-1' should only use true value
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,2 @@
|
|||
# Check against oob illegal value
|
||||
{ 'command': 'oob-command-1', 'allow-oob': 'some-string' }
|
|
@ -139,6 +139,9 @@
|
|||
{ 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
|
||||
{ 'command': 'boxed-union', 'data': 'UserDefNativeListUnion', 'boxed': true }
|
||||
|
||||
# Smoke test on Out-Of-Band
|
||||
{ 'command': 'an-oob-command', 'allow-oob': true }
|
||||
|
||||
# For testing integer range flattening in opts-visitor. The following schema
|
||||
# corresponds to the option format:
|
||||
#
|
||||
|
|
|
@ -16,7 +16,7 @@ object Empty1
|
|||
object Empty2
|
||||
base Empty1
|
||||
command user_def_cmd0 Empty2 -> Empty2
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
enum QEnumTwo ['value1', 'value2']
|
||||
prefix QENUM_TWO
|
||||
object UserDefOne
|
||||
|
@ -143,29 +143,31 @@ object UserDefNativeListUnion
|
|||
case sizes: q_obj_sizeList-wrapper
|
||||
case any: q_obj_anyList-wrapper
|
||||
command user_def_cmd None -> None
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
object q_obj_user_def_cmd1-arg
|
||||
member ud1a: UserDefOne optional=False
|
||||
command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
object q_obj_user_def_cmd2-arg
|
||||
member ud1a: UserDefOne optional=False
|
||||
member ud1b: UserDefOne optional=True
|
||||
command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
object q_obj_guest-get-time-arg
|
||||
member a: int optional=False
|
||||
member b: int optional=True
|
||||
command guest-get-time q_obj_guest-get-time-arg -> int
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
object q_obj_guest-sync-arg
|
||||
member arg: any optional=False
|
||||
command guest-sync q_obj_guest-sync-arg -> any
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
command boxed-struct UserDefZero -> None
|
||||
gen=True success_response=True boxed=True
|
||||
gen=True success_response=True boxed=True oob=False
|
||||
command boxed-union UserDefNativeListUnion -> None
|
||||
gen=True success_response=True boxed=True
|
||||
gen=True success_response=True boxed=True oob=False
|
||||
command an-oob-command None -> None
|
||||
gen=True success_response=True boxed=False oob=True
|
||||
object UserDefOptions
|
||||
member i64: intList optional=True
|
||||
member u64: uint64List optional=True
|
||||
|
@ -229,4 +231,4 @@ object q_obj___org.qemu_x-command-arg
|
|||
member c: __org.qemu_x-Union2 optional=False
|
||||
member d: __org.qemu_x-Alt optional=False
|
||||
command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
|
||||
gen=True success_response=True boxed=False
|
||||
gen=True success_response=True boxed=False oob=False
|
||||
|
|
|
@ -45,8 +45,8 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
|||
gen, success_response, boxed, allow_oob):
|
||||
print('command %s %s -> %s' % \
|
||||
(name, arg_type and arg_type.name, ret_type and ret_type.name))
|
||||
print(' gen=%s success_response=%s boxed=%s' % \
|
||||
(gen, success_response, boxed))
|
||||
print(' gen=%s success_response=%s boxed=%s oob=%s' % \
|
||||
(gen, success_response, boxed, allow_oob))
|
||||
|
||||
def visit_event(self, name, info, arg_type, boxed):
|
||||
print('event %s %s' % (name, arg_type and arg_type.name))
|
||||
|
|
|
@ -81,7 +81,7 @@ static void test_qmp_protocol(void)
|
|||
QList *capabilities;
|
||||
QTestState *qts;
|
||||
|
||||
qts = qtest_init_without_qmp_handshake(common_args);
|
||||
qts = qtest_init_without_qmp_handshake(false, common_args);
|
||||
|
||||
/* Test greeting */
|
||||
resp = qtest_qmp_receive(qts);
|
||||
|
@ -90,6 +90,7 @@ static void test_qmp_protocol(void)
|
|||
test_version(qdict_get(q, "version"));
|
||||
capabilities = qdict_get_qlist(q, "capabilities");
|
||||
g_assert(capabilities && qlist_empty(capabilities));
|
||||
QDECREF(resp);
|
||||
|
||||
/* Test valid command before handshake */
|
||||
resp = qtest_qmp(qts, "{ 'execute': 'query-version' }");
|
||||
|
@ -134,6 +135,87 @@ static void test_qmp_protocol(void)
|
|||
qtest_quit(qts);
|
||||
}
|
||||
|
||||
/* Tests for Out-Of-Band support. */
|
||||
static void test_qmp_oob(void)
|
||||
{
|
||||
QTestState *qts;
|
||||
QDict *resp, *q;
|
||||
int acks = 0;
|
||||
const QListEntry *entry;
|
||||
QList *capabilities;
|
||||
QString *qstr;
|
||||
const char *cmd_id;
|
||||
|
||||
qts = qtest_init_without_qmp_handshake(true, common_args);
|
||||
|
||||
/* Check the greeting message. */
|
||||
resp = qtest_qmp_receive(qts);
|
||||
q = qdict_get_qdict(resp, "QMP");
|
||||
g_assert(q);
|
||||
capabilities = qdict_get_qlist(q, "capabilities");
|
||||
g_assert(capabilities && !qlist_empty(capabilities));
|
||||
entry = qlist_first(capabilities);
|
||||
g_assert(entry);
|
||||
qstr = qobject_to(QString, entry->value);
|
||||
g_assert(qstr);
|
||||
g_assert_cmpstr(qstring_get_str(qstr), ==, "oob");
|
||||
QDECREF(resp);
|
||||
|
||||
/* Try a fake capability, it should fail. */
|
||||
resp = qtest_qmp(qts,
|
||||
"{ 'execute': 'qmp_capabilities', "
|
||||
" 'arguments': { 'enable': [ 'cap-does-not-exist' ] } }");
|
||||
g_assert(qdict_haskey(resp, "error"));
|
||||
QDECREF(resp);
|
||||
|
||||
/* Now, enable OOB in current QMP session, it should succeed. */
|
||||
resp = qtest_qmp(qts,
|
||||
"{ 'execute': 'qmp_capabilities', "
|
||||
" 'arguments': { 'enable': [ 'oob' ] } }");
|
||||
g_assert(qdict_haskey(resp, "return"));
|
||||
QDECREF(resp);
|
||||
|
||||
/*
|
||||
* Try any command that does not support OOB but with OOB flag. We
|
||||
* should get failure.
|
||||
*/
|
||||
resp = qtest_qmp(qts,
|
||||
"{ 'execute': 'query-cpus',"
|
||||
" 'control': { 'run-oob': true } }");
|
||||
g_assert(qdict_haskey(resp, "error"));
|
||||
QDECREF(resp);
|
||||
|
||||
/*
|
||||
* First send the "x-oob-test" command with lock=true and
|
||||
* oob=false, it should hang the dispatcher and main thread;
|
||||
* later, we send another lock=false with oob=true to continue
|
||||
* that thread processing. Finally we should receive replies from
|
||||
* both commands.
|
||||
*/
|
||||
qtest_async_qmp(qts,
|
||||
"{ 'execute': 'x-oob-test',"
|
||||
" 'arguments': { 'lock': true }, "
|
||||
" 'id': 'lock-cmd'}");
|
||||
qtest_async_qmp(qts,
|
||||
"{ 'execute': 'x-oob-test', "
|
||||
" 'arguments': { 'lock': false }, "
|
||||
" 'control': { 'run-oob': true }, "
|
||||
" 'id': 'unlock-cmd' }");
|
||||
|
||||
/* Ignore all events. Wait for 2 acks */
|
||||
while (acks < 2) {
|
||||
resp = qtest_qmp_receive(qts);
|
||||
cmd_id = qdict_get_str(resp, "id");
|
||||
if (!g_strcmp0(cmd_id, "lock-cmd") ||
|
||||
!g_strcmp0(cmd_id, "unlock-cmd")) {
|
||||
acks++;
|
||||
}
|
||||
QDECREF(resp);
|
||||
}
|
||||
|
||||
qtest_quit(qts);
|
||||
}
|
||||
|
||||
static int query_error_class(const char *cmd)
|
||||
{
|
||||
static struct {
|
||||
|
@ -318,6 +400,7 @@ int main(int argc, char *argv[])
|
|||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
qtest_add_func("qmp/protocol", test_qmp_protocol);
|
||||
qtest_add_func("qmp/oob", test_qmp_oob);
|
||||
qmp_schema_init(&schema);
|
||||
add_query_tests(&schema);
|
||||
|
||||
|
|
|
@ -16,6 +16,10 @@ void qmp_user_def_cmd(Error **errp)
|
|||
{
|
||||
}
|
||||
|
||||
void qmp_an_oob_command(Error **errp)
|
||||
{
|
||||
}
|
||||
|
||||
Empty2 *qmp_user_def_cmd0(Error **errp)
|
||||
{
|
||||
return g_new0(Empty2, 1);
|
||||
|
|
|
@ -1115,7 +1115,7 @@ static const SerializeOps visitors[] = {
|
|||
|
||||
static void add_visitor_type(const SerializeOps *ops)
|
||||
{
|
||||
char testname_prefix[128];
|
||||
char testname_prefix[32];
|
||||
char testname[128];
|
||||
TestArgs *args;
|
||||
int i = 0;
|
||||
|
|
5
vl.c
5
vl.c
|
@ -2404,6 +2404,11 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
|
|||
if (qemu_opt_get_bool(opts, "pretty", 0))
|
||||
flags |= MONITOR_USE_PRETTY;
|
||||
|
||||
/* OOB is off by default */
|
||||
if (qemu_opt_get_bool(opts, "x-oob", 0)) {
|
||||
flags |= MONITOR_USE_OOB;
|
||||
}
|
||||
|
||||
chardev = qemu_opt_get(opts, "chardev");
|
||||
chr = qemu_chr_find(chardev);
|
||||
if (chr == NULL) {
|
||||
|
|
Loading…
Reference in New Issue