| 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
|
|
|