• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 <stddef.h>
6 #include <stdint.h>
7 #include <stdio.h>
8 #include <string.h>
9 
10 #include <string>
11 #include <utility>
12 #include <vector>
13 
14 #include "base/bind.h"
15 #include "base/containers/hash_tables.h"
16 #include "base/files/file_path.h"
17 #include "base/files/file_util.h"
18 #include "base/files/scoped_file.h"
19 #include "base/files/scoped_temp_dir.h"
20 #include "base/logging.h"
21 #include "base/message_loop/message_loop.h"
22 #include "base/run_loop.h"
23 #include "base/strings/string_split.h"
24 #include "build/build_config.h"
25 #include "mojo/core/handle_signals_state.h"
26 #include "mojo/core/test/mojo_test_base.h"
27 #include "mojo/core/test/test_utils.h"
28 #include "mojo/core/test_utils.h"
29 #include "mojo/public/c/system/buffer.h"
30 #include "mojo/public/c/system/functions.h"
31 #include "mojo/public/c/system/types.h"
32 #include "mojo/public/cpp/system/message_pipe.h"
33 #include "mojo/public/cpp/system/platform_handle.h"
34 #include "mojo/public/cpp/system/simple_watcher.h"
35 #include "mojo/public/cpp/system/wait.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37 
38 namespace mojo {
39 namespace core {
40 namespace {
41 
42 // Temporary helpers to avoid tons of churn as old APIs are removed. These
43 // support only enough of a subset of the old APIs to satisfy the usage in these
44 // tests.
45 //
46 // TODO(rockot): Remove these.
MojoReadMessage(MojoHandle pipe,void * out_bytes,uint32_t * num_bytes,MojoHandle * out_handles,uint32_t * num_handles,MojoReadMessageFlags flags)47 MojoResult MojoReadMessage(MojoHandle pipe,
48                            void* out_bytes,
49                            uint32_t* num_bytes,
50                            MojoHandle* out_handles,
51                            uint32_t* num_handles,
52                            MojoReadMessageFlags flags) {
53   std::vector<uint8_t> bytes;
54   std::vector<ScopedHandle> handles;
55   MojoResult rv =
56       ReadMessageRaw(MessagePipeHandle(pipe), &bytes, &handles, flags);
57   if (rv != MOJO_RESULT_OK)
58     return rv;
59 
60   if (num_bytes)
61     *num_bytes = static_cast<uint32_t>(bytes.size());
62   if (!bytes.empty()) {
63     CHECK(out_bytes && num_bytes && *num_bytes >= bytes.size());
64     memcpy(out_bytes, bytes.data(), bytes.size());
65   }
66 
67   if (num_handles)
68     *num_handles = static_cast<uint32_t>(handles.size());
69   if (!handles.empty()) {
70     CHECK(out_handles && num_handles && *num_handles >= handles.size());
71     for (size_t i = 0; i < handles.size(); ++i)
72       out_handles[i] = handles[i].release().value();
73   }
74   return MOJO_RESULT_OK;
75 }
76 
MojoWriteMessage(MojoHandle pipe,const void * bytes,uint32_t num_bytes,const MojoHandle * handles,uint32_t num_handles,MojoWriteMessageFlags flags)77 MojoResult MojoWriteMessage(MojoHandle pipe,
78                             const void* bytes,
79                             uint32_t num_bytes,
80                             const MojoHandle* handles,
81                             uint32_t num_handles,
82                             MojoWriteMessageFlags flags) {
83   return WriteMessageRaw(MessagePipeHandle(pipe), bytes, num_bytes, handles,
84                          num_handles, flags);
85 }
86 
87 class MultiprocessMessagePipeTest : public test::MojoTestBase {
88  protected:
89   // Convenience class for tests which will control command-driven children.
90   // See the CommandDrivenClient definition below.
91   class CommandDrivenClientController {
92    public:
CommandDrivenClientController(MojoHandle h)93     explicit CommandDrivenClientController(MojoHandle h) : h_(h) {}
94 
Send(const std::string & command)95     void Send(const std::string& command) {
96       WriteMessage(h_, command);
97       EXPECT_EQ("ok", ReadMessage(h_));
98     }
99 
SendHandle(const std::string & name,MojoHandle p)100     void SendHandle(const std::string& name, MojoHandle p) {
101       WriteMessageWithHandles(h_, "take:" + name, &p, 1);
102       EXPECT_EQ("ok", ReadMessage(h_));
103     }
104 
RetrieveHandle(const std::string & name)105     MojoHandle RetrieveHandle(const std::string& name) {
106       WriteMessage(h_, "return:" + name);
107       MojoHandle p;
108       EXPECT_EQ("ok", ReadMessageWithHandles(h_, &p, 1));
109       return p;
110     }
111 
Exit()112     void Exit() { WriteMessage(h_, "exit"); }
113 
114    private:
115     MojoHandle h_;
116   };
117 };
118 
119 class MultiprocessMessagePipeTestWithPeerSupport
120     : public MultiprocessMessagePipeTest,
121       public testing::WithParamInterface<test::MojoTestBase::LaunchType> {
122  protected:
SetUp()123   void SetUp() override {
124     test::MojoTestBase::SetUp();
125     set_launch_type(GetParam());
126   }
127 };
128 
129 // For each message received, sends a reply message with the same contents
130 // repeated twice, until the other end is closed or it receives "quitquitquit"
131 // (which it doesn't reply to). It'll return the number of messages received,
132 // not including any "quitquitquit" message, modulo 100.
DEFINE_TEST_CLIENT_WITH_PIPE(EchoEcho,MultiprocessMessagePipeTest,h)133 DEFINE_TEST_CLIENT_WITH_PIPE(EchoEcho, MultiprocessMessagePipeTest, h) {
134   const std::string quitquitquit("quitquitquit");
135   int rv = 0;
136   for (;; rv = (rv + 1) % 100) {
137     // Wait for our end of the message pipe to be readable.
138     HandleSignalsState hss;
139     MojoResult result = WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss);
140     if (result != MOJO_RESULT_OK) {
141       // It was closed, probably.
142       CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION);
143       CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
144       CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
145       break;
146     } else {
147       CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
148       CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
149     }
150 
151     std::string read_buffer(1000, '\0');
152     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
153     CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &read_buffer_size, nullptr, 0,
154                              MOJO_READ_MESSAGE_FLAG_NONE),
155              MOJO_RESULT_OK);
156     read_buffer.resize(read_buffer_size);
157     VLOG(2) << "Child got: " << read_buffer;
158 
159     if (read_buffer == quitquitquit) {
160       VLOG(2) << "Child quitting.";
161       break;
162     }
163 
164     std::string write_buffer = read_buffer + read_buffer;
165     CHECK_EQ(MojoWriteMessage(h, write_buffer.data(),
166                               static_cast<uint32_t>(write_buffer.size()),
167                               nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE),
168              MOJO_RESULT_OK);
169   }
170 
171   return rv;
172 }
173 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,Basic)174 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, Basic) {
175   int exit_code = RunTestClientAndGetExitCode("EchoEcho", [&](MojoHandle h) {
176     std::string hello("hello");
177     ASSERT_EQ(
178         MOJO_RESULT_OK,
179         MojoWriteMessage(h, hello.data(), static_cast<uint32_t>(hello.size()),
180                          nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE));
181 
182     HandleSignalsState hss;
183     ASSERT_EQ(MOJO_RESULT_OK,
184               WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss));
185     // The child may or may not have closed its end of the message pipe and died
186     // (and we may or may not know it yet), so our end may or may not appear as
187     // writable.
188     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
189     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
190 
191     std::string read_buffer(1000, '\0');
192     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
193     CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &read_buffer_size, nullptr, 0,
194                              MOJO_READ_MESSAGE_FLAG_NONE),
195              MOJO_RESULT_OK);
196     read_buffer.resize(read_buffer_size);
197     VLOG(2) << "Parent got: " << read_buffer;
198     ASSERT_EQ(hello + hello, read_buffer);
199 
200     std::string quitquitquit("quitquitquit");
201     CHECK_EQ(MojoWriteMessage(h, quitquitquit.data(),
202                               static_cast<uint32_t>(quitquitquit.size()),
203                               nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE),
204              MOJO_RESULT_OK);
205   });
206   EXPECT_EQ(1, exit_code);
207 }
208 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,QueueMessages)209 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, QueueMessages) {
210   static const size_t kNumMessages = 1001;
211   int exit_code = RunTestClientAndGetExitCode("EchoEcho", [&](MojoHandle h) {
212     for (size_t i = 0; i < kNumMessages; i++) {
213       std::string write_buffer(i, 'A' + (i % 26));
214       ASSERT_EQ(MOJO_RESULT_OK,
215                 MojoWriteMessage(h, write_buffer.data(),
216                                  static_cast<uint32_t>(write_buffer.size()),
217                                  nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE));
218     }
219 
220     for (size_t i = 0; i < kNumMessages; i++) {
221       HandleSignalsState hss;
222       ASSERT_EQ(MOJO_RESULT_OK,
223                 WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss));
224       // The child may or may not have closed its end of the message pipe and
225       // died (and we may or may not know it yet), so our end may or may not
226       // appear as writable.
227       ASSERT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
228       ASSERT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
229 
230       std::string read_buffer(kNumMessages * 2, '\0');
231       uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
232       ASSERT_EQ(MojoReadMessage(h, &read_buffer[0], &read_buffer_size, nullptr,
233                                 0, MOJO_READ_MESSAGE_FLAG_NONE),
234                 MOJO_RESULT_OK);
235       read_buffer.resize(read_buffer_size);
236 
237       ASSERT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer);
238     }
239 
240     const std::string quitquitquit("quitquitquit");
241     ASSERT_EQ(MOJO_RESULT_OK,
242               MojoWriteMessage(h, quitquitquit.data(),
243                                static_cast<uint32_t>(quitquitquit.size()),
244                                nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE));
245 
246     // Wait for it to become readable, which should fail (since we sent
247     // "quitquitquit").
248     HandleSignalsState hss;
249     ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
250               WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss));
251     ASSERT_FALSE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
252     ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
253   });
254   EXPECT_EQ(static_cast<int>(kNumMessages % 100), exit_code);
255 }
256 
DEFINE_TEST_CLIENT_WITH_PIPE(CheckSharedBuffer,MultiprocessMessagePipeTest,h)257 DEFINE_TEST_CLIENT_WITH_PIPE(CheckSharedBuffer,
258                              MultiprocessMessagePipeTest,
259                              h) {
260   // Wait for the first message from our parent.
261   HandleSignalsState hss;
262   CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss),
263            MOJO_RESULT_OK);
264   // In this test, the parent definitely doesn't close its end of the message
265   // pipe before we do.
266   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
267   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
268 
269   // It should have a shared buffer.
270   std::string read_buffer(100, '\0');
271   uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
272   MojoHandle handles[10];
273   uint32_t num_handlers = arraysize(handles);  // Maximum number to receive
274   CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &num_bytes, &handles[0],
275                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE),
276            MOJO_RESULT_OK);
277   read_buffer.resize(num_bytes);
278   CHECK_EQ(read_buffer, std::string("go 1"));
279   CHECK_EQ(num_handlers, 1u);
280 
281   // Make a mapping.
282   void* buffer;
283   CHECK_EQ(MojoMapBuffer(handles[0], 0, 100, nullptr, &buffer), MOJO_RESULT_OK);
284 
285   // Write some stuff to the shared buffer.
286   static const char kHello[] = "hello";
287   memcpy(buffer, kHello, sizeof(kHello));
288 
289   // We should be able to close the dispatcher now.
290   MojoClose(handles[0]);
291 
292   // And send a message to signal that we've written stuff.
293   const std::string go2("go 2");
294   CHECK_EQ(MojoWriteMessage(h, go2.data(), static_cast<uint32_t>(go2.size()),
295                             nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE),
296            MOJO_RESULT_OK);
297 
298   // Now wait for our parent to send us a message.
299   hss = HandleSignalsState();
300   CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss),
301            MOJO_RESULT_OK);
302   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
303   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
304 
305   read_buffer = std::string(100, '\0');
306   num_bytes = static_cast<uint32_t>(read_buffer.size());
307   CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &num_bytes, nullptr, 0,
308                            MOJO_READ_MESSAGE_FLAG_NONE),
309            MOJO_RESULT_OK);
310   read_buffer.resize(num_bytes);
311   CHECK_EQ(read_buffer, std::string("go 3"));
312 
313   // It should have written something to the shared buffer.
314   static const char kWorld[] = "world!!!";
315   CHECK_EQ(memcmp(buffer, kWorld, sizeof(kWorld)), 0);
316 
317   // And we're done.
318 
319   return 0;
320 }
321 
TEST_F(MultiprocessMessagePipeTest,SharedBufferPassing)322 TEST_F(MultiprocessMessagePipeTest, SharedBufferPassing) {
323   RunTestClient("CheckSharedBuffer", [&](MojoHandle h) {
324     // Make a shared buffer.
325     MojoCreateSharedBufferOptions options;
326     options.struct_size = sizeof(options);
327     options.flags = MOJO_CREATE_SHARED_BUFFER_FLAG_NONE;
328 
329     MojoHandle shared_buffer;
330     ASSERT_EQ(MOJO_RESULT_OK,
331               MojoCreateSharedBuffer(100, &options, &shared_buffer));
332     MojoSharedBufferInfo buffer_info;
333     buffer_info.struct_size = sizeof(buffer_info);
334     ASSERT_EQ(MOJO_RESULT_OK,
335               MojoGetBufferInfo(shared_buffer, nullptr, &buffer_info));
336     EXPECT_GE(buffer_info.size, 100U);
337 
338     // Send the shared buffer.
339     const std::string go1("go 1");
340 
341     MojoHandle duplicated_shared_buffer;
342     ASSERT_EQ(MOJO_RESULT_OK,
343               MojoDuplicateBufferHandle(shared_buffer, nullptr,
344                                         &duplicated_shared_buffer));
345     buffer_info.size = 0;
346     ASSERT_EQ(MOJO_RESULT_OK,
347               MojoGetBufferInfo(shared_buffer, nullptr, &buffer_info));
348     EXPECT_GE(buffer_info.size, 100U);
349     MojoHandle handles[1];
350     handles[0] = duplicated_shared_buffer;
351     ASSERT_EQ(MOJO_RESULT_OK,
352               MojoWriteMessage(h, &go1[0], static_cast<uint32_t>(go1.size()),
353                                &handles[0], arraysize(handles),
354                                MOJO_WRITE_MESSAGE_FLAG_NONE));
355 
356     // Wait for a message from the child.
357     HandleSignalsState hss;
358     ASSERT_EQ(MOJO_RESULT_OK,
359               WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss));
360     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
361     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
362 
363     std::string read_buffer(100, '\0');
364     uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
365     ASSERT_EQ(MOJO_RESULT_OK,
366               MojoReadMessage(h, &read_buffer[0], &num_bytes, nullptr, 0,
367                               MOJO_READ_MESSAGE_FLAG_NONE));
368     read_buffer.resize(num_bytes);
369     ASSERT_EQ(std::string("go 2"), read_buffer);
370 
371     // After we get it, the child should have written something to the shared
372     // buffer.
373     static const char kHello[] = "hello";
374     void* buffer;
375     CHECK_EQ(MojoMapBuffer(shared_buffer, 0, 100, nullptr, &buffer),
376              MOJO_RESULT_OK);
377     ASSERT_EQ(0, memcmp(buffer, kHello, sizeof(kHello)));
378 
379     // Now we'll write some stuff to the shared buffer.
380     static const char kWorld[] = "world!!!";
381     memcpy(buffer, kWorld, sizeof(kWorld));
382 
383     // And send a message to signal that we've written stuff.
384     const std::string go3("go 3");
385     ASSERT_EQ(MOJO_RESULT_OK,
386               MojoWriteMessage(h, &go3[0], static_cast<uint32_t>(go3.size()),
387                                nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE));
388 
389     // Wait for |h| to become readable, which should fail.
390     hss = HandleSignalsState();
391     ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
392               WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss));
393     ASSERT_FALSE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
394     ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
395   });
396 }
397 
DEFINE_TEST_CLIENT_WITH_PIPE(CheckPlatformHandleFile,MultiprocessMessagePipeTest,h)398 DEFINE_TEST_CLIENT_WITH_PIPE(CheckPlatformHandleFile,
399                              MultiprocessMessagePipeTest,
400                              h) {
401   HandleSignalsState hss;
402   CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss),
403            MOJO_RESULT_OK);
404   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
405   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
406 
407   std::string read_buffer(100, '\0');
408   uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
409   MojoHandle handles[255];  // Maximum number to receive.
410   uint32_t num_handlers = arraysize(handles);
411 
412   CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &num_bytes, &handles[0],
413                            &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE),
414            MOJO_RESULT_OK);
415 
416   read_buffer.resize(num_bytes);
417   char hello[32];
418   int num_handles = 0;
419   sscanf(read_buffer.c_str(), "%s %d", hello, &num_handles);
420   CHECK_EQ(std::string("hello"), std::string(hello));
421   CHECK_GT(num_handles, 0);
422 
423   for (int i = 0; i < num_handles; ++i) {
424     PlatformHandle h = UnwrapPlatformHandle(ScopedHandle(Handle(handles[i])));
425     CHECK(h.is_valid());
426 
427     base::ScopedFILE fp = test::FILEFromPlatformHandle(std::move(h), "r");
428     CHECK(fp);
429     std::string fread_buffer(100, '\0');
430     size_t bytes_read =
431         fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get());
432     fread_buffer.resize(bytes_read);
433     CHECK_EQ(fread_buffer, "world");
434   }
435 
436   return 0;
437 }
438 
439 class MultiprocessMessagePipeTestWithPipeCount
440     : public MultiprocessMessagePipeTest,
441       public testing::WithParamInterface<size_t> {};
442 
TEST_P(MultiprocessMessagePipeTestWithPipeCount,PlatformHandlePassing)443 TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) {
444   base::ScopedTempDir temp_dir;
445   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
446 
447   RunTestClient("CheckPlatformHandleFile", [&](MojoHandle h) {
448     std::vector<MojoHandle> handles;
449 
450     size_t pipe_count = GetParam();
451     for (size_t i = 0; i < pipe_count; ++i) {
452       base::FilePath unused;
453       base::ScopedFILE fp(
454           CreateAndOpenTemporaryFileInDir(temp_dir.GetPath(), &unused));
455       const std::string world("world");
456       CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size());
457       fflush(fp.get());
458       rewind(fp.get());
459       ScopedHandle handle =
460           WrapPlatformHandle(test::PlatformHandleFromFILE(std::move(fp)));
461       ASSERT_TRUE(handle.is_valid());
462       handles.push_back(handle.release().value());
463     }
464 
465     char message[128];
466     snprintf(message, sizeof(message), "hello %d",
467              static_cast<int>(pipe_count));
468     ASSERT_EQ(
469         MOJO_RESULT_OK,
470         MojoWriteMessage(h, message, static_cast<uint32_t>(strlen(message)),
471                          &handles[0], static_cast<uint32_t>(handles.size()),
472                          MOJO_WRITE_MESSAGE_FLAG_NONE));
473 
474     // Wait for it to become readable, which should fail.
475     HandleSignalsState hss;
476     ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
477               WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss));
478     ASSERT_FALSE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
479     ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
480   });
481 }
482 
483 // Android multi-process tests are not executing the new process. This is flaky.
484 #if !defined(OS_ANDROID)
485 INSTANTIATE_TEST_CASE_P(PipeCount,
486                         MultiprocessMessagePipeTestWithPipeCount,
487                         // TODO(rockot): Enable the 128 and 250 pipe cases when
488                         // ChannelPosix and ChannelFuchsia have support for
489                         // sending larger numbers of handles per-message. See
490                         // kMaxAttachedHandles in channel.cc for details.
491                         testing::Values(1u, 64u /*, 128u, 250u*/));
492 #endif
493 
DEFINE_TEST_CLIENT_WITH_PIPE(CheckMessagePipe,MultiprocessMessagePipeTest,h)494 DEFINE_TEST_CLIENT_WITH_PIPE(CheckMessagePipe, MultiprocessMessagePipeTest, h) {
495   // Wait for the first message from our parent.
496   HandleSignalsState hss;
497   CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss),
498            MOJO_RESULT_OK);
499   // In this test, the parent definitely doesn't close its end of the message
500   // pipe before we do.
501   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
502   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
503 
504   // It should have a message pipe.
505   MojoHandle handles[10];
506   uint32_t num_handlers = arraysize(handles);
507   CHECK_EQ(MojoReadMessage(h, nullptr, nullptr, &handles[0], &num_handlers,
508                            MOJO_READ_MESSAGE_FLAG_NONE),
509            MOJO_RESULT_OK);
510   CHECK_EQ(num_handlers, 1u);
511 
512   // Read data from the received message pipe.
513   CHECK_EQ(WaitForSignals(handles[0], MOJO_HANDLE_SIGNAL_READABLE, &hss),
514            MOJO_RESULT_OK);
515   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
516   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
517 
518   std::string read_buffer(100, '\0');
519   uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
520   CHECK_EQ(MojoReadMessage(handles[0], &read_buffer[0], &read_buffer_size,
521                            nullptr, 0, MOJO_READ_MESSAGE_FLAG_NONE),
522            MOJO_RESULT_OK);
523   read_buffer.resize(read_buffer_size);
524   CHECK_EQ(read_buffer, std::string("hello"));
525 
526   // Now write some data into the message pipe.
527   std::string write_buffer = "world";
528   CHECK_EQ(MojoWriteMessage(handles[0], write_buffer.data(),
529                             static_cast<uint32_t>(write_buffer.size()), nullptr,
530                             0u, MOJO_WRITE_MESSAGE_FLAG_NONE),
531            MOJO_RESULT_OK);
532   MojoClose(handles[0]);
533   return 0;
534 }
535 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,MessagePipePassing)536 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MessagePipePassing) {
537   RunTestClient("CheckMessagePipe", [&](MojoHandle h) {
538     MojoCreateSharedBufferOptions options;
539     options.struct_size = sizeof(options);
540     options.flags = MOJO_CREATE_SHARED_BUFFER_FLAG_NONE;
541 
542     MojoHandle mp1, mp2;
543     ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp1, &mp2));
544 
545     // Write a string into one end of the new message pipe and send the other
546     // end.
547     const std::string hello("hello");
548     ASSERT_EQ(
549         MOJO_RESULT_OK,
550         MojoWriteMessage(mp1, &hello[0], static_cast<uint32_t>(hello.size()),
551                          nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
552     ASSERT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h, nullptr, 0, &mp2, 1,
553                                                MOJO_WRITE_MESSAGE_FLAG_NONE));
554 
555     // Wait for a message from the child.
556     HandleSignalsState hss;
557     ASSERT_EQ(MOJO_RESULT_OK,
558               WaitForSignals(mp1, MOJO_HANDLE_SIGNAL_READABLE, &hss));
559     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
560     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
561 
562     std::string read_buffer(100, '\0');
563     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
564     CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], &read_buffer_size, nullptr,
565                              0, MOJO_READ_MESSAGE_FLAG_NONE),
566              MOJO_RESULT_OK);
567     read_buffer.resize(read_buffer_size);
568     CHECK_EQ(read_buffer, std::string("world"));
569 
570     MojoClose(mp1);
571   });
572 }
573 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,MessagePipeTwoPassing)574 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MessagePipeTwoPassing) {
575   RunTestClient("CheckMessagePipe", [&](MojoHandle h) {
576     MojoHandle mp1, mp2;
577     ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp2, &mp1));
578 
579     // Write a string into one end of the new message pipe and send the other
580     // end.
581     const std::string hello("hello");
582     ASSERT_EQ(
583         MOJO_RESULT_OK,
584         MojoWriteMessage(mp1, &hello[0], static_cast<uint32_t>(hello.size()),
585                          nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE));
586     ASSERT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h, nullptr, 0u, &mp2, 1u,
587                                                MOJO_WRITE_MESSAGE_FLAG_NONE));
588 
589     // Wait for a message from the child.
590     HandleSignalsState hss;
591     ASSERT_EQ(MOJO_RESULT_OK,
592               WaitForSignals(mp1, MOJO_HANDLE_SIGNAL_READABLE, &hss));
593     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
594     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
595 
596     std::string read_buffer(100, '\0');
597     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
598     CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], &read_buffer_size, nullptr,
599                              0, MOJO_READ_MESSAGE_FLAG_NONE),
600              MOJO_RESULT_OK);
601     read_buffer.resize(read_buffer_size);
602     CHECK_EQ(read_buffer, std::string("world"));
603   });
604 }
605 
DEFINE_TEST_CLIENT_WITH_PIPE(DataPipeConsumer,MultiprocessMessagePipeTest,h)606 DEFINE_TEST_CLIENT_WITH_PIPE(DataPipeConsumer, MultiprocessMessagePipeTest, h) {
607   // Wait for the first message from our parent.
608   HandleSignalsState hss;
609   CHECK_EQ(WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE, &hss),
610            MOJO_RESULT_OK);
611   // In this test, the parent definitely doesn't close its end of the message
612   // pipe before we do.
613   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
614   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
615   CHECK_EQ(hss.satisfiable_signals,
616            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
617                MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE |
618                MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
619 
620   // It should have a message pipe.
621   MojoHandle handles[10];
622   uint32_t num_handlers = arraysize(handles);
623   CHECK_EQ(MojoReadMessage(h, nullptr, nullptr, &handles[0], &num_handlers,
624                            MOJO_READ_MESSAGE_FLAG_NONE),
625            MOJO_RESULT_OK);
626   CHECK_EQ(num_handlers, 1u);
627 
628   // Read data from the received message pipe.
629   CHECK_EQ(WaitForSignals(handles[0], MOJO_HANDLE_SIGNAL_READABLE, &hss),
630            MOJO_RESULT_OK);
631   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
632   CHECK(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
633   CHECK_EQ(hss.satisfiable_signals,
634            MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
635                MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE |
636                MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED);
637 
638   std::string read_buffer(100, '\0');
639   uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
640   CHECK_EQ(MojoReadMessage(handles[0], &read_buffer[0], &read_buffer_size,
641                            nullptr, 0, MOJO_READ_MESSAGE_FLAG_NONE),
642            MOJO_RESULT_OK);
643   read_buffer.resize(read_buffer_size);
644   CHECK_EQ(read_buffer, std::string("hello"));
645 
646   // Now write some data into the message pipe.
647   std::string write_buffer = "world";
648   CHECK_EQ(MojoWriteMessage(handles[0], write_buffer.data(),
649                             static_cast<uint32_t>(write_buffer.size()), nullptr,
650                             0u, MOJO_WRITE_MESSAGE_FLAG_NONE),
651            MOJO_RESULT_OK);
652   MojoClose(handles[0]);
653   return 0;
654 }
655 
TEST_F(MultiprocessMessagePipeTest,DataPipeConsumer)656 TEST_F(MultiprocessMessagePipeTest, DataPipeConsumer) {
657   RunTestClient("DataPipeConsumer", [&](MojoHandle h) {
658     MojoCreateSharedBufferOptions options;
659     options.struct_size = sizeof(options);
660     options.flags = MOJO_CREATE_SHARED_BUFFER_FLAG_NONE;
661 
662     MojoHandle mp1, mp2;
663     ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp2, &mp1));
664 
665     // Write a string into one end of the new message pipe and send the other
666     // end.
667     const std::string hello("hello");
668     ASSERT_EQ(
669         MOJO_RESULT_OK,
670         MojoWriteMessage(mp1, &hello[0], static_cast<uint32_t>(hello.size()),
671                          nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE));
672     ASSERT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h, nullptr, 0, &mp2, 1u,
673                                                MOJO_WRITE_MESSAGE_FLAG_NONE));
674 
675     // Wait for a message from the child.
676     HandleSignalsState hss;
677     ASSERT_EQ(MOJO_RESULT_OK,
678               WaitForSignals(mp1, MOJO_HANDLE_SIGNAL_READABLE, &hss));
679     EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
680     EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
681 
682     std::string read_buffer(100, '\0');
683     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
684     CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], &read_buffer_size, nullptr,
685                              0, MOJO_READ_MESSAGE_FLAG_NONE),
686              MOJO_RESULT_OK);
687     read_buffer.resize(read_buffer_size);
688     CHECK_EQ(read_buffer, std::string("world"));
689 
690     MojoClose(mp1);
691   });
692 }
693 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,CreateMessagePipe)694 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, CreateMessagePipe) {
695   MojoHandle p0, p1;
696   CreateMessagePipe(&p0, &p1);
697   VerifyTransmission(p0, p1, std::string(10 * 1024 * 1024, 'a'));
698   VerifyTransmission(p1, p0, std::string(10 * 1024 * 1024, 'e'));
699 
700   CloseHandle(p0);
701   CloseHandle(p1);
702 }
703 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,PassMessagePipeLocal)704 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, PassMessagePipeLocal) {
705   MojoHandle p0, p1;
706   CreateMessagePipe(&p0, &p1);
707   VerifyTransmission(p0, p1, "testing testing");
708   VerifyTransmission(p1, p0, "one two three");
709 
710   MojoHandle p2, p3;
711 
712   CreateMessagePipe(&p2, &p3);
713   VerifyTransmission(p2, p3, "testing testing");
714   VerifyTransmission(p3, p2, "one two three");
715 
716   // Pass p2 over p0 to p1.
717   const std::string message = "ceci n'est pas une pipe";
718   WriteMessageWithHandles(p0, message, &p2, 1);
719   EXPECT_EQ(message, ReadMessageWithHandles(p1, &p2, 1));
720 
721   CloseHandle(p0);
722   CloseHandle(p1);
723 
724   // Verify that the received handle (now in p2) still works.
725   VerifyTransmission(p2, p3, "Easy come, easy go; will you let me go?");
726   VerifyTransmission(p3, p2, "Bismillah! NO! We will not let you go!");
727 
728   CloseHandle(p2);
729   CloseHandle(p3);
730 }
731 
732 // Echos the primordial channel until "exit".
DEFINE_TEST_CLIENT_WITH_PIPE(ChannelEchoClient,MultiprocessMessagePipeTest,h)733 DEFINE_TEST_CLIENT_WITH_PIPE(ChannelEchoClient,
734                              MultiprocessMessagePipeTest,
735                              h) {
736   for (;;) {
737     std::string message = ReadMessage(h);
738     if (message == "exit")
739       break;
740     WriteMessage(h, message);
741   }
742   return 0;
743 }
744 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,MultiprocessChannelPipe)745 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, MultiprocessChannelPipe) {
746   RunTestClient("ChannelEchoClient", [&](MojoHandle h) {
747     VerifyEcho(h, "in an interstellar burst");
748     VerifyEcho(h, "i am back to save the universe");
749     VerifyEcho(h, std::string(10 * 1024 * 1024, 'o'));
750 
751     WriteMessage(h, "exit");
752   });
753 }
754 
755 // Receives a pipe handle from the primordial channel and echos on it until
756 // "exit". Used to test simple pipe transfer across processes via channels.
DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceClient,MultiprocessMessagePipeTest,h)757 DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceClient,
758                              MultiprocessMessagePipeTest,
759                              h) {
760   MojoHandle p;
761   ReadMessageWithHandles(h, &p, 1);
762   for (;;) {
763     std::string message = ReadMessage(p);
764     if (message == "exit")
765       break;
766     WriteMessage(p, message);
767   }
768   return 0;
769 }
770 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,PassMessagePipeCrossProcess)771 TEST_P(MultiprocessMessagePipeTestWithPeerSupport,
772        PassMessagePipeCrossProcess) {
773   MojoHandle p0, p1;
774   CreateMessagePipe(&p0, &p1);
775   RunTestClient("EchoServiceClient", [&](MojoHandle h) {
776     // Pass one end of the pipe to the other process.
777     WriteMessageWithHandles(h, "here take this", &p1, 1);
778 
779     VerifyEcho(p0, "and you may ask yourself");
780     VerifyEcho(p0, "where does that highway go?");
781     VerifyEcho(p0, std::string(20 * 1024 * 1024, 'i'));
782 
783     WriteMessage(p0, "exit");
784   });
785   CloseHandle(p0);
786 }
787 
788 // Receives a pipe handle from the primordial channel and reads new handles
789 // from it. Each read handle establishes a new echo channel.
DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceFactoryClient,MultiprocessMessagePipeTest,h)790 DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceFactoryClient,
791                              MultiprocessMessagePipeTest,
792                              h) {
793   MojoHandle p;
794   ReadMessageWithHandles(h, &p, 1);
795 
796   std::vector<Handle> handles(2);
797   handles[0] = Handle(h);
798   handles[1] = Handle(p);
799   std::vector<MojoHandleSignals> signals(2, MOJO_HANDLE_SIGNAL_READABLE);
800   for (;;) {
801     size_t index;
802     CHECK_EQ(
803         mojo::WaitMany(handles.data(), signals.data(), handles.size(), &index),
804         MOJO_RESULT_OK);
805     DCHECK_LE(index, handles.size());
806     if (index == 0) {
807       // If data is available on the first pipe, it should be an exit command.
808       EXPECT_EQ(std::string("exit"), ReadMessage(h));
809       break;
810     } else if (index == 1) {
811       // If the second pipe, it should be a new handle requesting echo service.
812       MojoHandle echo_request;
813       ReadMessageWithHandles(p, &echo_request, 1);
814       handles.push_back(Handle(echo_request));
815       signals.push_back(MOJO_HANDLE_SIGNAL_READABLE);
816     } else {
817       // Otherwise it was one of our established echo pipes. Echo!
818       WriteMessage(handles[index].value(), ReadMessage(handles[index].value()));
819     }
820   }
821 
822   for (size_t i = 1; i < handles.size(); ++i)
823     CloseHandle(handles[i].value());
824 
825   return 0;
826 }
827 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,PassMoarMessagePipesCrossProcess)828 TEST_P(MultiprocessMessagePipeTestWithPeerSupport,
829        PassMoarMessagePipesCrossProcess) {
830   MojoHandle echo_factory_proxy, echo_factory_request;
831   CreateMessagePipe(&echo_factory_proxy, &echo_factory_request);
832 
833   MojoHandle echo_proxy_a, echo_request_a;
834   CreateMessagePipe(&echo_proxy_a, &echo_request_a);
835 
836   MojoHandle echo_proxy_b, echo_request_b;
837   CreateMessagePipe(&echo_proxy_b, &echo_request_b);
838 
839   MojoHandle echo_proxy_c, echo_request_c;
840   CreateMessagePipe(&echo_proxy_c, &echo_request_c);
841 
842   RunTestClient("EchoServiceFactoryClient", [&](MojoHandle h) {
843     WriteMessageWithHandles(h, "gief factory naow plz", &echo_factory_request,
844                             1);
845 
846     WriteMessageWithHandles(echo_factory_proxy, "give me an echo service plz!",
847                             &echo_request_a, 1);
848     WriteMessageWithHandles(echo_factory_proxy, "give me one too!",
849                             &echo_request_b, 1);
850 
851     VerifyEcho(echo_proxy_a, "i came here for an argument");
852     VerifyEcho(echo_proxy_a, "shut your festering gob");
853     VerifyEcho(echo_proxy_a, "mumble mumble mumble");
854 
855     VerifyEcho(echo_proxy_b, "wubalubadubdub");
856     VerifyEcho(echo_proxy_b, "wubalubadubdub");
857 
858     WriteMessageWithHandles(echo_factory_proxy, "hook me up also thanks",
859                             &echo_request_c, 1);
860 
861     VerifyEcho(echo_proxy_a, "the frobinators taste like frobinators");
862     VerifyEcho(echo_proxy_b, "beep bop boop");
863     VerifyEcho(echo_proxy_c, "zzzzzzzzzzzzzzzzzzzzzzzzzz");
864 
865     WriteMessage(h, "exit");
866   });
867 
868   CloseHandle(echo_factory_proxy);
869   CloseHandle(echo_proxy_a);
870   CloseHandle(echo_proxy_b);
871   CloseHandle(echo_proxy_c);
872 }
873 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,ChannelPipesWithMultipleChildren)874 TEST_P(MultiprocessMessagePipeTestWithPeerSupport,
875        ChannelPipesWithMultipleChildren) {
876   RunTestClient("ChannelEchoClient", [&](MojoHandle a) {
877     RunTestClient("ChannelEchoClient", [&](MojoHandle b) {
878       VerifyEcho(a, "hello child 0");
879       VerifyEcho(b, "hello child 1");
880 
881       WriteMessage(a, "exit");
882       WriteMessage(b, "exit");
883     });
884   });
885 }
886 
887 // Reads and turns a pipe handle some number of times to create lots of
888 // transient proxies.
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(PingPongPipeClient,MultiprocessMessagePipeTest,h)889 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(PingPongPipeClient,
890                                   MultiprocessMessagePipeTest,
891                                   h) {
892   const size_t kNumBounces = 50;
893   MojoHandle p0, p1;
894   ReadMessageWithHandles(h, &p0, 1);
895   ReadMessageWithHandles(h, &p1, 1);
896   for (size_t i = 0; i < kNumBounces; ++i) {
897     WriteMessageWithHandles(h, "", &p1, 1);
898     ReadMessageWithHandles(h, &p1, 1);
899   }
900   WriteMessageWithHandles(h, "", &p0, 1);
901   WriteMessage(p1, "bye");
902   MojoClose(p1);
903   EXPECT_EQ("quit", ReadMessage(h));
904 }
905 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,PingPongPipe)906 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, PingPongPipe) {
907   MojoHandle p0, p1;
908   CreateMessagePipe(&p0, &p1);
909 
910   RunTestClient("PingPongPipeClient", [&](MojoHandle h) {
911     const size_t kNumBounces = 50;
912     WriteMessageWithHandles(h, "", &p0, 1);
913     WriteMessageWithHandles(h, "", &p1, 1);
914     for (size_t i = 0; i < kNumBounces; ++i) {
915       ReadMessageWithHandles(h, &p1, 1);
916       WriteMessageWithHandles(h, "", &p1, 1);
917     }
918     ReadMessageWithHandles(h, &p0, 1);
919     WriteMessage(h, "quit");
920   });
921 
922   EXPECT_EQ("bye", ReadMessage(p0));
923 
924   // We should still be able to observe peer closure from the other end.
925   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(p0, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
926 }
927 
928 // Parses commands from the parent pipe and does whatever it's asked to do.
DEFINE_TEST_CLIENT_WITH_PIPE(CommandDrivenClient,MultiprocessMessagePipeTest,h)929 DEFINE_TEST_CLIENT_WITH_PIPE(CommandDrivenClient,
930                              MultiprocessMessagePipeTest,
931                              h) {
932   base::hash_map<std::string, MojoHandle> named_pipes;
933   for (;;) {
934     MojoHandle p;
935     auto parts = base::SplitString(ReadMessageWithOptionalHandle(h, &p), ":",
936                                    base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
937     CHECK(!parts.empty());
938     std::string command = parts[0];
939     if (command == "take") {
940       // Take a pipe.
941       CHECK_EQ(parts.size(), 2u);
942       CHECK_NE(p, MOJO_HANDLE_INVALID);
943       named_pipes[parts[1]] = p;
944       WriteMessage(h, "ok");
945     } else if (command == "return") {
946       // Return a pipe.
947       CHECK_EQ(parts.size(), 2u);
948       CHECK_EQ(p, MOJO_HANDLE_INVALID);
949       p = named_pipes[parts[1]];
950       CHECK_NE(p, MOJO_HANDLE_INVALID);
951       named_pipes.erase(parts[1]);
952       WriteMessageWithHandles(h, "ok", &p, 1);
953     } else if (command == "say") {
954       // Say something to a named pipe.
955       CHECK_EQ(parts.size(), 3u);
956       CHECK_EQ(p, MOJO_HANDLE_INVALID);
957       p = named_pipes[parts[1]];
958       CHECK_NE(p, MOJO_HANDLE_INVALID);
959       CHECK(!parts[2].empty());
960       WriteMessage(p, parts[2]);
961       WriteMessage(h, "ok");
962     } else if (command == "hear") {
963       // Expect to read something from a named pipe.
964       CHECK_EQ(parts.size(), 3u);
965       CHECK_EQ(p, MOJO_HANDLE_INVALID);
966       p = named_pipes[parts[1]];
967       CHECK_NE(p, MOJO_HANDLE_INVALID);
968       CHECK(!parts[2].empty());
969       CHECK_EQ(parts[2], ReadMessage(p));
970       WriteMessage(h, "ok");
971     } else if (command == "pass") {
972       // Pass one named pipe over another named pipe.
973       CHECK_EQ(parts.size(), 3u);
974       CHECK_EQ(p, MOJO_HANDLE_INVALID);
975       p = named_pipes[parts[1]];
976       MojoHandle carrier = named_pipes[parts[2]];
977       CHECK_NE(p, MOJO_HANDLE_INVALID);
978       CHECK_NE(carrier, MOJO_HANDLE_INVALID);
979       named_pipes.erase(parts[1]);
980       WriteMessageWithHandles(carrier, "got a pipe for ya", &p, 1);
981       WriteMessage(h, "ok");
982     } else if (command == "catch") {
983       // Expect to receive one named pipe from another named pipe.
984       CHECK_EQ(parts.size(), 3u);
985       CHECK_EQ(p, MOJO_HANDLE_INVALID);
986       MojoHandle carrier = named_pipes[parts[2]];
987       CHECK_NE(carrier, MOJO_HANDLE_INVALID);
988       ReadMessageWithHandles(carrier, &p, 1);
989       CHECK_NE(p, MOJO_HANDLE_INVALID);
990       named_pipes[parts[1]] = p;
991       WriteMessage(h, "ok");
992     } else if (command == "exit") {
993       CHECK_EQ(parts.size(), 1u);
994       break;
995     }
996   }
997 
998   for (auto& pipe : named_pipes)
999     CloseHandle(pipe.second);
1000 
1001   return 0;
1002 }
1003 
TEST_F(MultiprocessMessagePipeTest,ChildToChildPipes)1004 TEST_F(MultiprocessMessagePipeTest, ChildToChildPipes) {
1005   RunTestClient("CommandDrivenClient", [&](MojoHandle h0) {
1006     RunTestClient("CommandDrivenClient", [&](MojoHandle h1) {
1007       CommandDrivenClientController a(h0);
1008       CommandDrivenClientController b(h1);
1009 
1010       // Create a pipe and pass each end to a different client.
1011       MojoHandle p0, p1;
1012       CreateMessagePipe(&p0, &p1);
1013       a.SendHandle("x", p0);
1014       b.SendHandle("y", p1);
1015 
1016       // Make sure they can talk.
1017       a.Send("say:x:hello");
1018       b.Send("hear:y:hello");
1019 
1020       b.Send("say:y:i love multiprocess pipes!");
1021       a.Send("hear:x:i love multiprocess pipes!");
1022 
1023       a.Exit();
1024       b.Exit();
1025     });
1026   });
1027 }
1028 
TEST_F(MultiprocessMessagePipeTest,MoreChildToChildPipes)1029 TEST_F(MultiprocessMessagePipeTest, MoreChildToChildPipes) {
1030   RunTestClient("CommandDrivenClient", [&](MojoHandle h0) {
1031     RunTestClient("CommandDrivenClient", [&](MojoHandle h1) {
1032       RunTestClient("CommandDrivenClient", [&](MojoHandle h2) {
1033         RunTestClient("CommandDrivenClient", [&](MojoHandle h3) {
1034           CommandDrivenClientController a(h0), b(h1), c(h2), d(h3);
1035 
1036           // Connect a to b and c to d
1037 
1038           MojoHandle p0, p1;
1039 
1040           CreateMessagePipe(&p0, &p1);
1041           a.SendHandle("b_pipe", p0);
1042           b.SendHandle("a_pipe", p1);
1043 
1044           MojoHandle p2, p3;
1045 
1046           CreateMessagePipe(&p2, &p3);
1047           c.SendHandle("d_pipe", p2);
1048           d.SendHandle("c_pipe", p3);
1049 
1050           // Connect b to c via a and d
1051           MojoHandle p4, p5;
1052           CreateMessagePipe(&p4, &p5);
1053           a.SendHandle("d_pipe", p4);
1054           d.SendHandle("a_pipe", p5);
1055 
1056           // Have |a| pass its new |d|-pipe to |b|. It will eventually connect
1057           // to |c|.
1058           a.Send("pass:d_pipe:b_pipe");
1059           b.Send("catch:c_pipe:a_pipe");
1060 
1061           // Have |d| pass its new |a|-pipe to |c|. It will now be connected to
1062           // |b|.
1063           d.Send("pass:a_pipe:c_pipe");
1064           c.Send("catch:b_pipe:d_pipe");
1065 
1066           // Make sure b and c and talk.
1067           b.Send("say:c_pipe:it's a beautiful day");
1068           c.Send("hear:b_pipe:it's a beautiful day");
1069 
1070           // Create x and y and have b and c exchange them.
1071           MojoHandle x, y;
1072           CreateMessagePipe(&x, &y);
1073           b.SendHandle("x", x);
1074           c.SendHandle("y", y);
1075           b.Send("pass:x:c_pipe");
1076           c.Send("pass:y:b_pipe");
1077           b.Send("catch:y:c_pipe");
1078           c.Send("catch:x:b_pipe");
1079 
1080           // Make sure the pipe still works in both directions.
1081           b.Send("say:y:hello");
1082           c.Send("hear:x:hello");
1083           c.Send("say:x:goodbye");
1084           b.Send("hear:y:goodbye");
1085 
1086           // Take both pipes back.
1087           y = c.RetrieveHandle("x");
1088           x = b.RetrieveHandle("y");
1089 
1090           VerifyTransmission(x, y, "still works");
1091           VerifyTransmission(y, x, "in both directions");
1092 
1093           CloseHandle(x);
1094           CloseHandle(y);
1095 
1096           a.Exit();
1097           b.Exit();
1098           c.Exit();
1099           d.Exit();
1100         });
1101       });
1102     });
1103   });
1104 }
1105 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeer,MultiprocessMessagePipeTest,h)1106 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeer,
1107                                   MultiprocessMessagePipeTest,
1108                                   h) {
1109   MojoHandle p;
1110   EXPECT_EQ("foo", ReadMessageWithHandles(h, &p, 1));
1111   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
1112 }
1113 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,SendPipeThenClosePeer)1114 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, SendPipeThenClosePeer) {
1115   RunTestClient("ReceivePipeWithClosedPeer", [&](MojoHandle h) {
1116     MojoHandle a, b;
1117     CreateMessagePipe(&a, &b);
1118 
1119     // Send |a| and immediately close |b|. The child should observe closure.
1120     WriteMessageWithHandles(h, "foo", &a, 1);
1121     MojoClose(b);
1122   });
1123 }
1124 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(SendOtherChildPipeWithClosedPeer,MultiprocessMessagePipeTest,h)1125 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(SendOtherChildPipeWithClosedPeer,
1126                                   MultiprocessMessagePipeTest,
1127                                   h) {
1128   // Create a new pipe and send one end to the parent, who will connect it to
1129   // a client running ReceivePipeWithClosedPeerFromOtherChild.
1130   MojoHandle application_proxy, application_request;
1131   CreateMessagePipe(&application_proxy, &application_request);
1132   WriteMessageWithHandles(h, "c2a plz", &application_request, 1);
1133 
1134   // Create another pipe and send one end to the remote "application".
1135   MojoHandle service_proxy, service_request;
1136   CreateMessagePipe(&service_proxy, &service_request);
1137   WriteMessageWithHandles(application_proxy, "c2s lol", &service_request, 1);
1138 
1139   // Immediately close the service proxy. The "application" should detect this.
1140   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(service_proxy));
1141 
1142   // Wait for quit.
1143   EXPECT_EQ("quit", ReadMessage(h));
1144 }
1145 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeerFromOtherChild,MultiprocessMessagePipeTest,h)1146 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeerFromOtherChild,
1147                                   MultiprocessMessagePipeTest,
1148                                   h) {
1149   // Receive a pipe from the parent. This is akin to an "application request".
1150   MojoHandle application_client;
1151   EXPECT_EQ("c2a", ReadMessageWithHandles(h, &application_client, 1));
1152 
1153   // Receive a pipe from the "application" "client".
1154   MojoHandle service_client;
1155   EXPECT_EQ("c2s lol",
1156             ReadMessageWithHandles(application_client, &service_client, 1));
1157 
1158   // Wait for the service client to signal closure.
1159   EXPECT_EQ(MOJO_RESULT_OK,
1160             WaitForSignals(service_client, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
1161 
1162   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(service_client));
1163   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(application_client));
1164 }
1165 
1166 #if defined(OS_ANDROID)
1167 // Android multi-process tests are not executing the new process. This is flaky.
1168 #define MAYBE_SendPipeWithClosedPeerBetweenChildren \
1169   DISABLED_SendPipeWithClosedPeerBetweenChildren
1170 #else
1171 #define MAYBE_SendPipeWithClosedPeerBetweenChildren \
1172   SendPipeWithClosedPeerBetweenChildren
1173 #endif
TEST_F(MultiprocessMessagePipeTest,MAYBE_SendPipeWithClosedPeerBetweenChildren)1174 TEST_F(MultiprocessMessagePipeTest,
1175        MAYBE_SendPipeWithClosedPeerBetweenChildren) {
1176   RunTestClient("SendOtherChildPipeWithClosedPeer", [&](MojoHandle kid_a) {
1177     RunTestClient(
1178         "ReceivePipeWithClosedPeerFromOtherChild", [&](MojoHandle kid_b) {
1179           // Receive an "application request" from the first child and forward
1180           // it to the second child.
1181           MojoHandle application_request;
1182           EXPECT_EQ("c2a plz",
1183                     ReadMessageWithHandles(kid_a, &application_request, 1));
1184 
1185           WriteMessageWithHandles(kid_b, "c2a", &application_request, 1);
1186         });
1187 
1188     WriteMessage(kid_a, "quit");
1189   });
1190 }
1191 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,SendClosePeerSend)1192 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, SendClosePeerSend) {
1193   MojoHandle a, b;
1194   CreateMessagePipe(&a, &b);
1195 
1196   MojoHandle c, d;
1197   CreateMessagePipe(&c, &d);
1198 
1199   // Send |a| over |c|, immediately close |b|, then send |a| back over |d|.
1200   WriteMessageWithHandles(c, "foo", &a, 1);
1201   EXPECT_EQ("foo", ReadMessageWithHandles(d, &a, 1));
1202   WriteMessageWithHandles(d, "bar", &a, 1);
1203   EXPECT_EQ("bar", ReadMessageWithHandles(c, &a, 1));
1204   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
1205 
1206   // We should be able to detect peer closure on |a|.
1207   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(a, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
1208 }
1209 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteCloseSendPeerClient,MultiprocessMessagePipeTest,h)1210 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteCloseSendPeerClient,
1211                                   MultiprocessMessagePipeTest,
1212                                   h) {
1213   MojoHandle pipe[2];
1214   EXPECT_EQ("foo", ReadMessageWithHandles(h, pipe, 2));
1215 
1216   // Write some messages to the first endpoint and then close it.
1217   WriteMessage(pipe[0], "baz");
1218   WriteMessage(pipe[0], "qux");
1219   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe[0]));
1220 
1221   MojoHandle c, d;
1222   CreateMessagePipe(&c, &d);
1223 
1224   // Pass the orphaned endpoint over another pipe before passing it back to
1225   // the parent, just for some extra proxying goodness.
1226   WriteMessageWithHandles(c, "foo", &pipe[1], 1);
1227   EXPECT_EQ("foo", ReadMessageWithHandles(d, &pipe[1], 1));
1228 
1229   // And finally pass it back to the parent.
1230   WriteMessageWithHandles(h, "bar", &pipe[1], 1);
1231 
1232   EXPECT_EQ("quit", ReadMessage(h));
1233 }
1234 
TEST_P(MultiprocessMessagePipeTestWithPeerSupport,WriteCloseSendPeer)1235 TEST_P(MultiprocessMessagePipeTestWithPeerSupport, WriteCloseSendPeer) {
1236   MojoHandle pipe[2];
1237   CreateMessagePipe(&pipe[0], &pipe[1]);
1238 
1239   RunTestClient("WriteCloseSendPeerClient", [&](MojoHandle h) {
1240     // Pass the pipe to the child.
1241     WriteMessageWithHandles(h, "foo", pipe, 2);
1242 
1243     // Read back an endpoint which should have messages on it.
1244     MojoHandle p;
1245     EXPECT_EQ("bar", ReadMessageWithHandles(h, &p, 1));
1246 
1247     EXPECT_EQ("baz", ReadMessage(p));
1248     EXPECT_EQ("qux", ReadMessage(p));
1249 
1250     // Expect to have peer closure signaled.
1251     EXPECT_EQ(MOJO_RESULT_OK,
1252               WaitForSignals(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
1253 
1254     WriteMessage(h, "quit");
1255   });
1256 }
1257 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MessagePipeStatusChangeInTransitClient,MultiprocessMessagePipeTest,parent)1258 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MessagePipeStatusChangeInTransitClient,
1259                                   MultiprocessMessagePipeTest,
1260                                   parent) {
1261   // This test verifies that peer closure is detectable through various
1262   // mechanisms when it races with handle transfer.
1263   MojoHandle handles[4];
1264   EXPECT_EQ("o_O", ReadMessageWithHandles(parent, handles, 4));
1265 
1266   EXPECT_EQ(MOJO_RESULT_OK,
1267             WaitForSignals(handles[0], MOJO_HANDLE_SIGNAL_PEER_CLOSED));
1268 
1269   base::MessageLoop message_loop;
1270 
1271   // Wait on handle 1 using a SimpleWatcher.
1272   {
1273     base::RunLoop run_loop;
1274     SimpleWatcher watcher(FROM_HERE, SimpleWatcher::ArmingPolicy::AUTOMATIC,
1275                           base::SequencedTaskRunnerHandle::Get());
1276     watcher.Watch(Handle(handles[1]), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
1277                   base::Bind(
1278                       [](base::RunLoop* loop, MojoResult result) {
1279                         EXPECT_EQ(MOJO_RESULT_OK, result);
1280                         loop->Quit();
1281                       },
1282                       &run_loop));
1283     run_loop.Run();
1284   }
1285 
1286   // Wait on handle 2 by polling with MojoReadMessage.
1287   MojoResult result;
1288   do {
1289     result = MojoReadMessage(handles[2], nullptr, nullptr, nullptr, nullptr,
1290                              MOJO_READ_MESSAGE_FLAG_NONE);
1291   } while (result == MOJO_RESULT_SHOULD_WAIT);
1292   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
1293 
1294   // Wait on handle 3 by polling with MojoWriteMessage.
1295   do {
1296     result = MojoWriteMessage(handles[3], nullptr, 0, nullptr, 0,
1297                               MOJO_WRITE_MESSAGE_FLAG_NONE);
1298   } while (result == MOJO_RESULT_OK);
1299   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
1300 
1301   for (size_t i = 0; i < 4; ++i)
1302     CloseHandle(handles[i]);
1303 }
1304 
TEST_F(MultiprocessMessagePipeTest,MessagePipeStatusChangeInTransit)1305 TEST_F(MultiprocessMessagePipeTest, MessagePipeStatusChangeInTransit) {
1306   MojoHandle local_handles[4];
1307   MojoHandle sent_handles[4];
1308   for (size_t i = 0; i < 4; ++i)
1309     CreateMessagePipe(&local_handles[i], &sent_handles[i]);
1310 
1311   RunTestClient("MessagePipeStatusChangeInTransitClient",
1312                 [&](MojoHandle child) {
1313                   // Send 4 handles and let their transfer race with their
1314                   // peers' closure.
1315                   WriteMessageWithHandles(child, "o_O", sent_handles, 4);
1316                   for (size_t i = 0; i < 4; ++i)
1317                     CloseHandle(local_handles[i]);
1318                 });
1319 }
1320 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(BadMessageClient,MultiprocessMessagePipeTest,parent)1321 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(BadMessageClient,
1322                                   MultiprocessMessagePipeTest,
1323                                   parent) {
1324   MojoHandle pipe;
1325   EXPECT_EQ("hi", ReadMessageWithHandles(parent, &pipe, 1));
1326   WriteMessage(pipe, "derp");
1327   EXPECT_EQ("bye", ReadMessage(parent));
1328 }
1329 
1330 INSTANTIATE_TEST_CASE_P(
1331     ,
1332     MultiprocessMessagePipeTestWithPeerSupport,
1333     testing::Values(test::MojoTestBase::LaunchType::CHILD,
1334                     test::MojoTestBase::LaunchType::PEER,
1335                     test::MojoTestBase::LaunchType::NAMED_CHILD,
1336                     test::MojoTestBase::LaunchType::NAMED_PEER));
1337 }  // namespace
1338 }  // namespace core
1339 }  // namespace mojo
1340