diff options
author | Volker Lendecke <vl@samba.org> | 2014-05-07 11:21:04 +0200 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2014-05-08 11:32:44 +0200 |
commit | 50a66d588a13888a594b785c700695771bf6224d (patch) | |
tree | aebe7fa1bb562b63a2cff7b76d9efd9902e01565 /source3/torture/test_messaging_read.c | |
parent | 8763c8c19625a974b040987e6fd73aea0434730a (diff) | |
download | samba-50a66d588a13888a594b785c700695771bf6224d.tar.gz samba-50a66d588a13888a594b785c700695771bf6224d.tar.xz samba-50a66d588a13888a594b785c700695771bf6224d.zip |
torture3: local-messaging-read3
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
Diffstat (limited to 'source3/torture/test_messaging_read.c')
-rw-r--r-- | source3/torture/test_messaging_read.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/source3/torture/test_messaging_read.c b/source3/torture/test_messaging_read.c index 0bb3128cd88..757b83eb341 100644 --- a/source3/torture/test_messaging_read.c +++ b/source3/torture/test_messaging_read.c @@ -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; +} |