qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]