From: Markus Armbruster <armbru@redhat.com>
To: Eric Blake <eblake@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v4 12/22] libqtest: Change qmp_fd_send() to drop varargs
Date: Wed, 09 Aug 2017 15:18:22 +0200 [thread overview]
Message-ID: <87mv78riap.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <20170804012551.2714-13-eblake@redhat.com> (Eric Blake's message of "Thu, 3 Aug 2017 20:25:41 -0500")
Eric Blake <eblake@redhat.com> writes:
> 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'.
I'm fine with the reversal of roles. The name qmp_fd_send() becomes
slightly problematic, though: it's *not* the ... variant of
qmp_fd_sendv(), as is the case for similar pairs of function names.
I wish libqtest's naming would follow libc conventions more closely.
libc: printf() and vprintf(), sprintf() and vsprintf(). libqtest:
qmp_fd_send() and qmp_sendv(), qtest_hmp() and qtest_hmpv(), ...
Exceptions (sort of): socket_send() and socket_sendf(), qtest_sendf().
Not sure this is worth cleaning up now.
If we decice it is, then the name qmp_fd_send() would be fine, because
its va_list buddy would be qmp_fd_vsendf(), and its ... buddy would be
qmp_fd_sendf().
> Add documentation while in the area.
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
> 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.
> */
"Internal code that ..." is awkward. It's static, so of course it's
internal, and of course it's code :)
"Convert from X into Y" sounds odd to my (non-native!) ears. "Convert
from X to Y" and "convert X into Y" don't.
"Without waiting for a reply" is kind of implied by "send", isn't it?
What about
/*
* Send a QMP message with %-interpolation like qobject_from_jsonv().
*/
Add parameter description to taste. Uglify to conform to GLib
documentation style if you want.
> -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 = NULL;
> - int log = getenv("QTEST_LOG") != 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 == '\377') {
> - socket_send(fd, fmt, 1);
> - assert(!fmt[1]);
> - return;
> - }
> assert(*fmt);
Is this assertion (still) useful? Why can't we leave the job to
qobject_from_jsonv()?
>
> /*
> @@ -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 = qobject_from_jsonv(fmt, ap);
> - qstr = qobject_to_json(qobj);
> - } else {
> - qstr = 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 = qobject_from_jsonv(fmt, ap);
> + qstr = qobject_to_json(qobj);
> str = 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 = getenv("QTEST_LOG") != NULL;
>
> - va_start(ap, fmt);
> - response = 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);
Hmm.
Before this series, qmp_fd_sendv() first parses @fmt with
%-interpolation from @ap, then converts the result back to JSON text.
Any newlines are lost, so we have to append one.
PATCH 10 adds a shortcut when @fmt doesn't contain '%'. Newlines are
not lost in that case. We add one anyway. Ugh.
This patch drops the non-shortcut case.
I think qmp_fd_send() should send exactly @msg, and the newline
appending should move to qmp_fd_sendv(), where the newline loss now
happens.
> }
>
> 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 TestFixture *fixture,
> QString *qstr = qobject_to_json(obj);
> const char *str;
>
> - qstring_append_chr(qstr, '\n');
Was appending a newline necessary before this patch?
It will be if you change qmp_fd_send() as I proposed.
> str = qstring_get_str(qstr);
> - assert(!strchr(str, '%'));
> qmp_fd_send(fixture->fd, str);
> QDECREF(qstr);
> qobject_decref(obj);
next prev parent reply other threads:[~2017-08-09 13:18 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-04 1:25 [Qemu-devel] [PATCH v4 00/22] Clean up around qmp() and hmp() Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 01/22] qobject: Accept "%"PRId64 in qobject_from_jsonf() Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 02/22] tests: Clean up wait for event Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 03/22] tests/libqtest: Clean up how we read the QMP greeting Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 04/22] tests: Add assertion for no qmp("") Eric Blake
2017-08-09 7:13 ` Markus Armbruster
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 05/22] qobject: Simplify qobject_from_jsonv() Eric Blake
2017-08-09 7:59 ` Markus Armbruster
2017-08-09 13:14 ` Eric Blake
2017-10-02 5:46 ` Markus Armbruster
2017-10-02 14:30 ` Eric Blake
2018-01-08 16:46 ` Eric Blake
2017-09-11 21:52 ` Eric Blake
2017-10-02 7:15 ` Markus Armbruster
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 06/22] qobject: Perform %% interpolation in qobject_from_jsonf() Eric Blake
2017-08-09 9:06 ` Markus Armbruster
2017-08-09 13:21 ` Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 07/22] numa-test: Use hmp() Eric Blake
2017-08-09 9:07 ` Markus Armbruster
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 08/22] qtest: Avoid passing raw strings through hmp() Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 09/22] qtest: Document calling conventions Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 10/22] libqtest: Skip round-trip through QObject Eric Blake
2017-08-09 10:10 ` Markus Armbruster
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 11/22] test-qga: Simplify command construction Eric Blake
2017-08-09 11:40 ` Markus Armbruster
2017-08-09 13:29 ` Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 12/22] libqtest: Change qmp_fd_send() to drop varargs Eric Blake
2017-08-09 13:18 ` Markus Armbruster [this message]
2017-08-09 13:44 ` Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 13/22] libqtest: Add qmp_raw() Eric Blake
2017-08-09 14:54 ` Markus Armbruster
2017-08-09 15:18 ` Eric Blake
2017-08-10 7:29 ` Markus Armbruster
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 14/22] libqtest: Separate qmp_discard_response() from command Eric Blake
2017-08-09 15:15 ` Markus Armbruster
2017-08-09 15:32 ` Eric Blake
2017-08-10 7:40 ` Markus Armbruster
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 15/22] libqtest: Delete qtest_qmp() wrappers Eric Blake
2017-08-09 15:34 ` Markus Armbruster
2017-08-09 16:35 ` Eric Blake
2017-08-10 7:47 ` Markus Armbruster
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 16/22] libqtest: Add qmp_cmd() helper Eric Blake
2017-08-09 15:40 ` Markus Armbruster
2017-08-09 16:39 ` Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 17/22] libqtest: Add qmp_args() helper Eric Blake
2017-08-09 15:57 ` Markus Armbruster
2017-08-09 21:57 ` Eric Blake
2017-08-10 8:17 ` Markus Armbruster
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 18/22] tests/libqos/usb: Clean up string interpolation into QMP input Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 19/22] libqtest: Add qmp_args_dict() helper Eric Blake
2017-08-09 15:59 ` Markus Armbruster
2017-08-09 16:41 ` Eric Blake
2017-08-10 8:19 ` Markus Armbruster
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 20/22] tests/libqos/pci: Clean up string interpolation into QMP input Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 21/22] libqtest: Drop now-unused qmp() Eric Blake
2017-08-09 16:01 ` Markus Armbruster
2017-08-09 16:43 ` Eric Blake
2017-08-04 1:25 ` [Qemu-devel] [PATCH v4 22/22] libqtest: Rename qmp_cmd() to qmp() Eric Blake
2017-08-04 1:54 ` [Qemu-devel] [PATCH v4 00/22] Clean up around qmp() and hmp() no-reply
2017-08-04 11:50 ` Eric Blake
2017-08-04 12:10 ` Fam Zheng
2017-08-07 6:43 ` Fam Zheng
2017-08-07 7:33 ` Fam Zheng
2017-08-07 14:08 ` Philippe Mathieu-Daudé
2017-08-07 8:09 ` Fam Zheng
2017-08-04 2:02 ` no-reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87mv78riap.fsf@dusky.pond.sub.org \
--to=armbru@redhat.com \
--cc=eblake@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.