[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 12/25] tests: add dispatch async tests
From: |
Marc-André Lureau |
Subject: |
[Qemu-devel] [PATCH v2 12/25] tests: add dispatch async tests |
Date: |
Wed, 18 Jan 2017 20:03:19 +0400 |
Add a few tests to check:
- async dispatch
- async command without "id" failure
- destroying the client with pending requests
Signed-off-by: Marc-André Lureau <address@hidden>
---
tests/test-qmp-commands.c | 132 ++++++++++++++++++++++++++++++++
tests/qapi-schema/qapi-schema-test.json | 6 ++
tests/qapi-schema/qapi-schema-test.out | 6 ++
3 files changed, 144 insertions(+)
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index a3c7c590d1..4613a9a4c8 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,97 @@ static void test_dispatch_cmd_io(void)
QDECREF(req);
}
+static void test_dispatch_cmd_async(void)
+{
+ QmpClient client = { .has_async = true };
+ 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_dispatch_cmd_async_no_id(void)
+{
+ QmpClient client = { .has_async = true };
+ QDict *req = qdict_new();
+ QDict *args = qdict_new();
+
+ qmp_client_init(&client, dispatch_cmd_error_return);
+
+ qdict_put(args, "a", qint_from_int(99));
+ qdict_put(req, "arguments", args);
+ qdict_put(req, "execute", qstring_from_str("user-async"));
+
+ qmp_dispatch(&client, QOBJECT(req), NULL);
+
+ assert(!dispatch_ret);
+ assert(QLIST_EMPTY(&client.pending));
+
+ qmp_client_destroy(&client);
+ QDECREF(req);
+}
+
+static void test_destroy_pending_async(void)
+{
+ QmpClient client = { .has_async = true };
+ 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)
{
@@ -287,11 +413,17 @@ 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/dispatch_cmd_async_no_id",
+ test_dispatch_cmd_async_no_id);
+ 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 f4d8cc4230..6fe35bae77 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -292,6 +292,12 @@
{ 'command': 'boxed-union', 'data': 'UserDefNativeListUnion', 'boxed': true }
##
+# @user-async:
+##
+{ 'command': 'user-async', 'data': { 'a': 'int', '*b': 'int' },
+ 'returns': 'UserDefB', 'async': true }
+
+##
# @UserDefOptions:
#
# For testing integer range flattening in opts-visitor. The following schema
diff --git a/tests/qapi-schema/qapi-schema-test.out
b/tests/qapi-schema/qapi-schema-test.out
index bc8d496ff4..5b97906aae 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
@@ -337,6 +342,7 @@ returns something
doc symbol=guest-sync expr=('command', 'guest-sync')
doc symbol=boxed-struct expr=('command', 'boxed-struct')
doc symbol=boxed-union expr=('command', 'boxed-union')
+doc symbol=user-async expr=('command', 'user-async')
doc symbol=UserDefOptions expr=('struct', 'UserDefOptions')
body=
For testing integer range flattening in opts-visitor. The following schema
--
2.11.0.295.gd7dffce1c
- [Qemu-devel] [PATCH v2 02/25] tests: change /0.15/* tests to /qmp/*, (continued)
- [Qemu-devel] [PATCH v2 02/25] tests: change /0.15/* tests to /qmp/*, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 03/25] qmp: teach qmp_dispatch() to take a pre-filled QDict, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 04/25] qmp: use a return callback for the command reply, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 05/25] qmp: add QmpClient, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 06/25] qmp: add qmp_return_is_cancelled(), Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 08/25] qapi: ignore top-level 'id' field, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 07/25] qmp: introduce async command type, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 09/25] qmp: take 'id' from request, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 10/25] qmp: check that async command have an 'id', Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 11/25] scripts: learn 'async' qapi commands, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 12/25] tests: add dispatch async tests,
Marc-André Lureau <=
- [Qemu-devel] [PATCH v2 13/25] monitor: add 'async' capability, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 14/25] monitor: add !qmp pre-conditions, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 15/25] monitor: suspend when running async and client has no async, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 16/25] qmp: update qmp-spec about async capability, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 17/25] qtest: add qtest-timeout, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 19/25] tests: add tests for async and non-async clients, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 18/25] qtest: add qtest_init_qmp_caps(), Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 20/25] qapi: improve 'screendump' documentation, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 21/25] console: graphic_hw_update return true if async, Marc-André Lureau, 2017/01/18
- [Qemu-devel] [PATCH v2 22/25] console: add graphic_hw_update_done(), Marc-André Lureau, 2017/01/18