Refactor IPCSupportTest and add a test.
The new test, IPCSupportTest.ConnectTwoSlaves, simulates a master with
two slaves, with the master creating a new message pipe and sending an
end to each slave. (Currently, this still goes through the existing
proxying path, but this will allow upcoming non-proxying code to be
tested.)
More tests along similar lines will be added later (which explains the
effort put into the refactoring).
R=yzshen@chromium.org
Review URL: https://codereview.chromium.org/1187183002.
diff --git a/mojo/edk/system/ipc_support_unittest.cc b/mojo/edk/system/ipc_support_unittest.cc
index b613e45..47d7a9e 100644
--- a/mojo/edk/system/ipc_support_unittest.cc
+++ b/mojo/edk/system/ipc_support_unittest.cc
@@ -4,6 +4,9 @@
#include "mojo/edk/system/ipc_support.h"
+#include <utility>
+#include <vector>
+
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
@@ -18,6 +21,8 @@
#include "mojo/edk/embedder/slave_process_delegate.h"
#include "mojo/edk/system/channel_manager.h"
#include "mojo/edk/system/connection_identifier.h"
+#include "mojo/edk/system/dispatcher.h"
+#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "mojo/edk/system/process_identifier.h"
#include "mojo/edk/system/test_utils.h"
@@ -35,9 +40,11 @@
class TestMasterProcessDelegate : public embedder::MasterProcessDelegate {
public:
TestMasterProcessDelegate()
- : on_slave_disconnect_event_(true, false) {} // Manual reset.
+ : on_slave_disconnect_event_(false, false) {} // Auto reset.
~TestMasterProcessDelegate() override {}
+ // Warning: There's only one slave disconnect event (which resets
+ // automatically).
bool TryWaitForOnSlaveDisconnect() {
return on_slave_disconnect_event_.TimedWait(TestTimeouts::action_timeout());
}
@@ -69,76 +76,280 @@
DISALLOW_COPY_AND_ASSIGN(TestSlaveProcessDelegate);
};
-TEST(IPCSupportTest, MasterSlave) {
- embedder::SimplePlatformSupport platform_support;
- base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
- TestMasterProcessDelegate master_process_delegate;
+// Represents the master's side of its connection to a slave.
+class TestSlaveConnection {
+ public:
+ TestSlaveConnection(base::TestIOThread* test_io_thread,
+ IPCSupport* master_ipc_support)
+ : test_io_thread_(test_io_thread),
+ master_ipc_support_(master_ipc_support),
+ connection_id_(master_ipc_support_->GenerateConnectionIdentifier()),
+ slave_id_(kInvalidProcessIdentifier),
+ event_(true, false) {}
+ ~TestSlaveConnection() {}
+
+ // After this is called, |ShutdownChannelToSlave()| must be called (possibly
+ // after |WaitForChannelToSlave()|) before destruction.
+ scoped_refptr<MessagePipeDispatcher> ConnectToSlave() {
+ embedder::PlatformChannelPair channel_pair;
+ // Note: |ChannelId|s and |ProcessIdentifier|s are interchangeable.
+ scoped_refptr<MessagePipeDispatcher> mp =
+ master_ipc_support_->ConnectToSlave(
+ connection_id_, nullptr, channel_pair.PassServerHandle(),
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event_)),
+ nullptr, &slave_id_);
+ EXPECT_TRUE(mp);
+ EXPECT_NE(slave_id_, kInvalidProcessIdentifier);
+ EXPECT_NE(slave_id_, kMasterProcessIdentifier);
+ slave_platform_handle_ = channel_pair.PassClientHandle();
+ return mp;
+ }
+
+ void WaitForChannelToSlave() {
+ EXPECT_TRUE(event_.TimedWait(TestTimeouts::action_timeout()));
+ }
+
+ void ShutdownChannelToSlave() {
+ // Since |event_| is manual-reset, calling this multiple times is OK.
+ WaitForChannelToSlave();
+
+ test_io_thread_->PostTaskAndWait(
+ FROM_HERE,
+ base::Bind(&ChannelManager::ShutdownChannelOnIOThread,
+ base::Unretained(master_ipc_support_->channel_manager()),
+ slave_id_));
+ }
+
+ embedder::ScopedPlatformHandle PassSlavePlatformHandle() {
+ return slave_platform_handle_.Pass();
+ }
+
+ const ConnectionIdentifier& connection_id() const { return connection_id_; }
+
+ private:
+ base::TestIOThread* const test_io_thread_;
+ IPCSupport* const master_ipc_support_;
+ const ConnectionIdentifier connection_id_;
+ // The master's message pipe dispatcher.
+ scoped_refptr<MessagePipeDispatcher> message_pipe_;
+ ProcessIdentifier slave_id_;
+ base::WaitableEvent event_;
+ embedder::ScopedPlatformHandle slave_platform_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSlaveConnection);
+};
+
+// Encapsulates the state of a slave. (Note, however, that we share a
+// |PlatformSupport| and an I/O thread.)
+class TestSlave {
+ public:
+ // Note: Before destruction, |ShutdownIPCSupport()| must be called.
+ TestSlave(embedder::PlatformSupport* platform_support,
+ base::TestIOThread* test_io_thread,
+ embedder::ScopedPlatformHandle platform_handle)
+ : test_io_thread_(test_io_thread),
+ slave_ipc_support_(platform_support,
+ embedder::ProcessType::SLAVE,
+ test_io_thread->task_runner(),
+ &slave_process_delegate_,
+ test_io_thread->task_runner(),
+ platform_handle.Pass()),
+ event_(true, false) {}
+ ~TestSlave() {}
+
+ // After this is called, |ShutdownChannelToMaster()| must be called (possibly
+ // after |WaitForChannelToMaster()|) before destruction.
+ scoped_refptr<MessagePipeDispatcher> ConnectToMaster(
+ const ConnectionIdentifier& connection_id) {
+ ProcessIdentifier master_id = kInvalidProcessIdentifier;
+ scoped_refptr<MessagePipeDispatcher> mp =
+ slave_ipc_support_.ConnectToMaster(
+ connection_id,
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event_)),
+ nullptr, &master_id);
+ EXPECT_TRUE(mp);
+ EXPECT_EQ(kMasterProcessIdentifier, master_id);
+ return mp;
+ }
+
+ void WaitForChannelToMaster() {
+ EXPECT_TRUE(event_.TimedWait(TestTimeouts::action_timeout()));
+ }
+
+ void ShutdownChannelToMaster() {
+ // Since |event_| is manual-reset, calling this multiple times is OK.
+ WaitForChannelToMaster();
+
+ test_io_thread_->PostTaskAndWait(
+ FROM_HERE,
+ base::Bind(&ChannelManager::ShutdownChannelOnIOThread,
+ base::Unretained(slave_ipc_support_.channel_manager()),
+ kMasterProcessIdentifier));
+ }
+
+ // No other methods may be called after this.
+ void ShutdownIPCSupport() {
+ test_io_thread_->PostTaskAndWait(
+ FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
+ base::Unretained(&slave_ipc_support_)));
+ }
+
+ private:
+ base::TestIOThread* const test_io_thread_;
+ TestSlaveProcessDelegate slave_process_delegate_;
+ IPCSupport slave_ipc_support_;
+ base::WaitableEvent event_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSlave);
+};
+
+class IPCSupportTest : public testing::Test {
+ public:
// Note: Run master process delegate methods on the I/O thread.
- IPCSupport master_ipc_support(
- &platform_support, embedder::ProcessType::MASTER,
- test_io_thread.task_runner(), &master_process_delegate,
- test_io_thread.task_runner(), embedder::ScopedPlatformHandle());
+ IPCSupportTest()
+ : test_io_thread_(base::TestIOThread::kAutoStart),
+ master_ipc_support_(&platform_support(),
+ embedder::ProcessType::MASTER,
+ test_io_thread_.task_runner(),
+ &master_process_delegate_,
+ test_io_thread_.task_runner(),
+ embedder::ScopedPlatformHandle()) {}
+ ~IPCSupportTest() override {}
- ConnectionIdentifier connection_id =
- master_ipc_support.GenerateConnectionIdentifier();
+ void ShutdownMasterIPCSupport() {
+ test_io_thread_.PostTaskAndWait(
+ FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
+ base::Unretained(&master_ipc_support_)));
+ }
- embedder::PlatformChannelPair channel_pair;
- // Note: |ChannelId|s and |ProcessIdentifier|s are interchangeable.
- ProcessIdentifier slave_id = kInvalidProcessIdentifier;
- base::WaitableEvent event1(true, false);
- scoped_refptr<MessagePipeDispatcher> master_mp =
- master_ipc_support.ConnectToSlave(
- connection_id, nullptr, channel_pair.PassServerHandle(),
- base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event1)),
- nullptr, &slave_id);
- ASSERT_TRUE(master_mp);
- EXPECT_NE(slave_id, kInvalidProcessIdentifier);
- EXPECT_NE(slave_id, kMasterProcessIdentifier);
- // Note: We don't have to wait on |event1| now, but we'll have to do so before
- // tearing down the channel.
+ embedder::SimplePlatformSupport& platform_support() {
+ return platform_support_;
+ }
+ base::TestIOThread& test_io_thread() { return test_io_thread_; }
+ TestMasterProcessDelegate& master_process_delegate() {
+ return master_process_delegate_;
+ }
+ IPCSupport& master_ipc_support() { return master_ipc_support_; }
- TestSlaveProcessDelegate slave_process_delegate;
- // Note: Run process delegate methods on the I/O thread.
- IPCSupport slave_ipc_support(
- &platform_support, embedder::ProcessType::SLAVE,
- test_io_thread.task_runner(), &slave_process_delegate,
- test_io_thread.task_runner(), channel_pair.PassClientHandle());
+ private:
+ embedder::SimplePlatformSupport platform_support_;
+ base::TestIOThread test_io_thread_;
- ProcessIdentifier master_id = kInvalidProcessIdentifier;
- base::WaitableEvent event2(true, false);
- scoped_refptr<MessagePipeDispatcher> slave_mp =
- slave_ipc_support.ConnectToMaster(
- connection_id,
- base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event2)),
- nullptr, &master_id);
- ASSERT_TRUE(slave_mp);
- EXPECT_EQ(kMasterProcessIdentifier, master_id);
+ // All tests require a master.
+ TestMasterProcessDelegate master_process_delegate_;
+ IPCSupport master_ipc_support_;
- // Set up waiting on the slave end first (to avoid racing).
+ DISALLOW_COPY_AND_ASSIGN(IPCSupportTest);
+};
+
+// Tests writing a message (containing just data) to |write_mp| and then reading
+// it from |read_mp| (it should be the next message, i.e., there should be no
+// other messages already enqueued in that direction).
+void TestWriteReadMessage(scoped_refptr<MessagePipeDispatcher> write_mp,
+ scoped_refptr<MessagePipeDispatcher> read_mp) {
+ // Set up waiting on the read end first (to avoid racing).
Waiter waiter;
waiter.Init();
ASSERT_EQ(
MOJO_RESULT_OK,
- slave_mp->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, nullptr));
+ read_mp->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, nullptr));
- // Write a message with just 'x' through the master's end.
+ // Write a message with just 'x' through the write end.
EXPECT_EQ(MOJO_RESULT_OK,
- master_mp->WriteMessage(UserPointer<const void>("x"), 1, nullptr,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
+ write_mp->WriteMessage(UserPointer<const void>("x"), 1, nullptr,
+ MOJO_WRITE_MESSAGE_FLAG_NONE));
// Wait for it to arrive.
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), nullptr));
- slave_mp->RemoveAwakable(&waiter, nullptr);
+ read_mp->RemoveAwakable(&waiter, nullptr);
- // Read the message from the slave's end.
+ // Read the message from the read end.
char buffer[10] = {};
uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
EXPECT_EQ(MOJO_RESULT_OK,
- slave_mp->ReadMessage(UserPointer<void>(buffer),
- MakeUserPointer(&buffer_size), 0, nullptr,
- MOJO_READ_MESSAGE_FLAG_NONE));
+ read_mp->ReadMessage(UserPointer<void>(buffer),
+ MakeUserPointer(&buffer_size), 0, nullptr,
+ MOJO_READ_MESSAGE_FLAG_NONE));
EXPECT_EQ(1u, buffer_size);
EXPECT_EQ('x', buffer[0]);
+}
+
+using MessagePipeDispatcherPair =
+ std::pair<scoped_refptr<MessagePipeDispatcher>,
+ scoped_refptr<MessagePipeDispatcher>>;
+MessagePipeDispatcherPair CreateMessagePipe() {
+ MessagePipeDispatcherPair rv;
+ rv.first =
+ new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions);
+ rv.second =
+ new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions);
+ scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
+ rv.first->Init(mp, 0);
+ rv.second->Init(mp, 1);
+ return rv;
+}
+
+// Writes a message pipe dispatcher (in a message) to |write_mp| and reads it
+// from |read_mp| (it should be the next message, i.e., there should be no other
+// other messages already enqueued in that direction).
+scoped_refptr<MessagePipeDispatcher> SendMessagePipeDispatcher(
+ scoped_refptr<MessagePipeDispatcher> write_mp,
+ scoped_refptr<MessagePipeDispatcher> read_mp,
+ scoped_refptr<MessagePipeDispatcher> mp_to_send) {
+ CHECK_NE(mp_to_send, write_mp);
+ CHECK_NE(mp_to_send, read_mp);
+
+ // Set up waiting on the read end first (to avoid racing).
+ Waiter waiter;
+ waiter.Init();
+ CHECK_EQ(
+ read_mp->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, nullptr),
+ MOJO_RESULT_OK);
+
+ // Write a message with just |mp_to_send| through the write end.
+ DispatcherTransport transport(
+ test::DispatcherTryStartTransport(mp_to_send.get()));
+ CHECK(transport.is_valid());
+ std::vector<DispatcherTransport> transports;
+ transports.push_back(transport);
+ CHECK_EQ(write_mp->WriteMessage(NullUserPointer(), 0, &transports,
+ MOJO_WRITE_MESSAGE_FLAG_NONE),
+ MOJO_RESULT_OK);
+ transport.End();
+
+ // Wait for it to arrive.
+ CHECK_EQ(waiter.Wait(test::ActionDeadline(), nullptr), MOJO_RESULT_OK);
+ read_mp->RemoveAwakable(&waiter, nullptr);
+
+ // Read the message from the read end.
+ DispatcherVector dispatchers;
+ uint32_t num_dispatchers = 10;
+ CHECK_EQ(
+ read_mp->ReadMessage(NullUserPointer(), NullUserPointer(), &dispatchers,
+ &num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE),
+ MOJO_RESULT_OK);
+ CHECK_EQ(dispatchers.size(), 1u);
+ CHECK_EQ(num_dispatchers, 1u);
+ CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::Type::MESSAGE_PIPE);
+ return scoped_refptr<MessagePipeDispatcher>(
+ static_cast<MessagePipeDispatcher*>(dispatchers[0].get()));
+}
+
+TEST_F(IPCSupportTest, MasterSlave) {
+ TestSlaveConnection slave_connection(&test_io_thread(),
+ &master_ipc_support());
+ scoped_refptr<MessagePipeDispatcher> master_mp =
+ slave_connection.ConnectToSlave();
+
+ TestSlave slave(&platform_support(), &test_io_thread(),
+ slave_connection.PassSlavePlatformHandle());
+ scoped_refptr<MessagePipeDispatcher> slave_mp =
+ slave.ConnectToMaster(slave_connection.connection_id());
+
+ // Test that we can send a message from the master to the slave.
+ TestWriteReadMessage(master_mp, slave_mp);
+ // And vice versa.
+ TestWriteReadMessage(slave_mp, master_mp);
// Don't need the message pipe anymore.
master_mp->Close();
@@ -147,51 +358,100 @@
// A message was sent through the message pipe, |Channel|s must have been
// established on both sides. The events have thus almost certainly been
// signalled, but we'll wait just to be sure.
- EXPECT_TRUE(event1.TimedWait(TestTimeouts::action_timeout()));
- EXPECT_TRUE(event2.TimedWait(TestTimeouts::action_timeout()));
+ slave_connection.WaitForChannelToSlave();
+ slave.WaitForChannelToMaster();
- test_io_thread.PostTaskAndWait(
- FROM_HERE,
- base::Bind(&ChannelManager::ShutdownChannelOnIOThread,
- base::Unretained(slave_ipc_support.channel_manager()),
- master_id));
- test_io_thread.PostTaskAndWait(
- FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
- base::Unretained(&slave_ipc_support)));
+ slave.ShutdownChannelToMaster();
+ slave.ShutdownIPCSupport();
+ EXPECT_TRUE(master_process_delegate().TryWaitForOnSlaveDisconnect());
- EXPECT_TRUE(master_process_delegate.TryWaitForOnSlaveDisconnect());
+ slave_connection.ShutdownChannelToSlave();
+ ShutdownMasterIPCSupport();
+}
- test_io_thread.PostTaskAndWait(
- FROM_HERE,
- base::Bind(&ChannelManager::ShutdownChannelOnIOThread,
- base::Unretained(master_ipc_support.channel_manager()),
- slave_id));
- test_io_thread.PostTaskAndWait(
- FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
- base::Unretained(&master_ipc_support)));
+// Simulates a master and two slaves. Initially, there are just message pipes
+// from the master to the slaves. This tests the master creating a message pipe
+// and sending an end to each slave, which should result in a direct connection
+// between the two slaves (TODO(vtl): this part doesn't happen yet).
+// TODO(vtl): There are various other similar scenarios we'll need to test, so
+// we'll need to factor out some of the code.
+// TODO(vtl): In this scenario, we can't test the intermediary (the master)
+// going away.
+TEST_F(IPCSupportTest, ConnectTwoSlaves) {
+ TestSlaveConnection slave1_connection(&test_io_thread(),
+ &master_ipc_support());
+ scoped_refptr<MessagePipeDispatcher> master_mp1 =
+ slave1_connection.ConnectToSlave();
+
+ TestSlave slave1(&platform_support(), &test_io_thread(),
+ slave1_connection.PassSlavePlatformHandle());
+ scoped_refptr<MessagePipeDispatcher> slave1_mp =
+ slave1.ConnectToMaster(slave1_connection.connection_id());
+
+ TestSlaveConnection slave2_connection(&test_io_thread(),
+ &master_ipc_support());
+ scoped_refptr<MessagePipeDispatcher> master_mp2 =
+ slave2_connection.ConnectToSlave();
+
+ TestSlave slave2(&platform_support(), &test_io_thread(),
+ slave2_connection.PassSlavePlatformHandle());
+ scoped_refptr<MessagePipeDispatcher> slave2_mp =
+ slave2.ConnectToMaster(slave2_connection.connection_id());
+
+ TestWriteReadMessage(master_mp1, slave1_mp);
+ TestWriteReadMessage(slave1_mp, master_mp1);
+ TestWriteReadMessage(master_mp2, slave2_mp);
+ TestWriteReadMessage(slave2_mp, master_mp2);
+
+ // Make a message pipe (logically "in" the master) and send one end to each
+ // slave.
+ MessagePipeDispatcherPair send_mps = CreateMessagePipe();
+ scoped_refptr<MessagePipeDispatcher> slave1_received_mp =
+ SendMessagePipeDispatcher(master_mp1, slave1_mp, send_mps.first);
+ scoped_refptr<MessagePipeDispatcher> slave2_received_mp =
+ SendMessagePipeDispatcher(master_mp2, slave2_mp, send_mps.second);
+
+ // These should be connected.
+ TestWriteReadMessage(slave1_received_mp, slave2_received_mp);
+ TestWriteReadMessage(slave2_received_mp, slave1_received_mp);
+
+ master_mp1->Close();
+ master_mp2->Close();
+ slave1_mp->Close();
+ slave2_mp->Close();
+
+ // They should still be connected.
+ TestWriteReadMessage(slave1_received_mp, slave2_received_mp);
+ TestWriteReadMessage(slave2_received_mp, slave1_received_mp);
+
+ slave1_received_mp->Close();
+ slave2_received_mp->Close();
+
+ slave1.ShutdownChannelToMaster();
+ slave1.ShutdownIPCSupport();
+ EXPECT_TRUE(master_process_delegate().TryWaitForOnSlaveDisconnect());
+ slave1_connection.ShutdownChannelToSlave();
+
+ slave2.ShutdownChannelToMaster();
+ slave2.ShutdownIPCSupport();
+ EXPECT_TRUE(master_process_delegate().TryWaitForOnSlaveDisconnect());
+ slave2_connection.ShutdownChannelToSlave();
+
+ ShutdownMasterIPCSupport();
}
} // namespace
// Note: This test isn't in an anonymous namespace, since it needs to be
// friended by |IPCSupport|.
-TEST(IPCSupportTest, MasterSlaveInternal) {
- embedder::SimplePlatformSupport platform_support;
- base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
- TestMasterProcessDelegate master_process_delegate;
- // Note: Run master process delegate methods on the I/O thread.
- IPCSupport master_ipc_support(
- &platform_support, embedder::ProcessType::MASTER,
- test_io_thread.task_runner(), &master_process_delegate,
- test_io_thread.task_runner(), embedder::ScopedPlatformHandle());
-
+TEST_F(IPCSupportTest, MasterSlaveInternal) {
ConnectionIdentifier connection_id =
- master_ipc_support.GenerateConnectionIdentifier();
+ master_ipc_support().GenerateConnectionIdentifier();
embedder::PlatformChannelPair channel_pair;
ProcessIdentifier slave_id = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle master_second_platform_handle =
- master_ipc_support.ConnectToSlaveInternal(
+ master_ipc_support().ConnectToSlaveInternal(
connection_id, nullptr, channel_pair.PassServerHandle(), &slave_id);
ASSERT_TRUE(master_second_platform_handle.is_valid());
EXPECT_NE(slave_id, kInvalidProcessIdentifier);
@@ -200,9 +460,9 @@
TestSlaveProcessDelegate slave_process_delegate;
// Note: Run process delegate methods on the I/O thread.
IPCSupport slave_ipc_support(
- &platform_support, embedder::ProcessType::SLAVE,
- test_io_thread.task_runner(), &slave_process_delegate,
- test_io_thread.task_runner(), channel_pair.PassClientHandle());
+ &platform_support(), embedder::ProcessType::SLAVE,
+ test_io_thread().task_runner(), &slave_process_delegate,
+ test_io_thread().task_runner(), channel_pair.PassClientHandle());
embedder::ScopedPlatformHandle slave_second_platform_handle =
slave_ipc_support.ConnectToMasterInternal(connection_id);
@@ -222,15 +482,13 @@
EXPECT_EQ(1u, n);
EXPECT_EQ('x', c);
- test_io_thread.PostTaskAndWait(
+ test_io_thread().PostTaskAndWait(
FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
base::Unretained(&slave_ipc_support)));
- EXPECT_TRUE(master_process_delegate.TryWaitForOnSlaveDisconnect());
+ EXPECT_TRUE(master_process_delegate().TryWaitForOnSlaveDisconnect());
- test_io_thread.PostTaskAndWait(
- FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
- base::Unretained(&master_ipc_support)));
+ ShutdownMasterIPCSupport();
}
// This is a true multiprocess version of IPCSupportTest.MasterSlaveInternal.
@@ -244,22 +502,13 @@
#else
#define MAYBE_MultiprocessMasterSlaveInternal MultiprocessMasterSlaveInternal
#endif // defined(OS_ANDROID)
-TEST(IPCSupportTest, MAYBE_MultiprocessMasterSlaveInternal) {
- embedder::SimplePlatformSupport platform_support;
- base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
- TestMasterProcessDelegate master_process_delegate;
- // Note: Run process delegate methods on the I/O thread.
- IPCSupport ipc_support(&platform_support, embedder::ProcessType::MASTER,
- test_io_thread.task_runner(), &master_process_delegate,
- test_io_thread.task_runner(),
- embedder::ScopedPlatformHandle());
-
+TEST_F(IPCSupportTest, MAYBE_MultiprocessMasterSlaveInternal) {
ConnectionIdentifier connection_id =
- ipc_support.GenerateConnectionIdentifier();
+ master_ipc_support().GenerateConnectionIdentifier();
mojo::test::MultiprocessTestHelper multiprocess_test_helper;
ProcessIdentifier slave_id = kInvalidProcessIdentifier;
embedder::ScopedPlatformHandle second_platform_handle =
- ipc_support.ConnectToSlaveInternal(
+ master_ipc_support().ConnectToSlaveInternal(
connection_id, nullptr,
multiprocess_test_helper.server_platform_handle.Pass(), &slave_id);
ASSERT_TRUE(second_platform_handle.is_valid());
@@ -283,12 +532,10 @@
EXPECT_EQ(1u, n);
EXPECT_EQ('!', c);
- EXPECT_TRUE(master_process_delegate.TryWaitForOnSlaveDisconnect());
+ EXPECT_TRUE(master_process_delegate().TryWaitForOnSlaveDisconnect());
EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown());
- test_io_thread.PostTaskAndWait(FROM_HERE,
- base::Bind(&IPCSupport::ShutdownOnIOThread,
- base::Unretained(&ipc_support)));
+ ShutdownMasterIPCSupport();
}
MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlaveInternal) {