diff options
-rwxr-xr-x | source3/selftest/tests.py | 1 | ||||
-rw-r--r-- | source3/torture/proto.h | 1 | ||||
-rw-r--r-- | source3/torture/test_messaging_read.c | 200 | ||||
-rw-r--r-- | source3/torture/torture.c | 1 |
4 files changed, 203 insertions, 0 deletions
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index fcf3cd58c0..bad66d3286 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -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"] diff --git a/source3/torture/proto.h b/source3/torture/proto.h index a737ea4eac..20c1110322 100644 --- a/source3/torture/proto.h +++ b/source3/torture/proto.h @@ -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__ */ diff --git a/source3/torture/test_messaging_read.c b/source3/torture/test_messaging_read.c index 0bb3128cd8..757b83eb34 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; +} diff --git a/source3/torture/torture.c b/source3/torture/torture.c index f97119add5..0826506723 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -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}, |