From patchwork Thu Jul 12 11:12:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 942943 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41RD8y2zMjz9rxs for ; Thu, 12 Jul 2018 21:24:02 +1000 (AEST) Received: from localhost ([::1]:58711 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fdZhX-0007HL-U3 for incoming@patchwork.ozlabs.org; Thu, 12 Jul 2018 07:23:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47968) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fdZWQ-0007Aa-TR for qemu-devel@nongnu.org; Thu, 12 Jul 2018 07:12:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fdZWM-0006rd-JO for qemu-devel@nongnu.org; Thu, 12 Jul 2018 07:12:30 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:55666 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fdZWM-0006qg-9j for qemu-devel@nongnu.org; Thu, 12 Jul 2018 07:12:26 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DE08FC12AF; Thu, 12 Jul 2018 11:12:25 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-125.ams2.redhat.com [10.36.116.125]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8F3A4111AF0E; Thu, 12 Jul 2018 11:12:25 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 00F2D1132D3F; Thu, 12 Jul 2018 13:12:21 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 12 Jul 2018 13:12:16 +0200 Message-Id: <20180712111221.20326-16-armbru@redhat.com> In-Reply-To: <20180712111221.20326-1-armbru@redhat.com> References: <20180712111221.20326-1-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Thu, 12 Jul 2018 11:12:25 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Thu, 12 Jul 2018 11:12:25 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'armbru@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH 15/20] tests: New helper qtest_qmp_receive_success() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Huth , Stefan Berger , "Dr . David Alan Gilbert" , Juan Quintela Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Commit b21373d0713 copied wait_command() from tests/migration-test.c to tests/tpm-util.c. Replace both copies by new libqtest helper qtest_qmp_receive_success(). Also use it to simplify qtest_qmp_device_del(). Bonus: gets rid of a non-literal format string. A step towards compile-time format string checking without triggering -Wformat-nonliteral. Cc: Thomas Huth Cc: Juan Quintela Cc: Dr. David Alan Gilbert Cc: Stefan Berger Signed-off-by: Markus Armbruster Reviewed-by: Juan Quintela Reviewed-by: Stefan Berger --- tests/libqtest.c | 69 ++++++++++++++++++++++++++++++------------ tests/libqtest.h | 17 +++++++++++ tests/migration-test.c | 29 ++++++------------ tests/tpm-util.c | 32 +++----------------- 4 files changed, 80 insertions(+), 67 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index dfca3af89d..ed832cd8e6 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -1029,6 +1029,35 @@ 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 command. */ @@ -1053,6 +1082,14 @@ void qtest_qmp_device_add(const char *driver, const char *id, qobject_unref(response); } +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. * Device deletion will get one response and one event. For example: @@ -1073,27 +1110,21 @@ void qtest_qmp_device_add(const char *driver, const char *id, */ void qtest_qmp_device_del(const char *id) { - QDict *response1, *response2, *event = NULL; + bool got_event = false; + QDict *rsp; - response1 = qmp("{'execute': 'device_del', 'arguments': {'id': %s}}", - id); - g_assert(response1); - g_assert(!qdict_haskey(response1, "error")); - - response2 = qmp_receive(); - g_assert(response2); - g_assert(!qdict_haskey(response2, "error")); - - if (qdict_haskey(response1, "event")) { - event = response1; - } else if (qdict_haskey(response2, "event")) { - event = response2; + qtest_qmp_send(global_qtest, + "{'execute': 'device_del', 'arguments': {'id': %s}}", + id); + rsp = qtest_qmp_receive_success(global_qtest, device_deleted_cb, + &got_event); + qobject_unref(rsp); + if (!got_event) { + rsp = qmp_receive(); + g_assert_cmpstr(qdict_get_try_str(rsp, "event"), + ==, "DEVICE_DELETED"); + qobject_unref(rsp); } - g_assert(event); - g_assert_cmpstr(qdict_get_str(event, "event"), ==, "DEVICE_DELETED"); - - qobject_unref(response1); - qobject_unref(response2); } bool qmp_rsp_is_err(QDict *rsp) diff --git a/tests/libqtest.h b/tests/libqtest.h index 53364849bf..68b767fc88 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -163,6 +163,23 @@ void qtest_qmp_eventwait(QTestState *s, const char *event); */ QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event); +/** + * qtest_qmp_receive_success: + * @s: #QTestState instance to operate on + * @event_cb: Event callback + * @opaque: Argument for @event_cb + * + * Poll QMP messages until a command success response is received. + * If @event_cb, call it for each event received, passing @opaque, + * the event's name and data. + * Return the success response's "return" member. + */ +QDict *qtest_qmp_receive_success(QTestState *s, + void (*event_cb)(void *opaque, + const char *name, + QDict *data), + void *opaque); + /** * qtest_hmp: * @s: #QTestState instance to operate on. diff --git a/tests/migration-test.c b/tests/migration-test.c index f9f2c0148a..267342fd3e 100644 --- a/tests/migration-test.c +++ b/tests/migration-test.c @@ -146,31 +146,20 @@ static void wait_for_serial(const char *side) } while (true); } +static void stop_cb(void *opaque, const char *name, QDict *data) +{ + if (!strcmp(name, "STOP")) { + got_stop = true; + } +} + /* * Events can get in the way of responses we are actually waiting for. */ static QDict *wait_command(QTestState *who, const char *command) { - const char *event_string; - QDict *response, *ret; - - response = qtest_qmp(who, command); - - while (qdict_haskey(response, "event")) { - /* OK, it was an event */ - event_string = qdict_get_str(response, "event"); - if (!strcmp(event_string, "STOP")) { - got_stop = true; - } - qobject_unref(response); - response = qtest_qmp_receive(who); - } - - ret = qdict_get_qdict(response, "return"); - g_assert(ret); - qobject_ref(ret); - qobject_unref(response); - return ret; + qtest_qmp_send(who, command); + return qtest_qmp_receive_success(who, stop_cb, NULL); } /* diff --git a/tests/tpm-util.c b/tests/tpm-util.c index 3bd2887f1e..9f3f156e42 100644 --- a/tests/tpm-util.c +++ b/tests/tpm-util.c @@ -22,8 +22,6 @@ #define TIS_REG(LOCTY, REG) \ (TPM_TIS_ADDR_BASE + ((LOCTY) << 12) + REG) -static bool got_stop; - void tpm_util_crb_transfer(QTestState *s, const unsigned char *req, size_t req_size, unsigned char *rsp, size_t rsp_size) @@ -247,41 +245,19 @@ void tpm_util_migrate(QTestState *who, const char *uri) qobject_unref(rsp); } -/* - * Events can get in the way of responses we are actually waiting for. - */ -static QDict *tpm_util_wait_command(QTestState *who, const char *command) -{ - const char *event_string; - QDict *response; - - response = qtest_qmp(who, command); - - while (qdict_haskey(response, "event")) { - /* OK, it was an event */ - event_string = qdict_get_str(response, "event"); - if (!strcmp(event_string, "STOP")) { - got_stop = true; - } - qobject_unref(response); - response = qtest_qmp_receive(who); - } - return response; -} - void tpm_util_wait_for_migration_complete(QTestState *who) { while (true) { - QDict *rsp, *rsp_return; + QDict *rsp_return; bool completed; const char *status; - rsp = tpm_util_wait_command(who, "{ 'execute': 'query-migrate' }"); - rsp_return = qdict_get_qdict(rsp, "return"); + qtest_qmp_send(who, "{ 'execute': 'query-migrate' }"); + rsp_return = qtest_qmp_receive_success(who, NULL, NULL); status = qdict_get_str(rsp_return, "status"); completed = strcmp(status, "completed") == 0; g_assert_cmpstr(status, !=, "failed"); - qobject_unref(rsp); + qobject_unref(rsp_return); if (completed) { return; }