xref: /qemu/tests/unit/test-qmp-cmds.c (revision 681c28a33e305923a717815808056d2d5a89c8f9)
1*681c28a3SPeter Maydell #include "qemu/osdep.h"
269ed8366SMichael Roth #include <glib.h>
379ee7df8SPaolo Bonzini #include "qemu-common.h"
47b1b5d19SPaolo Bonzini #include "qapi/qmp/types.h"
569ed8366SMichael Roth #include "test-qmp-commands.h"
67b1b5d19SPaolo Bonzini #include "qapi/qmp/dispatch.h"
71de7afc9SPaolo Bonzini #include "qemu/module.h"
8d98150f0SLaszlo Ersek #include "qapi/qmp-input-visitor.h"
9d98150f0SLaszlo Ersek #include "tests/test-qapi-types.h"
10d98150f0SLaszlo Ersek #include "tests/test-qapi-visit.h"
1169ed8366SMichael Roth 
1269ed8366SMichael Roth void qmp_user_def_cmd(Error **errp)
1369ed8366SMichael Roth {
1469ed8366SMichael Roth }
1569ed8366SMichael Roth 
1669ed8366SMichael Roth void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
1769ed8366SMichael Roth {
1869ed8366SMichael Roth }
1969ed8366SMichael Roth 
20ab22ad96SMarkus Armbruster UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
21ab22ad96SMarkus Armbruster                               bool has_udb1, UserDefOne *ud1b,
22ab22ad96SMarkus Armbruster                               Error **errp)
2369ed8366SMichael Roth {
2469ed8366SMichael Roth     UserDefTwo *ret;
257267c094SAnthony Liguori     UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
267267c094SAnthony Liguori     UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
2769ed8366SMichael Roth 
2869ed8366SMichael Roth     ud1c->string = strdup(ud1a->string);
29ddf21908SEric Blake     ud1c->integer = ud1a->integer;
30ab22ad96SMarkus Armbruster     ud1d->string = strdup(has_udb1 ? ud1b->string : "blah0");
31ddf21908SEric Blake     ud1d->integer = has_udb1 ? ud1b->integer : 0;
3269ed8366SMichael Roth 
33b6fcf32dSEric Blake     ret = g_new0(UserDefTwo, 1);
34b6fcf32dSEric Blake     ret->string0 = strdup("blah1");
356446a592SEric Blake     ret->dict1 = g_new0(UserDefTwoDict, 1);
366446a592SEric Blake     ret->dict1->string1 = strdup("blah2");
376446a592SEric Blake     ret->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
386446a592SEric Blake     ret->dict1->dict2->userdef = ud1c;
396446a592SEric Blake     ret->dict1->dict2->string = strdup("blah3");
406446a592SEric Blake     ret->dict1->dict3 = g_new0(UserDefTwoDictDict, 1);
416446a592SEric Blake     ret->dict1->has_dict3 = true;
426446a592SEric Blake     ret->dict1->dict3->userdef = ud1d;
436446a592SEric Blake     ret->dict1->dict3->string = strdup("blah4");
4469ed8366SMichael Roth 
4569ed8366SMichael Roth     return ret;
4669ed8366SMichael Roth }
4769ed8366SMichael Roth 
48cae95eaeSEric Blake int64_t qmp_guest_get_time(int64_t a, bool has_b, int64_t b, Error **errp)
49c2216a8aSMarkus Armbruster {
50c2216a8aSMarkus Armbruster     return a + (has_b ? b : 0);
51c2216a8aSMarkus Armbruster }
52c2216a8aSMarkus Armbruster 
5328770e05SMarkus Armbruster QObject *qmp_guest_sync(QObject *arg, Error **errp)
5428770e05SMarkus Armbruster {
5528770e05SMarkus Armbruster     return arg;
5628770e05SMarkus Armbruster }
5728770e05SMarkus Armbruster 
58e3c4c3d7SEric Blake __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
59e3c4c3d7SEric Blake                                               __org_qemu_x_StructList *b,
60e3c4c3d7SEric Blake                                               __org_qemu_x_Union2 *c,
61e3c4c3d7SEric Blake                                               __org_qemu_x_Alt *d,
62e3c4c3d7SEric Blake                                               Error **errp)
63e3c4c3d7SEric Blake {
64e3c4c3d7SEric Blake     __org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
65e3c4c3d7SEric Blake 
66c363acefSEric Blake     ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
67c363acefSEric Blake     ret->u.__org_qemu_x_branch = strdup("blah1");
68e3c4c3d7SEric Blake 
69c43567c1SEric Blake     /* Also test that 'wchar-t' was munged to 'q_wchar_t' */
70c43567c1SEric Blake     if (b && b->value && !b->value->has_q_wchar_t) {
71c43567c1SEric Blake         b->value->q_wchar_t = 1;
72c43567c1SEric Blake     }
73e3c4c3d7SEric Blake     return ret;
74e3c4c3d7SEric Blake }
75e3c4c3d7SEric Blake 
76e3c4c3d7SEric Blake 
7769ed8366SMichael Roth /* test commands with no input and no return value */
7869ed8366SMichael Roth static void test_dispatch_cmd(void)
7969ed8366SMichael Roth {
8069ed8366SMichael Roth     QDict *req = qdict_new();
8169ed8366SMichael Roth     QObject *resp;
8269ed8366SMichael Roth 
8369ed8366SMichael Roth     qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd")));
8469ed8366SMichael Roth 
8569ed8366SMichael Roth     resp = qmp_dispatch(QOBJECT(req));
8669ed8366SMichael Roth     assert(resp != NULL);
8769ed8366SMichael Roth     assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
8869ed8366SMichael Roth 
8969ed8366SMichael Roth     qobject_decref(resp);
9069ed8366SMichael Roth     QDECREF(req);
9169ed8366SMichael Roth }
9269ed8366SMichael Roth 
9369ed8366SMichael Roth /* test commands that return an error due to invalid parameters */
9469ed8366SMichael Roth static void test_dispatch_cmd_error(void)
9569ed8366SMichael Roth {
9669ed8366SMichael Roth     QDict *req = qdict_new();
9769ed8366SMichael Roth     QObject *resp;
9869ed8366SMichael Roth 
9969ed8366SMichael Roth     qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
10069ed8366SMichael Roth 
10169ed8366SMichael Roth     resp = qmp_dispatch(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 
109357765feSMarkus Armbruster static QObject *test_qmp_dispatch(QDict *req)
110357765feSMarkus Armbruster {
111357765feSMarkus Armbruster     QObject *resp_obj;
112357765feSMarkus Armbruster     QDict *resp;
113357765feSMarkus Armbruster     QObject *ret;
114357765feSMarkus Armbruster 
115357765feSMarkus Armbruster     resp_obj = qmp_dispatch(QOBJECT(req));
116357765feSMarkus Armbruster     assert(resp_obj);
117357765feSMarkus Armbruster     resp = qobject_to_qdict(resp_obj);
118357765feSMarkus Armbruster     assert(resp && !qdict_haskey(resp, "error"));
119357765feSMarkus Armbruster     ret = qdict_get(resp, "return");
120357765feSMarkus Armbruster     assert(ret);
121357765feSMarkus Armbruster     qobject_incref(ret);
122357765feSMarkus Armbruster     qobject_decref(resp_obj);
123357765feSMarkus Armbruster     return ret;
124357765feSMarkus Armbruster }
125357765feSMarkus Armbruster 
12669ed8366SMichael Roth /* test commands that involve both input parameters and return values */
12769ed8366SMichael Roth static void test_dispatch_cmd_io(void)
12869ed8366SMichael Roth {
12969ed8366SMichael Roth     QDict *req = qdict_new();
13069ed8366SMichael Roth     QDict *args = qdict_new();
131c2216a8aSMarkus Armbruster     QDict *args3 = qdict_new();
13269ed8366SMichael Roth     QDict *ud1a = qdict_new();
13369ed8366SMichael Roth     QDict *ud1b = qdict_new();
134357765feSMarkus Armbruster     QDict *ret, *ret_dict, *ret_dict_dict, *ret_dict_dict_userdef;
135357765feSMarkus Armbruster     QDict *ret_dict_dict2, *ret_dict_dict2_userdef;
136c2216a8aSMarkus Armbruster     QInt *ret3;
13769ed8366SMichael Roth 
13869ed8366SMichael Roth     qdict_put_obj(ud1a, "integer", QOBJECT(qint_from_int(42)));
13969ed8366SMichael Roth     qdict_put_obj(ud1a, "string", QOBJECT(qstring_from_str("hello")));
14069ed8366SMichael Roth     qdict_put_obj(ud1b, "integer", QOBJECT(qint_from_int(422)));
14169ed8366SMichael Roth     qdict_put_obj(ud1b, "string", QOBJECT(qstring_from_str("hello2")));
14269ed8366SMichael Roth     qdict_put_obj(args, "ud1a", QOBJECT(ud1a));
14369ed8366SMichael Roth     qdict_put_obj(args, "ud1b", QOBJECT(ud1b));
14469ed8366SMichael Roth     qdict_put_obj(req, "arguments", QOBJECT(args));
14569ed8366SMichael Roth     qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
14669ed8366SMichael Roth 
147357765feSMarkus Armbruster     ret = qobject_to_qdict(test_qmp_dispatch(req));
14869ed8366SMichael Roth 
149b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret, "string0"), "blah1"));
150b6fcf32dSEric Blake     ret_dict = qdict_get_qdict(ret, "dict1");
151b6fcf32dSEric Blake     assert(!strcmp(qdict_get_str(ret_dict, "string1"), "blah2"));
152b6fcf32dSEric Blake     ret_dict_dict = qdict_get_qdict(ret_dict, "dict2");
153357765feSMarkus Armbruster     ret_dict_dict_userdef = qdict_get_qdict(ret_dict_dict, "userdef");
154357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict_userdef, "integer") == 42);
155357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict_userdef, "string"), "hello"));
156357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict, "string"), "blah3"));
157b6fcf32dSEric Blake     ret_dict_dict2 = qdict_get_qdict(ret_dict, "dict3");
158357765feSMarkus Armbruster     ret_dict_dict2_userdef = qdict_get_qdict(ret_dict_dict2, "userdef");
159357765feSMarkus Armbruster     assert(qdict_get_int(ret_dict_dict2_userdef, "integer") == 422);
160357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2_userdef, "string"), "hello2"));
161357765feSMarkus Armbruster     assert(!strcmp(qdict_get_str(ret_dict_dict2, "string"), "blah4"));
162357765feSMarkus Armbruster     QDECREF(ret);
163c2216a8aSMarkus Armbruster 
164c2216a8aSMarkus Armbruster     qdict_put(args3, "a", qint_from_int(66));
165c2216a8aSMarkus Armbruster     qdict_put(req, "arguments", args3);
166cae95eaeSEric Blake     qdict_put(req, "execute", qstring_from_str("guest-get-time"));
167c2216a8aSMarkus Armbruster 
168c2216a8aSMarkus Armbruster     ret3 = qobject_to_qint(test_qmp_dispatch(req));
169c2216a8aSMarkus Armbruster     assert(qint_get_int(ret3) == 66);
1702a7a1a56SLuiz Capitulino     QDECREF(ret3);
171c2216a8aSMarkus Armbruster 
17269ed8366SMichael Roth     QDECREF(req);
17369ed8366SMichael Roth }
17469ed8366SMichael Roth 
1755cd5f0d0SMichael Roth /* test generated dealloc functions for generated types */
1765cd5f0d0SMichael Roth static void test_dealloc_types(void)
1775cd5f0d0SMichael Roth {
1785cd5f0d0SMichael Roth     UserDefOne *ud1test, *ud1a, *ud1b;
1795cd5f0d0SMichael Roth     UserDefOneList *ud1list;
1805cd5f0d0SMichael Roth 
1815cd5f0d0SMichael Roth     ud1test = g_malloc0(sizeof(UserDefOne));
182ddf21908SEric Blake     ud1test->integer = 42;
1835cd5f0d0SMichael Roth     ud1test->string = g_strdup("hi there 42");
1845cd5f0d0SMichael Roth 
1855cd5f0d0SMichael Roth     qapi_free_UserDefOne(ud1test);
1865cd5f0d0SMichael Roth 
1875cd5f0d0SMichael Roth     ud1a = g_malloc0(sizeof(UserDefOne));
188ddf21908SEric Blake     ud1a->integer = 43;
1895cd5f0d0SMichael Roth     ud1a->string = g_strdup("hi there 43");
1905cd5f0d0SMichael Roth 
1915cd5f0d0SMichael Roth     ud1b = g_malloc0(sizeof(UserDefOne));
192ddf21908SEric Blake     ud1b->integer = 44;
1935cd5f0d0SMichael Roth     ud1b->string = g_strdup("hi there 44");
1945cd5f0d0SMichael Roth 
1955cd5f0d0SMichael Roth     ud1list = g_malloc0(sizeof(UserDefOneList));
1965cd5f0d0SMichael Roth     ud1list->value = ud1a;
1975cd5f0d0SMichael Roth     ud1list->next = g_malloc0(sizeof(UserDefOneList));
1985cd5f0d0SMichael Roth     ud1list->next->value = ud1b;
1995cd5f0d0SMichael Roth 
2005cd5f0d0SMichael Roth     qapi_free_UserDefOneList(ud1list);
2015cd5f0d0SMichael Roth }
2025cd5f0d0SMichael Roth 
203d98150f0SLaszlo Ersek /* test generated deallocation on an object whose construction was prematurely
204d98150f0SLaszlo Ersek  * terminated due to an error */
205d98150f0SLaszlo Ersek static void test_dealloc_partial(void)
206d98150f0SLaszlo Ersek {
207d98150f0SLaszlo Ersek     static const char text[] = "don't leak me";
208d98150f0SLaszlo Ersek 
209d98150f0SLaszlo Ersek     UserDefTwo *ud2 = NULL;
210d98150f0SLaszlo Ersek     Error *err = NULL;
211d98150f0SLaszlo Ersek 
212d98150f0SLaszlo Ersek     /* create partial object */
213d98150f0SLaszlo Ersek     {
214d98150f0SLaszlo Ersek         QDict *ud2_dict;
215d98150f0SLaszlo Ersek         QmpInputVisitor *qiv;
216d98150f0SLaszlo Ersek 
217d98150f0SLaszlo Ersek         ud2_dict = qdict_new();
218b6fcf32dSEric Blake         qdict_put_obj(ud2_dict, "string0", QOBJECT(qstring_from_str(text)));
219d98150f0SLaszlo Ersek 
220d98150f0SLaszlo Ersek         qiv = qmp_input_visitor_new(QOBJECT(ud2_dict));
22151e72bc1SEric Blake         visit_type_UserDefTwo(qmp_input_get_visitor(qiv), NULL, &ud2, &err);
222d98150f0SLaszlo Ersek         qmp_input_visitor_cleanup(qiv);
223d98150f0SLaszlo Ersek         QDECREF(ud2_dict);
224d98150f0SLaszlo Ersek     }
225d98150f0SLaszlo Ersek 
226d98150f0SLaszlo Ersek     /* verify partial success */
227d98150f0SLaszlo Ersek     assert(ud2 != NULL);
228b6fcf32dSEric Blake     assert(ud2->string0 != NULL);
229b6fcf32dSEric Blake     assert(strcmp(ud2->string0, text) == 0);
2306446a592SEric Blake     assert(ud2->dict1 == NULL);
231d98150f0SLaszlo Ersek 
232d98150f0SLaszlo Ersek     /* confirm & release construction error */
233a12a5a1aSEric Blake     error_free_or_abort(&err);
234d98150f0SLaszlo Ersek 
235d98150f0SLaszlo Ersek     /* tear down partial object */
236d98150f0SLaszlo Ersek     qapi_free_UserDefTwo(ud2);
237d98150f0SLaszlo Ersek }
238d98150f0SLaszlo Ersek 
239d98150f0SLaszlo Ersek 
24069ed8366SMichael Roth int main(int argc, char **argv)
24169ed8366SMichael Roth {
24269ed8366SMichael Roth     g_test_init(&argc, &argv, NULL);
24369ed8366SMichael Roth 
24469ed8366SMichael Roth     g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
24569ed8366SMichael Roth     g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
24669ed8366SMichael Roth     g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
2475cd5f0d0SMichael Roth     g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
248d98150f0SLaszlo Ersek     g_test_add_func("/0.15/dealloc_partial", test_dealloc_partial);
24969ed8366SMichael Roth 
25069ed8366SMichael Roth     module_call_init(MODULE_INIT_QAPI);
25169ed8366SMichael Roth     g_test_run();
25269ed8366SMichael Roth 
25369ed8366SMichael Roth     return 0;
25469ed8366SMichael Roth }
255