xref: /qemu/tests/unit/test-qmp-cmds.c (revision cb3e7f08aeaab0ab13e629ce8496dca150a449ba)
1681c28a3SPeter Maydell #include "qemu/osdep.h"
279ee7df8SPaolo Bonzini #include "qemu-common.h"
36b673957SMarkus Armbruster #include "qapi/qmp/qdict.h"
415280c36SMarkus Armbruster #include "qapi/qmp/qnum.h"
56b673957SMarkus Armbruster #include "qapi/qmp/qstring.h"
6e688df6bSMarkus Armbruster #include "qapi/error.h"
71de7afc9SPaolo Bonzini #include "qemu/module.h"
8b3db211fSDaniel P. Berrange #include "qapi/qobject-input-visitor.h"
9d98150f0SLaszlo Ersek #include "tests/test-qapi-types.h"
10d98150f0SLaszlo Ersek #include "tests/test-qapi-visit.h"
11eb815e24SMarkus Armbruster #include "test-qapi-commands.h"
1269ed8366SMichael Roth 
131527badbSMarkus Armbruster static QmpCommandList qmp_commands;
141527badbSMarkus Armbruster 
1569ed8366SMichael Roth void qmp_user_def_cmd(Error **errp)
1669ed8366SMichael Roth {
1769ed8366SMichael Roth }
1869ed8366SMichael Roth 
191a1b11dcSPeter Xu void qmp_an_oob_command(Error **errp)
201a1b11dcSPeter Xu {
211a1b11dcSPeter Xu }
221a1b11dcSPeter Xu 
23972a1101SEric Blake Empty2 *qmp_user_def_cmd0(Error **errp)
24972a1101SEric Blake {
25972a1101SEric Blake     return g_new0(Empty2, 1);
26972a1101SEric Blake }
27972a1101SEric Blake 
2869ed8366SMichael Roth void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
2969ed8366SMichael Roth {
3069ed8366SMichael Roth }
3169ed8366SMichael Roth 
32ab22ad96SMarkus Armbruster UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
33ab22ad96SMarkus Armbruster                               bool has_udb1, UserDefOne *ud1b,
34ab22ad96SMarkus Armbruster                               Error **errp)
3569ed8366SMichael Roth {
3669ed8366SMichael Roth     UserDefTwo *ret;
377267c094SAnthony Liguori     UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
387267c094SAnthony Liguori     UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
3969ed8366SMichael Roth 
4069ed8366SMichael Roth     ud1c->string = strdup(ud1a->string);
41ddf21908SEric Blake     ud1c->integer = ud1a->integer;
42ab22ad96SMarkus Armbruster     ud1d->string = strdup(has_udb1 ? ud1b->string : "blah0");
43ddf21908SEric Blake     ud1d->integer = has_udb1 ? ud1b->integer : 0;
4469ed8366SMichael Roth 
45b6fcf32dSEric Blake     ret = g_new0(UserDefTwo, 1);
46b6fcf32dSEric Blake     ret->string0 = strdup("blah1");
476446a592SEric Blake     ret->dict1 = g_new0(UserDefTwoDict, 1);
486446a592SEric Blake     ret->dict1->string1 = strdup("blah2");
496446a592SEric Blake     ret->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
506446a592SEric Blake     ret->dict1->dict2->userdef = ud1c;
516446a592SEric Blake     ret->dict1->dict2->string = strdup("blah3");
526446a592SEric Blake     ret->dict1->dict3 = g_new0(UserDefTwoDictDict, 1);
536446a592SEric Blake     ret->dict1->has_dict3 = true;
546446a592SEric Blake     ret->dict1->dict3->userdef = ud1d;
556446a592SEric Blake     ret->dict1->dict3->string = strdup("blah4");
5669ed8366SMichael Roth 
5769ed8366SMichael Roth     return ret;
5869ed8366SMichael Roth }
5969ed8366SMichael Roth 
60cae95eaeSEric Blake int64_t qmp_guest_get_time(int64_t a, bool has_b, int64_t b, Error **errp)
61c2216a8aSMarkus Armbruster {
62c2216a8aSMarkus Armbruster     return a + (has_b ? b : 0);
63c2216a8aSMarkus Armbruster }
64c2216a8aSMarkus Armbruster 
6528770e05SMarkus Armbruster QObject *qmp_guest_sync(QObject *arg, Error **errp)
6628770e05SMarkus Armbruster {
6728770e05SMarkus Armbruster     return arg;
6828770e05SMarkus Armbruster }
6928770e05SMarkus Armbruster 
70c818408eSEric Blake void qmp_boxed_struct(UserDefZero *arg, Error **errp)
71c818408eSEric Blake {
72c818408eSEric Blake }
73c818408eSEric Blake 
74c818408eSEric Blake void qmp_boxed_union(UserDefNativeListUnion *arg, Error **errp)
75c818408eSEric Blake {
76c818408eSEric Blake }
77c818408eSEric Blake 
78e3c4c3d7SEric Blake __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
79e3c4c3d7SEric Blake                                               __org_qemu_x_StructList *b,
80e3c4c3d7SEric Blake                                               __org_qemu_x_Union2 *c,
81e3c4c3d7SEric Blake                                               __org_qemu_x_Alt *d,
82e3c4c3d7SEric Blake                                               Error **errp)
83e3c4c3d7SEric Blake {
84e3c4c3d7SEric Blake     __org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
85e3c4c3d7SEric Blake 
86c363acefSEric Blake     ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
8732bafa8fSEric Blake     ret->u.__org_qemu_x_branch.data = strdup("blah1");
88e3c4c3d7SEric Blake 
89c43567c1SEric Blake     /* Also test that 'wchar-t' was munged to 'q_wchar_t' */
90c43567c1SEric Blake     if (b && b->value && !b->value->has_q_wchar_t) {
91c43567c1SEric Blake         b->value->q_wchar_t = 1;
92c43567c1SEric Blake     }
93e3c4c3d7SEric Blake     return ret;
94e3c4c3d7SEric Blake }
95e3c4c3d7SEric Blake 
96e3c4c3d7SEric Blake 
9769ed8366SMichael Roth /* test commands with no input and no return value */
9869ed8366SMichael Roth static void test_dispatch_cmd(void)
9969ed8366SMichael Roth {
10069ed8366SMichael Roth     QDict *req = qdict_new();
10169ed8366SMichael Roth     QObject *resp;
10269ed8366SMichael Roth 
10346f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd");
10469ed8366SMichael Roth 
1051527badbSMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
10669ed8366SMichael Roth     assert(resp != NULL);
1077dc847ebSMax Reitz     assert(!qdict_haskey(qobject_to(QDict, resp), "error"));
10869ed8366SMichael Roth 
109*cb3e7f08SMarc-André Lureau     qobject_unref(resp);
110*cb3e7f08SMarc-André Lureau     qobject_unref(req);
11169ed8366SMichael Roth }
11269ed8366SMichael Roth 
11369ed8366SMichael Roth /* test commands that return an error due to invalid parameters */
11451009170SPeter Maydell static void test_dispatch_cmd_failure(void)
11569ed8366SMichael Roth {
11669ed8366SMichael Roth     QDict *req = qdict_new();
117a0067da1SMarc-André Lureau     QDict *args = qdict_new();
11869ed8366SMichael Roth     QObject *resp;
11969ed8366SMichael Roth 
12046f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
12169ed8366SMichael Roth 
1221527badbSMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
12369ed8366SMichael Roth     assert(resp != NULL);
1247dc847ebSMax Reitz     assert(qdict_haskey(qobject_to(QDict, resp), "error"));
12569ed8366SMichael Roth 
126*cb3e7f08SMarc-André Lureau     qobject_unref(resp);
127*cb3e7f08SMarc-André Lureau     qobject_unref(req);
128a0067da1SMarc-André Lureau 
129a0067da1SMarc-André Lureau     /* check that with extra arguments it throws an error */
130a0067da1SMarc-André Lureau     req = qdict_new();
13146f5ac20SEric Blake     qdict_put_int(args, "a", 66);
132a0067da1SMarc-André Lureau     qdict_put(req, "arguments", args);
133a0067da1SMarc-André Lureau 
13446f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd");
135a0067da1SMarc-André Lureau 
1361527badbSMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
137a0067da1SMarc-André Lureau     assert(resp != NULL);
1387dc847ebSMax Reitz     assert(qdict_haskey(qobject_to(QDict, resp), "error"));
139a0067da1SMarc-André Lureau 
140*cb3e7f08SMarc-André Lureau     qobject_unref(resp);
141*cb3e7f08SMarc-André Lureau     qobject_unref(req);
14269ed8366SMichael Roth }
14369ed8366SMichael Roth 
144357765feSMarkus Armbruster static QObject *test_qmp_dispatch(QDict *req)
145357765feSMarkus Armbruster {
146357765feSMarkus Armbruster     QObject *resp_obj;
147357765feSMarkus Armbruster     QDict *resp;
148357765feSMarkus Armbruster     QObject *ret;
149357765feSMarkus Armbruster 
1501527badbSMarkus Armbruster     resp_obj = qmp_dispatch(&qmp_commands, QOBJECT(req));
151357765feSMarkus Armbruster     assert(resp_obj);
1527dc847ebSMax Reitz     resp = qobject_to(QDict, resp_obj);
153357765feSMarkus Armbruster     assert(resp && !qdict_haskey(resp, "error"));
154357765feSMarkus Armbruster     ret = qdict_get(resp, "return");
155357765feSMarkus Armbruster     assert(ret);
156*cb3e7f08SMarc-André Lureau     qobject_ref(ret);
157*cb3e7f08SMarc-André Lureau     qobject_unref(resp_obj);
158357765feSMarkus Armbruster     return ret;
159357765feSMarkus Armbruster }
160357765feSMarkus Armbruster 
16169ed8366SMichael Roth /* test commands that involve both input parameters and return values */
16269ed8366SMichael Roth static void test_dispatch_cmd_io(void)
16369ed8366SMichael Roth {
16469ed8366SMichael Roth     QDict *req = qdict_new();
16569ed8366SMichael Roth     QDict *args = qdict_new();
166c2216a8aSMarkus Armbruster     QDict *args3 = qdict_new();
16769ed8366SMichael Roth     QDict *ud1a = qdict_new();
16869ed8366SMichael Roth     QDict *ud1b = qdict_new();
169357765feSMarkus Armbruster     QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
170357765feSMarkus Armbruster     QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
17101b2ffceSMarc-André Lureau     QNum *ret3;
17201b2ffceSMarc-André Lureau     int64_t val;
17369ed8366SMichael Roth 
17446f5ac20SEric Blake     qdict_put_int(ud1a, "integer", 42);
17546f5ac20SEric Blake     qdict_put_str(ud1a, "string", "hello");
17646f5ac20SEric Blake     qdict_put_int(ud1b, "integer", 422);
17746f5ac20SEric Blake     qdict_put_str(ud1b, "string", "hello2");
178de6e7951SEric Blake     qdict_put(args, "ud1a", ud1a);
179de6e7951SEric Blake     qdict_put(args, "ud1b", ud1b);
180de6e7951SEric Blake     qdict_put(req, "arguments", args);
18146f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
18269ed8366SMichael Roth 
1837dc847ebSMax Reitz     ret = qobject_to(QDict, test_qmp_dispatch(req));
18469ed8366SMichael Roth 
185b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret, "string0"), "blah1"));
186b6fcf32dSEric Blake     ret_dict = qdict_get_qdict(ret, "dict1");
187b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret_dict, "string1"), "blah2"));
188b6fcf32dSEric Blake     ret_dict_dict = qdict_get_qdict(ret_dict, "dict2");
189357765feSMarkus Armbruster     ret_dict_dict_userdef = qdict_get_qdict(ret_dict_dict, "userdef");
190357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict_userdef, "integer") == 42);
191357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict_userdef, "string"), "hello"));
192357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict, "string"), "blah3"));
193b6fcf32dSEric Blake     ret_dict_dict2 = qdict_get_qdict(ret_dict, "dict3");
194357765feSMarkus Armbruster     ret_dict_dict2_userdef = qdict_get_qdict(ret_dict_dict2, "userdef");
195357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict2_userdef, "integer") == 422);
196357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2_userdef, "string"), "hello2"));
197357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2, "string"), "blah4"));
198*cb3e7f08SMarc-André Lureau     qobject_unref(ret);
199c2216a8aSMarkus Armbruster 
20046f5ac20SEric Blake     qdict_put_int(args3, "a", 66);
201c2216a8aSMarkus Armbruster     qdict_put(req, "arguments", args3);
20246f5ac20SEric Blake     qdict_put_str(req, "execute", "guest-get-time");
203c2216a8aSMarkus Armbruster 
2047dc847ebSMax Reitz     ret3 = qobject_to(QNum, test_qmp_dispatch(req));
20501b2ffceSMarc-André Lureau     g_assert(qnum_get_try_int(ret3, &val));
20601b2ffceSMarc-André Lureau     g_assert_cmpint(val, ==, 66);
207*cb3e7f08SMarc-André Lureau     qobject_unref(ret3);
208c2216a8aSMarkus Armbruster 
209*cb3e7f08SMarc-André Lureau     qobject_unref(req);
21069ed8366SMichael Roth }
21169ed8366SMichael Roth 
2125cd5f0d0SMichael Roth /* test generated dealloc functions for generated types */
2135cd5f0d0SMichael Roth static void test_dealloc_types(void)
2145cd5f0d0SMichael Roth {
2155cd5f0d0SMichael Roth     UserDefOne *ud1test, *ud1a, *ud1b;
2165cd5f0d0SMichael Roth     UserDefOneList *ud1list;
2175cd5f0d0SMichael Roth 
2185cd5f0d0SMichael Roth     ud1test = g_malloc0(sizeof(UserDefOne));
219ddf21908SEric Blake     ud1test->integer = 42;
2205cd5f0d0SMichael Roth     ud1test->string = g_strdup("hi there 42");
2215cd5f0d0SMichael Roth 
2225cd5f0d0SMichael Roth     qapi_free_UserDefOne(ud1test);
2235cd5f0d0SMichael Roth 
2245cd5f0d0SMichael Roth     ud1a = g_malloc0(sizeof(UserDefOne));
225ddf21908SEric Blake     ud1a->integer = 43;
2265cd5f0d0SMichael Roth     ud1a->string = g_strdup("hi there 43");
2275cd5f0d0SMichael Roth 
2285cd5f0d0SMichael Roth     ud1b = g_malloc0(sizeof(UserDefOne));
229ddf21908SEric Blake     ud1b->integer = 44;
2305cd5f0d0SMichael Roth     ud1b->string = g_strdup("hi there 44");
2315cd5f0d0SMichael Roth 
2325cd5f0d0SMichael Roth     ud1list = g_malloc0(sizeof(UserDefOneList));
2335cd5f0d0SMichael Roth     ud1list->value = ud1a;
2345cd5f0d0SMichael Roth     ud1list->next = g_malloc0(sizeof(UserDefOneList));
2355cd5f0d0SMichael Roth     ud1list->next->value = ud1b;
2365cd5f0d0SMichael Roth 
2375cd5f0d0SMichael Roth     qapi_free_UserDefOneList(ud1list);
2385cd5f0d0SMichael Roth }
2395cd5f0d0SMichael Roth 
240d98150f0SLaszlo Ersek /* test generated deallocation on an object whose construction was prematurely
241d98150f0SLaszlo Ersek  * terminated due to an error */
242d98150f0SLaszlo Ersek static void test_dealloc_partial(void)
243d98150f0SLaszlo Ersek {
244d98150f0SLaszlo Ersek     static const char text[] = "don't leak me";
245d98150f0SLaszlo Ersek 
246d98150f0SLaszlo Ersek     UserDefTwo *ud2 = NULL;
247d98150f0SLaszlo Ersek     Error *err = NULL;
248d98150f0SLaszlo Ersek 
249d98150f0SLaszlo Ersek     /* create partial object */
250d98150f0SLaszlo Ersek     {
251d98150f0SLaszlo Ersek         QDict *ud2_dict;
252b70ce101SEric Blake         Visitor *v;
253d98150f0SLaszlo Ersek 
254d98150f0SLaszlo Ersek         ud2_dict = qdict_new();
25546f5ac20SEric Blake         qdict_put_str(ud2_dict, "string0", text);
256d98150f0SLaszlo Ersek 
257048abb7bSMarkus Armbruster         v = qobject_input_visitor_new(QOBJECT(ud2_dict));
258b70ce101SEric Blake         visit_type_UserDefTwo(v, NULL, &ud2, &err);
259b70ce101SEric Blake         visit_free(v);
260*cb3e7f08SMarc-André Lureau         qobject_unref(ud2_dict);
261d98150f0SLaszlo Ersek     }
262d98150f0SLaszlo Ersek 
26368ab47e4SEric Blake     /* verify that visit_type_XXX() cleans up properly on error */
264a12a5a1aSEric Blake     error_free_or_abort(&err);
26568ab47e4SEric Blake     assert(!ud2);
26668ab47e4SEric Blake 
26768ab47e4SEric Blake     /* Manually create a partial object, leaving ud2->dict1 at NULL */
26868ab47e4SEric Blake     ud2 = g_new0(UserDefTwo, 1);
26968ab47e4SEric Blake     ud2->string0 = g_strdup(text);
270d98150f0SLaszlo Ersek 
271d98150f0SLaszlo Ersek     /* tear down partial object */
272d98150f0SLaszlo Ersek     qapi_free_UserDefTwo(ud2);
273d98150f0SLaszlo Ersek }
274d98150f0SLaszlo Ersek 
275d98150f0SLaszlo Ersek 
27669ed8366SMichael Roth int main(int argc, char **argv)
27769ed8366SMichael Roth {
27869ed8366SMichael Roth     g_test_init(&argc, &argv, NULL);
27969ed8366SMichael Roth 
28069ed8366SMichael Roth     g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
28151009170SPeter Maydell     g_test_add_func("/0.15/dispatch_cmd_failure", test_dispatch_cmd_failure);
28269ed8366SMichael Roth     g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
2835cd5f0d0SMichael Roth     g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
284d98150f0SLaszlo Ersek     g_test_add_func("/0.15/dealloc_partial", test_dealloc_partial);
28569ed8366SMichael Roth 
2861527badbSMarkus Armbruster     test_qmp_init_marshal(&qmp_commands);
28769ed8366SMichael Roth     g_test_run();
28869ed8366SMichael Roth 
28969ed8366SMichael Roth     return 0;
29069ed8366SMichael Roth }
291