xref: /qemu/tests/qtest/qmp-test.c (revision 8258292e18c39480b64eba9f3551ab772ce29b5d)
1f66e7ac8SMarkus Armbruster /*
2f66e7ac8SMarkus Armbruster  * QMP protocol test cases
3f66e7ac8SMarkus Armbruster  *
4aed877c5SMarkus Armbruster  * Copyright (c) 2017-2018 Red Hat Inc.
5f66e7ac8SMarkus Armbruster  *
6f66e7ac8SMarkus Armbruster  * Authors:
7d93bb9d5SMarkus Armbruster  *  Markus Armbruster <armbru@redhat.com>
8f66e7ac8SMarkus Armbruster  *
9f66e7ac8SMarkus Armbruster  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10f66e7ac8SMarkus Armbruster  * See the COPYING file in the top-level directory.
11f66e7ac8SMarkus Armbruster  */
12f66e7ac8SMarkus Armbruster 
13f66e7ac8SMarkus Armbruster #include "qemu/osdep.h"
14f66e7ac8SMarkus Armbruster #include "libqtest.h"
15f66e7ac8SMarkus Armbruster #include "qapi/error.h"
16112ed241SMarkus Armbruster #include "qapi/qapi-visit-misc.h"
17452fcdbcSMarkus Armbruster #include "qapi/qmp/qdict.h"
1847e6b297SMarkus Armbruster #include "qapi/qmp/qlist.h"
19f66e7ac8SMarkus Armbruster #include "qapi/qobject-input-visitor.h"
2002130314SPeter Xu #include "qapi/qmp/qstring.h"
21f66e7ac8SMarkus Armbruster 
22f66e7ac8SMarkus Armbruster const char common_args[] = "-nodefaults -machine none";
23f66e7ac8SMarkus Armbruster 
24f66e7ac8SMarkus Armbruster static void test_version(QObject *version)
25f66e7ac8SMarkus Armbruster {
26f66e7ac8SMarkus Armbruster     Visitor *v;
27f66e7ac8SMarkus Armbruster     VersionInfo *vinfo;
28f66e7ac8SMarkus Armbruster 
29f66e7ac8SMarkus Armbruster     g_assert(version);
30048abb7bSMarkus Armbruster     v = qobject_input_visitor_new(version);
31f66e7ac8SMarkus Armbruster     visit_type_VersionInfo(v, "version", &vinfo, &error_abort);
32f66e7ac8SMarkus Armbruster     qapi_free_VersionInfo(vinfo);
33f66e7ac8SMarkus Armbruster     visit_free(v);
34f66e7ac8SMarkus Armbruster }
35f66e7ac8SMarkus Armbruster 
36ebb4d82dSMarc-André Lureau static void assert_recovered(QTestState *qts)
37aed877c5SMarkus Armbruster {
38aed877c5SMarkus Armbruster     QDict *resp;
39aed877c5SMarkus Armbruster 
40aed877c5SMarkus Armbruster     resp = qtest_qmp(qts, "{ 'execute': 'no-such-cmd' }");
41ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "CommandNotFound");
42aed877c5SMarkus Armbruster }
43aed877c5SMarkus Armbruster 
446a5c88f5SEric Blake static void test_malformed(QTestState *qts)
45f66e7ac8SMarkus Armbruster {
46f66e7ac8SMarkus Armbruster     QDict *resp;
47f66e7ac8SMarkus Armbruster 
48aed877c5SMarkus Armbruster     /* syntax error */
49aed877c5SMarkus Armbruster     qtest_qmp_send_raw(qts, "{]\n");
50aed877c5SMarkus Armbruster     resp = qtest_qmp_receive(qts);
51ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
52ebb4d82dSMarc-André Lureau     assert_recovered(qts);
53aed877c5SMarkus Armbruster 
54aed877c5SMarkus Armbruster     /* lexical error: impossible byte outside string */
55aed877c5SMarkus Armbruster     qtest_qmp_send_raw(qts, "{\xFF");
56aed877c5SMarkus Armbruster     resp = qtest_qmp_receive(qts);
57ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
58ebb4d82dSMarc-André Lureau     assert_recovered(qts);
59aed877c5SMarkus Armbruster 
606bc93a34SMarkus Armbruster     /* lexical error: funny control character outside string */
616bc93a34SMarkus Armbruster     qtest_qmp_send_raw(qts, "{\x01");
626bc93a34SMarkus Armbruster     resp = qtest_qmp_receive(qts);
63ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
64ebb4d82dSMarc-André Lureau     assert_recovered(qts);
656bc93a34SMarkus Armbruster 
66aed877c5SMarkus Armbruster     /* lexical error: impossible byte in string */
67aed877c5SMarkus Armbruster     qtest_qmp_send_raw(qts, "{'bad \xFF");
68aed877c5SMarkus Armbruster     resp = qtest_qmp_receive(qts);
69ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
70ebb4d82dSMarc-André Lureau     assert_recovered(qts);
71aed877c5SMarkus Armbruster 
726bc93a34SMarkus Armbruster     /* lexical error: control character in string */
73340db1edSMarkus Armbruster     qtest_qmp_send_raw(qts, "{'execute': 'nonexistent', 'id':'\n");
746bc93a34SMarkus Armbruster     resp = qtest_qmp_receive(qts);
75ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
76ebb4d82dSMarc-André Lureau     assert_recovered(qts);
776bc93a34SMarkus Armbruster 
78aed877c5SMarkus Armbruster     /* lexical error: interpolation */
790f07a5d5SMarkus Armbruster     qtest_qmp_send_raw(qts, "%%p");
80aed877c5SMarkus Armbruster     resp = qtest_qmp_receive(qts);
81ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
82ebb4d82dSMarc-André Lureau     assert_recovered(qts);
83aed877c5SMarkus Armbruster 
84f66e7ac8SMarkus Armbruster     /* Not even a dictionary */
856a5c88f5SEric Blake     resp = qtest_qmp(qts, "null");
86ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
87f66e7ac8SMarkus Armbruster 
88f66e7ac8SMarkus Armbruster     /* No "execute" key */
896a5c88f5SEric Blake     resp = qtest_qmp(qts, "{}");
90ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
91f66e7ac8SMarkus Armbruster 
92f66e7ac8SMarkus Armbruster     /* "execute" isn't a string */
936a5c88f5SEric Blake     resp = qtest_qmp(qts, "{ 'execute': true }");
94ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
95f66e7ac8SMarkus Armbruster 
96f66e7ac8SMarkus Armbruster     /* "arguments" isn't a dictionary */
976a5c88f5SEric Blake     resp = qtest_qmp(qts, "{ 'execute': 'no-such-cmd', 'arguments': [] }");
98ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
99f66e7ac8SMarkus Armbruster 
100f66e7ac8SMarkus Armbruster     /* extra key */
1016a5c88f5SEric Blake     resp = qtest_qmp(qts, "{ 'execute': 'no-such-cmd', 'extra': true }");
102ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
103f66e7ac8SMarkus Armbruster }
104f66e7ac8SMarkus Armbruster 
105f66e7ac8SMarkus Armbruster static void test_qmp_protocol(void)
106f66e7ac8SMarkus Armbruster {
107f66e7ac8SMarkus Armbruster     QDict *resp, *q, *ret;
108f66e7ac8SMarkus Armbruster     QList *capabilities;
1096a5c88f5SEric Blake     QTestState *qts;
110f66e7ac8SMarkus Armbruster 
111ddee57e0SEric Blake     qts = qtest_init_without_qmp_handshake(false, common_args);
112f66e7ac8SMarkus Armbruster 
113f66e7ac8SMarkus Armbruster     /* Test greeting */
1146a5c88f5SEric Blake     resp = qtest_qmp_receive(qts);
115f66e7ac8SMarkus Armbruster     q = qdict_get_qdict(resp, "QMP");
116f66e7ac8SMarkus Armbruster     g_assert(q);
117f66e7ac8SMarkus Armbruster     test_version(qdict_get(q, "version"));
118f66e7ac8SMarkus Armbruster     capabilities = qdict_get_qlist(q, "capabilities");
119*8258292eSPeter Xu     g_assert(capabilities);
120cb3e7f08SMarc-André Lureau     qobject_unref(resp);
121f66e7ac8SMarkus Armbruster 
122f66e7ac8SMarkus Armbruster     /* Test valid command before handshake */
1236a5c88f5SEric Blake     resp = qtest_qmp(qts, "{ 'execute': 'query-version' }");
124ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "CommandNotFound");
125f66e7ac8SMarkus Armbruster 
126f66e7ac8SMarkus Armbruster     /* Test malformed commands before handshake */
1276a5c88f5SEric Blake     test_malformed(qts);
128f66e7ac8SMarkus Armbruster 
129f66e7ac8SMarkus Armbruster     /* Test handshake */
1306a5c88f5SEric Blake     resp = qtest_qmp(qts, "{ 'execute': 'qmp_capabilities' }");
131f66e7ac8SMarkus Armbruster     ret = qdict_get_qdict(resp, "return");
132f66e7ac8SMarkus Armbruster     g_assert(ret && !qdict_size(ret));
133cb3e7f08SMarc-André Lureau     qobject_unref(resp);
134f66e7ac8SMarkus Armbruster 
135f66e7ac8SMarkus Armbruster     /* Test repeated handshake */
1366a5c88f5SEric Blake     resp = qtest_qmp(qts, "{ 'execute': 'qmp_capabilities' }");
137ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "CommandNotFound");
138f66e7ac8SMarkus Armbruster 
139f66e7ac8SMarkus Armbruster     /* Test valid command */
1406a5c88f5SEric Blake     resp = qtest_qmp(qts, "{ 'execute': 'query-version' }");
141f66e7ac8SMarkus Armbruster     test_version(qdict_get(resp, "return"));
142cb3e7f08SMarc-André Lureau     qobject_unref(resp);
143f66e7ac8SMarkus Armbruster 
144f66e7ac8SMarkus Armbruster     /* Test malformed commands */
1456a5c88f5SEric Blake     test_malformed(qts);
146f66e7ac8SMarkus Armbruster 
147f66e7ac8SMarkus Armbruster     /* Test 'id' */
1486a5c88f5SEric Blake     resp = qtest_qmp(qts, "{ 'execute': 'query-name', 'id': 'cookie#1' }");
149f66e7ac8SMarkus Armbruster     ret = qdict_get_qdict(resp, "return");
150f66e7ac8SMarkus Armbruster     g_assert(ret);
151f66e7ac8SMarkus Armbruster     g_assert_cmpstr(qdict_get_try_str(resp, "id"), ==, "cookie#1");
152cb3e7f08SMarc-André Lureau     qobject_unref(resp);
153f66e7ac8SMarkus Armbruster 
154f66e7ac8SMarkus Armbruster     /* Test command failure with 'id' */
1556a5c88f5SEric Blake     resp = qtest_qmp(qts, "{ 'execute': 'human-monitor-command', 'id': 2 }");
156f66e7ac8SMarkus Armbruster     g_assert_cmpint(qdict_get_int(resp, "id"), ==, 2);
157ebb4d82dSMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
158f66e7ac8SMarkus Armbruster 
1596a5c88f5SEric Blake     qtest_quit(qts);
160f66e7ac8SMarkus Armbruster }
161f66e7ac8SMarkus Armbruster 
16297ca0712SMarkus Armbruster /* Out-of-band tests */
16397ca0712SMarkus Armbruster 
16497ca0712SMarkus Armbruster char tmpdir[] = "/tmp/qmp-test-XXXXXX";
16597ca0712SMarkus Armbruster char *fifo_name;
16697ca0712SMarkus Armbruster 
16797ca0712SMarkus Armbruster static void setup_blocking_cmd(void)
16897ca0712SMarkus Armbruster {
16997ca0712SMarkus Armbruster     if (!mkdtemp(tmpdir)) {
17097ca0712SMarkus Armbruster         g_error("mkdtemp: %s", strerror(errno));
17197ca0712SMarkus Armbruster     }
17297ca0712SMarkus Armbruster     fifo_name = g_strdup_printf("%s/fifo", tmpdir);
17397ca0712SMarkus Armbruster     if (mkfifo(fifo_name, 0666)) {
17497ca0712SMarkus Armbruster         g_error("mkfifo: %s", strerror(errno));
17597ca0712SMarkus Armbruster     }
17697ca0712SMarkus Armbruster }
17797ca0712SMarkus Armbruster 
17897ca0712SMarkus Armbruster static void cleanup_blocking_cmd(void)
17997ca0712SMarkus Armbruster {
18097ca0712SMarkus Armbruster     unlink(fifo_name);
18197ca0712SMarkus Armbruster     rmdir(tmpdir);
18297ca0712SMarkus Armbruster }
18397ca0712SMarkus Armbruster 
18497ca0712SMarkus Armbruster static void send_cmd_that_blocks(QTestState *s, const char *id)
18597ca0712SMarkus Armbruster {
1864277f1ebSMarkus Armbruster     qtest_qmp_send(s, "{ 'execute': 'blockdev-add',  'id': %s,"
18797ca0712SMarkus Armbruster                    " 'arguments': {"
18897ca0712SMarkus Armbruster                    " 'driver': 'blkdebug', 'node-name': %s,"
18997ca0712SMarkus Armbruster                    " 'config': %s,"
19097ca0712SMarkus Armbruster                    " 'image': { 'driver': 'null-co' } } }",
19197ca0712SMarkus Armbruster                    id, id, fifo_name);
19297ca0712SMarkus Armbruster }
19397ca0712SMarkus Armbruster 
19497ca0712SMarkus Armbruster static void unblock_blocked_cmd(void)
19597ca0712SMarkus Armbruster {
19697ca0712SMarkus Armbruster     int fd = open(fifo_name, O_WRONLY);
19797ca0712SMarkus Armbruster     g_assert(fd >= 0);
19897ca0712SMarkus Armbruster     close(fd);
19997ca0712SMarkus Armbruster }
20097ca0712SMarkus Armbruster 
20197ca0712SMarkus Armbruster static void send_oob_cmd_that_fails(QTestState *s, const char *id)
20297ca0712SMarkus Armbruster {
2034277f1ebSMarkus Armbruster     qtest_qmp_send(s, "{ 'exec-oob': 'migrate-pause', 'id': %s }", id);
20497ca0712SMarkus Armbruster }
20597ca0712SMarkus Armbruster 
20697ca0712SMarkus Armbruster static void recv_cmd_id(QTestState *s, const char *id)
20797ca0712SMarkus Armbruster {
20897ca0712SMarkus Armbruster     QDict *resp = qtest_qmp_receive(s);
20997ca0712SMarkus Armbruster 
21097ca0712SMarkus Armbruster     g_assert_cmpstr(qdict_get_try_str(resp, "id"), ==, id);
21197ca0712SMarkus Armbruster     qobject_unref(resp);
21297ca0712SMarkus Armbruster }
21397ca0712SMarkus Armbruster 
214fa198ad9SPeter Xu static void test_qmp_oob(void)
215fa198ad9SPeter Xu {
216fa198ad9SPeter Xu     QTestState *qts;
217fa198ad9SPeter Xu     QDict *resp, *q;
218fa198ad9SPeter Xu     const QListEntry *entry;
219fa198ad9SPeter Xu     QList *capabilities;
220fa198ad9SPeter Xu     QString *qstr;
221fa198ad9SPeter Xu 
222fa198ad9SPeter Xu     qts = qtest_init_without_qmp_handshake(true, common_args);
223fa198ad9SPeter Xu 
224fa198ad9SPeter Xu     /* Check the greeting message. */
225fa198ad9SPeter Xu     resp = qtest_qmp_receive(qts);
226fa198ad9SPeter Xu     q = qdict_get_qdict(resp, "QMP");
227fa198ad9SPeter Xu     g_assert(q);
228fa198ad9SPeter Xu     capabilities = qdict_get_qlist(q, "capabilities");
229fa198ad9SPeter Xu     g_assert(capabilities && !qlist_empty(capabilities));
230fa198ad9SPeter Xu     entry = qlist_first(capabilities);
231fa198ad9SPeter Xu     g_assert(entry);
232fa198ad9SPeter Xu     qstr = qobject_to(QString, entry->value);
233fa198ad9SPeter Xu     g_assert(qstr);
234fa198ad9SPeter Xu     g_assert_cmpstr(qstring_get_str(qstr), ==, "oob");
235cb3e7f08SMarc-André Lureau     qobject_unref(resp);
236fa198ad9SPeter Xu 
237fa198ad9SPeter Xu     /* Try a fake capability, it should fail. */
238fa198ad9SPeter Xu     resp = qtest_qmp(qts,
239fa198ad9SPeter Xu                      "{ 'execute': 'qmp_capabilities', "
240fa198ad9SPeter Xu                      "  'arguments': { 'enable': [ 'cap-does-not-exist' ] } }");
241fa198ad9SPeter Xu     g_assert(qdict_haskey(resp, "error"));
242cb3e7f08SMarc-André Lureau     qobject_unref(resp);
243fa198ad9SPeter Xu 
244fa198ad9SPeter Xu     /* Now, enable OOB in current QMP session, it should succeed. */
245fa198ad9SPeter Xu     resp = qtest_qmp(qts,
246fa198ad9SPeter Xu                      "{ 'execute': 'qmp_capabilities', "
247fa198ad9SPeter Xu                      "  'arguments': { 'enable': [ 'oob' ] } }");
248fa198ad9SPeter Xu     g_assert(qdict_haskey(resp, "return"));
249cb3e7f08SMarc-André Lureau     qobject_unref(resp);
250fa198ad9SPeter Xu 
251fa198ad9SPeter Xu     /*
252fa198ad9SPeter Xu      * Try any command that does not support OOB but with OOB flag. We
253fa198ad9SPeter Xu      * should get failure.
254fa198ad9SPeter Xu      */
25500ecec15SMarkus Armbruster     resp = qtest_qmp(qts, "{ 'exec-oob': 'query-cpus' }");
256fa198ad9SPeter Xu     g_assert(qdict_haskey(resp, "error"));
257cb3e7f08SMarc-André Lureau     qobject_unref(resp);
258fa198ad9SPeter Xu 
25997ca0712SMarkus Armbruster     /* OOB command overtakes slow in-band command */
26097ca0712SMarkus Armbruster     setup_blocking_cmd();
26197ca0712SMarkus Armbruster     send_cmd_that_blocks(qts, "ib-blocks-1");
2624277f1ebSMarkus Armbruster     qtest_qmp_send(qts, "{ 'execute': 'query-name', 'id': 'ib-quick-1' }");
26397ca0712SMarkus Armbruster     send_oob_cmd_that_fails(qts, "oob-1");
26497ca0712SMarkus Armbruster     recv_cmd_id(qts, "oob-1");
26597ca0712SMarkus Armbruster     unblock_blocked_cmd();
26697ca0712SMarkus Armbruster     recv_cmd_id(qts, "ib-blocks-1");
2672970b446SMarkus Armbruster     recv_cmd_id(qts, "ib-quick-1");
268e8f4a221SMarkus Armbruster 
26969240fe6SMarkus Armbruster     /* Even malformed in-band command fails in-band */
270e8f4a221SMarkus Armbruster     send_cmd_that_blocks(qts, "blocks-2");
2714277f1ebSMarkus Armbruster     qtest_qmp_send(qts, "{ 'id': 'err-2' }");
272e8f4a221SMarkus Armbruster     unblock_blocked_cmd();
273e8f4a221SMarkus Armbruster     recv_cmd_id(qts, "blocks-2");
27469240fe6SMarkus Armbruster     recv_cmd_id(qts, "err-2");
27597ca0712SMarkus Armbruster     cleanup_blocking_cmd();
276fa198ad9SPeter Xu 
277fa198ad9SPeter Xu     qtest_quit(qts);
278fa198ad9SPeter Xu }
279fa198ad9SPeter Xu 
28097ca0712SMarkus Armbruster /* Preconfig tests */
28197ca0712SMarkus Armbruster 
282fb1e58f7SIgor Mammedov static void test_qmp_preconfig(void)
283fb1e58f7SIgor Mammedov {
284fb1e58f7SIgor Mammedov     QDict *rsp, *ret;
28588b988c8SMarkus Armbruster     QTestState *qs = qtest_initf("%s --preconfig", common_args);
286fb1e58f7SIgor Mammedov 
287fb1e58f7SIgor Mammedov     /* preconfig state */
288fb1e58f7SIgor Mammedov     /* enabled commands, no error expected  */
289fb1e58f7SIgor Mammedov     g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'query-commands' }")));
290fb1e58f7SIgor Mammedov 
291fb1e58f7SIgor Mammedov     /* forbidden commands, expected error */
292fb1e58f7SIgor Mammedov     g_assert(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'query-cpus' }")));
293fb1e58f7SIgor Mammedov 
294fb1e58f7SIgor Mammedov     /* check that query-status returns preconfig state */
295fb1e58f7SIgor Mammedov     rsp = qtest_qmp(qs, "{ 'execute': 'query-status' }");
296fb1e58f7SIgor Mammedov     ret = qdict_get_qdict(rsp, "return");
297fb1e58f7SIgor Mammedov     g_assert(ret);
298fb1e58f7SIgor Mammedov     g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "preconfig");
299fb1e58f7SIgor Mammedov     qobject_unref(rsp);
300fb1e58f7SIgor Mammedov 
301fb1e58f7SIgor Mammedov     /* exit preconfig state */
302361ac948SMarkus Armbruster     g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'x-exit-preconfig' }")));
303fb1e58f7SIgor Mammedov     qtest_qmp_eventwait(qs, "RESUME");
304fb1e58f7SIgor Mammedov 
305fb1e58f7SIgor Mammedov     /* check that query-status returns running state */
306fb1e58f7SIgor Mammedov     rsp = qtest_qmp(qs, "{ 'execute': 'query-status' }");
307fb1e58f7SIgor Mammedov     ret = qdict_get_qdict(rsp, "return");
308fb1e58f7SIgor Mammedov     g_assert(ret);
309fb1e58f7SIgor Mammedov     g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "running");
310fb1e58f7SIgor Mammedov     qobject_unref(rsp);
311fb1e58f7SIgor Mammedov 
312361ac948SMarkus Armbruster     /* check that x-exit-preconfig returns error after exiting preconfig */
313361ac948SMarkus Armbruster     g_assert(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'x-exit-preconfig' }")));
314fb1e58f7SIgor Mammedov 
315fb1e58f7SIgor Mammedov     /* enabled commands, no error expected  */
316fb1e58f7SIgor Mammedov     g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'query-cpus' }")));
317fb1e58f7SIgor Mammedov 
318fb1e58f7SIgor Mammedov     qtest_quit(qs);
319fb1e58f7SIgor Mammedov }
320fb1e58f7SIgor Mammedov 
32161793a62SMarc-André Lureau static void test_qmp_missing_any_arg(void)
32261793a62SMarc-André Lureau {
32361793a62SMarc-André Lureau     QTestState *qts;
32461793a62SMarc-André Lureau     QDict *resp;
32561793a62SMarc-André Lureau 
32661793a62SMarc-André Lureau     qts = qtest_init(common_args);
32761793a62SMarc-André Lureau     resp = qtest_qmp(qts, "{'execute': 'qom-set', 'arguments':"
32861793a62SMarc-André Lureau                      " { 'path': '/machine', 'property': 'rtc-time' } }");
32961793a62SMarc-André Lureau     g_assert_nonnull(resp);
33061793a62SMarc-André Lureau     qmp_assert_error_class(resp, "GenericError");
33161793a62SMarc-André Lureau     qtest_quit(qts);
33261793a62SMarc-André Lureau }
33361793a62SMarc-André Lureau 
334f66e7ac8SMarkus Armbruster int main(int argc, char *argv[])
335f66e7ac8SMarkus Armbruster {
336f66e7ac8SMarkus Armbruster     g_test_init(&argc, &argv, NULL);
337f66e7ac8SMarkus Armbruster 
338f66e7ac8SMarkus Armbruster     qtest_add_func("qmp/protocol", test_qmp_protocol);
339fa198ad9SPeter Xu     qtest_add_func("qmp/oob", test_qmp_oob);
340fb1e58f7SIgor Mammedov     qtest_add_func("qmp/preconfig", test_qmp_preconfig);
34161793a62SMarc-André Lureau     qtest_add_func("qmp/missing-any-arg", test_qmp_missing_any_arg);
342f66e7ac8SMarkus Armbruster 
343d93bb9d5SMarkus Armbruster     return g_test_run();
344f66e7ac8SMarkus Armbruster }
345