xref: /qemu/tests/unit/test-qmp-cmds.c (revision 214e4a5b3838358dbbf145692a82561cbbbc1dfb)
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 
151f7b9f31SMarc-André Lureau #if defined(TEST_IF_STRUCT) && defined(TEST_IF_CMD)
16967c8851SMarc-André Lureau UserDefThree *qmp_TestIfCmd(TestIfStruct *foo, Error **errp)
17967c8851SMarc-André Lureau {
18967c8851SMarc-André Lureau     return NULL;
19967c8851SMarc-André Lureau }
201f7b9f31SMarc-André Lureau #endif
21967c8851SMarc-André Lureau 
22967c8851SMarc-André Lureau UserDefThree *qmp_TestCmdReturnDefThree(Error **errp)
23967c8851SMarc-André Lureau {
24967c8851SMarc-André Lureau     return NULL;
25967c8851SMarc-André Lureau }
26967c8851SMarc-André Lureau 
2769ed8366SMichael Roth void qmp_user_def_cmd(Error **errp)
2869ed8366SMichael Roth {
2969ed8366SMichael Roth }
3069ed8366SMichael Roth 
317b13f2c2SIgor Mammedov void qmp_test_flags_command(Error **errp)
321a1b11dcSPeter Xu {
331a1b11dcSPeter Xu }
341a1b11dcSPeter Xu 
35972a1101SEric Blake Empty2 *qmp_user_def_cmd0(Error **errp)
36972a1101SEric Blake {
37972a1101SEric Blake     return g_new0(Empty2, 1);
38972a1101SEric Blake }
39972a1101SEric Blake 
4069ed8366SMichael Roth void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
4169ed8366SMichael Roth {
4269ed8366SMichael Roth }
4369ed8366SMichael Roth 
44ab22ad96SMarkus Armbruster UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
45ab22ad96SMarkus Armbruster                               bool has_udb1, UserDefOne *ud1b,
46ab22ad96SMarkus Armbruster                               Error **errp)
4769ed8366SMichael Roth {
4869ed8366SMichael Roth     UserDefTwo *ret;
497267c094SAnthony Liguori     UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
507267c094SAnthony Liguori     UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
5169ed8366SMichael Roth 
5269ed8366SMichael Roth     ud1c->string = strdup(ud1a->string);
53ddf21908SEric Blake     ud1c->integer = ud1a->integer;
54ab22ad96SMarkus Armbruster     ud1d->string = strdup(has_udb1 ? ud1b->string : "blah0");
55ddf21908SEric Blake     ud1d->integer = has_udb1 ? ud1b->integer : 0;
5669ed8366SMichael Roth 
57b6fcf32dSEric Blake     ret = g_new0(UserDefTwo, 1);
58b6fcf32dSEric Blake     ret->string0 = strdup("blah1");
596446a592SEric Blake     ret->dict1 = g_new0(UserDefTwoDict, 1);
606446a592SEric Blake     ret->dict1->string1 = strdup("blah2");
616446a592SEric Blake     ret->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
626446a592SEric Blake     ret->dict1->dict2->userdef = ud1c;
636446a592SEric Blake     ret->dict1->dict2->string = strdup("blah3");
646446a592SEric Blake     ret->dict1->dict3 = g_new0(UserDefTwoDictDict, 1);
656446a592SEric Blake     ret->dict1->has_dict3 = true;
666446a592SEric Blake     ret->dict1->dict3->userdef = ud1d;
676446a592SEric Blake     ret->dict1->dict3->string = strdup("blah4");
6869ed8366SMichael Roth 
6969ed8366SMichael Roth     return ret;
7069ed8366SMichael Roth }
7169ed8366SMichael Roth 
72cae95eaeSEric Blake int64_t qmp_guest_get_time(int64_t a, bool has_b, int64_t b, Error **errp)
73c2216a8aSMarkus Armbruster {
74c2216a8aSMarkus Armbruster     return a + (has_b ? b : 0);
75c2216a8aSMarkus Armbruster }
76c2216a8aSMarkus Armbruster 
7728770e05SMarkus Armbruster QObject *qmp_guest_sync(QObject *arg, Error **errp)
7828770e05SMarkus Armbruster {
7928770e05SMarkus Armbruster     return arg;
8028770e05SMarkus Armbruster }
8128770e05SMarkus Armbruster 
82c818408eSEric Blake void qmp_boxed_struct(UserDefZero *arg, Error **errp)
83c818408eSEric Blake {
84c818408eSEric Blake }
85c818408eSEric Blake 
86c818408eSEric Blake void qmp_boxed_union(UserDefNativeListUnion *arg, Error **errp)
87c818408eSEric Blake {
88c818408eSEric Blake }
89c818408eSEric Blake 
90e3c4c3d7SEric Blake __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
91e3c4c3d7SEric Blake                                               __org_qemu_x_StructList *b,
92e3c4c3d7SEric Blake                                               __org_qemu_x_Union2 *c,
93e3c4c3d7SEric Blake                                               __org_qemu_x_Alt *d,
94e3c4c3d7SEric Blake                                               Error **errp)
95e3c4c3d7SEric Blake {
96e3c4c3d7SEric Blake     __org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
97e3c4c3d7SEric Blake 
98c363acefSEric Blake     ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
9932bafa8fSEric Blake     ret->u.__org_qemu_x_branch.data = strdup("blah1");
100e3c4c3d7SEric Blake 
101c43567c1SEric Blake     /* Also test that 'wchar-t' was munged to 'q_wchar_t' */
102c43567c1SEric Blake     if (b && b->value && !b->value->has_q_wchar_t) {
103c43567c1SEric Blake         b->value->q_wchar_t = 1;
104c43567c1SEric Blake     }
105e3c4c3d7SEric Blake     return ret;
106e3c4c3d7SEric Blake }
107e3c4c3d7SEric Blake 
108e3c4c3d7SEric Blake 
10969ed8366SMichael Roth /* test commands with no input and no return value */
11069ed8366SMichael Roth static void test_dispatch_cmd(void)
11169ed8366SMichael Roth {
11269ed8366SMichael Roth     QDict *req = qdict_new();
113d43b1694SMarkus Armbruster     QDict *resp;
11469ed8366SMichael Roth 
11546f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd");
11669ed8366SMichael Roth 
117674ed722SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
11869ed8366SMichael Roth     assert(resp != NULL);
119d43b1694SMarkus Armbruster     assert(!qdict_haskey(resp, "error"));
12069ed8366SMichael Roth 
121cb3e7f08SMarc-André Lureau     qobject_unref(resp);
122cb3e7f08SMarc-André Lureau     qobject_unref(req);
12369ed8366SMichael Roth }
12469ed8366SMichael Roth 
12569ed8366SMichael Roth /* test commands that return an error due to invalid parameters */
12651009170SPeter Maydell static void test_dispatch_cmd_failure(void)
12769ed8366SMichael Roth {
12869ed8366SMichael Roth     QDict *req = qdict_new();
129a0067da1SMarc-André Lureau     QDict *args = qdict_new();
130d43b1694SMarkus Armbruster     QDict *resp;
13169ed8366SMichael Roth 
13246f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
13369ed8366SMichael Roth 
134674ed722SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
13569ed8366SMichael Roth     assert(resp != NULL);
136d43b1694SMarkus Armbruster     assert(qdict_haskey(resp, "error"));
13769ed8366SMichael Roth 
138cb3e7f08SMarc-André Lureau     qobject_unref(resp);
139cb3e7f08SMarc-André Lureau     qobject_unref(req);
140a0067da1SMarc-André Lureau 
141a0067da1SMarc-André Lureau     /* check that with extra arguments it throws an error */
142a0067da1SMarc-André Lureau     req = qdict_new();
14346f5ac20SEric Blake     qdict_put_int(args, "a", 66);
144a0067da1SMarc-André Lureau     qdict_put(req, "arguments", args);
145a0067da1SMarc-André Lureau 
14646f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd");
147a0067da1SMarc-André Lureau 
148674ed722SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
149a0067da1SMarc-André Lureau     assert(resp != NULL);
150d43b1694SMarkus Armbruster     assert(qdict_haskey(resp, "error"));
151a0067da1SMarc-André Lureau 
152cb3e7f08SMarc-André Lureau     qobject_unref(resp);
153cb3e7f08SMarc-André Lureau     qobject_unref(req);
15469ed8366SMichael Roth }
15569ed8366SMichael Roth 
156357765feSMarkus Armbruster static QObject *test_qmp_dispatch(QDict *req)
157357765feSMarkus Armbruster {
158357765feSMarkus Armbruster     QDict *resp;
159357765feSMarkus Armbruster     QObject *ret;
160357765feSMarkus Armbruster 
161d43b1694SMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req), false);
162357765feSMarkus Armbruster     assert(resp && !qdict_haskey(resp, "error"));
163357765feSMarkus Armbruster     ret = qdict_get(resp, "return");
164357765feSMarkus Armbruster     assert(ret);
165cb3e7f08SMarc-André Lureau     qobject_ref(ret);
166d43b1694SMarkus Armbruster     qobject_unref(resp);
167357765feSMarkus Armbruster     return ret;
168357765feSMarkus Armbruster }
169357765feSMarkus Armbruster 
17069ed8366SMichael Roth /* test commands that involve both input parameters and return values */
17169ed8366SMichael Roth static void test_dispatch_cmd_io(void)
17269ed8366SMichael Roth {
17369ed8366SMichael Roth     QDict *req = qdict_new();
17469ed8366SMichael Roth     QDict *args = qdict_new();
175c2216a8aSMarkus Armbruster     QDict *args3 = qdict_new();
17669ed8366SMichael Roth     QDict *ud1a = qdict_new();
17769ed8366SMichael Roth     QDict *ud1b = qdict_new();
178357765feSMarkus Armbruster     QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
179357765feSMarkus Armbruster     QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
18001b2ffceSMarc-André Lureau     QNum *ret3;
18101b2ffceSMarc-André Lureau     int64_t val;
18269ed8366SMichael Roth 
18346f5ac20SEric Blake     qdict_put_int(ud1a, "integer", 42);
18446f5ac20SEric Blake     qdict_put_str(ud1a, "string", "hello");
18546f5ac20SEric Blake     qdict_put_int(ud1b, "integer", 422);
18646f5ac20SEric Blake     qdict_put_str(ud1b, "string", "hello2");
187de6e7951SEric Blake     qdict_put(args, "ud1a", ud1a);
188de6e7951SEric Blake     qdict_put(args, "ud1b", ud1b);
189de6e7951SEric Blake     qdict_put(req, "arguments", args);
19046f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
19169ed8366SMichael Roth 
1927dc847ebSMax Reitz     ret = qobject_to(QDict, test_qmp_dispatch(req));
19369ed8366SMichael Roth 
194b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret, "string0"), "blah1"));
195b6fcf32dSEric Blake     ret_dict = qdict_get_qdict(ret, "dict1");
196b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret_dict, "string1"), "blah2"));
197b6fcf32dSEric Blake     ret_dict_dict = qdict_get_qdict(ret_dict, "dict2");
198357765feSMarkus Armbruster     ret_dict_dict_userdef = qdict_get_qdict(ret_dict_dict, "userdef");
199357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict_userdef, "integer") == 42);
200357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict_userdef, "string"), "hello"));
201357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict, "string"), "blah3"));
202b6fcf32dSEric Blake     ret_dict_dict2 = qdict_get_qdict(ret_dict, "dict3");
203357765feSMarkus Armbruster     ret_dict_dict2_userdef = qdict_get_qdict(ret_dict_dict2, "userdef");
204357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict2_userdef, "integer") == 422);
205357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2_userdef, "string"), "hello2"));
206357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2, "string"), "blah4"));
207cb3e7f08SMarc-André Lureau     qobject_unref(ret);
208c2216a8aSMarkus Armbruster 
20946f5ac20SEric Blake     qdict_put_int(args3, "a", 66);
210c2216a8aSMarkus Armbruster     qdict_put(req, "arguments", args3);
21146f5ac20SEric Blake     qdict_put_str(req, "execute", "guest-get-time");
212c2216a8aSMarkus Armbruster 
2137dc847ebSMax Reitz     ret3 = qobject_to(QNum, test_qmp_dispatch(req));
21401b2ffceSMarc-André Lureau     g_assert(qnum_get_try_int(ret3, &val));
21501b2ffceSMarc-André Lureau     g_assert_cmpint(val, ==, 66);
216cb3e7f08SMarc-André Lureau     qobject_unref(ret3);
217c2216a8aSMarkus Armbruster 
218cb3e7f08SMarc-André Lureau     qobject_unref(req);
21969ed8366SMichael Roth }
22069ed8366SMichael Roth 
2215cd5f0d0SMichael Roth /* test generated dealloc functions for generated types */
2225cd5f0d0SMichael Roth static void test_dealloc_types(void)
2235cd5f0d0SMichael Roth {
2245cd5f0d0SMichael Roth     UserDefOne *ud1test, *ud1a, *ud1b;
2255cd5f0d0SMichael Roth     UserDefOneList *ud1list;
2265cd5f0d0SMichael Roth 
2275cd5f0d0SMichael Roth     ud1test = g_malloc0(sizeof(UserDefOne));
228ddf21908SEric Blake     ud1test->integer = 42;
2295cd5f0d0SMichael Roth     ud1test->string = g_strdup("hi there 42");
2305cd5f0d0SMichael Roth 
2315cd5f0d0SMichael Roth     qapi_free_UserDefOne(ud1test);
2325cd5f0d0SMichael Roth 
2335cd5f0d0SMichael Roth     ud1a = g_malloc0(sizeof(UserDefOne));
234ddf21908SEric Blake     ud1a->integer = 43;
2355cd5f0d0SMichael Roth     ud1a->string = g_strdup("hi there 43");
2365cd5f0d0SMichael Roth 
2375cd5f0d0SMichael Roth     ud1b = g_malloc0(sizeof(UserDefOne));
238ddf21908SEric Blake     ud1b->integer = 44;
2395cd5f0d0SMichael Roth     ud1b->string = g_strdup("hi there 44");
2405cd5f0d0SMichael Roth 
2415cd5f0d0SMichael Roth     ud1list = g_malloc0(sizeof(UserDefOneList));
2425cd5f0d0SMichael Roth     ud1list->value = ud1a;
2435cd5f0d0SMichael Roth     ud1list->next = g_malloc0(sizeof(UserDefOneList));
2445cd5f0d0SMichael Roth     ud1list->next->value = ud1b;
2455cd5f0d0SMichael Roth 
2465cd5f0d0SMichael Roth     qapi_free_UserDefOneList(ud1list);
2475cd5f0d0SMichael Roth }
2485cd5f0d0SMichael Roth 
249d98150f0SLaszlo Ersek /* test generated deallocation on an object whose construction was prematurely
250d98150f0SLaszlo Ersek  * terminated due to an error */
251d98150f0SLaszlo Ersek static void test_dealloc_partial(void)
252d98150f0SLaszlo Ersek {
253d98150f0SLaszlo Ersek     static const char text[] = "don't leak me";
254d98150f0SLaszlo Ersek 
255d98150f0SLaszlo Ersek     UserDefTwo *ud2 = NULL;
256d98150f0SLaszlo Ersek     Error *err = NULL;
257d98150f0SLaszlo Ersek 
258d98150f0SLaszlo Ersek     /* create partial object */
259d98150f0SLaszlo Ersek     {
260d98150f0SLaszlo Ersek         QDict *ud2_dict;
261b70ce101SEric Blake         Visitor *v;
262d98150f0SLaszlo Ersek 
263d98150f0SLaszlo Ersek         ud2_dict = qdict_new();
26446f5ac20SEric Blake         qdict_put_str(ud2_dict, "string0", text);
265d98150f0SLaszlo Ersek 
266048abb7bSMarkus Armbruster         v = qobject_input_visitor_new(QOBJECT(ud2_dict));
267b70ce101SEric Blake         visit_type_UserDefTwo(v, NULL, &ud2, &err);
268b70ce101SEric Blake         visit_free(v);
269cb3e7f08SMarc-André Lureau         qobject_unref(ud2_dict);
270d98150f0SLaszlo Ersek     }
271d98150f0SLaszlo Ersek 
27268ab47e4SEric Blake     /* verify that visit_type_XXX() cleans up properly on error */
273a12a5a1aSEric Blake     error_free_or_abort(&err);
27468ab47e4SEric Blake     assert(!ud2);
27568ab47e4SEric Blake 
27668ab47e4SEric Blake     /* Manually create a partial object, leaving ud2->dict1 at NULL */
27768ab47e4SEric Blake     ud2 = g_new0(UserDefTwo, 1);
27868ab47e4SEric Blake     ud2->string0 = g_strdup(text);
279d98150f0SLaszlo Ersek 
280d98150f0SLaszlo Ersek     /* tear down partial object */
281d98150f0SLaszlo Ersek     qapi_free_UserDefTwo(ud2);
282d98150f0SLaszlo Ersek }
283d98150f0SLaszlo Ersek 
284d98150f0SLaszlo Ersek 
28569ed8366SMichael Roth int main(int argc, char **argv)
28669ed8366SMichael Roth {
28769ed8366SMichael Roth     g_test_init(&argc, &argv, NULL);
28869ed8366SMichael Roth 
289*214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dispatch_cmd", test_dispatch_cmd);
290*214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dispatch_cmd_failure", test_dispatch_cmd_failure);
291*214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io);
292*214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dealloc_types", test_dealloc_types);
293*214e4a5bSMarc-André Lureau     g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial);
29469ed8366SMichael Roth 
2951527badbSMarkus Armbruster     test_qmp_init_marshal(&qmp_commands);
29669ed8366SMichael Roth     g_test_run();
29769ed8366SMichael Roth 
29869ed8366SMichael Roth     return 0;
29969ed8366SMichael Roth }
300