From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810115079920.8575742808279; Thu, 3 Aug 2017 18:28:35 -0700 (PDT) Received: from localhost ([::1]:43431 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRPl-00016p-FG for importer@patchew.org; Thu, 03 Aug 2017 21:28:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59485) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNH-0008E9-KD for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNE-0003hk-ML for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:25:59 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51506) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNE-0003go-E1 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:25:56 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7B80937EE9 for ; Fri, 4 Aug 2017 01:25:55 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0078F627D7; Fri, 4 Aug 2017 01:25:54 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 7B80937EE9 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:30 -0500 Message-Id: <20170804012551.2714-2-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 04 Aug 2017 01:25:55 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 01/22] qobject: Accept "%"PRId64 in qobject_from_jsonf() 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Commit 1792d7d0 was written because PRId64 expands to non-portable crap for some libc, and we had testsuite failures on Mac OS as a result. This in turn makes it difficult to rely on the obvious conversions of 64-bit values into JSON, requiring things such as casting int64_t to long long so we can use a reliable %lld and still keep -Wformat happy. So now it's time to fix that. We are already lexing %I64d (hello mingw); now expand the lexer to parse %qd (hello Mac OS). In the process, we can drop one state: IN_ESCAPE_I64 is redundant with IN_ESCAPE_LL, and reused again by %qd, so rename it to IN_ESCAPE_64. And fix a comment that mistakenly omitted %u as a supported escape. Next, tweak the parser to accept the exact spelling of PRId64 regardless of what it expands to (note that there are are now dead branches in the 'if' chain for some platforms, like glibc; but there are other platforms where all branches are necessary). We are at least safe in that we are parsing the correct size 32-bit or a 64-bit quantity on whatever branch we end up in. This also means that we no longer parse everything that the lexer will consume (no more %I64d on glibc), but that is intentional. And of course, update the testsuite for coverage of the feature. Finally, update configure to barf on any libc that uses yet another form of PRId64 that we have not yet coded for, so that we can once again update json-lexer.c to cater to those quirks (my guess? we might see %jd next) (on the bright side, json-parser.c should no longer need updates). Yes, the only way I could find to quickly learn what spelling is preferred when cross-compiling is to grep a compiled binary; C does not make it easy to turn a string constant into an integer constant, let alone make preprocessor decisions; and even parsing '$CC -E' output is fragile, since 64-bit glibc pre-processes as "l" "d" rather than "ld", and newer gcc splits macro expansions across multiple lines. I'm assuming that 'strings' is portable enough during configure; if that assumption fails in some constrained docker environment, we can make a followup patch to configure along these lines: strings () { tr -d '\0' < "$1"; } Either way, it's better to avoid worrying about whether grep will portably handle a file still containing NUL bytes. Signed-off-by: Eric Blake Reviewed-by: Markus Armbruster --- v4: compile_object instead of compile_prog; another comment tweak v3: incorporate review comments from Markus --- configure | 24 ++++++++++++++++++++++++ qobject/json-lexer.c | 22 ++++++++++------------ qobject/json-parser.c | 10 ++++++---- tests/check-qjson.c | 7 +++++++ 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/configure b/configure index 987f59ba88..6e0e433cc4 100755 --- a/configure +++ b/configure @@ -3222,6 +3222,30 @@ for i in $glib_modules; do fi done +# Sanity check that we can parse PRId64 and friends in json-lexer.c +# (Sadly, the "easiest" way to do this is to grep the compiled binary, +# since we can't control whether the preprocessor would output "ld" vs. +# "l" "d", nor even portably ensure it fits output on the same line as +# a witness marker.) +cat > $TMPC < +int main(void) { + static const char findme[] =3D "\nUnLiKeLyToClAsH_" PRId64 "\n"; + return !findme[0]; +} +EOF +if ! compile_object "$CFLAGS" "$LIBS" ; then + error_exit "can't determine value of PRId64" +fi +nl=3D' +' +case $(strings $TMPO | grep ^UnLiKeLyToClAsH) in + '' | *"$nl"* ) error_exit "can't determine value of PRId64" ;; + *_ld | *_lld | *_I64d | *_qd) ;; + *) error_exit "unexepected value of PRId64, please add %$(strings $TMP= O | + sed -n s/^UnLiKeLyToClAsH_//p) support to json-lexer.c" ;; +esac + # Sanity check that the current size_t matches the # size that glib thinks it should be. This catches # problems on multi-arch where people try to build diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c index 980ba159d6..b846d2852d 100644 --- a/qobject/json-lexer.c +++ b/qobject/json-lexer.c @@ -29,9 +29,12 @@ * * '([^\\']|\\[\"'\\/bfnrt]|\\u[0-9a-fA-F]{4})*' * - * Extension for vararg handling in JSON construction: + * Extension for vararg handling in JSON construction, when using + * qobject_from_jsonf() instead of qobject_from_json() (this lexer + * actually accepts multiple forms of PRId64, but parse_escape() later + * filters to only parse the current platform's spelling): * - * %((l|ll|I64)?d|[ipsf]) + * %(PRI[du]64|(l|ll)?[ud]|[ipsf]) * */ @@ -60,10 +63,9 @@ enum json_lexer_state { IN_KEYWORD, IN_ESCAPE, IN_ESCAPE_L, - IN_ESCAPE_LL, + IN_ESCAPE_64, IN_ESCAPE_I, IN_ESCAPE_I6, - IN_ESCAPE_I64, IN_WHITESPACE, IN_START, }; @@ -225,24 +227,19 @@ static const uint8_t json_lexer[][256] =3D { }, /* escape */ - [IN_ESCAPE_LL] =3D { + [IN_ESCAPE_64] =3D { ['d'] =3D JSON_ESCAPE, ['u'] =3D JSON_ESCAPE, }, [IN_ESCAPE_L] =3D { ['d'] =3D JSON_ESCAPE, - ['l'] =3D IN_ESCAPE_LL, - ['u'] =3D JSON_ESCAPE, - }, - - [IN_ESCAPE_I64] =3D { - ['d'] =3D JSON_ESCAPE, + ['l'] =3D IN_ESCAPE_64, ['u'] =3D JSON_ESCAPE, }, [IN_ESCAPE_I6] =3D { - ['4'] =3D IN_ESCAPE_I64, + ['4'] =3D IN_ESCAPE_64, }, [IN_ESCAPE_I] =3D { @@ -257,6 +254,7 @@ static const uint8_t json_lexer[][256] =3D { ['u'] =3D JSON_ESCAPE, ['f'] =3D JSON_ESCAPE, ['l'] =3D IN_ESCAPE_L, + ['q'] =3D IN_ESCAPE_64, ['I'] =3D IN_ESCAPE_I, }, diff --git a/qobject/json-parser.c b/qobject/json-parser.c index 724ca240e4..388aa7a386 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -470,16 +470,18 @@ static QObject *parse_escape(JSONParserContext *ctxt,= va_list *ap) return QOBJECT(qnum_from_int(va_arg(*ap, int))); } else if (!strcmp(token->str, "%ld")) { return QOBJECT(qnum_from_int(va_arg(*ap, long))); - } else if (!strcmp(token->str, "%lld") || - !strcmp(token->str, "%I64d")) { + } else if (!strcmp(token->str, "%lld")) { return QOBJECT(qnum_from_int(va_arg(*ap, long long))); + } else if (!strcmp(token->str, "%" PRId64)) { + return QOBJECT(qnum_from_int(va_arg(*ap, int64_t))); } else if (!strcmp(token->str, "%u")) { return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned int))); } else if (!strcmp(token->str, "%lu")) { return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long))); - } else if (!strcmp(token->str, "%llu") || - !strcmp(token->str, "%I64u")) { + } else if (!strcmp(token->str, "%llu")) { return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long long))); + } else if (!strcmp(token->str, "%" PRIu64)) { + return QOBJECT(qnum_from_uint(va_arg(*ap, uint64_t))); } else if (!strcmp(token->str, "%s")) { return QOBJECT(qstring_from_str(va_arg(*ap, const char *))); } else if (!strcmp(token->str, "%f")) { diff --git a/tests/check-qjson.c b/tests/check-qjson.c index a3a97b0d99..1ad1f41a52 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -990,8 +990,10 @@ static void vararg_number(void) QNum *qnum; int value =3D 0x2342; long long value_ll =3D 0x2342342343LL; + uint64_t value_u64 =3D 0x2342342343ULL; double valuef =3D 2.323423423; int64_t val; + uint64_t uval; qnum =3D qobject_to_qnum(qobject_from_jsonf("%d", value)); g_assert(qnum_get_try_int(qnum, &val)); @@ -1003,6 +1005,11 @@ static void vararg_number(void) g_assert_cmpint(val, =3D=3D, value_ll); QDECREF(qnum); + qnum =3D qobject_to_qnum(qobject_from_jsonf("%" PRIu64, value_u64)); + g_assert(qnum_get_try_uint(qnum, &uval)); + g_assert_cmpint(uval, =3D=3D, value_u64); + QDECREF(qnum); + qnum =3D qobject_to_qnum(qobject_from_jsonf("%f", valuef)); g_assert(qnum_get_double(qnum) =3D=3D valuef); QDECREF(qnum); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810322608517.9734639380586; Thu, 3 Aug 2017 18:32:02 -0700 (PDT) Received: from localhost ([::1]:43455 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRT6-00041J-Kg for importer@patchew.org; Thu, 03 Aug 2017 21:32:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59617) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNL-0008FS-D9 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNK-0003mj-1K for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51458) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNJ-0003lT-Ol for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:01 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C57C27C82B for ; Fri, 4 Aug 2017 01:26:00 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id B8B93627D7; Fri, 4 Aug 2017 01:25:55 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C57C27C82B Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:31 -0500 Message-Id: <20170804012551.2714-3-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Fri, 04 Aug 2017 01:26:00 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 02/22] tests: Clean up wait for event 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: armbru@redhat.com, Gerd Hoffmann Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Markus Armbruster We still use hacks like qmp("") to wait for an event, even though we have qmp_eventwait() since commit 8fe941f, and qmp_eventwait_ref() since commit 7ffe312. Both commits neglected to convert all the existing hacks. Make up what they missed. Bonus: gets rid of empty format strings. A step towards compile-time format string checking without triggering -Wformat-zero-length. Signed-off-by: Markus Armbruster Message-Id: <1500645206-13559-8-git-send-email-armbru@redhat.com> Reviewed-by: Stefan Hajnoczi Signed-off-by: Eric Blake --- v4: hoist earlier in series --- tests/boot-order-test.c | 2 +- tests/libqos/pci-pc.c | 6 +----- tests/tco-test.c | 3 +-- tests/usb-hcd-uhci-test.c | 6 +----- tests/usb-hcd-xhci-test.c | 12 ++---------- tests/wdt_ib700-test.c | 35 ++++++++++------------------------- 6 files changed, 16 insertions(+), 48 deletions(-) diff --git a/tests/boot-order-test.c b/tests/boot-order-test.c index fc1e7941f7..9d516830dd 100644 --- a/tests/boot-order-test.c +++ b/tests/boot-order-test.c @@ -43,7 +43,7 @@ static void test_a_boot_order(const char *machine, * system_reset only requests reset. We get a RESET event after * the actual reset completes. Need to wait for that. */ - qmp_discard_response(""); /* HACK: wait for event */ + qmp_eventwait("RESET"); actual =3D read_boot_order(); g_assert_cmphex(actual, =3D=3D, expected_reboot); qtest_quit(global_qtest); diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c index ded1c54c06..02ce49927a 100644 --- a/tests/libqos/pci-pc.c +++ b/tests/libqos/pci-pc.c @@ -173,9 +173,5 @@ void qpci_unplug_acpi_device_test(const char *id, uint8= _t slot) outb(ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot); - response =3D qmp(""); - g_assert(response); - g_assert(qdict_haskey(response, "event")); - g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); - QDECREF(response); + qmp_eventwait("DEVICE_DELETED"); } diff --git a/tests/tco-test.c b/tests/tco-test.c index c4c264eb3d..f2ed6ed91c 100644 --- a/tests/tco-test.c +++ b/tests/tco-test.c @@ -237,9 +237,8 @@ static void test_tco_max_timeout(void) static QDict *get_watchdog_action(void) { - QDict *ev =3D qmp(""); + QDict *ev =3D qmp_eventwait_ref("WATCHDOG"); QDict *data; - g_assert(!strcmp(qdict_get_str(ev, "event"), "WATCHDOG")); data =3D qdict_get_qdict(ev, "data"); QINCREF(data); diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c index 5b500fedb0..0fb7f8d223 100644 --- a/tests/usb-hcd-uhci-test.c +++ b/tests/usb-hcd-uhci-test.c @@ -68,11 +68,7 @@ static void test_usb_storage_hotplug(void) g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp(""); - g_assert(response); - g_assert(qdict_haskey(response, "event")); - g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); - QDECREF(response); + qmp_eventwait("DEVICE_DELETED"); } int main(int argc, char **argv) diff --git a/tests/usb-hcd-xhci-test.c b/tests/usb-hcd-xhci-test.c index 031764da6d..c05a339894 100644 --- a/tests/usb-hcd-xhci-test.c +++ b/tests/usb-hcd-xhci-test.c @@ -57,11 +57,7 @@ static void test_usb_uas_hotplug(void) g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp(""); - g_assert(qdict_haskey(response, "event")); - g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); - QDECREF(response); - + qmp_eventwait("DEVICE_DELETED"); response =3D qmp("{'execute': 'device_del'," " 'arguments': {" @@ -71,11 +67,7 @@ static void test_usb_uas_hotplug(void) g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp(""); - g_assert(response); - g_assert(qdict_haskey(response, "event")); - g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); - QDECREF(response); + qmp_eventwait("DEVICE_DELETED"); } int main(int argc, char **argv) diff --git a/tests/wdt_ib700-test.c b/tests/wdt_ib700-test.c index 49f4f0c221..4fc8eeae86 100644 --- a/tests/wdt_ib700-test.c +++ b/tests/wdt_ib700-test.c @@ -18,26 +18,10 @@ static void qmp_check_no_event(void) QDECREF(resp); } -static QDict *qmp_get_event(const char *name) -{ - QDict *event =3D qmp(""); - QDict *data; - g_assert(qdict_haskey(event, "event")); - g_assert(!strcmp(qdict_get_str(event, "event"), name)); - - if (qdict_haskey(event, "data")) { - data =3D qdict_get_qdict(event, "data"); - QINCREF(data); - } else { - data =3D NULL; - } - - QDECREF(event); - return data; -} - static QDict *ib700_program_and_wait(QTestState *s) { + QDict *event, *data; + clock_step(NANOSECONDS_PER_SECOND * 40); qmp_check_no_event(); @@ -61,7 +45,11 @@ static QDict *ib700_program_and_wait(QTestState *s) clock_step(3 * NANOSECONDS_PER_SECOND); qmp_check_no_event(); clock_step(2 * NANOSECONDS_PER_SECOND); - return qmp_get_event("WATCHDOG"); + event =3D qmp_eventwait_ref("WATCHDOG"); + data =3D qdict_get_qdict(event, "data"); + QINCREF(data); + QDECREF(event); + return data; } @@ -73,8 +61,7 @@ static void ib700_pause(void) d =3D ib700_program_and_wait(s); g_assert(!strcmp(qdict_get_str(d, "action"), "pause")); QDECREF(d); - d =3D qmp_get_event("STOP"); - QDECREF(d); + qmp_eventwait("STOP"); qtest_end(); } @@ -86,8 +73,7 @@ static void ib700_reset(void) d =3D ib700_program_and_wait(s); g_assert(!strcmp(qdict_get_str(d, "action"), "reset")); QDECREF(d); - d =3D qmp_get_event("RESET"); - QDECREF(d); + qmp_eventwait("RESET"); qtest_end(); } @@ -99,8 +85,7 @@ static void ib700_shutdown(void) d =3D ib700_program_and_wait(s); g_assert(!strcmp(qdict_get_str(d, "action"), "reset")); QDECREF(d); - d =3D qmp_get_event("SHUTDOWN"); - QDECREF(d); + qmp_eventwait("SHUTDOWN"); qtest_end(); } --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810120439548.100802634571; Thu, 3 Aug 2017 18:28:40 -0700 (PDT) Received: from localhost ([::1]:43432 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRPq-0001Bm-CO for importer@patchew.org; Thu, 03 Aug 2017 21:28:38 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59650) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNM-0008GR-Mr for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNL-0003p2-U6 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:04 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45584) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNL-0003o3-OM for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:03 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A46CA85550 for ; Fri, 4 Aug 2017 01:26:02 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0418B627D7; Fri, 4 Aug 2017 01:26:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com A46CA85550 Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:32 -0500 Message-Id: <20170804012551.2714-4-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 04 Aug 2017 01:26:02 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 03/22] tests/libqtest: Clean up how we read the QMP greeting 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Markus Armbruster qtest_init() still uses the qtest_qmp_discard_response(s, "") hack to receive the greeting, even though we have qtest_qmp_receive() since commit 66e0c7b. Put it to use. Bonus: gets rid of an empty format string. A step towards compile-time format string checking without triggering -Wformat-zero-length. Signed-off-by: Markus Armbruster Message-Id: <1500645206-13559-9-git-send-email-armbru@redhat.com> Reviewed-by: Stefan Hajnoczi Signed-off-by: Eric Blake --- v4: hoist earlier in series --- tests/libqtest.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index 4a5492a603..7e5425d704 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -230,9 +230,11 @@ QTestState *qtest_init_without_qmp_handshake(const cha= r *extra_args) QTestState *qtest_init(const char *extra_args) { QTestState *s =3D qtest_init_without_qmp_handshake(extra_args); + QDict *greeting; /* Read the QMP greeting and then do the handshake */ - qtest_qmp_discard_response(s, ""); + greeting =3D qtest_qmp_receive(s); + QDECREF(greeting); qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }"); return s; --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810327885760.6446872932725; Thu, 3 Aug 2017 18:32:07 -0700 (PDT) Received: from localhost ([::1]:43456 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRTC-00043o-Eh for importer@patchew.org; Thu, 03 Aug 2017 21:32:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59678) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNN-0008H2-DK for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNM-0003pV-Gz for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46410) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNM-0003on-Bf for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:04 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5F1D8C047B6E for ; Fri, 4 Aug 2017 01:26:03 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id DA2E361F36; Fri, 4 Aug 2017 01:26:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 5F1D8C047B6E Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:33 -0500 Message-Id: <20170804012551.2714-5-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 04 Aug 2017 01:26:03 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 04/22] tests: Add assertion for no qmp("") 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Now that the previous patches have fixed all callers to avoid an empty message, we can tweak qmp_fd_sendv() to assert that we don't introduce new callers, and reindent accordingly. The additional assertions will also help verify that later refactoring is not breaking anything. Signed-off-by: Eric Blake Reviewed-by: Markus Armbruster --- tests/libqtest.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index 7e5425d704..99a07c246f 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -450,6 +450,9 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) { va_list ap_copy; QObject *qobj; + int log =3D getenv("QTEST_LOG") !=3D NULL; + QString *qstr; + const char *str; /* qobject_from_jsonv() silently eats leading 0xff as invalid * JSON, but we want to test sending them over the wire to force @@ -458,6 +461,7 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) socket_send(fd, fmt, 1); fmt++; } + assert(*fmt); /* Going through qobject ensures we escape strings properly. * This seemingly unnecessary copy is required in case va_list @@ -466,29 +470,23 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) va_copy(ap_copy, ap); qobj =3D qobject_from_jsonv(fmt, &ap_copy, &error_abort); va_end(ap_copy); + qstr =3D qobject_to_json(qobj); - /* No need to send anything for an empty QObject. */ - if (qobj) { - int log =3D getenv("QTEST_LOG") !=3D NULL; - QString *qstr =3D qobject_to_json(qobj); - const char *str; + /* + * BUG: QMP doesn't react to input until it sees a newline, an + * object, or an array. Work-around: give it a newline. + */ + qstring_append_chr(qstr, '\n'); + str =3D qstring_get_str(qstr); - /* - * BUG: QMP doesn't react to input until it sees a newline, an - * object, or an array. Work-around: give it a newline. - */ - qstring_append_chr(qstr, '\n'); - str =3D qstring_get_str(qstr); - - if (log) { - fprintf(stderr, "%s", str); - } - /* Send QMP request */ - socket_send(fd, str, qstring_get_length(qstr)); - - QDECREF(qstr); - qobject_decref(qobj); + if (log) { + fprintf(stderr, "%s", str); } + /* Send QMP request */ + socket_send(fd, str, qstring_get_length(qstr)); + + QDECREF(qstr); + qobject_decref(qobj); } void qtest_async_qmpv(QTestState *s, const char *fmt, va_list ap) --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 150181054902659.87374310336418; Thu, 3 Aug 2017 18:35:49 -0700 (PDT) Received: from localhost ([::1]:43481 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRWi-0006um-2Y for importer@patchew.org; Thu, 03 Aug 2017 21:35:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59790) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNQ-0008IO-Tx for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNN-0003qs-Fn for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51566) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNN-0003pf-64 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:05 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3D8D683F42; Fri, 4 Aug 2017 01:26:04 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 980D161F36; Fri, 4 Aug 2017 01:26:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 3D8D683F42 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:34 -0500 Message-Id: <20170804012551.2714-6-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Fri, 04 Aug 2017 01:26:04 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 05/22] qobject: Simplify qobject_from_jsonv() 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: armbru@redhat.com, Michael Roth Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" qobject_from_jsonv() was unusual in that it took a va_list*, instead of the more typical va_list; this was so that callers could pass NULL to avoid % interpolation. While this works under the hood, it is awkward for callers, so move the magic into qjson.c rather than in the public interface, and finally improve the documentation of qobject_from_jsonf(). test-qobject-input-visitor.c's visitor_input_test_init_internal() was the only caller passing NULL, fix it to instead use a QObject created by the various callers, who now use the appropriate form of qobject_from_json*() according to whether % interpolation is desired. Once that is done, all remaining callers to qobject_from_jsonv() are passing &error_abort; drop this parameter to match the counterpart qobject_from_jsonf() which assert()s success instead. Besides, all current callers that need interpolation live in the testsuite, where enforcing well-defined input by asserts can help catch typos, and where we should not be operating on dynamic untrusted arbitrary input in the first place. Asserting success has another nice benefit: if we pass more than one %p, but could return failure, we would have to worry about whether all arguments in the va_list had consistent refcount treatment (it should be an all-or-none decision on whether each QObject in the va_list had its reference count altered - but whichever way we prefer, it's a lot of overhead to ensure we do it for everything in the va_list even if we failed halfway through). But now that we promise success, we can now easily promise that all %p arguments will now be cleaned up when freeing the returned object. Signed-off-by: Eric Blake --- include/qapi/qmp/qjson.h | 2 +- tests/libqtest.c | 10 ++------ qobject/qjson.c | 49 ++++++++++++++++++++++++++++++++++= +--- tests/test-qobject-input-visitor.c | 18 ++++++++------ 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/include/qapi/qmp/qjson.h b/include/qapi/qmp/qjson.h index 6e84082d5f..9aacb1ccf6 100644 --- a/include/qapi/qmp/qjson.h +++ b/include/qapi/qmp/qjson.h @@ -19,7 +19,7 @@ QObject *qobject_from_json(const char *string, Error **errp); QObject *qobject_from_jsonf(const char *string, ...) GCC_FMT_ATTR(1, 2); -QObject *qobject_from_jsonv(const char *string, va_list *ap, Error **errp) +QObject *qobject_from_jsonv(const char *string, va_list ap) GCC_FMT_ATTR(1, 0); QString *qobject_to_json(const QObject *obj); diff --git a/tests/libqtest.c b/tests/libqtest.c index 99a07c246f..cde737ec5a 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -448,7 +448,6 @@ QDict *qtest_qmp_receive(QTestState *s) */ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) { - va_list ap_copy; QObject *qobj; int log =3D getenv("QTEST_LOG") !=3D NULL; QString *qstr; @@ -463,13 +462,8 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) } assert(*fmt); - /* Going through qobject ensures we escape strings properly. - * This seemingly unnecessary copy is required in case va_list - * is an array type. - */ - va_copy(ap_copy, ap); - qobj =3D qobject_from_jsonv(fmt, &ap_copy, &error_abort); - va_end(ap_copy); + /* Going through qobject ensures we escape strings properly. */ + qobj =3D qobject_from_jsonv(fmt, ap); qstr =3D qobject_to_json(qobj); /* diff --git a/qobject/qjson.c b/qobject/qjson.c index 2e0930884e..210c290aa9 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -35,7 +35,8 @@ static void parse_json(JSONMessageParser *parser, GQueue = *tokens) s->result =3D json_parser_parse_err(tokens, s->ap, &s->err); } -QObject *qobject_from_jsonv(const char *string, va_list *ap, Error **errp) +static QObject *qobject_from_json_internal(const char *string, va_list *ap, + Error **errp) { JSONParsingState state =3D {}; @@ -50,12 +51,31 @@ QObject *qobject_from_jsonv(const char *string, va_list= *ap, Error **errp) return state.result; } +/* + * Parses JSON input without interpolation. + * + * Returns a QObject matching the input on success, or NULL with + * an error set if the input is not valid JSON. + */ QObject *qobject_from_json(const char *string, Error **errp) { - return qobject_from_jsonv(string, NULL, errp); + return qobject_from_json_internal(string, NULL, errp); } /* + * Parses JSON input with interpolation of % sequences. + * + * The set of sequences recognized is compatible with gcc's -Wformat + * warnings, although not all printf sequences are valid. All use of + * % must occur outside JSON strings. + * + * %i - treat corresponding integer value as JSON bool + * %[l[l]]d, %PRId64 - treat sized integer value as signed JSON number + * %[l[l]]u, %PRIu64 - treat sized integer value as unsigned JSON number + * %f - treat double as JSON number (undefined for inf, NaN) + * %s - convert char * into JSON string (adds escapes, outer quotes) + * %p - embed QObject, transferring the reference to the returned object + * * IMPORTANT: This function aborts on error, thus it must not * be used with untrusted arguments. */ @@ -65,13 +85,36 @@ QObject *qobject_from_jsonf(const char *string, ...) va_list ap; va_start(ap, string); - obj =3D qobject_from_jsonv(string, &ap, &error_abort); + obj =3D qobject_from_json_internal(string, &ap, &error_abort); va_end(ap); assert(obj !=3D NULL); return obj; } +/* + * va_list form of qobject_from_jsonf(). + * + * IMPORTANT: This function aborts on error, thus it must not + * be used with untrusted arguments. + */ +QObject *qobject_from_jsonv(const char *string, va_list ap) +{ + QObject *obj; + va_list ap_copy; + + /* + * This seemingly unnecessary copy is required in case va_list + * is an array type. + */ + va_copy(ap_copy, ap); + obj =3D qobject_from_json_internal(string, &ap_copy, &error_abort); + va_end(ap_copy); + + assert(obj !=3D NULL); + return obj; +} + typedef struct ToJsonIterState { int indent; diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index bcf02617dc..a9addd9f98 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -45,13 +45,11 @@ static void visitor_input_teardown(TestInputVisitorData= *data, function so that the JSON string used by the tests are kept in the test functions (and not in main()). */ static Visitor *visitor_input_test_init_internal(TestInputVisitorData *dat= a, - bool keyval, - const char *json_string, - va_list *ap) + bool keyval, QObject *obj) { visitor_input_teardown(data, NULL); - data->obj =3D qobject_from_jsonv(json_string, ap, &error_abort); + data->obj =3D obj; g_assert(data->obj); if (keyval) { @@ -69,10 +67,12 @@ Visitor *visitor_input_test_init_full(TestInputVisitorD= ata *data, const char *json_string, ...) { Visitor *v; + QObject *obj; va_list ap; va_start(ap, json_string); - v =3D visitor_input_test_init_internal(data, keyval, json_string, &ap); + obj =3D qobject_from_jsonv(json_string, ap); + v =3D visitor_input_test_init_internal(data, keyval, obj); va_end(ap); return v; } @@ -82,10 +82,12 @@ Visitor *visitor_input_test_init(TestInputVisitorData *= data, const char *json_string, ...) { Visitor *v; + QObject *obj; va_list ap; va_start(ap, json_string); - v =3D visitor_input_test_init_internal(data, false, json_string, &ap); + obj =3D qobject_from_jsonv(json_string, ap); + v =3D visitor_input_test_init_internal(data, false, obj); va_end(ap); return v; } @@ -100,7 +102,9 @@ Visitor *visitor_input_test_init(TestInputVisitorData *= data, static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data, const char *json_string) { - return visitor_input_test_init_internal(data, false, json_string, NULL= ); + QObject *obj =3D qobject_from_json(json_string, &error_abort); + + return visitor_input_test_init_internal(data, false, obj); } static void test_visitor_in_int(TestInputVisitorData *data, --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810781569926.8541361779905; Thu, 3 Aug 2017 18:39:41 -0700 (PDT) Received: from localhost ([::1]:43505 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRaW-0001GH-11 for importer@patchew.org; Thu, 03 Aug 2017 21:39:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59793) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNQ-0008IP-VM for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNO-0003rp-Bb for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51854) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNO-0003qk-2K for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:06 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 004F713A60 for ; Fri, 4 Aug 2017 01:26:05 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7321461F57; Fri, 4 Aug 2017 01:26:04 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 004F713A60 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:35 -0500 Message-Id: <20170804012551.2714-7-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 04 Aug 2017 01:26:05 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 06/22] qobject: Perform %% interpolation in qobject_from_jsonf() 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" We want -Wformat to catch blatant programming errors in format strings that we pass to qobject_from_jsonf(). But if someone were to pass a JSON string "'%s'" as the format string, gcc would insist that it be paired with a char* argument, even though our lexer does not recognize % sequences inside a JSON string. You can bypass -Wformat checking by passing the Unicode escape \u0025 for %, but who wants to remember to type that? So the solution is that anywhere we are relying on -Wformat checking, the caller should pass the usual printf %% escape sequence where a literal % is wanted on output. Note that since % can only appear in JSON inside a string, we don't have to teach the lexer how to parse any new % sequences, but instead only have to add code to the parser. Likewise, the parser is still where we reject any attempt at mid-string % interpolation other than %% (this is only a runtime failure, rather than compile-time), but since we already document that qobject_from_jsonf() asserts on invalid usage, presumably anyone that is adding a new usage will have tested that their usage doesn't always fail. Simplify qstring_from_escaped_str() while touching it, by using bool, a more compact conditional, and qstring_append_chr(). Likewise, improve the error message when parse_escape() is reached without interpolation (for example, if a client sends garbage rather than JSON over a QMP connection). The testsuite additions pass under valgrind, proving that we are indeed passing the reference of anything given through %p to the returned containing object, even when more than one object is interpolated. Signed-off-by: Eric Blake --- qobject/json-lexer.c | 6 ++++-- qobject/json-parser.c | 49 ++++++++++++++++++++++++-----------------------= -- qobject/qjson.c | 4 ++-- tests/check-qjson.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++= +++ 4 files changed, 80 insertions(+), 29 deletions(-) diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c index b846d2852d..599b7446b7 100644 --- a/qobject/json-lexer.c +++ b/qobject/json-lexer.c @@ -32,9 +32,11 @@ * Extension for vararg handling in JSON construction, when using * qobject_from_jsonf() instead of qobject_from_json() (this lexer * actually accepts multiple forms of PRId64, but parse_escape() later - * filters to only parse the current platform's spelling): + * filters to only parse the current platform's spelling; meanwhile, + * JSON only allows % inside strings, where the parser handles %%, so + * we do not need to lex it here): * - * %(PRI[du]64|(l|ll)?[ud]|[ipsf]) + * %(PRI[du]64|(l|ll)?[ud]|[ipsf%]) * */ diff --git a/qobject/json-parser.c b/qobject/json-parser.c index 388aa7a386..daafe77a0c 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -120,25 +120,21 @@ static int hex2decimal(char ch) * \n * \r * \t - * \u four-hex-digits=20 + * \u four-hex-digits + * + * Additionally, if @percent is true, all % in @token must be doubled, + * replaced by a single % will be in the result; this allows -Wformat + * processing of qobject_from_jsonf(). */ static QString *qstring_from_escaped_str(JSONParserContext *ctxt, - JSONToken *token) + JSONToken *token, bool percent) { const char *ptr =3D token->str; QString *str; - int double_quote =3D 1; - - if (*ptr =3D=3D '"') { - double_quote =3D 1; - } else { - double_quote =3D 0; - } - ptr++; + bool double_quote =3D *ptr++ =3D=3D '"'; str =3D qstring_new(); - while (*ptr &&=20 - ((double_quote && *ptr !=3D '"') || (!double_quote && *ptr !=3D= '\''))) { + while (*ptr && *ptr !=3D "'\""[double_quote]) { if (*ptr =3D=3D '\\') { ptr++; @@ -205,12 +201,13 @@ static QString *qstring_from_escaped_str(JSONParserCo= ntext *ctxt, goto out; } } else { - char dummy[2]; - - dummy[0] =3D *ptr++; - dummy[1] =3D 0; - - qstring_append(str, dummy); + if (*ptr =3D=3D '%' && percent) { + if (*++ptr !=3D '%') { + parse_error(ctxt, token, "invalid %% sequence in strin= g"); + goto out; + } + } + qstring_append_chr(str, *ptr++); } } @@ -455,13 +452,15 @@ static QObject *parse_escape(JSONParserContext *ctxt,= va_list *ap) { JSONToken *token; - if (ap =3D=3D NULL) { - return NULL; - } - token =3D parser_context_pop_token(ctxt); assert(token && token->type =3D=3D JSON_ESCAPE); + if (ap =3D=3D NULL) { + parse_error(ctxt, token, "escape parsing for '%s' not requested", + token->str); + return NULL; + } + if (!strcmp(token->str, "%p")) { return va_arg(*ap, QObject *); } else if (!strcmp(token->str, "%i")) { @@ -490,7 +489,7 @@ static QObject *parse_escape(JSONParserContext *ctxt, v= a_list *ap) return NULL; } -static QObject *parse_literal(JSONParserContext *ctxt) +static QObject *parse_literal(JSONParserContext *ctxt, bool percent) { JSONToken *token; @@ -499,7 +498,7 @@ static QObject *parse_literal(JSONParserContext *ctxt) switch (token->type) { case JSON_STRING: - return QOBJECT(qstring_from_escaped_str(ctxt, token)); + return QOBJECT(qstring_from_escaped_str(ctxt, token, percent)); case JSON_INTEGER: { /* * Represent JSON_INTEGER as QNUM_I64 if possible, else as @@ -562,7 +561,7 @@ static QObject *parse_value(JSONParserContext *ctxt, va= _list *ap) case JSON_INTEGER: case JSON_FLOAT: case JSON_STRING: - return parse_literal(ctxt); + return parse_literal(ctxt, ap); case JSON_KEYWORD: return parse_keyword(ctxt); default: diff --git a/qobject/qjson.c b/qobject/qjson.c index 210c290aa9..2244292d1a 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -66,8 +66,7 @@ QObject *qobject_from_json(const char *string, Error **er= rp) * Parses JSON input with interpolation of % sequences. * * The set of sequences recognized is compatible with gcc's -Wformat - * warnings, although not all printf sequences are valid. All use of - * % must occur outside JSON strings. + * warnings, although not all printf sequences are valid. * * %i - treat corresponding integer value as JSON bool * %[l[l]]d, %PRId64 - treat sized integer value as signed JSON number @@ -75,6 +74,7 @@ QObject *qobject_from_json(const char *string, Error **er= rp) * %f - treat double as JSON number (undefined for inf, NaN) * %s - convert char * into JSON string (adds escapes, outer quotes) * %p - embed QObject, transferring the reference to the returned object + * %% - literal %, usable only within JSON string * * IMPORTANT: This function aborts on error, thus it must not * be used with untrusted arguments. diff --git a/tests/check-qjson.c b/tests/check-qjson.c index 1ad1f41a52..31815b2d04 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -1408,6 +1408,55 @@ static void empty_input(void) g_assert(obj =3D=3D NULL); } +static void percent_and_vararg(void) +{ + QObject *obj; + QString *str; + QList *list; + Error *err =3D NULL; + + /* Use of % escapes requires vararg form */ + obj =3D qobject_from_json("%d", &err); + error_free_or_abort(&err); + g_assert(!obj); + + /* In normal form, % in strings is literal */ + obj =3D qobject_from_json("'%% %s \\u0025d'", &error_abort); + str =3D qobject_to_qstring(obj); + g_assert_cmpstr(qstring_get_str(str), =3D=3D, "%% %s %d"); + qobject_decref(obj); + + /* + * In vararg form, % in strings must be escaped (via the normal + * printf-escaping, or via a \u escape). The returned value now + * owns references to any %p counterpart. + */ + obj =3D qobject_from_jsonf("[ %p, '%% \\u0025s', %p ]", + qstring_from_str("one"), + qstring_from_str("three")); + list =3D qobject_to_qlist(obj); + str =3D qobject_to_qstring(qlist_pop(list)); + g_assert_cmpstr(qstring_get_str(str), =3D=3D, "one"); + QDECREF(str); + str =3D qobject_to_qstring(qlist_pop(list)); + g_assert_cmpstr(qstring_get_str(str), =3D=3D, "% %s"); + QDECREF(str); + str =3D qobject_to_qstring(qlist_pop(list)); + g_assert_cmpstr(qstring_get_str(str), =3D=3D, "three"); + QDECREF(str); + g_assert(qlist_empty(list)); + qobject_decref(obj); + + /* The following intentionally cause assertion failures */ + + /* In vararg form, %% must occur in strings */ + /* qobject_from_jsonf("%%"); */ + /* qobject_from_jsonf("{%%}"); */ + + /* In vararg form, strings must not use % except for %% */ + /* qobject_from_jsonf("'%s'", "unpaired"); */ +} + static void unterminated_string(void) { Error *err =3D NULL; @@ -1540,6 +1589,7 @@ int main(int argc, char **argv) g_test_add_func("/varargs/simple_varargs", simple_varargs); g_test_add_func("/errors/empty_input", empty_input); + g_test_add_func("/errors/percent_and_vararg", percent_and_vararg); g_test_add_func("/errors/unterminated/string", unterminated_string); g_test_add_func("/errors/unterminated/escape", unterminated_escape); g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_stri= ng); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810120452895.6165631117622; Thu, 3 Aug 2017 18:28:40 -0700 (PDT) Received: from localhost ([::1]:43433 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRPq-0001CG-Tc for importer@patchew.org; Thu, 03 Aug 2017 21:28:38 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59794) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNQ-0008IQ-Vn for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNP-0003sc-0e for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51110) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNO-0003ri-RC for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:06 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D45E48125F for ; Fri, 4 Aug 2017 01:26:05 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2E79A61F36; Fri, 4 Aug 2017 01:26:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D45E48125F Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:36 -0500 Message-Id: <20170804012551.2714-8-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Fri, 04 Aug 2017 01:26:06 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 07/22] numa-test: Use hmp() 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Don't open-code something that has a convenient helper available. Signed-off-by: Eric Blake Reviewed-by: Markus Armbruster --- tests/numa-test.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/tests/numa-test.c b/tests/numa-test.c index 3f636840b1..e1b6152244 100644 --- a/tests/numa-test.c +++ b/tests/numa-test.c @@ -17,21 +17,6 @@ static char *make_cli(const char *generic_cli, const cha= r *test_cli) return g_strdup_printf("%s %s", generic_cli ? generic_cli : "", test_c= li); } -static char *hmp_info_numa(void) -{ - QDict *resp; - char *s; - - resp =3D qmp("{ 'execute': 'human-monitor-command', 'arguments': " - "{ 'command-line': 'info numa '} }"); - g_assert(resp); - g_assert(qdict_haskey(resp, "return")); - s =3D 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=3D1,cpus=3D4-7 "); qtest_start(cli); - s =3D hmp_info_numa(); + s =3D 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 =3D make_cli(data, "-smp 8 -numa node -numa node"); qtest_start(cli); - s =3D hmp_info_numa(); + s =3D 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=3D1,cpus=3D4-5 "); qtest_start(cli); - s =3D hmp_info_numa(); + s =3D 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); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 15018105493271002.5675423317072; Thu, 3 Aug 2017 18:35:49 -0700 (PDT) Received: from localhost ([::1]:43482 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRWl-0006v4-Sd for importer@patchew.org; Thu, 03 Aug 2017 21:35:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59797) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNR-0008IR-0s for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNQ-0003tf-7Y for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59236) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNP-0003sj-M3 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:08 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AF828883AB for ; Fri, 4 Aug 2017 01:26:06 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 15807627D7; Fri, 4 Aug 2017 01:26:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com AF828883AB Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:37 -0500 Message-Id: <20170804012551.2714-9-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 04 Aug 2017 01:26:06 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 08/22] qtest: Avoid passing raw strings through hmp() 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: armbru@redhat.com, "Dr. David Alan Gilbert" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The next patch will add __attribute__((__format__)) to hmp(), which in turn causes gcc to warn about non-literal format strings. Rather than risk an arbitrary string containing % being mis-handled, always pass variable strings along with a %s format. It also makes it easier to prove correctness locally, rather than auditing all the source strings. Signed-off-by: Eric Blake Reviewed-by: Markus Armbruster Message-Id: <20170720214008.28494-4-eblake@redhat.com> Signed-off-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi --- tests/test-hmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-hmp.c b/tests/test-hmp.c index 729c0339f7..4aadd6a432 100644 --- a/tests/test-hmp.c +++ b/tests/test-hmp.c @@ -80,7 +80,7 @@ static void test_commands(void) if (verbose) { fprintf(stderr, "\t%s\n", hmp_cmds[i]); } - response =3D hmp(hmp_cmds[i]); + response =3D hmp("%s", hmp_cmds[i]); g_free(response); } @@ -103,7 +103,7 @@ static void test_info_commands(void) if (verbose) { fprintf(stderr, "\t%s\n", info); } - resp =3D hmp(info); + resp =3D hmp("%s", info); g_free(resp); /* And move forward to the next line */ info =3D strchr(endp + 1, '\n'); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810336928587.1575829255623; Thu, 3 Aug 2017 18:32:16 -0700 (PDT) Received: from localhost ([::1]:43457 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRTL-0004AB-EI for importer@patchew.org; Thu, 03 Aug 2017 21:32:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59841) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNS-0008Ks-Ar for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNQ-0003uT-QH for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:44952) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNQ-0003tN-Gy for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:08 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 84ADBDB935 for ; Fri, 4 Aug 2017 01:26:07 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id E474A61F36; Fri, 4 Aug 2017 01:26:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 84ADBDB935 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:38 -0500 Message-Id: <20170804012551.2714-10-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 04 Aug 2017 01:26:07 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 09/22] qtest: Document calling conventions 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" We have two flavors of vararg usage in qtest: hmp() etc. work like sprintf(), and qmp() etc. work like qobject_from_jsonf(). Spell that out in the comments. Also add GCC_FMT_ATTR() to qtest_hmp() etc. so that the compiler can flag incorrect use. We have some cleanup work to do before we can do the same for qtest_qmp() etc. This will get us the same better-than-nothing checking we already have for qobject_from_jsonf(): common incorrect uses of supported conversion specifications will be flagged (e.g. passing a double for %d), but use of unsupported ones won't. Signed-off-by: Eric Blake --- v4: rebase to %% handling, update commit message v3: restore lost attributes, add comments on va_list forms, tweak commit message to mention upcoming qmp cleanups v2: several comment tweaks, explain why qmp() can't be marked --- tests/libqtest.h | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index 3ae570927a..38148af66b 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -50,7 +50,8 @@ void qtest_quit(QTestState *s); /** * qtest_qmp_discard_response: * @s: #QTestState instance to operate on. - * @fmt...: QMP message to send to qemu + * @fmt...: QMP message to send to qemu; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * * Sends a QMP message to QEMU and consumes the response. */ @@ -59,7 +60,8 @@ void qtest_qmp_discard_response(QTestState *s, const char= *fmt, ...); /** * qtest_qmp: * @s: #QTestState instance to operate on. - * @fmt...: QMP message to send to qemu + * @fmt...: QMP message to send to qemu; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * * Sends a QMP message to QEMU and returns the response. */ @@ -68,7 +70,8 @@ QDict *qtest_qmp(QTestState *s, const char *fmt, ...); /** * qtest_async_qmp: * @s: #QTestState instance to operate on. - * @fmt...: QMP message to send to qemu + * @fmt...: QMP message to send to qemu; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * * Sends a QMP message to QEMU and leaves the response in the stream. */ @@ -77,7 +80,8 @@ void qtest_async_qmp(QTestState *s, const char *fmt, ...); /** * qtest_qmpv_discard_response: * @s: #QTestState instance to operate on. - * @fmt: QMP message to send to QEMU + * @fmt: QMP message to send to QEMU; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * @ap: QMP message arguments * * Sends a QMP message to QEMU and consumes the response. @@ -87,7 +91,8 @@ void qtest_qmpv_discard_response(QTestState *s, const cha= r *fmt, va_list ap); /** * qtest_qmpv: * @s: #QTestState instance to operate on. - * @fmt: QMP message to send to QEMU + * @fmt: QMP message to send to QEMU; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * @ap: QMP message arguments * * Sends a QMP message to QEMU and returns the response. @@ -97,7 +102,8 @@ QDict *qtest_qmpv(QTestState *s, const char *fmt, va_lis= t ap); /** * qtest_async_qmpv: * @s: #QTestState instance to operate on. - * @fmt: QMP message to send to QEMU + * @fmt: QMP message to send to QEMU; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * @ap: QMP message arguments * * Sends a QMP message to QEMU and leaves the response in the stream. @@ -134,19 +140,19 @@ QDict *qtest_qmp_eventwait_ref(QTestState *s, const c= har *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: * @s: #QTestState instance to operate on. - * @fmt: HMP command to send to QEMU + * @fmt: HMP command to send to QEMU, formats arguments like vsprintf(). * @ap: HMP command arguments * * Send HMP command to QEMU via QMP's human-monitor-command. @@ -154,7 +160,8 @@ char *qtest_hmp(QTestState *s, const char *fmt, ...); * * Returns: the command's output. The caller should g_free() it. */ -char *qtest_hmpv(QTestState *s, const char *fmt, va_list ap); +char *qtest_hmpv(QTestState *s, const char *fmt, va_list ap) + GCC_FMT_ATTR(2, 0); /** * qtest_get_irq: @@ -535,7 +542,8 @@ static inline void qtest_end(void) /** * qmp: - * @fmt...: QMP message to send to qemu + * @fmt...: QMP message to send to qemu; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * * Sends a QMP message to QEMU and returns the response. */ @@ -543,7 +551,8 @@ QDict *qmp(const char *fmt, ...); /** * qmp_async: - * @fmt...: QMP message to send to qemu + * @fmt...: QMP message to send to qemu; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * * Sends a QMP message to QEMU and leaves the response in the stream. */ @@ -551,7 +560,8 @@ void qmp_async(const char *fmt, ...); /** * qmp_discard_response: - * @fmt...: QMP message to send to qemu + * @fmt...: QMP message to send to qemu; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * * Sends a QMP message to QEMU and consumes the response. */ @@ -592,13 +602,13 @@ static inline QDict *qmp_eventwait_ref(const char *ev= ent) /** * 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: --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 150181078060064.34233801453752; Thu, 3 Aug 2017 18:39:40 -0700 (PDT) Received: from localhost ([::1]:43504 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRaV-0001CY-6s for importer@patchew.org; Thu, 03 Aug 2017 21:39:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59845) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNS-0008Kx-DC for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNR-0003vM-Ft for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46638) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNR-0003uF-8g for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:09 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 44FD8C04B30E for ; Fri, 4 Aug 2017 01:26:08 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id BD78A61F36; Fri, 4 Aug 2017 01:26:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 44FD8C04B30E Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:39 -0500 Message-Id: <20170804012551.2714-11-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 04 Aug 2017 01:26:08 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 10/22] libqtest: Skip round-trip through QObject 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" When we don't have to do any % interpolation in qmp() and friends, there is no point wasting time allocating a QObject from the format string only to then format it back into the string we send over the wire. This is a temporary measure: it becomes important in the next patch, where test-qga will be refactored to do interpolation in place, and where we must not re-interpolate the string; but will go away when further refactoring makes it easier to directly output a string without going through qmp_fd_sendv(). Signed-off-by: Eric Blake --- tests/libqtest.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index cde737ec5a..0cb439eefa 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -448,7 +448,7 @@ QDict *qtest_qmp_receive(QTestState *s) */ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) { - QObject *qobj; + QObject *qobj =3D NULL; int log =3D getenv("QTEST_LOG") !=3D NULL; QString *qstr; const char *str; @@ -462,9 +462,17 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) } assert(*fmt); - /* Going through qobject ensures we escape strings properly. */ - qobj =3D qobject_from_jsonv(fmt, ap); - qstr =3D qobject_to_json(qobj); + /* + * A round trip through QObject is only needed if % interpolation + * is used. We interpolate through QObject rather than sprintf in + * order to escape strings properly. + */ + if (strchr(fmt, '%')) { + qobj =3D qobject_from_jsonv(fmt, ap); + qstr =3D qobject_to_json(qobj); + } else { + qstr =3D qstring_from_str(fmt); + } /* * BUG: QMP doesn't react to input until it sees a newline, an --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810957106199.16676167546427; Thu, 3 Aug 2017 18:42:37 -0700 (PDT) Received: from localhost ([::1]:43895 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRdL-0003kS-GT for importer@patchew.org; Thu, 03 Aug 2017 21:42:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59918) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNU-0008Ne-Nq for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNS-0003wA-Ab for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45000) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNS-0003vD-1n for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:10 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1DCCB4DD49 for ; Fri, 4 Aug 2017 01:26:09 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7BDF561F36; Fri, 4 Aug 2017 01:26:08 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 1DCCB4DD49 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:40 -0500 Message-Id: <20170804012551.2714-12-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 04 Aug 2017 01:26:09 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 11/22] test-qga: Simplify command construction 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" When you build qga input manually like this: cmd =3D g_strdup_printf("{'execute': 'guest-file-write'," " 'arguments': {'handle': %" PRId64 "," " 'buf-b64': '%s' } }", id, enc); ret =3D qmp_fd(fixture->fd, cmd); g_free(cmd); you're responsible for escaping the interpolated values for JSON. Not done here, and therefore works only because the base64 encoding does not include % or '. Leaving interpolation into JSON via qobject_from_jsonf() is more robust; we can also reduce the boilerplate by factoring out the common 'execute':%s and 'arguments':%p code into new qga() and qga_args() helpers: ret =3D qga_args(fixture, "guest-file-write", "{'handle': %" PRId64 ", 'buf-b64': %s}", id, enc); Note that this reverts part of commit 1792d7d0; but that is because we just recently guaranteed support of PRId64 in qobject_from_jsonf(). Also note that the simple form qga() sends "arguments":{} over the wire rather than the previous approach of omitting it entirely; test_qga_ping() is updated to use a long-hand form to ensure that "arguments" is truly optional. As a bonus, this eliminates the last external caller using varargs for qmp_fd_send(); the next patch will simplify that interface to take just the string being sent over the wire rather than performing a string->QObject->string round trip (there's already a hint of that in the simplification of passing '\xff' separately from the command, where this patch had to tweak things to avoid an assertion). Also, this is a step towards getting rid of non-literal format strings; our new helpers can already use GCC_ATTR_FMT() just like qobject_from_jsonf(). Signed-off-by: Eric Blake --- tests/libqtest.c | 3 +- tests/test-qga.c | 222 +++++++++++++++++++++++++++------------------------= ---- 2 files changed, 111 insertions(+), 114 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index 0cb439eefa..ba09c949dc 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -458,7 +458,8 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) * resyncs */ if (*fmt =3D=3D '\377') { socket_send(fd, fmt, 1); - fmt++; + assert(!fmt[1]); + return; } assert(*fmt); diff --git a/tests/test-qga.c b/tests/test-qga.c index fd6bc7690f..839481e49b 100644 --- a/tests/test-qga.c +++ b/tests/test-qga.c @@ -5,6 +5,7 @@ #include #include "libqtest.h" +#include "qapi/qmp/qjson.h" typedef struct { char *test_dir; @@ -111,6 +112,55 @@ fixture_tear_down(TestFixture *fixture, gconstpointer = data) g_free(fixture->test_dir); } +static void GCC_FMT_ATTR(3, 0) qga_sendv(const TestFixture *fixture, + const char *cmd, + const char *fmt, va_list ap) +{ + QObject *args =3D qobject_from_jsonv(fmt, ap); + QObject *obj =3D qobject_from_jsonf("{'execute':%s, 'arguments':%p}", + cmd, args); + QString *qstr =3D qobject_to_json(obj); + const char *str; + + qstring_append_chr(qstr, '\n'); + str =3D qstring_get_str(qstr); + assert(!strchr(str, '%')); + qmp_fd_send(fixture->fd, str); + QDECREF(qstr); + qobject_decref(obj); +} + +static void GCC_FMT_ATTR(3, 4) qga_send_args(const TestFixture *fixture, + const char *cmd, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + qga_sendv(fixture, cmd, fmt, ap); + va_end(ap); +} + + +static QDict * GCC_FMT_ATTR(3, 4) qga_args(const TestFixture *fixture, + const char *cmd, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + qga_sendv(fixture, cmd, fmt, ap); + va_end(ap); + return qmp_fd_receive(fixture->fd); +} + +static QDict *qga(const TestFixture *fixture, const char *cmd) +{ + qga_send_args(fixture, cmd, "{}"); + return qmp_fd_receive(fixture->fd); +} + + static void qmp_assertion_message_error(const char *domain, const char *file, int line, @@ -144,12 +194,9 @@ static void test_qga_sync_delimited(gconstpointer fix) guint32 v, r =3D g_random_int(); unsigned char c; QDict *ret; - gchar *cmd; - cmd =3D g_strdup_printf("\xff{'execute': 'guest-sync-delimited'," - " 'arguments': {'id': %u } }", r); - qmp_fd_send(fixture->fd, cmd); - g_free(cmd); + qmp_fd_send(fixture->fd, "\xff"); + qga_send_args(fixture, "guest-sync-delimited", "{'id': %u}", r); /* * Read and ignore garbage until resynchronized. @@ -186,7 +233,6 @@ static void test_qga_sync(gconstpointer fix) const TestFixture *fixture =3D fix; guint32 v, r =3D g_random_int(); QDict *ret; - gchar *cmd; /* * TODO guest-sync is inherently limited: we cannot distinguish @@ -199,10 +245,7 @@ static void test_qga_sync(gconstpointer fix) * invalid JSON. Testing of '\xff' handling is done in * guest-sync-delimited instead. */ - cmd =3D g_strdup_printf("{'execute': 'guest-sync'," - " 'arguments': {'id': %u } }", r); - ret =3D qmp_fd(fixture->fd, cmd); - g_free(cmd); + ret =3D qga_args(fixture, "guest-sync", "{'id': %u}", r); g_assert_nonnull(ret); qmp_assert_no_error(ret); @@ -218,10 +261,17 @@ static void test_qga_ping(gconstpointer fix) const TestFixture *fixture =3D fix; QDict *ret; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-ping'}"); + /* qga() adds an "arguments":{} over the wire... */ + ret =3D qga(fixture, "guest-ping"); g_assert_nonnull(ret); qmp_assert_no_error(ret); + QDECREF(ret); + /* ...so also test in long-hand that "arguments" can be omitted. */ + qmp_fd_send(fixture->fd, "{'execute':'guest-ping'}"); + ret =3D qmp_fd_receive(fixture->fd); + g_assert_nonnull(ret); + qmp_assert_no_error(ret); QDECREF(ret); } @@ -231,8 +281,7 @@ static void test_qga_invalid_args(gconstpointer fix) QDict *ret, *error; const gchar *class, *desc; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-ping', " - "'arguments': {'foo': 42 }}"); + ret =3D qga_args(fixture, "guest-ping", "{'foo': 42 }"); g_assert_nonnull(ret); error =3D qdict_get_qdict(ret, "error"); @@ -251,7 +300,7 @@ static void test_qga_invalid_cmd(gconstpointer fix) QDict *ret, *error; const gchar *class, *desc; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-invalid-cmd'}"); + ret =3D qga(fixture, "guest-invalid-cmd"); g_assert_nonnull(ret); error =3D qdict_get_qdict(ret, "error"); @@ -270,7 +319,7 @@ static void test_qga_info(gconstpointer fix) QDict *ret, *val; const gchar *version; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-info'}"); + ret =3D qga(fixture, "guest-info"); g_assert_nonnull(ret); qmp_assert_no_error(ret); @@ -288,7 +337,7 @@ static void test_qga_get_vcpus(gconstpointer fix) QList *list; const QListEntry *entry; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-get-vcpus'}"); + ret =3D qga(fixture, "guest-get-vcpus"); g_assert_nonnull(ret); qmp_assert_no_error(ret); @@ -308,7 +357,7 @@ static void test_qga_get_fsinfo(gconstpointer fix) QList *list; const QListEntry *entry; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-get-fsinfo'}"); + ret =3D qga(fixture, "guest-get-fsinfo"); g_assert_nonnull(ret); qmp_assert_no_error(ret); @@ -331,7 +380,7 @@ static void test_qga_get_memory_block_info(gconstpointe= r fix) QDict *ret, *val; int64_t size; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-block-info'= }"); + ret =3D qga(fixture, "guest-get-memory-block-info"); g_assert_nonnull(ret); /* some systems might not expose memory block info in sysfs */ @@ -352,7 +401,7 @@ static void test_qga_get_memory_blocks(gconstpointer fi= x) QList *list; const QListEntry *entry; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-blocks'}"); + ret =3D qga(fixture, "guest-get-memory-blocks"); g_assert_nonnull(ret); /* some systems might not expose memory block info in sysfs */ @@ -376,7 +425,7 @@ static void test_qga_network_get_interfaces(gconstpoint= er fix) QList *list; const QListEntry *entry; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-network-get-interfaces= '}"); + ret =3D qga(fixture, "guest-network-get-interfaces"); g_assert_nonnull(ret); qmp_assert_no_error(ret); @@ -393,7 +442,7 @@ static void test_qga_file_ops(gconstpointer fix) const TestFixture *fixture =3D fix; const unsigned char helloworld[] =3D "Hello World!\n"; const char *b64; - gchar *cmd, *path, *enc; + gchar *path, *enc; unsigned char *dec; QDict *ret, *val; int64_t id, eof; @@ -402,8 +451,8 @@ static void test_qga_file_ops(gconstpointer fix) char tmp[100]; /* open */ - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-file-open'," - " 'arguments': { 'path': 'foo', 'mode': 'w+' } }"); + ret =3D qga_args(fixture, "guest-file-open", + "{ 'path': 'foo', 'mode': 'w+' }"); g_assert_nonnull(ret); qmp_assert_no_error(ret); id =3D qdict_get_int(ret, "return"); @@ -411,10 +460,8 @@ static void test_qga_file_ops(gconstpointer fix) enc =3D g_base64_encode(helloworld, sizeof(helloworld)); /* write */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-write'," - " 'arguments': { 'handle': %" PRId64 "," - " 'buf-b64': '%s' } }", id, enc); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-write", + "{ 'handle': %" PRId64 ", 'buf-b64': %s }", id, enc); g_assert_nonnull(ret); qmp_assert_no_error(ret); @@ -424,23 +471,14 @@ static void test_qga_file_ops(gconstpointer fix) g_assert_cmpint(count, =3D=3D, sizeof(helloworld)); g_assert_cmpint(eof, =3D=3D, 0); QDECREF(ret); - g_free(cmd); /* flush */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-flush'," - " 'arguments': {'handle': %" PRId64 "} }", - id); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-flush", "{'handle': %" PRId64 "}= ", id); QDECREF(ret); - g_free(cmd); /* close */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-close'," - " 'arguments': {'handle': %" PRId64 "} }", - id); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-close", "{'handle': %" PRId64 "}= ", id); QDECREF(ret); - g_free(cmd); /* check content */ path =3D g_build_filename(fixture->test_dir, "foo", NULL); @@ -454,18 +492,15 @@ static void test_qga_file_ops(gconstpointer fix) fclose(f); /* open */ - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-file-open'," - " 'arguments': { 'path': 'foo', 'mode': 'r' } }"); + ret =3D qga_args(fixture, "guest-file-open", + "{ 'path': 'foo', 'mode': 'r' }"); g_assert_nonnull(ret); qmp_assert_no_error(ret); id =3D qdict_get_int(ret, "return"); QDECREF(ret); /* read */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-read'," - " 'arguments': { 'handle': %" PRId64 "} }", - id); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-read", "{'handle': %" PRId64 "}"= , id); val =3D qdict_get_qdict(ret, "return"); count =3D qdict_get_int(val, "count"); eof =3D qdict_get_bool(val, "eof"); @@ -475,14 +510,10 @@ static void test_qga_file_ops(gconstpointer fix) g_assert_cmpstr(b64, =3D=3D, enc); QDECREF(ret); - g_free(cmd); g_free(enc); /* read eof */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-read'," - " 'arguments': { 'handle': %" PRId64 "} }", - id); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-read", "{'handle': %" PRId64 "}"= , id); val =3D qdict_get_qdict(ret, "return"); count =3D qdict_get_int(val, "count"); eof =3D qdict_get_bool(val, "eof"); @@ -491,14 +522,11 @@ static void test_qga_file_ops(gconstpointer fix) g_assert(eof); g_assert_cmpstr(b64, =3D=3D, ""); QDECREF(ret); - g_free(cmd); /* seek */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-seek'," - " 'arguments': { 'handle': %" PRId64 ", " - " 'offset': %d, 'whence': '%s' } }", - id, 6, "set"); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-seek", + "{'handle': %" PRId64 ", 'offset': %d, 'whence': %s}", + id, 6, "set"); qmp_assert_no_error(ret); val =3D qdict_get_qdict(ret, "return"); count =3D qdict_get_int(val, "position"); @@ -506,13 +534,9 @@ static void test_qga_file_ops(gconstpointer fix) g_assert_cmpint(count, =3D=3D, 6); g_assert(!eof); QDECREF(ret); - g_free(cmd); /* partial read */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-read'," - " 'arguments': { 'handle': %" PRId64 "} }", - id); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-read", "{'handle': %" PRId64 "}"= , id); val =3D qdict_get_qdict(ret, "return"); count =3D qdict_get_int(val, "count"); eof =3D qdict_get_bool(val, "eof"); @@ -525,15 +549,10 @@ static void test_qga_file_ops(gconstpointer fix) g_free(dec); QDECREF(ret); - g_free(cmd); /* close */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-close'," - " 'arguments': {'handle': %" PRId64 "} }", - id); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-close", "{'handle': %" PRId64 "}= ", id); QDECREF(ret); - g_free(cmd); } static void test_qga_file_write_read(gconstpointer fix) @@ -541,14 +560,14 @@ static void test_qga_file_write_read(gconstpointer fi= x) const TestFixture *fixture =3D fix; const unsigned char helloworld[] =3D "Hello World!\n"; const char *b64; - gchar *cmd, *enc; + gchar *enc; QDict *ret, *val; int64_t id, eof; gsize count; /* open */ - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-file-open'," - " 'arguments': { 'path': 'foo', 'mode': 'w+' } }"); + ret =3D qga_args(fixture, "guest-file-open", + "{ 'path': 'foo', 'mode': 'w+' }"); g_assert_nonnull(ret); qmp_assert_no_error(ret); id =3D qdict_get_int(ret, "return"); @@ -556,10 +575,8 @@ static void test_qga_file_write_read(gconstpointer fix) enc =3D g_base64_encode(helloworld, sizeof(helloworld)); /* write */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-write'," - " 'arguments': { 'handle': %" PRId64 "," - " 'buf-b64': '%s' } }", id, enc); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-write", + "{'handle': %" PRId64 ", 'buf-b64': %s}", id, enc); g_assert_nonnull(ret); qmp_assert_no_error(ret); @@ -569,13 +586,9 @@ static void test_qga_file_write_read(gconstpointer fix) g_assert_cmpint(count, =3D=3D, sizeof(helloworld)); g_assert_cmpint(eof, =3D=3D, 0); QDECREF(ret); - g_free(cmd); /* read (check implicit flush) */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-read'," - " 'arguments': { 'handle': %" PRId64 "} }", - id); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-read", "{'handle': %" PRId64 "}"= , id); val =3D qdict_get_qdict(ret, "return"); count =3D qdict_get_int(val, "count"); eof =3D qdict_get_bool(val, "eof"); @@ -584,14 +597,11 @@ static void test_qga_file_write_read(gconstpointer fi= x) g_assert(eof); g_assert_cmpstr(b64, =3D=3D, ""); QDECREF(ret); - g_free(cmd); /* seek to 0 */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-seek'," - " 'arguments': { 'handle': %" PRId64 ", " - " 'offset': %d, 'whence': '%s' } }", - id, 0, "set"); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-seek", + "{'handle': %" PRId64 ", 'offset': %d, 'whence': %s}", + id, 0, "set"); qmp_assert_no_error(ret); val =3D qdict_get_qdict(ret, "return"); count =3D qdict_get_int(val, "position"); @@ -599,13 +609,9 @@ static void test_qga_file_write_read(gconstpointer fix) g_assert_cmpint(count, =3D=3D, 0); g_assert(!eof); QDECREF(ret); - g_free(cmd); /* read */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-read'," - " 'arguments': { 'handle': %" PRId64 "} }", - id); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-read", "{'handle': %" PRId64 "}"= , id); val =3D qdict_get_qdict(ret, "return"); count =3D qdict_get_int(val, "count"); eof =3D qdict_get_bool(val, "eof"); @@ -614,16 +620,11 @@ static void test_qga_file_write_read(gconstpointer fi= x) g_assert(eof); g_assert_cmpstr(b64, =3D=3D, enc); QDECREF(ret); - g_free(cmd); g_free(enc); /* close */ - cmd =3D g_strdup_printf("{'execute': 'guest-file-close'," - " 'arguments': {'handle': %" PRId64 "} }", - id); - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-file-close", "{'handle': %" PRId64 "}= ", id); QDECREF(ret); - g_free(cmd); } static void test_qga_get_time(gconstpointer fix) @@ -632,7 +633,7 @@ static void test_qga_get_time(gconstpointer fix) QDict *ret; int64_t time; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}"); + ret =3D qga(fixture, "guest-get-time"); g_assert_nonnull(ret); qmp_assert_no_error(ret); @@ -651,7 +652,7 @@ static void test_qga_blacklist(gconstpointer data) fixture_setup(&fix, "-b guest-ping,guest-get-time", NULL); /* check blacklist */ - ret =3D qmp_fd(fix.fd, "{'execute': 'guest-ping'}"); + ret =3D qga(&fix, "guest-ping"); g_assert_nonnull(ret); error =3D qdict_get_qdict(ret, "error"); class =3D qdict_get_try_str(error, "class"); @@ -660,7 +661,7 @@ static void test_qga_blacklist(gconstpointer data) g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled")); QDECREF(ret); - ret =3D qmp_fd(fix.fd, "{'execute': 'guest-get-time'}"); + ret =3D qga(&fix, "guest-get-time"); g_assert_nonnull(ret); error =3D qdict_get_qdict(ret, "error"); class =3D qdict_get_try_str(error, "class"); @@ -670,7 +671,7 @@ static void test_qga_blacklist(gconstpointer data) QDECREF(ret); /* check something work */ - ret =3D qmp_fd(fix.fd, "{'execute': 'guest-get-fsinfo'}"); + ret =3D qga(&fix, "guest-get-fsinfo"); qmp_assert_no_error(ret); QDECREF(ret); @@ -762,7 +763,7 @@ static void test_qga_fsfreeze_status(gconstpointer fix) QDict *ret; const gchar *status; - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}"); + ret =3D qga(fixture, "guest-fsfreeze-status"); g_assert_nonnull(ret); qmp_assert_no_error(ret); @@ -781,12 +782,11 @@ static void test_qga_guest_exec(gconstpointer fix) int64_t pid, now, exitcode; gsize len; bool exited; - char *cmd; /* exec 'echo foo bar' */ - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" - " 'path': '/bin/echo', 'arg': [ '-n', '\" test_str \"' ]," - " 'capture-output': true } }"); + ret =3D qga_args(fixture, "guest-exec", + "{ 'path': '/bin/echo', 'arg': [ '-n', '\" test_str \"' ]= ," + " 'capture-output': true }"); g_assert_nonnull(ret); qmp_assert_no_error(ret); val =3D qdict_get_qdict(ret, "return"); @@ -796,10 +796,9 @@ static void test_qga_guest_exec(gconstpointer fix) /* wait for completion */ now =3D g_get_monotonic_time(); - cmd =3D g_strdup_printf("{'execute': 'guest-exec-status'," - " 'arguments': { 'pid': %" PRId64 " } }", pid); do { - ret =3D qmp_fd(fixture->fd, cmd); + ret =3D qga_args(fixture, "guest-exec-status", "{'pid': %" PRId64 = "}", + pid); g_assert_nonnull(ret); val =3D qdict_get_qdict(ret, "return"); exited =3D qdict_get_bool(val, "exited"); @@ -809,7 +808,6 @@ static void test_qga_guest_exec(gconstpointer fix) } while (!exited && g_get_monotonic_time() < now + 5 * G_TIME_SPAN_SECOND); g_assert(exited); - g_free(cmd); /* check stdout */ exitcode =3D qdict_get_int(val, "exitcode"); @@ -829,8 +827,7 @@ static void test_qga_guest_exec_invalid(gconstpointer f= ix) const gchar *class, *desc; /* invalid command */ - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" - " 'path': '/bin/invalid-cmd42' } }"); + ret =3D qga_args(fixture, "guest-exec", "{ 'path': '/bin/invalid-cmd42= ' }"); g_assert_nonnull(ret); error =3D qdict_get_qdict(ret, "error"); g_assert_nonnull(error); @@ -841,8 +838,7 @@ static void test_qga_guest_exec_invalid(gconstpointer f= ix) QDECREF(ret); /* invalid pid */ - ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-exec-status'," - " 'arguments': { 'pid': 0 } }"); + ret =3D qga_args(fixture, "guest-exec-status", "{ 'pid': 0 }"); g_assert_nonnull(ret); error =3D qdict_get_qdict(ret, "error"); g_assert_nonnull(error); @@ -868,7 +864,7 @@ static void test_qga_guest_get_osinfo(gconstpointer dat= a) g_free(cwd); fixture_setup(&fixture, NULL, env); - ret =3D qmp_fd(fixture.fd, "{'execute': 'guest-get-osinfo'}"); + ret =3D qga(&fixture, "guest-get-osinfo"); g_assert_nonnull(ret); qmp_assert_no_error(ret); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810955747184.34493028147983; Thu, 3 Aug 2017 18:42:35 -0700 (PDT) Received: from localhost ([::1]:43892 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRdJ-0003j7-T9 for importer@patchew.org; Thu, 03 Aug 2017 21:42:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59916) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNU-0008NX-Kw for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNT-0003x6-8x for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51300) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNS-0003w8-VX for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:11 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DBBC3C0587C1 for ; Fri, 4 Aug 2017 01:26:09 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5856D61F36; Fri, 4 Aug 2017 01:26:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com DBBC3C0587C1 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:41 -0500 Message-Id: <20170804012551.2714-13-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Fri, 04 Aug 2017 01:26:10 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 12/22] libqtest: Change qmp_fd_send() to drop varargs 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" With the previous commit, no external clients are using qmp_fd() or qmp_fd_sendv(). Making qmp_fd_sendv() static lets us refactor the public qmp_fd_send() to be the common point where we send a fixed string over the wire as well as log that string, while qmp_fd_sendv() worries about converting varargs into the final string. Note that the refactoring changes roles: previously, qmp_fd_send() deferred to qmp_fd_sendv(); now the call chain is in the opposite direction. Likewise, now that we take a fixed string, we no longer have to special case '\xff'. Add documentation while in the area. Signed-off-by: Eric Blake --- tests/libqtest.h | 20 ++++++++++++---- tests/libqtest.c | 73 +++++++++++++++++-----------------------------------= ---- tests/test-qga.c | 2 -- 3 files changed, 38 insertions(+), 57 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index 38148af66b..33af3ae8ff 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -923,11 +923,23 @@ static inline int64_t clock_set(int64_t val) return qtest_clock_set(global_qtest, val); } +/** + * qmp_fd_receive: + * @fd: Socket to read from. + * + * Read from input until a complete JSON object has been parsed, + * returning NULL on errors. + */ QDict *qmp_fd_receive(int fd); -void qmp_fd_sendv(int fd, const char *fmt, va_list ap); -void qmp_fd_send(int fd, const char *fmt, ...); -QDict *qmp_fdv(int fd, const char *fmt, va_list ap); -QDict *qmp_fd(int fd, const char *fmt, ...); + +/** + * qmp_fd_send: + * @fd: Socket to write to. + * @msg: Fixed string to send. + * + * Send a message to the destination, without waiting for a reply. + */ +void qmp_fd_send(int fd, const char *msg); /** * qtest_cb_for_every_machine: diff --git a/tests/libqtest.c b/tests/libqtest.c index ba09c949dc..0fa32928c8 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -441,26 +441,16 @@ QDict *qtest_qmp_receive(QTestState *s) return qmp_fd_receive(s->qmp_fd); } -/** - * Allow users to send a message without waiting for the reply, - * in the case that they choose to discard all replies up until - * a particular EVENT is received. +/* + * Internal code that converts from interpolated JSON into a message + * to send over the wire, without waiting for a reply. */ -void qmp_fd_sendv(int fd, const char *fmt, va_list ap) +static void qmp_fd_sendv(int fd, const char *fmt, va_list ap) { QObject *qobj =3D NULL; - int log =3D getenv("QTEST_LOG") !=3D NULL; QString *qstr; const char *str; - /* qobject_from_jsonv() silently eats leading 0xff as invalid - * JSON, but we want to test sending them over the wire to force - * resyncs */ - if (*fmt =3D=3D '\377') { - socket_send(fd, fmt, 1); - assert(!fmt[1]); - return; - } assert(*fmt); /* @@ -468,25 +458,17 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap) * is used. We interpolate through QObject rather than sprintf in * order to escape strings properly. */ - if (strchr(fmt, '%')) { - qobj =3D qobject_from_jsonv(fmt, ap); - qstr =3D qobject_to_json(qobj); - } else { - qstr =3D qstring_from_str(fmt); + if (!strchr(fmt, '%')) { + qmp_fd_send(fd, fmt); + return; } - /* - * BUG: QMP doesn't react to input until it sees a newline, an - * object, or an array. Work-around: give it a newline. - */ - qstring_append_chr(qstr, '\n'); + qobj =3D qobject_from_jsonv(fmt, ap); + qstr =3D qobject_to_json(qobj); str =3D qstring_get_str(qstr); - if (log) { - fprintf(stderr, "%s", str); - } /* Send QMP request */ - socket_send(fd, str, qstring_get_length(qstr)); + qmp_fd_send(fd, str); QDECREF(qstr); qobject_decref(qobj); @@ -497,13 +479,6 @@ void qtest_async_qmpv(QTestState *s, const char *fmt, = va_list ap) qmp_fd_sendv(s->qmp_fd, fmt, ap); } -QDict *qmp_fdv(int fd, const char *fmt, va_list ap) -{ - qmp_fd_sendv(fd, fmt, ap); - - return qmp_fd_receive(fd); -} - QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap) { qtest_async_qmpv(s, fmt, ap); @@ -512,24 +487,20 @@ QDict *qtest_qmpv(QTestState *s, const char *fmt, va_= list ap) return qtest_qmp_receive(s); } -QDict *qmp_fd(int fd, const char *fmt, ...) +void qmp_fd_send(int fd, const char *msg) { - va_list ap; - QDict *response; + int log =3D getenv("QTEST_LOG") !=3D NULL; - va_start(ap, fmt); - response =3D qmp_fdv(fd, fmt, ap); - va_end(ap); - return response; -} - -void qmp_fd_send(int fd, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - qmp_fd_sendv(fd, fmt, ap); - va_end(ap); + if (log) { + fprintf(stderr, "%s\n", msg); + } + /* Send QMP request */ + socket_send(fd, msg, strlen(msg)); + /* + * BUG: QMP doesn't react to input until it sees a newline, an + * object, or an array. Work-around: give it a newline. + */ + socket_send(fd, "\n", 1); } QDict *qtest_qmp(QTestState *s, const char *fmt, ...) diff --git a/tests/test-qga.c b/tests/test-qga.c index 839481e49b..ae0da6c9ac 100644 --- a/tests/test-qga.c +++ b/tests/test-qga.c @@ -122,9 +122,7 @@ static void GCC_FMT_ATTR(3, 0) qga_sendv(const TestFixt= ure *fixture, QString *qstr =3D qobject_to_json(obj); const char *str; - qstring_append_chr(qstr, '\n'); str =3D qstring_get_str(qstr); - assert(!strchr(str, '%')); qmp_fd_send(fixture->fd, str); QDECREF(qstr); qobject_decref(obj); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501811180896838.7104044030702; Thu, 3 Aug 2017 18:46:20 -0700 (PDT) Received: from localhost ([::1]:44399 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRgx-0006jP-Bq for importer@patchew.org; Thu, 03 Aug 2017 21:46:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59972) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNV-0008Ot-UV for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNU-0003yX-Bd for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:13 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45034) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNU-0003xJ-2e for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:12 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A703D4DD49 for ; Fri, 4 Aug 2017 01:26:10 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 17E7261F58; Fri, 4 Aug 2017 01:26:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com A703D4DD49 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:42 -0500 Message-Id: <20170804012551.2714-14-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 04 Aug 2017 01:26:11 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 13/22] libqtest: Add qmp_raw() 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The majority of calls into libqtest's qmp() and friends are passing a JSON object that includes a command name; we can prove this by adding an assertion. The only outlier is qmp-test, which is testing appropriate error responses to protocol violations and id support, by sending raw strings, where those raw strings don't need interpolation anyways. Adding a new entry-point makes a clean separation of which input needs interpolation, so that upcoming patches can refactor qmp() to be more like the recent additions to test-qga in taking the command name separately from the arguments for an overall reduction in testsuite boilerplate. This change also lets us move the workaround for the QMP parser limitation of not ending a parse until } or newline: all calls through qmp() are passing an object ending in }, so only the few callers of qmp_raw() have to worry about a trailing newline. Signed-off-by: Eric Blake --- tests/libqtest.h | 8 ++++++++ tests/libqtest.c | 13 +++++++------ tests/qmp-test.c | 19 ++++++++++++------- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index 33af3ae8ff..917ec5cf92 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -550,6 +550,14 @@ static inline void qtest_end(void) QDict *qmp(const char *fmt, ...); /** + * qmp_raw: + * @msg: Raw QMP message to send to qemu. + * + * Sends a QMP message to QEMU and returns the response. + */ +QDict *qmp_raw(const char *msg); + +/** * qmp_async: * @fmt...: QMP message to send to qemu; formats arguments through * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). diff --git a/tests/libqtest.c b/tests/libqtest.c index 0fa32928c8..3071be2efb 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -451,7 +451,7 @@ static void qmp_fd_sendv(int fd, const char *fmt, va_li= st ap) QString *qstr; const char *str; - assert(*fmt); + assert(strstr(fmt, "execute")); /* * A round trip through QObject is only needed if % interpolation @@ -496,11 +496,6 @@ void qmp_fd_send(int fd, const char *msg) } /* Send QMP request */ socket_send(fd, msg, strlen(msg)); - /* - * BUG: QMP doesn't react to input until it sees a newline, an - * object, or an array. Work-around: give it a newline. - */ - socket_send(fd, "\n", 1); } QDict *qtest_qmp(QTestState *s, const char *fmt, ...) @@ -899,6 +894,12 @@ QDict *qmp(const char *fmt, ...) return response; } +QDict *qmp_raw(const char *msg) +{ + qmp_fd_send(global_qtest->qmp_fd, msg); + return qtest_qmp_receive(global_qtest); +} + void qmp_async(const char *fmt, ...) { va_list ap; diff --git a/tests/qmp-test.c b/tests/qmp-test.c index 5d0260b2be..905fb4b3e5 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -44,28 +44,33 @@ static void test_malformed(void) { QDict *resp; + /* + * BUG: QMP doesn't react to input until it sees a newline, an + * object, or an array. Work-around: give it a newline. + */ + /* Not even a dictionary */ - resp =3D qmp("null"); + resp =3D qmp_raw("null\n"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); QDECREF(resp); /* No "execute" key */ - resp =3D qmp("{}"); + resp =3D qmp_raw("{}"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); QDECREF(resp); /* "execute" isn't a string */ - resp =3D qmp("{ 'execute': true }"); + resp =3D qmp_raw("{ 'execute': true }"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); QDECREF(resp); /* "arguments" isn't a dictionary */ - resp =3D qmp("{ 'execute': 'no-such-cmd', 'arguments': [] }"); + resp =3D qmp_raw("{ 'execute': 'no-such-cmd', 'arguments': [] }"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); QDECREF(resp); /* extra key */ - resp =3D qmp("{ 'execute': 'no-such-cmd', 'extra': true }"); + resp =3D qmp_raw("{ 'execute': 'no-such-cmd', 'extra': true }"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); QDECREF(resp); } @@ -114,14 +119,14 @@ static void test_qmp_protocol(void) test_malformed(); /* Test 'id' */ - resp =3D qmp("{ 'execute': 'query-name', 'id': 'cookie#1' }"); + resp =3D qmp_raw("{ 'execute': 'query-name', 'id': 'cookie#1' }"); ret =3D qdict_get_qdict(resp, "return"); g_assert(ret); g_assert_cmpstr(qdict_get_try_str(resp, "id"), =3D=3D, "cookie#1"); QDECREF(resp); /* Test command failure with 'id' */ - resp =3D qmp("{ 'execute': 'human-monitor-command', 'id': 2 }"); + resp =3D qmp_raw("{ 'execute': 'human-monitor-command', 'id': 2 }"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "GenericError"); g_assert_cmpint(qdict_get_int(resp, "id"), =3D=3D, 2); QDECREF(resp); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501811138447997.5463924159413; Thu, 3 Aug 2017 18:45:38 -0700 (PDT) Received: from localhost ([::1]:44373 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRgF-0006Nh-81 for importer@patchew.org; Thu, 03 Aug 2017 21:45:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60292) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNg-0008WQ-6f for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNd-0004HP-Vi for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59434) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNY-000460-Vj; Thu, 03 Aug 2017 21:26:17 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B91EC883AB; Fri, 4 Aug 2017 01:26:15 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id D703F61F36; Fri, 4 Aug 2017 01:26:10 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com B91EC883AB Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:43 -0500 Message-Id: <20170804012551.2714-15-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 04 Aug 2017 01:26:16 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 14/22] libqtest: Separate qmp_discard_response() from command 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: "open list:IDE" , John Snow , armbru@redhat.com, Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Upcoming patches will be adding new convenience methods for constructing QMP commands. But making every variation of sending support every variation of response handling becomes unwieldy; it's easier to specify that discarding a JSON response is unassociated with sending the command, where qmp_async() already fits the bill for sending a command without tying up a reference to the response. Doing this renders qtest_qmp[v]_discard_response() unused. Bonus: gets rid of a non-literal format string, which is a step towards compile-time format string checking without triggering -Wformat-nonliteral. Signed-off-by: Eric Blake --- tests/libqtest.h | 27 ++------------------------- tests/libqtest.c | 30 ++++++------------------------ tests/ahci-test.c | 20 ++++++++++---------- tests/boot-order-test.c | 2 +- tests/drive_del-test.c | 5 +++-- tests/fdc-test.c | 11 ++++++----- tests/ide-test.c | 5 ++--- tests/postcopy-test.c | 3 ++- tests/test-filter-mirror.c | 3 ++- tests/test-filter-redirector.c | 6 ++++-- tests/virtio-blk-test.c | 21 ++++++++++++--------- 11 files changed, 50 insertions(+), 83 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index 917ec5cf92..6bae0223aa 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -48,16 +48,6 @@ QTestState *qtest_init_without_qmp_handshake(const char = *extra_args); void qtest_quit(QTestState *s); /** - * qtest_qmp_discard_response: - * @s: #QTestState instance to operate on. - * @fmt...: QMP message to send to qemu; formats arguments through - * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). - * - * Sends a QMP message to QEMU and consumes the response. - */ -void qtest_qmp_discard_response(QTestState *s, const char *fmt, ...); - -/** * qtest_qmp: * @s: #QTestState instance to operate on. * @fmt...: QMP message to send to qemu; formats arguments through @@ -78,17 +68,6 @@ QDict *qtest_qmp(QTestState *s, const char *fmt, ...); void qtest_async_qmp(QTestState *s, const char *fmt, ...); /** - * qtest_qmpv_discard_response: - * @s: #QTestState instance to operate on. - * @fmt: QMP message to send to QEMU; formats arguments through - * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). - * @ap: QMP message arguments - * - * Sends a QMP message to QEMU and consumes the response. - */ -void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list a= p); - -/** * qtest_qmpv: * @s: #QTestState instance to operate on. * @fmt: QMP message to send to QEMU; formats arguments through @@ -568,12 +547,10 @@ void qmp_async(const char *fmt, ...); /** * qmp_discard_response: - * @fmt...: QMP message to send to qemu; formats arguments through - * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). * - * Sends a QMP message to QEMU and consumes the response. + * Read and discard a QMP response, typically after qmp_async(). */ -void qmp_discard_response(const char *fmt, ...); +void qmp_discard_response(void); /** * qmp_receive: diff --git a/tests/libqtest.c b/tests/libqtest.c index 3071be2efb..f9781d67f5 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -235,7 +235,8 @@ QTestState *qtest_init(const char *extra_args) /* Read the QMP greeting and then do the handshake */ greeting =3D qtest_qmp_receive(s); QDECREF(greeting); - qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }"); + greeting =3D qtest_qmp(s, "{ 'execute': 'qmp_capabilities' }"); + QDECREF(greeting); return s; } @@ -518,23 +519,6 @@ void qtest_async_qmp(QTestState *s, const char *fmt, .= ..) va_end(ap); } -void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list a= p) -{ - QDict *response =3D qtest_qmpv(s, fmt, ap); - QDECREF(response); -} - -void qtest_qmp_discard_response(QTestState *s, const char *fmt, ...) -{ - va_list ap; - QDict *response; - - va_start(ap, fmt); - response =3D qtest_qmpv(s, fmt, ap); - va_end(ap); - QDECREF(response); -} - QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event) { QDict *response; @@ -909,14 +893,12 @@ void qmp_async(const char *fmt, ...) va_end(ap); } -void qmp_discard_response(const char *fmt, ...) +void qmp_discard_response(void) { - va_list ap; - - va_start(ap, fmt); - qtest_qmpv_discard_response(global_qtest, fmt, ap); - va_end(ap); + QDict *response =3D qtest_qmp_receive(global_qtest); + QDECREF(response); } + char *hmp(const char *fmt, ...) { va_list ap; diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 999121bb7c..9460843a9f 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -1596,8 +1596,9 @@ static void test_atapi_tray(void) rsp =3D qmp_receive(); QDECREF(rsp); - qmp_discard_response("{'execute': 'x-blockdev-remove-medium', " - "'arguments': {'device': 'drive0'}}"); + qmp_async("{'execute': 'x-blockdev-remove-medium', " + "'arguments': {'device': 'drive0'}}"); + qmp_discard_response(); /* Test the tray without a medium */ ahci_atapi_load(ahci, port); @@ -1607,14 +1608,13 @@ static void test_atapi_tray(void) atapi_wait_tray(true); /* Re-insert media */ - qmp_discard_response("{'execute': 'blockdev-add', " - "'arguments': {'node-name': 'node0', " - "'driver': 'raw', " - "'file': { 'driver': 'file', " - "'filename': %s }}}", is= o); - qmp_discard_response("{'execute': 'x-blockdev-insert-medium'," - "'arguments': { 'device': 'drive0', " - "'node-name': 'node0' }}"); + qmp_async("{'execute': 'blockdev-add', 'arguments': {" + " 'node-name': 'node0', 'driver': 'raw', " + " 'file': { 'driver': 'file', 'filename': %s }}}", iso); + qmp_discard_response(); + qmp_async("{'execute': 'x-blockdev-insert-medium'," + "'arguments': { 'device': 'drive0', 'node-name': 'node0' }}"= ); + qmp_discard_response(); /* Again, the event shows up first */ qmp_async("{'execute': 'blockdev-close-tray', " diff --git a/tests/boot-order-test.c b/tests/boot-order-test.c index 9d516830dd..4114720236 100644 --- a/tests/boot-order-test.c +++ b/tests/boot-order-test.c @@ -38,7 +38,7 @@ static void test_a_boot_order(const char *machine, qtest_start(args); actual =3D read_boot_order(); g_assert_cmphex(actual, =3D=3D, expected_boot); - qmp_discard_response("{ 'execute': 'system_reset' }"); + qmp_async("{ 'execute': 'system_reset' }"); /* * system_reset only requests reset. We get a RESET event after * the actual reset completes. Need to wait for that. diff --git a/tests/drive_del-test.c b/tests/drive_del-test.c index 2175139abb..834a634da3 100644 --- a/tests/drive_del-test.c +++ b/tests/drive_del-test.c @@ -34,8 +34,9 @@ static void device_del(void) QDict *response; /* Complication: ignore DEVICE_DELETED event */ - qmp_discard_response("{'execute': 'device_del'," - " 'arguments': { 'id': 'dev0' } }"); + qmp_async("{'execute': 'device_del'," + " 'arguments': { 'id': 'dev0' } }"); + qmp_discard_response(); response =3D qmp_receive(); g_assert(response); g_assert(qdict_haskey(response, "return")); diff --git a/tests/fdc-test.c b/tests/fdc-test.c index 325712e0f2..ab61a82873 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -298,9 +298,10 @@ static void test_media_insert(void) /* Insert media in drive. DSKCHK should not be reset until a step pulse * is sent. */ - qmp_discard_response("{'execute':'blockdev-change-medium', 'arguments'= :{" - " 'id':'floppy0', 'filename': %s, 'format': 'raw'= }}", - test_image); + qmp_async("{'execute':'blockdev-change-medium', 'arguments':{" + " 'id':'floppy0', 'filename': %s, 'format': 'raw' }}", + test_image); + qmp_discard_response(); dir =3D inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); @@ -329,8 +330,8 @@ static void test_media_change(void) /* Eject the floppy and check that DSKCHG is set. Reading it out doesn= 't * reset the bit. */ - qmp_discard_response("{'execute':'eject', 'arguments':{" - " 'id':'floppy0' }}"); + qmp_async("{'execute':'eject', 'arguments':{ 'id':'floppy0' }}"); + qmp_discard_response(); dir =3D inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); diff --git a/tests/ide-test.c b/tests/ide-test.c index bfd79ddbdc..757af7cd1d 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -624,7 +624,6 @@ static void test_retry_flush(const char *machine) QPCIDevice *dev; QPCIBar bmdma_bar, ide_bar; uint8_t data; - const char *s; prepare_blkdebug_script(debug_path, "flush_to_disk"); @@ -652,8 +651,8 @@ static void test_retry_flush(const char *machine) qmp_eventwait("STOP"); /* Complete the command */ - s =3D "{'execute':'cont' }"; - qmp_discard_response(s); + qmp_async("{'execute':'cont' }"); + qmp_discard_response(); /* Check registers */ data =3D qpci_io_readb(dev, ide_bar, reg_device); diff --git a/tests/postcopy-test.c b/tests/postcopy-test.c index 8142f2ab90..ceaed823eb 100644 --- a/tests/postcopy-test.c +++ b/tests/postcopy-test.c @@ -482,7 +482,8 @@ static void test_migrate(void) usleep(10 * 1000); } while (dest_byte_a =3D=3D dest_byte_b); - qmp_discard_response("{ 'execute' : 'stop'}"); + qmp_async("{ 'execute' : 'stop'}"); + qmp_discard_response(); /* With it stopped, check nothing changes */ qtest_memread(to, start_address, &dest_byte_c, 1); sleep(1); diff --git a/tests/test-filter-mirror.c b/tests/test-filter-mirror.c index 9f84402493..79c5306fe7 100644 --- a/tests/test-filter-mirror.c +++ b/tests/test-filter-mirror.c @@ -57,7 +57,8 @@ static void test_mirror(void) }; /* send a qmp command to guarantee that 'connected' is setting to true= . */ - qmp_discard_response("{ 'execute' : 'query-status'}"); + qmp_async("{ 'execute' : 'query-status'}"); + qmp_discard_response(); ret =3D iov_send(send_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_b= uf)); g_assert_cmpint(ret, =3D=3D, sizeof(send_buf) + sizeof(size)); close(send_sock[0]); diff --git a/tests/test-filter-redirector.c b/tests/test-filter-redirector.c index 0c4b8d52ef..a6a714abea 100644 --- a/tests/test-filter-redirector.c +++ b/tests/test-filter-redirector.c @@ -99,7 +99,8 @@ static void test_redirector_tx(void) g_assert_cmpint(recv_sock, !=3D, -1); /* send a qmp command to guarantee that 'connected' is setting to true= . */ - qmp_discard_response("{ 'execute' : 'query-status'}"); + qmp_async("{ 'execute' : 'query-status'}"); + qmp_discard_response(); struct iovec iov[] =3D { { @@ -184,7 +185,8 @@ static void test_redirector_rx(void) send_sock =3D unix_connect(sock_path1, NULL); g_assert_cmpint(send_sock, !=3D, -1); /* send a qmp command to guarantee that 'connected' is setting to true= . */ - qmp_discard_response("{ 'execute' : 'query-status'}"); + qmp_async("{ 'execute' : 'query-status'}"); + qmp_discard_response(); ret =3D iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf)= ); g_assert_cmpint(ret, =3D=3D, sizeof(send_buf) + sizeof(size)); diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index 0576cb16ba..fe966c0606 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -409,9 +409,10 @@ static void pci_config(void) qvirtio_set_driver_ok(&dev->vdev); - qmp_discard_response("{ 'execute': 'block_resize', " - " 'arguments': { 'device': 'drive0', " - " 'size': %d } }", n_size); + qmp_async("{ 'execute': 'block_resize', " + " 'arguments': { 'device': 'drive0', " + " 'size': %d } }", n_size); + qmp_discard_response(); qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US); capacity =3D qvirtio_config_readq(&dev->vdev, 0); @@ -459,9 +460,10 @@ static void pci_msix(void) qvirtio_set_driver_ok(&dev->vdev); - qmp_discard_response("{ 'execute': 'block_resize', " - " 'arguments': { 'device': 'drive0', " - " 'size': %d } }", n_size); + qmp_async("{ 'execute': 'block_resize', " + " 'arguments': { 'device': 'drive0', " + " 'size': %d } }", n_size); + qmp_discard_response(); qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US); @@ -700,9 +702,10 @@ static void mmio_basic(void) test_basic(&dev->vdev, alloc, vq); - qmp_discard_response("{ 'execute': 'block_resize', " - " 'arguments': { 'device': 'drive0', " - " 'size': %d } }", n_size); + qmp_async("{ 'execute': 'block_resize', " + " 'arguments': { 'device': 'drive0', " + " 'size': %d } }", n_size); + qmp_discard_response(); qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810345988146.3062594643808; Thu, 3 Aug 2017 18:32:25 -0700 (PDT) Received: from localhost ([::1]:43458 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRTU-0004Hp-Fe for importer@patchew.org; Thu, 03 Aug 2017 21:32:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60164) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNb-0008Tr-W3 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNZ-00049t-Rc for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59448) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNZ-00047L-JL for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:17 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 69FDF883B4 for ; Fri, 4 Aug 2017 01:26:16 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id DF66061F57; Fri, 4 Aug 2017 01:26:15 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 69FDF883B4 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:44 -0500 Message-Id: <20170804012551.2714-16-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 04 Aug 2017 01:26:16 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 15/22] libqtest: Delete qtest_qmp() wrappers 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" None of our tests were directly using qtest_qmp() and friends; even tests like postcopy-test.c that manage multiple connections get along just fine changing global_qtest as needed (other than one callsite where it forgot to use the inlined form). It's also annoying that we have qmp_async() but qtest_async_qmp(), with inconsistent naming for tracing through the wrappers. As future patches are about to add some convenience functions for easier generation of QMP commands, it's easier if we don't have to percolate the changes through as many layers of the stack, by getting rid of the layer that no one uses, and just documenting that callers have to massage the global variable as needed. (Yes, this is backwards from good design that says all state should be passed as parameters rather than via a global variable - but such is life in maintaining a testsuite, where it is easier to write concise tests than it is to retrofit all existing tests to pass the extra parameter everywhere.) Internally, we rename qmp_fd_sendv() to qtest_qmp_sendv(), as well as give it a ... counterpart qmp_fd_send(), but the overall reduction in code makes this file a bit less repetitive. Signed-off-by: Eric Blake --- tests/libqtest.h | 75 +++++------------------------------------------= ---- tests/libqtest.c | 71 +++++++++++++----------------------------------- tests/postcopy-test.c | 2 +- 3 files changed, 25 insertions(+), 123 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index 6bae0223aa..684cfb3507 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -21,6 +21,11 @@ typedef struct QTestState QTestState; +/* + * The various qmp_*() commands operate on global_qtest. Tests can + * alternate between two parallel connections by switching which state + * is current before issuing commands. + */ extern QTestState *global_qtest; /** @@ -48,49 +53,7 @@ QTestState *qtest_init_without_qmp_handshake(const char = *extra_args); void qtest_quit(QTestState *s); /** - * qtest_qmp: - * @s: #QTestState instance to operate on. - * @fmt...: QMP message to send to qemu; formats arguments through - * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). - * - * Sends a QMP message to QEMU and returns the response. - */ -QDict *qtest_qmp(QTestState *s, const char *fmt, ...); - -/** - * qtest_async_qmp: - * @s: #QTestState instance to operate on. - * @fmt...: QMP message to send to qemu; formats arguments through - * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). - * - * Sends a QMP message to QEMU and leaves the response in the stream. - */ -void qtest_async_qmp(QTestState *s, const char *fmt, ...); - -/** - * qtest_qmpv: - * @s: #QTestState instance to operate on. - * @fmt: QMP message to send to QEMU; formats arguments through - * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). - * @ap: QMP message arguments - * - * Sends a QMP message to QEMU and returns the response. - */ -QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap); - -/** - * qtest_async_qmpv: - * @s: #QTestState instance to operate on. - * @fmt: QMP message to send to QEMU; formats arguments through - * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). - * @ap: QMP message arguments - * - * Sends a QMP message to QEMU and leaves the response in the stream. - */ -void qtest_async_qmpv(QTestState *s, const char *fmt, va_list ap); - -/** - * qtest_receive: + * qtest_qmp_receive: * @s: #QTestState instance to operate on. * * Reads a QMP message from QEMU and returns the response. @@ -117,32 +80,6 @@ void qtest_qmp_eventwait(QTestState *s, const char *eve= nt); 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, 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, ...) GCC_FMT_ATTR(2, 3); - -/** - * qtest_hmpv: - * @s: #QTestState instance to operate on. - * @fmt: HMP command to send to QEMU, formats arguments like vsprintf(). - * @ap: HMP command arguments - * - * 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_hmpv(QTestState *s, const char *fmt, va_list ap) - GCC_FMT_ATTR(2, 0); - -/** * qtest_get_irq: * @s: #QTestState instance to operate on. * @num: Interrupt to observe. diff --git a/tests/libqtest.c b/tests/libqtest.c index f9781d67f5..2df01682c0 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -233,9 +233,10 @@ QTestState *qtest_init(const char *extra_args) QDict *greeting; /* Read the QMP greeting and then do the handshake */ - greeting =3D qtest_qmp_receive(s); + greeting =3D qmp_fd_receive(s->qmp_fd); QDECREF(greeting); - greeting =3D qtest_qmp(s, "{ 'execute': 'qmp_capabilities' }"); + qmp_fd_send(s->qmp_fd, "{ 'execute': 'qmp_capabilities' }"); + greeting =3D qmp_fd_receive(s->qmp_fd); QDECREF(greeting); return s; @@ -446,7 +447,7 @@ QDict *qtest_qmp_receive(QTestState *s) * Internal code that converts from interpolated JSON into a message * to send over the wire, without waiting for a reply. */ -static void qmp_fd_sendv(int fd, const char *fmt, va_list ap) +static void qtest_qmp_sendv(QTestState *s, const char *fmt, va_list ap) { QObject *qobj =3D NULL; QString *qstr; @@ -460,7 +461,7 @@ static void qmp_fd_sendv(int fd, const char *fmt, va_li= st ap) * order to escape strings properly. */ if (!strchr(fmt, '%')) { - qmp_fd_send(fd, fmt); + qmp_fd_send(s->qmp_fd, fmt); return; } @@ -469,23 +470,19 @@ static void qmp_fd_sendv(int fd, const char *fmt, va_= list ap) str =3D qstring_get_str(qstr); /* Send QMP request */ - qmp_fd_send(fd, str); + qmp_fd_send(s->qmp_fd, str); QDECREF(qstr); qobject_decref(qobj); } -void qtest_async_qmpv(QTestState *s, const char *fmt, va_list ap) +static void qtest_qmp_send(QTestState *s, const char *fmt, ...) { - qmp_fd_sendv(s->qmp_fd, fmt, ap); -} + va_list ap; -QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap) -{ - qtest_async_qmpv(s, fmt, ap); - - /* Receive reply */ - return qtest_qmp_receive(s); + va_start(ap, fmt); + qtest_qmp_sendv(s, fmt, ap); + va_end(ap); } void qmp_fd_send(int fd, const char *msg) @@ -499,26 +496,6 @@ void qmp_fd_send(int fd, const char *msg) socket_send(fd, msg, strlen(msg)); } -QDict *qtest_qmp(QTestState *s, const char *fmt, ...) -{ - va_list ap; - QDict *response; - - va_start(ap, fmt); - response =3D qtest_qmpv(s, fmt, ap); - va_end(ap); - return response; -} - -void qtest_async_qmp(QTestState *s, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - qtest_async_qmpv(s, fmt, ap); - va_end(ap); -} - QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event) { QDict *response; @@ -541,16 +518,16 @@ void qtest_qmp_eventwait(QTestState *s, const char *e= vent) QDECREF(response); } -char *qtest_hmpv(QTestState *s, const char *fmt, va_list ap) +static char *qtest_hmpv(QTestState *s, const char *fmt, va_list ap) { char *cmd; QDict *resp; char *ret; cmd =3D g_strdup_vprintf(fmt, ap); - resp =3D qtest_qmp(s, "{'execute': 'human-monitor-command'," - " 'arguments': {'command-line': %s}}", - cmd); + qtest_qmp_send(s, "{'execute': 'human-monitor-command'," + " 'arguments': {'command-line': %s}}", cmd); + resp =3D qtest_qmp_receive(s); ret =3D g_strdup(qdict_get_try_str(resp, "return")); while (ret =3D=3D NULL && qdict_get_try_str(resp, "event")) { /* Ignore asynchronous QMP events */ @@ -564,17 +541,6 @@ char *qtest_hmpv(QTestState *s, const char *fmt, va_li= st ap) return ret; } -char *qtest_hmp(QTestState *s, const char *fmt, ...) -{ - va_list ap; - char *ret; - - va_start(ap, fmt); - ret =3D qtest_hmpv(s, fmt, ap); - va_end(ap); - return ret; -} - const char *qtest_get_arch(void) { const char *qemu =3D getenv("QTEST_QEMU_BINARY"); @@ -870,12 +836,11 @@ void qtest_memset(QTestState *s, uint64_t addr, uint8= _t pattern, size_t size) QDict *qmp(const char *fmt, ...) { va_list ap; - QDict *response; va_start(ap, fmt); - response =3D qtest_qmpv(global_qtest, fmt, ap); + qtest_qmp_sendv(global_qtest, fmt, ap); va_end(ap); - return response; + return qtest_qmp_receive(global_qtest); } QDict *qmp_raw(const char *msg) @@ -889,7 +854,7 @@ void qmp_async(const char *fmt, ...) va_list ap; va_start(ap, fmt); - qtest_async_qmpv(global_qtest, fmt, ap); + qtest_qmp_sendv(global_qtest, fmt, ap); va_end(ap); } diff --git a/tests/postcopy-test.c b/tests/postcopy-test.c index ceaed823eb..61f4b4180a 100644 --- a/tests/postcopy-test.c +++ b/tests/postcopy-test.c @@ -236,7 +236,7 @@ static QDict *return_or_event(QDict *response) got_stop =3D true; } QDECREF(response); - return return_or_event(qtest_qmp_receive(global_qtest)); + return return_or_event(qmp_receive()); } --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810792378734.2631624805364; Thu, 3 Aug 2017 18:39:52 -0700 (PDT) Received: from localhost ([::1]:43507 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRaf-0001U9-UI for importer@patchew.org; Thu, 03 Aug 2017 21:39:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60452) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNl-000082-Jc for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNj-0004W0-4O for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53856) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNb-0004BJ-34; Thu, 03 Aug 2017 21:26:19 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D8E7261461; Fri, 4 Aug 2017 01:26:17 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id AFB2A61F36; Fri, 4 Aug 2017 01:26:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D8E7261461 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:45 -0500 Message-Id: <20170804012551.2714-17-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 04 Aug 2017 01:26:18 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 16/22] libqtest: Add qmp_cmd() helper 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: Ben Warren , "open list:IDE" , Jason Wang , armbru@redhat.com, John Snow , =?UTF-8?q?Andreas=20F=C3=A4rber?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Now that we've asserted that all of our interpolated QMP commands include 'execute', we can reduce some of the caller boilerplate by providing a helpr function to wrap commands with no arguments (later patches will cover commands with arguments). Adjust all callers that can use the new helpers; in the process, fixing a couple of places where we would have failed -Wformat-nonliteral. Likewise, libqos.c no longer needs qmp_execute(), which in turn fixes the fact that it is better to interpolate JSON strings through qobject_from_json() than through sprintf(). The current name is long, but temporary: later patches will remove all other uses of qmp(), and then make the mass rename of qmp_cmd() down to qmp(). Signed-off-by: Eric Blake --- tests/libqtest.h | 16 ++++++++++++++++ tests/libqtest.c | 13 ++++++++++++- tests/ahci-test.c | 4 +--- tests/boot-order-test.c | 2 +- tests/ide-test.c | 2 +- tests/libqos/ahci.c | 4 ++-- tests/libqos/libqos.c | 16 ++-------------- tests/numa-test.c | 2 +- tests/postcopy-test.c | 8 ++++---- tests/q35-test.c | 2 +- tests/qmp-test.c | 8 ++++---- tests/qom-test.c | 2 +- tests/test-filter-mirror.c | 2 +- tests/test-filter-redirector.c | 4 ++-- tests/test-x86-cpuid-compat.c | 2 +- tests/virtio-net-test.c | 13 ++++++------- tests/vmgenid-test.c | 2 +- tests/wdt_ib700-test.c | 2 +- 18 files changed, 58 insertions(+), 46 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index 684cfb3507..e0d87d035a 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -483,6 +483,22 @@ QDict *qmp_raw(const char *msg); void qmp_async(const char *fmt, ...); /** + * qmp_cmd: + * @cmd: QMP command, with no arguments. + * + * Sends a QMP message to QEMU and returns the response. + */ +QDict *qmp_cmd(const char *cmd); + +/** + * qmp_cmd_async: + * @cmd: QMP command, with no arguments. + * + * Sends a QMP message to QEMU and leaves the response in the stream. + */ +void qmp_cmd_async(const char *cmd); + +/** * qmp_discard_response: * * Read and discard a QMP response, typically after qmp_async(). diff --git a/tests/libqtest.c b/tests/libqtest.c index 2df01682c0..3926a4d481 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -858,6 +858,17 @@ void qmp_async(const char *fmt, ...) va_end(ap); } +QDict *qmp_cmd(const char *cmd) +{ + qmp_cmd_async(cmd); + return qtest_qmp_receive(global_qtest); +} + +void qmp_cmd_async(const char *cmd) +{ + qtest_qmp_send(global_qtest, "{'execute':%s}", cmd); +} + void qmp_discard_response(void) { QDict *response =3D qtest_qmp_receive(global_qtest); @@ -890,7 +901,7 @@ void qtest_cb_for_every_machine(void (*cb)(const char *= machine)) const char *mname; qtest_start("-machine none"); - response =3D qmp("{ 'execute': 'query-machines' }"); + response =3D qmp_cmd("query-machines"); g_assert(response); list =3D qdict_get_qlist(response, "return"); g_assert(list); diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 9460843a9f..63d52edfca 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -1350,7 +1350,6 @@ static void test_flush_migrate(void) AHCIQState *src, *dst; AHCICommand *cmd; uint8_t px; - const char *s; char *uri =3D g_strdup_printf("unix:%s", mig_socket); prepare_blkdebug_script(debug_path, "flush_to_disk"); @@ -1386,8 +1385,7 @@ static void test_flush_migrate(void) ahci_migrate(src, dst, uri); /* Complete the command */ - s =3D "{'execute':'cont' }"; - qmp_async(s); + qmp_cmd_async("cont"); qmp_eventwait("RESUME"); ahci_command_wait(dst, cmd); ahci_command_verify(dst, cmd); diff --git a/tests/boot-order-test.c b/tests/boot-order-test.c index 4114720236..0be3333e6b 100644 --- a/tests/boot-order-test.c +++ b/tests/boot-order-test.c @@ -38,7 +38,7 @@ static void test_a_boot_order(const char *machine, qtest_start(args); actual =3D read_boot_order(); g_assert_cmphex(actual, =3D=3D, expected_boot); - qmp_async("{ 'execute': 'system_reset' }"); + qmp_cmd_async("system_reset"); /* * system_reset only requests reset. We get a RESET event after * the actual reset completes. Need to wait for that. diff --git a/tests/ide-test.c b/tests/ide-test.c index 757af7cd1d..56a02b1c7f 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -651,7 +651,7 @@ static void test_retry_flush(const char *machine) qmp_eventwait("STOP"); /* Complete the command */ - qmp_async("{'execute':'cont' }"); + qmp_cmd_async("cont"); qmp_discard_response(); /* Check registers */ diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c index 1ca7f456b5..06b9ce3a13 100644 --- a/tests/libqos/ahci.c +++ b/tests/libqos/ahci.c @@ -668,7 +668,7 @@ void ahci_exec(AHCIQState *ahci, uint8_t port, g_assert_cmpint(rc, =3D=3D, 0); } if (opts->error) { - qmp_async("{'execute':'cont' }"); + qmp_cmd_async("cont"); qmp_eventwait("RESUME"); } @@ -706,7 +706,7 @@ AHCICommand *ahci_guest_io_halt(AHCIQState *ahci, uint8= _t port, void ahci_guest_io_resume(AHCIQState *ahci, AHCICommand *cmd) { /* Complete the command */ - qmp_async("{'execute':'cont' }"); + qmp_cmd_async("cont"); qmp_eventwait("RESUME"); ahci_command_wait(ahci, cmd); ahci_command_verify(ahci, cmd); diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c index 6226546c28..246a04d6e6 100644 --- a/tests/libqos/libqos.c +++ b/tests/libqos/libqos.c @@ -84,18 +84,6 @@ void set_context(QOSState *s) global_qtest =3D s->qts; } -static QDict *qmp_execute(const char *command) -{ - char *fmt; - QDict *rsp; - - fmt =3D g_strdup_printf("{ 'execute': '%s' }", command); - rsp =3D qmp(fmt); - g_free(fmt); - - return rsp; -} - void migrate(QOSState *from, QOSState *to, const char *uri) { const char *st; @@ -106,7 +94,7 @@ void migrate(QOSState *from, QOSState *to, const char *u= ri) set_context(from); /* Is the machine currently running? */ - rsp =3D qmp_execute("query-status"); + rsp =3D qmp_cmd("query-status"); g_assert(qdict_haskey(rsp, "return")); sub =3D qdict_get_qdict(rsp, "return"); g_assert(qdict_haskey(sub, "running")); @@ -137,7 +125,7 @@ void migrate(QOSState *from, QOSState *to, const char *= uri) /* Otherwise, we need to wait: poll until migration is completed. */ while (1) { - rsp =3D qmp_execute("query-migrate"); + rsp =3D qmp_cmd("query-migrate"); g_assert(qdict_haskey(rsp, "return")); sub =3D qdict_get_qdict(rsp, "return"); g_assert(qdict_haskey(sub, "status")); diff --git a/tests/numa-test.c b/tests/numa-test.c index e1b6152244..d98500012f 100644 --- a/tests/numa-test.c +++ b/tests/numa-test.c @@ -74,7 +74,7 @@ static void test_mon_partial(const void *data) static QList *get_cpus(QDict **resp) { - *resp =3D qmp("{ 'execute': 'query-cpus' }"); + *resp =3D qmp_cmd("query-cpus"); g_assert(*resp); g_assert(qdict_haskey(*resp, "return")); return qdict_get_qlist(*resp, "return"); diff --git a/tests/postcopy-test.c b/tests/postcopy-test.c index 61f4b4180a..6f7f81eccd 100644 --- a/tests/postcopy-test.c +++ b/tests/postcopy-test.c @@ -252,7 +252,7 @@ static uint64_t get_migration_pass(void) QDict *rsp, *rsp_return, *rsp_ram; uint64_t result; - rsp =3D return_or_event(qmp("{ 'execute': 'query-migrate' }")); + rsp =3D return_or_event(qmp_cmd("query-migrate")); rsp_return =3D qdict_get_qdict(rsp, "return"); if (!qdict_haskey(rsp_return, "ram")) { /* Still in setup */ @@ -273,7 +273,7 @@ static void wait_for_migration_complete(void) do { const char *status; - rsp =3D return_or_event(qmp("{ 'execute': 'query-migrate' }")); + rsp =3D return_or_event(qmp_cmd("query-migrate")); rsp_return =3D qdict_get_qdict(rsp, "return"); status =3D qdict_get_str(rsp_return, "status"); completed =3D strcmp(status, "completed") =3D=3D 0; @@ -455,7 +455,7 @@ static void test_migrate(void) wait_for_migration_pass(); - rsp =3D return_or_event(qmp("{ 'execute': 'migrate-start-postcopy' }")= ); + rsp =3D return_or_event(qmp_cmd("migrate-start-postcopy")); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); @@ -482,7 +482,7 @@ static void test_migrate(void) usleep(10 * 1000); } while (dest_byte_a =3D=3D dest_byte_b); - qmp_async("{ 'execute' : 'stop'}"); + qmp_cmd_async("stop"); qmp_discard_response(); /* With it stopped, check nothing changes */ qtest_memread(to, start_address, &dest_byte_c, 1); diff --git a/tests/q35-test.c b/tests/q35-test.c index f98bed7a2d..122872b90d 100644 --- a/tests/q35-test.c +++ b/tests/q35-test.c @@ -105,7 +105,7 @@ static void test_smram_lock(void) g_assert(smram_test_bit(pcidev, MCH_HOST_BRIDGE_SMRAM_D_OPEN) =3D=3D f= alse); /* reset */ - response =3D qmp("{'execute': 'system_reset', 'arguments': {} }"); + response =3D qmp_cmd("system_reset"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); diff --git a/tests/qmp-test.c b/tests/qmp-test.c index 905fb4b3e5..082c5f7e8d 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -92,7 +92,7 @@ static void test_qmp_protocol(void) QDECREF(resp); /* Test valid command before handshake */ - resp =3D qmp("{ 'execute': 'query-version' }"); + resp =3D qmp_cmd("query-version"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "CommandNotFound"); QDECREF(resp); @@ -100,18 +100,18 @@ static void test_qmp_protocol(void) test_malformed(); /* Test handshake */ - resp =3D qmp("{ 'execute': 'qmp_capabilities' }"); + resp =3D qmp_cmd("qmp_capabilities"); ret =3D qdict_get_qdict(resp, "return"); g_assert(ret && !qdict_size(ret)); QDECREF(resp); /* Test repeated handshake */ - resp =3D qmp("{ 'execute': 'qmp_capabilities' }"); + resp =3D qmp_cmd("qmp_capabilities"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "CommandNotFound"); QDECREF(resp); /* Test valid command */ - resp =3D qmp("{ 'execute': 'query-version' }"); + resp =3D qmp_cmd("query-version"); test_version(qdict_get(resp, "return")); QDECREF(resp); diff --git a/tests/qom-test.c b/tests/qom-test.c index ab0595dc75..369972629a 100644 --- a/tests/qom-test.c +++ b/tests/qom-test.c @@ -98,7 +98,7 @@ static void test_machine(gconstpointer data) test_properties("/machine", true); - response =3D qmp("{ 'execute': 'quit' }"); + response =3D qmp_cmd("quit"); g_assert(qdict_haskey(response, "return")); QDECREF(response); diff --git a/tests/test-filter-mirror.c b/tests/test-filter-mirror.c index 79c5306fe7..0fb87c124d 100644 --- a/tests/test-filter-mirror.c +++ b/tests/test-filter-mirror.c @@ -57,7 +57,7 @@ static void test_mirror(void) }; /* send a qmp command to guarantee that 'connected' is setting to true= . */ - qmp_async("{ 'execute' : 'query-status'}"); + qmp_cmd_async("query-status"); qmp_discard_response(); ret =3D iov_send(send_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_b= uf)); g_assert_cmpint(ret, =3D=3D, sizeof(send_buf) + sizeof(size)); diff --git a/tests/test-filter-redirector.c b/tests/test-filter-redirector.c index a6a714abea..00f58f63b5 100644 --- a/tests/test-filter-redirector.c +++ b/tests/test-filter-redirector.c @@ -99,7 +99,7 @@ static void test_redirector_tx(void) g_assert_cmpint(recv_sock, !=3D, -1); /* send a qmp command to guarantee that 'connected' is setting to true= . */ - qmp_async("{ 'execute' : 'query-status'}"); + qmp_cmd_async("query-status"); qmp_discard_response(); struct iovec iov[] =3D { @@ -185,7 +185,7 @@ static void test_redirector_rx(void) send_sock =3D unix_connect(sock_path1, NULL); g_assert_cmpint(send_sock, !=3D, -1); /* send a qmp command to guarantee that 'connected' is setting to true= . */ - qmp_async("{ 'execute' : 'query-status'}"); + qmp_cmd_async("query-status"); qmp_discard_response(); ret =3D iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf)= ); diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c index 58a2dd9fe8..f29df9b9df 100644 --- a/tests/test-x86-cpuid-compat.c +++ b/tests/test-x86-cpuid-compat.c @@ -13,7 +13,7 @@ static char *get_cpu0_qom_path(void) QDict *cpu0; char *path; - resp =3D qmp("{'execute': 'query-cpus', 'arguments': {}}"); + resp =3D qmp_cmd("query-cpus"); g_assert(qdict_haskey(resp, "return")); ret =3D qdict_get_qlist(resp, "return"); diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c index 635b942c36..5d934d19c2 100644 --- a/tests/virtio-net-test.c +++ b/tests/virtio-net-test.c @@ -151,7 +151,6 @@ static void rx_stop_cont_test(QVirtioDevice *dev, char test[] =3D "TEST"; char buffer[64]; int len =3D htonl(sizeof(test)); - QDict *rsp; struct iovec iov[] =3D { { .iov_base =3D &len, @@ -168,8 +167,8 @@ static void rx_stop_cont_test(QVirtioDevice *dev, free_head =3D qvirtqueue_add(vq, req_addr, 64, true, false); qvirtqueue_kick(dev, vq, free_head); - rsp =3D qmp("{ 'execute' : 'stop'}"); - QDECREF(rsp); + qmp_cmd_async("stop"); + qmp_discard_response(); ret =3D iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test)); g_assert_cmpint(ret, =3D=3D, sizeof(test) + sizeof(len)); @@ -177,10 +176,10 @@ static void rx_stop_cont_test(QVirtioDevice *dev, /* We could check the status, but this command is more importantly to * ensure the packet data gets queued in QEMU, before we do 'cont'. */ - rsp =3D qmp("{ 'execute' : 'query-status'}"); - QDECREF(rsp); - rsp =3D qmp("{ 'execute' : 'cont'}"); - QDECREF(rsp); + qmp_cmd_async("query-status"); + qmp_discard_response(); + qmp_cmd_async("cont"); + qmp_discard_response(); qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US); memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test)); diff --git a/tests/vmgenid-test.c b/tests/vmgenid-test.c index 3d5c1c3615..0842833eba 100644 --- a/tests/vmgenid-test.c +++ b/tests/vmgenid-test.c @@ -118,7 +118,7 @@ static void read_guid_from_monitor(QemuUUID *guid) QDict *rsp, *rsp_ret; const char *guid_str; - rsp =3D qmp("{ 'execute': 'query-vm-generation-id' }"); + rsp =3D qmp_cmd("query-vm-generation-id"); if (qdict_haskey(rsp, "return")) { rsp_ret =3D qdict_get_qdict(rsp, "return"); g_assert(qdict_haskey(rsp_ret, "guid")); diff --git a/tests/wdt_ib700-test.c b/tests/wdt_ib700-test.c index 4fc8eeae86..a5fd795cc9 100644 --- a/tests/wdt_ib700-test.c +++ b/tests/wdt_ib700-test.c @@ -13,7 +13,7 @@ static void qmp_check_no_event(void) { - QDict *resp =3D qmp("{'execute':'query-status'}"); + QDict *resp =3D qmp_cmd("query-status"); g_assert(qdict_haskey(resp, "return")); QDECREF(resp); } --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501811437353944.7088639572812; Thu, 3 Aug 2017 18:50:37 -0700 (PDT) Received: from localhost ([::1]:44740 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRl4-00017Z-Mm for importer@patchew.org; Thu, 03 Aug 2017 21:50:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60577) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNq-0000Cr-2h for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNm-0004eu-Gf for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:34 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59570) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNe-0004Hu-Oq; Thu, 03 Aug 2017 21:26:23 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 90587883AB; Fri, 4 Aug 2017 01:26:21 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2D82E61F36; Fri, 4 Aug 2017 01:26:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 90587883AB Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:46 -0500 Message-Id: <20170804012551.2714-18-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 04 Aug 2017 01:26:21 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 17/22] libqtest: Add qmp_args() helper 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: "open list:IDE" , Amit Shah , armbru@redhat.com, Gerd Hoffmann , Stefan Hajnoczi , Paolo Bonzini , John Snow , =?UTF-8?q?Andreas=20F=C3=A4rber?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Similar to the previous helper, we can reduce the boilerplate of most callers by passing the command name separately from the interpolated arguments. Adjust the majority of the callers that can use the new helpers; in the process, fixing a few places where we would have failed -Wformat-nonliteral. The new helper function already uses GCC_FMT_ATTR to match the underlying use of qobject_from_jsonv(). Signed-off-by: Eric Blake --- tests/libqtest.h | 20 ++++++ tests/libqtest.c | 29 +++++++++ tests/ahci-test.c | 19 +++--- tests/device-introspect-test.c | 4 +- tests/drive_del-test.c | 10 +-- tests/fdc-test.c | 8 +-- tests/libqos/libqos.c | 7 +-- tests/libqos/pci-pc.c | 8 +-- tests/pc-cpu-test.c | 8 +-- tests/postcopy-test.c | 30 +++------ tests/qom-test.c | 9 +-- tests/test-netfilter.c | 139 ++++++++++++++++---------------------= ---- tests/test-x86-cpuid-compat.c | 6 +- tests/tmp105-test.c | 9 +-- tests/usb-hcd-uhci-test.c | 14 ++--- tests/usb-hcd-xhci-test.c | 25 ++------ tests/vhost-user-test.c | 12 +--- tests/virtio-blk-test.c | 12 +--- tests/virtio-scsi-test.c | 13 +--- tests/virtio-serial-test.c | 12 +--- 20 files changed, 167 insertions(+), 227 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index e0d87d035a..86ca7fa581 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -499,6 +499,26 @@ QDict *qmp_cmd(const char *cmd); void qmp_cmd_async(const char *cmd); /** + * qmp_args: + * @cmd: QMP command to send to QEMU. + * @fmt...: Arguments for the command; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). + * + * Sends a QMP message to QEMU and returns the response. + */ +QDict *qmp_args(const char *cmd, const char *fmt, ...) GCC_FMT_ATTR(2, 3); + +/** + * qmp_args_async: + * @cmd: QMP command to send to QEMU. + * @fmt...: Arguments for the command; formats arguments through + * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). + * + * Sends a QMP message to QEMU and leaves the response in the stream. + */ +void qmp_args_async(const char *cmd, const char *fmt, ...) GCC_FMT_ATTR(2,= 3); + +/** * qmp_discard_response: * * Read and discard a QMP response, typically after qmp_async(). diff --git a/tests/libqtest.c b/tests/libqtest.c index 3926a4d481..49786cf2d7 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -869,6 +869,35 @@ void qmp_cmd_async(const char *cmd) qtest_qmp_send(global_qtest, "{'execute':%s}", cmd); } +static void qmp_args_dict_async(const char *cmd, QDict *args) +{ + assert(args); + qtest_qmp_send(global_qtest, "{'execute':%s, 'arguments':%p}", cmd, ar= gs); +} + +QDict *qmp_args(const char *cmd, const char *fmt, ...) +{ + va_list ap; + QObject *obj; + + va_start(ap, fmt); + obj =3D qobject_from_jsonv(fmt, ap); + va_end(ap); + qmp_args_dict_async(cmd, qobject_to_qdict(obj)); + return qtest_qmp_receive(global_qtest); +} + +void qmp_args_async(const char *cmd, const char *fmt, ...) +{ + va_list ap; + QObject *obj; + + va_start(ap, fmt); + obj =3D qobject_from_jsonv(fmt, ap); + va_end(ap); + qmp_args_dict_async(cmd, qobject_to_qdict(obj)); +} + void qmp_discard_response(void) { QDict *response =3D qtest_qmp_receive(global_qtest); diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 63d52edfca..ee8a539cf6 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -1588,14 +1588,12 @@ static void test_atapi_tray(void) atapi_wait_tray(false); /* Remove media */ - qmp_async("{'execute': 'blockdev-open-tray', " - "'arguments': {'device': 'drive0'}}"); + qmp_args_async("blockdev-open-tray", "{'device': 'drive0'}"); atapi_wait_tray(true); rsp =3D qmp_receive(); QDECREF(rsp); - qmp_async("{'execute': 'x-blockdev-remove-medium', " - "'arguments': {'device': 'drive0'}}"); + qmp_args_async("x-blockdev-remove-medium", "{'device': 'drive0'}"); qmp_discard_response(); /* Test the tray without a medium */ @@ -1606,17 +1604,16 @@ static void test_atapi_tray(void) atapi_wait_tray(true); /* Re-insert media */ - qmp_async("{'execute': 'blockdev-add', 'arguments': {" - " 'node-name': 'node0', 'driver': 'raw', " - " 'file': { 'driver': 'file', 'filename': %s }}}", iso); + qmp_args_async("blockdev-add", "{'node-name': 'node0', " + "'driver': 'raw', " + "'file': { 'driver': 'file', 'filename': %s }}", iso); qmp_discard_response(); - qmp_async("{'execute': 'x-blockdev-insert-medium'," - "'arguments': { 'device': 'drive0', 'node-name': 'node0' }}"= ); + qmp_args_async("x-blockdev-insert-medium", + "{ 'device': 'drive0', 'node-name': 'node0' }"); qmp_discard_response(); /* Again, the event shows up first */ - qmp_async("{'execute': 'blockdev-close-tray', " - "'arguments': {'device': 'drive0'}}"); + qmp_args_async("blockdev-close-tray", "{'device': 'drive0'}"); atapi_wait_tray(false); rsp =3D qmp_receive(); QDECREF(rsp); diff --git a/tests/device-introspect-test.c b/tests/device-introspect-test.c index f7162c023f..e1fcd3b6c6 100644 --- a/tests/device-introspect-test.c +++ b/tests/device-introspect-test.c @@ -105,9 +105,7 @@ static void test_one_device(const char *type) QDict *resp; char *help, *qom_tree; - resp =3D qmp("{'execute': 'device-list-properties'," - " 'arguments': {'typename': %s}}", - type); + resp =3D qmp_args("device-list-properties", "{'typename': %s}", type); QDECREF(resp); help =3D hmp("device_add \"%s,help\"", type); diff --git a/tests/drive_del-test.c b/tests/drive_del-test.c index 834a634da3..442eb35c2b 100644 --- a/tests/drive_del-test.c +++ b/tests/drive_del-test.c @@ -34,8 +34,7 @@ static void device_del(void) QDict *response; /* Complication: ignore DEVICE_DELETED event */ - qmp_async("{'execute': 'device_del'," - " 'arguments': { 'id': 'dev0' } }"); + qmp_args_async("device_del", "{ 'id': 'dev0' }"); qmp_discard_response(); response =3D qmp_receive(); g_assert(response); @@ -69,11 +68,8 @@ static void test_after_failed_device_add(void) /* Make device_add fail. If this leaks the virtio-blk-pci device then= a * reference to drive0 will also be held (via qdev properties). */ - response =3D qmp("{'execute': 'device_add'," - " 'arguments': {" - " 'driver': 'virtio-blk-pci'," - " 'drive': 'drive0'" - "}}"); + response =3D qmp_args("device_add", + "{'driver': 'virtio-blk-pci', 'drive': 'drive0'}"); g_assert(response); error =3D qdict_get_qdict(response, "error"); g_assert_cmpstr(qdict_get_try_str(error, "class"), =3D=3D, "GenericErr= or"); diff --git a/tests/fdc-test.c b/tests/fdc-test.c index ab61a82873..9999e5f5c4 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -298,9 +298,9 @@ static void test_media_insert(void) /* Insert media in drive. DSKCHK should not be reset until a step pulse * is sent. */ - qmp_async("{'execute':'blockdev-change-medium', 'arguments':{" - " 'id':'floppy0', 'filename': %s, 'format': 'raw' }}", - test_image); + qmp_args_async("blockdev-change-medium", + "{'id':'floppy0', 'filename': %s, 'format': 'raw' }", + test_image); qmp_discard_response(); dir =3D inb(FLOPPY_BASE + reg_dir); @@ -330,7 +330,7 @@ static void test_media_change(void) /* Eject the floppy and check that DSKCHG is set. Reading it out doesn= 't * reset the bit. */ - qmp_async("{'execute':'eject', 'arguments':{ 'id':'floppy0' }}"); + qmp_args_async("eject", "{ 'id':'floppy0' }"); qmp_discard_response(); dir =3D inb(FLOPPY_BASE + reg_dir); diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c index 246a04d6e6..ba2707f89e 100644 --- a/tests/libqos/libqos.c +++ b/tests/libqos/libqos.c @@ -87,7 +87,6 @@ void set_context(QOSState *s) void migrate(QOSState *from, QOSState *to, const char *uri) { const char *st; - char *s; QDict *rsp, *sub; bool running; @@ -102,11 +101,7 @@ void migrate(QOSState *from, QOSState *to, const char = *uri) QDECREF(rsp); /* Issue the migrate command. */ - s =3D g_strdup_printf("{ 'execute': 'migrate'," - "'arguments': { 'uri': '%s' } }", - uri); - rsp =3D qmp(s); - g_free(s); + rsp =3D qmp_args("migrate", "{'uri': %s}", uri); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c index 02ce49927a..b4790650ab 100644 --- a/tests/libqos/pci-pc.c +++ b/tests/libqos/pci-pc.c @@ -159,14 +159,8 @@ void qpci_free_pc(QPCIBus *bus) void qpci_unplug_acpi_device_test(const char *id, uint8_t slot) { QDict *response; - char *cmd; - cmd =3D g_strdup_printf("{'execute': 'device_del'," - " 'arguments': {" - " 'id': '%s'" - "}}", id); - response =3D qmp(cmd); - g_free(cmd); + response =3D qmp_args("device_del", "{'id': %s}", id); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); diff --git a/tests/pc-cpu-test.c b/tests/pc-cpu-test.c index c4211a4e85..d4ea7ec612 100644 --- a/tests/pc-cpu-test.c +++ b/tests/pc-cpu-test.c @@ -37,8 +37,7 @@ static void test_pc_with_cpu_add(gconstpointer data) qtest_start(args); for (i =3D s->sockets * s->cores * s->threads; i < s->maxcpus; i++) { - response =3D qmp("{ 'execute': 'cpu-add'," - " 'arguments': { 'id': %d } }", i); + response =3D qmp_args("cpu-add", "{ 'id': %d }", i); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); @@ -60,9 +59,8 @@ static void test_pc_without_cpu_add(gconstpointer data) s->sockets, s->cores, s->threads, s->maxcpus); qtest_start(args); - response =3D qmp("{ 'execute': 'cpu-add'," - " 'arguments': { 'id': %d } }", - s->sockets * s->cores * s->threads); + response =3D qmp_args("cpu-add", "{ 'id': %d }", + s->sockets * s->cores * s->threads); g_assert(response); g_assert(qdict_haskey(response, "error")); QDECREF(response); diff --git a/tests/postcopy-test.c b/tests/postcopy-test.c index 6f7f81eccd..4e585006a8 100644 --- a/tests/postcopy-test.c +++ b/tests/postcopy-test.c @@ -358,7 +358,7 @@ static void test_migrate(void) char *uri =3D g_strdup_printf("unix:%s/migsocket", tmpfs); QTestState *global =3D global_qtest, *from, *to; unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d; - gchar *cmd, *cmd_src, *cmd_dst; + gchar *cmd_src, *cmd_dst; QDict *rsp; char *bootpath =3D g_strdup_printf("%s/bootsect", tmpfs); @@ -408,20 +408,16 @@ static void test_migrate(void) g_free(cmd_dst); global_qtest =3D from; - rsp =3D qmp("{ 'execute': 'migrate-set-capabilities'," - "'arguments': { " - "'capabilities': [ {" - "'capability': 'postcopy-ram'," - "'state': true } ] } }"); + rsp =3D qmp_args("migrate-set-capabilities", + "{'capabilities': [" + " {'capability': 'postcopy-ram', 'state': true } ] }"); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); global_qtest =3D to; - rsp =3D qmp("{ 'execute': 'migrate-set-capabilities'," - "'arguments': { " - "'capabilities': [ {" - "'capability': 'postcopy-ram'," - "'state': true } ] } }"); + rsp =3D qmp_args("migrate-set-capabilities", + "{'capabilities': [" + " {'capability': 'postcopy-ram', 'state': true } ] }"); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); @@ -430,14 +426,12 @@ static void test_migrate(void) * machine, so also set the downtime. */ global_qtest =3D from; - rsp =3D qmp("{ 'execute': 'migrate_set_speed'," - "'arguments': { 'value': 100000000 } }"); + rsp =3D qmp_args("migrate_set_speed", "{ 'value': 100000000 }"); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); /* 1ms downtime - it should never finish precopy */ - rsp =3D qmp("{ 'execute': 'migrate_set_downtime'," - "'arguments': { 'value': 0.001 } }"); + rsp =3D qmp_args("migrate_set_downtime", "{ 'value': 0.001 }"); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); @@ -445,11 +439,7 @@ static void test_migrate(void) /* Wait for the first serial output from the source */ wait_for_serial("src_serial"); - cmd =3D g_strdup_printf("{ 'execute': 'migrate'," - "'arguments': { 'uri': '%s' } }", - uri); - rsp =3D qmp(cmd); - g_free(cmd); + rsp =3D qmp_args("migrate", "{'uri':%s}", uri); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); diff --git a/tests/qom-test.c b/tests/qom-test.c index 369972629a..3c315cf864 100644 --- a/tests/qom-test.c +++ b/tests/qom-test.c @@ -51,8 +51,7 @@ static void test_properties(const char *path, bool recurs= e) QListEntry *entry; g_test_message("Obtaining properties of %s", path); - response =3D qmp("{ 'execute': 'qom-list'," - " 'arguments': { 'path': %s } }", path); + response =3D qmp_args("qom-list", "{ 'path': %s }", path); g_assert(response); if (!recurse) { @@ -75,10 +74,8 @@ static void test_properties(const char *path, bool recur= se) } else { const char *prop =3D qdict_get_str(tuple, "name"); g_test_message("Testing property %s.%s", path, prop); - tmp =3D qmp("{ 'execute': 'qom-get'," - " 'arguments': { 'path': %s," - " 'property': %s } }", - path, prop); + tmp =3D qmp_args("qom-get", "{ 'path': %s, 'property': %s }", + path, prop); /* qom-get may fail but should not, e.g., segfault. */ g_assert(tmp); QDECREF(tmp); diff --git a/tests/test-netfilter.c b/tests/test-netfilter.c index 8b5a9b21b5..736abc26ec 100644 --- a/tests/test-netfilter.c +++ b/tests/test-netfilter.c @@ -16,24 +16,20 @@ static void add_one_netfilter(void) { QDict *response; - response =3D qmp("{'execute': 'object-add'," - " 'arguments': {" - " 'qom-type': 'filter-buffer'," - " 'id': 'qtest-f0'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + response =3D qmp_args("object-add", + "{ 'qom-type': 'filter-buffer'," + " 'id': 'qtest-f0'," + " 'props': {" + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{'execute': 'object-del'," - " 'arguments': {" - " 'id': 'qtest-f0'" - "}}"); + response =3D qmp_args("object-del", "{'id': 'qtest-f0'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); @@ -44,34 +40,26 @@ static void remove_netdev_with_one_netfilter(void) { QDict *response; - response =3D qmp("{'execute': 'object-add'," - " 'arguments': {" - " 'qom-type': 'filter-buffer'," - " 'id': 'qtest-f0'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + response =3D qmp_args("object-add", + "{ 'qom-type': 'filter-buffer'," + " 'id': 'qtest-f0'," + " 'props': {" + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{'execute': 'netdev_del'," - " 'arguments': {" - " 'id': 'qtest-bn0'" - "}}"); + response =3D qmp_args("netdev_del", "{'id': 'qtest-bn0'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); /* add back the netdev */ - response =3D qmp("{'execute': 'netdev_add'," - " 'arguments': {" - " 'type': 'user'," - " 'id': 'qtest-bn0'" - "}}"); + response =3D qmp_args("netdev_add", "{'type': 'user', 'id': 'qtest-bn0= '}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); @@ -82,46 +70,38 @@ static void add_multi_netfilter(void) { QDict *response; - response =3D qmp("{'execute': 'object-add'," - " 'arguments': {" - " 'qom-type': 'filter-buffer'," - " 'id': 'qtest-f0'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + response =3D qmp_args("object-add", + "{ 'qom-type': 'filter-buffer'," + " 'id': 'qtest-f0'," + " 'props': {" + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{'execute': 'object-add'," - " 'arguments': {" - " 'qom-type': 'filter-buffer'," - " 'id': 'qtest-f1'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + response =3D qmp_args("object-add", + "{ 'qom-type': 'filter-buffer'," + " 'id': 'qtest-f1'," + " 'props': {" + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{'execute': 'object-del'," - " 'arguments': {" - " 'id': 'qtest-f0'" - "}}"); + response =3D qmp_args("object-del", "{'id': 'qtest-f0'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{'execute': 'object-del'," - " 'arguments': {" - " 'id': 'qtest-f1'" - "}}"); + response =3D qmp_args("object-del", "{'id': 'qtest-f1'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); @@ -132,48 +112,39 @@ static void remove_netdev_with_multi_netfilter(void) { QDict *response; - response =3D qmp("{'execute': 'object-add'," - " 'arguments': {" - " 'qom-type': 'filter-buffer'," - " 'id': 'qtest-f0'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + response =3D qmp_args("object-add", + "{ 'qom-type': 'filter-buffer'," + " 'id': 'qtest-f0'," + " 'props': {" + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{'execute': 'object-add'," - " 'arguments': {" - " 'qom-type': 'filter-buffer'," - " 'id': 'qtest-f1'," - " 'props': {" - " 'netdev': 'qtest-bn0'," - " 'queue': 'rx'," - " 'interval': 1000" - "}}}"); + response =3D qmp_args("object-add", + "{ 'qom-type': 'filter-buffer'," + " 'id': 'qtest-f1'," + " 'props': {" + " 'netdev': 'qtest-bn0'," + " 'queue': 'rx'," + " 'interval': 1000" + "}}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{'execute': 'netdev_del'," - " 'arguments': {" - " 'id': 'qtest-bn0'" - "}}"); + response =3D qmp_args("netdev_del", "{'id': 'qtest-bn0'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); /* add back the netdev */ - response =3D qmp("{'execute': 'netdev_add'," - " 'arguments': {" - " 'type': 'user'," - " 'id': 'qtest-bn0'" - "}}"); + response =3D qmp_args("netdev_add", "{'type': 'user', 'id': 'qtest-bn0= '}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c index f29df9b9df..536e1cae2c 100644 --- a/tests/test-x86-cpuid-compat.c +++ b/tests/test-x86-cpuid-compat.c @@ -25,10 +25,8 @@ static char *get_cpu0_qom_path(void) static QObject *qom_get(const char *path, const char *prop) { - QDict *resp =3D qmp("{ 'execute': 'qom-get'," - " 'arguments': { 'path': %s," - " 'property': %s } }", - path, prop); + QDict *resp =3D qmp_args("qom-get", "{ 'path': %s, 'property': %s }", + path, prop); QObject *ret =3D qdict_get(resp, "return"); qobject_incref(ret); QDECREF(resp); diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c index a7940a4639..28e6f300bc 100644 --- a/tests/tmp105-test.c +++ b/tests/tmp105-test.c @@ -69,8 +69,8 @@ static int qmp_tmp105_get_temperature(const char *id) QDict *response; int ret; - response =3D qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, " - "'property': 'temperature' } }", id); + response =3D qmp_args("qom-get", "{ 'path': %s, 'property': 'temperatu= re' }", + id); g_assert(qdict_haskey(response, "return")); ret =3D qdict_get_int(response, "return"); QDECREF(response); @@ -81,8 +81,9 @@ static void qmp_tmp105_set_temperature(const char *id, in= t value) { QDict *response; - response =3D qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, " - "'property': 'temperature', 'value': %d } }", id, value= ); + response =3D qmp_args("qom-set", + "{'path':%s, 'property':'temperature', 'value':%d}= ", + id, value); g_assert(qdict_haskey(response, "return")); QDECREF(response); } diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c index 0fb7f8d223..b45c0d7ac0 100644 --- a/tests/usb-hcd-uhci-test.c +++ b/tests/usb-hcd-uhci-test.c @@ -50,20 +50,14 @@ static void test_usb_storage_hotplug(void) { QDict *response; - response =3D qmp("{'execute': 'device_add'," - " 'arguments': {" - " 'driver': 'usb-storage'," - " 'drive': 'drive0'," - " 'id': 'usbdev0'" - "}}"); + response =3D qmp_args("device_add", + "{ 'driver': 'usb-storage', 'drive': 'drive0'," + " 'id': 'usbdev0'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{'execute': 'device_del'," - " 'arguments': {" - " 'id': 'usbdev0'" - "}}"); + response =3D qmp_args("device_del", "{'id': 'usbdev0'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); diff --git a/tests/usb-hcd-xhci-test.c b/tests/usb-hcd-xhci-test.c index c05a339894..408e819a61 100644 --- a/tests/usb-hcd-xhci-test.c +++ b/tests/usb-hcd-xhci-test.c @@ -25,21 +25,14 @@ static void test_usb_uas_hotplug(void) { QDict *response; - response =3D qmp("{'execute': 'device_add'," - " 'arguments': {" - " 'driver': 'usb-uas'," - " 'id': 'uas'" - "}}"); + response =3D qmp_args("device_add", "{'driver': 'usb-uas', 'id': 'uas'= }"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{'execute': 'device_add'," - " 'arguments': {" - " 'driver': 'scsi-hd'," - " 'drive': 'drive0'," - " 'id': 'scsi-hd'" - "}}"); + response =3D qmp_args("device_add", + "{'driver': 'scsi-hd', 'drive': 'drive0'," + " 'id': 'scsi-hd'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); @@ -49,20 +42,14 @@ static void test_usb_uas_hotplug(void) added disk is visible after BUS rescan */ - response =3D qmp("{'execute': 'device_del'," - " 'arguments': {" - " 'id': 'scsi-hd'" - "}}"); + response =3D qmp_args("device_del", "{'id': 'scsi-hd'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); qmp_eventwait("DEVICE_DELETED"); - response =3D qmp("{'execute': 'device_del'," - " 'arguments': {" - " 'id': 'uas'" - "}}"); + response =3D qmp_args("device_del", "{'id': 'uas'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c index d4da09f147..7c00f4b527 100644 --- a/tests/vhost-user-test.c +++ b/tests/vhost-user-test.c @@ -657,16 +657,11 @@ static void test_migrate(void) /* slow down migration to have time to fiddle with log */ /* TODO: qtest could learn to break on some places */ - rsp =3D qmp("{ 'execute': 'migrate_set_speed'," - "'arguments': { 'value': 10 } }"); + rsp =3D qmp_args("migrate_set_speed", "{ 'value': 10 }"); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); - cmd =3D g_strdup_printf("{ 'execute': 'migrate'," - "'arguments': { 'uri': '%s' } }", - uri); - rsp =3D qmp(cmd); - g_free(cmd); + rsp =3D qmp_args("migrate", "{'uri':%s}", uri); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); @@ -681,8 +676,7 @@ static void test_migrate(void) munmap(log, size); /* speed things up */ - rsp =3D qmp("{ 'execute': 'migrate_set_speed'," - "'arguments': { 'value': 0 } }"); + rsp =3D qmp_args("migrate_set_speed", "{ 'value': 0 }"); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index fe966c0606..649ba03c92 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -409,9 +409,7 @@ static void pci_config(void) qvirtio_set_driver_ok(&dev->vdev); - qmp_async("{ 'execute': 'block_resize', " - " 'arguments': { 'device': 'drive0', " - " 'size': %d } }", n_size); + qmp_args_async("block_resize", "{'device': 'drive0', 'size': %d}", n_s= ize); qmp_discard_response(); qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US); @@ -460,9 +458,7 @@ static void pci_msix(void) qvirtio_set_driver_ok(&dev->vdev); - qmp_async("{ 'execute': 'block_resize', " - " 'arguments': { 'device': 'drive0', " - " 'size': %d } }", n_size); + qmp_args_async("block_resize", "{'device': 'drive0', 'size': %d}", n_s= ize); qmp_discard_response(); qvirtio_wait_config_isr(&dev->vdev, QVIRTIO_BLK_TIMEOUT_US); @@ -702,9 +698,7 @@ static void mmio_basic(void) test_basic(&dev->vdev, alloc, vq); - qmp_async("{ 'execute': 'block_resize', " - " 'arguments': { 'device': 'drive0', " - " 'size': %d } }", n_size); + qmp_args_async("block_resize", "{'device': 'drive0', 'size': %d}", n_s= ize); qmp_discard_response(); qvirtio_wait_queue_isr(&dev->vdev, vq, QVIRTIO_BLK_TIMEOUT_US); diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c index 87a3b6e81a..126a6225f0 100644 --- a/tests/virtio-scsi-test.c +++ b/tests/virtio-scsi-test.c @@ -197,21 +197,14 @@ static void hotplug(void) qs =3D qvirtio_scsi_start( "-drive id=3Ddrv1,if=3Dnone,file=3Dnull-co://,format=3Draw"); - response =3D qmp("{\"execute\": \"device_add\"," - " \"arguments\": {" - " \"driver\": \"scsi-hd\"," - " \"id\": \"scsi-hd\"," - " \"drive\": \"drv1\"" - "}}"); + response =3D qmp_args("device_add", + "{'driver':'scsi-hd', 'id':'scsi-hd', 'drive':'drv= 1'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{\"execute\": \"device_del\"," - " \"arguments\": {" - " \"id\": \"scsi-hd\"" - "}}"); + response =3D qmp_args("device_del", "{'id':'scsi-hd'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); diff --git a/tests/virtio-serial-test.c b/tests/virtio-serial-test.c index b14d943ada..f47c343a2f 100644 --- a/tests/virtio-serial-test.c +++ b/tests/virtio-serial-test.c @@ -19,20 +19,14 @@ static void hotplug(void) { QDict *response; - response =3D qmp("{\"execute\": \"device_add\"," - " \"arguments\": {" - " \"driver\": \"virtserialport\"," - " \"id\": \"hp-port\"" - "}}"); + response =3D qmp_args("device_add", + "{'driver':'virtserialport', 'id':'hp-port'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); - response =3D qmp("{\"execute\": \"device_del\"," - " \"arguments\": {" - " \"id\": \"hp-port\"" - "}}"); + response =3D qmp_args("device_del", "{'id':'hp-port'}"); g_assert(response); g_assert(!qdict_haskey(response, "error")); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501811286658313.6442389954419; Thu, 3 Aug 2017 18:48:06 -0700 (PDT) Received: from localhost ([::1]:44498 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRie-0007gM-JZ for importer@patchew.org; Thu, 03 Aug 2017 21:48:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60351) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNi-00004w-Kk for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNf-0004Ky-IZ for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:26 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51428) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNf-0004Iq-C4 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:23 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 427EE81233 for ; Fri, 4 Aug 2017 01:26:22 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id B03FB627D7; Fri, 4 Aug 2017 01:26:21 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 427EE81233 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:47 -0500 Message-Id: <20170804012551.2714-19-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Fri, 04 Aug 2017 01:26:22 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 18/22] tests/libqos/usb: Clean up string interpolation into QMP input 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Markus Armbruster Leaving interpolation into JSON to qmp() is more robust than building QMP input manually, as explained in a previous commit. The case in usb_test_hotplug() is slightly more complicated: it interpolates *into* JSON values. Clean it up by building the values separately, so we can again leave interpolation to qmp(). Signed-off-by: Markus Armbruster Message-Id: <1500645206-13559-6-git-send-email-armbru@redhat.com> [use qmp_args(), fix commit message typo] Signed-off-by: Eric Blake --- tests/libqos/usb.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/tests/libqos/usb.c b/tests/libqos/usb.c index 0cdfaecda7..498e6e60e7 100644 --- a/tests/libqos/usb.c +++ b/tests/libqos/usb.c @@ -40,18 +40,17 @@ 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)) { + char id[32]; + char *bus; QDict *response; - char *cmd; - cmd =3D g_strdup_printf("{'execute': 'device_add'," - " 'arguments': {" - " 'driver': 'usb-tablet'," - " 'port': '%d'," - " 'bus': '%s.0'," - " 'id': 'usbdev%d'" - "}}", port, hcd_id, port); - response =3D qmp(cmd); - g_free(cmd); + sprintf(id, "usbdev%d", port); + bus =3D g_strdup_printf("%s.0", hcd_id); + response =3D qmp_args("device_add", + "{'driver': 'usb-tablet'," + " 'port': %s, 'bus': %s, 'id': %s}", + id + 6, bus, id); + g_free(bus); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); @@ -60,12 +59,7 @@ void usb_test_hotplug(const char *hcd_id, const int port, port_check(); } - cmd =3D g_strdup_printf("{'execute': 'device_del'," - " 'arguments': {" - " 'id': 'usbdev%d'" - "}}", port); - response =3D qmp(cmd); - g_free(cmd); + response =3D qmp_args("device_del", "{ 'id': %s }", id); g_assert(response); g_assert(qdict_haskey(response, "event")); g_assert(!strcmp(qdict_get_str(response, "event"), "DEVICE_DELETED")); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810574267215.1068897649228; Thu, 3 Aug 2017 18:36:14 -0700 (PDT) Received: from localhost ([::1]:43489 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRXA-0007IA-SA for importer@patchew.org; Thu, 03 Aug 2017 21:36:12 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60378) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNj-00005f-Df for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNi-0004Tk-B8 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:27 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46920) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNi-0004R5-4Q for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:26 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 27C57C047B6E for ; Fri, 4 Aug 2017 01:26:25 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7846961F36; Fri, 4 Aug 2017 01:26:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 27C57C047B6E Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:48 -0500 Message-Id: <20170804012551.2714-20-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 04 Aug 2017 01:26:25 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 19/22] libqtest: Add qmp_args_dict() helper 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Leaving interpolation into JSON to qobject_from_jsonf() is more robust than building QMP input manually; however, we have a few places where code is already creating a QDict to interpolate individual arguments, which cannot be reproduced with the qobject_from_jsonf() parser. Expose a public wrapper qmp_args_dict() for the internal helper qmp_args_dict_async() that we needed earlier for qmp_args(), and fix a test to use the new helper. Signed-off-by: Eric Blake --- tests/libqtest.h | 9 +++++++++ tests/libqtest.c | 6 ++++++ tests/device-introspect-test.c | 3 +-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index 86ca7fa581..193adf1eb9 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -499,6 +499,15 @@ QDict *qmp_cmd(const char *cmd); void qmp_cmd_async(const char *cmd); /** + * qmp_args_dict: + * @cmd: QMP command to send to QEMU. + * @args: Arguments for the command; will have reference count reduced. + * + * Sends a QMP message to QEMU and returns the response. + */ +QDict *qmp_args_dict(const char *cmd, QDict *args); + +/** * qmp_args: * @cmd: QMP command to send to QEMU. * @fmt...: Arguments for the command; formats arguments through diff --git a/tests/libqtest.c b/tests/libqtest.c index 49786cf2d7..5012ecf929 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -875,6 +875,12 @@ static void qmp_args_dict_async(const char *cmd, QDict= *args) qtest_qmp_send(global_qtest, "{'execute':%s, 'arguments':%p}", cmd, ar= gs); } +QDict *qmp_args_dict(const char *cmd, QDict *args) +{ + qmp_args_dict_async(cmd, args); + return qtest_qmp_receive(global_qtest); +} + QDict *qmp_args(const char *cmd, const char *fmt, ...) { va_list ap; diff --git a/tests/device-introspect-test.c b/tests/device-introspect-test.c index e1fcd3b6c6..d2de4a5fc0 100644 --- a/tests/device-introspect-test.c +++ b/tests/device-introspect-test.c @@ -36,8 +36,7 @@ static QList *qom_list_types(const char *implements, bool= abstract) if (implements) { qdict_put_str(args, "implements", implements); } - resp =3D qmp("{'execute': 'qom-list-types'," - " 'arguments': %p }", args); + resp =3D qmp_args_dict("qom-list-types", args); g_assert(qdict_haskey(resp, "return")); ret =3D qdict_get_qlist(resp, "return"); QINCREF(ret); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501811332960602.9015604841871; Thu, 3 Aug 2017 18:48:52 -0700 (PDT) Received: from localhost ([::1]:44542 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRjP-00089X-Cc for importer@patchew.org; Thu, 03 Aug 2017 21:48:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60528) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNo-0000Ab-1O for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNm-0004fX-QT for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45352) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNj-0004UV-7m; Thu, 03 Aug 2017 21:26:27 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2F1284E4F3; Fri, 4 Aug 2017 01:26:26 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6542561F57; Fri, 4 Aug 2017 01:26:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 2F1284E4F3 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:49 -0500 Message-Id: <20170804012551.2714-21-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 04 Aug 2017 01:26:26 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 20/22] tests/libqos/pci: Clean up string interpolation into QMP input 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: "open list:virtio-blk" , armbru@redhat.com, Stefan Hajnoczi Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Markus Armbruster Leaving interpolation into JSON to qmp() is more robust than building QMP input manually, as explained in previous commits. The case in qpci_plug_device_test() is a bit complicated: it interpolates several JSON object members, not just a value. Clean it up by passing them in as QDict rather than string, so we can leave interpolation to qmp() here and to qobject_from_jsonf() in callers. Signed-off-by: Markus Armbruster Message-Id: <1500645206-13559-7-git-send-email-armbru@redhat.com> [use qmp_args_dict for a slightly smaller diff, fix '%s' typo in ivshmem-te= st] Signed-off-by: Eric Blake --- tests/libqos/pci.h | 2 +- tests/ivshmem-test.c | 10 +++++----- tests/libqos/pci.c | 32 +++++++++++++++++--------------- tests/virtio-blk-test.c | 5 ++++- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h index ed480614ff..c981061703 100644 --- a/tests/libqos/pci.h +++ b/tests/libqos/pci.h @@ -109,6 +109,6 @@ void qpci_iounmap(QPCIDevice *dev, QPCIBar addr); 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); + uint8_t slot, QDict *extra_args); void qpci_unplug_acpi_device_test(const char *id, uint8_t slot); #endif diff --git a/tests/ivshmem-test.c b/tests/ivshmem-test.c index 37763425ee..4cb5a030da 100644 --- a/tests/ivshmem-test.c +++ b/tests/ivshmem-test.c @@ -14,6 +14,7 @@ #include "libqos/libqos-pc.h" #include "libqos/libqos-spapr.h" #include "libqtest.h" +#include "qapi/qmp/qjson.h" #include "qemu-common.h" #define TMPSHMSIZE (1 << 20) @@ -419,19 +420,18 @@ static void test_ivshmem_server_irq(void) static void test_ivshmem_hotplug(void) { const char *arch =3D qtest_get_arch(); - gchar *opts; + QObject *extra_args =3D qobject_from_jsonf("{ 'shm': %s, 'size': '1M' = }", + tmpshm); qtest_start(""); - opts =3D g_strdup_printf("'shm': '%s', 'size': '1M'", tmpshm); - - qpci_plug_device_test("ivshmem", "iv1", PCI_SLOT_HP, opts); + qpci_plug_device_test("ivshmem", "iv1", PCI_SLOT_HP, + qobject_to_qdict(extra_args)); if (strcmp(arch, "ppc64") !=3D 0) { qpci_unplug_acpi_device_test("iv1", PCI_SLOT_HP); } qtest_end(); - g_free(opts); } static void test_ivshmem_memdev(void) diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c index 2dcdeade2a..68623795b7 100644 --- a/tests/libqos/pci.c +++ b/tests/libqos/pci.c @@ -14,6 +14,7 @@ #include "libqos/pci.h" #include "hw/pci/pci_regs.h" +#include "qapi/qmp/qjson.h" #include "qemu/host-utils.h" void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id, @@ -392,22 +393,23 @@ QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t a= ddr) } void qpci_plug_device_test(const char *driver, const char *id, - uint8_t slot, const char *opts) + uint8_t slot, QDict *extra_args) { - QDict *response; - char *cmd; - - cmd =3D g_strdup_printf("{'execute': 'device_add'," - " 'arguments': {" - " 'driver': '%s'," - " 'addr': '%d'," - " %s%s" - " 'id': '%s'" - "}}", driver, slot, - opts ? opts : "", opts ? "," : "", - id); - response =3D qmp(cmd); - g_free(cmd); + char addr[8]; + QDict *args, *response; + + sprintf(addr, "%d", slot); + args =3D qobject_to_qdict( + qobject_from_jsonf("{ 'driver': %s, 'addr': %s, 'id': %s}", + driver, addr, id)); + + if (extra_args) { + qdict_join(args, extra_args, true); + QDECREF(extra_args); + } + + response =3D qmp_args_dict("device_add", args); + g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); diff --git a/tests/virtio-blk-test.c b/tests/virtio-blk-test.c index 649ba03c92..78a9ebfb0d 100644 --- a/tests/virtio-blk-test.c +++ b/tests/virtio-blk-test.c @@ -16,6 +16,7 @@ #include "libqos/virtio-pci.h" #include "libqos/virtio-mmio.h" #include "libqos/malloc-generic.h" +#include "qapi/qmp/qjson.h" #include "qemu/bswap.h" #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_config.h" @@ -656,12 +657,13 @@ static void pci_hotplug(void) QVirtioPCIDevice *dev; QOSState *qs; const char *arch =3D qtest_get_arch(); + QObject *extra_args =3D qobject_from_jsonf("{ 'drive': 'drive1' }"); qs =3D pci_test_start(); /* plug secondary disk */ qpci_plug_device_test("virtio-blk-pci", "drv1", PCI_SLOT_HP, - "'drive': 'drive1'"); + qobject_to_qdict(extra_args)); dev =3D virtio_blk_pci_init(qs->pcibus, PCI_SLOT_HP); g_assert(dev); @@ -672,6 +674,7 @@ static void pci_hotplug(void) if (strcmp(arch, "i386") =3D=3D 0 || strcmp(arch, "x86_64") =3D=3D 0) { qpci_unplug_acpi_device_test("drv1", PCI_SLOT_HP); } + qtest_shutdown(qs); } --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810563137559.4478024669141; Thu, 3 Aug 2017 18:36:03 -0700 (PDT) Received: from localhost ([::1]:43488 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRWz-00079f-Pv for importer@patchew.org; Thu, 03 Aug 2017 21:36:01 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60447) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNl-00007g-9Z for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNk-0004Yv-78 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:29 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54040) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNj-0004WO-Ur for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:28 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E6C0361474 for ; Fri, 4 Aug 2017 01:26:26 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5BA0761F36; Fri, 4 Aug 2017 01:26:26 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com E6C0361474 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:50 -0500 Message-Id: <20170804012551.2714-22-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 04 Aug 2017 01:26:27 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 21/22] libqtest: Drop now-unused qmp() 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: armbru@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" All callers have been converted to a form of qmp_cmd() or qmp_args() that takes the command name with less boilerplate. Therefore, we also know that all commands are using interpolation, and can remove an assertion. This also means that we have fixed the testsuite to comply with -Wformat checking on the strings being interpolated for qmp() (similar to what we previously did for strings used in hmp(), and matching the checking present on qobject_from_jsonf()). Signed-off-by: Eric Blake --- tests/libqtest.h | 20 +------------------- tests/libqtest.c | 32 ++++---------------------------- 2 files changed, 5 insertions(+), 47 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index 193adf1eb9..04b36a7b11 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -457,15 +457,6 @@ static inline void qtest_end(void) } /** - * qmp: - * @fmt...: QMP message to send to qemu; formats arguments through - * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). - * - * Sends a QMP message to QEMU and returns the response. - */ -QDict *qmp(const char *fmt, ...); - -/** * qmp_raw: * @msg: Raw QMP message to send to qemu. * @@ -474,15 +465,6 @@ QDict *qmp(const char *fmt, ...); QDict *qmp_raw(const char *msg); /** - * qmp_async: - * @fmt...: QMP message to send to qemu; formats arguments through - * json-lexer.c (only understands '%(PRI[ud]64|(l|ll)?[du]|[ipsf%])'). - * - * Sends a QMP message to QEMU and leaves the response in the stream. - */ -void qmp_async(const char *fmt, ...); - -/** * qmp_cmd: * @cmd: QMP command, with no arguments. * @@ -530,7 +512,7 @@ void qmp_args_async(const char *cmd, const char *fmt, .= ..) GCC_FMT_ATTR(2, 3); /** * qmp_discard_response: * - * Read and discard a QMP response, typically after qmp_async(). + * Read and discard a QMP response, typically after qmp_cmd_async(). */ void qmp_discard_response(void); diff --git a/tests/libqtest.c b/tests/libqtest.c index 5012ecf929..4597d4ac66 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -453,17 +453,12 @@ static void qtest_qmp_sendv(QTestState *s, const char= *fmt, va_list ap) QString *qstr; const char *str; - assert(strstr(fmt, "execute")); - /* - * A round trip through QObject is only needed if % interpolation - * is used. We interpolate through QObject rather than sprintf in - * order to escape strings properly. + * A round trip through QObject (and not sprintf) is needed + * because % interpolation is used, and we must escape strings + * properly. */ - if (!strchr(fmt, '%')) { - qmp_fd_send(s->qmp_fd, fmt); - return; - } + assert(strchr(fmt, '%')); qobj =3D qobject_from_jsonv(fmt, ap); qstr =3D qobject_to_json(qobj); @@ -833,31 +828,12 @@ void qtest_memset(QTestState *s, uint64_t addr, uint8= _t pattern, size_t size) qtest_rsp(s, 0); } -QDict *qmp(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - qtest_qmp_sendv(global_qtest, fmt, ap); - va_end(ap); - return qtest_qmp_receive(global_qtest); -} - QDict *qmp_raw(const char *msg) { qmp_fd_send(global_qtest->qmp_fd, msg); return qtest_qmp_receive(global_qtest); } -void qmp_async(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - qtest_qmp_sendv(global_qtest, fmt, ap); - va_end(ap); -} - QDict *qmp_cmd(const char *cmd) { qmp_cmd_async(cmd); --=20 2.13.3 From nobody Sat May 4 14:11:55 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1501810970060573.2726989114504; Thu, 3 Aug 2017 18:42:50 -0700 (PDT) Received: from localhost ([::1]:43898 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRdY-0003ro-Kc for importer@patchew.org; Thu, 03 Aug 2017 21:42:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60691) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ddRNw-0000H7-9e for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ddRNu-0004y1-B4 for qemu-devel@nongnu.org; Thu, 03 Aug 2017 21:26:40 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52178) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ddRNl-0004aB-Fe; Thu, 03 Aug 2017 21:26:29 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4F41078EA2; Fri, 4 Aug 2017 01:26:28 +0000 (UTC) Received: from red.redhat.com (ovpn-121-23.rdu2.redhat.com [10.10.121.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 31AB061F36; Fri, 4 Aug 2017 01:26:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 4F41078EA2 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eblake@redhat.com From: Eric Blake To: qemu-devel@nongnu.org Date: Thu, 3 Aug 2017 20:25:51 -0500 Message-Id: <20170804012551.2714-23-eblake@redhat.com> In-Reply-To: <20170804012551.2714-1-eblake@redhat.com> References: <20170804012551.2714-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Fri, 04 Aug 2017 01:26:28 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v4 22/22] libqtest: Rename qmp_cmd() to qmp() 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: Ben Warren , "open list:IDE" , Jason Wang , armbru@redhat.com, John Snow , =?UTF-8?q?Andreas=20F=C3=A4rber?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Now that the previous patch got rid of the old signature of qmp(), we can go back to using the shortest possible name for the common action. Performed mechanically with: for f in $(git grep -l qmp_cmd tests/); do case $f in *qemu-iotests*) continue;; esac sed -i s/qmp_cmd/qmp/ $f; done Signed-off-by: Eric Blake --- tests/libqtest.h | 10 +++++----- tests/libqtest.c | 8 ++++---- tests/ahci-test.c | 2 +- tests/boot-order-test.c | 2 +- tests/ide-test.c | 2 +- tests/libqos/ahci.c | 4 ++-- tests/libqos/libqos.c | 4 ++-- tests/numa-test.c | 2 +- tests/postcopy-test.c | 8 ++++---- tests/q35-test.c | 2 +- tests/qmp-test.c | 8 ++++---- tests/qom-test.c | 2 +- tests/test-filter-mirror.c | 2 +- tests/test-filter-redirector.c | 4 ++-- tests/test-x86-cpuid-compat.c | 2 +- tests/virtio-net-test.c | 6 +++--- tests/vmgenid-test.c | 2 +- tests/wdt_ib700-test.c | 2 +- 18 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tests/libqtest.h b/tests/libqtest.h index 04b36a7b11..874f0f9c35 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -465,20 +465,20 @@ static inline void qtest_end(void) QDict *qmp_raw(const char *msg); /** - * qmp_cmd: + * qmp: * @cmd: QMP command, with no arguments. * * Sends a QMP message to QEMU and returns the response. */ -QDict *qmp_cmd(const char *cmd); +QDict *qmp(const char *cmd); /** - * qmp_cmd_async: + * qmp_async: * @cmd: QMP command, with no arguments. * * Sends a QMP message to QEMU and leaves the response in the stream. */ -void qmp_cmd_async(const char *cmd); +void qmp_async(const char *cmd); /** * qmp_args_dict: @@ -512,7 +512,7 @@ void qmp_args_async(const char *cmd, const char *fmt, .= ..) GCC_FMT_ATTR(2, 3); /** * qmp_discard_response: * - * Read and discard a QMP response, typically after qmp_cmd_async(). + * Read and discard a QMP response, typically after qmp_async(). */ void qmp_discard_response(void); diff --git a/tests/libqtest.c b/tests/libqtest.c index 4597d4ac66..50e6c312a4 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -834,13 +834,13 @@ QDict *qmp_raw(const char *msg) return qtest_qmp_receive(global_qtest); } -QDict *qmp_cmd(const char *cmd) +QDict *qmp(const char *cmd) { - qmp_cmd_async(cmd); + qmp_async(cmd); return qtest_qmp_receive(global_qtest); } -void qmp_cmd_async(const char *cmd) +void qmp_async(const char *cmd) { qtest_qmp_send(global_qtest, "{'execute':%s}", cmd); } @@ -912,7 +912,7 @@ void qtest_cb_for_every_machine(void (*cb)(const char *= machine)) const char *mname; qtest_start("-machine none"); - response =3D qmp_cmd("query-machines"); + response =3D qmp("query-machines"); g_assert(response); list =3D qdict_get_qlist(response, "return"); g_assert(list); diff --git a/tests/ahci-test.c b/tests/ahci-test.c index ee8a539cf6..96a7249157 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -1385,7 +1385,7 @@ static void test_flush_migrate(void) ahci_migrate(src, dst, uri); /* Complete the command */ - qmp_cmd_async("cont"); + qmp_async("cont"); qmp_eventwait("RESUME"); ahci_command_wait(dst, cmd); ahci_command_verify(dst, cmd); diff --git a/tests/boot-order-test.c b/tests/boot-order-test.c index 0be3333e6b..cd883c05c7 100644 --- a/tests/boot-order-test.c +++ b/tests/boot-order-test.c @@ -38,7 +38,7 @@ static void test_a_boot_order(const char *machine, qtest_start(args); actual =3D read_boot_order(); g_assert_cmphex(actual, =3D=3D, expected_boot); - qmp_cmd_async("system_reset"); + qmp_async("system_reset"); /* * system_reset only requests reset. We get a RESET event after * the actual reset completes. Need to wait for that. diff --git a/tests/ide-test.c b/tests/ide-test.c index 56a02b1c7f..5819c2ed24 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -651,7 +651,7 @@ static void test_retry_flush(const char *machine) qmp_eventwait("STOP"); /* Complete the command */ - qmp_cmd_async("cont"); + qmp_async("cont"); qmp_discard_response(); /* Check registers */ diff --git a/tests/libqos/ahci.c b/tests/libqos/ahci.c index 06b9ce3a13..8bdf8ef246 100644 --- a/tests/libqos/ahci.c +++ b/tests/libqos/ahci.c @@ -668,7 +668,7 @@ void ahci_exec(AHCIQState *ahci, uint8_t port, g_assert_cmpint(rc, =3D=3D, 0); } if (opts->error) { - qmp_cmd_async("cont"); + qmp_async("cont"); qmp_eventwait("RESUME"); } @@ -706,7 +706,7 @@ AHCICommand *ahci_guest_io_halt(AHCIQState *ahci, uint8= _t port, void ahci_guest_io_resume(AHCIQState *ahci, AHCICommand *cmd) { /* Complete the command */ - qmp_cmd_async("cont"); + qmp_async("cont"); qmp_eventwait("RESUME"); ahci_command_wait(ahci, cmd); ahci_command_verify(ahci, cmd); diff --git a/tests/libqos/libqos.c b/tests/libqos/libqos.c index ba2707f89e..c215b81833 100644 --- a/tests/libqos/libqos.c +++ b/tests/libqos/libqos.c @@ -93,7 +93,7 @@ void migrate(QOSState *from, QOSState *to, const char *ur= i) set_context(from); /* Is the machine currently running? */ - rsp =3D qmp_cmd("query-status"); + rsp =3D qmp("query-status"); g_assert(qdict_haskey(rsp, "return")); sub =3D qdict_get_qdict(rsp, "return"); g_assert(qdict_haskey(sub, "running")); @@ -120,7 +120,7 @@ void migrate(QOSState *from, QOSState *to, const char *= uri) /* Otherwise, we need to wait: poll until migration is completed. */ while (1) { - rsp =3D qmp_cmd("query-migrate"); + rsp =3D qmp("query-migrate"); g_assert(qdict_haskey(rsp, "return")); sub =3D qdict_get_qdict(rsp, "return"); g_assert(qdict_haskey(sub, "status")); diff --git a/tests/numa-test.c b/tests/numa-test.c index d98500012f..237a9387d2 100644 --- a/tests/numa-test.c +++ b/tests/numa-test.c @@ -74,7 +74,7 @@ static void test_mon_partial(const void *data) static QList *get_cpus(QDict **resp) { - *resp =3D qmp_cmd("query-cpus"); + *resp =3D qmp("query-cpus"); g_assert(*resp); g_assert(qdict_haskey(*resp, "return")); return qdict_get_qlist(*resp, "return"); diff --git a/tests/postcopy-test.c b/tests/postcopy-test.c index 4e585006a8..98478f7f14 100644 --- a/tests/postcopy-test.c +++ b/tests/postcopy-test.c @@ -252,7 +252,7 @@ static uint64_t get_migration_pass(void) QDict *rsp, *rsp_return, *rsp_ram; uint64_t result; - rsp =3D return_or_event(qmp_cmd("query-migrate")); + rsp =3D return_or_event(qmp("query-migrate")); rsp_return =3D qdict_get_qdict(rsp, "return"); if (!qdict_haskey(rsp_return, "ram")) { /* Still in setup */ @@ -273,7 +273,7 @@ static void wait_for_migration_complete(void) do { const char *status; - rsp =3D return_or_event(qmp_cmd("query-migrate")); + rsp =3D return_or_event(qmp("query-migrate")); rsp_return =3D qdict_get_qdict(rsp, "return"); status =3D qdict_get_str(rsp_return, "status"); completed =3D strcmp(status, "completed") =3D=3D 0; @@ -445,7 +445,7 @@ static void test_migrate(void) wait_for_migration_pass(); - rsp =3D return_or_event(qmp_cmd("migrate-start-postcopy")); + rsp =3D return_or_event(qmp("migrate-start-postcopy")); g_assert(qdict_haskey(rsp, "return")); QDECREF(rsp); @@ -472,7 +472,7 @@ static void test_migrate(void) usleep(10 * 1000); } while (dest_byte_a =3D=3D dest_byte_b); - qmp_cmd_async("stop"); + qmp_async("stop"); qmp_discard_response(); /* With it stopped, check nothing changes */ qtest_memread(to, start_address, &dest_byte_c, 1); diff --git a/tests/q35-test.c b/tests/q35-test.c index 122872b90d..20de9b0937 100644 --- a/tests/q35-test.c +++ b/tests/q35-test.c @@ -105,7 +105,7 @@ static void test_smram_lock(void) g_assert(smram_test_bit(pcidev, MCH_HOST_BRIDGE_SMRAM_D_OPEN) =3D=3D f= alse); /* reset */ - response =3D qmp_cmd("system_reset"); + response =3D qmp("system_reset"); g_assert(response); g_assert(!qdict_haskey(response, "error")); QDECREF(response); diff --git a/tests/qmp-test.c b/tests/qmp-test.c index 082c5f7e8d..150df1bf2e 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -92,7 +92,7 @@ static void test_qmp_protocol(void) QDECREF(resp); /* Test valid command before handshake */ - resp =3D qmp_cmd("query-version"); + resp =3D qmp("query-version"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "CommandNotFound"); QDECREF(resp); @@ -100,18 +100,18 @@ static void test_qmp_protocol(void) test_malformed(); /* Test handshake */ - resp =3D qmp_cmd("qmp_capabilities"); + resp =3D qmp("qmp_capabilities"); ret =3D qdict_get_qdict(resp, "return"); g_assert(ret && !qdict_size(ret)); QDECREF(resp); /* Test repeated handshake */ - resp =3D qmp_cmd("qmp_capabilities"); + resp =3D qmp("qmp_capabilities"); g_assert_cmpstr(get_error_class(resp), =3D=3D, "CommandNotFound"); QDECREF(resp); /* Test valid command */ - resp =3D qmp_cmd("query-version"); + resp =3D qmp("query-version"); test_version(qdict_get(resp, "return")); QDECREF(resp); diff --git a/tests/qom-test.c b/tests/qom-test.c index 3c315cf864..2970f62bf5 100644 --- a/tests/qom-test.c +++ b/tests/qom-test.c @@ -95,7 +95,7 @@ static void test_machine(gconstpointer data) test_properties("/machine", true); - response =3D qmp_cmd("quit"); + response =3D qmp("quit"); g_assert(qdict_haskey(response, "return")); QDECREF(response); diff --git a/tests/test-filter-mirror.c b/tests/test-filter-mirror.c index 0fb87c124d..8980c288d4 100644 --- a/tests/test-filter-mirror.c +++ b/tests/test-filter-mirror.c @@ -57,7 +57,7 @@ static void test_mirror(void) }; /* send a qmp command to guarantee that 'connected' is setting to true= . */ - qmp_cmd_async("query-status"); + qmp_async("query-status"); qmp_discard_response(); ret =3D iov_send(send_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_b= uf)); g_assert_cmpint(ret, =3D=3D, sizeof(send_buf) + sizeof(size)); diff --git a/tests/test-filter-redirector.c b/tests/test-filter-redirector.c index 00f58f63b5..14ea136b4d 100644 --- a/tests/test-filter-redirector.c +++ b/tests/test-filter-redirector.c @@ -99,7 +99,7 @@ static void test_redirector_tx(void) g_assert_cmpint(recv_sock, !=3D, -1); /* send a qmp command to guarantee that 'connected' is setting to true= . */ - qmp_cmd_async("query-status"); + qmp_async("query-status"); qmp_discard_response(); struct iovec iov[] =3D { @@ -185,7 +185,7 @@ static void test_redirector_rx(void) send_sock =3D unix_connect(sock_path1, NULL); g_assert_cmpint(send_sock, !=3D, -1); /* send a qmp command to guarantee that 'connected' is setting to true= . */ - qmp_cmd_async("query-status"); + qmp_async("query-status"); qmp_discard_response(); ret =3D iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf)= ); diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c index 536e1cae2c..9a0b42475f 100644 --- a/tests/test-x86-cpuid-compat.c +++ b/tests/test-x86-cpuid-compat.c @@ -13,7 +13,7 @@ static char *get_cpu0_qom_path(void) QDict *cpu0; char *path; - resp =3D qmp_cmd("query-cpus"); + resp =3D qmp("query-cpus"); g_assert(qdict_haskey(resp, "return")); ret =3D qdict_get_qlist(resp, "return"); diff --git a/tests/virtio-net-test.c b/tests/virtio-net-test.c index 5d934d19c2..e204a9c561 100644 --- a/tests/virtio-net-test.c +++ b/tests/virtio-net-test.c @@ -167,7 +167,7 @@ static void rx_stop_cont_test(QVirtioDevice *dev, free_head =3D qvirtqueue_add(vq, req_addr, 64, true, false); qvirtqueue_kick(dev, vq, free_head); - qmp_cmd_async("stop"); + qmp_async("stop"); qmp_discard_response(); ret =3D iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test)); @@ -176,9 +176,9 @@ static void rx_stop_cont_test(QVirtioDevice *dev, /* We could check the status, but this command is more importantly to * ensure the packet data gets queued in QEMU, before we do 'cont'. */ - qmp_cmd_async("query-status"); + qmp_async("query-status"); qmp_discard_response(); - qmp_cmd_async("cont"); + qmp_async("cont"); qmp_discard_response(); qvirtio_wait_used_elem(dev, vq, free_head, QVIRTIO_NET_TIMEOUT_US); diff --git a/tests/vmgenid-test.c b/tests/vmgenid-test.c index 0842833eba..44385adb38 100644 --- a/tests/vmgenid-test.c +++ b/tests/vmgenid-test.c @@ -118,7 +118,7 @@ static void read_guid_from_monitor(QemuUUID *guid) QDict *rsp, *rsp_ret; const char *guid_str; - rsp =3D qmp_cmd("query-vm-generation-id"); + rsp =3D qmp("query-vm-generation-id"); if (qdict_haskey(rsp, "return")) { rsp_ret =3D qdict_get_qdict(rsp, "return"); g_assert(qdict_haskey(rsp_ret, "guid")); diff --git a/tests/wdt_ib700-test.c b/tests/wdt_ib700-test.c index a5fd795cc9..c22e4f8fc3 100644 --- a/tests/wdt_ib700-test.c +++ b/tests/wdt_ib700-test.c @@ -13,7 +13,7 @@ static void qmp_check_no_event(void) { - QDict *resp =3D qmp_cmd("query-status"); + QDict *resp =3D qmp("query-status"); g_assert(qdict_haskey(resp, "return")); QDECREF(resp); } --=20 2.13.3