OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "ipc/mojo/ipc_channel_mojo.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 #include <memory> | |
10 #include <utility> | |
11 | |
12 #include "base/base_paths.h" | |
13 #include "base/files/file.h" | |
14 #include "base/location.h" | |
15 #include "base/path_service.h" | |
16 #include "base/pickle.h" | |
17 #include "base/run_loop.h" | |
18 #include "base/single_thread_task_runner.h" | |
19 #include "base/test/test_io_thread.h" | |
20 #include "base/test/test_timeouts.h" | |
21 #include "base/threading/thread.h" | |
22 #include "base/threading/thread_task_runner_handle.h" | |
23 #include "build/build_config.h" | |
24 #include "ipc/ipc_message.h" | |
25 #include "ipc/ipc_test_base.h" | |
26 #include "ipc/ipc_test_channel_listener.h" | |
27 #include "ipc/mojo/ipc_channel_mojo.h" | |
28 #include "ipc/mojo/ipc_mojo_handle_attachment.h" | |
29 #include "ipc/mojo/ipc_mojo_message_helper.h" | |
30 #include "ipc/mojo/ipc_mojo_param_traits.h" | |
31 #include "mojo/edk/test/mojo_test_base.h" | |
32 #include "mojo/edk/test/multiprocess_test_helper.h" | |
33 #include "testing/gtest/include/gtest/gtest.h" | |
34 | |
35 #if defined(OS_POSIX) | |
36 #include "base/file_descriptor_posix.h" | |
37 #include "ipc/ipc_platform_file_attachment_posix.h" | |
38 #endif | |
39 | |
40 #define DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(client_name, test_base) \ | |
41 class client_name##_MainFixture : public test_base { \ | |
42 public: \ | |
43 void Main(); \ | |
44 }; \ | |
45 MULTIPROCESS_TEST_MAIN_WITH_SETUP( \ | |
46 client_name##TestChildMain, \ | |
47 ::mojo::edk::test::MultiprocessTestHelper::ChildSetup) { \ | |
48 CHECK(!mojo::edk::test::MultiprocessTestHelper::primordial_pipe_token \ | |
49 .empty()); \ | |
50 client_name##_MainFixture test; \ | |
51 test.Init(mojo::edk::CreateChildMessagePipe( \ | |
52 mojo::edk::test::MultiprocessTestHelper::primordial_pipe_token)); \ | |
53 test.Main(); \ | |
54 return (::testing::Test::HasFatalFailure() || \ | |
55 ::testing::Test::HasNonfatalFailure()) \ | |
56 ? 1 \ | |
57 : 0; \ | |
58 } \ | |
59 void client_name##_MainFixture::Main() | |
60 | |
61 namespace { | |
62 | |
63 class ListenerThatExpectsOK : public IPC::Listener { | |
64 public: | |
65 ListenerThatExpectsOK() : received_ok_(false) {} | |
66 | |
67 ~ListenerThatExpectsOK() override {} | |
68 | |
69 bool OnMessageReceived(const IPC::Message& message) override { | |
70 base::PickleIterator iter(message); | |
71 std::string should_be_ok; | |
72 EXPECT_TRUE(iter.ReadString(&should_be_ok)); | |
73 EXPECT_EQ(should_be_ok, "OK"); | |
74 received_ok_ = true; | |
75 base::MessageLoop::current()->QuitWhenIdle(); | |
76 return true; | |
77 } | |
78 | |
79 void OnChannelError() override { | |
80 // The connection should be healthy while the listener is waiting | |
81 // message. An error can occur after that because the peer | |
82 // process dies. | |
83 DCHECK(received_ok_); | |
84 } | |
85 | |
86 static void SendOK(IPC::Sender* sender) { | |
87 IPC::Message* message = | |
88 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); | |
89 message->WriteString(std::string("OK")); | |
90 ASSERT_TRUE(sender->Send(message)); | |
91 } | |
92 | |
93 private: | |
94 bool received_ok_; | |
95 }; | |
96 | |
97 class ChannelClient { | |
98 public: | |
99 void Init(mojo::ScopedMessagePipeHandle handle) { | |
100 handle_ = std::move(handle); | |
101 } | |
102 void Connect(IPC::Listener* listener) { | |
103 channel_ = IPC::ChannelMojo::Create(std::move(handle_), | |
104 IPC::Channel::MODE_CLIENT, listener); | |
105 CHECK(channel_->Connect()); | |
106 } | |
107 | |
108 void Close() { | |
109 channel_->Close(); | |
110 | |
111 base::RunLoop run_loop; | |
112 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | |
113 run_loop.QuitClosure()); | |
114 run_loop.Run(); | |
115 } | |
116 | |
117 IPC::ChannelMojo* channel() const { return channel_.get(); } | |
118 | |
119 private: | |
120 base::MessageLoopForIO main_message_loop_; | |
121 mojo::ScopedMessagePipeHandle handle_; | |
122 std::unique_ptr<IPC::ChannelMojo> channel_; | |
123 }; | |
124 | |
125 class IPCChannelMojoTest : public testing::Test { | |
126 public: | |
127 IPCChannelMojoTest() : io_thread_(base::TestIOThread::Mode::kAutoStart) {} | |
128 | |
129 void TearDown() override { base::RunLoop().RunUntilIdle(); } | |
130 | |
131 void InitWithMojo(const std::string& test_client_name) { | |
132 handle_ = helper_.StartChild(test_client_name); | |
133 } | |
134 | |
135 void CreateChannel(IPC::Listener* listener) { | |
136 channel_ = IPC::ChannelMojo::Create(std::move(handle_), | |
137 IPC::Channel::MODE_SERVER, listener); | |
138 } | |
139 | |
140 bool ConnectChannel() { return channel_->Connect(); } | |
141 | |
142 void DestroyChannel() { channel_.reset(); } | |
143 | |
144 bool WaitForClientShutdown() { return helper_.WaitForChildTestShutdown(); } | |
145 | |
146 IPC::Sender* sender() { return channel(); } | |
147 IPC::Channel* channel() { return channel_.get(); } | |
148 | |
149 private: | |
150 base::MessageLoop message_loop_; | |
151 base::TestIOThread io_thread_; | |
152 mojo::edk::test::MultiprocessTestHelper helper_; | |
153 mojo::ScopedMessagePipeHandle handle_; | |
154 std::unique_ptr<IPC::Channel> channel_; | |
155 }; | |
156 | |
157 class TestChannelListenerWithExtraExpectations | |
158 : public IPC::TestChannelListener { | |
159 public: | |
160 TestChannelListenerWithExtraExpectations() : is_connected_called_(false) {} | |
161 | |
162 void OnChannelConnected(int32_t peer_pid) override { | |
163 IPC::TestChannelListener::OnChannelConnected(peer_pid); | |
164 EXPECT_TRUE(base::kNullProcessId != peer_pid); | |
165 is_connected_called_ = true; | |
166 } | |
167 | |
168 bool is_connected_called() const { return is_connected_called_; } | |
169 | |
170 private: | |
171 bool is_connected_called_; | |
172 }; | |
173 | |
174 TEST_F(IPCChannelMojoTest, ConnectedFromClient) { | |
175 InitWithMojo("IPCChannelMojoTestClient"); | |
176 | |
177 // Set up IPC channel and start client. | |
178 TestChannelListenerWithExtraExpectations listener; | |
179 CreateChannel(&listener); | |
180 listener.Init(sender()); | |
181 ASSERT_TRUE(ConnectChannel()); | |
182 | |
183 IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); | |
184 | |
185 base::MessageLoop::current()->Run(); | |
186 | |
187 channel()->Close(); | |
188 | |
189 EXPECT_TRUE(WaitForClientShutdown()); | |
190 EXPECT_TRUE(listener.is_connected_called()); | |
191 EXPECT_TRUE(listener.HasSentAll()); | |
192 | |
193 DestroyChannel(); | |
194 } | |
195 | |
196 // A long running process that connects to us | |
197 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestClient, ChannelClient) { | |
198 TestChannelListenerWithExtraExpectations listener; | |
199 Connect(&listener); | |
200 listener.Init(channel()); | |
201 | |
202 IPC::TestChannelListener::SendOneMessage(channel(), "hello from child"); | |
203 base::MessageLoop::current()->Run(); | |
204 EXPECT_TRUE(listener.is_connected_called()); | |
205 EXPECT_TRUE(listener.HasSentAll()); | |
206 | |
207 Close(); | |
208 } | |
209 | |
210 class ListenerExpectingErrors : public IPC::Listener { | |
211 public: | |
212 ListenerExpectingErrors() : has_error_(false) {} | |
213 | |
214 void OnChannelConnected(int32_t peer_pid) override { | |
215 base::MessageLoop::current()->QuitWhenIdle(); | |
216 } | |
217 | |
218 bool OnMessageReceived(const IPC::Message& message) override { return true; } | |
219 | |
220 void OnChannelError() override { | |
221 has_error_ = true; | |
222 base::MessageLoop::current()->QuitWhenIdle(); | |
223 } | |
224 | |
225 bool has_error() const { return has_error_; } | |
226 | |
227 private: | |
228 bool has_error_; | |
229 }; | |
230 | |
231 class ListenerThatQuits : public IPC::Listener { | |
232 public: | |
233 ListenerThatQuits() {} | |
234 | |
235 bool OnMessageReceived(const IPC::Message& message) override { return true; } | |
236 | |
237 void OnChannelConnected(int32_t peer_pid) override { | |
238 base::MessageLoop::current()->QuitWhenIdle(); | |
239 } | |
240 }; | |
241 | |
242 // A long running process that connects to us. | |
243 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoErraticTestClient, | |
244 ChannelClient) { | |
245 ListenerThatQuits listener; | |
246 Connect(&listener); | |
247 | |
248 base::MessageLoop::current()->Run(); | |
249 | |
250 Close(); | |
251 } | |
252 | |
253 TEST_F(IPCChannelMojoTest, SendFailWithPendingMessages) { | |
254 InitWithMojo("IPCChannelMojoErraticTestClient"); | |
255 | |
256 // Set up IPC channel and start client. | |
257 ListenerExpectingErrors listener; | |
258 CreateChannel(&listener); | |
259 ASSERT_TRUE(ConnectChannel()); | |
260 | |
261 // This matches a value in mojo/edk/system/constants.h | |
262 const int kMaxMessageNumBytes = 4 * 1024 * 1024; | |
263 std::string overly_large_data(kMaxMessageNumBytes, '*'); | |
264 // This messages are queued as pending. | |
265 for (size_t i = 0; i < 10; ++i) { | |
266 IPC::TestChannelListener::SendOneMessage(sender(), | |
267 overly_large_data.c_str()); | |
268 } | |
269 | |
270 base::MessageLoop::current()->Run(); | |
271 | |
272 channel()->Close(); | |
273 | |
274 EXPECT_TRUE(WaitForClientShutdown()); | |
275 EXPECT_TRUE(listener.has_error()); | |
276 | |
277 DestroyChannel(); | |
278 } | |
279 | |
280 struct TestingMessagePipe { | |
281 TestingMessagePipe() { | |
282 EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateMessagePipe(nullptr, &self, &peer)); | |
283 } | |
284 | |
285 mojo::ScopedMessagePipeHandle self; | |
286 mojo::ScopedMessagePipeHandle peer; | |
287 }; | |
288 | |
289 class HandleSendingHelper { | |
290 public: | |
291 static std::string GetSendingFileContent() { return "Hello"; } | |
292 | |
293 static void WritePipe(IPC::Message* message, TestingMessagePipe* pipe) { | |
294 std::string content = HandleSendingHelper::GetSendingFileContent(); | |
295 EXPECT_EQ(MOJO_RESULT_OK, | |
296 mojo::WriteMessageRaw(pipe->self.get(), &content[0], | |
297 static_cast<uint32_t>(content.size()), | |
298 nullptr, 0, 0)); | |
299 EXPECT_TRUE(IPC::MojoMessageHelper::WriteMessagePipeTo( | |
300 message, std::move(pipe->peer))); | |
301 } | |
302 | |
303 static void WritePipeThenSend(IPC::Sender* sender, TestingMessagePipe* pipe) { | |
304 IPC::Message* message = | |
305 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); | |
306 WritePipe(message, pipe); | |
307 ASSERT_TRUE(sender->Send(message)); | |
308 } | |
309 | |
310 static void ReadReceivedPipe(const IPC::Message& message, | |
311 base::PickleIterator* iter) { | |
312 mojo::ScopedMessagePipeHandle pipe; | |
313 EXPECT_TRUE( | |
314 IPC::MojoMessageHelper::ReadMessagePipeFrom(&message, iter, &pipe)); | |
315 std::string content(GetSendingFileContent().size(), ' '); | |
316 | |
317 uint32_t num_bytes = static_cast<uint32_t>(content.size()); | |
318 ASSERT_EQ(MOJO_RESULT_OK, | |
319 mojo::Wait(pipe.get(), MOJO_HANDLE_SIGNAL_READABLE, | |
320 MOJO_DEADLINE_INDEFINITE, nullptr)); | |
321 EXPECT_EQ(MOJO_RESULT_OK, | |
322 mojo::ReadMessageRaw(pipe.get(), &content[0], &num_bytes, nullptr, | |
323 nullptr, 0)); | |
324 EXPECT_EQ(content, GetSendingFileContent()); | |
325 } | |
326 | |
327 #if defined(OS_POSIX) | |
328 static base::FilePath GetSendingFilePath() { | |
329 base::FilePath path; | |
330 bool ok = PathService::Get(base::DIR_CACHE, &path); | |
331 EXPECT_TRUE(ok); | |
332 return path.Append("ListenerThatExpectsFile.txt"); | |
333 } | |
334 | |
335 static void WriteFile(IPC::Message* message, base::File& file) { | |
336 std::string content = GetSendingFileContent(); | |
337 file.WriteAtCurrentPos(content.data(), content.size()); | |
338 file.Flush(); | |
339 message->WriteAttachment(new IPC::internal::PlatformFileAttachment( | |
340 base::ScopedFD(file.TakePlatformFile()))); | |
341 } | |
342 | |
343 static void WriteFileThenSend(IPC::Sender* sender, base::File& file) { | |
344 IPC::Message* message = | |
345 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); | |
346 WriteFile(message, file); | |
347 ASSERT_TRUE(sender->Send(message)); | |
348 } | |
349 | |
350 static void WriteFileAndPipeThenSend(IPC::Sender* sender, | |
351 base::File& file, | |
352 TestingMessagePipe* pipe) { | |
353 IPC::Message* message = | |
354 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); | |
355 WriteFile(message, file); | |
356 WritePipe(message, pipe); | |
357 ASSERT_TRUE(sender->Send(message)); | |
358 } | |
359 | |
360 static void ReadReceivedFile(const IPC::Message& message, | |
361 base::PickleIterator* iter) { | |
362 base::ScopedFD fd; | |
363 scoped_refptr<base::Pickle::Attachment> attachment; | |
364 EXPECT_TRUE(message.ReadAttachment(iter, &attachment)); | |
365 EXPECT_EQ(IPC::MessageAttachment::TYPE_PLATFORM_FILE, | |
366 static_cast<IPC::MessageAttachment*>(attachment.get()) | |
367 ->GetType()); | |
368 base::File file(static_cast<IPC::MessageAttachment*>(attachment.get()) | |
369 ->TakePlatformFile()); | |
370 std::string content(GetSendingFileContent().size(), ' '); | |
371 file.Read(0, &content[0], content.size()); | |
372 EXPECT_EQ(content, GetSendingFileContent()); | |
373 } | |
374 #endif | |
375 }; | |
376 | |
377 class ListenerThatExpectsMessagePipe : public IPC::Listener { | |
378 public: | |
379 ListenerThatExpectsMessagePipe() : sender_(NULL) {} | |
380 | |
381 ~ListenerThatExpectsMessagePipe() override {} | |
382 | |
383 bool OnMessageReceived(const IPC::Message& message) override { | |
384 base::PickleIterator iter(message); | |
385 HandleSendingHelper::ReadReceivedPipe(message, &iter); | |
386 ListenerThatExpectsOK::SendOK(sender_); | |
387 return true; | |
388 } | |
389 | |
390 void OnChannelError() override { | |
391 base::MessageLoop::current()->QuitWhenIdle(); | |
392 } | |
393 | |
394 void set_sender(IPC::Sender* sender) { sender_ = sender; } | |
395 | |
396 private: | |
397 IPC::Sender* sender_; | |
398 }; | |
399 | |
400 TEST_F(IPCChannelMojoTest, SendMessagePipe) { | |
401 InitWithMojo("IPCChannelMojoTestSendMessagePipeClient"); | |
402 | |
403 ListenerThatExpectsOK listener; | |
404 CreateChannel(&listener); | |
405 ASSERT_TRUE(ConnectChannel()); | |
406 | |
407 TestingMessagePipe pipe; | |
408 HandleSendingHelper::WritePipeThenSend(channel(), &pipe); | |
409 | |
410 base::MessageLoop::current()->Run(); | |
411 channel()->Close(); | |
412 | |
413 EXPECT_TRUE(WaitForClientShutdown()); | |
414 DestroyChannel(); | |
415 } | |
416 | |
417 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendMessagePipeClient, | |
418 ChannelClient) { | |
419 ListenerThatExpectsMessagePipe listener; | |
420 Connect(&listener); | |
421 listener.set_sender(channel()); | |
422 | |
423 base::MessageLoop::current()->Run(); | |
424 | |
425 Close(); | |
426 } | |
427 | |
428 void ReadOK(mojo::MessagePipeHandle pipe) { | |
429 std::string should_be_ok("xx"); | |
430 uint32_t num_bytes = static_cast<uint32_t>(should_be_ok.size()); | |
431 CHECK_EQ(MOJO_RESULT_OK, mojo::Wait(pipe, MOJO_HANDLE_SIGNAL_READABLE, | |
432 MOJO_DEADLINE_INDEFINITE, nullptr)); | |
433 CHECK_EQ(MOJO_RESULT_OK, | |
434 mojo::ReadMessageRaw(pipe, &should_be_ok[0], &num_bytes, nullptr, | |
435 nullptr, 0)); | |
436 EXPECT_EQ(should_be_ok, std::string("OK")); | |
437 } | |
438 | |
439 void WriteOK(mojo::MessagePipeHandle pipe) { | |
440 std::string ok("OK"); | |
441 CHECK_EQ(MOJO_RESULT_OK, | |
442 mojo::WriteMessageRaw(pipe, &ok[0], static_cast<uint32_t>(ok.size()), | |
443 nullptr, 0, 0)); | |
444 } | |
445 | |
446 class ListenerThatExpectsMessagePipeUsingParamTrait : public IPC::Listener { | |
447 public: | |
448 explicit ListenerThatExpectsMessagePipeUsingParamTrait(bool receiving_valid) | |
449 : sender_(NULL), receiving_valid_(receiving_valid) {} | |
450 | |
451 ~ListenerThatExpectsMessagePipeUsingParamTrait() override {} | |
452 | |
453 bool OnMessageReceived(const IPC::Message& message) override { | |
454 base::PickleIterator iter(message); | |
455 mojo::MessagePipeHandle handle; | |
456 EXPECT_TRUE(IPC::ParamTraits<mojo::MessagePipeHandle>::Read(&message, &iter, | |
457 &handle)); | |
458 EXPECT_EQ(handle.is_valid(), receiving_valid_); | |
459 if (receiving_valid_) { | |
460 ReadOK(handle); | |
461 MojoClose(handle.value()); | |
462 } | |
463 | |
464 ListenerThatExpectsOK::SendOK(sender_); | |
465 return true; | |
466 } | |
467 | |
468 void OnChannelError() override { | |
469 base::MessageLoop::current()->QuitWhenIdle(); | |
470 } | |
471 | |
472 void set_sender(IPC::Sender* sender) { sender_ = sender; } | |
473 | |
474 private: | |
475 IPC::Sender* sender_; | |
476 bool receiving_valid_; | |
477 }; | |
478 | |
479 class ParamTraitMessagePipeClient : public ChannelClient { | |
480 public: | |
481 void RunTest(bool receiving_valid_handle) { | |
482 ListenerThatExpectsMessagePipeUsingParamTrait listener( | |
483 receiving_valid_handle); | |
484 Connect(&listener); | |
485 listener.set_sender(channel()); | |
486 | |
487 base::MessageLoop::current()->Run(); | |
488 | |
489 Close(); | |
490 } | |
491 }; | |
492 | |
493 TEST_F(IPCChannelMojoTest, ParamTraitValidMessagePipe) { | |
494 InitWithMojo("ParamTraitValidMessagePipeClient"); | |
495 | |
496 ListenerThatExpectsOK listener; | |
497 CreateChannel(&listener); | |
498 ASSERT_TRUE(ConnectChannel()); | |
499 | |
500 TestingMessagePipe pipe; | |
501 | |
502 std::unique_ptr<IPC::Message> message(new IPC::Message()); | |
503 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(), | |
504 pipe.peer.release()); | |
505 WriteOK(pipe.self.get()); | |
506 | |
507 channel()->Send(message.release()); | |
508 base::MessageLoop::current()->Run(); | |
509 channel()->Close(); | |
510 | |
511 EXPECT_TRUE(WaitForClientShutdown()); | |
512 DestroyChannel(); | |
513 } | |
514 | |
515 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ParamTraitValidMessagePipeClient, | |
516 ParamTraitMessagePipeClient) { | |
517 RunTest(true); | |
518 } | |
519 | |
520 TEST_F(IPCChannelMojoTest, ParamTraitInvalidMessagePipe) { | |
521 InitWithMojo("ParamTraitInvalidMessagePipeClient"); | |
522 | |
523 ListenerThatExpectsOK listener; | |
524 CreateChannel(&listener); | |
525 ASSERT_TRUE(ConnectChannel()); | |
526 | |
527 mojo::MessagePipeHandle invalid_handle; | |
528 std::unique_ptr<IPC::Message> message(new IPC::Message()); | |
529 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(), | |
530 invalid_handle); | |
531 | |
532 channel()->Send(message.release()); | |
533 base::MessageLoop::current()->Run(); | |
534 channel()->Close(); | |
535 | |
536 EXPECT_TRUE(WaitForClientShutdown()); | |
537 DestroyChannel(); | |
538 } | |
539 | |
540 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ParamTraitInvalidMessagePipeClient, | |
541 ParamTraitMessagePipeClient) { | |
542 RunTest(false); | |
543 } | |
544 | |
545 TEST_F(IPCChannelMojoTest, SendFailAfterClose) { | |
546 InitWithMojo("IPCChannelMojoTestSendOkClient"); | |
547 | |
548 ListenerThatExpectsOK listener; | |
549 CreateChannel(&listener); | |
550 ASSERT_TRUE(ConnectChannel()); | |
551 | |
552 base::MessageLoop::current()->Run(); | |
553 channel()->Close(); | |
554 ASSERT_FALSE(channel()->Send(new IPC::Message())); | |
555 | |
556 EXPECT_TRUE(WaitForClientShutdown()); | |
557 DestroyChannel(); | |
558 } | |
559 | |
560 class ListenerSendingOneOk : public IPC::Listener { | |
561 public: | |
562 ListenerSendingOneOk() {} | |
563 | |
564 bool OnMessageReceived(const IPC::Message& message) override { return true; } | |
565 | |
566 void OnChannelConnected(int32_t peer_pid) override { | |
567 ListenerThatExpectsOK::SendOK(sender_); | |
568 base::MessageLoop::current()->QuitWhenIdle(); | |
569 } | |
570 | |
571 void set_sender(IPC::Sender* sender) { sender_ = sender; } | |
572 | |
573 private: | |
574 IPC::Sender* sender_; | |
575 }; | |
576 | |
577 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendOkClient, | |
578 ChannelClient) { | |
579 ListenerSendingOneOk listener; | |
580 Connect(&listener); | |
581 listener.set_sender(channel()); | |
582 | |
583 base::MessageLoop::current()->Run(); | |
584 | |
585 Close(); | |
586 } | |
587 | |
588 #if defined(OS_POSIX) | |
589 class ListenerThatExpectsFile : public IPC::Listener { | |
590 public: | |
591 ListenerThatExpectsFile() : sender_(NULL) {} | |
592 | |
593 ~ListenerThatExpectsFile() override {} | |
594 | |
595 bool OnMessageReceived(const IPC::Message& message) override { | |
596 base::PickleIterator iter(message); | |
597 HandleSendingHelper::ReadReceivedFile(message, &iter); | |
598 ListenerThatExpectsOK::SendOK(sender_); | |
599 return true; | |
600 } | |
601 | |
602 void OnChannelError() override { | |
603 base::MessageLoop::current()->QuitWhenIdle(); | |
604 } | |
605 | |
606 void set_sender(IPC::Sender* sender) { sender_ = sender; } | |
607 | |
608 private: | |
609 IPC::Sender* sender_; | |
610 }; | |
611 | |
612 TEST_F(IPCChannelMojoTest, SendPlatformHandle) { | |
613 InitWithMojo("IPCChannelMojoTestSendPlatformHandleClient"); | |
614 | |
615 ListenerThatExpectsOK listener; | |
616 CreateChannel(&listener); | |
617 ASSERT_TRUE(ConnectChannel()); | |
618 | |
619 base::File file(HandleSendingHelper::GetSendingFilePath(), | |
620 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | | |
621 base::File::FLAG_READ); | |
622 HandleSendingHelper::WriteFileThenSend(channel(), file); | |
623 base::MessageLoop::current()->Run(); | |
624 | |
625 channel()->Close(); | |
626 | |
627 EXPECT_TRUE(WaitForClientShutdown()); | |
628 DestroyChannel(); | |
629 } | |
630 | |
631 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendPlatformHandleClient, | |
632 ChannelClient) { | |
633 ListenerThatExpectsFile listener; | |
634 Connect(&listener); | |
635 listener.set_sender(channel()); | |
636 | |
637 base::MessageLoop::current()->Run(); | |
638 | |
639 Close(); | |
640 } | |
641 | |
642 class ListenerThatExpectsFileAndPipe : public IPC::Listener { | |
643 public: | |
644 ListenerThatExpectsFileAndPipe() : sender_(NULL) {} | |
645 | |
646 ~ListenerThatExpectsFileAndPipe() override {} | |
647 | |
648 bool OnMessageReceived(const IPC::Message& message) override { | |
649 base::PickleIterator iter(message); | |
650 HandleSendingHelper::ReadReceivedFile(message, &iter); | |
651 HandleSendingHelper::ReadReceivedPipe(message, &iter); | |
652 ListenerThatExpectsOK::SendOK(sender_); | |
653 return true; | |
654 } | |
655 | |
656 void OnChannelError() override { | |
657 base::MessageLoop::current()->QuitWhenIdle(); | |
658 } | |
659 | |
660 void set_sender(IPC::Sender* sender) { sender_ = sender; } | |
661 | |
662 private: | |
663 IPC::Sender* sender_; | |
664 }; | |
665 | |
666 TEST_F(IPCChannelMojoTest, SendPlatformHandleAndPipe) { | |
667 InitWithMojo("IPCChannelMojoTestSendPlatformHandleAndPipeClient"); | |
668 | |
669 ListenerThatExpectsOK listener; | |
670 CreateChannel(&listener); | |
671 ASSERT_TRUE(ConnectChannel()); | |
672 | |
673 base::File file(HandleSendingHelper::GetSendingFilePath(), | |
674 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | | |
675 base::File::FLAG_READ); | |
676 TestingMessagePipe pipe; | |
677 HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe); | |
678 | |
679 base::MessageLoop::current()->Run(); | |
680 channel()->Close(); | |
681 | |
682 EXPECT_TRUE(WaitForClientShutdown()); | |
683 DestroyChannel(); | |
684 } | |
685 | |
686 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT( | |
687 IPCChannelMojoTestSendPlatformHandleAndPipeClient, | |
688 ChannelClient) { | |
689 ListenerThatExpectsFileAndPipe listener; | |
690 Connect(&listener); | |
691 listener.set_sender(channel()); | |
692 | |
693 base::MessageLoop::current()->Run(); | |
694 | |
695 Close(); | |
696 } | |
697 | |
698 #endif | |
699 | |
700 #if defined(OS_LINUX) | |
701 | |
702 const base::ProcessId kMagicChildId = 54321; | |
703 | |
704 class ListenerThatVerifiesPeerPid : public IPC::Listener { | |
705 public: | |
706 void OnChannelConnected(int32_t peer_pid) override { | |
707 EXPECT_EQ(peer_pid, kMagicChildId); | |
708 base::MessageLoop::current()->QuitWhenIdle(); | |
709 } | |
710 | |
711 bool OnMessageReceived(const IPC::Message& message) override { | |
712 NOTREACHED(); | |
713 return true; | |
714 } | |
715 }; | |
716 | |
717 TEST_F(IPCChannelMojoTest, VerifyGlobalPid) { | |
718 InitWithMojo("IPCChannelMojoTestVerifyGlobalPidClient"); | |
719 | |
720 ListenerThatVerifiesPeerPid listener; | |
721 CreateChannel(&listener); | |
722 ASSERT_TRUE(ConnectChannel()); | |
723 | |
724 base::MessageLoop::current()->Run(); | |
725 channel()->Close(); | |
726 | |
727 EXPECT_TRUE(WaitForClientShutdown()); | |
728 DestroyChannel(); | |
729 } | |
730 | |
731 DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestVerifyGlobalPidClient, | |
732 ChannelClient) { | |
733 IPC::Channel::SetGlobalPid(kMagicChildId); | |
734 ListenerThatQuits listener; | |
735 Connect(&listener); | |
736 | |
737 base::MessageLoop::current()->Run(); | |
738 | |
739 Close(); | |
740 } | |
741 | |
742 #endif // OS_LINUX | |
743 | |
744 } // namespace | |
OLD | NEW |