1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ipc/mojo/ipc_channel_mojo.h"
7 #include "base/base_paths.h"
8 #include "base/files/file.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/pickle.h"
12 #include "base/threading/thread.h"
13 #include "ipc/ipc_message.h"
14 #include "ipc/ipc_test_base.h"
15 #include "ipc/ipc_test_channel_listener.h"
16 #include "ipc/mojo/ipc_channel_mojo_host.h"
17 #include "ipc/mojo/ipc_channel_mojo_readers.h"
20 #include "base/file_descriptor_posix.h"
25 class ListenerThatExpectsOK : public IPC::Listener {
27 ListenerThatExpectsOK()
28 : received_ok_(false) {}
30 ~ListenerThatExpectsOK() override {}
32 bool OnMessageReceived(const IPC::Message& message) override {
33 PickleIterator iter(message);
34 std::string should_be_ok;
35 EXPECT_TRUE(iter.ReadString(&should_be_ok));
36 EXPECT_EQ(should_be_ok, "OK");
38 base::MessageLoop::current()->Quit();
42 void OnChannelError() override {
43 // The connection should be healthy while the listener is waiting
44 // message. An error can occur after that because the peer
49 static void SendOK(IPC::Sender* sender) {
50 IPC::Message* message = new IPC::Message(
51 0, 2, IPC::Message::PRIORITY_NORMAL);
52 message->WriteString(std::string("OK"));
53 ASSERT_TRUE(sender->Send(message));
62 explicit ChannelClient(IPC::Listener* listener, const char* name) {
63 channel_ = IPC::ChannelMojo::Create(NULL,
64 IPCTestBase::GetChannelName(name),
65 IPC::Channel::MODE_CLIENT,
70 CHECK(channel_->Connect());
73 IPC::ChannelMojo* channel() const { return channel_.get(); }
76 base::MessageLoopForIO main_message_loop_;
77 scoped_ptr<IPC::ChannelMojo> channel_;
80 class IPCChannelMojoTest : public IPCTestBase {
82 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
83 const IPC::ChannelHandle& handle,
84 base::TaskRunner* runner) override {
85 host_.reset(new IPC::ChannelMojoHost(task_runner()));
86 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
90 bool DidStartClient() override {
91 bool ok = IPCTestBase::DidStartClient();
93 host_->OnClientLaunched(client_process());
98 scoped_ptr<IPC::ChannelMojoHost> host_;
102 class TestChannelListenerWithExtraExpectations
103 : public IPC::TestChannelListener {
105 TestChannelListenerWithExtraExpectations()
106 : is_connected_called_(false) {
109 void OnChannelConnected(int32 peer_pid) override {
110 IPC::TestChannelListener::OnChannelConnected(peer_pid);
111 EXPECT_TRUE(base::kNullProcessId != peer_pid);
112 is_connected_called_ = true;
115 bool is_connected_called() const { return is_connected_called_; }
118 bool is_connected_called_;
121 TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
122 Init("IPCChannelMojoTestClient");
124 // Set up IPC channel and start client.
125 TestChannelListenerWithExtraExpectations listener;
126 CreateChannel(&listener);
127 listener.Init(sender());
128 ASSERT_TRUE(ConnectChannel());
129 ASSERT_TRUE(StartClient());
131 IPC::TestChannelListener::SendOneMessage(
132 sender(), "hello from parent");
134 base::MessageLoop::current()->Run();
135 EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());
137 this->channel()->Close();
139 EXPECT_TRUE(WaitForClientShutdown());
140 EXPECT_TRUE(listener.is_connected_called());
141 EXPECT_TRUE(listener.HasSentAll());
146 // A long running process that connects to us
147 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
148 TestChannelListenerWithExtraExpectations listener;
149 ChannelClient client(&listener, "IPCChannelMojoTestClient");
151 listener.Init(client.channel());
153 IPC::TestChannelListener::SendOneMessage(
154 client.channel(), "hello from child");
155 base::MessageLoop::current()->Run();
156 EXPECT_TRUE(listener.is_connected_called());
157 EXPECT_TRUE(listener.HasSentAll());
162 class ListenerExpectingErrors : public IPC::Listener {
164 ListenerExpectingErrors()
165 : has_error_(false) {
168 void OnChannelConnected(int32 peer_pid) override {
169 base::MessageLoop::current()->Quit();
172 bool OnMessageReceived(const IPC::Message& message) override { return true; }
174 void OnChannelError() override {
176 base::MessageLoop::current()->Quit();
179 bool has_error() const { return has_error_; }
186 class IPCChannelMojoErrorTest : public IPCTestBase {
188 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
189 const IPC::ChannelHandle& handle,
190 base::TaskRunner* runner) override {
191 host_.reset(new IPC::ChannelMojoHost(task_runner()));
192 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
196 bool DidStartClient() override {
197 bool ok = IPCTestBase::DidStartClient();
199 host_->OnClientLaunched(client_process());
204 scoped_ptr<IPC::ChannelMojoHost> host_;
207 class ListenerThatQuits : public IPC::Listener {
209 ListenerThatQuits() {
212 bool OnMessageReceived(const IPC::Message& message) override {
216 void OnChannelConnected(int32 peer_pid) override {
217 base::MessageLoop::current()->Quit();
221 // A long running process that connects to us.
222 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
223 ListenerThatQuits listener;
224 ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
227 base::MessageLoop::current()->Run();
232 TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
233 Init("IPCChannelMojoErraticTestClient");
235 // Set up IPC channel and start client.
236 ListenerExpectingErrors listener;
237 CreateChannel(&listener);
238 ASSERT_TRUE(ConnectChannel());
240 // This matches a value in mojo/edk/system/constants.h
241 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
242 std::string overly_large_data(kMaxMessageNumBytes, '*');
243 // This messages are queued as pending.
244 for (size_t i = 0; i < 10; ++i) {
245 IPC::TestChannelListener::SendOneMessage(
246 sender(), overly_large_data.c_str());
249 ASSERT_TRUE(StartClient());
250 base::MessageLoop::current()->Run();
252 this->channel()->Close();
254 EXPECT_TRUE(WaitForClientShutdown());
255 EXPECT_TRUE(listener.has_error());
261 class IPCChannelMojoDeadHandleTest : public IPCTestBase {
263 virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
264 const IPC::ChannelHandle& handle,
265 base::TaskRunner* runner) override {
266 host_.reset(new IPC::ChannelMojoHost(task_runner()));
267 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
271 virtual bool DidStartClient() override {
272 IPCTestBase::DidStartClient();
273 base::ProcessHandle client = client_process();
274 // Forces GetFileHandleForProcess() fail. It happens occasionally
275 // in production, so we should exercise it somehow.
276 ::CloseHandle(client);
277 host_->OnClientLaunched(client);
282 scoped_ptr<IPC::ChannelMojoHost> host_;
285 TEST_F(IPCChannelMojoDeadHandleTest, InvalidClientHandle) {
286 // Any client type is fine as it is going to be killed anyway.
287 Init("IPCChannelMojoTestDoNothingClient");
289 // Set up IPC channel and start client.
290 ListenerExpectingErrors listener;
291 CreateChannel(&listener);
292 ASSERT_TRUE(ConnectChannel());
294 ASSERT_TRUE(StartClient());
295 base::MessageLoop::current()->Run();
297 this->channel()->Close();
299 // WaitForClientShutdown() fails as client_hanadle() is already
301 EXPECT_FALSE(WaitForClientShutdown());
302 EXPECT_TRUE(listener.has_error());
307 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient) {
308 ListenerThatQuits listener;
309 ChannelClient client(&listener, "IPCChannelMojoTestDoNothingClient");
312 // Quits without running the message loop as this client won't
313 // receive any messages from the server.
319 #if defined(OS_POSIX)
320 class ListenerThatExpectsFile : public IPC::Listener {
322 ListenerThatExpectsFile()
325 ~ListenerThatExpectsFile() override {}
327 bool OnMessageReceived(const IPC::Message& message) override {
328 PickleIterator iter(message);
331 EXPECT_TRUE(message.ReadFile(&iter, &fd));
332 base::File file(fd.release());
333 std::string content(GetSendingFileContent().size(), ' ');
334 file.Read(0, &content[0], content.size());
335 EXPECT_EQ(content, GetSendingFileContent());
336 base::MessageLoop::current()->Quit();
337 ListenerThatExpectsOK::SendOK(sender_);
341 void OnChannelError() override {
345 static std::string GetSendingFileContent() {
349 static base::FilePath GetSendingFilePath() {
351 bool ok = PathService::Get(base::DIR_CACHE, &path);
353 return path.Append("ListenerThatExpectsFile.txt");
356 static void WriteAndSendFile(IPC::Sender* sender, base::File& file) {
357 std::string content = GetSendingFileContent();
358 file.WriteAtCurrentPos(content.data(), content.size());
360 IPC::Message* message = new IPC::Message(
361 0, 2, IPC::Message::PRIORITY_NORMAL);
362 message->WriteFile(base::ScopedFD(file.TakePlatformFile()));
363 ASSERT_TRUE(sender->Send(message));
366 void set_sender(IPC::Sender* sender) { sender_ = sender; }
369 IPC::Sender* sender_;
373 TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
374 Init("IPCChannelMojoTestSendPlatformHandleClient");
376 ListenerThatExpectsOK listener;
377 CreateChannel(&listener);
378 ASSERT_TRUE(ConnectChannel());
379 ASSERT_TRUE(StartClient());
381 base::File file(ListenerThatExpectsFile::GetSendingFilePath(),
382 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
383 base::File::FLAG_READ);
384 ListenerThatExpectsFile::WriteAndSendFile(channel(), file);
385 base::MessageLoop::current()->Run();
387 this->channel()->Close();
389 EXPECT_TRUE(WaitForClientShutdown());
393 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
394 ListenerThatExpectsFile listener;
395 ChannelClient client(
396 &listener, "IPCChannelMojoTestSendPlatformHandleClient");
398 listener.set_sender(client.channel());
400 base::MessageLoop::current()->Run();