s4:messaging: add local.messaging.multi_ctx.multi_ctx test
authorStefan Metzmacher <metze@samba.org>
Tue, 10 Jul 2018 14:21:55 +0000 (16:21 +0200)
committerJeremy Allison <jra@samba.org>
Tue, 10 Jul 2018 18:31:13 +0000 (20:31 +0200)
This tests the usage of multiple imessaging_contexts in one process
and also freeing two of them during a message handler.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=13514

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
selftest/knownfail.d/imessaging [new file with mode: 0644]
source4/lib/messaging/tests/messaging.c

diff --git a/selftest/knownfail.d/imessaging b/selftest/knownfail.d/imessaging
new file mode 100644 (file)
index 0000000..af8fa8d
--- /dev/null
@@ -0,0 +1 @@
+^samba4.local.messaging.multi_ctx
index ba58978828808e8fbd683ed43ffff93a13a5fc24..80c8583c21ebad1fafe4ca586c5fd755644582db 100644 (file)
@@ -393,6 +393,226 @@ static bool test_messaging_overflow_check(struct torture_context *tctx)
        return true;
 }
 
+struct test_multi_ctx {
+       struct torture_context *tctx;
+       struct imessaging_context *server_ctx;
+       struct imessaging_context *client_ctx[4];
+       size_t num_missing;
+       bool got_server;
+       bool got_client_0_1;
+       bool got_client_2_3;
+       bool ok;
+};
+
+static void multi_ctx_server_handler(struct imessaging_context *msg,
+                                    void *private_data,
+                                    uint32_t msg_type,
+                                    struct server_id server_id,
+                                    DATA_BLOB *data)
+{
+       struct test_multi_ctx *state = private_data;
+       char *str = NULL;
+
+       torture_assert_goto(state->tctx, state->num_missing >= 1,
+                           state->ok, fail,
+                           "num_missing should be at least 1.");
+       state->num_missing -= 1;
+
+       torture_assert_goto(state->tctx, !state->got_server,
+                           state->ok, fail,
+                           "already got server.");
+       state->got_server = true;
+
+       /*
+        * We free the context itself and most likely reuse
+        * the memory immediately.
+        */
+       TALLOC_FREE(state->server_ctx);
+       str = generate_random_str(state->tctx, 128);
+       torture_assert_goto(state->tctx, str != NULL,
+                           state->ok, fail,
+                           "generate_random_str()");
+
+fail:
+       return;
+}
+
+static void multi_ctx_client_0_1_handler(struct imessaging_context *msg,
+                                        void *private_data,
+                                        uint32_t msg_type,
+                                        struct server_id server_id,
+                                        DATA_BLOB *data)
+{
+       struct test_multi_ctx *state = private_data;
+       char *str = NULL;
+
+       torture_assert_goto(state->tctx, state->num_missing >= 2,
+                           state->ok, fail,
+                           "num_missing should be at least 2.");
+       state->num_missing -= 2;
+
+       torture_assert_goto(state->tctx, !state->got_client_0_1,
+                           state->ok, fail,
+                           "already got client_0_1.");
+       state->got_client_0_1 = true;
+
+       /*
+        * We free two contexts and most likely reuse
+        * the memory immediately.
+        */
+       TALLOC_FREE(state->client_ctx[0]);
+       str = generate_random_str(state->tctx, 128);
+       torture_assert_goto(state->tctx, str != NULL,
+                           state->ok, fail,
+                           "generate_random_str()");
+       TALLOC_FREE(state->client_ctx[1]);
+       str = generate_random_str(state->tctx, 128);
+       torture_assert_goto(state->tctx, str != NULL,
+                           state->ok, fail,
+                           "generate_random_str()");
+
+fail:
+       return;
+}
+
+static void multi_ctx_client_2_3_handler(struct imessaging_context *msg,
+                                        void *private_data,
+                                        uint32_t msg_type,
+                                        struct server_id server_id,
+                                        DATA_BLOB *data)
+{
+       struct test_multi_ctx *state = private_data;
+       char *str = NULL;
+
+       torture_assert_goto(state->tctx, state->num_missing >= 2,
+                           state->ok, fail,
+                           "num_missing should be at least 2.");
+       state->num_missing -= 2;
+
+       torture_assert_goto(state->tctx, !state->got_client_2_3,
+                           state->ok, fail,
+                           "already got client_2_3.");
+       state->got_client_2_3 = true;
+
+       /*
+        * We free two contexts and most likely reuse
+        * the memory immediately.
+        */
+       TALLOC_FREE(state->client_ctx[2]);
+       str = generate_random_str(state->tctx, 128);
+       torture_assert_goto(state->tctx, str != NULL,
+                           state->ok, fail,
+                           "generate_random_str()");
+       TALLOC_FREE(state->client_ctx[3]);
+       str = generate_random_str(state->tctx, 128);
+       torture_assert_goto(state->tctx, str != NULL,
+                           state->ok, fail,
+                           "generate_random_str()");
+
+fail:
+       return;
+}
+
+static bool test_multi_ctx(struct torture_context *tctx)
+{
+       struct test_multi_ctx state = {
+               .tctx = tctx,
+               .ok = true,
+       };
+       struct timeval tv;
+       NTSTATUS status;
+
+       lpcfg_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
+
+       /*
+        * We use cluster_id(0, 0) as that gets for
+        * all task ids.
+        */
+       state.server_ctx = imessaging_init(tctx,
+                                          tctx->lp_ctx,
+                                          cluster_id(0, 0),
+                                          tctx->ev);
+       torture_assert(tctx, state.server_ctx != NULL,
+                      "Failed to init messaging context");
+
+       status = imessaging_register(state.server_ctx, &state,
+                                    MSG_TMP_BASE-1,
+                                    multi_ctx_server_handler);
+       torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
+
+       state.client_ctx[0] = imessaging_init(tctx,
+                                             tctx->lp_ctx,
+                                             cluster_id(0, 0),
+                                             tctx->ev);
+       torture_assert(tctx, state.client_ctx[0] != NULL,
+                      "msg_client_ctx imessaging_init() failed");
+       status = imessaging_register(state.client_ctx[0], &state,
+                                    MSG_TMP_BASE-1,
+                                    multi_ctx_client_0_1_handler);
+       torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
+       state.client_ctx[1] = imessaging_init(tctx,
+                                             tctx->lp_ctx,
+                                             cluster_id(0, 0),
+                                             tctx->ev);
+       torture_assert(tctx, state.client_ctx[1] != NULL,
+                      "msg_client_ctx imessaging_init() failed");
+       status = imessaging_register(state.client_ctx[1], &state,
+                                    MSG_TMP_BASE-1,
+                                    multi_ctx_client_0_1_handler);
+       torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
+       state.client_ctx[2] = imessaging_init(tctx,
+                                             tctx->lp_ctx,
+                                             cluster_id(0, 0),
+                                             tctx->ev);
+       torture_assert(tctx, state.client_ctx[2] != NULL,
+                      "msg_client_ctx imessaging_init() failed");
+       status = imessaging_register(state.client_ctx[2], &state,
+                                    MSG_TMP_BASE-1,
+                                    multi_ctx_client_2_3_handler);
+       torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
+       state.client_ctx[3] = imessaging_init(tctx,
+                                             tctx->lp_ctx,
+                                             cluster_id(0, 0),
+                                             tctx->ev);
+       torture_assert(tctx, state.client_ctx[3] != NULL,
+                      "msg_client_ctx imessaging_init() failed");
+       status = imessaging_register(state.client_ctx[3], &state,
+                                    MSG_TMP_BASE-1,
+                                    multi_ctx_client_2_3_handler);
+       torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
+
+       /*
+        * Send one message that need to arrive on 3 ( 5 - 2 ) handlers.
+        */
+       state.num_missing = 5;
+
+       status = imessaging_send(state.server_ctx,
+                                cluster_id(0, 0),
+                                MSG_TMP_BASE-1, NULL);
+       torture_assert_ntstatus_ok(tctx, status, "msg failed");
+
+       tv = timeval_current();
+       while (timeval_elapsed(&tv) < 30 && state.num_missing > 0 && state.ok) {
+               int ret;
+
+               ret = tevent_loop_once(tctx->ev);
+               torture_assert_int_equal(tctx, ret, 0, "tevent_loop_once()");
+       }
+
+       if (!state.ok) {
+               return false;
+       }
+
+       torture_assert_int_equal(tctx, state.num_missing, 0,
+                                "wrong message count");
+
+       torture_assert(tctx, state.got_client_0_1, "got_client_0_1");
+       torture_assert(tctx, state.got_client_2_3, "got_client_2_3");
+       torture_assert(tctx, state.got_server, "got_server");
+
+       return true;
+}
+
 struct torture_suite *torture_local_messaging(TALLOC_CTX *mem_ctx)
 {
        struct torture_suite *s = torture_suite_create(mem_ctx, "messaging");
@@ -400,5 +620,6 @@ struct torture_suite *torture_local_messaging(TALLOC_CTX *mem_ctx)
        torture_suite_add_simple_test(s, "overflow_check",
                                      test_messaging_overflow_check);
        torture_suite_add_simple_test(s, "ping_speed", test_ping_speed);
+       torture_suite_add_simple_test(s, "multi_ctx", test_multi_ctx);
        return s;
 }