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