Index: mojo/edk/system/multiprocess_message_pipe_unittest.cc |
diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc |
index 124daec9a8b0c6703bf712c037bd304d4a472f7d..03f89987295c2eb747cf15f91904d18fe83aa3d8 100644 |
--- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc |
+++ b/mojo/edk/system/multiprocess_message_pipe_unittest.cc |
@@ -18,6 +18,8 @@ |
#include "base/files/scoped_file.h" |
#include "base/files/scoped_temp_dir.h" |
#include "base/logging.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
#include "base/strings/string_split.h" |
#include "build/build_config.h" |
#include "mojo/edk/embedder/platform_channel_pair.h" |
@@ -29,6 +31,7 @@ |
#include "mojo/public/c/system/buffer.h" |
#include "mojo/public/c/system/functions.h" |
#include "mojo/public/c/system/types.h" |
+#include "mojo/public/cpp/system/watcher.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -1294,6 +1297,75 @@ TEST_F(MultiprocessMessagePipeTest, BootstrapMessagePipeAsync) { |
END_CHILD() |
} |
+DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MessagePipeStatusChangeInTransitClient, |
+ MultiprocessMessagePipeTest, parent) { |
+ // This test verifies that peer closure is detectable through various |
+ // mechanisms when it races with handle transfer. |
+ MojoHandle handles[4]; |
+ EXPECT_EQ("o_O", ReadMessageWithHandles(parent, handles, 4)); |
+ MojoHandle b = handles[0]; |
yzshen1
2016/08/19 22:20:05
optional, nit: it seems a little easier to read if
Ken Rockot(use gerrit already)
2016/08/19 22:28:00
Done
|
+ MojoHandle d = handles[1]; |
+ MojoHandle f = handles[2]; |
+ MojoHandle h = handles[3]; |
+ |
+ // Wait on handle |b| using MojoWait. |
+ EXPECT_EQ(MOJO_RESULT_OK, MojoWait(b, MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ MOJO_DEADLINE_INDEFINITE, nullptr)); |
+ |
+ base::MessageLoop message_loop; |
+ |
+ // Wait on handle |d| using a Watcher. |
+ { |
+ base::RunLoop run_loop; |
+ Watcher watcher; |
+ watcher.Start(Handle(d), MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ base::Bind([] (base::RunLoop* loop, MojoResult result) { |
+ EXPECT_EQ(MOJO_RESULT_OK, result); |
+ loop->Quit(); |
+ }, &run_loop)); |
+ run_loop.Run(); |
+ } |
+ |
+ // Wait on handle |f| by polling with MojoReadMessage. |
+ MojoResult result; |
+ do { |
+ result = MojoReadMessage(f, nullptr, nullptr, nullptr, nullptr, |
+ MOJO_READ_MESSAGE_FLAG_NONE); |
+ } while (result == MOJO_RESULT_SHOULD_WAIT); |
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
+ |
+ // Wait on handle |h| by polling with MojoWriteMessage. |
+ do { |
+ result = MojoWriteMessage(h, nullptr, 0, nullptr, 0, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE); |
+ } while (result == MOJO_RESULT_OK); |
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
+ |
+ CloseHandle(b); |
+ CloseHandle(d); |
+ CloseHandle(f); |
+ CloseHandle(h); |
+} |
+ |
+TEST_F(MultiprocessMessagePipeTest, MessagePipeStatusChangeInTransit) { |
+ MojoHandle a, b, c, d, e, f, g, h; |
+ CreateMessagePipe(&a, &b); |
+ CreateMessagePipe(&c, &d); |
+ CreateMessagePipe(&e, &f); |
+ CreateMessagePipe(&g, &h); |
+ |
+ RUN_CHILD_ON_PIPE(MessagePipeStatusChangeInTransitClient, child) |
+ MojoHandle handles[] = { b, d, f, h }; |
+ |
+ // Send 4 handles and let their transfer race with their peers' closure. |
+ WriteMessageWithHandles(child, "o_O", handles, 4); |
+ CloseHandle(a); |
+ CloseHandle(c); |
+ CloseHandle(e); |
+ CloseHandle(g); |
+ END_CHILD() |
+} |
+ |
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(BadMessageClient, MultiprocessMessagePipeTest, |
parent) { |
MojoHandle pipe; |