[DevTools] Emulation domain implementation (browser side).
[chromium-blink-merge.git] / ipc / mojo / ipc_channel_mojo_unittest.cc
blob662e75829694e0358e206cfaa01be2983c40321a
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/run_loop.h"
13 #include "base/test/test_timeouts.h"
14 #include "base/threading/thread.h"
15 #include "ipc/ipc_message.h"
16 #include "ipc/ipc_test_base.h"
17 #include "ipc/ipc_test_channel_listener.h"
18 #include "ipc/mojo/ipc_channel_mojo_host.h"
19 #include "ipc/mojo/ipc_mojo_handle_attachment.h"
20 #include "ipc/mojo/ipc_mojo_message_helper.h"
21 #include "ipc/mojo/scoped_ipc_support.h"
23 #if defined(OS_POSIX)
24 #include "base/file_descriptor_posix.h"
25 #include "ipc/ipc_platform_file_attachment_posix.h"
26 #endif
28 namespace {
30 class ListenerThatExpectsOK : public IPC::Listener {
31 public:
32 ListenerThatExpectsOK()
33 : received_ok_(false) {}
35 ~ListenerThatExpectsOK() override {}
37 bool OnMessageReceived(const IPC::Message& message) override {
38 PickleIterator iter(message);
39 std::string should_be_ok;
40 EXPECT_TRUE(iter.ReadString(&should_be_ok));
41 EXPECT_EQ(should_be_ok, "OK");
42 received_ok_ = true;
43 base::MessageLoop::current()->Quit();
44 return true;
47 void OnChannelError() override {
48 // The connection should be healthy while the listener is waiting
49 // message. An error can occur after that because the peer
50 // process dies.
51 DCHECK(received_ok_);
54 static void SendOK(IPC::Sender* sender) {
55 IPC::Message* message = new IPC::Message(
56 0, 2, IPC::Message::PRIORITY_NORMAL);
57 message->WriteString(std::string("OK"));
58 ASSERT_TRUE(sender->Send(message));
61 private:
62 bool received_ok_;
65 class ChannelClient {
66 public:
67 explicit ChannelClient(IPC::Listener* listener, const char* name) {
68 ipc_support_.reset(
69 new IPC::ScopedIPCSupport(main_message_loop_.task_runner()));
70 channel_ = IPC::ChannelMojo::Create(NULL,
71 IPCTestBase::GetChannelName(name),
72 IPC::Channel::MODE_CLIENT,
73 listener);
76 void Connect() {
77 CHECK(channel_->Connect());
80 void Close() {
81 channel_->Close();
83 base::RunLoop run_loop;
84 base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
85 run_loop.Run();
88 IPC::ChannelMojo* channel() const { return channel_.get(); }
90 private:
91 base::MessageLoopForIO main_message_loop_;
92 scoped_ptr<IPC::ScopedIPCSupport> ipc_support_;
93 scoped_ptr<IPC::ChannelMojo> channel_;
96 class IPCChannelMojoTestBase : public IPCTestBase {
97 public:
98 void InitWithMojo(const std::string& test_client_name) {
99 Init(test_client_name);
100 ipc_support_.reset(new IPC::ScopedIPCSupport(task_runner()));
103 void TearDown() override {
104 // Make sure Mojo IPC support is properly shutdown on the I/O loop before
105 // TearDown continues.
106 ipc_support_.reset();
107 base::RunLoop run_loop;
108 task_runner()->PostTask(FROM_HERE, run_loop.QuitClosure());
109 run_loop.Run();
111 IPCTestBase::TearDown();
114 private:
115 scoped_ptr<IPC::ScopedIPCSupport> ipc_support_;
118 class IPCChannelMojoTest : public IPCChannelMojoTestBase {
119 protected:
120 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
121 const IPC::ChannelHandle& handle,
122 base::SequencedTaskRunner* runner) override {
123 host_.reset(new IPC::ChannelMojoHost(task_runner()));
124 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
125 handle);
128 bool DidStartClient() override {
129 bool ok = IPCTestBase::DidStartClient();
130 DCHECK(ok);
131 host_->OnClientLaunched(client_process().Handle());
132 return ok;
135 private:
136 scoped_ptr<IPC::ChannelMojoHost> host_;
140 class TestChannelListenerWithExtraExpectations
141 : public IPC::TestChannelListener {
142 public:
143 TestChannelListenerWithExtraExpectations()
144 : is_connected_called_(false) {
147 void OnChannelConnected(int32 peer_pid) override {
148 IPC::TestChannelListener::OnChannelConnected(peer_pid);
149 EXPECT_TRUE(base::kNullProcessId != peer_pid);
150 is_connected_called_ = true;
153 bool is_connected_called() const { return is_connected_called_; }
155 private:
156 bool is_connected_called_;
159 TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
160 InitWithMojo("IPCChannelMojoTestClient");
162 // Set up IPC channel and start client.
163 TestChannelListenerWithExtraExpectations listener;
164 CreateChannel(&listener);
165 listener.Init(sender());
166 ASSERT_TRUE(ConnectChannel());
167 ASSERT_TRUE(StartClient());
169 IPC::TestChannelListener::SendOneMessage(
170 sender(), "hello from parent");
172 base::MessageLoop::current()->Run();
173 EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());
175 this->channel()->Close();
177 EXPECT_TRUE(WaitForClientShutdown());
178 EXPECT_TRUE(listener.is_connected_called());
179 EXPECT_TRUE(listener.HasSentAll());
181 DestroyChannel();
184 // A long running process that connects to us
185 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
186 TestChannelListenerWithExtraExpectations listener;
187 ChannelClient client(&listener, "IPCChannelMojoTestClient");
188 client.Connect();
189 listener.Init(client.channel());
191 IPC::TestChannelListener::SendOneMessage(
192 client.channel(), "hello from child");
193 base::MessageLoop::current()->Run();
194 EXPECT_TRUE(listener.is_connected_called());
195 EXPECT_TRUE(listener.HasSentAll());
197 client.Close();
199 return 0;
202 class ListenerExpectingErrors : public IPC::Listener {
203 public:
204 ListenerExpectingErrors()
205 : has_error_(false) {
208 void OnChannelConnected(int32 peer_pid) override {
209 base::MessageLoop::current()->Quit();
212 bool OnMessageReceived(const IPC::Message& message) override { return true; }
214 void OnChannelError() override {
215 has_error_ = true;
216 base::MessageLoop::current()->Quit();
219 bool has_error() const { return has_error_; }
221 private:
222 bool has_error_;
226 class IPCChannelMojoErrorTest : public IPCChannelMojoTestBase {
227 protected:
228 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
229 const IPC::ChannelHandle& handle,
230 base::SequencedTaskRunner* runner) override {
231 host_.reset(new IPC::ChannelMojoHost(task_runner()));
232 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
233 handle);
236 bool DidStartClient() override {
237 bool ok = IPCTestBase::DidStartClient();
238 DCHECK(ok);
239 host_->OnClientLaunched(client_process().Handle());
240 return ok;
243 private:
244 scoped_ptr<IPC::ChannelMojoHost> host_;
247 class ListenerThatQuits : public IPC::Listener {
248 public:
249 ListenerThatQuits() {
252 bool OnMessageReceived(const IPC::Message& message) override {
253 return true;
256 void OnChannelConnected(int32 peer_pid) override {
257 base::MessageLoop::current()->Quit();
261 // A long running process that connects to us.
262 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
263 ListenerThatQuits listener;
264 ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
265 client.Connect();
267 base::MessageLoop::current()->Run();
269 client.Close();
271 return 0;
274 TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
275 InitWithMojo("IPCChannelMojoErraticTestClient");
277 // Set up IPC channel and start client.
278 ListenerExpectingErrors listener;
279 CreateChannel(&listener);
280 ASSERT_TRUE(ConnectChannel());
282 // This matches a value in mojo/edk/system/constants.h
283 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
284 std::string overly_large_data(kMaxMessageNumBytes, '*');
285 // This messages are queued as pending.
286 for (size_t i = 0; i < 10; ++i) {
287 IPC::TestChannelListener::SendOneMessage(
288 sender(), overly_large_data.c_str());
291 ASSERT_TRUE(StartClient());
292 base::MessageLoop::current()->Run();
294 this->channel()->Close();
296 EXPECT_TRUE(WaitForClientShutdown());
297 EXPECT_TRUE(listener.has_error());
299 DestroyChannel();
302 struct TestingMessagePipe {
303 TestingMessagePipe() {
304 EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateMessagePipe(nullptr, &self, &peer));
307 mojo::ScopedMessagePipeHandle self;
308 mojo::ScopedMessagePipeHandle peer;
311 class HandleSendingHelper {
312 public:
313 static std::string GetSendingFileContent() { return "Hello"; }
315 static void WritePipe(IPC::Message* message, TestingMessagePipe* pipe) {
316 std::string content = HandleSendingHelper::GetSendingFileContent();
317 EXPECT_EQ(MOJO_RESULT_OK,
318 mojo::WriteMessageRaw(pipe->self.get(), &content[0],
319 static_cast<uint32_t>(content.size()),
320 nullptr, 0, 0));
321 EXPECT_TRUE(
322 IPC::MojoMessageHelper::WriteMessagePipeTo(message, pipe->peer.Pass()));
325 static void WritePipeThenSend(IPC::Sender* sender, TestingMessagePipe* pipe) {
326 IPC::Message* message =
327 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
328 WritePipe(message, pipe);
329 ASSERT_TRUE(sender->Send(message));
332 static void ReadReceivedPipe(const IPC::Message& message,
333 PickleIterator* iter) {
334 mojo::ScopedMessagePipeHandle pipe;
335 EXPECT_TRUE(
336 IPC::MojoMessageHelper::ReadMessagePipeFrom(&message, iter, &pipe));
337 std::string content(GetSendingFileContent().size(), ' ');
339 uint32_t num_bytes = static_cast<uint32_t>(content.size());
340 EXPECT_EQ(MOJO_RESULT_OK,
341 mojo::ReadMessageRaw(pipe.get(), &content[0], &num_bytes, nullptr,
342 nullptr, 0));
343 EXPECT_EQ(content, GetSendingFileContent());
346 #if defined(OS_POSIX)
347 static base::FilePath GetSendingFilePath() {
348 base::FilePath path;
349 bool ok = PathService::Get(base::DIR_CACHE, &path);
350 EXPECT_TRUE(ok);
351 return path.Append("ListenerThatExpectsFile.txt");
354 static void WriteFile(IPC::Message* message, base::File& file) {
355 std::string content = GetSendingFileContent();
356 file.WriteAtCurrentPos(content.data(), content.size());
357 file.Flush();
358 message->WriteAttachment(new IPC::internal::PlatformFileAttachment(
359 base::ScopedFD(file.TakePlatformFile())));
362 static void WriteFileThenSend(IPC::Sender* sender, base::File& file) {
363 IPC::Message* message =
364 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
365 WriteFile(message, file);
366 ASSERT_TRUE(sender->Send(message));
369 static void WriteFileAndPipeThenSend(IPC::Sender* sender,
370 base::File& file,
371 TestingMessagePipe* pipe) {
372 IPC::Message* message =
373 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
374 WriteFile(message, file);
375 WritePipe(message, pipe);
376 ASSERT_TRUE(sender->Send(message));
379 static void ReadReceivedFile(const IPC::Message& message,
380 PickleIterator* iter) {
381 base::ScopedFD fd;
382 scoped_refptr<IPC::MessageAttachment> attachment;
383 EXPECT_TRUE(message.ReadAttachment(iter, &attachment));
384 base::File file(attachment->TakePlatformFile());
385 std::string content(GetSendingFileContent().size(), ' ');
386 file.Read(0, &content[0], content.size());
387 EXPECT_EQ(content, GetSendingFileContent());
389 #endif
392 class ListenerThatExpectsMessagePipe : public IPC::Listener {
393 public:
394 ListenerThatExpectsMessagePipe() : sender_(NULL) {}
396 ~ListenerThatExpectsMessagePipe() override {}
398 bool OnMessageReceived(const IPC::Message& message) override {
399 PickleIterator iter(message);
400 HandleSendingHelper::ReadReceivedPipe(message, &iter);
401 base::MessageLoop::current()->Quit();
402 ListenerThatExpectsOK::SendOK(sender_);
403 return true;
406 void OnChannelError() override { NOTREACHED(); }
408 void set_sender(IPC::Sender* sender) { sender_ = sender; }
410 private:
411 IPC::Sender* sender_;
414 TEST_F(IPCChannelMojoTest, SendMessagePipe) {
415 InitWithMojo("IPCChannelMojoTestSendMessagePipeClient");
417 ListenerThatExpectsOK listener;
418 CreateChannel(&listener);
419 ASSERT_TRUE(ConnectChannel());
420 ASSERT_TRUE(StartClient());
422 TestingMessagePipe pipe;
423 HandleSendingHelper::WritePipeThenSend(channel(), &pipe);
425 base::MessageLoop::current()->Run();
426 this->channel()->Close();
428 EXPECT_TRUE(WaitForClientShutdown());
429 DestroyChannel();
432 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendMessagePipeClient) {
433 ListenerThatExpectsMessagePipe listener;
434 ChannelClient client(&listener, "IPCChannelMojoTestSendMessagePipeClient");
435 client.Connect();
436 listener.set_sender(client.channel());
438 base::MessageLoop::current()->Run();
440 client.Close();
442 return 0;
445 #if defined(OS_WIN)
446 class IPCChannelMojoDeadHandleTest : public IPCChannelMojoTestBase {
447 protected:
448 virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
449 const IPC::ChannelHandle& handle,
450 base::SequencedTaskRunner* runner) override {
451 host_.reset(new IPC::ChannelMojoHost(task_runner()));
452 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
453 handle);
456 virtual bool DidStartClient() override {
457 IPCTestBase::DidStartClient();
458 const base::ProcessHandle client = client_process().Handle();
459 // Forces GetFileHandleForProcess() fail. It happens occasionally
460 // in production, so we should exercise it somehow.
461 // TODO(morrita): figure out how to safely test this. See crbug.com/464109.
462 // ::CloseHandle(client);
463 host_->OnClientLaunched(client);
464 return true;
467 private:
468 scoped_ptr<IPC::ChannelMojoHost> host_;
471 TEST_F(IPCChannelMojoDeadHandleTest, InvalidClientHandle) {
472 // Any client type is fine as it is going to be killed anyway.
473 InitWithMojo("IPCChannelMojoTestDoNothingClient");
475 // Set up IPC channel and start client.
476 ListenerExpectingErrors listener;
477 CreateChannel(&listener);
478 ASSERT_TRUE(ConnectChannel());
480 ASSERT_TRUE(StartClient());
481 base::MessageLoop::current()->Run();
483 this->channel()->Close();
485 // TODO(morrita): We need CloseHandle() call in DidStartClient(),
486 // which has been disabled since crrev.com/843113003, to
487 // make this fail. See crbug.com/464109.
488 // EXPECT_FALSE(WaitForClientShutdown());
489 WaitForClientShutdown();
490 EXPECT_TRUE(listener.has_error());
492 DestroyChannel();
495 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient) {
496 ListenerThatQuits listener;
497 ChannelClient client(&listener, "IPCChannelMojoTestDoNothingClient");
498 client.Connect();
500 // Quits without running the message loop as this client won't
501 // receive any messages from the server.
503 return 0;
505 #endif
507 #if defined(OS_POSIX)
508 class ListenerThatExpectsFile : public IPC::Listener {
509 public:
510 ListenerThatExpectsFile()
511 : sender_(NULL) {}
513 ~ListenerThatExpectsFile() override {}
515 bool OnMessageReceived(const IPC::Message& message) override {
516 PickleIterator iter(message);
517 HandleSendingHelper::ReadReceivedFile(message, &iter);
518 base::MessageLoop::current()->Quit();
519 ListenerThatExpectsOK::SendOK(sender_);
520 return true;
523 void OnChannelError() override {
524 NOTREACHED();
527 void set_sender(IPC::Sender* sender) { sender_ = sender; }
529 private:
530 IPC::Sender* sender_;
534 TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
535 InitWithMojo("IPCChannelMojoTestSendPlatformHandleClient");
537 ListenerThatExpectsOK listener;
538 CreateChannel(&listener);
539 ASSERT_TRUE(ConnectChannel());
540 ASSERT_TRUE(StartClient());
542 base::File file(HandleSendingHelper::GetSendingFilePath(),
543 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
544 base::File::FLAG_READ);
545 HandleSendingHelper::WriteFileThenSend(channel(), file);
546 base::MessageLoop::current()->Run();
548 this->channel()->Close();
550 EXPECT_TRUE(WaitForClientShutdown());
551 DestroyChannel();
554 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
555 ListenerThatExpectsFile listener;
556 ChannelClient client(
557 &listener, "IPCChannelMojoTestSendPlatformHandleClient");
558 client.Connect();
559 listener.set_sender(client.channel());
561 base::MessageLoop::current()->Run();
563 client.Close();
565 return 0;
568 class ListenerThatExpectsFileAndPipe : public IPC::Listener {
569 public:
570 ListenerThatExpectsFileAndPipe() : sender_(NULL) {}
572 ~ListenerThatExpectsFileAndPipe() override {}
574 bool OnMessageReceived(const IPC::Message& message) override {
575 PickleIterator iter(message);
576 HandleSendingHelper::ReadReceivedFile(message, &iter);
577 HandleSendingHelper::ReadReceivedPipe(message, &iter);
578 base::MessageLoop::current()->Quit();
579 ListenerThatExpectsOK::SendOK(sender_);
580 return true;
583 void OnChannelError() override { NOTREACHED(); }
585 void set_sender(IPC::Sender* sender) { sender_ = sender; }
587 private:
588 IPC::Sender* sender_;
591 TEST_F(IPCChannelMojoTest, SendPlatformHandleAndPipe) {
592 InitWithMojo("IPCChannelMojoTestSendPlatformHandleAndPipeClient");
594 ListenerThatExpectsOK listener;
595 CreateChannel(&listener);
596 ASSERT_TRUE(ConnectChannel());
597 ASSERT_TRUE(StartClient());
599 base::File file(HandleSendingHelper::GetSendingFilePath(),
600 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
601 base::File::FLAG_READ);
602 TestingMessagePipe pipe;
603 HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe);
605 base::MessageLoop::current()->Run();
606 this->channel()->Close();
608 EXPECT_TRUE(WaitForClientShutdown());
609 DestroyChannel();
612 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(
613 IPCChannelMojoTestSendPlatformHandleAndPipeClient) {
614 ListenerThatExpectsFileAndPipe listener;
615 ChannelClient client(&listener,
616 "IPCChannelMojoTestSendPlatformHandleAndPipeClient");
617 client.Connect();
618 listener.set_sender(client.channel());
620 base::MessageLoop::current()->Run();
622 client.Close();
624 return 0;
627 #endif
629 #if defined(OS_LINUX)
631 const base::ProcessId kMagicChildId = 54321;
633 class ListenerThatVerifiesPeerPid : public IPC::Listener {
634 public:
635 void OnChannelConnected(int32 peer_pid) override {
636 EXPECT_EQ(peer_pid, kMagicChildId);
637 base::MessageLoop::current()->Quit();
640 bool OnMessageReceived(const IPC::Message& message) override {
641 NOTREACHED();
642 return true;
646 TEST_F(IPCChannelMojoTest, VerifyGlobalPid) {
647 InitWithMojo("IPCChannelMojoTestVerifyGlobalPidClient");
649 ListenerThatVerifiesPeerPid listener;
650 CreateChannel(&listener);
651 ASSERT_TRUE(ConnectChannel());
652 ASSERT_TRUE(StartClient());
654 base::MessageLoop::current()->Run();
655 channel()->Close();
657 EXPECT_TRUE(WaitForClientShutdown());
658 DestroyChannel();
661 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestVerifyGlobalPidClient) {
662 IPC::Channel::SetGlobalPid(kMagicChildId);
663 ListenerThatQuits listener;
664 ChannelClient client(&listener,
665 "IPCChannelMojoTestVerifyGlobalPidClient");
666 client.Connect();
668 base::MessageLoop::current()->Run();
670 client.Close();
672 return 0;
675 #endif // OS_LINUX
677 } // namespace