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