blob: a133ba4367fdb80bea4d4aad915ace923eda6d26 [file] [log] [blame]
[email protected]64860882014-08-04 23:44:171// 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
amistryd4aa70d2016-06-23 07:52:375#include "ipc/ipc_channel_mojo.h"
[email protected]64860882014-08-04 23:44:176
avi246998d82015-12-22 02:39:047#include <stddef.h>
tfarina10a5c062015-09-04 18:47:578#include <stdint.h>
rockot7c6bf952016-07-14 00:34:119
danakj03de39b22016-04-23 04:21:0910#include <memory>
dchenge48600452015-12-28 02:24:5011#include <utility>
tfarina10a5c062015-09-04 18:47:5712
[email protected]64860882014-08-04 23:44:1713#include "base/base_paths.h"
rockot8d890f62016-07-14 16:37:1414#include "base/bind.h"
[email protected]64860882014-08-04 23:44:1715#include "base/files/file.h"
amistry20e2b1d62016-06-23 06:12:3516#include "base/files/scoped_temp_dir.h"
skyostile687bdff2015-05-12 11:29:2117#include "base/location.h"
rockot8d890f62016-07-14 16:37:1418#include "base/macros.h"
19#include "base/message_loop/message_loop.h"
[email protected]64860882014-08-04 23:44:1720#include "base/path_service.h"
21#include "base/pickle.h"
rockotcbca72f2015-03-03 16:31:0422#include "base/run_loop.h"
skyostile687bdff2015-05-12 11:29:2123#include "base/single_thread_task_runner.h"
rockot7c6bf952016-07-14 00:34:1124#include "base/strings/stringprintf.h"
rockot9abe09b2016-08-02 20:57:3425#include "base/synchronization/waitable_event.h"
sammc57ed9f982016-03-10 06:28:3526#include "base/test/test_io_thread.h"
morrita0bd20bd2015-02-25 20:11:2727#include "base/test/test_timeouts.h"
[email protected]64860882014-08-04 23:44:1728#include "base/threading/thread.h"
gabf08ccc02016-05-11 18:51:1129#include "base/threading/thread_task_runner_handle.h"
avi246998d82015-12-22 02:39:0430#include "build/build_config.h"
[email protected]64860882014-08-04 23:44:1731#include "ipc/ipc_message.h"
amistryd4aa70d2016-06-23 07:52:3732#include "ipc/ipc_mojo_handle_attachment.h"
33#include "ipc/ipc_mojo_message_helper.h"
34#include "ipc/ipc_mojo_param_traits.h"
rockot9abe09b2016-08-02 20:57:3435#include "ipc/ipc_sync_channel.h"
36#include "ipc/ipc_sync_message.h"
rockot7c6bf952016-07-14 00:34:1137#include "ipc/ipc_test.mojom.h"
[email protected]64860882014-08-04 23:44:1738#include "ipc/ipc_test_base.h"
39#include "ipc/ipc_test_channel_listener.h"
sammc57ed9f982016-03-10 06:28:3540#include "mojo/edk/test/mojo_test_base.h"
41#include "mojo/edk/test/multiprocess_test_helper.h"
42#include "testing/gtest/include/gtest/gtest.h"
[email protected]64860882014-08-04 23:44:1743
44#if defined(OS_POSIX)
45#include "base/file_descriptor_posix.h"
morrita1aa788c2015-01-31 05:45:4246#include "ipc/ipc_platform_file_attachment_posix.h"
[email protected]64860882014-08-04 23:44:1747#endif
48
sammcb0a39f82016-08-10 06:29:5449#define DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(client_name, test_base) \
50 class client_name##_MainFixture : public test_base { \
51 public: \
52 void Main(); \
53 }; \
54 MULTIPROCESS_TEST_MAIN_WITH_SETUP( \
55 client_name##TestChildMain, \
56 ::mojo::edk::test::MultiprocessTestHelper::ChildSetup) { \
57 client_name##_MainFixture test; \
58 test.Init( \
59 std::move(mojo::edk::test::MultiprocessTestHelper::primordial_pipe)); \
60 test.Main(); \
61 return (::testing::Test::HasFatalFailure() || \
62 ::testing::Test::HasNonfatalFailure()) \
63 ? 1 \
64 : 0; \
65 } \
sammc57ed9f982016-03-10 06:28:3566 void client_name##_MainFixture::Main()
67
[email protected]64860882014-08-04 23:44:1768namespace {
69
rockot7c6bf952016-07-14 00:34:1170void SendString(IPC::Sender* sender, const std::string& str) {
71 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
72 message->WriteString(str);
73 ASSERT_TRUE(sender->Send(message));
74}
75
rockot9abe09b2016-08-02 20:57:3476void SendValue(IPC::Sender* sender, int32_t value) {
77 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
78 message->WriteInt(value);
79 ASSERT_TRUE(sender->Send(message));
80}
81
[email protected]64860882014-08-04 23:44:1782class ListenerThatExpectsOK : public IPC::Listener {
83 public:
sammc57ed9f982016-03-10 06:28:3584 ListenerThatExpectsOK() : received_ok_(false) {}
[email protected]64860882014-08-04 23:44:1785
dchengfe61fca2014-10-22 02:29:5286 ~ListenerThatExpectsOK() override {}
[email protected]64860882014-08-04 23:44:1787
dchengfe61fca2014-10-22 02:29:5288 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:2589 base::PickleIterator iter(message);
[email protected]64860882014-08-04 23:44:1790 std::string should_be_ok;
91 EXPECT_TRUE(iter.ReadString(&should_be_ok));
92 EXPECT_EQ(should_be_ok, "OK");
[email protected]e5c27752014-08-08 21:45:1393 received_ok_ = true;
ki.stfua21ed8c2015-10-12 17:26:0094 base::MessageLoop::current()->QuitWhenIdle();
[email protected]64860882014-08-04 23:44:1795 return true;
96 }
97
dchengfe61fca2014-10-22 02:29:5298 void OnChannelError() override {
[email protected]e5c27752014-08-08 21:45:1399 // The connection should be healthy while the listener is waiting
100 // message. An error can occur after that because the peer
101 // process dies.
102 DCHECK(received_ok_);
[email protected]64860882014-08-04 23:44:17103 }
104
rockot7c6bf952016-07-14 00:34:11105 static void SendOK(IPC::Sender* sender) { SendString(sender, "OK"); }
[email protected]e5c27752014-08-08 21:45:13106
107 private:
108 bool received_ok_;
[email protected]64860882014-08-04 23:44:17109};
110
[email protected]64860882014-08-04 23:44:17111class ChannelClient {
112 public:
sammc57ed9f982016-03-10 06:28:35113 void Init(mojo::ScopedMessagePipeHandle handle) {
114 handle_ = std::move(handle);
tsergeant896012862016-03-10 03:51:33115 }
rockot8d890f62016-07-14 16:37:14116
sammc57ed9f982016-03-10 06:28:35117 void Connect(IPC::Listener* listener) {
rockota34707ca2016-07-20 04:28:32118 channel_ = IPC::ChannelMojo::Create(
119 std::move(handle_), IPC::Channel::MODE_CLIENT, listener,
120 base::ThreadTaskRunnerHandle::Get());
[email protected]64860882014-08-04 23:44:17121 CHECK(channel_->Connect());
122 }
123
rockotcbca72f2015-03-03 16:31:04124 void Close() {
125 channel_->Close();
126
127 base::RunLoop run_loop;
skyostile687bdff2015-05-12 11:29:21128 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
129 run_loop.QuitClosure());
rockotcbca72f2015-03-03 16:31:04130 run_loop.Run();
131 }
132
[email protected]64860882014-08-04 23:44:17133 IPC::ChannelMojo* channel() const { return channel_.get(); }
134
135 private:
[email protected]64860882014-08-04 23:44:17136 base::MessageLoopForIO main_message_loop_;
sammc57ed9f982016-03-10 06:28:35137 mojo::ScopedMessagePipeHandle handle_;
danakj03de39b22016-04-23 04:21:09138 std::unique_ptr<IPC::ChannelMojo> channel_;
[email protected]64860882014-08-04 23:44:17139};
140
rockot8d890f62016-07-14 16:37:14141class IPCChannelMojoTestBase : public testing::Test {
rockotcbca72f2015-03-03 16:31:04142 public:
143 void InitWithMojo(const std::string& test_client_name) {
sammc57ed9f982016-03-10 06:28:35144 handle_ = helper_.StartChild(test_client_name);
rockotcbca72f2015-03-03 16:31:04145 }
146
rockot8d890f62016-07-14 16:37:14147 bool WaitForClientShutdown() { return helper_.WaitForChildTestShutdown(); }
148
149 protected:
150 mojo::ScopedMessagePipeHandle TakeHandle() { return std::move(handle_); }
151
152 private:
153 mojo::ScopedMessagePipeHandle handle_;
154 mojo::edk::test::MultiprocessTestHelper helper_;
155};
156
157class IPCChannelMojoTest : public IPCChannelMojoTestBase {
158 public:
159 void TearDown() override { base::RunLoop().RunUntilIdle(); }
160
sammc57ed9f982016-03-10 06:28:35161 void CreateChannel(IPC::Listener* listener) {
rockot8d890f62016-07-14 16:37:14162 channel_ = IPC::ChannelMojo::Create(
rockota34707ca2016-07-20 04:28:32163 TakeHandle(), IPC::Channel::MODE_SERVER, listener,
164 base::ThreadTaskRunnerHandle::Get());
rockotcbca72f2015-03-03 16:31:04165 }
sammc57ed9f982016-03-10 06:28:35166
167 bool ConnectChannel() { return channel_->Connect(); }
168
169 void DestroyChannel() { channel_.reset(); }
170
sammc57ed9f982016-03-10 06:28:35171 IPC::Sender* sender() { return channel(); }
172 IPC::Channel* channel() { return channel_.get(); }
173
174 private:
175 base::MessageLoop message_loop_;
danakj03de39b22016-04-23 04:21:09176 std::unique_ptr<IPC::Channel> channel_;
rockotcbca72f2015-03-03 16:31:04177};
178
[email protected]64860882014-08-04 23:44:17179class TestChannelListenerWithExtraExpectations
180 : public IPC::TestChannelListener {
181 public:
sammc57ed9f982016-03-10 06:28:35182 TestChannelListenerWithExtraExpectations() : is_connected_called_(false) {}
[email protected]64860882014-08-04 23:44:17183
tfarina10a5c062015-09-04 18:47:57184 void OnChannelConnected(int32_t peer_pid) override {
[email protected]64860882014-08-04 23:44:17185 IPC::TestChannelListener::OnChannelConnected(peer_pid);
186 EXPECT_TRUE(base::kNullProcessId != peer_pid);
187 is_connected_called_ = true;
188 }
189
190 bool is_connected_called() const { return is_connected_called_; }
191
192 private:
193 bool is_connected_called_;
194};
195
amistry0027a0952016-05-03 00:52:47196TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
rockotcbca72f2015-03-03 16:31:04197 InitWithMojo("IPCChannelMojoTestClient");
[email protected]64860882014-08-04 23:44:17198
199 // Set up IPC channel and start client.
200 TestChannelListenerWithExtraExpectations listener;
morrita373af03b2014-09-09 19:35:24201 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:17202 listener.Init(sender());
203 ASSERT_TRUE(ConnectChannel());
[email protected]64860882014-08-04 23:44:17204
sammc57ed9f982016-03-10 06:28:35205 IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent");
[email protected]64860882014-08-04 23:44:17206
fdoray8e32586852016-06-22 19:56:16207 base::RunLoop().Run();
[email protected]64860882014-08-04 23:44:17208
sammc57ed9f982016-03-10 06:28:35209 channel()->Close();
[email protected]64860882014-08-04 23:44:17210
211 EXPECT_TRUE(WaitForClientShutdown());
212 EXPECT_TRUE(listener.is_connected_called());
213 EXPECT_TRUE(listener.HasSentAll());
214
215 DestroyChannel();
216}
217
218// A long running process that connects to us
sammc57ed9f982016-03-10 06:28:35219DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestClient, ChannelClient) {
[email protected]64860882014-08-04 23:44:17220 TestChannelListenerWithExtraExpectations listener;
sammc57ed9f982016-03-10 06:28:35221 Connect(&listener);
222 listener.Init(channel());
[email protected]64860882014-08-04 23:44:17223
sammc57ed9f982016-03-10 06:28:35224 IPC::TestChannelListener::SendOneMessage(channel(), "hello from child");
fdoray8e32586852016-06-22 19:56:16225 base::RunLoop().Run();
[email protected]64860882014-08-04 23:44:17226 EXPECT_TRUE(listener.is_connected_called());
227 EXPECT_TRUE(listener.HasSentAll());
228
sammc57ed9f982016-03-10 06:28:35229 Close();
[email protected]64860882014-08-04 23:44:17230}
231
morrita0a24cfc92014-09-16 03:20:48232class ListenerExpectingErrors : public IPC::Listener {
233 public:
sammc57ed9f982016-03-10 06:28:35234 ListenerExpectingErrors() : has_error_(false) {}
morrita0a24cfc92014-09-16 03:20:48235
dchengfe61fca2014-10-22 02:29:52236 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita0a24cfc92014-09-16 03:20:48237
dchengfe61fca2014-10-22 02:29:52238 void OnChannelError() override {
morrita0a24cfc92014-09-16 03:20:48239 has_error_ = true;
ki.stfua21ed8c2015-10-12 17:26:00240 base::MessageLoop::current()->QuitWhenIdle();
morrita0a24cfc92014-09-16 03:20:48241 }
242
243 bool has_error() const { return has_error_; }
244
245 private:
246 bool has_error_;
247};
248
morrita0a24cfc92014-09-16 03:20:48249class ListenerThatQuits : public IPC::Listener {
250 public:
sammc57ed9f982016-03-10 06:28:35251 ListenerThatQuits() {}
morrita0a24cfc92014-09-16 03:20:48252
sammc57ed9f982016-03-10 06:28:35253 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita0a24cfc92014-09-16 03:20:48254
tfarina10a5c062015-09-04 18:47:57255 void OnChannelConnected(int32_t peer_pid) override {
ki.stfua21ed8c2015-10-12 17:26:00256 base::MessageLoop::current()->QuitWhenIdle();
morrita0a24cfc92014-09-16 03:20:48257 }
258};
259
260// A long running process that connects to us.
sammc57ed9f982016-03-10 06:28:35261DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoErraticTestClient,
262 ChannelClient) {
morrita0a24cfc92014-09-16 03:20:48263 ListenerThatQuits listener;
sammc57ed9f982016-03-10 06:28:35264 Connect(&listener);
morrita0a24cfc92014-09-16 03:20:48265
fdoray8e32586852016-06-22 19:56:16266 base::RunLoop().Run();
morrita0a24cfc92014-09-16 03:20:48267
sammc57ed9f982016-03-10 06:28:35268 Close();
morrita0a24cfc92014-09-16 03:20:48269}
270
rockot8c23d462016-07-25 17:33:04271TEST_F(IPCChannelMojoTest, SendFailWithPendingMessages) {
rockotcbca72f2015-03-03 16:31:04272 InitWithMojo("IPCChannelMojoErraticTestClient");
morrita0a24cfc92014-09-16 03:20:48273
274 // Set up IPC channel and start client.
275 ListenerExpectingErrors listener;
276 CreateChannel(&listener);
277 ASSERT_TRUE(ConnectChannel());
278
jamesra03ae492014-10-03 04:26:48279 // This matches a value in mojo/edk/system/constants.h
morritabe6c4cc2014-09-24 23:38:44280 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
281 std::string overly_large_data(kMaxMessageNumBytes, '*');
morrita0a24cfc92014-09-16 03:20:48282 // This messages are queued as pending.
morritabe6c4cc2014-09-24 23:38:44283 for (size_t i = 0; i < 10; ++i) {
sammc57ed9f982016-03-10 06:28:35284 IPC::TestChannelListener::SendOneMessage(sender(),
285 overly_large_data.c_str());
morrita0a24cfc92014-09-16 03:20:48286 }
287
fdoray8e32586852016-06-22 19:56:16288 base::RunLoop().Run();
morrita0a24cfc92014-09-16 03:20:48289
sammc57ed9f982016-03-10 06:28:35290 channel()->Close();
morrita0a24cfc92014-09-16 03:20:48291
292 EXPECT_TRUE(WaitForClientShutdown());
293 EXPECT_TRUE(listener.has_error());
294
295 DestroyChannel();
296}
297
morrita81b17e02015-02-06 00:58:30298struct TestingMessagePipe {
299 TestingMessagePipe() {
300 EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateMessagePipe(nullptr, &self, &peer));
301 }
302
303 mojo::ScopedMessagePipeHandle self;
304 mojo::ScopedMessagePipeHandle peer;
305};
306
307class HandleSendingHelper {
308 public:
309 static std::string GetSendingFileContent() { return "Hello"; }
310
311 static void WritePipe(IPC::Message* message, TestingMessagePipe* pipe) {
312 std::string content = HandleSendingHelper::GetSendingFileContent();
313 EXPECT_EQ(MOJO_RESULT_OK,
314 mojo::WriteMessageRaw(pipe->self.get(), &content[0],
315 static_cast<uint32_t>(content.size()),
316 nullptr, 0, 0));
dchenge48600452015-12-28 02:24:50317 EXPECT_TRUE(IPC::MojoMessageHelper::WriteMessagePipeTo(
318 message, std::move(pipe->peer)));
morrita81b17e02015-02-06 00:58:30319 }
320
321 static void WritePipeThenSend(IPC::Sender* sender, TestingMessagePipe* pipe) {
322 IPC::Message* message =
323 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
324 WritePipe(message, pipe);
325 ASSERT_TRUE(sender->Send(message));
326 }
327
328 static void ReadReceivedPipe(const IPC::Message& message,
brettwbd4d7112015-06-03 04:29:25329 base::PickleIterator* iter) {
morrita81b17e02015-02-06 00:58:30330 mojo::ScopedMessagePipeHandle pipe;
331 EXPECT_TRUE(
332 IPC::MojoMessageHelper::ReadMessagePipeFrom(&message, iter, &pipe));
333 std::string content(GetSendingFileContent().size(), ' ');
334
335 uint32_t num_bytes = static_cast<uint32_t>(content.size());
sammc57ed9f982016-03-10 06:28:35336 ASSERT_EQ(MOJO_RESULT_OK,
337 mojo::Wait(pipe.get(), MOJO_HANDLE_SIGNAL_READABLE,
338 MOJO_DEADLINE_INDEFINITE, nullptr));
morrita81b17e02015-02-06 00:58:30339 EXPECT_EQ(MOJO_RESULT_OK,
340 mojo::ReadMessageRaw(pipe.get(), &content[0], &num_bytes, nullptr,
341 nullptr, 0));
342 EXPECT_EQ(content, GetSendingFileContent());
343 }
344
345#if defined(OS_POSIX)
amistry20e2b1d62016-06-23 06:12:35346 static base::FilePath GetSendingFilePath(const base::FilePath& dir_path) {
347 return dir_path.Append("ListenerThatExpectsFile.txt");
morrita81b17e02015-02-06 00:58:30348 }
349
350 static void WriteFile(IPC::Message* message, base::File& file) {
351 std::string content = GetSendingFileContent();
352 file.WriteAtCurrentPos(content.data(), content.size());
353 file.Flush();
354 message->WriteAttachment(new IPC::internal::PlatformFileAttachment(
355 base::ScopedFD(file.TakePlatformFile())));
356 }
357
358 static void WriteFileThenSend(IPC::Sender* sender, base::File& file) {
359 IPC::Message* message =
360 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
361 WriteFile(message, file);
362 ASSERT_TRUE(sender->Send(message));
363 }
364
365 static void WriteFileAndPipeThenSend(IPC::Sender* sender,
366 base::File& file,
367 TestingMessagePipe* pipe) {
368 IPC::Message* message =
369 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
370 WriteFile(message, file);
371 WritePipe(message, pipe);
372 ASSERT_TRUE(sender->Send(message));
373 }
374
375 static void ReadReceivedFile(const IPC::Message& message,
brettwbd4d7112015-06-03 04:29:25376 base::PickleIterator* iter) {
morrita81b17e02015-02-06 00:58:30377 base::ScopedFD fd;
rockot502c94f2016-02-03 20:20:16378 scoped_refptr<base::Pickle::Attachment> attachment;
morrita81b17e02015-02-06 00:58:30379 EXPECT_TRUE(message.ReadAttachment(iter, &attachment));
amistry980a61b2016-06-09 02:51:20380 EXPECT_EQ(IPC::MessageAttachment::TYPE_PLATFORM_FILE,
381 static_cast<IPC::MessageAttachment*>(attachment.get())
382 ->GetType());
rockot502c94f2016-02-03 20:20:16383 base::File file(static_cast<IPC::MessageAttachment*>(attachment.get())
384 ->TakePlatformFile());
morrita81b17e02015-02-06 00:58:30385 std::string content(GetSendingFileContent().size(), ' ');
386 file.Read(0, &content[0], content.size());
387 EXPECT_EQ(content, GetSendingFileContent());
388 }
389#endif
390};
391
392class ListenerThatExpectsMessagePipe : public IPC::Listener {
393 public:
394 ListenerThatExpectsMessagePipe() : sender_(NULL) {}
395
396 ~ListenerThatExpectsMessagePipe() override {}
397
398 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:25399 base::PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:30400 HandleSendingHelper::ReadReceivedPipe(message, &iter);
morrita81b17e02015-02-06 00:58:30401 ListenerThatExpectsOK::SendOK(sender_);
402 return true;
403 }
404
amistry6c70caea2016-06-09 03:08:29405 void OnChannelError() override {
406 base::MessageLoop::current()->QuitWhenIdle();
407 }
morrita81b17e02015-02-06 00:58:30408
409 void set_sender(IPC::Sender* sender) { sender_ = sender; }
410
411 private:
412 IPC::Sender* sender_;
413};
414
amistry0027a0952016-05-03 00:52:47415TEST_F(IPCChannelMojoTest, SendMessagePipe) {
rockotcbca72f2015-03-03 16:31:04416 InitWithMojo("IPCChannelMojoTestSendMessagePipeClient");
morrita81b17e02015-02-06 00:58:30417
418 ListenerThatExpectsOK listener;
419 CreateChannel(&listener);
420 ASSERT_TRUE(ConnectChannel());
morrita81b17e02015-02-06 00:58:30421
422 TestingMessagePipe pipe;
423 HandleSendingHelper::WritePipeThenSend(channel(), &pipe);
424
fdoray8e32586852016-06-22 19:56:16425 base::RunLoop().Run();
sammc57ed9f982016-03-10 06:28:35426 channel()->Close();
morrita81b17e02015-02-06 00:58:30427
428 EXPECT_TRUE(WaitForClientShutdown());
429 DestroyChannel();
430}
431
sammc57ed9f982016-03-10 06:28:35432DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendMessagePipeClient,
433 ChannelClient) {
morrita81b17e02015-02-06 00:58:30434 ListenerThatExpectsMessagePipe listener;
sammc57ed9f982016-03-10 06:28:35435 Connect(&listener);
436 listener.set_sender(channel());
morrita81b17e02015-02-06 00:58:30437
fdoray8e32586852016-06-22 19:56:16438 base::RunLoop().Run();
morrita81b17e02015-02-06 00:58:30439
sammc57ed9f982016-03-10 06:28:35440 Close();
morrita81b17e02015-02-06 00:58:30441}
442
morrita438a2ee2015-04-03 05:28:21443void ReadOK(mojo::MessagePipeHandle pipe) {
444 std::string should_be_ok("xx");
445 uint32_t num_bytes = static_cast<uint32_t>(should_be_ok.size());
sammc57ed9f982016-03-10 06:28:35446 CHECK_EQ(MOJO_RESULT_OK, mojo::Wait(pipe, MOJO_HANDLE_SIGNAL_READABLE,
447 MOJO_DEADLINE_INDEFINITE, nullptr));
morrita438a2ee2015-04-03 05:28:21448 CHECK_EQ(MOJO_RESULT_OK,
449 mojo::ReadMessageRaw(pipe, &should_be_ok[0], &num_bytes, nullptr,
450 nullptr, 0));
451 EXPECT_EQ(should_be_ok, std::string("OK"));
452}
453
454void WriteOK(mojo::MessagePipeHandle pipe) {
455 std::string ok("OK");
456 CHECK_EQ(MOJO_RESULT_OK,
457 mojo::WriteMessageRaw(pipe, &ok[0], static_cast<uint32_t>(ok.size()),
458 nullptr, 0, 0));
459}
460
461class ListenerThatExpectsMessagePipeUsingParamTrait : public IPC::Listener {
462 public:
463 explicit ListenerThatExpectsMessagePipeUsingParamTrait(bool receiving_valid)
464 : sender_(NULL), receiving_valid_(receiving_valid) {}
465
466 ~ListenerThatExpectsMessagePipeUsingParamTrait() override {}
467
468 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:25469 base::PickleIterator iter(message);
morrita438a2ee2015-04-03 05:28:21470 mojo::MessagePipeHandle handle;
471 EXPECT_TRUE(IPC::ParamTraits<mojo::MessagePipeHandle>::Read(&message, &iter,
472 &handle));
473 EXPECT_EQ(handle.is_valid(), receiving_valid_);
474 if (receiving_valid_) {
475 ReadOK(handle);
476 MojoClose(handle.value());
477 }
478
morrita438a2ee2015-04-03 05:28:21479 ListenerThatExpectsOK::SendOK(sender_);
480 return true;
481 }
482
amistry6c70caea2016-06-09 03:08:29483 void OnChannelError() override {
484 base::MessageLoop::current()->QuitWhenIdle();
485 }
486
morrita438a2ee2015-04-03 05:28:21487 void set_sender(IPC::Sender* sender) { sender_ = sender; }
488
489 private:
490 IPC::Sender* sender_;
491 bool receiving_valid_;
492};
493
sammc57ed9f982016-03-10 06:28:35494class ParamTraitMessagePipeClient : public ChannelClient {
495 public:
496 void RunTest(bool receiving_valid_handle) {
497 ListenerThatExpectsMessagePipeUsingParamTrait listener(
498 receiving_valid_handle);
499 Connect(&listener);
500 listener.set_sender(channel());
morrita438a2ee2015-04-03 05:28:21501
fdoray8e32586852016-06-22 19:56:16502 base::RunLoop().Run();
morrita438a2ee2015-04-03 05:28:21503
sammc57ed9f982016-03-10 06:28:35504 Close();
505 }
506};
morrita438a2ee2015-04-03 05:28:21507
amistry0027a0952016-05-03 00:52:47508TEST_F(IPCChannelMojoTest, ParamTraitValidMessagePipe) {
morrita438a2ee2015-04-03 05:28:21509 InitWithMojo("ParamTraitValidMessagePipeClient");
510
511 ListenerThatExpectsOK listener;
512 CreateChannel(&listener);
513 ASSERT_TRUE(ConnectChannel());
morrita438a2ee2015-04-03 05:28:21514
515 TestingMessagePipe pipe;
516
danakj03de39b22016-04-23 04:21:09517 std::unique_ptr<IPC::Message> message(new IPC::Message());
morrita438a2ee2015-04-03 05:28:21518 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(),
519 pipe.peer.release());
520 WriteOK(pipe.self.get());
521
sammc57ed9f982016-03-10 06:28:35522 channel()->Send(message.release());
fdoray8e32586852016-06-22 19:56:16523 base::RunLoop().Run();
sammc57ed9f982016-03-10 06:28:35524 channel()->Close();
morrita438a2ee2015-04-03 05:28:21525
526 EXPECT_TRUE(WaitForClientShutdown());
527 DestroyChannel();
528}
529
sammc57ed9f982016-03-10 06:28:35530DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ParamTraitValidMessagePipeClient,
531 ParamTraitMessagePipeClient) {
532 RunTest(true);
morrita438a2ee2015-04-03 05:28:21533}
534
amistry0027a0952016-05-03 00:52:47535TEST_F(IPCChannelMojoTest, ParamTraitInvalidMessagePipe) {
morrita438a2ee2015-04-03 05:28:21536 InitWithMojo("ParamTraitInvalidMessagePipeClient");
537
538 ListenerThatExpectsOK listener;
539 CreateChannel(&listener);
540 ASSERT_TRUE(ConnectChannel());
morrita438a2ee2015-04-03 05:28:21541
542 mojo::MessagePipeHandle invalid_handle;
danakj03de39b22016-04-23 04:21:09543 std::unique_ptr<IPC::Message> message(new IPC::Message());
morrita438a2ee2015-04-03 05:28:21544 IPC::ParamTraits<mojo::MessagePipeHandle>::Write(message.get(),
545 invalid_handle);
546
sammc57ed9f982016-03-10 06:28:35547 channel()->Send(message.release());
fdoray8e32586852016-06-22 19:56:16548 base::RunLoop().Run();
sammc57ed9f982016-03-10 06:28:35549 channel()->Close();
morrita438a2ee2015-04-03 05:28:21550
551 EXPECT_TRUE(WaitForClientShutdown());
552 DestroyChannel();
553}
554
sammc57ed9f982016-03-10 06:28:35555DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ParamTraitInvalidMessagePipeClient,
556 ParamTraitMessagePipeClient) {
557 RunTest(false);
morrita438a2ee2015-04-03 05:28:21558}
559
amistry0027a0952016-05-03 00:52:47560TEST_F(IPCChannelMojoTest, SendFailAfterClose) {
morrita17137e62015-06-23 22:29:36561 InitWithMojo("IPCChannelMojoTestSendOkClient");
562
563 ListenerThatExpectsOK listener;
564 CreateChannel(&listener);
565 ASSERT_TRUE(ConnectChannel());
morrita17137e62015-06-23 22:29:36566
fdoray8e32586852016-06-22 19:56:16567 base::RunLoop().Run();
sammc57ed9f982016-03-10 06:28:35568 channel()->Close();
569 ASSERT_FALSE(channel()->Send(new IPC::Message()));
morrita17137e62015-06-23 22:29:36570
571 EXPECT_TRUE(WaitForClientShutdown());
572 DestroyChannel();
573}
574
575class ListenerSendingOneOk : public IPC::Listener {
576 public:
sammc57ed9f982016-03-10 06:28:35577 ListenerSendingOneOk() {}
morrita17137e62015-06-23 22:29:36578
sammc57ed9f982016-03-10 06:28:35579 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita17137e62015-06-23 22:29:36580
tfarina10a5c062015-09-04 18:47:57581 void OnChannelConnected(int32_t peer_pid) override {
morrita17137e62015-06-23 22:29:36582 ListenerThatExpectsOK::SendOK(sender_);
ki.stfua21ed8c2015-10-12 17:26:00583 base::MessageLoop::current()->QuitWhenIdle();
morrita17137e62015-06-23 22:29:36584 }
585
586 void set_sender(IPC::Sender* sender) { sender_ = sender; }
587
588 private:
589 IPC::Sender* sender_;
590};
591
sammc57ed9f982016-03-10 06:28:35592DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendOkClient,
593 ChannelClient) {
morrita17137e62015-06-23 22:29:36594 ListenerSendingOneOk listener;
sammc57ed9f982016-03-10 06:28:35595 Connect(&listener);
596 listener.set_sender(channel());
morrita17137e62015-06-23 22:29:36597
fdoray8e32586852016-06-22 19:56:16598 base::RunLoop().Run();
morrita17137e62015-06-23 22:29:36599
sammc57ed9f982016-03-10 06:28:35600 Close();
morrita17137e62015-06-23 22:29:36601}
602
rockot7c6bf952016-07-14 00:34:11603class ListenerWithSimpleAssociatedInterface
604 : public IPC::Listener,
605 public IPC::mojom::SimpleTestDriver {
606 public:
607 static const int kNumMessages;
608
609 ListenerWithSimpleAssociatedInterface() : binding_(this) {}
610
611 ~ListenerWithSimpleAssociatedInterface() override {}
612
613 bool OnMessageReceived(const IPC::Message& message) override {
614 base::PickleIterator iter(message);
rockot9abe09b2016-08-02 20:57:34615 int32_t should_be_expected;
616 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
617 EXPECT_EQ(should_be_expected, next_expected_value_);
rockot7c6bf952016-07-14 00:34:11618 num_messages_received_++;
619 return true;
620 }
621
622 void OnChannelError() override {
623 DCHECK(received_quit_);
624 }
625
626 void RegisterInterfaceFactory(IPC::Channel* channel) {
627 channel->GetAssociatedInterfaceSupport()->AddAssociatedInterface(
628 base::Bind(&ListenerWithSimpleAssociatedInterface::BindRequest,
629 base::Unretained(this)));
630 }
631
632 private:
633 // IPC::mojom::SimpleTestDriver:
rockot9abe09b2016-08-02 20:57:34634 void ExpectValue(int32_t value) override {
635 next_expected_value_ = value;
636 }
637
638 void GetExpectedValue(const GetExpectedValueCallback& callback) override {
639 NOTREACHED();
640 }
641
642 void RequestValue(const RequestValueCallback& callback) override {
643 NOTREACHED();
rockot7c6bf952016-07-14 00:34:11644 }
645
646 void RequestQuit(const RequestQuitCallback& callback) override {
647 EXPECT_EQ(kNumMessages, num_messages_received_);
648 received_quit_ = true;
649 callback.Run();
650 base::MessageLoop::current()->QuitWhenIdle();
651 }
652
653 void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
654 DCHECK(!binding_.is_bound());
655 binding_.Bind(std::move(request));
656 }
657
rockot9abe09b2016-08-02 20:57:34658 int32_t next_expected_value_ = 0;
rockot7c6bf952016-07-14 00:34:11659 int num_messages_received_ = 0;
660 bool received_quit_ = false;
661
662 mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_;
663};
664
665const int ListenerWithSimpleAssociatedInterface::kNumMessages = 1000;
666
667class ListenerSendingAssociatedMessages : public IPC::Listener {
668 public:
669 ListenerSendingAssociatedMessages() {}
670
671 bool OnMessageReceived(const IPC::Message& message) override { return true; }
672
673 void OnChannelConnected(int32_t peer_pid) override {
674 DCHECK(channel_);
675 channel_->GetAssociatedInterfaceSupport()->GetRemoteAssociatedInterface(
676 &driver_);
677
678 // Send a bunch of interleaved messages, alternating between the associated
679 // interface and a legacy IPC::Message.
680 for (int i = 0; i < ListenerWithSimpleAssociatedInterface::kNumMessages;
681 ++i) {
rockot9abe09b2016-08-02 20:57:34682 driver_->ExpectValue(i);
683 SendValue(channel_, i);
rockot7c6bf952016-07-14 00:34:11684 }
685 driver_->RequestQuit(base::Bind(&OnQuitAck));
686 }
687
688 void set_channel(IPC::Channel* channel) { channel_ = channel; }
689
690 private:
691 static void OnQuitAck() { base::MessageLoop::current()->QuitWhenIdle(); }
692
693 IPC::Channel* channel_ = nullptr;
694 IPC::mojom::SimpleTestDriverAssociatedPtr driver_;
695};
696
697TEST_F(IPCChannelMojoTest, SimpleAssociatedInterface) {
698 InitWithMojo("SimpleAssociatedInterfaceClient");
699
700 ListenerWithSimpleAssociatedInterface listener;
701 CreateChannel(&listener);
702 ASSERT_TRUE(ConnectChannel());
703
704 listener.RegisterInterfaceFactory(channel());
705
706 base::RunLoop().Run();
707 channel()->Close();
708
709 EXPECT_TRUE(WaitForClientShutdown());
710 DestroyChannel();
711}
712
713DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SimpleAssociatedInterfaceClient,
714 ChannelClient) {
715 ListenerSendingAssociatedMessages listener;
716 Connect(&listener);
717 listener.set_channel(channel());
718
719 base::RunLoop().Run();
720
721 Close();
722}
723
rockot8d890f62016-07-14 16:37:14724class ChannelProxyRunner {
725 public:
rockota34707ca2016-07-20 04:28:32726 ChannelProxyRunner(mojo::ScopedMessagePipeHandle handle,
727 bool for_server)
728 : for_server_(for_server),
729 handle_(std::move(handle)),
rockot9abe09b2016-08-02 20:57:34730 io_thread_("ChannelProxyRunner IO thread"),
731 never_signaled_(base::WaitableEvent::ResetPolicy::MANUAL,
732 base::WaitableEvent::InitialState::NOT_SIGNALED) {
rockot8d890f62016-07-14 16:37:14733 }
734
735 void CreateProxy(IPC::Listener* listener) {
736 io_thread_.StartWithOptions(
737 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
rockot9abe09b2016-08-02 20:57:34738 proxy_ = IPC::SyncChannel::Create(
739 listener, io_thread_.task_runner(), &never_signaled_);
rockot8d890f62016-07-14 16:37:14740 }
rockota34707ca2016-07-20 04:28:32741
742 void RunProxy() {
743 std::unique_ptr<IPC::ChannelFactory> factory;
744 if (for_server_) {
745 factory = IPC::ChannelMojo::CreateServerFactory(
746 std::move(handle_), io_thread_.task_runner());
747 } else {
748 factory = IPC::ChannelMojo::CreateClientFactory(
749 std::move(handle_), io_thread_.task_runner());
750 }
751 proxy_->Init(std::move(factory), true);
752 }
rockot8d890f62016-07-14 16:37:14753
754 IPC::ChannelProxy* proxy() { return proxy_.get(); }
755
756 private:
rockota34707ca2016-07-20 04:28:32757 const bool for_server_;
rockot8d890f62016-07-14 16:37:14758
rockota34707ca2016-07-20 04:28:32759 mojo::ScopedMessagePipeHandle handle_;
rockot8d890f62016-07-14 16:37:14760 base::Thread io_thread_;
761 std::unique_ptr<IPC::ChannelProxy> proxy_;
rockot9abe09b2016-08-02 20:57:34762 base::WaitableEvent never_signaled_;
rockot8d890f62016-07-14 16:37:14763
764 DISALLOW_COPY_AND_ASSIGN(ChannelProxyRunner);
765};
766
767class IPCChannelProxyMojoTest : public IPCChannelMojoTestBase {
768 public:
769 void InitWithMojo(const std::string& client_name) {
770 IPCChannelMojoTestBase::InitWithMojo(client_name);
rockota34707ca2016-07-20 04:28:32771 runner_.reset(new ChannelProxyRunner(TakeHandle(), true));
rockot8d890f62016-07-14 16:37:14772 }
773 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); }
774 void RunProxy() { runner_->RunProxy(); }
rockot0e4de5f2016-07-22 21:18:07775 void DestroyProxy() {
776 runner_.reset();
777 base::RunLoop().RunUntilIdle();
778 }
rockot8d890f62016-07-14 16:37:14779
780 IPC::ChannelProxy* proxy() { return runner_->proxy(); }
781
782 private:
783 base::MessageLoop message_loop_;
784 std::unique_ptr<ChannelProxyRunner> runner_;
785};
786
787class ListenerWithSimpleProxyAssociatedInterface
788 : public IPC::Listener,
789 public IPC::mojom::SimpleTestDriver {
790 public:
791 static const int kNumMessages;
792
793 ListenerWithSimpleProxyAssociatedInterface() : binding_(this) {}
794
795 ~ListenerWithSimpleProxyAssociatedInterface() override {}
796
797 bool OnMessageReceived(const IPC::Message& message) override {
798 base::PickleIterator iter(message);
rockot9abe09b2016-08-02 20:57:34799 int32_t should_be_expected;
800 EXPECT_TRUE(iter.ReadInt(&should_be_expected));
801 EXPECT_EQ(should_be_expected, next_expected_value_);
rockot8d890f62016-07-14 16:37:14802 num_messages_received_++;
803 return true;
804 }
805
806 void OnChannelError() override {
807 DCHECK(received_quit_);
808 }
809
810 void RegisterInterfaceFactory(IPC::ChannelProxy* proxy) {
811 proxy->AddAssociatedInterface(
812 base::Bind(&ListenerWithSimpleProxyAssociatedInterface::BindRequest,
813 base::Unretained(this)));
814 }
815
816 bool received_all_messages() const {
817 return num_messages_received_ == kNumMessages && received_quit_;
818 }
819
820 private:
821 // IPC::mojom::SimpleTestDriver:
rockot9abe09b2016-08-02 20:57:34822 void ExpectValue(int32_t value) override {
823 next_expected_value_ = value;
824 }
825
826 void GetExpectedValue(const GetExpectedValueCallback& callback) override {
827 callback.Run(next_expected_value_);
828 }
829
830 void RequestValue(const RequestValueCallback& callback) override {
831 NOTREACHED();
rockot8d890f62016-07-14 16:37:14832 }
833
834 void RequestQuit(const RequestQuitCallback& callback) override {
835 received_quit_ = true;
836 callback.Run();
rockot0e4de5f2016-07-22 21:18:07837 binding_.Close();
rockot8d890f62016-07-14 16:37:14838 base::MessageLoop::current()->QuitWhenIdle();
839 }
840
841 void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
842 DCHECK(!binding_.is_bound());
843 binding_.Bind(std::move(request));
844 }
845
rockot9abe09b2016-08-02 20:57:34846 int32_t next_expected_value_ = 0;
rockot8d890f62016-07-14 16:37:14847 int num_messages_received_ = 0;
848 bool received_quit_ = false;
849
850 mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_;
851};
852
853const int ListenerWithSimpleProxyAssociatedInterface::kNumMessages = 1000;
854
855TEST_F(IPCChannelProxyMojoTest, ProxyThreadAssociatedInterface) {
856 InitWithMojo("ProxyThreadAssociatedInterfaceClient");
857
858 ListenerWithSimpleProxyAssociatedInterface listener;
859 CreateProxy(&listener);
860 listener.RegisterInterfaceFactory(proxy());
861 RunProxy();
862
863 base::RunLoop().Run();
864
865 EXPECT_TRUE(WaitForClientShutdown());
866 EXPECT_TRUE(listener.received_all_messages());
867
rockot0e4de5f2016-07-22 21:18:07868 DestroyProxy();
rockot8d890f62016-07-14 16:37:14869}
870
871class ChannelProxyClient {
872 public:
873 void Init(mojo::ScopedMessagePipeHandle handle) {
rockota34707ca2016-07-20 04:28:32874 runner_.reset(new ChannelProxyRunner(std::move(handle), false));
rockot8d890f62016-07-14 16:37:14875 }
rockot9abe09b2016-08-02 20:57:34876
rockot8d890f62016-07-14 16:37:14877 void CreateProxy(IPC::Listener* listener) { runner_->CreateProxy(listener); }
rockot9abe09b2016-08-02 20:57:34878
rockot8d890f62016-07-14 16:37:14879 void RunProxy() { runner_->RunProxy(); }
rockot9abe09b2016-08-02 20:57:34880
rockot0e4de5f2016-07-22 21:18:07881 void DestroyProxy() {
882 runner_.reset();
883 base::RunLoop().RunUntilIdle();
884 }
rockot8d890f62016-07-14 16:37:14885
rockot9abe09b2016-08-02 20:57:34886 void RequestQuitAndWaitForAck(IPC::mojom::SimpleTestDriver* driver) {
887 base::RunLoop loop;
888 driver->RequestQuit(loop.QuitClosure());
889 loop.Run();
890 }
891
rockot8d890f62016-07-14 16:37:14892 IPC::ChannelProxy* proxy() { return runner_->proxy(); }
893
894 private:
895 base::MessageLoop message_loop_;
896 std::unique_ptr<ChannelProxyRunner> runner_;
897};
898
rockot0e4de5f2016-07-22 21:18:07899class DummyListener : public IPC::Listener {
rockot8d890f62016-07-14 16:37:14900 public:
rockot8d890f62016-07-14 16:37:14901 // IPC::Listener
902 bool OnMessageReceived(const IPC::Message& message) override { return true; }
rockot8d890f62016-07-14 16:37:14903};
904
905DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(ProxyThreadAssociatedInterfaceClient,
906 ChannelProxyClient) {
rockot0e4de5f2016-07-22 21:18:07907 DummyListener listener;
rockot8d890f62016-07-14 16:37:14908 CreateProxy(&listener);
909 RunProxy();
rockot8d890f62016-07-14 16:37:14910
911 // Send a bunch of interleaved messages, alternating between the associated
912 // interface and a legacy IPC::Message.
913 IPC::mojom::SimpleTestDriverAssociatedPtr driver;
914 proxy()->GetRemoteAssociatedInterface(&driver);
915 for (int i = 0; i < ListenerWithSimpleProxyAssociatedInterface::kNumMessages;
916 ++i) {
rockot9abe09b2016-08-02 20:57:34917 driver->ExpectValue(i);
918 SendValue(proxy(), i);
rockot8d890f62016-07-14 16:37:14919 }
920 driver->RequestQuit(base::MessageLoop::QuitWhenIdleClosure());
921 base::RunLoop().Run();
rockot0e4de5f2016-07-22 21:18:07922
923 DestroyProxy();
rockot8d890f62016-07-14 16:37:14924}
925
rockot9abe09b2016-08-02 20:57:34926class ListenerWithSyncAssociatedInterface
927 : public IPC::Listener,
928 public IPC::mojom::SimpleTestDriver {
929 public:
930 ListenerWithSyncAssociatedInterface() : binding_(this) {}
931 ~ListenerWithSyncAssociatedInterface() override {}
932
933 void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
934
935 void RegisterInterfaceFactory(IPC::ChannelProxy* proxy) {
936 proxy->AddAssociatedInterface(
937 base::Bind(&ListenerWithSyncAssociatedInterface::BindRequest,
938 base::Unretained(this)));
939 }
940
941 void RunUntilQuitRequested() {
942 base::RunLoop loop;
943 quit_closure_ = loop.QuitClosure();
944 loop.Run();
945 }
946
947 void CloseBinding() { binding_.Close(); }
948
949 void set_response_value(int32_t response) {
950 response_value_ = response;
951 }
952
953 private:
954 // IPC::mojom::SimpleTestDriver:
955 void ExpectValue(int32_t value) override {
956 next_expected_value_ = value;
957 }
958
959 void GetExpectedValue(const GetExpectedValueCallback& callback) override {
960 callback.Run(next_expected_value_);
961 }
962
963 void RequestValue(const RequestValueCallback& callback) override {
964 callback.Run(response_value_);
965 }
966
967 void RequestQuit(const RequestQuitCallback& callback) override {
968 quit_closure_.Run();
969 callback.Run();
970 }
971
972 // IPC::Listener:
973 bool OnMessageReceived(const IPC::Message& message) override {
974 EXPECT_EQ(0u, message.type());
975 EXPECT_TRUE(message.is_sync());
976 EXPECT_TRUE(message.should_unblock());
977 std::unique_ptr<IPC::Message> reply(
978 IPC::SyncMessage::GenerateReply(&message));
979 reply->WriteInt(response_value_);
980 DCHECK(sync_sender_);
981 EXPECT_TRUE(sync_sender_->Send(reply.release()));
982 return true;
983 }
984
985 void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) {
986 DCHECK(!binding_.is_bound());
987 binding_.Bind(std::move(request));
988 }
989
990 IPC::Sender* sync_sender_ = nullptr;
991 int32_t next_expected_value_ = 0;
992 int32_t response_value_ = 0;
993 base::Closure quit_closure_;
994
995 mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_;
996};
997
998class SyncReplyReader : public IPC::MessageReplyDeserializer {
999 public:
1000 explicit SyncReplyReader(int32_t* storage) : storage_(storage) {}
1001 ~SyncReplyReader() override {}
1002
1003 private:
1004 // IPC::MessageReplyDeserializer:
1005 bool SerializeOutputParameters(const IPC::Message& message,
1006 base::PickleIterator iter) override {
1007 if (!iter.ReadInt(storage_))
1008 return false;
1009 return true;
1010 }
1011
1012 int32_t* storage_;
1013
1014 DISALLOW_COPY_AND_ASSIGN(SyncReplyReader);
1015};
1016
1017TEST_F(IPCChannelProxyMojoTest, SyncAssociatedInterface) {
1018 InitWithMojo("SyncAssociatedInterface");
1019
1020 ListenerWithSyncAssociatedInterface listener;
1021 CreateProxy(&listener);
1022 listener.set_sync_sender(proxy());
1023 listener.RegisterInterfaceFactory(proxy());
1024 RunProxy();
1025
1026 // Run the client's simple sanity check to completion.
1027 listener.RunUntilQuitRequested();
1028
1029 // Verify that we can send a sync IPC and service an incoming sync request
1030 // while waiting on it
1031 listener.set_response_value(42);
1032 IPC::mojom::SimpleTestClientAssociatedPtr client;
1033 proxy()->GetRemoteAssociatedInterface(&client);
1034 int32_t received_value;
1035 EXPECT_TRUE(client->RequestValue(&received_value));
1036 EXPECT_EQ(42, received_value);
1037
1038 // Do it again. This time the client will send a classical sync IPC to us
1039 // while we wait.
1040 received_value = 0;
1041 EXPECT_TRUE(client->RequestValue(&received_value));
1042 EXPECT_EQ(42, received_value);
1043
1044 // Now make a classical sync IPC request to the client. It will send a
1045 // sync associated interface message to us while we wait.
1046 received_value = 0;
1047 std::unique_ptr<IPC::SyncMessage> request(
1048 new IPC::SyncMessage(0, 0, IPC::Message::PRIORITY_NORMAL,
1049 new SyncReplyReader(&received_value)));
1050 EXPECT_TRUE(proxy()->Send(request.release()));
1051 EXPECT_EQ(42, received_value);
1052
1053 listener.CloseBinding();
1054 EXPECT_TRUE(WaitForClientShutdown());
1055
1056 DestroyProxy();
1057}
1058
1059class SimpleTestClientImpl : public IPC::mojom::SimpleTestClient,
1060 public IPC::Listener {
1061 public:
1062 SimpleTestClientImpl() : binding_(this) {}
1063
1064 void set_driver(IPC::mojom::SimpleTestDriver* driver) { driver_ = driver; }
1065 void set_sync_sender(IPC::Sender* sync_sender) { sync_sender_ = sync_sender; }
1066
1067 void BindRequest(IPC::mojom::SimpleTestClientAssociatedRequest request) {
1068 DCHECK(!binding_.is_bound());
1069 binding_.Bind(std::move(request));
1070 }
1071
1072 void WaitForValueRequest() {
1073 run_loop_.reset(new base::RunLoop);
1074 run_loop_->Run();
1075 }
1076
1077 void UseSyncSenderForRequest(bool use_sync_sender) {
1078 use_sync_sender_ = use_sync_sender;
1079 }
1080
1081 private:
1082 // IPC::mojom::SimpleTestClient:
1083 void RequestValue(const RequestValueCallback& callback) override {
1084 int32_t response = 0;
1085 if (use_sync_sender_) {
1086 std::unique_ptr<IPC::SyncMessage> reply(new IPC::SyncMessage(
1087 0, 0, IPC::Message::PRIORITY_NORMAL, new SyncReplyReader(&response)));
1088 EXPECT_TRUE(sync_sender_->Send(reply.release()));
1089 } else {
1090 DCHECK(driver_);
1091 EXPECT_TRUE(driver_->RequestValue(&response));
1092 }
1093
1094 callback.Run(response);
1095
1096 DCHECK(run_loop_);
1097 run_loop_->Quit();
1098 }
1099
1100 // IPC::Listener:
1101 bool OnMessageReceived(const IPC::Message& message) override {
1102 int32_t response;
1103 DCHECK(driver_);
1104 EXPECT_TRUE(driver_->RequestValue(&response));
1105 std::unique_ptr<IPC::Message> reply(
1106 IPC::SyncMessage::GenerateReply(&message));
1107 reply->WriteInt(response);
1108 EXPECT_TRUE(sync_sender_->Send(reply.release()));
1109
1110 DCHECK(run_loop_);
1111 run_loop_->Quit();
1112 return true;
1113 }
1114
1115 bool use_sync_sender_ = false;
1116 mojo::AssociatedBinding<IPC::mojom::SimpleTestClient> binding_;
1117 IPC::Sender* sync_sender_ = nullptr;
1118 IPC::mojom::SimpleTestDriver* driver_ = nullptr;
1119 std::unique_ptr<base::RunLoop> run_loop_;
1120
1121 DISALLOW_COPY_AND_ASSIGN(SimpleTestClientImpl);
1122};
1123
1124DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SyncAssociatedInterface,
1125 ChannelProxyClient) {
1126 SimpleTestClientImpl client_impl;
1127 CreateProxy(&client_impl);
1128 client_impl.set_sync_sender(proxy());
1129 proxy()->AddAssociatedInterface(base::Bind(&SimpleTestClientImpl::BindRequest,
1130 base::Unretained(&client_impl)));
1131 RunProxy();
1132
1133 IPC::mojom::SimpleTestDriverAssociatedPtr driver;
1134 proxy()->GetRemoteAssociatedInterface(&driver);
1135 client_impl.set_driver(driver.get());
1136
1137 // Simple sync message sanity check.
1138 driver->ExpectValue(42);
1139 int32_t expected_value = 0;
1140 EXPECT_TRUE(driver->GetExpectedValue(&expected_value));
1141 EXPECT_EQ(42, expected_value);
1142 RequestQuitAndWaitForAck(driver.get());
1143
1144 // Wait for the test driver to perform a sync call test with our own sync
1145 // associated interface message nested inside.
1146 client_impl.UseSyncSenderForRequest(false);
1147 client_impl.WaitForValueRequest();
1148
1149 // Wait for the test driver to perform a sync call test with our own classical
1150 // sync IPC nested inside.
1151 client_impl.UseSyncSenderForRequest(true);
1152 client_impl.WaitForValueRequest();
1153
1154 // Wait for the test driver to perform a classical sync IPC request, with our
1155 // own sync associated interface message nested inside.
1156 client_impl.UseSyncSenderForRequest(false);
1157 client_impl.WaitForValueRequest();
1158
1159 DestroyProxy();
1160}
1161
[email protected]64860882014-08-04 23:44:171162#if defined(OS_POSIX)
rockot8d890f62016-07-14 16:37:141163
[email protected]64860882014-08-04 23:44:171164class ListenerThatExpectsFile : public IPC::Listener {
1165 public:
sammc57ed9f982016-03-10 06:28:351166 ListenerThatExpectsFile() : sender_(NULL) {}
[email protected]64860882014-08-04 23:44:171167
dchengfe61fca2014-10-22 02:29:521168 ~ListenerThatExpectsFile() override {}
[email protected]64860882014-08-04 23:44:171169
dchengfe61fca2014-10-22 02:29:521170 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:251171 base::PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:301172 HandleSendingHelper::ReadReceivedFile(message, &iter);
[email protected]64860882014-08-04 23:44:171173 ListenerThatExpectsOK::SendOK(sender_);
1174 return true;
1175 }
1176
amistry6c70caea2016-06-09 03:08:291177 void OnChannelError() override {
1178 base::MessageLoop::current()->QuitWhenIdle();
1179 }
[email protected]64860882014-08-04 23:44:171180
[email protected]64860882014-08-04 23:44:171181 void set_sender(IPC::Sender* sender) { sender_ = sender; }
1182
1183 private:
1184 IPC::Sender* sender_;
1185};
1186
amistry0027a0952016-05-03 00:52:471187TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
rockotcbca72f2015-03-03 16:31:041188 InitWithMojo("IPCChannelMojoTestSendPlatformHandleClient");
[email protected]64860882014-08-04 23:44:171189
1190 ListenerThatExpectsOK listener;
morrita373af03b2014-09-09 19:35:241191 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:171192 ASSERT_TRUE(ConnectChannel());
[email protected]64860882014-08-04 23:44:171193
amistry20e2b1d62016-06-23 06:12:351194 base::ScopedTempDir temp_dir;
1195 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1196 base::File file(HandleSendingHelper::GetSendingFilePath(temp_dir.path()),
[email protected]64860882014-08-04 23:44:171197 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
morrita81b17e02015-02-06 00:58:301198 base::File::FLAG_READ);
1199 HandleSendingHelper::WriteFileThenSend(channel(), file);
fdoray8e32586852016-06-22 19:56:161200 base::RunLoop().Run();
[email protected]64860882014-08-04 23:44:171201
sammc57ed9f982016-03-10 06:28:351202 channel()->Close();
[email protected]64860882014-08-04 23:44:171203
1204 EXPECT_TRUE(WaitForClientShutdown());
1205 DestroyChannel();
1206}
1207
sammc57ed9f982016-03-10 06:28:351208DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestSendPlatformHandleClient,
1209 ChannelClient) {
[email protected]64860882014-08-04 23:44:171210 ListenerThatExpectsFile listener;
sammc57ed9f982016-03-10 06:28:351211 Connect(&listener);
1212 listener.set_sender(channel());
[email protected]64860882014-08-04 23:44:171213
fdoray8e32586852016-06-22 19:56:161214 base::RunLoop().Run();
[email protected]64860882014-08-04 23:44:171215
sammc57ed9f982016-03-10 06:28:351216 Close();
[email protected]64860882014-08-04 23:44:171217}
morrita81b17e02015-02-06 00:58:301218
1219class ListenerThatExpectsFileAndPipe : public IPC::Listener {
1220 public:
1221 ListenerThatExpectsFileAndPipe() : sender_(NULL) {}
1222
1223 ~ListenerThatExpectsFileAndPipe() override {}
1224
1225 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:251226 base::PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:301227 HandleSendingHelper::ReadReceivedFile(message, &iter);
1228 HandleSendingHelper::ReadReceivedPipe(message, &iter);
morrita81b17e02015-02-06 00:58:301229 ListenerThatExpectsOK::SendOK(sender_);
1230 return true;
1231 }
1232
amistry6c70caea2016-06-09 03:08:291233 void OnChannelError() override {
1234 base::MessageLoop::current()->QuitWhenIdle();
1235 }
morrita81b17e02015-02-06 00:58:301236
1237 void set_sender(IPC::Sender* sender) { sender_ = sender; }
1238
1239 private:
1240 IPC::Sender* sender_;
1241};
1242
amistry0027a0952016-05-03 00:52:471243TEST_F(IPCChannelMojoTest, SendPlatformHandleAndPipe) {
rockotcbca72f2015-03-03 16:31:041244 InitWithMojo("IPCChannelMojoTestSendPlatformHandleAndPipeClient");
morrita81b17e02015-02-06 00:58:301245
1246 ListenerThatExpectsOK listener;
1247 CreateChannel(&listener);
1248 ASSERT_TRUE(ConnectChannel());
morrita81b17e02015-02-06 00:58:301249
amistry20e2b1d62016-06-23 06:12:351250 base::ScopedTempDir temp_dir;
1251 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
1252 base::File file(HandleSendingHelper::GetSendingFilePath(temp_dir.path()),
morrita81b17e02015-02-06 00:58:301253 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
1254 base::File::FLAG_READ);
1255 TestingMessagePipe pipe;
1256 HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe);
1257
fdoray8e32586852016-06-22 19:56:161258 base::RunLoop().Run();
sammc57ed9f982016-03-10 06:28:351259 channel()->Close();
morrita81b17e02015-02-06 00:58:301260
1261 EXPECT_TRUE(WaitForClientShutdown());
1262 DestroyChannel();
1263}
1264
sammc57ed9f982016-03-10 06:28:351265DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(
1266 IPCChannelMojoTestSendPlatformHandleAndPipeClient,
1267 ChannelClient) {
morrita81b17e02015-02-06 00:58:301268 ListenerThatExpectsFileAndPipe listener;
sammc57ed9f982016-03-10 06:28:351269 Connect(&listener);
1270 listener.set_sender(channel());
morrita81b17e02015-02-06 00:58:301271
fdoray8e32586852016-06-22 19:56:161272 base::RunLoop().Run();
morrita81b17e02015-02-06 00:58:301273
sammc57ed9f982016-03-10 06:28:351274 Close();
morrita81b17e02015-02-06 00:58:301275}
1276
rockot7c6bf952016-07-14 00:34:111277#endif // defined(OS_POSIX)
[email protected]64860882014-08-04 23:44:171278
morrita0bd20bd2015-02-25 20:11:271279#if defined(OS_LINUX)
1280
1281const base::ProcessId kMagicChildId = 54321;
1282
1283class ListenerThatVerifiesPeerPid : public IPC::Listener {
1284 public:
tfarina10a5c062015-09-04 18:47:571285 void OnChannelConnected(int32_t peer_pid) override {
morrita0bd20bd2015-02-25 20:11:271286 EXPECT_EQ(peer_pid, kMagicChildId);
ki.stfua21ed8c2015-10-12 17:26:001287 base::MessageLoop::current()->QuitWhenIdle();
morrita0bd20bd2015-02-25 20:11:271288 }
1289
1290 bool OnMessageReceived(const IPC::Message& message) override {
1291 NOTREACHED();
1292 return true;
1293 }
1294};
1295
sammc57ed9f982016-03-10 06:28:351296TEST_F(IPCChannelMojoTest, VerifyGlobalPid) {
rockotcbca72f2015-03-03 16:31:041297 InitWithMojo("IPCChannelMojoTestVerifyGlobalPidClient");
morrita0bd20bd2015-02-25 20:11:271298
1299 ListenerThatVerifiesPeerPid listener;
1300 CreateChannel(&listener);
1301 ASSERT_TRUE(ConnectChannel());
morrita0bd20bd2015-02-25 20:11:271302
1303 base::MessageLoop::current()->Run();
rockotcbca72f2015-03-03 16:31:041304 channel()->Close();
morrita0bd20bd2015-02-25 20:11:271305
1306 EXPECT_TRUE(WaitForClientShutdown());
1307 DestroyChannel();
1308}
1309
sammc57ed9f982016-03-10 06:28:351310DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(IPCChannelMojoTestVerifyGlobalPidClient,
1311 ChannelClient) {
morrita0bd20bd2015-02-25 20:11:271312 IPC::Channel::SetGlobalPid(kMagicChildId);
1313 ListenerThatQuits listener;
sammc57ed9f982016-03-10 06:28:351314 Connect(&listener);
morrita0bd20bd2015-02-25 20:11:271315
1316 base::MessageLoop::current()->Run();
1317
sammc57ed9f982016-03-10 06:28:351318 Close();
morrita0bd20bd2015-02-25 20:11:271319}
1320
sammc57ed9f982016-03-10 06:28:351321#endif // OS_LINUX
morrita0bd20bd2015-02-25 20:11:271322
[email protected]64860882014-08-04 23:44:171323} // namespace