Index: mojo/edk/system/data_pipe_unittest.cc |
diff --git a/mojo/edk/system/data_pipe_unittest.cc b/mojo/edk/system/data_pipe_unittest.cc |
index 526444c6d58095e13cc76115380c2c9cc6b390da..6f8362e69c4a9607626dc7c942a549ebebb8e381 100644 |
--- a/mojo/edk/system/data_pipe_unittest.cc |
+++ b/mojo/edk/system/data_pipe_unittest.cc |
@@ -12,6 +12,7 @@ |
#include "base/logging.h" |
#include "base/macros.h" |
#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
#include "mojo/edk/embedder/embedder.h" |
#include "mojo/edk/embedder/platform_channel_pair.h" |
#include "mojo/edk/system/test_utils.h" |
@@ -20,6 +21,7 @@ |
#include "mojo/public/c/system/data_pipe.h" |
#include "mojo/public/c/system/functions.h" |
#include "mojo/public/c/system/message_pipe.h" |
+#include "mojo/public/cpp/system/watcher.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace mojo { |
@@ -1898,6 +1900,90 @@ TEST_F(DataPipeTest, CreateInChild) { |
END_CHILD() |
} |
+DEFINE_TEST_CLIENT_TEST_WITH_PIPE(DataPipeStatusChangeInTransitClient, |
+ DataPipeTest, parent) { |
+ // This test verifies that peer closure is detectable through various |
+ // mechanisms when it races with handle transfer. |
+ |
+ MojoHandle handles[6]; |
+ EXPECT_EQ("o_O", ReadMessageWithHandles(parent, handles, 6)); |
+ MojoHandle* producers = &handles[0]; |
+ MojoHandle* consumers = &handles[3]; |
+ |
+ // Wait on producer 0 using MojoWait. |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoWait(producers[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ MOJO_DEADLINE_INDEFINITE, nullptr)); |
+ |
+ // Wait on consumer 0 using MojoWait. |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ MojoWait(consumers[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
+ MOJO_DEADLINE_INDEFINITE, nullptr)); |
+ |
+ base::MessageLoop message_loop; |
+ |
+ // Wait on producer 1 and consumer 1 using Watchers. |
+ { |
+ base::RunLoop run_loop; |
+ int count = 0; |
+ auto callback = base::Bind( |
+ [] (base::RunLoop* loop, int* count, MojoResult result) { |
+ EXPECT_EQ(MOJO_RESULT_OK, result); |
+ if (++*count == 2) |
+ loop->Quit(); |
+ }, |
+ &run_loop, &count); |
+ Watcher producer_watcher, consumer_watcher; |
+ producer_watcher.Start( |
+ Handle(producers[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, callback); |
+ consumer_watcher.Start( |
+ Handle(consumers[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED, callback); |
+ run_loop.Run(); |
+ } |
+ |
+ // Wait on producer 2 by polling with MojoWriteData. |
+ MojoResult result; |
+ do { |
+ uint32_t num_bytes = 0; |
+ result = MojoWriteData( |
+ producers[2], nullptr, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE); |
+ } while (result == MOJO_RESULT_OK); |
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
+ |
+ // Wait on consumer 2 by polling with MojoReadData. |
+ do { |
+ char byte; |
+ uint32_t num_bytes = 1; |
+ result = MojoReadData( |
+ consumers[2], &byte, &num_bytes, MOJO_READ_DATA_FLAG_NONE); |
+ } while (result == MOJO_RESULT_SHOULD_WAIT); |
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
+ |
+ for (size_t i = 0; i < 6; ++i) |
+ CloseHandle(handles[i]); |
+} |
+ |
+TEST_F(DataPipeTest, StatusChangeInTransit) { |
+ MojoHandle producers[6]; |
+ MojoHandle consumers[6]; |
+ for (size_t i = 0; i < 6; ++i) |
+ CreateDataPipe(&producers[i], &consumers[i], 1); |
+ |
+ RUN_CHILD_ON_PIPE(DataPipeStatusChangeInTransitClient, child) |
+ MojoHandle handles[] = { producers[0], producers[1], producers[2], |
+ consumers[3], consumers[4], consumers[5] }; |
+ |
+ // Send 3 producers and 3 consumers, and let their transfer race with their |
+ // peers' closure. |
+ WriteMessageWithHandles(child, "o_O", handles, 6); |
+ |
+ for (size_t i = 0; i < 3; ++i) |
+ CloseHandle(consumers[i]); |
+ for (size_t i = 3; i < 6; ++i) |
+ CloseHandle(producers[i]); |
+ END_CHILD() |
+} |
+ |
#endif // !defined(OS_IOS) |
} // namespace |