Index: ipc/mojo/ipc_channel_mojo_unittest.cc |
diff --git a/ipc/mojo/ipc_channel_mojo_unittest.cc b/ipc/mojo/ipc_channel_mojo_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..915029df56ffbfa3cd3de81c6276e0e579d74115 |
--- /dev/null |
+++ b/ipc/mojo/ipc_channel_mojo_unittest.cc |
@@ -0,0 +1,260 @@ |
+// Copyright 2014 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 "ipc/mojo/ipc_channel_mojo.h" |
+ |
+#include "base/base_paths.h" |
+#include "base/files/file.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/path_service.h" |
+#include "base/pickle.h" |
+#include "base/threading/thread.h" |
+#include "ipc/ipc_message.h" |
+#include "ipc/ipc_test_base.h" |
+#include "ipc/ipc_test_channel_listener.h" |
+ |
+#if defined(OS_POSIX) |
+#include "base/file_descriptor_posix.h" |
+#endif |
+ |
+namespace { |
+ |
+class ListenerThatExpectsOK : public IPC::Listener { |
+ public: |
+ ListenerThatExpectsOK() {} |
+ |
+ virtual ~ListenerThatExpectsOK() {} |
+ |
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
+ PickleIterator iter(message); |
+ std::string should_be_ok; |
+ EXPECT_TRUE(iter.ReadString(&should_be_ok)); |
+ EXPECT_EQ(should_be_ok, "OK"); |
+ base::MessageLoop::current()->Quit(); |
+ return true; |
+ } |
+ |
+ virtual void OnChannelError() OVERRIDE { |
+ NOTREACHED(); |
+ } |
+ |
+ static void SendOK(IPC::Sender* sender) { |
+ IPC::Message* message = new IPC::Message( |
+ 0, 2, IPC::Message::PRIORITY_NORMAL); |
+ message->WriteString(std::string("OK")); |
+ ASSERT_TRUE(sender->Send(message)); |
+ } |
+}; |
+ |
+class ListenerThatShouldBeNeverCalled : public IPC::Listener { |
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
+ NOTREACHED(); |
+ return true; |
+ } |
+ |
+ virtual void OnChannelError() OVERRIDE { |
+ NOTREACHED(); |
+ } |
+ |
+ virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { |
+ NOTREACHED(); |
+ } |
+ |
+ virtual void OnBadMessageReceived(const IPC::Message& message) OVERRIDE { |
+ NOTREACHED(); |
+ } |
+}; |
+ |
+class ChannelClient { |
+ public: |
+ explicit ChannelClient(IPC::Listener* listener, const char* name) { |
+ scoped_ptr<IPC::Channel> bootstrap(IPC::Channel::CreateClient( |
+ IPCTestBase::GetChannelName(name), |
+ &never_called_)); |
+ channel_ = IPC::ChannelMojo::Create( |
+ bootstrap.Pass(), IPC::Channel::MODE_CLIENT, listener, |
+ main_message_loop_.message_loop_proxy()); |
+ } |
+ |
+ void Connect() { |
+ CHECK(channel_->Connect()); |
+ } |
+ |
+ IPC::ChannelMojo* channel() const { return channel_.get(); } |
+ |
+ private: |
+ scoped_ptr<IPC::ChannelMojo> channel_; |
+ ListenerThatShouldBeNeverCalled never_called_; |
+ base::MessageLoopForIO main_message_loop_; |
+}; |
+ |
+class IPCChannelMojoTest : public IPCTestBase { |
+ public: |
+ void CreateMojoChannel(IPC::Listener* listener); |
+ |
+ protected: |
+ virtual void SetUp() OVERRIDE { |
+ IPCTestBase::SetUp(); |
+ } |
+ |
+ ListenerThatShouldBeNeverCalled never_called_; |
+}; |
+ |
+ |
+void IPCChannelMojoTest::CreateMojoChannel(IPC::Listener* listener) { |
+ CreateChannel(&never_called_); |
+ scoped_ptr<IPC::Channel> mojo_channel = IPC::ChannelMojo::Create( |
+ ReleaseChannel(), IPC::Channel::MODE_SERVER, listener, |
+ io_thread_task_runner()).PassAs<IPC::Channel>(); |
+ SetChannel(mojo_channel.PassAs<IPC::Channel>()); |
+} |
+ |
+class TestChannelListenerWithExtraExpectations |
+ : public IPC::TestChannelListener { |
+ public: |
+ TestChannelListenerWithExtraExpectations() |
+ : is_connected_called_(false) { |
+ } |
+ |
+ virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { |
+ IPC::TestChannelListener::OnChannelConnected(peer_pid); |
+ EXPECT_TRUE(base::kNullProcessId != peer_pid); |
+ is_connected_called_ = true; |
+ } |
+ |
+ bool is_connected_called() const { return is_connected_called_; } |
+ |
+ private: |
+ bool is_connected_called_; |
+}; |
+ |
+TEST_F(IPCChannelMojoTest, ConnectedFromClient) { |
+ Init("IPCChannelMojoTestClient"); |
+ |
+ // Set up IPC channel and start client. |
+ TestChannelListenerWithExtraExpectations listener; |
+ CreateMojoChannel(&listener); |
+ listener.Init(sender()); |
+ ASSERT_TRUE(ConnectChannel()); |
+ ASSERT_TRUE(StartClient()); |
+ |
+ IPC::TestChannelListener::SendOneMessage( |
+ sender(), "hello from parent"); |
+ |
+ base::MessageLoop::current()->Run(); |
+ EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID()); |
+ |
+ this->channel()->Close(); |
+ |
+ EXPECT_TRUE(WaitForClientShutdown()); |
+ EXPECT_TRUE(listener.is_connected_called()); |
+ EXPECT_TRUE(listener.HasSentAll()); |
+ |
+ DestroyChannel(); |
+} |
+ |
+// A long running process that connects to us |
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) { |
+ TestChannelListenerWithExtraExpectations listener; |
+ ChannelClient client(&listener, "IPCChannelMojoTestClient"); |
+ client.Connect(); |
+ listener.Init(client.channel()); |
+ |
+ IPC::TestChannelListener::SendOneMessage( |
+ client.channel(), "hello from child"); |
+ base::MessageLoop::current()->Run(); |
+ EXPECT_TRUE(listener.is_connected_called()); |
+ EXPECT_TRUE(listener.HasSentAll()); |
+ |
+ return 0; |
+} |
+ |
+#if defined(OS_POSIX) |
+class ListenerThatExpectsFile : public IPC::Listener { |
+ public: |
+ ListenerThatExpectsFile() |
+ : sender_(NULL) {} |
+ |
+ virtual ~ListenerThatExpectsFile() {} |
+ |
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
+ PickleIterator iter(message); |
+ base::FileDescriptor desc; |
+ EXPECT_TRUE(message.ReadFileDescriptor(&iter, &desc)); |
+ std::string content(GetSendingFileContent().size(), ' '); |
+ base::File file(desc.fd); |
+ file.Read(0, &content[0], content.size()); |
+ EXPECT_EQ(content, GetSendingFileContent()); |
+ base::MessageLoop::current()->Quit(); |
+ ListenerThatExpectsOK::SendOK(sender_); |
+ return true; |
+ } |
+ |
+ virtual void OnChannelError() OVERRIDE { |
+ NOTREACHED(); |
+ } |
+ |
+ static std::string GetSendingFileContent() { |
+ return "Hello"; |
+ } |
+ |
+ static base::FilePath GetSendingFilePath() { |
+ base::FilePath path; |
+ bool ok = PathService::Get(base::DIR_CACHE, &path); |
+ EXPECT_TRUE(ok); |
+ return path.Append("ListenerThatExpectsFile.txt"); |
+ } |
+ |
+ static void WriteAndSendFile(IPC::Sender* sender, base::File& file) { |
+ std::string content = GetSendingFileContent(); |
+ file.WriteAtCurrentPos(content.data(), content.size()); |
+ file.Flush(); |
+ IPC::Message* message = new IPC::Message( |
+ 0, 2, IPC::Message::PRIORITY_NORMAL); |
+ message->WriteFileDescriptor( |
+ base::FileDescriptor(file.TakePlatformFile(), false)); |
+ ASSERT_TRUE(sender->Send(message)); |
+ } |
+ |
+ void set_sender(IPC::Sender* sender) { sender_ = sender; } |
+ |
+ private: |
+ IPC::Sender* sender_; |
+}; |
+ |
+ |
+TEST_F(IPCChannelMojoTest, SendPlatformHandle) { |
+ Init("IPCChannelMojoTestSendPlatformHandleClient"); |
+ |
+ ListenerThatExpectsOK listener; |
+ CreateMojoChannel(&listener); |
+ ASSERT_TRUE(ConnectChannel()); |
+ ASSERT_TRUE(StartClient()); |
+ |
+ base::File file(ListenerThatExpectsFile::GetSendingFilePath(), |
+ base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | |
+ base::File::FLAG_READ); |
+ ListenerThatExpectsFile::WriteAndSendFile(channel(), file); |
+ base::MessageLoop::current()->Run(); |
+ |
+ this->channel()->Close(); |
+ |
+ EXPECT_TRUE(WaitForClientShutdown()); |
+ DestroyChannel(); |
+} |
+ |
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) { |
+ ListenerThatExpectsFile listener; |
+ ChannelClient client( |
+ &listener, "IPCChannelMojoTestSendPlatformHandleClient"); |
+ client.Connect(); |
+ listener.set_sender(client.channel()); |
+ |
+ base::MessageLoop::current()->Run(); |
+ |
+ return 0; |
+} |
+#endif |
+ |
+} // namespace |