blob: 6ebaa73ee10b0b037a590a64f2c0443bd6d58e8b [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
5#include "ipc/mojo/ipc_channel_mojo.h"
6
7#include "base/base_paths.h"
8#include "base/files/file.h"
9#include "base/message_loop/message_loop.h"
10#include "base/path_service.h"
11#include "base/pickle.h"
12#include "base/threading/thread.h"
13#include "ipc/ipc_message.h"
14#include "ipc/ipc_test_base.h"
15#include "ipc/ipc_test_channel_listener.h"
morrita54f6f80c2014-09-23 21:16:0016#include "ipc/mojo/ipc_channel_mojo_host.h"
[email protected]64860882014-08-04 23:44:1717
18#if defined(OS_POSIX)
19#include "base/file_descriptor_posix.h"
morrita1aa788c2015-01-31 05:45:4220#include "ipc/ipc_platform_file_attachment_posix.h"
[email protected]64860882014-08-04 23:44:1721#endif
22
23namespace {
24
25class ListenerThatExpectsOK : public IPC::Listener {
26 public:
[email protected]e5c27752014-08-08 21:45:1327 ListenerThatExpectsOK()
28 : received_ok_(false) {}
[email protected]64860882014-08-04 23:44:1729
dchengfe61fca2014-10-22 02:29:5230 ~ListenerThatExpectsOK() override {}
[email protected]64860882014-08-04 23:44:1731
dchengfe61fca2014-10-22 02:29:5232 bool OnMessageReceived(const IPC::Message& message) override {
[email protected]64860882014-08-04 23:44:1733 PickleIterator iter(message);
34 std::string should_be_ok;
35 EXPECT_TRUE(iter.ReadString(&should_be_ok));
36 EXPECT_EQ(should_be_ok, "OK");
[email protected]e5c27752014-08-08 21:45:1337 received_ok_ = true;
[email protected]64860882014-08-04 23:44:1738 base::MessageLoop::current()->Quit();
39 return true;
40 }
41
dchengfe61fca2014-10-22 02:29:5242 void OnChannelError() override {
[email protected]e5c27752014-08-08 21:45:1343 // The connection should be healthy while the listener is waiting
44 // message. An error can occur after that because the peer
45 // process dies.
46 DCHECK(received_ok_);
[email protected]64860882014-08-04 23:44:1747 }
48
49 static void SendOK(IPC::Sender* sender) {
50 IPC::Message* message = new IPC::Message(
51 0, 2, IPC::Message::PRIORITY_NORMAL);
52 message->WriteString(std::string("OK"));
53 ASSERT_TRUE(sender->Send(message));
54 }
[email protected]e5c27752014-08-08 21:45:1355
56 private:
57 bool received_ok_;
[email protected]64860882014-08-04 23:44:1758};
59
[email protected]64860882014-08-04 23:44:1760class ChannelClient {
61 public:
62 explicit ChannelClient(IPC::Listener* listener, const char* name) {
morrita54f6f80c2014-09-23 21:16:0063 channel_ = IPC::ChannelMojo::Create(NULL,
64 IPCTestBase::GetChannelName(name),
65 IPC::Channel::MODE_CLIENT,
66 listener);
[email protected]64860882014-08-04 23:44:1767 }
68
69 void Connect() {
70 CHECK(channel_->Connect());
71 }
72
73 IPC::ChannelMojo* channel() const { return channel_.get(); }
74
75 private:
[email protected]64860882014-08-04 23:44:1776 base::MessageLoopForIO main_message_loop_;
morrita54f6f80c2014-09-23 21:16:0077 scoped_ptr<IPC::ChannelMojo> channel_;
[email protected]64860882014-08-04 23:44:1778};
79
80class IPCChannelMojoTest : public IPCTestBase {
[email protected]64860882014-08-04 23:44:1781 protected:
dchengfe61fca2014-10-22 02:29:5282 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
morrita373af03b2014-09-09 19:35:2483 const IPC::ChannelHandle& handle,
mostynb50a41f32014-10-07 07:17:1684 base::TaskRunner* runner) override {
morrita54f6f80c2014-09-23 21:16:0085 host_.reset(new IPC::ChannelMojoHost(task_runner()));
morritae9453ea2014-09-26 03:20:4886 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
87 handle);
[email protected]64860882014-08-04 23:44:1788 }
morrita54f6f80c2014-09-23 21:16:0089
dchengfe61fca2014-10-22 02:29:5290 bool DidStartClient() override {
morrita54f6f80c2014-09-23 21:16:0091 bool ok = IPCTestBase::DidStartClient();
92 DCHECK(ok);
rvargas07b589c2015-01-12 22:23:2393 host_->OnClientLaunched(client_process().Handle());
morrita54f6f80c2014-09-23 21:16:0094 return ok;
95 }
96
97 private:
98 scoped_ptr<IPC::ChannelMojoHost> host_;
[email protected]64860882014-08-04 23:44:1799};
100
101
[email protected]64860882014-08-04 23:44:17102class TestChannelListenerWithExtraExpectations
103 : public IPC::TestChannelListener {
104 public:
105 TestChannelListenerWithExtraExpectations()
106 : is_connected_called_(false) {
107 }
108
dchengfe61fca2014-10-22 02:29:52109 void OnChannelConnected(int32 peer_pid) override {
[email protected]64860882014-08-04 23:44:17110 IPC::TestChannelListener::OnChannelConnected(peer_pid);
111 EXPECT_TRUE(base::kNullProcessId != peer_pid);
112 is_connected_called_ = true;
113 }
114
115 bool is_connected_called() const { return is_connected_called_; }
116
117 private:
118 bool is_connected_called_;
119};
120
121TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
122 Init("IPCChannelMojoTestClient");
123
124 // Set up IPC channel and start client.
125 TestChannelListenerWithExtraExpectations listener;
morrita373af03b2014-09-09 19:35:24126 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:17127 listener.Init(sender());
128 ASSERT_TRUE(ConnectChannel());
129 ASSERT_TRUE(StartClient());
130
131 IPC::TestChannelListener::SendOneMessage(
132 sender(), "hello from parent");
133
134 base::MessageLoop::current()->Run();
135 EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());
136
137 this->channel()->Close();
138
139 EXPECT_TRUE(WaitForClientShutdown());
140 EXPECT_TRUE(listener.is_connected_called());
141 EXPECT_TRUE(listener.HasSentAll());
142
143 DestroyChannel();
144}
145
146// A long running process that connects to us
147MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
148 TestChannelListenerWithExtraExpectations listener;
149 ChannelClient client(&listener, "IPCChannelMojoTestClient");
150 client.Connect();
151 listener.Init(client.channel());
152
153 IPC::TestChannelListener::SendOneMessage(
154 client.channel(), "hello from child");
155 base::MessageLoop::current()->Run();
156 EXPECT_TRUE(listener.is_connected_called());
157 EXPECT_TRUE(listener.HasSentAll());
158
159 return 0;
160}
161
morrita0a24cfc92014-09-16 03:20:48162class ListenerExpectingErrors : public IPC::Listener {
163 public:
164 ListenerExpectingErrors()
165 : has_error_(false) {
166 }
167
dchengfe61fca2014-10-22 02:29:52168 void OnChannelConnected(int32 peer_pid) override {
morritabe6c4cc2014-09-24 23:38:44169 base::MessageLoop::current()->Quit();
170 }
171
dchengfe61fca2014-10-22 02:29:52172 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita0a24cfc92014-09-16 03:20:48173
dchengfe61fca2014-10-22 02:29:52174 void OnChannelError() override {
morrita0a24cfc92014-09-16 03:20:48175 has_error_ = true;
176 base::MessageLoop::current()->Quit();
177 }
178
179 bool has_error() const { return has_error_; }
180
181 private:
182 bool has_error_;
183};
184
185
186class IPCChannelMojoErrorTest : public IPCTestBase {
187 protected:
dchengfe61fca2014-10-22 02:29:52188 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
morrita0a24cfc92014-09-16 03:20:48189 const IPC::ChannelHandle& handle,
mostynb50a41f32014-10-07 07:17:16190 base::TaskRunner* runner) override {
morrita54f6f80c2014-09-23 21:16:00191 host_.reset(new IPC::ChannelMojoHost(task_runner()));
morritae9453ea2014-09-26 03:20:48192 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
193 handle);
morrita0a24cfc92014-09-16 03:20:48194 }
morrita54f6f80c2014-09-23 21:16:00195
dchengfe61fca2014-10-22 02:29:52196 bool DidStartClient() override {
morrita54f6f80c2014-09-23 21:16:00197 bool ok = IPCTestBase::DidStartClient();
198 DCHECK(ok);
rvargas07b589c2015-01-12 22:23:23199 host_->OnClientLaunched(client_process().Handle());
morrita54f6f80c2014-09-23 21:16:00200 return ok;
201 }
202
203 private:
204 scoped_ptr<IPC::ChannelMojoHost> host_;
morrita0a24cfc92014-09-16 03:20:48205};
206
207class ListenerThatQuits : public IPC::Listener {
208 public:
209 ListenerThatQuits() {
210 }
211
dchengfe61fca2014-10-22 02:29:52212 bool OnMessageReceived(const IPC::Message& message) override {
dchengf3076af2014-10-21 18:02:42213 return true;
214 }
morrita0a24cfc92014-09-16 03:20:48215
dchengfe61fca2014-10-22 02:29:52216 void OnChannelConnected(int32 peer_pid) override {
morrita0a24cfc92014-09-16 03:20:48217 base::MessageLoop::current()->Quit();
218 }
219};
220
221// A long running process that connects to us.
222MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
223 ListenerThatQuits listener;
224 ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
225 client.Connect();
226
227 base::MessageLoop::current()->Run();
228
229 return 0;
230}
231
morritabe6c4cc2014-09-24 23:38:44232TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
morrita0a24cfc92014-09-16 03:20:48233 Init("IPCChannelMojoErraticTestClient");
234
235 // Set up IPC channel and start client.
236 ListenerExpectingErrors listener;
237 CreateChannel(&listener);
238 ASSERT_TRUE(ConnectChannel());
239
jamesra03ae492014-10-03 04:26:48240 // This matches a value in mojo/edk/system/constants.h
morritabe6c4cc2014-09-24 23:38:44241 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
242 std::string overly_large_data(kMaxMessageNumBytes, '*');
morrita0a24cfc92014-09-16 03:20:48243 // This messages are queued as pending.
morritabe6c4cc2014-09-24 23:38:44244 for (size_t i = 0; i < 10; ++i) {
morrita0a24cfc92014-09-16 03:20:48245 IPC::TestChannelListener::SendOneMessage(
morritabe6c4cc2014-09-24 23:38:44246 sender(), overly_large_data.c_str());
morrita0a24cfc92014-09-16 03:20:48247 }
248
249 ASSERT_TRUE(StartClient());
250 base::MessageLoop::current()->Run();
251
252 this->channel()->Close();
253
254 EXPECT_TRUE(WaitForClientShutdown());
255 EXPECT_TRUE(listener.has_error());
256
257 DestroyChannel();
258}
259
morrita25803672014-10-15 18:50:19260#if defined(OS_WIN)
261class IPCChannelMojoDeadHandleTest : public IPCTestBase {
262 protected:
263 virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
264 const IPC::ChannelHandle& handle,
265 base::TaskRunner* runner) override {
266 host_.reset(new IPC::ChannelMojoHost(task_runner()));
267 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
268 handle);
269 }
270
271 virtual bool DidStartClient() override {
272 IPCTestBase::DidStartClient();
rvargas07b589c2015-01-12 22:23:23273 const base::ProcessHandle client = client_process().Handle();
morrita25803672014-10-15 18:50:19274 // Forces GetFileHandleForProcess() fail. It happens occasionally
275 // in production, so we should exercise it somehow.
rvargas07b589c2015-01-12 22:23:23276 // TODO(morrita): figure out how to safely test this.
277 // ::CloseHandle(client);
morrita25803672014-10-15 18:50:19278 host_->OnClientLaunched(client);
279 return true;
280 }
281
282 private:
283 scoped_ptr<IPC::ChannelMojoHost> host_;
284};
285
286TEST_F(IPCChannelMojoDeadHandleTest, InvalidClientHandle) {
287 // Any client type is fine as it is going to be killed anyway.
288 Init("IPCChannelMojoTestDoNothingClient");
289
290 // Set up IPC channel and start client.
291 ListenerExpectingErrors listener;
292 CreateChannel(&listener);
293 ASSERT_TRUE(ConnectChannel());
294
295 ASSERT_TRUE(StartClient());
296 base::MessageLoop::current()->Run();
297
298 this->channel()->Close();
299
300 // WaitForClientShutdown() fails as client_hanadle() is already
301 // closed.
302 EXPECT_FALSE(WaitForClientShutdown());
303 EXPECT_TRUE(listener.has_error());
304
305 DestroyChannel();
306}
307
308MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient) {
309 ListenerThatQuits listener;
310 ChannelClient client(&listener, "IPCChannelMojoTestDoNothingClient");
311 client.Connect();
312
313 // Quits without running the message loop as this client won't
314 // receive any messages from the server.
315
316 return 0;
317}
318#endif
morrita0a24cfc92014-09-16 03:20:48319
[email protected]64860882014-08-04 23:44:17320#if defined(OS_POSIX)
321class ListenerThatExpectsFile : public IPC::Listener {
322 public:
323 ListenerThatExpectsFile()
324 : sender_(NULL) {}
325
dchengfe61fca2014-10-22 02:29:52326 ~ListenerThatExpectsFile() override {}
[email protected]64860882014-08-04 23:44:17327
dchengfe61fca2014-10-22 02:29:52328 bool OnMessageReceived(const IPC::Message& message) override {
[email protected]64860882014-08-04 23:44:17329 PickleIterator iter(message);
morrita96693852014-09-24 20:11:45330
331 base::ScopedFD fd;
morrita1aa788c2015-01-31 05:45:42332 scoped_refptr<IPC::MessageAttachment> attachment;
333 EXPECT_TRUE(message.ReadAttachment(&iter, &attachment));
334 base::File file(attachment->TakePlatformFile());
[email protected]64860882014-08-04 23:44:17335 std::string content(GetSendingFileContent().size(), ' ');
[email protected]64860882014-08-04 23:44:17336 file.Read(0, &content[0], content.size());
337 EXPECT_EQ(content, GetSendingFileContent());
338 base::MessageLoop::current()->Quit();
339 ListenerThatExpectsOK::SendOK(sender_);
340 return true;
341 }
342
dchengfe61fca2014-10-22 02:29:52343 void OnChannelError() override {
dchengf3076af2014-10-21 18:02:42344 NOTREACHED();
345 }
[email protected]64860882014-08-04 23:44:17346
347 static std::string GetSendingFileContent() {
348 return "Hello";
349 }
350
351 static base::FilePath GetSendingFilePath() {
352 base::FilePath path;
353 bool ok = PathService::Get(base::DIR_CACHE, &path);
354 EXPECT_TRUE(ok);
355 return path.Append("ListenerThatExpectsFile.txt");
356 }
357
358 static void WriteAndSendFile(IPC::Sender* sender, base::File& file) {
359 std::string content = GetSendingFileContent();
360 file.WriteAtCurrentPos(content.data(), content.size());
361 file.Flush();
362 IPC::Message* message = new IPC::Message(
363 0, 2, IPC::Message::PRIORITY_NORMAL);
morrita1aa788c2015-01-31 05:45:42364 message->WriteAttachment(new IPC::internal::PlatformFileAttachment(
365 base::ScopedFD(file.TakePlatformFile())));
[email protected]64860882014-08-04 23:44:17366 ASSERT_TRUE(sender->Send(message));
367 }
368
369 void set_sender(IPC::Sender* sender) { sender_ = sender; }
370
371 private:
372 IPC::Sender* sender_;
373};
374
375
376TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
377 Init("IPCChannelMojoTestSendPlatformHandleClient");
378
379 ListenerThatExpectsOK listener;
morrita373af03b2014-09-09 19:35:24380 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:17381 ASSERT_TRUE(ConnectChannel());
382 ASSERT_TRUE(StartClient());
383
384 base::File file(ListenerThatExpectsFile::GetSendingFilePath(),
385 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
386 base::File::FLAG_READ);
387 ListenerThatExpectsFile::WriteAndSendFile(channel(), file);
388 base::MessageLoop::current()->Run();
389
390 this->channel()->Close();
391
392 EXPECT_TRUE(WaitForClientShutdown());
393 DestroyChannel();
394}
395
396MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
397 ListenerThatExpectsFile listener;
398 ChannelClient client(
399 &listener, "IPCChannelMojoTestSendPlatformHandleClient");
400 client.Connect();
401 listener.set_sender(client.channel());
402
403 base::MessageLoop::current()->Run();
404
405 return 0;
406}
407#endif
408
409} // namespace