summaryrefslogtreecommitdiffstats
path: root/tests/qtest/libqtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/qtest/libqtest.c')
-rw-r--r--tests/qtest/libqtest.c110
1 files changed, 54 insertions, 56 deletions
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index 58f58e1ece..08929f5ff6 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -63,6 +63,7 @@ struct QTestState
bool irq_level[MAX_IRQ];
GString *rx;
QTestTransportOps ops;
+ GList *pending_events;
};
static GHookList abrt_hooks;
@@ -279,6 +280,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
g_test_message("starting QEMU: %s", command);
+ s->pending_events = NULL;
s->wstatus = 0;
s->expected_status = 0;
s->qemu_pid = fork();
@@ -386,6 +388,13 @@ void qtest_quit(QTestState *s)
close(s->fd);
close(s->qmp_fd);
g_string_free(s->rx, true);
+
+ for (GList *it = s->pending_events; it != NULL; it = it->next) {
+ qobject_unref((QDict *)it->data);
+ }
+
+ g_list_free(s->pending_events);
+
g_free(s);
}
@@ -605,6 +614,19 @@ QDict *qmp_fd_receive(int fd)
QDict *qtest_qmp_receive(QTestState *s)
{
+ while (true) {
+ QDict *response = qtest_qmp_receive_dict(s);
+
+ if (!qdict_get_try_str(response, "event")) {
+ return response;
+ }
+ /* Stash the event for a later consumption */
+ s->pending_events = g_list_prepend(s->pending_events, response);
+ }
+}
+
+QDict *qtest_qmp_receive_dict(QTestState *s)
+{
return qmp_fd_receive(s->qmp_fd);
}
@@ -771,12 +793,36 @@ void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...)
va_end(ap);
}
-QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event)
+QDict *qtest_qmp_event_ref(QTestState *s, const char *event)
{
+ GList *next = NULL;
QDict *response;
+ for (GList *it = s->pending_events; it != NULL; it = next) {
+
+ next = it->next;
+ response = (QDict *)it->data;
+
+ s->pending_events = g_list_remove_link(s->pending_events, it);
+
+ if (!strcmp(qdict_get_str(response, "event"), event)) {
+ return response;
+ }
+ qobject_unref(response);
+ }
+ return NULL;
+}
+
+QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event)
+{
+ QDict *response = qtest_qmp_event_ref(s, event);
+
+ if (response) {
+ return response;
+ }
+
for (;;) {
- response = qtest_qmp_receive(s);
+ response = qtest_qmp_receive_dict(s);
if ((qdict_haskey(response, "event")) &&
(strcmp(qdict_get_str(response, "event"), event) == 0)) {
return response;
@@ -804,12 +850,6 @@ char *qtest_vhmp(QTestState *s, const char *fmt, va_list ap)
" 'arguments': {'command-line': %s}}",
cmd);
ret = g_strdup(qdict_get_try_str(resp, "return"));
- while (ret == NULL && qdict_get_try_str(resp, "event")) {
- /* Ignore asynchronous QMP events */
- qobject_unref(resp);
- resp = qtest_qmp_receive(s);
- ret = g_strdup(qdict_get_try_str(resp, "return"));
- }
g_assert(ret);
qobject_unref(resp);
g_free(cmd);
@@ -1245,35 +1285,6 @@ void qtest_cb_for_every_machine(void (*cb)(const char *machine),
qobject_unref(response);
}
-QDict *qtest_qmp_receive_success(QTestState *s,
- void (*event_cb)(void *opaque,
- const char *event,
- QDict *data),
- void *opaque)
-{
- QDict *response, *ret, *data;
- const char *event;
-
- for (;;) {
- response = qtest_qmp_receive(s);
- g_assert(!qdict_haskey(response, "error"));
- ret = qdict_get_qdict(response, "return");
- if (ret) {
- break;
- }
- event = qdict_get_str(response, "event");
- data = qdict_get_qdict(response, "data");
- if (event_cb) {
- event_cb(opaque, event, data);
- }
- qobject_unref(response);
- }
-
- qobject_ref(ret);
- qobject_unref(response);
- return ret;
-}
-
/*
* Generic hot-plugging test via the device_add QMP commands.
*/
@@ -1309,13 +1320,6 @@ void qtest_qmp_device_add(QTestState *qts, const char *driver, const char *id,
qobject_unref(args);
}
-static void device_deleted_cb(void *opaque, const char *name, QDict *data)
-{
- bool *got_event = opaque;
-
- g_assert_cmpstr(name, ==, "DEVICE_DELETED");
- *got_event = true;
-}
/*
* Generic hot-unplugging test via the device_del QMP command.
@@ -1332,24 +1336,17 @@ static void device_deleted_cb(void *opaque, const char *name, QDict *data)
* and this one:
*
* {"return": {}}
- *
- * But the order of arrival may vary - so we've got to detect both.
*/
void qtest_qmp_device_del(QTestState *qts, const char *id)
{
- bool got_event = false;
QDict *rsp;
- qtest_qmp_send(qts, "{'execute': 'device_del', 'arguments': {'id': %s}}",
- id);
- rsp = qtest_qmp_receive_success(qts, device_deleted_cb, &got_event);
+ rsp = qtest_qmp(qts, "{'execute': 'device_del', 'arguments': {'id': %s}}",
+ id);
+
+ g_assert(qdict_haskey(rsp, "return"));
qobject_unref(rsp);
- if (!got_event) {
- rsp = qtest_qmp_receive(qts);
- g_assert_cmpstr(qdict_get_try_str(rsp, "event"),
- ==, "DEVICE_DELETED");
- qobject_unref(rsp);
- }
+ qtest_qmp_eventwait(qts, "DEVICE_DELETED");
}
bool qmp_rsp_is_err(QDict *rsp)
@@ -1403,6 +1400,7 @@ QTestState *qtest_inproc_init(QTestState **s, bool log, const char* arch,
{
QTestState *qts;
qts = g_new0(QTestState, 1);
+ qts->pending_events = NULL;
*s = qts; /* Expose qts early on, since the query endianness relies on it */
qts->wstatus = 0;
for (int i = 0; i < MAX_IRQ; i++) {