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