aboutsummaryrefslogtreecommitdiff
path: root/tests/qmp-test.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-07-05 11:25:14 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-07-05 11:25:14 +0100
commit4fd1cbaf146d4ab35f465bba0fe23115c33cd5a7 (patch)
treed93d0fa4d40d7b5a76d22b9469da56012d4a18e3 /tests/qmp-test.c
parent5dafaf4fbceeb4c5d204039045b50b2f37443ff4 (diff)
parent153d73f320f422ecb5807ac3a93547b9f819599b (diff)
Merge remote-tracking branch 'remotes/armbru/tags/pull-monitor-2018-07-03-v2' into staging
Monitor patches for 2018-07-03 # gpg: Signature made Tue 03 Jul 2018 22:20:13 BST # gpg: using RSA key 3870B400EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-monitor-2018-07-03-v2: (32 commits) qapi: Polish command flags documentation in qapi-code-gen.txt monitor: Improve some comments qmp: Clean up capability negotiation after commit 02130314d8c qobject: Let qobject_from_jsonf() fail instead of abort qmp: Switch timestamp_put() to qdict_from_jsonf_nofail() qmp: Add some comments around null responses qmp: Simplify monitor_qmp_respond() qmp: Replace get_qmp_greeting() by qmp_greeting() qmp: Replace monitor_json_emitter{,raw}() by qmp_{queue,send}_response() qmp: Use QDict * instead of QObject * for response objects qmp: De-duplicate error response building qobject: New qdict_from_jsonf_nofail() monitor: Peel off @mon_global wrapper monitor: Rename use_io_thr to use_io_thread qmp: Don't let JSON errors jump the queue qmp: Don't let malformed in-band commands jump the queue tests/qmp-test: Demonstrate QMP errors jumping the queue qmp: Simplify code around monitor_qmp_dispatch_one() qmp: Always free QMPRequest with qmp_request_free() qmp: Revert change to handle_qmp_command tracepoint ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests/qmp-test.c')
-rw-r--r--tests/qmp-test.c107
1 files changed, 74 insertions, 33 deletions
diff --git a/tests/qmp-test.c b/tests/qmp-test.c
index a49cbc6fde..ceaf4a6789 100644
--- a/tests/qmp-test.c
+++ b/tests/qmp-test.c
@@ -135,16 +135,65 @@ static void test_qmp_protocol(void)
qtest_quit(qts);
}
-/* Tests for Out-Of-Band support. */
+/* Out-of-band tests */
+
+char tmpdir[] = "/tmp/qmp-test-XXXXXX";
+char *fifo_name;
+
+static void setup_blocking_cmd(void)
+{
+ if (!mkdtemp(tmpdir)) {
+ g_error("mkdtemp: %s", strerror(errno));
+ }
+ fifo_name = g_strdup_printf("%s/fifo", tmpdir);
+ if (mkfifo(fifo_name, 0666)) {
+ g_error("mkfifo: %s", strerror(errno));
+ }
+}
+
+static void cleanup_blocking_cmd(void)
+{
+ unlink(fifo_name);
+ rmdir(tmpdir);
+}
+
+static void send_cmd_that_blocks(QTestState *s, const char *id)
+{
+ qtest_async_qmp(s, "{ 'execute': 'blockdev-add', 'id': %s,"
+ " 'arguments': {"
+ " 'driver': 'blkdebug', 'node-name': %s,"
+ " 'config': %s,"
+ " 'image': { 'driver': 'null-co' } } }",
+ id, id, fifo_name);
+}
+
+static void unblock_blocked_cmd(void)
+{
+ int fd = open(fifo_name, O_WRONLY);
+ g_assert(fd >= 0);
+ close(fd);
+}
+
+static void send_oob_cmd_that_fails(QTestState *s, const char *id)
+{
+ qtest_async_qmp(s, "{ 'exec-oob': 'migrate-pause', 'id': %s }", id);
+}
+
+static void recv_cmd_id(QTestState *s, const char *id)
+{
+ QDict *resp = qtest_qmp_receive(s);
+
+ g_assert_cmpstr(qdict_get_try_str(resp, "id"), ==, id);
+ qobject_unref(resp);
+}
+
static void test_qmp_oob(void)
{
QTestState *qts;
QDict *resp, *q;
- int acks = 0;
const QListEntry *entry;
QList *capabilities;
QString *qstr;
- const char *cmd_id;
qts = qtest_init_without_qmp_handshake(true, common_args);
@@ -179,43 +228,33 @@ static void test_qmp_oob(void)
* Try any command that does not support OOB but with OOB flag. We
* should get failure.
*/
- resp = qtest_qmp(qts,
- "{ 'execute': 'query-cpus',"
- " 'control': { 'run-oob': true } }");
+ resp = qtest_qmp(qts, "{ 'exec-oob': 'query-cpus' }");
g_assert(qdict_haskey(resp, "error"));
qobject_unref(resp);
- /*
- * First send the "x-oob-test" command with lock=true and
- * oob=false, it should hang the dispatcher and main thread;
- * later, we send another lock=false with oob=true to continue
- * that thread processing. Finally we should receive replies from
- * both commands.
- */
- qtest_async_qmp(qts,
- "{ 'execute': 'x-oob-test',"
- " 'arguments': { 'lock': true }, "
- " 'id': 'lock-cmd'}");
- qtest_async_qmp(qts,
- "{ 'execute': 'x-oob-test', "
- " 'arguments': { 'lock': false }, "
- " 'control': { 'run-oob': true }, "
- " 'id': 'unlock-cmd' }");
-
- /* Ignore all events. Wait for 2 acks */
- while (acks < 2) {
- resp = qtest_qmp_receive(qts);
- cmd_id = qdict_get_str(resp, "id");
- if (!g_strcmp0(cmd_id, "lock-cmd") ||
- !g_strcmp0(cmd_id, "unlock-cmd")) {
- acks++;
- }
- qobject_unref(resp);
- }
+ /* OOB command overtakes slow in-band command */
+ setup_blocking_cmd();
+ send_cmd_that_blocks(qts, "ib-blocks-1");
+ qtest_async_qmp(qts, "{ 'execute': 'query-name', 'id': 'ib-quick-1' }");
+ send_oob_cmd_that_fails(qts, "oob-1");
+ recv_cmd_id(qts, "oob-1");
+ unblock_blocked_cmd();
+ recv_cmd_id(qts, "ib-blocks-1");
+ recv_cmd_id(qts, "ib-quick-1");
+
+ /* Even malformed in-band command fails in-band */
+ send_cmd_that_blocks(qts, "blocks-2");
+ qtest_async_qmp(qts, "{ 'id': 'err-2' }");
+ unblock_blocked_cmd();
+ recv_cmd_id(qts, "blocks-2");
+ recv_cmd_id(qts, "err-2");
+ cleanup_blocking_cmd();
qtest_quit(qts);
}
+/* Query smoke tests */
+
static int query_error_class(const char *cmd)
{
static struct {
@@ -392,6 +431,8 @@ static void add_query_tests(QmpSchema *schema)
}
}
+/* Preconfig tests */
+
static void test_qmp_preconfig(void)
{
QDict *rsp, *ret;