Remove an old PangoFontDescription forward declaration.
[chromium-blink-merge.git] / ipc / mojo / ipc_channel_mojo_unittest.cc
blob556e65accf59f03ac867f8cd4d11dcc6bc41da12
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_mojo_handle_attachment.h"
18 #include "ipc/mojo/ipc_mojo_message_helper.h"
20 #if defined(OS_POSIX)
21 #include "base/file_descriptor_posix.h"
22 #include "ipc/ipc_platform_file_attachment_posix.h"
23 #endif
25 namespace {
27 class ListenerThatExpectsOK : public IPC::Listener {
28 public:
29 ListenerThatExpectsOK()
30 : received_ok_(false) {}
32 ~ListenerThatExpectsOK() override {}
34 bool OnMessageReceived(const IPC::Message& message) override {
35 PickleIterator iter(message);
36 std::string should_be_ok;
37 EXPECT_TRUE(iter.ReadString(&should_be_ok));
38 EXPECT_EQ(should_be_ok, "OK");
39 received_ok_ = true;
40 base::MessageLoop::current()->Quit();
41 return true;
44 void OnChannelError() override {
45 // The connection should be healthy while the listener is waiting
46 // message. An error can occur after that because the peer
47 // process dies.
48 DCHECK(received_ok_);
51 static void SendOK(IPC::Sender* sender) {
52 IPC::Message* message = new IPC::Message(
53 0, 2, IPC::Message::PRIORITY_NORMAL);
54 message->WriteString(std::string("OK"));
55 ASSERT_TRUE(sender->Send(message));
58 private:
59 bool received_ok_;
62 class ChannelClient {
63 public:
64 explicit ChannelClient(IPC::Listener* listener, const char* name) {
65 channel_ = IPC::ChannelMojo::Create(NULL,
66 IPCTestBase::GetChannelName(name),
67 IPC::Channel::MODE_CLIENT,
68 listener);
71 void Connect() {
72 CHECK(channel_->Connect());
75 IPC::ChannelMojo* channel() const { return channel_.get(); }
77 private:
78 base::MessageLoopForIO main_message_loop_;
79 scoped_ptr<IPC::ChannelMojo> channel_;
82 class IPCChannelMojoTest : public IPCTestBase {
83 protected:
84 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
85 const IPC::ChannelHandle& handle,
86 base::TaskRunner* runner) override {
87 host_.reset(new IPC::ChannelMojoHost(task_runner()));
88 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
89 handle);
92 bool DidStartClient() override {
93 bool ok = IPCTestBase::DidStartClient();
94 DCHECK(ok);
95 host_->OnClientLaunched(client_process().Handle());
96 return ok;
99 private:
100 scoped_ptr<IPC::ChannelMojoHost> host_;
104 class TestChannelListenerWithExtraExpectations
105 : public IPC::TestChannelListener {
106 public:
107 TestChannelListenerWithExtraExpectations()
108 : is_connected_called_(false) {
111 void OnChannelConnected(int32 peer_pid) override {
112 IPC::TestChannelListener::OnChannelConnected(peer_pid);
113 EXPECT_TRUE(base::kNullProcessId != peer_pid);
114 is_connected_called_ = true;
117 bool is_connected_called() const { return is_connected_called_; }
119 private:
120 bool is_connected_called_;
123 TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
124 Init("IPCChannelMojoTestClient");
126 // Set up IPC channel and start client.
127 TestChannelListenerWithExtraExpectations listener;
128 CreateChannel(&listener);
129 listener.Init(sender());
130 ASSERT_TRUE(ConnectChannel());
131 ASSERT_TRUE(StartClient());
133 IPC::TestChannelListener::SendOneMessage(
134 sender(), "hello from parent");
136 base::MessageLoop::current()->Run();
137 EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());
139 this->channel()->Close();
141 EXPECT_TRUE(WaitForClientShutdown());
142 EXPECT_TRUE(listener.is_connected_called());
143 EXPECT_TRUE(listener.HasSentAll());
145 DestroyChannel();
148 // A long running process that connects to us
149 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
150 TestChannelListenerWithExtraExpectations listener;
151 ChannelClient client(&listener, "IPCChannelMojoTestClient");
152 client.Connect();
153 listener.Init(client.channel());
155 IPC::TestChannelListener::SendOneMessage(
156 client.channel(), "hello from child");
157 base::MessageLoop::current()->Run();
158 EXPECT_TRUE(listener.is_connected_called());
159 EXPECT_TRUE(listener.HasSentAll());
161 return 0;
164 class ListenerExpectingErrors : public IPC::Listener {
165 public:
166 ListenerExpectingErrors()
167 : has_error_(false) {
170 void OnChannelConnected(int32 peer_pid) override {
171 base::MessageLoop::current()->Quit();
174 bool OnMessageReceived(const IPC::Message& message) override { return true; }
176 void OnChannelError() override {
177 has_error_ = true;
178 base::MessageLoop::current()->Quit();
181 bool has_error() const { return has_error_; }
183 private:
184 bool has_error_;
188 class IPCChannelMojoErrorTest : public IPCTestBase {
189 protected:
190 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
191 const IPC::ChannelHandle& handle,
192 base::TaskRunner* runner) override {
193 host_.reset(new IPC::ChannelMojoHost(task_runner()));
194 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
195 handle);
198 bool DidStartClient() override {
199 bool ok = IPCTestBase::DidStartClient();
200 DCHECK(ok);
201 host_->OnClientLaunched(client_process().Handle());
202 return ok;
205 private:
206 scoped_ptr<IPC::ChannelMojoHost> host_;
209 class ListenerThatQuits : public IPC::Listener {
210 public:
211 ListenerThatQuits() {
214 bool OnMessageReceived(const IPC::Message& message) override {
215 return true;
218 void OnChannelConnected(int32 peer_pid) override {
219 base::MessageLoop::current()->Quit();
223 // A long running process that connects to us.
224 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
225 ListenerThatQuits listener;
226 ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
227 client.Connect();
229 base::MessageLoop::current()->Run();
231 return 0;
234 TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
235 Init("IPCChannelMojoErraticTestClient");
237 // Set up IPC channel and start client.
238 ListenerExpectingErrors listener;
239 CreateChannel(&listener);
240 ASSERT_TRUE(ConnectChannel());
242 // This matches a value in mojo/edk/system/constants.h
243 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
244 std::string overly_large_data(kMaxMessageNumBytes, '*');
245 // This messages are queued as pending.
246 for (size_t i = 0; i < 10; ++i) {
247 IPC::TestChannelListener::SendOneMessage(
248 sender(), overly_large_data.c_str());
251 ASSERT_TRUE(StartClient());
252 base::MessageLoop::current()->Run();
254 this->channel()->Close();
256 EXPECT_TRUE(WaitForClientShutdown());
257 EXPECT_TRUE(listener.has_error());
259 DestroyChannel();
262 struct TestingMessagePipe {
263 TestingMessagePipe() {
264 EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateMessagePipe(nullptr, &self, &peer));
267 mojo::ScopedMessagePipeHandle self;
268 mojo::ScopedMessagePipeHandle peer;
271 class HandleSendingHelper {
272 public:
273 static std::string GetSendingFileContent() { return "Hello"; }
275 static void WritePipe(IPC::Message* message, TestingMessagePipe* pipe) {
276 std::string content = HandleSendingHelper::GetSendingFileContent();
277 EXPECT_EQ(MOJO_RESULT_OK,
278 mojo::WriteMessageRaw(pipe->self.get(), &content[0],
279 static_cast<uint32_t>(content.size()),
280 nullptr, 0, 0));
281 EXPECT_TRUE(
282 IPC::MojoMessageHelper::WriteMessagePipeTo(message, pipe->peer.Pass()));
285 static void WritePipeThenSend(IPC::Sender* sender, TestingMessagePipe* pipe) {
286 IPC::Message* message =
287 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
288 WritePipe(message, pipe);
289 ASSERT_TRUE(sender->Send(message));
292 static void ReadReceivedPipe(const IPC::Message& message,
293 PickleIterator* iter) {
294 mojo::ScopedMessagePipeHandle pipe;
295 EXPECT_TRUE(
296 IPC::MojoMessageHelper::ReadMessagePipeFrom(&message, iter, &pipe));
297 std::string content(GetSendingFileContent().size(), ' ');
299 uint32_t num_bytes = static_cast<uint32_t>(content.size());
300 EXPECT_EQ(MOJO_RESULT_OK,
301 mojo::ReadMessageRaw(pipe.get(), &content[0], &num_bytes, nullptr,
302 nullptr, 0));
303 EXPECT_EQ(content, GetSendingFileContent());
306 #if defined(OS_POSIX)
307 static base::FilePath GetSendingFilePath() {
308 base::FilePath path;
309 bool ok = PathService::Get(base::DIR_CACHE, &path);
310 EXPECT_TRUE(ok);
311 return path.Append("ListenerThatExpectsFile.txt");
314 static void WriteFile(IPC::Message* message, base::File& file) {
315 std::string content = GetSendingFileContent();
316 file.WriteAtCurrentPos(content.data(), content.size());
317 file.Flush();
318 message->WriteAttachment(new IPC::internal::PlatformFileAttachment(
319 base::ScopedFD(file.TakePlatformFile())));
322 static void WriteFileThenSend(IPC::Sender* sender, base::File& file) {
323 IPC::Message* message =
324 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
325 WriteFile(message, file);
326 ASSERT_TRUE(sender->Send(message));
329 static void WriteFileAndPipeThenSend(IPC::Sender* sender,
330 base::File& file,
331 TestingMessagePipe* pipe) {
332 IPC::Message* message =
333 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
334 WriteFile(message, file);
335 WritePipe(message, pipe);
336 ASSERT_TRUE(sender->Send(message));
339 static void ReadReceivedFile(const IPC::Message& message,
340 PickleIterator* iter) {
341 base::ScopedFD fd;
342 scoped_refptr<IPC::MessageAttachment> attachment;
343 EXPECT_TRUE(message.ReadAttachment(iter, &attachment));
344 base::File file(attachment->TakePlatformFile());
345 std::string content(GetSendingFileContent().size(), ' ');
346 file.Read(0, &content[0], content.size());
347 EXPECT_EQ(content, GetSendingFileContent());
349 #endif
352 class ListenerThatExpectsMessagePipe : public IPC::Listener {
353 public:
354 ListenerThatExpectsMessagePipe() : sender_(NULL) {}
356 ~ListenerThatExpectsMessagePipe() override {}
358 bool OnMessageReceived(const IPC::Message& message) override {
359 PickleIterator iter(message);
360 HandleSendingHelper::ReadReceivedPipe(message, &iter);
361 base::MessageLoop::current()->Quit();
362 ListenerThatExpectsOK::SendOK(sender_);
363 return true;
366 void OnChannelError() override { NOTREACHED(); }
368 void set_sender(IPC::Sender* sender) { sender_ = sender; }
370 private:
371 IPC::Sender* sender_;
374 TEST_F(IPCChannelMojoTest, SendMessagePipe) {
375 Init("IPCChannelMojoTestSendMessagePipeClient");
377 ListenerThatExpectsOK listener;
378 CreateChannel(&listener);
379 ASSERT_TRUE(ConnectChannel());
380 ASSERT_TRUE(StartClient());
382 TestingMessagePipe pipe;
383 HandleSendingHelper::WritePipeThenSend(channel(), &pipe);
385 base::MessageLoop::current()->Run();
386 this->channel()->Close();
388 EXPECT_TRUE(WaitForClientShutdown());
389 DestroyChannel();
392 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendMessagePipeClient) {
393 ListenerThatExpectsMessagePipe listener;
394 ChannelClient client(&listener, "IPCChannelMojoTestSendPlatformHandleClient");
395 client.Connect();
396 listener.set_sender(client.channel());
398 base::MessageLoop::current()->Run();
400 return 0;
403 #if defined(OS_WIN)
404 class IPCChannelMojoDeadHandleTest : public IPCTestBase {
405 protected:
406 virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
407 const IPC::ChannelHandle& handle,
408 base::TaskRunner* runner) override {
409 host_.reset(new IPC::ChannelMojoHost(task_runner()));
410 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
411 handle);
414 virtual bool DidStartClient() override {
415 IPCTestBase::DidStartClient();
416 const base::ProcessHandle client = client_process().Handle();
417 // Forces GetFileHandleForProcess() fail. It happens occasionally
418 // in production, so we should exercise it somehow.
419 // TODO(morrita): figure out how to safely test this.
420 // ::CloseHandle(client);
421 host_->OnClientLaunched(client);
422 return true;
425 private:
426 scoped_ptr<IPC::ChannelMojoHost> host_;
429 TEST_F(IPCChannelMojoDeadHandleTest, InvalidClientHandle) {
430 // Any client type is fine as it is going to be killed anyway.
431 Init("IPCChannelMojoTestDoNothingClient");
433 // Set up IPC channel and start client.
434 ListenerExpectingErrors listener;
435 CreateChannel(&listener);
436 ASSERT_TRUE(ConnectChannel());
438 ASSERT_TRUE(StartClient());
439 base::MessageLoop::current()->Run();
441 this->channel()->Close();
443 // WaitForClientShutdown() fails as client_hanadle() is already
444 // closed.
445 EXPECT_FALSE(WaitForClientShutdown());
446 EXPECT_TRUE(listener.has_error());
448 DestroyChannel();
451 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient) {
452 ListenerThatQuits listener;
453 ChannelClient client(&listener, "IPCChannelMojoTestDoNothingClient");
454 client.Connect();
456 // Quits without running the message loop as this client won't
457 // receive any messages from the server.
459 return 0;
461 #endif
463 #if defined(OS_POSIX)
464 class ListenerThatExpectsFile : public IPC::Listener {
465 public:
466 ListenerThatExpectsFile()
467 : sender_(NULL) {}
469 ~ListenerThatExpectsFile() override {}
471 bool OnMessageReceived(const IPC::Message& message) override {
472 PickleIterator iter(message);
473 HandleSendingHelper::ReadReceivedFile(message, &iter);
474 base::MessageLoop::current()->Quit();
475 ListenerThatExpectsOK::SendOK(sender_);
476 return true;
479 void OnChannelError() override {
480 NOTREACHED();
483 void set_sender(IPC::Sender* sender) { sender_ = sender; }
485 private:
486 IPC::Sender* sender_;
490 TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
491 Init("IPCChannelMojoTestSendPlatformHandleClient");
493 ListenerThatExpectsOK listener;
494 CreateChannel(&listener);
495 ASSERT_TRUE(ConnectChannel());
496 ASSERT_TRUE(StartClient());
498 base::File file(HandleSendingHelper::GetSendingFilePath(),
499 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
500 base::File::FLAG_READ);
501 HandleSendingHelper::WriteFileThenSend(channel(), file);
502 base::MessageLoop::current()->Run();
504 this->channel()->Close();
506 EXPECT_TRUE(WaitForClientShutdown());
507 DestroyChannel();
510 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
511 ListenerThatExpectsFile listener;
512 ChannelClient client(
513 &listener, "IPCChannelMojoTestSendPlatformHandleClient");
514 client.Connect();
515 listener.set_sender(client.channel());
517 base::MessageLoop::current()->Run();
519 return 0;
522 class ListenerThatExpectsFileAndPipe : public IPC::Listener {
523 public:
524 ListenerThatExpectsFileAndPipe() : sender_(NULL) {}
526 ~ListenerThatExpectsFileAndPipe() override {}
528 bool OnMessageReceived(const IPC::Message& message) override {
529 PickleIterator iter(message);
530 HandleSendingHelper::ReadReceivedFile(message, &iter);
531 HandleSendingHelper::ReadReceivedPipe(message, &iter);
532 base::MessageLoop::current()->Quit();
533 ListenerThatExpectsOK::SendOK(sender_);
534 return true;
537 void OnChannelError() override { NOTREACHED(); }
539 void set_sender(IPC::Sender* sender) { sender_ = sender; }
541 private:
542 IPC::Sender* sender_;
545 TEST_F(IPCChannelMojoTest, SendPlatformHandleAndPipe) {
546 Init("IPCChannelMojoTestSendPlatformHandleAndPipeClient");
548 ListenerThatExpectsOK listener;
549 CreateChannel(&listener);
550 ASSERT_TRUE(ConnectChannel());
551 ASSERT_TRUE(StartClient());
553 base::File file(HandleSendingHelper::GetSendingFilePath(),
554 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
555 base::File::FLAG_READ);
556 TestingMessagePipe pipe;
557 HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe);
559 base::MessageLoop::current()->Run();
560 this->channel()->Close();
562 EXPECT_TRUE(WaitForClientShutdown());
563 DestroyChannel();
566 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(
567 IPCChannelMojoTestSendPlatformHandleAndPipeClient) {
568 ListenerThatExpectsFileAndPipe listener;
569 ChannelClient client(&listener,
570 "IPCChannelMojoTestSendPlatformHandleAndPipeClient");
571 client.Connect();
572 listener.set_sender(client.channel());
574 base::MessageLoop::current()->Run();
576 return 0;
579 #endif
581 } // namespace