libqtest: Work around a "QMP wants a newline" bug

The next commit is going to add a test that calls qmp("null").
Curiously, this hangs.  Here's why.

qmp_fd_sendv() doesn't send newlines.  Not even when @fmt contains
some.  At first glance, the QMP parser seems to be fine with that.
However, it turns out that it fails to react to input until it sees
either a newline, an object or an array.  To reproduce, feed to a QMP
monitor like this:

    $ echo -n 'null' | socat UNIX:/work/armbru/images/test-qmp STDIO
    {"QMP": {"version": {"qemu": {"micro": 50, "minor": 8, "major": 2}, "package": " (v2.8.0-1195-gf84141e-dirty)"}, "capabilities": []}}

No output after the greeting.

Add a newline:

    $ echo 'null' | socat UNIX:/work/armbru/images/test-qmp STDIO
    {"QMP": {"version": {"qemu": {"micro": 50, "minor": 8, "major": 2}, "package": " (v2.8.0-1195-gf84141e-dirty)"}, "capabilities": []}}
    {"error": {"class": "GenericError", "desc": "Expected 'object' in QMP input"}}

Correct output for input 'null'.

Add an object instead:

    $ echo -n 'null { "execute": "qmp_capabilities" }' | socat UNIX:qmp-socket STDIO
    {"QMP": {"version": {"qemu": {"micro": 50, "minor": 8, "major": 2}, "package": " (v2.8.0-1195-gf84141e-dirty)"}, "capabilities": []}}
    {"error": {"class": "GenericError", "desc": "Expected 'object' in QMP input"}}
    {"return": {}}

Also correct output.

Work around this QMP bug by having qmp_fd_sendv() append a newline.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1488544368-30622-3-git-send-email-armbru@redhat.com>
This commit is contained in:
Markus Armbruster 2017-03-03 13:32:22 +01:00
parent 74d8c9d99d
commit 13420ef837

View File

@ -442,14 +442,20 @@ void qmp_fd_sendv(int fd, const char *fmt, va_list ap)
if (qobj) {
int log = getenv("QTEST_LOG") != NULL;
QString *qstr = qobject_to_json(qobj);
const char *str = qstring_get_str(qstr);
size_t size = qstring_get_length(qstr);
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 = qstring_get_str(qstr);
if (log) {
fprintf(stderr, "%s", str);
}
/* Send QMP request */
socket_send(fd, str, size);
socket_send(fd, str, qstring_get_length(qstr));
QDECREF(qstr);
qobject_decref(qobj);