[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 12/24] tests: add dispatch async tests
From: |
Marc-André Lureau |
Subject: |
[Qemu-devel] [PATCH 12/24] tests: add dispatch async tests |
Date: |
Mon, 10 Oct 2016 13:22:49 +0400 |
Add a few tests to check:
- that async dispatch works
- destroying the client with pending requests
Signed-off-by: Marc-André Lureau <address@hidden>
---
tests/test-qmp-commands.c | 109 ++++++++++++++++++++++++++++++++
tests/qapi-schema/qapi-schema-test.json | 4 ++
tests/qapi-schema/qapi-schema-test.out | 5 ++
3 files changed, 118 insertions(+)
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index fd559f2..cca5555 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -85,6 +85,36 @@ __org_qemu_x_Union1
*qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
return ret;
}
+static GMainLoop *loop;
+
+typedef struct AsyncRet {
+ QmpReturn *qret;
+ UserDefB *ret;
+} AsyncRet;
+
+static gboolean qmp_user_async_idle(gpointer data)
+{
+ struct AsyncRet *async = (struct AsyncRet *)data;
+
+ qmp_user_async_return(async->qret, async->ret);
+ g_free(async);
+
+ g_main_loop_quit(loop);
+
+ return FALSE;
+}
+
+void qmp_user_async(int64_t a, bool has_b, int64_t b, QmpReturn *qret)
+{
+ AsyncRet *async = g_new0(AsyncRet, 1);
+
+ async->ret = g_new0(UserDefB, 1);
+ async->ret->intb = a + (has_b ? b : 0);
+ async->qret = qret;
+
+ g_idle_add(qmp_user_async_idle, async);
+}
+
static void dispatch_cmd_return(QmpClient *client, QObject *resp)
{
assert(resp != NULL);
@@ -142,14 +172,19 @@ static void test_dispatch_cmd_failure(void)
}
static QObject *dispatch_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"));
dispatch_ret = qdict_get(resp, "return");
assert(dispatch_ret);
qobject_incref(dispatch_ret);
+
+ g_free(ret_id);
+ ret_id = g_strdup(qdict_get_try_str(resp, "id"));
}
static QObject *test_qmp_dispatch(QDict *req)
@@ -216,6 +251,76 @@ 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);
+ assert(!dispatch_ret);
+
+ g_main_loop_run(loop);
+ g_main_loop_unref(loop);
+
+ g_assert_cmpstr(ret_id, ==, "foo99");
+ dret = qobject_to_qdict(dispatch_ret);
+ assert(qdict_get_int(dret, "intb") == 99);
+ QDECREF(dret);
+ dispatch_ret = NULL;
+
+ qmp_client_destroy(&client);
+ QDECREF(req);
+}
+
+static void test_destroy_pending_async(void)
+{
+ QmpClient client;
+ QDict *req = qdict_new();
+ QDict *args = qdict_new();
+ QmpReturn *r;
+ int npending = 0;
+
+ 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);
+ qmp_dispatch(&client, QOBJECT(req), NULL);
+ assert(!dispatch_ret);
+ QDECREF(req);
+
+ npending = 0;
+ QLIST_FOREACH(r, &client.pending, link) {
+ npending++;
+ }
+
+ g_assert_cmpint(npending, ==, 2);
+
+ /* destroy with pending async */
+ qmp_client_destroy(&client);
+
+ while (g_main_context_pending(NULL)) {
+ g_main_loop_run(loop);
+ /* no return since the client is gone */
+ assert(!dispatch_ret);
+ }
+
+ g_main_loop_unref(loop);
+}
+
/* test generated dealloc functions for generated types */
static void test_dealloc_types(void)
{
@@ -286,11 +391,15 @@ int main(int argc, char **argv)
g_test_add_func("/qmp/dispatch_cmd", test_dispatch_cmd);
g_test_add_func("/qmp/dispatch_cmd_failure", test_dispatch_cmd_failure);
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/destroy_pending_async", test_destroy_pending_async);
g_test_add_func("/qmp/dealloc_types", test_dealloc_types);
g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial);
module_call_init(MODULE_INIT_QAPI);
g_test_run();
+ g_free(ret_id);
+
return 0;
}
diff --git a/tests/qapi-schema/qapi-schema-test.json
b/tests/qapi-schema/qapi-schema-test.json
index 1719463..a522fab 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -130,6 +130,10 @@
{ 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
{ 'command': 'boxed-union', 'data': 'UserDefNativeListUnion', 'boxed': true }
+# async
+{ '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:
#
diff --git a/tests/qapi-schema/qapi-schema-test.out
b/tests/qapi-schema/qapi-schema-test.out
index 9d99c4e..61b75fd 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -219,11 +219,16 @@ object q_obj_uint64List-wrapper
member data: uint64List optional=False
object q_obj_uint8List-wrapper
member data: uint8List optional=False
+object q_obj_user-async-arg
+ member a: int optional=False
+ member b: int optional=True
object q_obj_user_def_cmd1-arg
member ud1a: UserDefOne optional=False
object q_obj_user_def_cmd2-arg
member ud1a: UserDefOne optional=False
member ud1b: UserDefOne optional=True
+command user-async q_obj_user-async-arg -> UserDefB
+ gen=True success_response=True boxed=False async=True
command user_def_cmd None -> None
gen=True success_response=True boxed=False
command user_def_cmd0 Empty2 -> Empty2
--
2.10.0
- [Qemu-devel] [PATCH 03/24] qmp: teach qmp_dispatch() to take a pre-filled QDict, (continued)
- [Qemu-devel] [PATCH 03/24] qmp: teach qmp_dispatch() to take a pre-filled QDict, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 04/24] qmp: use a return callback for the command reply, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 05/24] qmp: add QmpClient, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 06/24] qmp: add qmp_return_is_cancelled(), Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 07/24] qmp: introduce async command type, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 08/24] qapi: ignore top-level 'id' field, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 10/24] qmp: check that async command have an 'id', Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 09/24] qmp: take 'id' from request, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 11/24] scripts: learn 'async' qapi commands, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 12/24] tests: add dispatch async tests,
Marc-André Lureau <=
- [Qemu-devel] [PATCH 13/24] monitor: add 'async' capability, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 14/24] monitor: add !qmp pre-conditions, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 15/24] monitor: suspend when running async and client has no async, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 16/24] qmp: update qmp-spec about async capability, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 17/24] qtest: add qtest-timeout, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 19/24] tests: add tests for async and non-async clients, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 18/24] qtest: add qtest_init_qmp_caps(), Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 20/24] qapi: improve 'screendump' documentation, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 21/24] console: graphic_hw_update return true if async, Marc-André Lureau, 2016/10/10
- [Qemu-devel] [PATCH 22/24] console: add graphic_hw_update_done(), Marc-André Lureau, 2016/10/10