Some fixes and improvements for various qtests by Eric and me.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJZu4MxAAoJEC7Z13T+cC21D/AQAJUxgGbNwos+hzxrXnzQCj6K EqC0pqyUE/XkxZvy3/HjSt4VzecHDS59i8hNEo0+wyb/Wt/RV4lTkedZye8P3VO1 OdhPw2cMB18MtHPG+tuGMjj6wySqn67cV4Y1swNl34N//9PebcsYVLVrNWgz3bSw +U7023ztWbHF7MebzOt6JaKZPTej4S1aQoSGVQs7S4hj1ydIOur3vRCpdTmsGbts VcDbsVANFNYszP9y/EVU+z30s03iJzDdw2GRCr9C1JOwQbbpNB3onqbr9j2XA9uI dI6KkO+T02azKAgsJ4F8mqD3wm8dFjxY/CZGN//G1eQEWW2by2wiQcTbR5rm457T mbt5evqLQG8SmZsvrepKeM99JFKRzkoBloAOul8wGzK+7yG0vJVGw0dCwkjLWxW1 DgiHKn4dcilLi2ybXvB7vK62dE5z3qk391YpZI/0gh1XOaNlc8/CnX93z9oFgpdP ZhUxzO4cWRRGw7rx49Skt6zg6JSvbgmjbpG7BJ0jjZhJt42I8d3/GtVDWkZ7XJI7 AlNukRy/norwXOiTcT6OMiQe1/ZBkNbqxhgdJ2bhRQQ/sqrEV6B0vPGgb36qKwPc 9abVsycIVWc5NNqV4zH8hS72lBb8UKwpl2gZUqM8TFwG9uv6y+KO0Z4eTgW/z0HD EfaZknpeBQzlt6srXKaB =9guJ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/huth/tags/check-20170915' into staging Some fixes and improvements for various qtests by Eric and me. # gpg: Signature made Fri 15 Sep 2017 08:37:21 BST # gpg: using RSA key 0x2ED9D774FE702DB5 # gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" # gpg: aka "Thomas Huth <thuth@redhat.com>" # gpg: aka "Thomas Huth <huth@tuxfamily.org>" # gpg: aka "Thomas Huth <th.huth@posteo.de>" # Primary key fingerprint: 27B8 8847 EEE0 2501 18F3 EAB9 2ED9 D774 FE70 2DB5 * remotes/huth/tags/check-20170915: qtest: Avoid passing raw strings through hmp() libqtest: Remove dead qtest_instances variable numa-test: Use hmp() qtest: Don't perform side effects inside assertion test-qga: Kill broken and dead QGA_TEST_SIDE_EFFECTING code tests: Fix broken ivshmem-server-msi/-irq tests tests/libqtest: Use a proper error message if QTEST_QEMU_BINARY is missing tests/test-hmp: Remove puv3 and tricore_testboard from the blacklist tests: Introduce generic device hot-plug/hot-unplug functions Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5faf2d376a
80
qtest.c
80
qtest.c
@ -332,10 +332,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
strcmp(words[0], "outl") == 0) {
|
||||
unsigned long addr;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1] && words[2]);
|
||||
g_assert(qemu_strtoul(words[1], NULL, 0, &addr) == 0);
|
||||
g_assert(qemu_strtoul(words[2], NULL, 0, &value) == 0);
|
||||
ret = qemu_strtoul(words[1], NULL, 0, &addr);
|
||||
g_assert(ret == 0);
|
||||
ret = qemu_strtoul(words[2], NULL, 0, &value);
|
||||
g_assert(ret == 0);
|
||||
g_assert(addr <= 0xffff);
|
||||
|
||||
if (words[0][3] == 'b') {
|
||||
@ -352,9 +355,11 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
strcmp(words[0], "inl") == 0) {
|
||||
unsigned long addr;
|
||||
uint32_t value = -1U;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1]);
|
||||
g_assert(qemu_strtoul(words[1], NULL, 0, &addr) == 0);
|
||||
ret = qemu_strtoul(words[1], NULL, 0, &addr);
|
||||
g_assert(ret == 0);
|
||||
g_assert(addr <= 0xffff);
|
||||
|
||||
if (words[0][2] == 'b') {
|
||||
@ -372,10 +377,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
strcmp(words[0], "writeq") == 0) {
|
||||
uint64_t addr;
|
||||
uint64_t value;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1] && words[2]);
|
||||
g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
|
||||
g_assert(qemu_strtou64(words[2], NULL, 0, &value) == 0);
|
||||
ret = qemu_strtou64(words[1], NULL, 0, &addr);
|
||||
g_assert(ret == 0);
|
||||
ret = qemu_strtou64(words[2], NULL, 0, &value);
|
||||
g_assert(ret == 0);
|
||||
|
||||
if (words[0][5] == 'b') {
|
||||
uint8_t data = value;
|
||||
@ -401,9 +409,11 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
strcmp(words[0], "readq") == 0) {
|
||||
uint64_t addr;
|
||||
uint64_t value = UINT64_C(-1);
|
||||
int ret;
|
||||
|
||||
g_assert(words[1]);
|
||||
g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
|
||||
ret = qemu_strtou64(words[1], NULL, 0, &addr);
|
||||
g_assert(ret == 0);
|
||||
|
||||
if (words[0][4] == 'b') {
|
||||
uint8_t data;
|
||||
@ -427,10 +437,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
uint64_t addr, len, i;
|
||||
uint8_t *data;
|
||||
char *enc;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1] && words[2]);
|
||||
g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
|
||||
g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
|
||||
ret = qemu_strtou64(words[1], NULL, 0, &addr);
|
||||
g_assert(ret == 0);
|
||||
ret = qemu_strtou64(words[2], NULL, 0, &len);
|
||||
g_assert(ret == 0);
|
||||
/* We'd send garbage to libqtest if len is 0 */
|
||||
g_assert(len);
|
||||
|
||||
@ -451,10 +464,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
uint64_t addr, len;
|
||||
uint8_t *data;
|
||||
gchar *b64_data;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1] && words[2]);
|
||||
g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
|
||||
g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
|
||||
ret = qemu_strtou64(words[1], NULL, 0, &addr);
|
||||
g_assert(ret == 0);
|
||||
ret = qemu_strtou64(words[2], NULL, 0, &len);
|
||||
g_assert(ret == 0);
|
||||
|
||||
data = g_malloc(len);
|
||||
cpu_physical_memory_read(addr, data, len);
|
||||
@ -468,10 +484,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
uint64_t addr, len, i;
|
||||
uint8_t *data;
|
||||
size_t data_len;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1] && words[2] && words[3]);
|
||||
g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
|
||||
g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
|
||||
ret = qemu_strtou64(words[1], NULL, 0, &addr);
|
||||
g_assert(ret == 0);
|
||||
ret = qemu_strtou64(words[2], NULL, 0, &len);
|
||||
g_assert(ret == 0);
|
||||
|
||||
data_len = strlen(words[3]);
|
||||
if (data_len < 3) {
|
||||
@ -497,11 +516,15 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
uint64_t addr, len;
|
||||
uint8_t *data;
|
||||
unsigned long pattern;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1] && words[2] && words[3]);
|
||||
g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
|
||||
g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
|
||||
g_assert(qemu_strtoul(words[3], NULL, 0, &pattern) == 0);
|
||||
ret = qemu_strtou64(words[1], NULL, 0, &addr);
|
||||
g_assert(ret == 0);
|
||||
ret = qemu_strtou64(words[2], NULL, 0, &len);
|
||||
g_assert(ret == 0);
|
||||
ret = qemu_strtoul(words[3], NULL, 0, &pattern);
|
||||
g_assert(ret == 0);
|
||||
|
||||
if (len) {
|
||||
data = g_malloc(len);
|
||||
@ -517,10 +540,13 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
uint8_t *data;
|
||||
size_t data_len;
|
||||
gsize out_len;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1] && words[2] && words[3]);
|
||||
g_assert(qemu_strtou64(words[1], NULL, 0, &addr) == 0);
|
||||
g_assert(qemu_strtou64(words[2], NULL, 0, &len) == 0);
|
||||
ret = qemu_strtou64(words[1], NULL, 0, &addr);
|
||||
g_assert(ret == 0);
|
||||
ret = qemu_strtou64(words[2], NULL, 0, &len);
|
||||
g_assert(ret == 0);
|
||||
|
||||
data_len = strlen(words[3]);
|
||||
if (data_len < 3) {
|
||||
@ -551,11 +577,16 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
} else if (strcmp(words[0], "rtas") == 0) {
|
||||
uint64_t res, args, ret;
|
||||
unsigned long nargs, nret;
|
||||
int rc;
|
||||
|
||||
g_assert(qemu_strtoul(words[2], NULL, 0, &nargs) == 0);
|
||||
g_assert(qemu_strtou64(words[3], NULL, 0, &args) == 0);
|
||||
g_assert(qemu_strtoul(words[4], NULL, 0, &nret) == 0);
|
||||
g_assert(qemu_strtou64(words[5], NULL, 0, &ret) == 0);
|
||||
rc = qemu_strtoul(words[2], NULL, 0, &nargs);
|
||||
g_assert(rc == 0);
|
||||
rc = qemu_strtou64(words[3], NULL, 0, &args);
|
||||
g_assert(rc == 0);
|
||||
rc = qemu_strtoul(words[4], NULL, 0, &nret);
|
||||
g_assert(rc == 0);
|
||||
rc = qemu_strtou64(words[5], NULL, 0, &ret);
|
||||
g_assert(rc == 0);
|
||||
res = qtest_rtas_call(words[1], nargs, args, nret, ret);
|
||||
|
||||
qtest_send_prefix(chr);
|
||||
@ -565,7 +596,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
int64_t ns;
|
||||
|
||||
if (words[1]) {
|
||||
g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
|
||||
int ret = qemu_strtoi64(words[1], NULL, 0, &ns);
|
||||
g_assert(ret == 0);
|
||||
} else {
|
||||
ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
|
||||
}
|
||||
@ -575,9 +607,11 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
(int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
|
||||
} else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) {
|
||||
int64_t ns;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1]);
|
||||
g_assert(qemu_strtoi64(words[1], NULL, 0, &ns) == 0);
|
||||
ret = qemu_strtoi64(words[1], NULL, 0, &ns);
|
||||
g_assert(ret == 0);
|
||||
qtest_clock_warp(ns);
|
||||
qtest_send_prefix(chr);
|
||||
qtest_sendf(chr, "OK %"PRIi64"\n",
|
||||
|
@ -120,6 +120,8 @@ void qpci_msix_enable(QPCIDevice *dev)
|
||||
bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
|
||||
if (bir_pba != bir_table) {
|
||||
dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL);
|
||||
} else {
|
||||
dev->msix_pba_bar = dev->msix_table_bar;
|
||||
}
|
||||
dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
|
||||
|
||||
@ -138,8 +140,11 @@ void qpci_msix_disable(QPCIDevice *dev)
|
||||
qpci_config_writew(dev, addr + PCI_MSIX_FLAGS,
|
||||
val & ~PCI_MSIX_FLAGS_ENABLE);
|
||||
|
||||
if (dev->msix_pba_bar.addr != dev->msix_table_bar.addr) {
|
||||
qpci_iounmap(dev, dev->msix_pba_bar);
|
||||
}
|
||||
qpci_iounmap(dev, dev->msix_table_bar);
|
||||
qpci_iounmap(dev, dev->msix_pba_bar);
|
||||
|
||||
dev->msix_enabled = 0;
|
||||
dev->msix_table_off = 0;
|
||||
dev->msix_pba_off = 0;
|
||||
@ -394,21 +399,6 @@ QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
|
||||
void qpci_plug_device_test(const char *driver, const char *id,
|
||||
uint8_t slot, const char *opts)
|
||||
{
|
||||
QDict *response;
|
||||
char *cmd;
|
||||
|
||||
cmd = g_strdup_printf("{'execute': 'device_add',"
|
||||
" 'arguments': {"
|
||||
" 'driver': '%s',"
|
||||
" 'addr': '%d',"
|
||||
" %s%s"
|
||||
" 'id': '%s'"
|
||||
"}}", driver, slot,
|
||||
opts ? opts : "", opts ? "," : "",
|
||||
id);
|
||||
response = qmp(cmd);
|
||||
g_free(cmd);
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
qtest_qmp_device_add(driver, id, "'addr': '%d'%s%s", slot,
|
||||
opts ? ", " : "", opts ? opts : "");
|
||||
}
|
||||
|
@ -40,34 +40,16 @@ void uhci_port_test(struct qhc *hc, int port, uint16_t expect)
|
||||
void usb_test_hotplug(const char *hcd_id, const int port,
|
||||
void (*port_check)(void))
|
||||
{
|
||||
QDict *response;
|
||||
char *cmd;
|
||||
char *id = g_strdup_printf("usbdev%d", port);
|
||||
|
||||
cmd = g_strdup_printf("{'execute': 'device_add',"
|
||||
" 'arguments': {"
|
||||
" 'driver': 'usb-tablet',"
|
||||
" 'port': '%d',"
|
||||
" 'bus': '%s.0',"
|
||||
" 'id': 'usbdev%d'"
|
||||
"}}", port, hcd_id, port);
|
||||
response = qmp(cmd);
|
||||
g_free(cmd);
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
qtest_qmp_device_add("usb-tablet", id, "'port': '%d', 'bus': '%s.0'",
|
||||
port, hcd_id);
|
||||
|
||||
if (port_check) {
|
||||
port_check();
|
||||
}
|
||||
|
||||
cmd = g_strdup_printf("{'execute': 'device_del',"
|
||||
" 'arguments': {"
|
||||
" 'id': 'usbdev%d'"
|
||||
"}}", port);
|
||||
response = qmp(cmd);
|
||||
g_free(cmd);
|
||||
g_assert(response);
|
||||
g_assert(qdict_haskey(response, "event"));
|
||||
g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));
|
||||
QDECREF(response);
|
||||
qtest_qmp_device_del(id);
|
||||
|
||||
g_free(id);
|
||||
}
|
||||
|
105
tests/libqtest.c
105
tests/libqtest.c
@ -42,7 +42,6 @@ struct QTestState
|
||||
};
|
||||
|
||||
static GHookList abrt_hooks;
|
||||
static GList *qtest_instances;
|
||||
static struct sigaction sigact_old;
|
||||
|
||||
#define g_assert_no_errno(ret) do { \
|
||||
@ -150,6 +149,19 @@ void qtest_add_abrt_handler(GHookFunc fn, const void *data)
|
||||
g_hook_prepend(&abrt_hooks, hook);
|
||||
}
|
||||
|
||||
static const char *qtest_qemu_binary(void)
|
||||
{
|
||||
const char *qemu_bin;
|
||||
|
||||
qemu_bin = getenv("QTEST_QEMU_BINARY");
|
||||
if (!qemu_bin) {
|
||||
fprintf(stderr, "Environment variable QTEST_QEMU_BINARY required\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return qemu_bin;
|
||||
}
|
||||
|
||||
QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
|
||||
{
|
||||
QTestState *s;
|
||||
@ -157,13 +169,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
|
||||
gchar *socket_path;
|
||||
gchar *qmp_socket_path;
|
||||
gchar *command;
|
||||
const char *qemu_binary;
|
||||
|
||||
qemu_binary = getenv("QTEST_QEMU_BINARY");
|
||||
if (!qemu_binary) {
|
||||
fprintf(stderr, "Environment variable QTEST_QEMU_BINARY required\n");
|
||||
exit(1);
|
||||
}
|
||||
const char *qemu_binary = qtest_qemu_binary();
|
||||
|
||||
s = g_malloc(sizeof(*s));
|
||||
|
||||
@ -240,13 +246,10 @@ QTestState *qtest_init(const char *extra_args)
|
||||
|
||||
void qtest_quit(QTestState *s)
|
||||
{
|
||||
qtest_instances = g_list_remove(qtest_instances, s);
|
||||
g_hook_destroy_link(&abrt_hooks, g_hook_find_data(&abrt_hooks, TRUE, s));
|
||||
|
||||
/* Uninstall SIGABRT handler on last instance */
|
||||
if (!qtest_instances) {
|
||||
cleanup_sigabrt_handler();
|
||||
}
|
||||
cleanup_sigabrt_handler();
|
||||
|
||||
kill_qemu(s);
|
||||
close(s->fd);
|
||||
@ -624,8 +627,7 @@ char *qtest_hmp(QTestState *s, const char *fmt, ...)
|
||||
|
||||
const char *qtest_get_arch(void)
|
||||
{
|
||||
const char *qemu = getenv("QTEST_QEMU_BINARY");
|
||||
g_assert(qemu != NULL);
|
||||
const char *qemu = qtest_qemu_binary();
|
||||
const char *end = strrchr(qemu, '/');
|
||||
|
||||
return end + strlen("/qemu-system-");
|
||||
@ -987,3 +989,78 @@ void qtest_cb_for_every_machine(void (*cb)(const char *machine))
|
||||
qtest_end();
|
||||
QDECREF(response);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic hot-plugging test via the device_add QMP command.
|
||||
*/
|
||||
void qtest_qmp_device_add(const char *driver, const char *id, const char *fmt,
|
||||
...)
|
||||
{
|
||||
QDict *response;
|
||||
char *cmd, *opts = NULL;
|
||||
va_list va;
|
||||
|
||||
if (fmt) {
|
||||
va_start(va, fmt);
|
||||
opts = g_strdup_vprintf(fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
cmd = g_strdup_printf("{'execute': 'device_add',"
|
||||
" 'arguments': { 'driver': '%s', 'id': '%s'%s%s }}",
|
||||
driver, id, opts ? ", " : "", opts ? opts : "");
|
||||
g_free(opts);
|
||||
|
||||
response = qmp(cmd);
|
||||
g_free(cmd);
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "event")); /* We don't expect any events */
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic hot-unplugging test via the device_del QMP command.
|
||||
* Device deletion will get one response and one event. For example:
|
||||
*
|
||||
* {'execute': 'device_del','arguments': { 'id': 'scsi-hd'}}
|
||||
*
|
||||
* will get this one:
|
||||
*
|
||||
* {"timestamp": {"seconds": 1505289667, "microseconds": 569862},
|
||||
* "event": "DEVICE_DELETED", "data": {"device": "scsi-hd",
|
||||
* "path": "/machine/peripheral/scsi-hd"}}
|
||||
*
|
||||
* and this one:
|
||||
*
|
||||
* {"return": {}}
|
||||
*
|
||||
* But the order of arrival may vary - so we've got to detect both.
|
||||
*/
|
||||
void qtest_qmp_device_del(const char *id)
|
||||
{
|
||||
QDict *response1, *response2, *event = NULL;
|
||||
char *cmd;
|
||||
|
||||
cmd = g_strdup_printf("{'execute': 'device_del',"
|
||||
" 'arguments': { 'id': '%s' }}", id);
|
||||
response1 = qmp(cmd);
|
||||
g_free(cmd);
|
||||
g_assert(response1);
|
||||
g_assert(!qdict_haskey(response1, "error"));
|
||||
|
||||
response2 = qmp("");
|
||||
g_assert(response2);
|
||||
g_assert(!qdict_haskey(response2, "error"));
|
||||
|
||||
if (qdict_haskey(response1, "event")) {
|
||||
event = response1;
|
||||
} else if (qdict_haskey(response2, "event")) {
|
||||
event = response2;
|
||||
}
|
||||
g_assert(event);
|
||||
g_assert_cmpstr(qdict_get_str(event, "event"), ==, "DEVICE_DELETED");
|
||||
|
||||
QDECREF(response1);
|
||||
QDECREF(response2);
|
||||
}
|
||||
|
@ -134,14 +134,14 @@ QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event);
|
||||
/**
|
||||
* qtest_hmp:
|
||||
* @s: #QTestState instance to operate on.
|
||||
* @fmt...: HMP command to send to QEMU
|
||||
* @fmt...: HMP command to send to QEMU, formats arguments like sprintf().
|
||||
*
|
||||
* Send HMP command to QEMU via QMP's human-monitor-command.
|
||||
* QMP events are discarded.
|
||||
*
|
||||
* Returns: the command's output. The caller should g_free() it.
|
||||
*/
|
||||
char *qtest_hmp(QTestState *s, const char *fmt, ...);
|
||||
char *qtest_hmp(QTestState *s, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
||||
|
||||
/**
|
||||
* qtest_hmpv:
|
||||
@ -592,13 +592,13 @@ static inline QDict *qmp_eventwait_ref(const char *event)
|
||||
|
||||
/**
|
||||
* hmp:
|
||||
* @fmt...: HMP command to send to QEMU
|
||||
* @fmt...: HMP command to send to QEMU, formats arguments like sprintf().
|
||||
*
|
||||
* Send HMP command to QEMU via QMP's human-monitor-command.
|
||||
*
|
||||
* Returns: the command's output. The caller should g_free() it.
|
||||
*/
|
||||
char *hmp(const char *fmt, ...);
|
||||
char *hmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
|
||||
|
||||
/**
|
||||
* get_irq:
|
||||
@ -927,4 +927,23 @@ QDict *qmp_fd(int fd, const char *fmt, ...);
|
||||
*/
|
||||
void qtest_cb_for_every_machine(void (*cb)(const char *machine));
|
||||
|
||||
/**
|
||||
* qtest_qmp_device_add:
|
||||
* @driver: Name of the device that should be added
|
||||
* @id: Identification string
|
||||
* @fmt: printf-like format string for further options to device_add
|
||||
*
|
||||
* Generic hot-plugging test via the device_add QMP command.
|
||||
*/
|
||||
void qtest_qmp_device_add(const char *driver, const char *id, const char *fmt,
|
||||
...) GCC_FMT_ATTR(3, 4);
|
||||
|
||||
/**
|
||||
* qtest_qmp_device_del:
|
||||
* @id: Identification string
|
||||
*
|
||||
* Generic hot-unplugging test via the device_del QMP command.
|
||||
*/
|
||||
void qtest_qmp_device_del(const char *id);
|
||||
|
||||
#endif
|
||||
|
@ -17,21 +17,6 @@ static char *make_cli(const char *generic_cli, const char *test_cli)
|
||||
return g_strdup_printf("%s %s", generic_cli ? generic_cli : "", test_cli);
|
||||
}
|
||||
|
||||
static char *hmp_info_numa(void)
|
||||
{
|
||||
QDict *resp;
|
||||
char *s;
|
||||
|
||||
resp = qmp("{ 'execute': 'human-monitor-command', 'arguments': "
|
||||
"{ 'command-line': 'info numa '} }");
|
||||
g_assert(resp);
|
||||
g_assert(qdict_haskey(resp, "return"));
|
||||
s = g_strdup(qdict_get_str(resp, "return"));
|
||||
g_assert(s);
|
||||
QDECREF(resp);
|
||||
return s;
|
||||
}
|
||||
|
||||
static void test_mon_explicit(const void *data)
|
||||
{
|
||||
char *s;
|
||||
@ -42,7 +27,7 @@ static void test_mon_explicit(const void *data)
|
||||
"-numa node,nodeid=1,cpus=4-7 ");
|
||||
qtest_start(cli);
|
||||
|
||||
s = hmp_info_numa();
|
||||
s = hmp("info numa");
|
||||
g_assert(strstr(s, "node 0 cpus: 0 1 2 3"));
|
||||
g_assert(strstr(s, "node 1 cpus: 4 5 6 7"));
|
||||
g_free(s);
|
||||
@ -59,7 +44,7 @@ static void test_mon_default(const void *data)
|
||||
cli = make_cli(data, "-smp 8 -numa node -numa node");
|
||||
qtest_start(cli);
|
||||
|
||||
s = hmp_info_numa();
|
||||
s = hmp("info numa");
|
||||
g_assert(strstr(s, "node 0 cpus: 0 2 4 6"));
|
||||
g_assert(strstr(s, "node 1 cpus: 1 3 5 7"));
|
||||
g_free(s);
|
||||
@ -78,7 +63,7 @@ static void test_mon_partial(const void *data)
|
||||
"-numa node,nodeid=1,cpus=4-5 ");
|
||||
qtest_start(cli);
|
||||
|
||||
s = hmp_info_numa();
|
||||
s = hmp("info numa");
|
||||
g_assert(strstr(s, "node 0 cpus: 0 1 2 3 6 7"));
|
||||
g_assert(strstr(s, "node 1 cpus: 4 5"));
|
||||
g_free(s);
|
||||
|
@ -81,7 +81,7 @@ static void test_commands(void)
|
||||
if (verbose) {
|
||||
fprintf(stderr, "\t%s\n", hmp_cmds[i]);
|
||||
}
|
||||
response = hmp(hmp_cmds[i]);
|
||||
response = hmp("%s", hmp_cmds[i]);
|
||||
g_free(response);
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ static void test_info_commands(void)
|
||||
if (verbose) {
|
||||
fprintf(stderr, "\t%s\n", info);
|
||||
}
|
||||
resp = hmp(info);
|
||||
resp = hmp("%s", info);
|
||||
g_free(resp);
|
||||
/* And move forward to the next line */
|
||||
info = strchr(endp + 1, '\n');
|
||||
@ -138,8 +138,7 @@ static void add_machine_test_case(const char *mname)
|
||||
char *path;
|
||||
|
||||
/* Ignore blacklisted machines that have known problems */
|
||||
if (!strcmp("puv3", mname) || !strcmp("tricore_testboard", mname) ||
|
||||
!strcmp("xenfv", mname) || !strcmp("xenpv", mname)) {
|
||||
if (!strcmp("xenfv", mname) || !strcmp("xenpv", mname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -642,65 +642,6 @@ static void test_qga_get_time(gconstpointer fix)
|
||||
QDECREF(ret);
|
||||
}
|
||||
|
||||
static void test_qga_set_time(gconstpointer fix)
|
||||
{
|
||||
const TestFixture *fixture = fix;
|
||||
QDict *ret;
|
||||
int64_t current, time;
|
||||
gchar *cmd;
|
||||
|
||||
/* get current time */
|
||||
ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
|
||||
g_assert_nonnull(ret);
|
||||
qmp_assert_no_error(ret);
|
||||
current = qdict_get_int(ret, "return");
|
||||
g_assert_cmpint(current, >, 0);
|
||||
QDECREF(ret);
|
||||
|
||||
/* set some old time */
|
||||
ret = qmp_fd(fixture->fd, "{'execute': 'guest-set-time',"
|
||||
" 'arguments': { 'time': 1000 } }");
|
||||
g_assert_nonnull(ret);
|
||||
qmp_assert_no_error(ret);
|
||||
QDECREF(ret);
|
||||
|
||||
/* check old time */
|
||||
ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
|
||||
g_assert_nonnull(ret);
|
||||
qmp_assert_no_error(ret);
|
||||
time = qdict_get_int(ret, "return");
|
||||
g_assert_cmpint(time / 1000, <, G_USEC_PER_SEC * 10);
|
||||
QDECREF(ret);
|
||||
|
||||
/* set back current time */
|
||||
cmd = g_strdup_printf("{'execute': 'guest-set-time',"
|
||||
" 'arguments': { 'time': %" PRId64 " } }",
|
||||
current + time * 1000);
|
||||
ret = qmp_fd(fixture->fd, cmd);
|
||||
g_free(cmd);
|
||||
g_assert_nonnull(ret);
|
||||
qmp_assert_no_error(ret);
|
||||
QDECREF(ret);
|
||||
}
|
||||
|
||||
static void test_qga_fstrim(gconstpointer fix)
|
||||
{
|
||||
const TestFixture *fixture = fix;
|
||||
QDict *ret;
|
||||
QList *list;
|
||||
const QListEntry *entry;
|
||||
|
||||
ret = qmp_fd(fixture->fd, "{'execute': 'guest-fstrim',"
|
||||
" arguments: { minimum: 4194304 } }");
|
||||
g_assert_nonnull(ret);
|
||||
qmp_assert_no_error(ret);
|
||||
list = qdict_get_qlist(ret, "return");
|
||||
entry = qlist_first(list);
|
||||
g_assert(qdict_haskey(qobject_to_qdict(entry->value), "paths"));
|
||||
|
||||
QDECREF(ret);
|
||||
}
|
||||
|
||||
static void test_qga_blacklist(gconstpointer data)
|
||||
{
|
||||
TestFixture fix;
|
||||
@ -831,30 +772,6 @@ static void test_qga_fsfreeze_status(gconstpointer fix)
|
||||
QDECREF(ret);
|
||||
}
|
||||
|
||||
static void test_qga_fsfreeze_and_thaw(gconstpointer fix)
|
||||
{
|
||||
const TestFixture *fixture = fix;
|
||||
QDict *ret;
|
||||
const gchar *status;
|
||||
|
||||
ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-freeze'}");
|
||||
g_assert_nonnull(ret);
|
||||
qmp_assert_no_error(ret);
|
||||
QDECREF(ret);
|
||||
|
||||
ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}");
|
||||
g_assert_nonnull(ret);
|
||||
qmp_assert_no_error(ret);
|
||||
status = qdict_get_try_str(ret, "return");
|
||||
g_assert_cmpstr(status, ==, "frozen");
|
||||
QDECREF(ret);
|
||||
|
||||
ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-thaw'}");
|
||||
g_assert_nonnull(ret);
|
||||
qmp_assert_no_error(ret);
|
||||
QDECREF(ret);
|
||||
}
|
||||
|
||||
static void test_qga_guest_exec(gconstpointer fix)
|
||||
{
|
||||
const TestFixture *fixture = fix;
|
||||
@ -1029,13 +946,6 @@ int main(int argc, char **argv)
|
||||
g_test_add_data_func("/qga/guest-get-osinfo", &fix,
|
||||
test_qga_guest_get_osinfo);
|
||||
|
||||
if (g_getenv("QGA_TEST_SIDE_EFFECTING")) {
|
||||
g_test_add_data_func("/qga/fsfreeze-and-thaw", &fix,
|
||||
test_qga_fsfreeze_and_thaw);
|
||||
g_test_add_data_func("/qga/set-time", &fix, test_qga_set_time);
|
||||
g_test_add_data_func("/qga/fstrim", &fix, test_qga_fstrim);
|
||||
}
|
||||
|
||||
ret = g_test_run();
|
||||
|
||||
fixture_tear_down(&fix, NULL);
|
||||
|
@ -48,31 +48,9 @@ static void test_uhci_hotplug(void)
|
||||
|
||||
static void test_usb_storage_hotplug(void)
|
||||
{
|
||||
QDict *response;
|
||||
qtest_qmp_device_add("usb-storage", "usbdev0", "'drive': 'drive0'");
|
||||
|
||||
response = qmp("{'execute': 'device_add',"
|
||||
" 'arguments': {"
|
||||
" 'driver': 'usb-storage',"
|
||||
" 'drive': 'drive0',"
|
||||
" 'id': 'usbdev0'"
|
||||
"}}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
|
||||
response = qmp("{'execute': 'device_del',"
|
||||
" 'arguments': {"
|
||||
" 'id': 'usbdev0'"
|
||||
"}}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
|
||||
response = qmp("");
|
||||
g_assert(response);
|
||||
g_assert(qdict_haskey(response, "event"));
|
||||
g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));
|
||||
QDECREF(response);
|
||||
qtest_qmp_device_del("usbdev0");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
@ -23,59 +23,16 @@ static void test_xhci_hotplug(void)
|
||||
|
||||
static void test_usb_uas_hotplug(void)
|
||||
{
|
||||
QDict *response;
|
||||
|
||||
response = qmp("{'execute': 'device_add',"
|
||||
" 'arguments': {"
|
||||
" 'driver': 'usb-uas',"
|
||||
" 'id': 'uas'"
|
||||
"}}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
|
||||
response = qmp("{'execute': 'device_add',"
|
||||
" 'arguments': {"
|
||||
" 'driver': 'scsi-hd',"
|
||||
" 'drive': 'drive0',"
|
||||
" 'id': 'scsi-hd'"
|
||||
"}}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
qtest_qmp_device_add("usb-uas", "uas", NULL);
|
||||
qtest_qmp_device_add("scsi-hd", "scsihd", "'drive': 'drive0'");
|
||||
|
||||
/* TODO:
|
||||
UAS HBA driver in libqos, to check that
|
||||
added disk is visible after BUS rescan
|
||||
*/
|
||||
|
||||
response = qmp("{'execute': 'device_del',"
|
||||
" 'arguments': {"
|
||||
" 'id': 'scsi-hd'"
|
||||
"}}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
|
||||
response = qmp("");
|
||||
g_assert(qdict_haskey(response, "event"));
|
||||
g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));
|
||||
QDECREF(response);
|
||||
|
||||
|
||||
response = qmp("{'execute': 'device_del',"
|
||||
" 'arguments': {"
|
||||
" 'id': 'uas'"
|
||||
"}}");
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
|
||||
response = qmp("");
|
||||
g_assert(response);
|
||||
g_assert(qdict_haskey(response, "event"));
|
||||
g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));
|
||||
QDECREF(response);
|
||||
qtest_qmp_device_del("scsihd");
|
||||
qtest_qmp_device_del("uas");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
@ -192,32 +192,12 @@ static void pci_nop(void)
|
||||
|
||||
static void hotplug(void)
|
||||
{
|
||||
QDict *response;
|
||||
QOSState *qs;
|
||||
|
||||
qs = qvirtio_scsi_start(
|
||||
"-drive id=drv1,if=none,file=null-co://,format=raw");
|
||||
response = qmp("{\"execute\": \"device_add\","
|
||||
" \"arguments\": {"
|
||||
" \"driver\": \"scsi-hd\","
|
||||
" \"id\": \"scsi-hd\","
|
||||
" \"drive\": \"drv1\""
|
||||
"}}");
|
||||
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
|
||||
response = qmp("{\"execute\": \"device_del\","
|
||||
" \"arguments\": {"
|
||||
" \"id\": \"scsi-hd\""
|
||||
"}}");
|
||||
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
g_assert(qdict_haskey(response, "event"));
|
||||
g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));
|
||||
QDECREF(response);
|
||||
qtest_qmp_device_add("scsi-hd", "scsihd", "'drive': 'drv1'");
|
||||
qtest_qmp_device_del("scsihd");
|
||||
qvirtio_scsi_stop(qs);
|
||||
}
|
||||
|
||||
|
@ -17,28 +17,9 @@ static void pci_nop(void)
|
||||
|
||||
static void hotplug(void)
|
||||
{
|
||||
QDict *response;
|
||||
qtest_qmp_device_add("virtserialport", "hp-port", NULL);
|
||||
|
||||
response = qmp("{\"execute\": \"device_add\","
|
||||
" \"arguments\": {"
|
||||
" \"driver\": \"virtserialport\","
|
||||
" \"id\": \"hp-port\""
|
||||
"}}");
|
||||
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
QDECREF(response);
|
||||
|
||||
response = qmp("{\"execute\": \"device_del\","
|
||||
" \"arguments\": {"
|
||||
" \"id\": \"hp-port\""
|
||||
"}}");
|
||||
|
||||
g_assert(response);
|
||||
g_assert(!qdict_haskey(response, "error"));
|
||||
g_assert(qdict_haskey(response, "event"));
|
||||
g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED"));
|
||||
QDECREF(response);
|
||||
qtest_qmp_device_del("hp-port");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
Loading…
Reference in New Issue
Block a user