xref: /qemu/tests/unit/test-qmp-cmds.c (revision 8aa3a33e442fc49fd67e4c8df8869d257c41c77e)
1681c28a3SPeter Maydell #include "qemu/osdep.h"
26b673957SMarkus Armbruster #include "qapi/qmp/qdict.h"
315280c36SMarkus Armbruster #include "qapi/qmp/qnum.h"
46b673957SMarkus Armbruster #include "qapi/qmp/qstring.h"
5e688df6bSMarkus Armbruster #include "qapi/error.h"
6b3db211fSDaniel P. Berrange #include "qapi/qobject-input-visitor.h"
7d98150f0SLaszlo Ersek #include "tests/test-qapi-types.h"
8d98150f0SLaszlo Ersek #include "tests/test-qapi-visit.h"
9eb815e24SMarkus Armbruster #include "test-qapi-commands.h"
1069ed8366SMichael Roth 
111527badbSMarkus Armbruster static QmpCommandList qmp_commands;
121527badbSMarkus Armbruster 
131f7b9f31SMarc-André Lureau #if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD)
14967c8851SMarc-André Lureau UserDefThree *qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
15967c8851SMarc-André Lureau {
16967c8851SMarc-André Lureau     return NULL;
17967c8851SMarc-André Lureau }
181f7b9f31SMarc-André Lureau #endif
19967c8851SMarc-André Lureau 
20967c8851SMarc-André Lureau UserDefThree *qmp_TestCmdReturnDefThree(Error **errp)
21967c8851SMarc-André Lureau {
22967c8851SMarc-André Lureau     return NULL;
23967c8851SMarc-André Lureau }
24967c8851SMarc-André Lureau 
2569ed8366SMichael Roth void qmp_user_def_cmd(Error **errp)
2669ed8366SMichael Roth {
2769ed8366SMichael Roth }
2869ed8366SMichael Roth 
297b13f2c2SIgor Mammedov void qmp_test_flags_command(Error **errp)
301a1b11dcSPeter Xu {
311a1b11dcSPeter Xu }
321a1b11dcSPeter Xu 
33ae6bf766SMarc-André Lureau void qmp_cmd_success_response(Error **errp)
34ae6bf766SMarc-André Lureau {
35ae6bf766SMarc-André Lureau }
36ae6bf766SMarc-André Lureau 
37972a1101SEric Blake Empty2 *qmp_user_def_cmd0(Error **errp)
38972a1101SEric Blake {
39972a1101SEric Blake     return g_new0(Empty2, 1);
40972a1101SEric Blake }
41972a1101SEric Blake 
4269ed8366SMichael Roth void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
4369ed8366SMichael Roth {
4469ed8366SMichael Roth }
4569ed8366SMichael Roth 
46*8aa3a33eSKevin Wolf void qmp_test_features(FeatureStruct0 *fs0, FeatureStruct1 *fs1,
47*8aa3a33eSKevin Wolf                        FeatureStruct2 *fs2, FeatureStruct3 *fs3,
48*8aa3a33eSKevin Wolf                        FeatureStruct4 *fs4, CondFeatureStruct1 *cfs1,
49*8aa3a33eSKevin Wolf                        CondFeatureStruct2 *cfs2, CondFeatureStruct3 *cfs3,
50*8aa3a33eSKevin Wolf                        Error **errp)
51*8aa3a33eSKevin Wolf {
52*8aa3a33eSKevin Wolf }
53*8aa3a33eSKevin Wolf 
54ab22ad96SMarkus Armbruster UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
55ab22ad96SMarkus Armbruster                               bool has_udb1, UserDefOne *ud1b,
56ab22ad96SMarkus Armbruster                               Error **errp)
5769ed8366SMichael Roth {
5869ed8366SMichael Roth     UserDefTwo *ret;
597267c094SAnthony Liguori     UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
607267c094SAnthony Liguori     UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
6169ed8366SMichael Roth 
6269ed8366SMichael Roth     ud1c->string = strdup(ud1a->string);
63ddf21908SEric Blake     ud1c->integer = ud1a->integer;
64ab22ad96SMarkus Armbruster     ud1d->string = strdup(has_udb1 ? ud1b->string : "blah0");
65ddf21908SEric Blake     ud1d->integer = has_udb1 ? ud1b->integer : 0;
6669ed8366SMichael Roth 
67b6fcf32dSEric Blake     ret = g_new0(UserDefTwo, 1);
68b6fcf32dSEric Blake     ret->string0 = strdup("blah1");
696446a592SEric Blake     ret->dict1 = g_new0(UserDefTwoDict, 1);
706446a592SEric Blake     ret->dict1->string1 = strdup("blah2");
716446a592SEric Blake     ret->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
726446a592SEric Blake     ret->dict1->dict2->userdef = ud1c;
736446a592SEric Blake     ret->dict1->dict2->string = strdup("blah3");
746446a592SEric Blake     ret->dict1->dict3 = g_new0(UserDefTwoDictDict, 1);
756446a592SEric Blake     ret->dict1->has_dict3 = true;
766446a592SEric Blake     ret->dict1->dict3->userdef = ud1d;
776446a592SEric Blake     ret->dict1->dict3->string = strdup("blah4");
7869ed8366SMichael Roth 
7969ed8366SMichael Roth     return ret;
8069ed8366SMichael Roth }
8169ed8366SMichael Roth 
82cae95eaeSEric Blake int64_t qmp_guest_get_time(int64_t a, bool has_b, int64_t b, Error **errp)
83c2216a8aSMarkus Armbruster {
84c2216a8aSMarkus Armbruster     return a + (has_b ? b : 0);
85c2216a8aSMarkus Armbruster }
86c2216a8aSMarkus Armbruster 
8728770e05SMarkus Armbruster QObject *qmp_guest_sync(QObject *arg, Error **errp)
8828770e05SMarkus Armbruster {
8928770e05SMarkus Armbruster     return arg;
9028770e05SMarkus Armbruster }
9128770e05SMarkus Armbruster 
92c818408eSEric Blake void qmp_boxed_struct(UserDefZero *arg, Error **errp)
93c818408eSEric Blake {
94c818408eSEric Blake }
95c818408eSEric Blake 
96b359f4b2SMarkus Armbruster void qmp_boxed_union(UserDefListUnion *arg, Error **errp)
97c818408eSEric Blake {
98c818408eSEric Blake }
99c818408eSEric Blake 
100e3c4c3d7SEric Blake __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
101e3c4c3d7SEric Blake                                               __org_qemu_x_StructList *b,
102e3c4c3d7SEric Blake                                               __org_qemu_x_Union2 *c,
103e3c4c3d7SEric Blake                                               __org_qemu_x_Alt *d,
104e3c4c3d7SEric Blake                                               Error **errp)
105e3c4c3d7SEric Blake {
106e3c4c3d7SEric Blake     __org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
107e3c4c3d7SEric Blake 
108c363acefSEric Blake     ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
10932bafa8fSEric Blake     ret->u.__org_qemu_x_branch.data = strdup("blah1");
110e3c4c3d7SEric Blake 
111c43567c1SEric Blake     /* Also test that 'wchar-t' was munged to 'q_wchar_t' */
112c43567c1SEric Blake     if (b && b->value && !b->value->has_q_wchar_t) {
113c43567c1SEric Blake         b->value->q_wchar_t = 1;
114c43567c1SEric Blake     }
115e3c4c3d7SEric Blake     return ret;
116e3c4c3d7SEric Blake }
117e3c4c3d7SEric Blake 
118e3c4c3d7SEric Blake 
11969ed8366SMichael Roth /* test commands with no input and no return value */
12069ed8366SMichael Roth static void test_dispatch_cmd(void)
12169ed8366SMichael Roth {
12269ed8366SMichael Roth     QDict *req = qdict_new();
123d43b1694SMarkus Armbruster     QDict *resp;
12469ed8366SMichael Roth 
12546f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd");
12669ed8366SMichael Roth 
127674ed722SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
12869ed8366SMichael Roth     assert(resp != NULL);
129d43b1694SMarkus Armbruster     assert(!qdict_haskey(resp, "error"));
13069ed8366SMichael Roth 
131cb3e7f08SMarc-André Lureau     qobject_unref(resp);
132cb3e7f08SMarc-André Lureau     qobject_unref(req);
13369ed8366SMichael Roth }
13469ed8366SMichael Roth 
135c55f070bSPeter Xu static void test_dispatch_cmd_oob(void)
136c55f070bSPeter Xu {
137c55f070bSPeter Xu     QDict *req = qdict_new();
138c55f070bSPeter Xu     QDict *resp;
139c55f070bSPeter Xu 
140c55f070bSPeter Xu     qdict_put_str(req, "exec-oob", "test-flags-command");
141c55f070bSPeter Xu 
142c55f070bSPeter Xu     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), true);
143c55f070bSPeter Xu     assert(resp != NULL);
144c55f070bSPeter Xu     assert(!qdict_haskey(resp, "error"));
145c55f070bSPeter Xu 
146c55f070bSPeter Xu     qobject_unref(resp);
147c55f070bSPeter Xu     qobject_unref(req);
148c55f070bSPeter Xu }
149c55f070bSPeter Xu 
15069ed8366SMichael Roth /* test commands that return an error due to invalid parameters */
15151009170SPeter Maydell static void test_dispatch_cmd_failure(void)
15269ed8366SMichael Roth {
15369ed8366SMichael Roth     QDict *req = qdict_new();
154a0067da1SMarc-André Lureau     QDict *args = qdict_new();
155d43b1694SMarkus Armbruster     QDict *resp;
15669ed8366SMichael Roth 
15746f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
15869ed8366SMichael Roth 
159674ed722SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
16069ed8366SMichael Roth     assert(resp != NULL);
161d43b1694SMarkus Armbruster     assert(qdict_haskey(resp, "error"));
16269ed8366SMichael Roth 
163cb3e7f08SMarc-André Lureau     qobject_unref(resp);
164cb3e7f08SMarc-André Lureau     qobject_unref(req);
165a0067da1SMarc-André Lureau 
166a0067da1SMarc-André Lureau     /* check that with extra arguments it throws an error */
167a0067da1SMarc-André Lureau     req = qdict_new();
16846f5ac20SEric Blake     qdict_put_int(args, "a", 66);
169a0067da1SMarc-André Lureau     qdict_put(req, "arguments", args);
170a0067da1SMarc-André Lureau 
17146f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd");
172a0067da1SMarc-André Lureau 
173674ed722SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
174a0067da1SMarc-André Lureau     assert(resp != NULL);
175d43b1694SMarkus Armbruster     assert(qdict_haskey(resp, "error"));
176a0067da1SMarc-André Lureau 
177cb3e7f08SMarc-André Lureau     qobject_unref(resp);
178cb3e7f08SMarc-André Lureau     qobject_unref(req);
17969ed8366SMichael Roth }
18069ed8366SMichael Roth 
181ae6bf766SMarc-André Lureau static void test_dispatch_cmd_success_response(void)
182ae6bf766SMarc-André Lureau {
183ae6bf766SMarc-André Lureau     QDict *req = qdict_new();
184ae6bf766SMarc-André Lureau     QDict *resp;
185ae6bf766SMarc-André Lureau 
186ae6bf766SMarc-André Lureau     qdict_put_str(req, "execute", "cmd-success-response");
187ae6bf766SMarc-André Lureau     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
188ae6bf766SMarc-André Lureau     g_assert_null(resp);
189ae6bf766SMarc-André Lureau     qobject_unref(req);
190ae6bf766SMarc-André Lureau }
191ae6bf766SMarc-André Lureau 
192357765feSMarkus Armbruster static QObject *test_qmp_dispatch(QDict *req)
193357765feSMarkus Armbruster {
194357765feSMarkus Armbruster     QDict *resp;
195357765feSMarkus Armbruster     QObject *ret;
196357765feSMarkus Armbruster 
197d43b1694SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
198357765feSMarkus Armbruster     assert(resp && !qdict_haskey(resp, "error"));
199357765feSMarkus Armbruster     ret = qdict_get(resp, "return");
200357765feSMarkus Armbruster     assert(ret);
201cb3e7f08SMarc-André Lureau     qobject_ref(ret);
202d43b1694SMarkus Armbruster     qobject_unref(resp);
203357765feSMarkus Armbruster     return ret;
204357765feSMarkus Armbruster }
205357765feSMarkus Armbruster 
20669ed8366SMichael Roth /* test commands that involve both input parameters and return values */
20769ed8366SMichael Roth static void test_dispatch_cmd_io(void)
20869ed8366SMichael Roth {
20969ed8366SMichael Roth     QDict *req = qdict_new();
21069ed8366SMichael Roth     QDict *args = qdict_new();
211c2216a8aSMarkus Armbruster     QDict *args3 = qdict_new();
21269ed8366SMichael Roth     QDict *ud1a = qdict_new();
21369ed8366SMichael Roth     QDict *ud1b = qdict_new();
214357765feSMarkus Armbruster     QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
215357765feSMarkus Armbruster     QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
21601b2ffceSMarc-André Lureau     QNum *ret3;
21701b2ffceSMarc-André Lureau     int64_t val;
21869ed8366SMichael Roth 
21946f5ac20SEric Blake     qdict_put_int(ud1a, "integer", 42);
22046f5ac20SEric Blake     qdict_put_str(ud1a, "string", "hello");
22146f5ac20SEric Blake     qdict_put_int(ud1b, "integer", 422);
22246f5ac20SEric Blake     qdict_put_str(ud1b, "string", "hello2");
223de6e7951SEric Blake     qdict_put(args, "ud1a", ud1a);
224de6e7951SEric Blake     qdict_put(args, "ud1b", ud1b);
225de6e7951SEric Blake     qdict_put(req, "arguments", args);
22646f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
22769ed8366SMichael Roth 
2287dc847ebSMax Reitz     ret = qobject_to(QDict, test_qmp_dispatch(req));
22969ed8366SMichael Roth 
230b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret, "string0"), "blah1"));
231b6fcf32dSEric Blake     ret_dict = qdict_get_qdict(ret, "dict1");
232b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret_dict, "string1"), "blah2"));
233b6fcf32dSEric Blake     ret_dict_dict = qdict_get_qdict(ret_dict, "dict2");
234357765feSMarkus Armbruster     ret_dict_dict_userdef = qdict_get_qdict(ret_dict_dict, "userdef");
235357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict_userdef, "integer") == 42);
236357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict_userdef, "string"), "hello"));
237357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict, "string"), "blah3"));
238b6fcf32dSEric Blake     ret_dict_dict2 = qdict_get_qdict(ret_dict, "dict3");
239357765feSMarkus Armbruster     ret_dict_dict2_userdef = qdict_get_qdict(ret_dict_dict2, "userdef");
240357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict2_userdef, "integer") == 422);
241357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2_userdef, "string"), "hello2"));
242357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2, "string"), "blah4"));
243cb3e7f08SMarc-André Lureau     qobject_unref(ret);
244c2216a8aSMarkus Armbruster 
24546f5ac20SEric Blake     qdict_put_int(args3, "a", 66);
246c2216a8aSMarkus Armbruster     qdict_put(req, "arguments", args3);
24746f5ac20SEric Blake     qdict_put_str(req, "execute", "guest-get-time");
248c2216a8aSMarkus Armbruster 
2497dc847ebSMax Reitz     ret3 = qobject_to(QNum, test_qmp_dispatch(req));
25001b2ffceSMarc-André Lureau     g_assert(qnum_get_try_int(ret3, &val));
25101b2ffceSMarc-André Lureau     g_assert_cmpint(val, ==, 66);
252cb3e7f08SMarc-André Lureau     qobject_unref(ret3);
253c2216a8aSMarkus Armbruster 
254cb3e7f08SMarc-André Lureau     qobject_unref(req);
25569ed8366SMichael Roth }
25669ed8366SMichael Roth 
2575cd5f0d0SMichael Roth /* test generated dealloc functions for generated types */
2585cd5f0d0SMichael Roth static void test_dealloc_types(void)
2595cd5f0d0SMichael Roth {
2605cd5f0d0SMichael Roth     UserDefOne *ud1test, *ud1a, *ud1b;
2615cd5f0d0SMichael Roth     UserDefOneList *ud1list;
2625cd5f0d0SMichael Roth 
2635cd5f0d0SMichael Roth     ud1test = g_malloc0(sizeof(UserDefOne));
264ddf21908SEric Blake     ud1test->integer = 42;
2655cd5f0d0SMichael Roth     ud1test->string = g_strdup("hi there 42");
2665cd5f0d0SMichael Roth 
2675cd5f0d0SMichael Roth     qapi_free_UserDefOne(ud1test);
2685cd5f0d0SMichael Roth 
2695cd5f0d0SMichael Roth     ud1a = g_malloc0(sizeof(UserDefOne));
270ddf21908SEric Blake     ud1a->integer = 43;
2715cd5f0d0SMichael Roth     ud1a->string = g_strdup("hi there 43");
2725cd5f0d0SMichael Roth 
2735cd5f0d0SMichael Roth     ud1b = g_malloc0(sizeof(UserDefOne));
274ddf21908SEric Blake     ud1b->integer = 44;
2755cd5f0d0SMichael Roth     ud1b->string = g_strdup("hi there 44");
2765cd5f0d0SMichael Roth 
2775cd5f0d0SMichael Roth     ud1list = g_malloc0(sizeof(UserDefOneList));
2785cd5f0d0SMichael Roth     ud1list->value = ud1a;
2795cd5f0d0SMichael Roth     ud1list->next = g_malloc0(sizeof(UserDefOneList));
2805cd5f0d0SMichael Roth     ud1list->next->value = ud1b;
2815cd5f0d0SMichael Roth 
2825cd5f0d0SMichael Roth     qapi_free_UserDefOneList(ud1list);
2835cd5f0d0SMichael Roth }
2845cd5f0d0SMichael Roth 
285d98150f0SLaszlo Ersek /* test generated deallocation on an object whose construction was prematurely
286d98150f0SLaszlo Ersek  * terminated due to an error */
287d98150f0SLaszlo Ersek static void test_dealloc_partial(void)
288d98150f0SLaszlo Ersek {
289d98150f0SLaszlo Ersek     static const char text[] = "don't leak me";
290d98150f0SLaszlo Ersek 
291d98150f0SLaszlo Ersek     UserDefTwo *ud2 = NULL;
292d98150f0SLaszlo Ersek     Error *err = NULL;
293d98150f0SLaszlo Ersek 
294d98150f0SLaszlo Ersek     /* create partial object */
295d98150f0SLaszlo Ersek     {
296d98150f0SLaszlo Ersek         QDict *ud2_dict;
297b70ce101SEric Blake         Visitor *v;
298d98150f0SLaszlo Ersek 
299d98150f0SLaszlo Ersek         ud2_dict = qdict_new();
30046f5ac20SEric Blake         qdict_put_str(ud2_dict, "string0", text);
301d98150f0SLaszlo Ersek 
302048abb7bSMarkus Armbruster         v = qobject_input_visitor_new(QOBJECT(ud2_dict));
303b70ce101SEric Blake         visit_type_UserDefTwo(v, NULL, &ud2, &err);
304b70ce101SEric Blake         visit_free(v);
305cb3e7f08SMarc-André Lureau         qobject_unref(ud2_dict);
306d98150f0SLaszlo Ersek     }
307d98150f0SLaszlo Ersek 
30868ab47e4SEric Blake     /* verify that visit_type_XXX() cleans up properly on error */
309a12a5a1aSEric Blake     error_free_or_abort(&err);
31068ab47e4SEric Blake     assert(!ud2);
31168ab47e4SEric Blake 
31268ab47e4SEric Blake     /* Manually create a partial object, leaving ud2->dict1 at NULL */
31368ab47e4SEric Blake     ud2 = g_new0(UserDefTwo, 1);
31468ab47e4SEric Blake     ud2->string0 = g_strdup(text);
315d98150f0SLaszlo Ersek 
316d98150f0SLaszlo Ersek     /* tear down partial object */
317d98150f0SLaszlo Ersek     qapi_free_UserDefTwo(ud2);
318d98150f0SLaszlo Ersek }
319d98150f0SLaszlo Ersek 
320d98150f0SLaszlo Ersek 
32169ed8366SMichael Roth int main(int argc, char **argv)
32269ed8366SMichael Roth {
32369ed8366SMichael Roth     g_test_init(&argc, &argv, NULL);
32469ed8366SMichael Roth 
325214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dispatch_cmd", test_dispatch_cmd);
326c55f070bSPeter Xu     g_test_add_func("/qmp/dispatch_cmd_oob", test_dispatch_cmd_oob);
327214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dispatch_cmd_failure", test_dispatch_cmd_failure);
328214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io);
329ae6bf766SMarc-André Lureau     g_test_add_func("/qmp/dispatch_cmd_success_response",
330ae6bf766SMarc-André Lureau                     test_dispatch_cmd_success_response);
331214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dealloc_types", test_dealloc_types);
332214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial);
33369ed8366SMichael Roth 
3341527badbSMarkus Armbruster     test_qmp_init_marshal(&qmp_commands);
33569ed8366SMichael Roth     g_test_run();
33669ed8366SMichael Roth 
33769ed8366SMichael Roth     return 0;
33869ed8366SMichael Roth }
339