xref: /qemu/tests/unit/test-qmp-cmds.c (revision d43b16945afa8457b03aee543a110c4ff0b7f070)
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 
197b13f2c2SIgor Mammedov void qmp_test_flags_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();
101*d43b1694SMarkus Armbruster     QDict *resp;
10269ed8366SMichael Roth 
10346f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd");
10469ed8366SMichael Roth 
105674ed722SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
10669ed8366SMichael Roth     assert(resp != NULL);
107*d43b1694SMarkus Armbruster     assert(!qdict_haskey(resp, "error"));
10869ed8366SMichael Roth 
109cb3e7f08SMarc-André Lureau     qobject_unref(resp);
110cb3e7f08SMarc-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();
118*d43b1694SMarkus Armbruster     QDict *resp;
11969ed8366SMichael Roth 
12046f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
12169ed8366SMichael Roth 
122674ed722SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
12369ed8366SMichael Roth     assert(resp != NULL);
124*d43b1694SMarkus Armbruster     assert(qdict_haskey(resp, "error"));
12569ed8366SMichael Roth 
126cb3e7f08SMarc-André Lureau     qobject_unref(resp);
127cb3e7f08SMarc-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 
136674ed722SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
137a0067da1SMarc-André Lureau     assert(resp != NULL);
138*d43b1694SMarkus Armbruster     assert(qdict_haskey(resp, "error"));
139a0067da1SMarc-André Lureau 
140cb3e7f08SMarc-André Lureau     qobject_unref(resp);
141cb3e7f08SMarc-André Lureau     qobject_unref(req);
14269ed8366SMichael Roth }
14369ed8366SMichael Roth 
144357765feSMarkus Armbruster static QObject *test_qmp_dispatch(QDict *req)
145357765feSMarkus Armbruster {
146357765feSMarkus Armbruster     QDict *resp;
147357765feSMarkus Armbruster     QObject *ret;
148357765feSMarkus Armbruster 
149*d43b1694SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
150357765feSMarkus Armbruster     assert(resp && !qdict_haskey(resp, "error"));
151357765feSMarkus Armbruster     ret = qdict_get(resp, "return");
152357765feSMarkus Armbruster     assert(ret);
153cb3e7f08SMarc-André Lureau     qobject_ref(ret);
154*d43b1694SMarkus Armbruster     qobject_unref(resp);
155357765feSMarkus Armbruster     return ret;
156357765feSMarkus Armbruster }
157357765feSMarkus Armbruster 
15869ed8366SMichael Roth /* test commands that involve both input parameters and return values */
15969ed8366SMichael Roth static void test_dispatch_cmd_io(void)
16069ed8366SMichael Roth {
16169ed8366SMichael Roth     QDict *req = qdict_new();
16269ed8366SMichael Roth     QDict *args = qdict_new();
163c2216a8aSMarkus Armbruster     QDict *args3 = qdict_new();
16469ed8366SMichael Roth     QDict *ud1a = qdict_new();
16569ed8366SMichael Roth     QDict *ud1b = qdict_new();
166357765feSMarkus Armbruster     QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
167357765feSMarkus Armbruster     QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
16801b2ffceSMarc-André Lureau     QNum *ret3;
16901b2ffceSMarc-André Lureau     int64_t val;
17069ed8366SMichael Roth 
17146f5ac20SEric Blake     qdict_put_int(ud1a, "integer", 42);
17246f5ac20SEric Blake     qdict_put_str(ud1a, "string", "hello");
17346f5ac20SEric Blake     qdict_put_int(ud1b, "integer", 422);
17446f5ac20SEric Blake     qdict_put_str(ud1b, "string", "hello2");
175de6e7951SEric Blake     qdict_put(args, "ud1a", ud1a);
176de6e7951SEric Blake     qdict_put(args, "ud1b", ud1b);
177de6e7951SEric Blake     qdict_put(req, "arguments", args);
17846f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
17969ed8366SMichael Roth 
1807dc847ebSMax Reitz     ret = qobject_to(QDict, test_qmp_dispatch(req));
18169ed8366SMichael Roth 
182b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret, "string0"), "blah1"));
183b6fcf32dSEric Blake     ret_dict = qdict_get_qdict(ret, "dict1");
184b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret_dict, "string1"), "blah2"));
185b6fcf32dSEric Blake     ret_dict_dict = qdict_get_qdict(ret_dict, "dict2");
186357765feSMarkus Armbruster     ret_dict_dict_userdef = qdict_get_qdict(ret_dict_dict, "userdef");
187357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict_userdef, "integer") == 42);
188357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict_userdef, "string"), "hello"));
189357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict, "string"), "blah3"));
190b6fcf32dSEric Blake     ret_dict_dict2 = qdict_get_qdict(ret_dict, "dict3");
191357765feSMarkus Armbruster     ret_dict_dict2_userdef = qdict_get_qdict(ret_dict_dict2, "userdef");
192357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict2_userdef, "integer") == 422);
193357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2_userdef, "string"), "hello2"));
194357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2, "string"), "blah4"));
195cb3e7f08SMarc-André Lureau     qobject_unref(ret);
196c2216a8aSMarkus Armbruster 
19746f5ac20SEric Blake     qdict_put_int(args3, "a", 66);
198c2216a8aSMarkus Armbruster     qdict_put(req, "arguments", args3);
19946f5ac20SEric Blake     qdict_put_str(req, "execute", "guest-get-time");
200c2216a8aSMarkus Armbruster 
2017dc847ebSMax Reitz     ret3 = qobject_to(QNum, test_qmp_dispatch(req));
20201b2ffceSMarc-André Lureau     g_assert(qnum_get_try_int(ret3, &val));
20301b2ffceSMarc-André Lureau     g_assert_cmpint(val, ==, 66);
204cb3e7f08SMarc-André Lureau     qobject_unref(ret3);
205c2216a8aSMarkus Armbruster 
206cb3e7f08SMarc-André Lureau     qobject_unref(req);
20769ed8366SMichael Roth }
20869ed8366SMichael Roth 
2095cd5f0d0SMichael Roth /* test generated dealloc functions for generated types */
2105cd5f0d0SMichael Roth static void test_dealloc_types(void)
2115cd5f0d0SMichael Roth {
2125cd5f0d0SMichael Roth     UserDefOne *ud1test, *ud1a, *ud1b;
2135cd5f0d0SMichael Roth     UserDefOneList *ud1list;
2145cd5f0d0SMichael Roth 
2155cd5f0d0SMichael Roth     ud1test = g_malloc0(sizeof(UserDefOne));
216ddf21908SEric Blake     ud1test->integer = 42;
2175cd5f0d0SMichael Roth     ud1test->string = g_strdup("hi there 42");
2185cd5f0d0SMichael Roth 
2195cd5f0d0SMichael Roth     qapi_free_UserDefOne(ud1test);
2205cd5f0d0SMichael Roth 
2215cd5f0d0SMichael Roth     ud1a = g_malloc0(sizeof(UserDefOne));
222ddf21908SEric Blake     ud1a->integer = 43;
2235cd5f0d0SMichael Roth     ud1a->string = g_strdup("hi there 43");
2245cd5f0d0SMichael Roth 
2255cd5f0d0SMichael Roth     ud1b = g_malloc0(sizeof(UserDefOne));
226ddf21908SEric Blake     ud1b->integer = 44;
2275cd5f0d0SMichael Roth     ud1b->string = g_strdup("hi there 44");
2285cd5f0d0SMichael Roth 
2295cd5f0d0SMichael Roth     ud1list = g_malloc0(sizeof(UserDefOneList));
2305cd5f0d0SMichael Roth     ud1list->value = ud1a;
2315cd5f0d0SMichael Roth     ud1list->next = g_malloc0(sizeof(UserDefOneList));
2325cd5f0d0SMichael Roth     ud1list->next->value = ud1b;
2335cd5f0d0SMichael Roth 
2345cd5f0d0SMichael Roth     qapi_free_UserDefOneList(ud1list);
2355cd5f0d0SMichael Roth }
2365cd5f0d0SMichael Roth 
237d98150f0SLaszlo Ersek /* test generated deallocation on an object whose construction was prematurely
238d98150f0SLaszlo Ersek  * terminated due to an error */
239d98150f0SLaszlo Ersek static void test_dealloc_partial(void)
240d98150f0SLaszlo Ersek {
241d98150f0SLaszlo Ersek     static const char text[] = "don't leak me";
242d98150f0SLaszlo Ersek 
243d98150f0SLaszlo Ersek     UserDefTwo *ud2 = NULL;
244d98150f0SLaszlo Ersek     Error *err = NULL;
245d98150f0SLaszlo Ersek 
246d98150f0SLaszlo Ersek     /* create partial object */
247d98150f0SLaszlo Ersek     {
248d98150f0SLaszlo Ersek         QDict *ud2_dict;
249b70ce101SEric Blake         Visitor *v;
250d98150f0SLaszlo Ersek 
251d98150f0SLaszlo Ersek         ud2_dict = qdict_new();
25246f5ac20SEric Blake         qdict_put_str(ud2_dict, "string0", text);
253d98150f0SLaszlo Ersek 
254048abb7bSMarkus Armbruster         v = qobject_input_visitor_new(QOBJECT(ud2_dict));
255b70ce101SEric Blake         visit_type_UserDefTwo(v, NULL, &ud2, &err);
256b70ce101SEric Blake         visit_free(v);
257cb3e7f08SMarc-André Lureau         qobject_unref(ud2_dict);
258d98150f0SLaszlo Ersek     }
259d98150f0SLaszlo Ersek 
26068ab47e4SEric Blake     /* verify that visit_type_XXX() cleans up properly on error */
261a12a5a1aSEric Blake     error_free_or_abort(&err);
26268ab47e4SEric Blake     assert(!ud2);
26368ab47e4SEric Blake 
26468ab47e4SEric Blake     /* Manually create a partial object, leaving ud2->dict1 at NULL */
26568ab47e4SEric Blake     ud2 = g_new0(UserDefTwo, 1);
26668ab47e4SEric Blake     ud2->string0 = g_strdup(text);
267d98150f0SLaszlo Ersek 
268d98150f0SLaszlo Ersek     /* tear down partial object */
269d98150f0SLaszlo Ersek     qapi_free_UserDefTwo(ud2);
270d98150f0SLaszlo Ersek }
271d98150f0SLaszlo Ersek 
272d98150f0SLaszlo Ersek 
27369ed8366SMichael Roth int main(int argc, char **argv)
27469ed8366SMichael Roth {
27569ed8366SMichael Roth     g_test_init(&argc, &argv, NULL);
27669ed8366SMichael Roth 
27769ed8366SMichael Roth     g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
27851009170SPeter Maydell     g_test_add_func("/0.15/dispatch_cmd_failure", test_dispatch_cmd_failure);
27969ed8366SMichael Roth     g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
2805cd5f0d0SMichael Roth     g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
281d98150f0SLaszlo Ersek     g_test_add_func("/0.15/dealloc_partial", test_dealloc_partial);
28269ed8366SMichael Roth 
2831527badbSMarkus Armbruster     test_qmp_init_marshal(&qmp_commands);
28469ed8366SMichael Roth     g_test_run();
28569ed8366SMichael Roth 
28669ed8366SMichael Roth     return 0;
28769ed8366SMichael Roth }
288