xref: /qemu/tests/unit/test-qmp-cmds.c (revision eb815e248f50cde9ab86eddd57eca5019b71ca78)
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"
11*eb815e24SMarkus 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 
19972a1101SEric Blake Empty2 *qmp_user_def_cmd0(Error **errp)
20972a1101SEric Blake {
21972a1101SEric Blake     return g_new0(Empty2, 1);
22972a1101SEric Blake }
23972a1101SEric Blake 
2469ed8366SMichael Roth void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
2569ed8366SMichael Roth {
2669ed8366SMichael Roth }
2769ed8366SMichael Roth 
28ab22ad96SMarkus Armbruster UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
29ab22ad96SMarkus Armbruster                               bool has_udb1, UserDefOne *ud1b,
30ab22ad96SMarkus Armbruster                               Error **errp)
3169ed8366SMichael Roth {
3269ed8366SMichael Roth     UserDefTwo *ret;
337267c094SAnthony Liguori     UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
347267c094SAnthony Liguori     UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
3569ed8366SMichael Roth 
3669ed8366SMichael Roth     ud1c->string = strdup(ud1a->string);
37ddf21908SEric Blake     ud1c->integer = ud1a->integer;
38ab22ad96SMarkus Armbruster     ud1d->string = strdup(has_udb1 ? ud1b->string : "blah0");
39ddf21908SEric Blake     ud1d->integer = has_udb1 ? ud1b->integer : 0;
4069ed8366SMichael Roth 
41b6fcf32dSEric Blake     ret = g_new0(UserDefTwo, 1);
42b6fcf32dSEric Blake     ret->string0 = strdup("blah1");
436446a592SEric Blake     ret->dict1 = g_new0(UserDefTwoDict, 1);
446446a592SEric Blake     ret->dict1->string1 = strdup("blah2");
456446a592SEric Blake     ret->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
466446a592SEric Blake     ret->dict1->dict2->userdef = ud1c;
476446a592SEric Blake     ret->dict1->dict2->string = strdup("blah3");
486446a592SEric Blake     ret->dict1->dict3 = g_new0(UserDefTwoDictDict, 1);
496446a592SEric Blake     ret->dict1->has_dict3 = true;
506446a592SEric Blake     ret->dict1->dict3->userdef = ud1d;
516446a592SEric Blake     ret->dict1->dict3->string = strdup("blah4");
5269ed8366SMichael Roth 
5369ed8366SMichael Roth     return ret;
5469ed8366SMichael Roth }
5569ed8366SMichael Roth 
56cae95eaeSEric Blake int64_t qmp_guest_get_time(int64_t a, bool has_b, int64_t b, Error **errp)
57c2216a8aSMarkus Armbruster {
58c2216a8aSMarkus Armbruster     return a + (has_b ? b : 0);
59c2216a8aSMarkus Armbruster }
60c2216a8aSMarkus Armbruster 
6128770e05SMarkus Armbruster QObject *qmp_guest_sync(QObject *arg, Error **errp)
6228770e05SMarkus Armbruster {
6328770e05SMarkus Armbruster     return arg;
6428770e05SMarkus Armbruster }
6528770e05SMarkus Armbruster 
66c818408eSEric Blake void qmp_boxed_struct(UserDefZero *arg, Error **errp)
67c818408eSEric Blake {
68c818408eSEric Blake }
69c818408eSEric Blake 
70c818408eSEric Blake void qmp_boxed_union(UserDefNativeListUnion *arg, Error **errp)
71c818408eSEric Blake {
72c818408eSEric Blake }
73c818408eSEric Blake 
74e3c4c3d7SEric Blake __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
75e3c4c3d7SEric Blake                                               __org_qemu_x_StructList *b,
76e3c4c3d7SEric Blake                                               __org_qemu_x_Union2 *c,
77e3c4c3d7SEric Blake                                               __org_qemu_x_Alt *d,
78e3c4c3d7SEric Blake                                               Error **errp)
79e3c4c3d7SEric Blake {
80e3c4c3d7SEric Blake     __org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
81e3c4c3d7SEric Blake 
82c363acefSEric Blake     ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
8332bafa8fSEric Blake     ret->u.__org_qemu_x_branch.data = strdup("blah1");
84e3c4c3d7SEric Blake 
85c43567c1SEric Blake     /* Also test that 'wchar-t' was munged to 'q_wchar_t' */
86c43567c1SEric Blake     if (b && b->value && !b->value->has_q_wchar_t) {
87c43567c1SEric Blake         b->value->q_wchar_t = 1;
88c43567c1SEric Blake     }
89e3c4c3d7SEric Blake     return ret;
90e3c4c3d7SEric Blake }
91e3c4c3d7SEric Blake 
92e3c4c3d7SEric Blake 
9369ed8366SMichael Roth /* test commands with no input and no return value */
9469ed8366SMichael Roth static void test_dispatch_cmd(void)
9569ed8366SMichael Roth {
9669ed8366SMichael Roth     QDict *req = qdict_new();
9769ed8366SMichael Roth     QObject *resp;
9869ed8366SMichael Roth 
9946f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd");
10069ed8366SMichael Roth 
1011527badbSMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
10269ed8366SMichael Roth     assert(resp != NULL);
10369ed8366SMichael Roth     assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
10469ed8366SMichael Roth 
10569ed8366SMichael Roth     qobject_decref(resp);
10669ed8366SMichael Roth     QDECREF(req);
10769ed8366SMichael Roth }
10869ed8366SMichael Roth 
10969ed8366SMichael Roth /* test commands that return an error due to invalid parameters */
11051009170SPeter Maydell static void test_dispatch_cmd_failure(void)
11169ed8366SMichael Roth {
11269ed8366SMichael Roth     QDict *req = qdict_new();
113a0067da1SMarc-André Lureau     QDict *args = qdict_new();
11469ed8366SMichael Roth     QObject *resp;
11569ed8366SMichael Roth 
11646f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
11769ed8366SMichael Roth 
1181527badbSMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
11969ed8366SMichael Roth     assert(resp != NULL);
12069ed8366SMichael Roth     assert(qdict_haskey(qobject_to_qdict(resp), "error"));
12169ed8366SMichael Roth 
12269ed8366SMichael Roth     qobject_decref(resp);
12369ed8366SMichael Roth     QDECREF(req);
124a0067da1SMarc-André Lureau 
125a0067da1SMarc-André Lureau     /* check that with extra arguments it throws an error */
126a0067da1SMarc-André Lureau     req = qdict_new();
12746f5ac20SEric Blake     qdict_put_int(args, "a", 66);
128a0067da1SMarc-André Lureau     qdict_put(req, "arguments", args);
129a0067da1SMarc-André Lureau 
13046f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd");
131a0067da1SMarc-André Lureau 
1321527badbSMarkus Armbruster     resp = qmp_dispatch(&qmp_commands, QOBJECT(req));
133a0067da1SMarc-André Lureau     assert(resp != NULL);
134a0067da1SMarc-André Lureau     assert(qdict_haskey(qobject_to_qdict(resp), "error"));
135a0067da1SMarc-André Lureau 
136a0067da1SMarc-André Lureau     qobject_decref(resp);
137a0067da1SMarc-André Lureau     QDECREF(req);
13869ed8366SMichael Roth }
13969ed8366SMichael Roth 
140357765feSMarkus Armbruster static QObject *test_qmp_dispatch(QDict *req)
141357765feSMarkus Armbruster {
142357765feSMarkus Armbruster     QObject *resp_obj;
143357765feSMarkus Armbruster     QDict *resp;
144357765feSMarkus Armbruster     QObject *ret;
145357765feSMarkus Armbruster 
1461527badbSMarkus Armbruster     resp_obj = qmp_dispatch(&qmp_commands, QOBJECT(req));
147357765feSMarkus Armbruster     assert(resp_obj);
148357765feSMarkus Armbruster     resp = qobject_to_qdict(resp_obj);
149357765feSMarkus Armbruster     assert(resp && !qdict_haskey(resp, "error"));
150357765feSMarkus Armbruster     ret = qdict_get(resp, "return");
151357765feSMarkus Armbruster     assert(ret);
152357765feSMarkus Armbruster     qobject_incref(ret);
153357765feSMarkus Armbruster     qobject_decref(resp_obj);
154357765feSMarkus Armbruster     return ret;
155357765feSMarkus Armbruster }
156357765feSMarkus Armbruster 
15769ed8366SMichael Roth /* test commands that involve both input parameters and return values */
15869ed8366SMichael Roth static void test_dispatch_cmd_io(void)
15969ed8366SMichael Roth {
16069ed8366SMichael Roth     QDict *req = qdict_new();
16169ed8366SMichael Roth     QDict *args = qdict_new();
162c2216a8aSMarkus Armbruster     QDict *args3 = qdict_new();
16369ed8366SMichael Roth     QDict *ud1a = qdict_new();
16469ed8366SMichael Roth     QDict *ud1b = qdict_new();
165357765feSMarkus Armbruster     QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
166357765feSMarkus Armbruster     QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
16701b2ffceSMarc-André Lureau     QNum *ret3;
16801b2ffceSMarc-André Lureau     int64_t val;
16969ed8366SMichael Roth 
17046f5ac20SEric Blake     qdict_put_int(ud1a, "integer", 42);
17146f5ac20SEric Blake     qdict_put_str(ud1a, "string", "hello");
17246f5ac20SEric Blake     qdict_put_int(ud1b, "integer", 422);
17346f5ac20SEric Blake     qdict_put_str(ud1b, "string", "hello2");
174de6e7951SEric Blake     qdict_put(args, "ud1a", ud1a);
175de6e7951SEric Blake     qdict_put(args, "ud1b", ud1b);
176de6e7951SEric Blake     qdict_put(req, "arguments", args);
17746f5ac20SEric Blake     qdict_put_str(req, "execute", "user_def_cmd2");
17869ed8366SMichael Roth 
179357765feSMarkus Armbruster     ret = qobject_to_qdict(test_qmp_dispatch(req));
18069ed8366SMichael Roth 
181b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret, "string0"), "blah1"));
182b6fcf32dSEric Blake     ret_dict = qdict_get_qdict(ret, "dict1");
183b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret_dict, "string1"), "blah2"));
184b6fcf32dSEric Blake     ret_dict_dict = qdict_get_qdict(ret_dict, "dict2");
185357765feSMarkus Armbruster     ret_dict_dict_userdef = qdict_get_qdict(ret_dict_dict, "userdef");
186357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict_userdef, "integer") == 42);
187357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict_userdef, "string"), "hello"));
188357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict, "string"), "blah3"));
189b6fcf32dSEric Blake     ret_dict_dict2 = qdict_get_qdict(ret_dict, "dict3");
190357765feSMarkus Armbruster     ret_dict_dict2_userdef = qdict_get_qdict(ret_dict_dict2, "userdef");
191357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict2_userdef, "integer") == 422);
192357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2_userdef, "string"), "hello2"));
193357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2, "string"), "blah4"));
194357765feSMarkus Armbruster     QDECREF(ret);
195c2216a8aSMarkus Armbruster 
19646f5ac20SEric Blake     qdict_put_int(args3, "a", 66);
197c2216a8aSMarkus Armbruster     qdict_put(req, "arguments", args3);
19846f5ac20SEric Blake     qdict_put_str(req, "execute", "guest-get-time");
199c2216a8aSMarkus Armbruster 
20001b2ffceSMarc-André Lureau     ret3 = qobject_to_qnum(test_qmp_dispatch(req));
20101b2ffceSMarc-André Lureau     g_assert(qnum_get_try_int(ret3, &val));
20201b2ffceSMarc-André Lureau     g_assert_cmpint(val, ==, 66);
2032a7a1a56SLuiz Capitulino     QDECREF(ret3);
204c2216a8aSMarkus Armbruster 
20569ed8366SMichael Roth     QDECREF(req);
20669ed8366SMichael Roth }
20769ed8366SMichael Roth 
2085cd5f0d0SMichael Roth /* test generated dealloc functions for generated types */
2095cd5f0d0SMichael Roth static void test_dealloc_types(void)
2105cd5f0d0SMichael Roth {
2115cd5f0d0SMichael Roth     UserDefOne *ud1test, *ud1a, *ud1b;
2125cd5f0d0SMichael Roth     UserDefOneList *ud1list;
2135cd5f0d0SMichael Roth 
2145cd5f0d0SMichael Roth     ud1test = g_malloc0(sizeof(UserDefOne));
215ddf21908SEric Blake     ud1test->integer = 42;
2165cd5f0d0SMichael Roth     ud1test->string = g_strdup("hi there 42");
2175cd5f0d0SMichael Roth 
2185cd5f0d0SMichael Roth     qapi_free_UserDefOne(ud1test);
2195cd5f0d0SMichael Roth 
2205cd5f0d0SMichael Roth     ud1a = g_malloc0(sizeof(UserDefOne));
221ddf21908SEric Blake     ud1a->integer = 43;
2225cd5f0d0SMichael Roth     ud1a->string = g_strdup("hi there 43");
2235cd5f0d0SMichael Roth 
2245cd5f0d0SMichael Roth     ud1b = g_malloc0(sizeof(UserDefOne));
225ddf21908SEric Blake     ud1b->integer = 44;
2265cd5f0d0SMichael Roth     ud1b->string = g_strdup("hi there 44");
2275cd5f0d0SMichael Roth 
2285cd5f0d0SMichael Roth     ud1list = g_malloc0(sizeof(UserDefOneList));
2295cd5f0d0SMichael Roth     ud1list->value = ud1a;
2305cd5f0d0SMichael Roth     ud1list->next = g_malloc0(sizeof(UserDefOneList));
2315cd5f0d0SMichael Roth     ud1list->next->value = ud1b;
2325cd5f0d0SMichael Roth 
2335cd5f0d0SMichael Roth     qapi_free_UserDefOneList(ud1list);
2345cd5f0d0SMichael Roth }
2355cd5f0d0SMichael Roth 
236d98150f0SLaszlo Ersek /* test generated deallocation on an object whose construction was prematurely
237d98150f0SLaszlo Ersek  * terminated due to an error */
238d98150f0SLaszlo Ersek static void test_dealloc_partial(void)
239d98150f0SLaszlo Ersek {
240d98150f0SLaszlo Ersek     static const char text[] = "don't leak me";
241d98150f0SLaszlo Ersek 
242d98150f0SLaszlo Ersek     UserDefTwo *ud2 = NULL;
243d98150f0SLaszlo Ersek     Error *err = NULL;
244d98150f0SLaszlo Ersek 
245d98150f0SLaszlo Ersek     /* create partial object */
246d98150f0SLaszlo Ersek     {
247d98150f0SLaszlo Ersek         QDict *ud2_dict;
248b70ce101SEric Blake         Visitor *v;
249d98150f0SLaszlo Ersek 
250d98150f0SLaszlo Ersek         ud2_dict = qdict_new();
25146f5ac20SEric Blake         qdict_put_str(ud2_dict, "string0", text);
252d98150f0SLaszlo Ersek 
253048abb7bSMarkus Armbruster         v = qobject_input_visitor_new(QOBJECT(ud2_dict));
254b70ce101SEric Blake         visit_type_UserDefTwo(v, NULL, &ud2, &err);
255b70ce101SEric Blake         visit_free(v);
256d98150f0SLaszlo Ersek         QDECREF(ud2_dict);
257d98150f0SLaszlo Ersek     }
258d98150f0SLaszlo Ersek 
25968ab47e4SEric Blake     /* verify that visit_type_XXX() cleans up properly on error */
260a12a5a1aSEric Blake     error_free_or_abort(&err);
26168ab47e4SEric Blake     assert(!ud2);
26268ab47e4SEric Blake 
26368ab47e4SEric Blake     /* Manually create a partial object, leaving ud2->dict1 at NULL */
26468ab47e4SEric Blake     ud2 = g_new0(UserDefTwo, 1);
26568ab47e4SEric Blake     ud2->string0 = g_strdup(text);
266d98150f0SLaszlo Ersek 
267d98150f0SLaszlo Ersek     /* tear down partial object */
268d98150f0SLaszlo Ersek     qapi_free_UserDefTwo(ud2);
269d98150f0SLaszlo Ersek }
270d98150f0SLaszlo Ersek 
271d98150f0SLaszlo Ersek 
27269ed8366SMichael Roth int main(int argc, char **argv)
27369ed8366SMichael Roth {
27469ed8366SMichael Roth     g_test_init(&argc, &argv, NULL);
27569ed8366SMichael Roth 
27669ed8366SMichael Roth     g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
27751009170SPeter Maydell     g_test_add_func("/0.15/dispatch_cmd_failure", test_dispatch_cmd_failure);
27869ed8366SMichael Roth     g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
2795cd5f0d0SMichael Roth     g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
280d98150f0SLaszlo Ersek     g_test_add_func("/0.15/dealloc_partial", test_dealloc_partial);
28169ed8366SMichael Roth 
2821527badbSMarkus Armbruster     test_qmp_init_marshal(&qmp_commands);
28369ed8366SMichael Roth     g_test_run();
28469ed8366SMichael Roth 
28569ed8366SMichael Roth     return 0;
28669ed8366SMichael Roth }
287