qmp-test: Cover syntax and lexical errors

qmp-test neglects to cover QMP input that isn't valid JSON.  libqtest
doesn't let us send such input.  Add qtest_qmp_send_raw() for this
purpose, and put it to use in qmp-test.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20180823164025.12553-7-armbru@redhat.com>
[Commit message typo fixed]
This commit is contained in:
Markus Armbruster 2018-08-23 18:39:33 +02:00
parent d93bb9d5c3
commit aed877c53b
3 changed files with 68 additions and 1 deletions

View File

@ -604,6 +604,23 @@ void qtest_qmp_send(QTestState *s, const char *fmt, ...)
va_end(ap);
}
void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...)
{
bool log = getenv("QTEST_LOG") != NULL;
va_list ap;
char *str;
va_start(ap, fmt);
str = g_strdup_vprintf(fmt, ap);
va_end(ap);
if (log) {
fprintf(stderr, "%s", str);
}
socket_send(s->qmp_fd, str, strlen(str));
g_free(str);
}
QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event)
{
QDict *response;

View File

@ -96,6 +96,17 @@ QDict *qtest_qmp(QTestState *s, const char *fmt, ...)
void qtest_qmp_send(QTestState *s, const char *fmt, ...)
GCC_FMT_ATTR(2, 3);
/**
* qtest_qmp_send_raw:
* @s: #QTestState instance to operate on.
* @fmt...: text to send, formatted like sprintf()
*
* Sends text to the QMP monitor verbatim. Need not be valid JSON;
* this is useful for negative tests.
*/
void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...)
GCC_FMT_ATTR(2, 3);
/**
* qtest_qmpv:
* @s: #QTestState instance to operate on.

View File

@ -1,7 +1,7 @@
/*
* QMP protocol test cases
*
* Copyright (c) 2017 Red Hat Inc.
* Copyright (c) 2017-2018 Red Hat Inc.
*
* Authors:
* Markus Armbruster <armbru@redhat.com>
@ -42,10 +42,49 @@ static void test_version(QObject *version)
visit_free(v);
}
static bool recovered(QTestState *qts)
{
QDict *resp;
bool ret;
resp = qtest_qmp(qts, "{ 'execute': 'no-such-cmd' }");
ret = !strcmp(get_error_class(resp), "CommandNotFound");
qobject_unref(resp);
return ret;
}
static void test_malformed(QTestState *qts)
{
QDict *resp;
/* syntax error */
qtest_qmp_send_raw(qts, "{]\n");
resp = qtest_qmp_receive(qts);
g_assert_cmpstr(get_error_class(resp), ==, "GenericError");
qobject_unref(resp);
g_assert(recovered(qts));
/* lexical error: impossible byte outside string */
qtest_qmp_send_raw(qts, "{\xFF");
resp = qtest_qmp_receive(qts);
g_assert_cmpstr(get_error_class(resp), ==, "GenericError");
qobject_unref(resp);
g_assert(recovered(qts));
/* lexical error: impossible byte in string */
qtest_qmp_send_raw(qts, "{'bad \xFF");
resp = qtest_qmp_receive(qts);
g_assert_cmpstr(get_error_class(resp), ==, "GenericError");
qobject_unref(resp);
g_assert(recovered(qts));
/* lexical error: interpolation */
qtest_qmp_send_raw(qts, "%%p\n");
resp = qtest_qmp_receive(qts);
g_assert_cmpstr(get_error_class(resp), ==, "GenericError");
qobject_unref(resp);
g_assert(recovered(qts));
/* Not even a dictionary */
resp = qtest_qmp(qts, "null");
g_assert_cmpstr(get_error_class(resp), ==, "GenericError");