@@ -107,6 +107,8 @@
{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
{ 'command': 'boxed', 'box': true, 'data': 'UserDefZero' }
{ 'command': 'boxed2', 'data': 'UserDefNativeListUnion', 'box': true }
+{ 'command': 'user-async', 'data': { 'a': 'int', '*b': 'int' },
+ 'returns': 'UserDefB', 'async': true }
# For testing integer range flattening in opts-visitor. The following schema
# corresponds to the option format:
@@ -48,6 +48,9 @@ object :obj-uint64List-wrapper
member data: uint64List optional=False
object :obj-uint8List-wrapper
member data: uint8List optional=False
+object :obj-user-async-arg
+ member a: int optional=False
+ member b: int optional=True
object :obj-user_def_cmd1-arg
member ud1a: UserDefOne optional=False
object :obj-user_def_cmd2-arg
@@ -196,6 +199,8 @@ command boxed2 UserDefNativeListUnion -> None
gen=True success_response=True box=True
command guest-sync :obj-guest-sync-arg -> any
gen=True success_response=True box=False
+command user-async :obj-user-async-arg -> UserDefB
+ gen=True success_response=True box=False async
command user_def_cmd None -> None
gen=True success_response=True box=False
command user_def_cmd1 :obj-user_def_cmd1-arg -> None
@@ -76,6 +76,35 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
return ret;
}
+static GMainLoop *loop;
+
+static struct AsyncRet {
+ QmpReturn *qret;
+ UserDefB *ret;
+} async_ret;
+
+static gboolean qmp_user_async_idle(gpointer data)
+{
+ struct AsyncRet *ret = (struct AsyncRet *)data;
+
+ qmp_user_async_return(ret->qret, ret->ret);
+
+ g_main_loop_quit(loop);
+
+ return FALSE;
+}
+
+void qmp_user_async(int64_t a, bool has_b, int64_t b, QmpReturn *qret)
+{
+ UserDefB *ret = g_new0(UserDefB, 1);
+
+ ret->intb = a + (has_b ? b : 0);
+
+ async_ret.qret = qret;
+ async_ret.ret = ret;
+ g_idle_add(qmp_user_async_idle, &async_ret);
+}
+
static void dispatch_cmd_return(QmpClient *client, QObject *resp)
{
assert(resp != NULL);
@@ -121,12 +150,15 @@ static void test_dispatch_cmd_error(void)
}
static QObject *ret;
+static char *ret_id;
static void qmp_dispatch_return(QmpClient *client, QObject *resp_obj)
{
QDict *resp = qobject_to_qdict(resp_obj);
assert(resp && !qdict_haskey(resp, "error"));
ret = qdict_get(resp, "return");
+ g_free(ret_id);
+ ret_id = g_strdup(qdict_get_try_str(resp, "id"));
assert(ret);
qobject_incref(ret);
}
@@ -193,6 +225,34 @@ static void test_dispatch_cmd_io(void)
QDECREF(req);
}
+static void test_dispatch_cmd_async(void)
+{
+ QmpClient client;
+ QDict *dret, *req = qdict_new();
+ QDict *args = qdict_new();
+
+ loop = g_main_loop_new(NULL, FALSE);
+ qmp_client_init(&client, qmp_dispatch_return);
+
+ qdict_put(args, "a", qint_from_int(99));
+ qdict_put(req, "arguments", args);
+ qdict_put(req, "id", qstring_from_str("foo99"));
+ qdict_put(req, "execute", qstring_from_str("user-async"));
+
+ qmp_dispatch(&client, QOBJECT(req), NULL);
+
+ g_main_loop_run(loop);
+ g_main_loop_unref(loop);
+
+ g_assert_cmpstr(ret_id, ==, "foo99");
+ dret = qobject_to_qdict(ret);
+ assert(qdict_get_int(dret, "intb") == 99);
+ QDECREF(dret);
+
+ qmp_client_destroy(&client);
+ QDECREF(req);
+}
+
/* test generated dealloc functions for generated types */
static void test_dealloc_types(void)
{
@@ -264,6 +324,7 @@ int main(int argc, char **argv)
g_test_add_func("/qmp/dispatch_cmd", test_dispatch_cmd);
g_test_add_func("/qmp/dispatch_cmd_error", test_dispatch_cmd_error);
g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io);
+ g_test_add_func("/qmp/dispatch_cmd_async", test_dispatch_cmd_async);
g_test_add_func("/qmp/dealloc_types", test_dealloc_types);
g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial);