blob: 556e65accf59f03ac867f8cd4d11dcc6bc41da12 [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"
morrita81b17e02015-02-06 00:58:3017#include "ipc/mojo/ipc_mojo_handle_attachment.h"
18#include "ipc/mojo/ipc_mojo_message_helper.h"
[email protected]64860882014-08-04 23:44:1719
20#if defined(OS_POSIX)
21#include "base/file_descriptor_posix.h"
morrita1aa788c2015-01-31 05:45:4222#include "ipc/ipc_platform_file_attachment_posix.h"
[email protected]64860882014-08-04 23:44:1723#endif
24
25namespace {
26
27class ListenerThatExpectsOK : public IPC::Listener {
28 public:
[email protected]e5c27752014-08-08 21:45:1329 ListenerThatExpectsOK()
30 : received_ok_(false) {}
[email protected]64860882014-08-04 23:44:1731
dchengfe61fca2014-10-22 02:29:5232 ~ListenerThatExpectsOK() override {}
[email protected]64860882014-08-04 23:44:1733
dchengfe61fca2014-10-22 02:29:5234 bool OnMessageReceived(const IPC::Message& message) override {
[email protected]64860882014-08-04 23:44:1735 PickleIterator iter(message);
36 std::string should_be_ok;
37 EXPECT_TRUE(iter.ReadString(&should_be_ok));
38 EXPECT_EQ(should_be_ok, "OK");
[email protected]e5c27752014-08-08 21:45:1339 received_ok_ = true;
[email protected]64860882014-08-04 23:44:1740 base::MessageLoop::current()->Quit();
41 return true;
42 }
43
dchengfe61fca2014-10-22 02:29:5244 void OnChannelError() override {
[email protected]e5c27752014-08-08 21:45:1345 // The connection should be healthy while the listener is waiting
46 // message. An error can occur after that because the peer
47 // process dies.
48 DCHECK(received_ok_);
[email protected]64860882014-08-04 23:44:1749 }
50
51 static void SendOK(IPC::Sender* sender) {
52 IPC::Message* message = new IPC::Message(
53 0, 2, IPC::Message::PRIORITY_NORMAL);
54 message->WriteString(std::string("OK"));
55 ASSERT_TRUE(sender->Send(message));
56 }
[email protected]e5c27752014-08-08 21:45:1357
58 private:
59 bool received_ok_;
[email protected]64860882014-08-04 23:44:1760};
61
[email protected]64860882014-08-04 23:44:1762class ChannelClient {
63 public:
64 explicit ChannelClient(IPC::Listener* listener, const char* name) {
morrita54f6f80c2014-09-23 21:16:0065 channel_ = IPC::ChannelMojo::Create(NULL,
66 IPCTestBase::GetChannelName(name),
67 IPC::Channel::MODE_CLIENT,
68 listener);
[email protected]64860882014-08-04 23:44:1769 }
70
71 void Connect() {
72 CHECK(channel_->Connect());
73 }
74
75 IPC::ChannelMojo* channel() const { return channel_.get(); }
76
77 private:
[email protected]64860882014-08-04 23:44:1778 base::MessageLoopForIO main_message_loop_;
morrita54f6f80c2014-09-23 21:16:0079 scoped_ptr<IPC::ChannelMojo> channel_;
[email protected]64860882014-08-04 23:44:1780};
81
82class IPCChannelMojoTest : public IPCTestBase {
[email protected]64860882014-08-04 23:44:1783 protected:
dchengfe61fca2014-10-22 02:29:5284 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
morrita373af03b2014-09-09 19:35:2485 const IPC::ChannelHandle& handle,
mostynb50a41f32014-10-07 07:17:1686 base::TaskRunner* runner) override {
morrita54f6f80c2014-09-23 21:16:0087 host_.reset(new IPC::ChannelMojoHost(task_runner()));
morritae9453ea2014-09-26 03:20:4888 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
89 handle);
[email protected]64860882014-08-04 23:44:1790 }
morrita54f6f80c2014-09-23 21:16:0091
dchengfe61fca2014-10-22 02:29:5292 bool DidStartClient() override {
morrita54f6f80c2014-09-23 21:16:0093 bool ok = IPCTestBase::DidStartClient();
94 DCHECK(ok);
rvargas07b589c2015-01-12 22:23:2395 host_->OnClientLaunched(client_process().Handle());
morrita54f6f80c2014-09-23 21:16:0096 return ok;
97 }
98
99 private:
100 scoped_ptr<IPC::ChannelMojoHost> host_;
[email protected]64860882014-08-04 23:44:17101};
102
103
[email protected]64860882014-08-04 23:44:17104class TestChannelListenerWithExtraExpectations
105 : public IPC::TestChannelListener {
106 public:
107 TestChannelListenerWithExtraExpectations()
108 : is_connected_called_(false) {
109 }
110
dchengfe61fca2014-10-22 02:29:52111 void OnChannelConnected(int32 peer_pid) override {
[email protected]64860882014-08-04 23:44:17112 IPC::TestChannelListener::OnChannelConnected(peer_pid);
113 EXPECT_TRUE(base::kNullProcessId != peer_pid);
114 is_connected_called_ = true;
115 }
116
117 bool is_connected_called() const { return is_connected_called_; }
118
119 private:
120 bool is_connected_called_;
121};
122
123TEST_F(IPCChannelMojoTest, ConnectedFromClient) {
124 Init("IPCChannelMojoTestClient");
125
126 // Set up IPC channel and start client.
127 TestChannelListenerWithExtraExpectations listener;
morrita373af03b2014-09-09 19:35:24128 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:17129 listener.Init(sender());
130 ASSERT_TRUE(ConnectChannel());
131 ASSERT_TRUE(StartClient());
132
133 IPC::TestChannelListener::SendOneMessage(
134 sender(), "hello from parent");
135
136 base::MessageLoop::current()->Run();
137 EXPECT_TRUE(base::kNullProcessId != this->channel()->GetPeerPID());
138
139 this->channel()->Close();
140
141 EXPECT_TRUE(WaitForClientShutdown());
142 EXPECT_TRUE(listener.is_connected_called());
143 EXPECT_TRUE(listener.HasSentAll());
144
145 DestroyChannel();
146}
147
148// A long running process that connects to us
149MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestClient) {
150 TestChannelListenerWithExtraExpectations listener;
151 ChannelClient client(&listener, "IPCChannelMojoTestClient");
152 client.Connect();
153 listener.Init(client.channel());
154
155 IPC::TestChannelListener::SendOneMessage(
156 client.channel(), "hello from child");
157 base::MessageLoop::current()->Run();
158 EXPECT_TRUE(listener.is_connected_called());
159 EXPECT_TRUE(listener.HasSentAll());
160
161 return 0;
162}
163
morrita0a24cfc92014-09-16 03:20:48164class ListenerExpectingErrors : public IPC::Listener {
165 public:
166 ListenerExpectingErrors()
167 : has_error_(false) {
168 }
169
dchengfe61fca2014-10-22 02:29:52170 void OnChannelConnected(int32 peer_pid) override {
morritabe6c4cc2014-09-24 23:38:44171 base::MessageLoop::current()->Quit();
172 }
173
dchengfe61fca2014-10-22 02:29:52174 bool OnMessageReceived(const IPC::Message& message) override { return true; }
morrita0a24cfc92014-09-16 03:20:48175
dchengfe61fca2014-10-22 02:29:52176 void OnChannelError() override {
morrita0a24cfc92014-09-16 03:20:48177 has_error_ = true;
178 base::MessageLoop::current()->Quit();
179 }
180
181 bool has_error() const { return has_error_; }
182
183 private:
184 bool has_error_;
185};
186
187
188class IPCChannelMojoErrorTest : public IPCTestBase {
189 protected:
dchengfe61fca2014-10-22 02:29:52190 scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
morrita0a24cfc92014-09-16 03:20:48191 const IPC::ChannelHandle& handle,
mostynb50a41f32014-10-07 07:17:16192 base::TaskRunner* runner) override {
morrita54f6f80c2014-09-23 21:16:00193 host_.reset(new IPC::ChannelMojoHost(task_runner()));
morritae9453ea2014-09-26 03:20:48194 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
195 handle);
morrita0a24cfc92014-09-16 03:20:48196 }
morrita54f6f80c2014-09-23 21:16:00197
dchengfe61fca2014-10-22 02:29:52198 bool DidStartClient() override {
morrita54f6f80c2014-09-23 21:16:00199 bool ok = IPCTestBase::DidStartClient();
200 DCHECK(ok);
rvargas07b589c2015-01-12 22:23:23201 host_->OnClientLaunched(client_process().Handle());
morrita54f6f80c2014-09-23 21:16:00202 return ok;
203 }
204
205 private:
206 scoped_ptr<IPC::ChannelMojoHost> host_;
morrita0a24cfc92014-09-16 03:20:48207};
208
209class ListenerThatQuits : public IPC::Listener {
210 public:
211 ListenerThatQuits() {
212 }
213
dchengfe61fca2014-10-22 02:29:52214 bool OnMessageReceived(const IPC::Message& message) override {
dchengf3076af2014-10-21 18:02:42215 return true;
216 }
morrita0a24cfc92014-09-16 03:20:48217
dchengfe61fca2014-10-22 02:29:52218 void OnChannelConnected(int32 peer_pid) override {
morrita0a24cfc92014-09-16 03:20:48219 base::MessageLoop::current()->Quit();
220 }
221};
222
223// A long running process that connects to us.
224MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoErraticTestClient) {
225 ListenerThatQuits listener;
226 ChannelClient client(&listener, "IPCChannelMojoErraticTestClient");
227 client.Connect();
228
229 base::MessageLoop::current()->Run();
230
231 return 0;
232}
233
morritabe6c4cc2014-09-24 23:38:44234TEST_F(IPCChannelMojoErrorTest, SendFailWithPendingMessages) {
morrita0a24cfc92014-09-16 03:20:48235 Init("IPCChannelMojoErraticTestClient");
236
237 // Set up IPC channel and start client.
238 ListenerExpectingErrors listener;
239 CreateChannel(&listener);
240 ASSERT_TRUE(ConnectChannel());
241
jamesra03ae492014-10-03 04:26:48242 // This matches a value in mojo/edk/system/constants.h
morritabe6c4cc2014-09-24 23:38:44243 const int kMaxMessageNumBytes = 4 * 1024 * 1024;
244 std::string overly_large_data(kMaxMessageNumBytes, '*');
morrita0a24cfc92014-09-16 03:20:48245 // This messages are queued as pending.
morritabe6c4cc2014-09-24 23:38:44246 for (size_t i = 0; i < 10; ++i) {
morrita0a24cfc92014-09-16 03:20:48247 IPC::TestChannelListener::SendOneMessage(
morritabe6c4cc2014-09-24 23:38:44248 sender(), overly_large_data.c_str());
morrita0a24cfc92014-09-16 03:20:48249 }
250
251 ASSERT_TRUE(StartClient());
252 base::MessageLoop::current()->Run();
253
254 this->channel()->Close();
255
256 EXPECT_TRUE(WaitForClientShutdown());
257 EXPECT_TRUE(listener.has_error());
258
259 DestroyChannel();
260}
261
morrita81b17e02015-02-06 00:58:30262struct TestingMessagePipe {
263 TestingMessagePipe() {
264 EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateMessagePipe(nullptr, &self, &peer));
265 }
266
267 mojo::ScopedMessagePipeHandle self;
268 mojo::ScopedMessagePipeHandle peer;
269};
270
271class HandleSendingHelper {
272 public:
273 static std::string GetSendingFileContent() { return "Hello"; }
274
275 static void WritePipe(IPC::Message* message, TestingMessagePipe* pipe) {
276 std::string content = HandleSendingHelper::GetSendingFileContent();
277 EXPECT_EQ(MOJO_RESULT_OK,
278 mojo::WriteMessageRaw(pipe->self.get(), &content[0],
279 static_cast<uint32_t>(content.size()),
280 nullptr, 0, 0));
281 EXPECT_TRUE(
282 IPC::MojoMessageHelper::WriteMessagePipeTo(message, pipe->peer.Pass()));
283 }
284
285 static void WritePipeThenSend(IPC::Sender* sender, TestingMessagePipe* pipe) {
286 IPC::Message* message =
287 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
288 WritePipe(message, pipe);
289 ASSERT_TRUE(sender->Send(message));
290 }
291
292 static void ReadReceivedPipe(const IPC::Message& message,
293 PickleIterator* iter) {
294 mojo::ScopedMessagePipeHandle pipe;
295 EXPECT_TRUE(
296 IPC::MojoMessageHelper::ReadMessagePipeFrom(&message, iter, &pipe));
297 std::string content(GetSendingFileContent().size(), ' ');
298
299 uint32_t num_bytes = static_cast<uint32_t>(content.size());
300 EXPECT_EQ(MOJO_RESULT_OK,
301 mojo::ReadMessageRaw(pipe.get(), &content[0], &num_bytes, nullptr,
302 nullptr, 0));
303 EXPECT_EQ(content, GetSendingFileContent());
304 }
305
306#if defined(OS_POSIX)
307 static base::FilePath GetSendingFilePath() {
308 base::FilePath path;
309 bool ok = PathService::Get(base::DIR_CACHE, &path);
310 EXPECT_TRUE(ok);
311 return path.Append("ListenerThatExpectsFile.txt");
312 }
313
314 static void WriteFile(IPC::Message* message, base::File& file) {
315 std::string content = GetSendingFileContent();
316 file.WriteAtCurrentPos(content.data(), content.size());
317 file.Flush();
318 message->WriteAttachment(new IPC::internal::PlatformFileAttachment(
319 base::ScopedFD(file.TakePlatformFile())));
320 }
321
322 static void WriteFileThenSend(IPC::Sender* sender, base::File& file) {
323 IPC::Message* message =
324 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
325 WriteFile(message, file);
326 ASSERT_TRUE(sender->Send(message));
327 }
328
329 static void WriteFileAndPipeThenSend(IPC::Sender* sender,
330 base::File& file,
331 TestingMessagePipe* pipe) {
332 IPC::Message* message =
333 new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL);
334 WriteFile(message, file);
335 WritePipe(message, pipe);
336 ASSERT_TRUE(sender->Send(message));
337 }
338
339 static void ReadReceivedFile(const IPC::Message& message,
340 PickleIterator* iter) {
341 base::ScopedFD fd;
342 scoped_refptr<IPC::MessageAttachment> attachment;
343 EXPECT_TRUE(message.ReadAttachment(iter, &attachment));
344 base::File file(attachment->TakePlatformFile());
345 std::string content(GetSendingFileContent().size(), ' ');
346 file.Read(0, &content[0], content.size());
347 EXPECT_EQ(content, GetSendingFileContent());
348 }
349#endif
350};
351
352class ListenerThatExpectsMessagePipe : public IPC::Listener {
353 public:
354 ListenerThatExpectsMessagePipe() : sender_(NULL) {}
355
356 ~ListenerThatExpectsMessagePipe() override {}
357
358 bool OnMessageReceived(const IPC::Message& message) override {
359 PickleIterator iter(message);
360 HandleSendingHelper::ReadReceivedPipe(message, &iter);
361 base::MessageLoop::current()->Quit();
362 ListenerThatExpectsOK::SendOK(sender_);
363 return true;
364 }
365
366 void OnChannelError() override { NOTREACHED(); }
367
368 void set_sender(IPC::Sender* sender) { sender_ = sender; }
369
370 private:
371 IPC::Sender* sender_;
372};
373
374TEST_F(IPCChannelMojoTest, SendMessagePipe) {
375 Init("IPCChannelMojoTestSendMessagePipeClient");
376
377 ListenerThatExpectsOK listener;
378 CreateChannel(&listener);
379 ASSERT_TRUE(ConnectChannel());
380 ASSERT_TRUE(StartClient());
381
382 TestingMessagePipe pipe;
383 HandleSendingHelper::WritePipeThenSend(channel(), &pipe);
384
385 base::MessageLoop::current()->Run();
386 this->channel()->Close();
387
388 EXPECT_TRUE(WaitForClientShutdown());
389 DestroyChannel();
390}
391
392MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendMessagePipeClient) {
393 ListenerThatExpectsMessagePipe listener;
394 ChannelClient client(&listener, "IPCChannelMojoTestSendPlatformHandleClient");
395 client.Connect();
396 listener.set_sender(client.channel());
397
398 base::MessageLoop::current()->Run();
399
400 return 0;
401}
402
morrita25803672014-10-15 18:50:19403#if defined(OS_WIN)
404class IPCChannelMojoDeadHandleTest : public IPCTestBase {
405 protected:
406 virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory(
407 const IPC::ChannelHandle& handle,
408 base::TaskRunner* runner) override {
409 host_.reset(new IPC::ChannelMojoHost(task_runner()));
410 return IPC::ChannelMojo::CreateServerFactory(host_->channel_delegate(),
411 handle);
412 }
413
414 virtual bool DidStartClient() override {
415 IPCTestBase::DidStartClient();
rvargas07b589c2015-01-12 22:23:23416 const base::ProcessHandle client = client_process().Handle();
morrita25803672014-10-15 18:50:19417 // Forces GetFileHandleForProcess() fail. It happens occasionally
418 // in production, so we should exercise it somehow.
rvargas07b589c2015-01-12 22:23:23419 // TODO(morrita): figure out how to safely test this.
420 // ::CloseHandle(client);
morrita25803672014-10-15 18:50:19421 host_->OnClientLaunched(client);
422 return true;
423 }
424
425 private:
426 scoped_ptr<IPC::ChannelMojoHost> host_;
427};
428
429TEST_F(IPCChannelMojoDeadHandleTest, InvalidClientHandle) {
430 // Any client type is fine as it is going to be killed anyway.
431 Init("IPCChannelMojoTestDoNothingClient");
432
433 // Set up IPC channel and start client.
434 ListenerExpectingErrors listener;
435 CreateChannel(&listener);
436 ASSERT_TRUE(ConnectChannel());
437
438 ASSERT_TRUE(StartClient());
439 base::MessageLoop::current()->Run();
440
441 this->channel()->Close();
442
443 // WaitForClientShutdown() fails as client_hanadle() is already
444 // closed.
445 EXPECT_FALSE(WaitForClientShutdown());
446 EXPECT_TRUE(listener.has_error());
447
448 DestroyChannel();
449}
450
451MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestDoNothingClient) {
452 ListenerThatQuits listener;
453 ChannelClient client(&listener, "IPCChannelMojoTestDoNothingClient");
454 client.Connect();
455
456 // Quits without running the message loop as this client won't
457 // receive any messages from the server.
458
459 return 0;
460}
461#endif
morrita0a24cfc92014-09-16 03:20:48462
[email protected]64860882014-08-04 23:44:17463#if defined(OS_POSIX)
464class ListenerThatExpectsFile : public IPC::Listener {
465 public:
466 ListenerThatExpectsFile()
467 : sender_(NULL) {}
468
dchengfe61fca2014-10-22 02:29:52469 ~ListenerThatExpectsFile() override {}
[email protected]64860882014-08-04 23:44:17470
dchengfe61fca2014-10-22 02:29:52471 bool OnMessageReceived(const IPC::Message& message) override {
[email protected]64860882014-08-04 23:44:17472 PickleIterator iter(message);
morrita81b17e02015-02-06 00:58:30473 HandleSendingHelper::ReadReceivedFile(message, &iter);
[email protected]64860882014-08-04 23:44:17474 base::MessageLoop::current()->Quit();
475 ListenerThatExpectsOK::SendOK(sender_);
476 return true;
477 }
478
dchengfe61fca2014-10-22 02:29:52479 void OnChannelError() override {
dchengf3076af2014-10-21 18:02:42480 NOTREACHED();
481 }
[email protected]64860882014-08-04 23:44:17482
[email protected]64860882014-08-04 23:44:17483 void set_sender(IPC::Sender* sender) { sender_ = sender; }
484
485 private:
486 IPC::Sender* sender_;
487};
488
489
490TEST_F(IPCChannelMojoTest, SendPlatformHandle) {
491 Init("IPCChannelMojoTestSendPlatformHandleClient");
492
493 ListenerThatExpectsOK listener;
morrita373af03b2014-09-09 19:35:24494 CreateChannel(&listener);
[email protected]64860882014-08-04 23:44:17495 ASSERT_TRUE(ConnectChannel());
496 ASSERT_TRUE(StartClient());
497
morrita81b17e02015-02-06 00:58:30498 base::File file(HandleSendingHelper::GetSendingFilePath(),
[email protected]64860882014-08-04 23:44:17499 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
morrita81b17e02015-02-06 00:58:30500 base::File::FLAG_READ);
501 HandleSendingHelper::WriteFileThenSend(channel(), file);
[email protected]64860882014-08-04 23:44:17502 base::MessageLoop::current()->Run();
503
504 this->channel()->Close();
505
506 EXPECT_TRUE(WaitForClientShutdown());
507 DestroyChannel();
508}
509
510MULTIPROCESS_IPC_TEST_CLIENT_MAIN(IPCChannelMojoTestSendPlatformHandleClient) {
511 ListenerThatExpectsFile listener;
512 ChannelClient client(
513 &listener, "IPCChannelMojoTestSendPlatformHandleClient");
514 client.Connect();
515 listener.set_sender(client.channel());
516
517 base::MessageLoop::current()->Run();
518
519 return 0;
520}
morrita81b17e02015-02-06 00:58:30521
522class ListenerThatExpectsFileAndPipe : public IPC::Listener {
523 public:
524 ListenerThatExpectsFileAndPipe() : sender_(NULL) {}
525
526 ~ListenerThatExpectsFileAndPipe() override {}
527
528 bool OnMessageReceived(const IPC::Message& message) override {
529 PickleIterator iter(message);
530 HandleSendingHelper::ReadReceivedFile(message, &iter);
531 HandleSendingHelper::ReadReceivedPipe(message, &iter);
532 base::MessageLoop::current()->Quit();
533 ListenerThatExpectsOK::SendOK(sender_);
534 return true;
535 }
536
537 void OnChannelError() override { NOTREACHED(); }
538
539 void set_sender(IPC::Sender* sender) { sender_ = sender; }
540
541 private:
542 IPC::Sender* sender_;
543};
544
545TEST_F(IPCChannelMojoTest, SendPlatformHandleAndPipe) {
546 Init("IPCChannelMojoTestSendPlatformHandleAndPipeClient");
547
548 ListenerThatExpectsOK listener;
549 CreateChannel(&listener);
550 ASSERT_TRUE(ConnectChannel());
551 ASSERT_TRUE(StartClient());
552
553 base::File file(HandleSendingHelper::GetSendingFilePath(),
554 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
555 base::File::FLAG_READ);
556 TestingMessagePipe pipe;
557 HandleSendingHelper::WriteFileAndPipeThenSend(channel(), file, &pipe);
558
559 base::MessageLoop::current()->Run();
560 this->channel()->Close();
561
562 EXPECT_TRUE(WaitForClientShutdown());
563 DestroyChannel();
564}
565
566MULTIPROCESS_IPC_TEST_CLIENT_MAIN(
567 IPCChannelMojoTestSendPlatformHandleAndPipeClient) {
568 ListenerThatExpectsFileAndPipe listener;
569 ChannelClient client(&listener,
570 "IPCChannelMojoTestSendPlatformHandleAndPipeClient");
571 client.Connect();
572 listener.set_sender(client.channel());
573
574 base::MessageLoop::current()->Run();
575
576 return 0;
577}
578
[email protected]64860882014-08-04 23:44:17579#endif
580
581} // namespace