torture3: local-messaging-read3
authorVolker Lendecke <vl@samba.org>
Wed, 7 May 2014 09:21:04 +0000 (11:21 +0200)
committerVolker Lendecke <vl@samba.org>
Thu, 8 May 2014 09:32:44 +0000 (11:32 +0200)
This is a testcase for the rpc-style messaging nested event context. We have to
fork here: The nested event context does not reply to the PING message, it only
listens for the PONG response. But that's the point of the patches: Correctly
pick just one message in a nested event context. I think this is the best we
can do with nested event contexts.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Volker Lendecke <vl@samba.org>
Autobuild-Date(master): Thu May  8 11:32:44 CEST 2014 on sn-devel-104

source3/selftest/tests.py
source3/torture/proto.h
source3/torture/test_messaging_read.c
source3/torture/torture.c

index fcf3cd58c01f9f5bb7c8a3d1fe4fe36db7fc8064..bad66d32868c2059bf51fa0da16e8a03a63becc4 100755 (executable)
@@ -104,6 +104,7 @@ local_tests = [
     "LOCAL-IDMAP-TDB-COMMON",
     "LOCAL-MESSAGING-READ1",
     "LOCAL-MESSAGING-READ2",
+    "LOCAL-MESSAGING-READ3",
     "LOCAL-hex_encode_buf",
     "LOCAL-sprintf_append",
     "LOCAL-remove_duplicate_addrs2"]
index a737ea4eacc3c75733ed0fd065dd62dc5366baab..20c11103220ccdd6c2d2554a098f50b05564e696 100644 (file)
@@ -115,5 +115,6 @@ bool run_qpathinfo_bufsize(int dummy);
 bool run_bench_pthreadpool(int dummy);
 bool run_messaging_read1(int dummy);
 bool run_messaging_read2(int dummy);
+bool run_messaging_read3(int dummy);
 
 #endif /* __TORTURE_H__ */
index 0bb3128cd887e5382dbaaee62276a6b3fa661608..757b83eb341415c540472aa8713b4dc7c0ca8ba0 100644 (file)
@@ -248,3 +248,203 @@ fail:
        TALLOC_FREE(ev);
        return retval;
 }
+
+struct msg_pingpong_state {
+       uint8_t dummy;
+};
+
+static void msg_pingpong_done(struct tevent_req *subreq);
+
+static struct tevent_req *msg_pingpong_send(TALLOC_CTX *mem_ctx,
+                                           struct tevent_context *ev,
+                                           struct messaging_context *msg_ctx,
+                                           struct server_id dst)
+{
+       struct tevent_req *req, *subreq;
+       struct msg_pingpong_state *state;
+       NTSTATUS status;
+
+       req = tevent_req_create(mem_ctx, &state, struct msg_pingpong_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       status = messaging_send_buf(msg_ctx, dst, MSG_PING, NULL, 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_error(req, map_errno_from_nt_status(status));
+               return tevent_req_post(req, ev);
+       }
+
+       subreq = messaging_read_send(state, ev, msg_ctx, MSG_PONG);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, msg_pingpong_done, req);
+       return req;
+}
+
+static void msg_pingpong_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       int ret;
+
+       ret = messaging_read_recv(subreq, NULL, NULL);
+       TALLOC_FREE(subreq);
+       if (ret != 0) {
+               tevent_req_error(req, ret);
+               return;
+       }
+       tevent_req_done(req);
+}
+
+static int msg_pingpong_recv(struct tevent_req *req)
+{
+       int err;
+
+       if (tevent_req_is_unix_error(req, &err)) {
+               return err;
+       }
+       return 0;
+}
+
+static int msg_pingpong(struct messaging_context *msg_ctx,
+                       struct server_id dst)
+{
+       struct tevent_context *ev;
+       struct tevent_req *req;
+       int ret = ENOMEM;
+
+       ev = tevent_context_init(msg_ctx);
+       if (ev == NULL) {
+               goto fail;
+       }
+       req = msg_pingpong_send(ev, ev, msg_ctx, dst);
+       if (req == NULL) {
+               goto fail;
+       }
+       if (!tevent_req_poll(req, ev)) {
+               ret = errno;
+               goto fail;
+       }
+       ret = msg_pingpong_recv(req);
+fail:
+       TALLOC_FREE(ev);
+       return ret;
+}
+
+static void ping_responder_exit(struct tevent_context *ev,
+                               struct tevent_fd *fde,
+                               uint16_t flags,
+                               void *private_data)
+{
+       bool *done = private_data;
+       *done = true;
+}
+
+static void ping_responder(int ready_pipe, int exit_pipe)
+{
+       struct tevent_context *ev;
+       struct messaging_context *msg_ctx;
+       struct tevent_fd *exit_handler;
+       char c = 0;
+       bool done = false;
+
+       ev = samba_tevent_context_init(talloc_tos());
+       if (ev == NULL) {
+               fprintf(stderr, "child tevent_context_init failed\n");
+               exit(1);
+       }
+       msg_ctx = messaging_init(ev, ev);
+       if (msg_ctx == NULL) {
+               fprintf(stderr, "child messaging_init failed\n");
+               exit(1);
+       }
+       exit_handler = tevent_add_fd(ev, ev, exit_pipe, TEVENT_FD_READ,
+                                    ping_responder_exit, &done);
+       if (exit_handler == NULL) {
+               fprintf(stderr, "child tevent_add_fd failed\n");
+               exit(1);
+       }
+
+       if (write(ready_pipe, &c, 1) != 1) {
+               fprintf(stderr, "child messaging_init failed\n");
+               exit(1);
+       }
+
+       while (!done) {
+               int ret;
+               ret = tevent_loop_once(ev);
+               if (ret != 0) {
+                       fprintf(stderr, "child tevent_loop_once failed\n");
+                       exit(1);
+               }
+       }
+
+       TALLOC_FREE(msg_ctx);
+       TALLOC_FREE(ev);
+}
+
+bool run_messaging_read3(int dummy)
+{
+       struct tevent_context *ev = NULL;
+       struct messaging_context *msg_ctx = NULL;
+       bool retval = false;
+       pid_t child;
+       int ready_pipe[2];
+       int exit_pipe[2];
+       int ret;
+       char c;
+       struct server_id dst;
+
+       if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
+               perror("pipe failed");
+               return false;
+       }
+
+       child = fork();
+       if (child == -1) {
+               perror("fork failed");
+               return false;
+       }
+
+       if (child == 0) {
+               close(ready_pipe[0]);
+               close(exit_pipe[1]);
+               ping_responder(ready_pipe[1], exit_pipe[0]);
+               exit(0);
+       }
+       close(ready_pipe[1]);
+       close(exit_pipe[0]);
+
+       if (read(ready_pipe[0], &c, 1) != 1) {
+               perror("read failed");
+               return false;
+       }
+
+       ev = samba_tevent_context_init(talloc_tos());
+       if (ev == NULL) {
+               fprintf(stderr, "tevent_context_init failed\n");
+               goto fail;
+       }
+       msg_ctx = messaging_init(ev, ev);
+       if (msg_ctx == NULL) {
+               fprintf(stderr, "messaging_init failed\n");
+               goto fail;
+       }
+
+       dst = messaging_server_id(msg_ctx);
+       dst.pid = child;
+
+       ret = msg_pingpong(msg_ctx, dst);
+       if (ret != 0){
+               fprintf(stderr, "msg_pingpong failed\n");
+               goto fail;
+       }
+
+       retval = true;
+fail:
+       TALLOC_FREE(msg_ctx);
+       TALLOC_FREE(ev);
+       return retval;
+}
index f97119add56ad31549ecbc2779935f54922d03d5..08265067238010aee7f228bc227a32a3402ff28e 100644 (file)
@@ -9576,6 +9576,7 @@ static struct {
        { "LOCAL-DBWRAP-WATCH1", run_dbwrap_watch1, 0 },
        { "LOCAL-MESSAGING-READ1", run_messaging_read1, 0 },
        { "LOCAL-MESSAGING-READ2", run_messaging_read2, 0 },
+       { "LOCAL-MESSAGING-READ3", run_messaging_read3, 0 },
        { "LOCAL-BASE64", run_local_base64, 0},
        { "LOCAL-RBTREE", run_local_rbtree, 0},
        { "LOCAL-MEMCACHE", run_local_memcache, 0},