summaryrefslogtreecommitdiffstats
path: root/tests/qtest
diff options
context:
space:
mode:
authorStefan Hajnoczi2022-10-31 11:19:53 +0100
committerStefan Hajnoczi2022-10-31 11:19:54 +0100
commit395a90be6f0af51732540c5e632c0fe49222e28c (patch)
tree517b3eaac4b6a32fe03237ba9fbe9c9ad06ff4ad /tests/qtest
parentMerge tag 'mem-2022-10-28' of https://github.com/davidhildenbrand/qemu into s... (diff)
parenttests/qtest: libqtest: Correct the timeout unit of blocking receive calls for... (diff)
downloadqemu-395a90be6f0af51732540c5e632c0fe49222e28c.tar.gz
qemu-395a90be6f0af51732540c5e632c0fe49222e28c.tar.xz
qemu-395a90be6f0af51732540c5e632c0fe49222e28c.zip
Merge tag 'pull-request-2022-10-28' of https://gitlab.com/thuth/qemu into staging
* Fix and test the VISTR instruction on s390x * Some more small s390x fixes and maintainer updates * Make sure to remove all temporary files from qtests * OpenBSD VM test update to version 7.2 * Add sndio to FreeBSD tests * More patches to enable the qtests on Windows # -----BEGIN PGP SIGNATURE----- # # iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmNb1x8RHHRodXRoQHJl # ZGhhdC5jb20ACgkQLtnXdP5wLbXmcA//TCliiFkhprVxzIqy7zb9uz2Odu+sS4dT # azUSlXvC14fECm/Rb/rd2VLqCu5x2er8CYauxKQ4VhRImzcDta4kvpt/HKIppN2t # sqw5tipJL0DYcWBwYL1llvfutM26M+Oh0igwR8uV7b+W1FjojEZdcOr9IZ6E6V55 # wQCE5OHm0VCr61QeI5IBfZTsiPo+DFomUCpj7w66j6i0CVDvmpoe36tCmvGgrcpZ # SP7ep7/Iq+dnGh2YnJyoUOPlXeeiBCxAygOVnIRXptDeniGoliCFn7ksLdKDQ9qY # 69pSPR/W7mTZB/HkCRalAbYuYrI9Rcqxdu6c9vcyB8Pr0snQLTf8qThY+BJ2oC4w # JSGgWVniAk5MmrDazwNRkSbgngYLYf+CcT1h5AANuU5Kt50Bdy9Y3TuL5YVmofEp # N4bypV0ICImQyDECz76+i5/iJOcWiRyjMfLT6y00dspeuy983xHakrsHGD8xj0U/ # 3IVxnF9bDnUSVg6lFhYrgCB3dRG1TNPJoYQOM7raS5MAPRrDtIuSabwtyn84jo4+ # 9kZRPJBriMBHNsCjGVlJ9CATmaK1SKVAbRcabjgOKoIwhZTpAe6JalykREUJlTys # hB2V//lWWYPaSpzwY+OkvxoOmJIziixEskOmx6hPcoxID5v/bqlR69W15aUlKuLq # VWFb+/yMvaE= # =h0Ep # -----END PGP SIGNATURE----- # gpg: Signature made Fri 28 Oct 2022 09:20:31 EDT # gpg: using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5 # gpg: issuer "thuth@redhat.com" # gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full] # gpg: aka "Thomas Huth <thuth@redhat.com>" [full] # gpg: aka "Thomas Huth <huth@tuxfamily.org>" [full] # gpg: aka "Thomas Huth <th.huth@posteo.de>" [unknown] # Primary key fingerprint: 27B8 8847 EEE0 2501 18F3 EAB9 2ED9 D774 FE70 2DB5 * tag 'pull-request-2022-10-28' of https://gitlab.com/thuth/qemu: (21 commits) tests/qtest: libqtest: Correct the timeout unit of blocking receive calls for win32 tests/qtest: libqos: Do not build virtio-9p unconditionally tests/qtest: migration-test: Make sure QEMU process "to" exited after migration is canceled tests/qtest: libqtest: Introduce qtest_wait_qemu() tests/qtest: Use EXIT_FAILURE instead of magic number tests/qtest: device-plug-test: Reverse the usage of double/single quotes tests/qtest: Support libqtest to build and run on Windows tests/qtest: Use send/recv for socket communication accel/qtest: Support qtest accelerator for Windows tests: Add sndio to the FreeBSD CI containers / VM tests/vm: update openbsd to release 7.2 tests/qtest/libqos/e1000e: Use e1000_regs.h tests/qtest/cxl-test: Remove temporary directories after testing tests/qtest/tpm: Clean up remainders of swtpm MAINTAINERS: target/s390x/: add Ilya as reviewer tests/tcg/s390x: Add a test for the vistr instruction target/s390x: Fix emulation of the VISTR instruction tests/tcg/s390x: Test compiler flags only once, not every time s390x/tod-kvm: don't save/restore the TOD in PV guests s390x: step down as general arch maintainer ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'tests/qtest')
-rw-r--r--tests/qtest/cxl-test.c3
-rw-r--r--tests/qtest/dbus-vmstate-test.c2
-rw-r--r--tests/qtest/device-plug-test.c16
-rw-r--r--tests/qtest/libqmp.c5
-rw-r--r--tests/qtest/libqos/e1000e.c119
-rw-r--r--tests/qtest/libqos/meson.build6
-rw-r--r--tests/qtest/libqtest.c151
-rw-r--r--tests/qtest/libqtest.h9
-rw-r--r--tests/qtest/migration-test.c8
-rw-r--r--tests/qtest/tpm-crb-swtpm-test.c5
-rw-r--r--tests/qtest/tpm-tis-device-swtpm-test.c5
-rw-r--r--tests/qtest/tpm-tis-swtpm-test.c5
-rw-r--r--tests/qtest/tpm-util.c19
-rw-r--r--tests/qtest/tpm-util.h1
14 files changed, 237 insertions, 117 deletions
diff --git a/tests/qtest/cxl-test.c b/tests/qtest/cxl-test.c
index cbe0fb549b..61f25a72b6 100644
--- a/tests/qtest/cxl-test.c
+++ b/tests/qtest/cxl-test.c
@@ -101,6 +101,7 @@ static void cxl_t3d(void)
qtest_start(cmdline->str);
qtest_end();
+ rmdir(tmpfs);
}
static void cxl_1pxb_2rp_2t3d(void)
@@ -115,6 +116,7 @@ static void cxl_1pxb_2rp_2t3d(void)
qtest_start(cmdline->str);
qtest_end();
+ rmdir(tmpfs);
}
static void cxl_2pxb_4rp_4t3d(void)
@@ -130,6 +132,7 @@ static void cxl_2pxb_4rp_4t3d(void)
qtest_start(cmdline->str);
qtest_end();
+ rmdir(tmpfs);
}
#endif /* CONFIG_POSIX */
diff --git a/tests/qtest/dbus-vmstate-test.c b/tests/qtest/dbus-vmstate-test.c
index 74ede651f6..6c990864e3 100644
--- a/tests/qtest/dbus-vmstate-test.c
+++ b/tests/qtest/dbus-vmstate-test.c
@@ -233,7 +233,7 @@ test_dbus_vmstate(Test *test)
test->src_qemu = src_qemu;
if (test->migrate_fail) {
wait_for_migration_fail(src_qemu, true);
- qtest_set_expected_status(dst_qemu, 1);
+ qtest_set_expected_status(dst_qemu, EXIT_FAILURE);
} else {
wait_for_migration_complete(src_qemu);
}
diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c
index 3f44f731d1..5a6afa2b57 100644
--- a/tests/qtest/device-plug-test.c
+++ b/tests/qtest/device-plug-test.c
@@ -112,16 +112,16 @@ static void test_pci_unplug_json_request(void)
static void test_q35_pci_unplug_json_request(void)
{
- const char *port = "-device '{\"driver\": \"pcie-root-port\", "
- "\"id\": \"p1\"}'";
+ const char *port = "-device \"{'driver': 'pcie-root-port', "
+ "'id': 'p1'}\"";
- const char *bridge = "-device '{\"driver\": \"pcie-pci-bridge\", "
- "\"id\": \"b1\", "
- "\"bus\": \"p1\"}'";
+ const char *bridge = "-device \"{'driver': 'pcie-pci-bridge', "
+ "'id': 'b1', "
+ "'bus': 'p1'}\"";
- const char *device = "-device '{\"driver\": \"virtio-mouse-pci\", "
- "\"bus\": \"b1\", "
- "\"id\": \"dev0\"}'";
+ const char *device = "-device \"{'driver': 'virtio-mouse-pci', "
+ "'bus': 'b1', "
+ "'id': 'dev0'}\"";
QTestState *qtest = qtest_initf("-machine q35 %s %s %s",
port, bridge, device);
diff --git a/tests/qtest/libqmp.c b/tests/qtest/libqmp.c
index ade26c15f0..2b08382e5d 100644
--- a/tests/qtest/libqmp.c
+++ b/tests/qtest/libqmp.c
@@ -23,6 +23,7 @@
#endif
#include "qemu/cutils.h"
+#include "qemu/sockets.h"
#include "qapi/error.h"
#include "qapi/qmp/json-parser.h"
#include "qapi/qmp/qjson.h"
@@ -36,7 +37,7 @@ typedef struct {
static void socket_send(int fd, const char *buf, size_t size)
{
- size_t res = qemu_write_full(fd, buf, size);
+ ssize_t res = qemu_send_full(fd, buf, size);
assert(res == size);
}
@@ -69,7 +70,7 @@ QDict *qmp_fd_receive(int fd)
ssize_t len;
char c;
- len = read(fd, &c, 1);
+ len = recv(fd, &c, 1, 0);
if (len == -1 && errno == EINTR) {
continue;
}
diff --git a/tests/qtest/libqos/e1000e.c b/tests/qtest/libqos/e1000e.c
index fc14b07884..ed47e34044 100644
--- a/tests/qtest/libqos/e1000e.c
+++ b/tests/qtest/libqos/e1000e.c
@@ -17,6 +17,7 @@
*/
#include "qemu/osdep.h"
+#include "hw/net/e1000_regs.h"
#include "../libqtest.h"
#include "pci-pc.h"
#include "qemu/sockets.h"
@@ -27,49 +28,13 @@
#include "qgraph.h"
#include "e1000e.h"
-#define E1000E_IMS (0x00d0)
+#define E1000E_IVAR_TEST_CFG \
+ (E1000E_RX0_MSG_ID | E1000_IVAR_INT_ALLOC_VALID | \
+ ((E1000E_TX0_MSG_ID | E1000_IVAR_INT_ALLOC_VALID) << 8) | \
+ ((E1000E_OTHER_MSG_ID | E1000_IVAR_INT_ALLOC_VALID) << 16) | \
+ E1000_IVAR_TX_INT_EVERY_WB)
-#define E1000E_STATUS (0x0008)
-#define E1000E_STATUS_LU BIT(1)
-#define E1000E_STATUS_ASDV1000 BIT(9)
-
-#define E1000E_CTRL (0x0000)
-#define E1000E_CTRL_RESET BIT(26)
-
-#define E1000E_RCTL (0x0100)
-#define E1000E_RCTL_EN BIT(1)
-#define E1000E_RCTL_UPE BIT(3)
-#define E1000E_RCTL_MPE BIT(4)
-
-#define E1000E_RFCTL (0x5008)
-#define E1000E_RFCTL_EXTEN BIT(15)
-
-#define E1000E_TCTL (0x0400)
-#define E1000E_TCTL_EN BIT(1)
-
-#define E1000E_CTRL_EXT (0x0018)
-#define E1000E_CTRL_EXT_DRV_LOAD BIT(28)
-#define E1000E_CTRL_EXT_TXLSFLOW BIT(22)
-
-#define E1000E_IVAR (0x00E4)
-#define E1000E_IVAR_TEST_CFG ((E1000E_RX0_MSG_ID << 0) | BIT(3) | \
- (E1000E_TX0_MSG_ID << 8) | BIT(11) | \
- (E1000E_OTHER_MSG_ID << 16) | BIT(19) | \
- BIT(31))
-
-#define E1000E_RING_LEN (0x1000)
-
-#define E1000E_TDBAL (0x3800)
-
-#define E1000E_TDBAH (0x3804)
-#define E1000E_TDH (0x3810)
-
-#define E1000E_RDBAL (0x2800)
-#define E1000E_RDBAH (0x2804)
-#define E1000E_RDH (0x2810)
-
-#define E1000E_TXD_LEN (16)
-#define E1000E_RXD_LEN (16)
+#define E1000E_RING_LEN (0x1000)
static void e1000e_macreg_write(QE1000E *d, uint32_t reg, uint32_t val)
{
@@ -87,30 +52,34 @@ void e1000e_tx_ring_push(QE1000E *d, void *descr)
{
QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e);
uint32_t tail = e1000e_macreg_read(d, E1000E_TDT);
- uint32_t len = e1000e_macreg_read(d, E1000E_TDLEN) / E1000E_TXD_LEN;
+ uint32_t len = e1000e_macreg_read(d, E1000E_TDLEN) / E1000_RING_DESC_LEN;
- qtest_memwrite(d_pci->pci_dev.bus->qts, d->tx_ring + tail * E1000E_TXD_LEN,
- descr, E1000E_TXD_LEN);
+ qtest_memwrite(d_pci->pci_dev.bus->qts,
+ d->tx_ring + tail * E1000_RING_DESC_LEN,
+ descr, E1000_RING_DESC_LEN);
e1000e_macreg_write(d, E1000E_TDT, (tail + 1) % len);
/* Read WB data for the packet transmitted */
- qtest_memread(d_pci->pci_dev.bus->qts, d->tx_ring + tail * E1000E_TXD_LEN,
- descr, E1000E_TXD_LEN);
+ qtest_memread(d_pci->pci_dev.bus->qts,
+ d->tx_ring + tail * E1000_RING_DESC_LEN,
+ descr, E1000_RING_DESC_LEN);
}
void e1000e_rx_ring_push(QE1000E *d, void *descr)
{
QE1000E_PCI *d_pci = container_of(d, QE1000E_PCI, e1000e);
uint32_t tail = e1000e_macreg_read(d, E1000E_RDT);
- uint32_t len = e1000e_macreg_read(d, E1000E_RDLEN) / E1000E_RXD_LEN;
+ uint32_t len = e1000e_macreg_read(d, E1000E_RDLEN) / E1000_RING_DESC_LEN;
- qtest_memwrite(d_pci->pci_dev.bus->qts, d->rx_ring + tail * E1000E_RXD_LEN,
- descr, E1000E_RXD_LEN);
+ qtest_memwrite(d_pci->pci_dev.bus->qts,
+ d->rx_ring + tail * E1000_RING_DESC_LEN,
+ descr, E1000_RING_DESC_LEN);
e1000e_macreg_write(d, E1000E_RDT, (tail + 1) % len);
/* Read WB data for the packet received */
- qtest_memread(d_pci->pci_dev.bus->qts, d->rx_ring + tail * E1000E_RXD_LEN,
- descr, E1000E_RXD_LEN);
+ qtest_memread(d_pci->pci_dev.bus->qts,
+ d->rx_ring + tail * E1000_RING_DESC_LEN,
+ descr, E1000_RING_DESC_LEN);
}
static void e1000e_foreach_callback(QPCIDevice *dev, int devfn, void *data)
@@ -151,53 +120,53 @@ static void e1000e_pci_start_hw(QOSGraphObject *obj)
qpci_device_enable(&d->pci_dev);
/* Reset the device */
- val = e1000e_macreg_read(&d->e1000e, E1000E_CTRL);
- e1000e_macreg_write(&d->e1000e, E1000E_CTRL, val | E1000E_CTRL_RESET);
+ val = e1000e_macreg_read(&d->e1000e, E1000_CTRL);
+ e1000e_macreg_write(&d->e1000e, E1000_CTRL, val | E1000_CTRL_RST);
/* Enable and configure MSI-X */
qpci_msix_enable(&d->pci_dev);
- e1000e_macreg_write(&d->e1000e, E1000E_IVAR, E1000E_IVAR_TEST_CFG);
+ e1000e_macreg_write(&d->e1000e, E1000_IVAR, E1000E_IVAR_TEST_CFG);
/* Check the device status - link and speed */
- val = e1000e_macreg_read(&d->e1000e, E1000E_STATUS);
- g_assert_cmphex(val & (E1000E_STATUS_LU | E1000E_STATUS_ASDV1000),
- ==, E1000E_STATUS_LU | E1000E_STATUS_ASDV1000);
+ val = e1000e_macreg_read(&d->e1000e, E1000_STATUS);
+ g_assert_cmphex(val & (E1000_STATUS_LU | E1000_STATUS_LAN_INIT_DONE),
+ ==, E1000_STATUS_LU | E1000_STATUS_LAN_INIT_DONE);
/* Initialize TX/RX logic */
- e1000e_macreg_write(&d->e1000e, E1000E_RCTL, 0);
- e1000e_macreg_write(&d->e1000e, E1000E_TCTL, 0);
+ e1000e_macreg_write(&d->e1000e, E1000_RCTL, 0);
+ e1000e_macreg_write(&d->e1000e, E1000_TCTL, 0);
/* Notify the device that the driver is ready */
- val = e1000e_macreg_read(&d->e1000e, E1000E_CTRL_EXT);
- e1000e_macreg_write(&d->e1000e, E1000E_CTRL_EXT,
- val | E1000E_CTRL_EXT_DRV_LOAD | E1000E_CTRL_EXT_TXLSFLOW);
+ val = e1000e_macreg_read(&d->e1000e, E1000_CTRL_EXT);
+ e1000e_macreg_write(&d->e1000e, E1000_CTRL_EXT,
+ val | E1000_CTRL_EXT_DRV_LOAD);
- e1000e_macreg_write(&d->e1000e, E1000E_TDBAL,
+ e1000e_macreg_write(&d->e1000e, E1000_TDBAL,
(uint32_t) d->e1000e.tx_ring);
- e1000e_macreg_write(&d->e1000e, E1000E_TDBAH,
+ e1000e_macreg_write(&d->e1000e, E1000_TDBAH,
(uint32_t) (d->e1000e.tx_ring >> 32));
e1000e_macreg_write(&d->e1000e, E1000E_TDLEN, E1000E_RING_LEN);
e1000e_macreg_write(&d->e1000e, E1000E_TDT, 0);
- e1000e_macreg_write(&d->e1000e, E1000E_TDH, 0);
+ e1000e_macreg_write(&d->e1000e, E1000_TDH, 0);
/* Enable transmit */
- e1000e_macreg_write(&d->e1000e, E1000E_TCTL, E1000E_TCTL_EN);
- e1000e_macreg_write(&d->e1000e, E1000E_RDBAL,
+ e1000e_macreg_write(&d->e1000e, E1000_TCTL, E1000_TCTL_EN);
+ e1000e_macreg_write(&d->e1000e, E1000_RDBAL,
(uint32_t)d->e1000e.rx_ring);
- e1000e_macreg_write(&d->e1000e, E1000E_RDBAH,
+ e1000e_macreg_write(&d->e1000e, E1000_RDBAH,
(uint32_t)(d->e1000e.rx_ring >> 32));
e1000e_macreg_write(&d->e1000e, E1000E_RDLEN, E1000E_RING_LEN);
e1000e_macreg_write(&d->e1000e, E1000E_RDT, 0);
- e1000e_macreg_write(&d->e1000e, E1000E_RDH, 0);
+ e1000e_macreg_write(&d->e1000e, E1000_RDH, 0);
/* Enable receive */
- e1000e_macreg_write(&d->e1000e, E1000E_RFCTL, E1000E_RFCTL_EXTEN);
- e1000e_macreg_write(&d->e1000e, E1000E_RCTL, E1000E_RCTL_EN |
- E1000E_RCTL_UPE |
- E1000E_RCTL_MPE);
+ e1000e_macreg_write(&d->e1000e, E1000_RFCTL, E1000_RFCTL_EXTEN);
+ e1000e_macreg_write(&d->e1000e, E1000_RCTL, E1000_RCTL_EN |
+ E1000_RCTL_UPE |
+ E1000_RCTL_MPE);
/* Enable all interrupts */
- e1000e_macreg_write(&d->e1000e, E1000E_IMS, 0xFFFFFFFF);
+ e1000e_macreg_write(&d->e1000e, E1000_IMS, 0xFFFFFFFF);
}
diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build
index 113c80b4e4..32f028872c 100644
--- a/tests/qtest/libqos/meson.build
+++ b/tests/qtest/libqos/meson.build
@@ -33,8 +33,6 @@ libqos_srcs = files(
'sdhci.c',
'tpci200.c',
'virtio.c',
- 'virtio-9p.c',
- 'virtio-9p-client.c',
'virtio-balloon.c',
'virtio-blk.c',
'vhost-user-blk.c',
@@ -62,6 +60,10 @@ libqos_srcs = files(
'x86_64_pc-machine.c',
)
+if have_virtfs
+ libqos_srcs += files('virtio-9p.c', 'virtio-9p-client.c')
+endif
+
libqos = static_library('qos', libqos_srcs + genh,
name_suffix: 'fa',
build_by_default: false)
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index b23eb3edc3..2fbc3b88f3 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -16,9 +16,11 @@
#include "qemu/osdep.h"
+#ifndef _WIN32
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
+#endif /* _WIN32 */
#ifdef __linux__
#include <sys/prctl.h>
#endif /* __linux__ */
@@ -27,13 +29,25 @@
#include "libqmp.h"
#include "qemu/ctype.h"
#include "qemu/cutils.h"
+#include "qemu/sockets.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h"
#define MAX_IRQ 256
-#define SOCKET_TIMEOUT 50
+
+#ifndef _WIN32
+# define SOCKET_TIMEOUT 50
+# define CMD_EXEC "exec "
+# define DEV_STDERR "/dev/fd/2"
+# define DEV_NULL "/dev/null"
+#else
+# define SOCKET_TIMEOUT 50000
+# define CMD_EXEC ""
+# define DEV_STDERR "2"
+# define DEV_NULL "nul"
+#endif
typedef void (*QTestSendFn)(QTestState *s, const char *buf);
typedef void (*ExternalSendFn)(void *s, const char *buf);
@@ -57,6 +71,9 @@ struct QTestState
int qmp_fd;
pid_t qemu_pid; /* our child QEMU process */
int wstatus;
+#ifdef _WIN32
+ DWORD exit_code;
+#endif
int expected_status;
bool big_endian;
bool irq_level[MAX_IRQ];
@@ -90,8 +107,16 @@ static int socket_accept(int sock)
struct sockaddr_un addr;
socklen_t addrlen;
int ret;
+ /*
+ * timeout unit of blocking receive calls is different among platfoms.
+ * It's in seconds on non-Windows platforms but milliseconds on Windows.
+ */
+#ifndef _WIN32
struct timeval timeout = { .tv_sec = SOCKET_TIMEOUT,
.tv_usec = 0 };
+#else
+ DWORD timeout = SOCKET_TIMEOUT;
+#endif
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
(void *)&timeout, sizeof(timeout))) {
@@ -118,10 +143,18 @@ bool qtest_probe_child(QTestState *s)
pid_t pid = s->qemu_pid;
if (pid != -1) {
+#ifndef _WIN32
pid = waitpid(pid, &s->wstatus, WNOHANG);
if (pid == 0) {
return true;
}
+#else
+ GetExitCodeProcess((HANDLE)pid, &s->exit_code);
+ if (s->exit_code == STILL_ACTIVE) {
+ return true;
+ }
+ CloseHandle((HANDLE)pid);
+#endif
s->qemu_pid = -1;
}
return false;
@@ -132,24 +165,14 @@ void qtest_set_expected_status(QTestState *s, int status)
s->expected_status = status;
}
-void qtest_kill_qemu(QTestState *s)
+static void qtest_check_status(QTestState *s)
{
- pid_t pid = s->qemu_pid;
- int wstatus;
-
- /* Skip wait if qtest_probe_child already reaped. */
- if (pid != -1) {
- kill(pid, SIGTERM);
- TFR(pid = waitpid(s->qemu_pid, &s->wstatus, 0));
- assert(pid == s->qemu_pid);
- s->qemu_pid = -1;
- }
-
/*
* Check whether qemu exited with expected exit status; anything else is
* fishy and should be logged with as much detail as possible.
*/
- wstatus = s->wstatus;
+#ifndef _WIN32
+ int wstatus = s->wstatus;
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != s->expected_status) {
fprintf(stderr, "%s:%d: kill_qemu() tried to terminate QEMU "
"process but encountered exit status %d (expected %d)\n",
@@ -165,6 +188,50 @@ void qtest_kill_qemu(QTestState *s)
__FILE__, __LINE__, sig, signame, dump);
abort();
}
+#else
+ if (s->exit_code != s->expected_status) {
+ fprintf(stderr, "%s:%d: kill_qemu() tried to terminate QEMU "
+ "process but encountered exit status %ld (expected %d)\n",
+ __FILE__, __LINE__, s->exit_code, s->expected_status);
+ abort();
+ }
+#endif
+}
+
+void qtest_wait_qemu(QTestState *s)
+{
+#ifndef _WIN32
+ pid_t pid;
+
+ TFR(pid = waitpid(s->qemu_pid, &s->wstatus, 0));
+ assert(pid == s->qemu_pid);
+#else
+ DWORD ret;
+
+ ret = WaitForSingleObject((HANDLE)s->qemu_pid, INFINITE);
+ assert(ret == WAIT_OBJECT_0);
+ GetExitCodeProcess((HANDLE)s->qemu_pid, &s->exit_code);
+ CloseHandle((HANDLE)s->qemu_pid);
+#endif
+
+ qtest_check_status(s);
+}
+
+void qtest_kill_qemu(QTestState *s)
+{
+ /* Skip wait if qtest_probe_child() already reaped */
+ if (s->qemu_pid != -1) {
+#ifndef _WIN32
+ kill(s->qemu_pid, SIGTERM);
+#else
+ TerminateProcess((HANDLE)s->qemu_pid, s->expected_status);
+#endif
+ qtest_wait_qemu(s);
+ s->qemu_pid = -1;
+ return;
+ }
+
+ qtest_check_status(s);
}
static void kill_qemu_hook_func(void *s)
@@ -243,6 +310,38 @@ static const char *qtest_qemu_binary(void)
return qemu_bin;
}
+#ifdef _WIN32
+static pid_t qtest_create_process(char *cmd)
+{
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ BOOL ret;
+
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+ ZeroMemory(&pi, sizeof(pi));
+
+ ret = CreateProcess(NULL, /* module name */
+ cmd, /* command line */
+ NULL, /* process handle not inheritable */
+ NULL, /* thread handle not inheritable */
+ FALSE, /* set handle inheritance to FALSE */
+ 0, /* No creation flags */
+ NULL, /* use parent's environment block */
+ NULL, /* use parent's starting directory */
+ &si, /* pointer to STARTUPINFO structure */
+ &pi /* pointer to PROCESS_INFORMATION structure */
+ );
+ if (ret == 0) {
+ fprintf(stderr, "%s:%d: unable to create a new process (%s)\n",
+ __FILE__, __LINE__, strerror(GetLastError()));
+ abort();
+ }
+
+ return (pid_t)pi.hProcess;
+}
+#endif /* _WIN32 */
+
QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
{
QTestState *s;
@@ -270,6 +369,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
unlink(socket_path);
unlink(qmp_socket_path);
+ socket_init();
sock = init_socket(socket_path);
qmpsock = init_socket(qmp_socket_path);
@@ -278,7 +378,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
qtest_add_abrt_handler(kill_qemu_hook_func, s);
- command = g_strdup_printf("exec %s %s"
+ command = g_strdup_printf(CMD_EXEC "%s %s"
"-qtest unix:%s "
"-qtest-log %s "
"-chardev socket,path=%s,id=char0 "
@@ -287,7 +387,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
"%s"
" -accel qtest",
qemu_binary, tracearg, socket_path,
- getenv("QTEST_LOG") ? "/dev/fd/2" : "/dev/null",
+ getenv("QTEST_LOG") ? DEV_STDERR : DEV_NULL,
qmp_socket_path,
extra_args ?: "");
@@ -296,6 +396,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
s->pending_events = NULL;
s->wstatus = 0;
s->expected_status = 0;
+#ifndef _WIN32
s->qemu_pid = fork();
if (s->qemu_pid == 0) {
#ifdef __linux__
@@ -318,6 +419,9 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
execlp("/bin/sh", "sh", "-c", command, NULL);
exit(1);
}
+#else
+ s->qemu_pid = qtest_create_process(command);
+#endif /* _WIN32 */
g_free(command);
s->fd = socket_accept(sock);
@@ -336,9 +440,19 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
s->irq_level[i] = false;
}
+ /*
+ * Stopping QEMU for debugging is not supported on Windows.
+ *
+ * Using DebugActiveProcess() API can suspend the QEMU process,
+ * but gdb cannot attach to the process. Using the undocumented
+ * NtSuspendProcess() can suspend the QEMU process and gdb can
+ * attach to the process, but gdb cannot resume it.
+ */
+#ifndef _WIN32
if (getenv("QTEST_STOP")) {
kill(s->qemu_pid, SIGSTOP);
}
+#endif
/* ask endianness of the target */
@@ -392,6 +506,7 @@ QTestState *qtest_init_with_serial(const char *extra_args, int *sock_fd)
g_assert_true(sock_dir != NULL);
sock_path = g_strdup_printf("%s/sock", sock_dir);
+ socket_init();
sock_fd_init = init_socket(sock_path);
qts = qtest_initf("-chardev socket,id=s0,path=%s -serial chardev:s0 %s",
@@ -428,7 +543,7 @@ void qtest_quit(QTestState *s)
static void socket_send(int fd, const char *buf, size_t size)
{
- size_t res = qemu_write_full(fd, buf, size);
+ ssize_t res = qemu_send_full(fd, buf, size);
assert(res == size);
}
@@ -460,7 +575,7 @@ static GString *qtest_client_socket_recv_line(QTestState *s)
ssize_t len;
char buffer[1024];
- len = read(s->fd, buffer, sizeof(buffer));
+ len = recv(s->fd, buffer, sizeof(buffer), 0);
if (len == -1 && errno == EINTR) {
continue;
}
diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
index 65c040e504..91a5f7edd9 100644
--- a/tests/qtest/libqtest.h
+++ b/tests/qtest/libqtest.h
@@ -76,6 +76,15 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args);
QTestState *qtest_init_with_serial(const char *extra_args, int *sock_fd);
/**
+ * qtest_wait_qemu:
+ * @s: #QTestState instance to operate on.
+ *
+ * Wait for the QEMU process to terminate. It is safe to call this function
+ * multiple times.
+ */
+void qtest_wait_qemu(QTestState *s);
+
+/**
* qtest_kill_qemu:
* @s: #QTestState instance to operate on.
*
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index aa1ba179fa..d2eb107f0c 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1342,7 +1342,7 @@ static void test_precopy_common(MigrateCommon *args)
wait_for_migration_fail(from, allow_active);
if (args->result == MIG_TEST_FAIL_DEST_QUIT_ERR) {
- qtest_set_expected_status(to, 1);
+ qtest_set_expected_status(to, EXIT_FAILURE);
}
} else {
if (args->iterations) {
@@ -1738,7 +1738,7 @@ static void do_test_validate_uuid(MigrateStart *args, bool should_fail)
migrate_qmp(from, uri, "{}");
if (should_fail) {
- qtest_set_expected_status(to, 1);
+ qtest_set_expected_status(to, EXIT_FAILURE);
wait_for_migration_fail(from, true);
} else {
wait_for_migration_complete(from);
@@ -2141,6 +2141,10 @@ static void test_multifd_tcp_cancel(void)
migrate_cancel(from);
+ /* Make sure QEMU process "to" exited */
+ qtest_set_expected_status(to, EXIT_FAILURE);
+ qtest_wait_qemu(to);
+
args = (MigrateStart){
.only_target = true,
};
diff --git a/tests/qtest/tpm-crb-swtpm-test.c b/tests/qtest/tpm-crb-swtpm-test.c
index 55fdb5657d..40254f762f 100644
--- a/tests/qtest/tpm-crb-swtpm-test.c
+++ b/tests/qtest/tpm-crb-swtpm-test.c
@@ -13,7 +13,6 @@
*/
#include "qemu/osdep.h"
-#include <glib/gstdio.h>
#include "libqtest.h"
#include "qemu/module.h"
@@ -62,9 +61,9 @@ int main(int argc, char **argv)
tpm_crb_swtpm_migration_test);
ret = g_test_run();
- g_rmdir(ts.dst_tpm_path);
+ tpm_util_rmdir(ts.dst_tpm_path);
g_free(ts.dst_tpm_path);
- g_rmdir(ts.src_tpm_path);
+ tpm_util_rmdir(ts.src_tpm_path);
g_free(ts.src_tpm_path);
g_free(ts.uri);
diff --git a/tests/qtest/tpm-tis-device-swtpm-test.c b/tests/qtest/tpm-tis-device-swtpm-test.c
index 7b20035142..8c067fddd4 100644
--- a/tests/qtest/tpm-tis-device-swtpm-test.c
+++ b/tests/qtest/tpm-tis-device-swtpm-test.c
@@ -14,7 +14,6 @@
*/
#include "qemu/osdep.h"
-#include <glib/gstdio.h>
#include "libqtest.h"
#include "qemu/module.h"
@@ -66,9 +65,9 @@ int main(int argc, char **argv)
tpm_tis_swtpm_migration_test);
ret = g_test_run();
- g_rmdir(ts.dst_tpm_path);
+ tpm_util_rmdir(ts.dst_tpm_path);
g_free(ts.dst_tpm_path);
- g_rmdir(ts.src_tpm_path);
+ tpm_util_rmdir(ts.src_tpm_path);
g_free(ts.src_tpm_path);
g_free(ts.uri);
diff --git a/tests/qtest/tpm-tis-swtpm-test.c b/tests/qtest/tpm-tis-swtpm-test.c
index 90131cb3c4..11539c0a52 100644
--- a/tests/qtest/tpm-tis-swtpm-test.c
+++ b/tests/qtest/tpm-tis-swtpm-test.c
@@ -13,7 +13,6 @@
*/
#include "qemu/osdep.h"
-#include <glib/gstdio.h>
#include "libqtest.h"
#include "qemu/module.h"
@@ -61,9 +60,9 @@ int main(int argc, char **argv)
tpm_tis_swtpm_migration_test);
ret = g_test_run();
- g_rmdir(ts.dst_tpm_path);
+ tpm_util_rmdir(ts.dst_tpm_path);
g_free(ts.dst_tpm_path);
- g_rmdir(ts.src_tpm_path);
+ tpm_util_rmdir(ts.src_tpm_path);
g_free(ts.src_tpm_path);
g_free(ts.uri);
diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
index e0dc5da0af..a7efe2d0d2 100644
--- a/tests/qtest/tpm-util.c
+++ b/tests/qtest/tpm-util.c
@@ -13,6 +13,7 @@
*/
#include "qemu/osdep.h"
+#include <glib/gstdio.h>
#include "hw/acpi/tpm.h"
#include "libqtest.h"
@@ -292,3 +293,21 @@ void tpm_util_migration_start_qemu(QTestState **src_qemu,
g_free(src_qemu_args);
g_free(dst_qemu_args);
}
+
+/* Remove directory with remainders of swtpm */
+void tpm_util_rmdir(const char *path)
+{
+ char *filename;
+ int ret;
+
+ filename = g_strdup_printf("%s/tpm2-00.permall", path);
+ g_unlink(filename);
+ g_free(filename);
+
+ filename = g_strdup_printf("%s/.lock", path);
+ g_unlink(filename);
+ g_free(filename);
+
+ ret = g_rmdir(path);
+ g_assert(!ret);
+}
diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h
index 3b97d69017..80720afac0 100644
--- a/tests/qtest/tpm-util.h
+++ b/tests/qtest/tpm-util.h
@@ -53,5 +53,6 @@ void tpm_util_migration_start_qemu(QTestState **src_qemu,
const char *machine_options);
void tpm_util_wait_for_migration_complete(QTestState *who);
+void tpm_util_rmdir(const char *path);
#endif /* TESTS_TPM_UTIL_H */