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