| Index: third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc
|
| diff --git a/third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc b/third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc
|
| deleted file mode 100644
|
| index 31a1ac54daa48dcd1aa6089a7e9508ead18a936e..0000000000000000000000000000000000000000
|
| --- a/third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc
|
| +++ /dev/null
|
| @@ -1,732 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "third_party/mojo/src/mojo/edk/system/ipc_support.h"
|
| -
|
| -#include <utility>
|
| -#include <vector>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/command_line.h"
|
| -#include "base/location.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/run_loop.h"
|
| -#include "base/synchronization/waitable_event.h"
|
| -#include "base/test/test_io_thread.h"
|
| -#include "base/test/test_timeouts.h"
|
| -#include "mojo/public/cpp/system/macros.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -#include "third_party/mojo/src/mojo/edk/embedder/master_process_delegate.h"
|
| -#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
|
| -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h"
|
| -#include "third_party/mojo/src/mojo/edk/embedder/slave_process_delegate.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/channel_manager.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/connection_identifier.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/dispatcher.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/message_pipe.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/process_identifier.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/test_utils.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/waiter.h"
|
| -#include "third_party/mojo/src/mojo/edk/test/multiprocess_test_helper.h"
|
| -#include "third_party/mojo/src/mojo/edk/test/test_utils.h"
|
| -
|
| -namespace mojo {
|
| -namespace system {
|
| -namespace {
|
| -
|
| -const char kConnectionIdFlag[] = "test-connection-id";
|
| -
|
| -// 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,
|
| - read_mp->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, nullptr));
|
| -
|
| - // Write a message with just 'x' through the write end.
|
| - EXPECT_EQ(MOJO_RESULT_OK,
|
| - 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));
|
| - read_mp->RemoveAwakable(&waiter, nullptr);
|
| -
|
| - // 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,
|
| - 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]);
|
| -}
|
| -
|
| -// 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()));
|
| -}
|
| -
|
| -class TestMasterProcessDelegate : public embedder::MasterProcessDelegate {
|
| - public:
|
| - TestMasterProcessDelegate() : slave_disconnected_(false) {}
|
| - ~TestMasterProcessDelegate() override {}
|
| -
|
| - // Warning: There's only one slave disconnect event (which resets
|
| - // automatically).
|
| - void TryWaitForOnSlaveDisconnect() {
|
| - if (!slave_disconnected_)
|
| - run_loop_.Run();
|
| - }
|
| -
|
| - private:
|
| - // |embedder::MasterProcessDelegate| methods:
|
| - void OnShutdownComplete() override { NOTREACHED(); }
|
| -
|
| - void OnSlaveDisconnect(embedder::SlaveInfo /*slave_info*/) override {
|
| - slave_disconnected_ = true;
|
| - if (run_loop_.running())
|
| - run_loop_.Quit();
|
| - }
|
| -
|
| - bool slave_disconnected_;
|
| - base::RunLoop run_loop_;
|
| -
|
| - MOJO_DISALLOW_COPY_AND_ASSIGN(TestMasterProcessDelegate);
|
| -};
|
| -
|
| -class TestSlaveProcessDelegate : public embedder::SlaveProcessDelegate {
|
| - public:
|
| - TestSlaveProcessDelegate() {}
|
| - ~TestSlaveProcessDelegate() override {}
|
| -
|
| - private:
|
| - // |embedder::SlaveProcessDelegate| methods:
|
| - void OnShutdownComplete() override { NOTREACHED(); }
|
| -
|
| - void OnMasterDisconnect() override { NOTREACHED(); }
|
| -
|
| - MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlaveProcessDelegate);
|
| -};
|
| -
|
| -// 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 std::move(slave_platform_handle_);
|
| - }
|
| -
|
| - 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_;
|
| -
|
| - MOJO_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,
|
| - &slave_process_delegate_,
|
| - test_io_thread->task_runner(),
|
| - std::move(platform_handle)),
|
| - 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_;
|
| -
|
| - MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlave);
|
| -};
|
| -
|
| -// Encapsulates both the master and slave sides for each slave.
|
| -class TestSlaveSetup {
|
| - public:
|
| - TestSlaveSetup(embedder::SimplePlatformSupport* platform_support,
|
| - base::TestIOThread* test_io_thread,
|
| - TestMasterProcessDelegate* master_process_delegate,
|
| - IPCSupport* master_ipc_support)
|
| - : platform_support_(platform_support),
|
| - test_io_thread_(test_io_thread),
|
| - master_process_delegate_(master_process_delegate),
|
| - master_ipc_support_(master_ipc_support) {}
|
| - ~TestSlaveSetup() {
|
| - CHECK(!slave_connection_);
|
| - CHECK(!slave_);
|
| - }
|
| -
|
| - void Init() {
|
| - // Set up the master side entirely before the slave side, since this
|
| - // simulates what's likely to happen "in reality" more closely.
|
| - slave_connection_.reset(
|
| - new TestSlaveConnection(test_io_thread_, master_ipc_support_));
|
| - master_mp_ = slave_connection_->ConnectToSlave();
|
| -
|
| - slave_.reset(new TestSlave(platform_support_, test_io_thread_,
|
| - slave_connection_->PassSlavePlatformHandle()));
|
| - slave_mp_ = slave_->ConnectToMaster(slave_connection_->connection_id());
|
| - }
|
| -
|
| - void TestConnection() {
|
| - TestWriteReadMessage(master_mp_, slave_mp_);
|
| - TestWriteReadMessage(slave_mp_, master_mp_);
|
| - }
|
| -
|
| - scoped_refptr<MessagePipeDispatcher> PassMasterMessagePipe() {
|
| - return std::move(master_mp_);
|
| - }
|
| -
|
| - scoped_refptr<MessagePipeDispatcher> PassSlaveMessagePipe() {
|
| - return std::move(slave_mp_);
|
| - }
|
| -
|
| - void Shutdown() {
|
| - if (master_mp_) {
|
| - master_mp_->Close();
|
| - master_mp_ = nullptr;
|
| - }
|
| - if (slave_mp_) {
|
| - slave_mp_->Close();
|
| - slave_mp_ = nullptr;
|
| - }
|
| -
|
| - slave_->ShutdownChannelToMaster();
|
| - slave_->ShutdownIPCSupport();
|
| - master_process_delegate_->TryWaitForOnSlaveDisconnect();
|
| - slave_connection_->ShutdownChannelToSlave();
|
| -
|
| - slave_.reset();
|
| - slave_connection_.reset();
|
| - }
|
| -
|
| - TestSlaveConnection* slave_connection() { return slave_connection_.get(); }
|
| - // Note: To close the master message pipe, use |PassMasterMessagePipe()|.
|
| - MessagePipeDispatcher* master_mp() { return master_mp_.get(); }
|
| -
|
| - TestSlave* slave() { return slave_.get(); }
|
| - // Note: To close the slave message pipe, use |PassSlaveMessagePipe()|.
|
| - MessagePipeDispatcher* slave_mp() { return slave_mp_.get(); }
|
| -
|
| - private:
|
| - embedder::SimplePlatformSupport* const platform_support_;
|
| - base::TestIOThread* const test_io_thread_;
|
| - TestMasterProcessDelegate* const master_process_delegate_;
|
| - IPCSupport* const master_ipc_support_;
|
| -
|
| - scoped_ptr<TestSlaveConnection> slave_connection_;
|
| - scoped_refptr<MessagePipeDispatcher> master_mp_;
|
| -
|
| - scoped_ptr<TestSlave> slave_;
|
| - scoped_refptr<MessagePipeDispatcher> slave_mp_;
|
| -
|
| - MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlaveSetup);
|
| -};
|
| -
|
| -class IPCSupportTest : public testing::Test {
|
| - public:
|
| - // Note: Run master process delegate methods on the I/O thread.
|
| - IPCSupportTest()
|
| - : test_io_thread_(base::TestIOThread::kAutoStart),
|
| - master_ipc_support_(&platform_support_,
|
| - embedder::ProcessType::MASTER,
|
| - &master_process_delegate_,
|
| - test_io_thread_.task_runner(),
|
| - embedder::ScopedPlatformHandle()) {}
|
| - ~IPCSupportTest() override {}
|
| -
|
| - scoped_ptr<TestSlaveSetup> SetupSlave() {
|
| - scoped_ptr<TestSlaveSetup> s(
|
| - new TestSlaveSetup(&platform_support_, &test_io_thread_,
|
| - &master_process_delegate_, &master_ipc_support_));
|
| - s->Init();
|
| - return s;
|
| - }
|
| -
|
| - void ShutdownMasterIPCSupport() {
|
| - test_io_thread_.PostTaskAndWait(
|
| - FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
|
| - base::Unretained(&master_ipc_support_)));
|
| - }
|
| -
|
| - 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_; }
|
| -
|
| - private:
|
| - base::MessageLoop message_loop_;
|
| - embedder::SimplePlatformSupport platform_support_;
|
| - base::TestIOThread test_io_thread_;
|
| -
|
| - // All tests require a master.
|
| - TestMasterProcessDelegate master_process_delegate_;
|
| - IPCSupport master_ipc_support_;
|
| -
|
| - MOJO_DISALLOW_COPY_AND_ASSIGN(IPCSupportTest);
|
| -};
|
| -
|
| -using MessagePipeDispatcherPair =
|
| - std::pair<scoped_refptr<MessagePipeDispatcher>,
|
| - scoped_refptr<MessagePipeDispatcher>>;
|
| -MessagePipeDispatcherPair CreateMessagePipe() {
|
| - MessagePipeDispatcherPair rv;
|
| - rv.first = MessagePipeDispatcher::Create(
|
| - MessagePipeDispatcher::kDefaultCreateOptions);
|
| - rv.second = MessagePipeDispatcher::Create(
|
| - MessagePipeDispatcher::kDefaultCreateOptions);
|
| - scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
|
| - rv.first->Init(mp, 0);
|
| - rv.second->Init(mp, 1);
|
| - return rv;
|
| -}
|
| -
|
| -TEST_F(IPCSupportTest, MasterSlave) {
|
| - scoped_ptr<TestSlaveSetup> s(SetupSlave());
|
| -
|
| - s->TestConnection();
|
| -
|
| - // Don't need the message pipe anymore.
|
| - s->PassMasterMessagePipe()->Close();
|
| - s->PassSlaveMessagePipe()->Close();
|
| -
|
| - // 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.
|
| - s->slave_connection()->WaitForChannelToSlave();
|
| - s->slave()->WaitForChannelToMaster();
|
| -
|
| - s->Shutdown();
|
| -
|
| - ShutdownMasterIPCSupport();
|
| -}
|
| -
|
| -// 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) {
|
| - scoped_ptr<TestSlaveSetup> s1(SetupSlave());
|
| - scoped_ptr<TestSlaveSetup> s2(SetupSlave());
|
| - s1->TestConnection();
|
| - s2->TestConnection();
|
| -
|
| - // Make a message pipe (logically "in" the master) and send one end to each
|
| - // slave.
|
| - MessagePipeDispatcherPair send_mp = CreateMessagePipe();
|
| - scoped_refptr<MessagePipeDispatcher> slave1_received_mp =
|
| - SendMessagePipeDispatcher(s1->master_mp(), s1->slave_mp(), send_mp.first);
|
| - scoped_refptr<MessagePipeDispatcher> slave2_received_mp =
|
| - SendMessagePipeDispatcher(s2->master_mp(), s2->slave_mp(),
|
| - send_mp.second);
|
| -
|
| - // These should be connected.
|
| - TestWriteReadMessage(slave1_received_mp, slave2_received_mp);
|
| - TestWriteReadMessage(slave2_received_mp, slave1_received_mp);
|
| -
|
| - s1->PassMasterMessagePipe()->Close();
|
| - s2->PassMasterMessagePipe()->Close();
|
| - s1->PassSlaveMessagePipe()->Close();
|
| - s2->PassSlaveMessagePipe()->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();
|
| -
|
| - s1->Shutdown();
|
| - s2->Shutdown();
|
| -
|
| - ShutdownMasterIPCSupport();
|
| -}
|
| -
|
| -// Like |ConnectTwoSlaves|, but does it twice, to test reusing a connection.
|
| -TEST_F(IPCSupportTest, ConnectTwoSlavesTwice) {
|
| - scoped_ptr<TestSlaveSetup> s1(SetupSlave());
|
| - scoped_ptr<TestSlaveSetup> s2(SetupSlave());
|
| - s1->TestConnection();
|
| - s2->TestConnection();
|
| -
|
| - MessagePipeDispatcherPair send_mp1 = CreateMessagePipe();
|
| - scoped_refptr<MessagePipeDispatcher> slave1_received_mp1 =
|
| - SendMessagePipeDispatcher(s1->master_mp(), s1->slave_mp(),
|
| - send_mp1.first);
|
| - scoped_refptr<MessagePipeDispatcher> slave2_received_mp1 =
|
| - SendMessagePipeDispatcher(s2->master_mp(), s2->slave_mp(),
|
| - send_mp1.second);
|
| -
|
| - MessagePipeDispatcherPair send_mp2 = CreateMessagePipe();
|
| - scoped_refptr<MessagePipeDispatcher> slave1_received_mp2 =
|
| - SendMessagePipeDispatcher(s1->master_mp(), s1->slave_mp(),
|
| - send_mp2.first);
|
| - scoped_refptr<MessagePipeDispatcher> slave2_received_mp2 =
|
| - SendMessagePipeDispatcher(s2->master_mp(), s2->slave_mp(),
|
| - send_mp2.second);
|
| -
|
| - s1->PassMasterMessagePipe()->Close();
|
| - s2->PassMasterMessagePipe()->Close();
|
| - s1->PassSlaveMessagePipe()->Close();
|
| - s2->PassSlaveMessagePipe()->Close();
|
| -
|
| - TestWriteReadMessage(slave1_received_mp1, slave2_received_mp1);
|
| - TestWriteReadMessage(slave2_received_mp1, slave1_received_mp1);
|
| -
|
| - TestWriteReadMessage(slave1_received_mp2, slave2_received_mp2);
|
| - TestWriteReadMessage(slave2_received_mp2, slave1_received_mp2);
|
| -
|
| - slave1_received_mp1->Close();
|
| - slave2_received_mp1->Close();
|
| -
|
| - TestWriteReadMessage(slave1_received_mp2, slave2_received_mp2);
|
| - TestWriteReadMessage(slave2_received_mp2, slave1_received_mp2);
|
| -
|
| - slave1_received_mp2->Close();
|
| - slave2_received_mp2->Close();
|
| -
|
| - s1->Shutdown();
|
| - s2->Shutdown();
|
| -
|
| - ShutdownMasterIPCSupport();
|
| -}
|
| -
|
| -// Creates a message pipe in the slave, which sends both ends (in separate
|
| -// messages) to the master.
|
| -TEST_F(IPCSupportTest, SlavePassBackToMaster) {
|
| - scoped_ptr<TestSlaveSetup> s(SetupSlave());
|
| -
|
| - s->TestConnection();
|
| -
|
| - // Make a message pipe (logically "in" the slave) and send both ends
|
| - // (separately) to the master.
|
| - MessagePipeDispatcherPair send_mp = CreateMessagePipe();
|
| - scoped_refptr<MessagePipeDispatcher> received_mp1 =
|
| - SendMessagePipeDispatcher(s->slave_mp(), s->master_mp(), send_mp.first);
|
| -
|
| - TestWriteReadMessage(received_mp1, send_mp.second);
|
| - TestWriteReadMessage(send_mp.second, received_mp1);
|
| -
|
| - scoped_refptr<MessagePipeDispatcher> received_mp2 =
|
| - SendMessagePipeDispatcher(s->slave_mp(), s->master_mp(), send_mp.second);
|
| -
|
| - s->PassMasterMessagePipe()->Close();
|
| - s->PassSlaveMessagePipe()->Close();
|
| -
|
| - TestWriteReadMessage(received_mp1, received_mp2);
|
| - TestWriteReadMessage(received_mp2, received_mp1);
|
| -
|
| - s->Shutdown();
|
| -
|
| - // These should still be connected.
|
| - // TODO(vtl): This is not yet implemented, thus will fail here!
|
| - // TestWriteReadMessage(received_mp1, received_mp2);
|
| - // TestWriteReadMessage(received_mp2, received_mp1);
|
| -
|
| - received_mp1->Close();
|
| - received_mp2->Close();
|
| -
|
| - ShutdownMasterIPCSupport();
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// Note: This test isn't in an anonymous namespace, since it needs to be
|
| -// friended by |IPCSupport|.
|
| -TEST_F(IPCSupportTest, MasterSlaveInternal) {
|
| - ConnectionIdentifier connection_id =
|
| - master_ipc_support().GenerateConnectionIdentifier();
|
| -
|
| - embedder::PlatformChannelPair channel_pair;
|
| - ProcessIdentifier slave_id = kInvalidProcessIdentifier;
|
| - embedder::ScopedPlatformHandle master_second_platform_handle =
|
| - 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);
|
| - EXPECT_NE(slave_id, kMasterProcessIdentifier);
|
| -
|
| - TestSlaveProcessDelegate slave_process_delegate;
|
| - // Note: Run process delegate methods on the I/O thread.
|
| - IPCSupport slave_ipc_support(
|
| - &platform_support(), embedder::ProcessType::SLAVE,
|
| - &slave_process_delegate, test_io_thread().task_runner(),
|
| - channel_pair.PassClientHandle());
|
| -
|
| - embedder::ScopedPlatformHandle slave_second_platform_handle =
|
| - slave_ipc_support.ConnectToMasterInternal(connection_id);
|
| - ASSERT_TRUE(slave_second_platform_handle.is_valid());
|
| -
|
| - // Write an 'x' through the master's end.
|
| - size_t n = 0;
|
| - EXPECT_TRUE(mojo::test::BlockingWrite(master_second_platform_handle.get(),
|
| - "x", 1, &n));
|
| - EXPECT_EQ(1u, n);
|
| -
|
| - // Read it from the slave's end.
|
| - char c = '\0';
|
| - n = 0;
|
| - EXPECT_TRUE(
|
| - mojo::test::BlockingRead(slave_second_platform_handle.get(), &c, 1, &n));
|
| - EXPECT_EQ(1u, n);
|
| - EXPECT_EQ('x', c);
|
| -
|
| - test_io_thread().PostTaskAndWait(
|
| - FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
|
| - base::Unretained(&slave_ipc_support)));
|
| -
|
| - master_process_delegate().TryWaitForOnSlaveDisconnect();
|
| -
|
| - ShutdownMasterIPCSupport();
|
| -}
|
| -
|
| -// This is a true multiprocess version of IPCSupportTest.MasterSlaveInternal.
|
| -// Note: This test isn't in an anonymous namespace, since it needs to be
|
| -// friended by |IPCSupport|.
|
| -#if defined(OS_ANDROID)
|
| -// Android multi-process tests are not executing the new process. This is flaky.
|
| -// TODO(vtl): I'm guessing this is true of this test too?
|
| -#define MAYBE_MultiprocessMasterSlaveInternal \
|
| - DISABLED_MultiprocessMasterSlaveInternal
|
| -#else
|
| -#define MAYBE_MultiprocessMasterSlaveInternal MultiprocessMasterSlaveInternal
|
| -#endif // defined(OS_ANDROID)
|
| -TEST_F(IPCSupportTest, MAYBE_MultiprocessMasterSlaveInternal) {
|
| - ConnectionIdentifier connection_id =
|
| - master_ipc_support().GenerateConnectionIdentifier();
|
| - mojo::test::MultiprocessTestHelper multiprocess_test_helper;
|
| - ProcessIdentifier slave_id = kInvalidProcessIdentifier;
|
| - embedder::ScopedPlatformHandle second_platform_handle =
|
| - master_ipc_support().ConnectToSlaveInternal(
|
| - connection_id, nullptr,
|
| - std::move(multiprocess_test_helper.server_platform_handle),
|
| - &slave_id);
|
| - ASSERT_TRUE(second_platform_handle.is_valid());
|
| - EXPECT_NE(slave_id, kInvalidProcessIdentifier);
|
| - EXPECT_NE(slave_id, kMasterProcessIdentifier);
|
| -
|
| - multiprocess_test_helper.StartChildWithExtraSwitch(
|
| - "MultiprocessMasterSlaveInternal", kConnectionIdFlag,
|
| - connection_id.ToString());
|
| -
|
| - // We write a '?'. The slave should write a '!' in response.
|
| - size_t n = 0;
|
| - EXPECT_TRUE(
|
| - mojo::test::BlockingWrite(second_platform_handle.get(), "?", 1, &n));
|
| - EXPECT_EQ(1u, n);
|
| -
|
| - char c = '\0';
|
| - n = 0;
|
| - EXPECT_TRUE(
|
| - mojo::test::BlockingRead(second_platform_handle.get(), &c, 1, &n));
|
| - EXPECT_EQ(1u, n);
|
| - EXPECT_EQ('!', c);
|
| -
|
| - master_process_delegate().TryWaitForOnSlaveDisconnect();
|
| - EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown());
|
| -
|
| - ShutdownMasterIPCSupport();
|
| -}
|
| -
|
| -MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlaveInternal) {
|
| - embedder::ScopedPlatformHandle client_platform_handle =
|
| - std::move(mojo::test::MultiprocessTestHelper::client_platform_handle);
|
| - ASSERT_TRUE(client_platform_handle.is_valid());
|
| -
|
| - embedder::SimplePlatformSupport platform_support;
|
| - base::MessageLoop message_loop;
|
| - base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
|
| - TestSlaveProcessDelegate slave_process_delegate;
|
| - // Note: Run process delegate methods on the I/O thread.
|
| - IPCSupport ipc_support(&platform_support, embedder::ProcessType::SLAVE,
|
| - &slave_process_delegate, test_io_thread.task_runner(),
|
| - std::move(client_platform_handle));
|
| -
|
| - const base::CommandLine& command_line =
|
| - *base::CommandLine::ForCurrentProcess();
|
| - ASSERT_TRUE(command_line.HasSwitch(kConnectionIdFlag));
|
| - bool ok = false;
|
| - ConnectionIdentifier connection_id = ConnectionIdentifier::FromString(
|
| - command_line.GetSwitchValueASCII(kConnectionIdFlag), &ok);
|
| - ASSERT_TRUE(ok);
|
| -
|
| - embedder::ScopedPlatformHandle second_platform_handle =
|
| - ipc_support.ConnectToMasterInternal(connection_id);
|
| - ASSERT_TRUE(second_platform_handle.is_valid());
|
| -
|
| - // The master should write a '?'. We'll write a '!' in response.
|
| - char c = '\0';
|
| - size_t n = 0;
|
| - EXPECT_TRUE(
|
| - mojo::test::BlockingRead(second_platform_handle.get(), &c, 1, &n));
|
| - EXPECT_EQ(1u, n);
|
| - EXPECT_EQ('?', c);
|
| -
|
| - n = 0;
|
| - EXPECT_TRUE(
|
| - mojo::test::BlockingWrite(second_platform_handle.get(), "!", 1, &n));
|
| - EXPECT_EQ(1u, n);
|
| -
|
| - test_io_thread.PostTaskAndWait(FROM_HERE,
|
| - base::Bind(&IPCSupport::ShutdownOnIOThread,
|
| - base::Unretained(&ipc_support)));
|
| -}
|
| -
|
| -// TODO(vtl): Also test the case of the master "dying" before the slave. (The
|
| -// slave should get OnMasterDisconnect(), which we currently don't test.)
|
| -
|
| -} // namespace system
|
| -} // namespace mojo
|
|
|