OLD | NEW |
---|---|
(Empty) | |
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 <stdint.h> | |
6 #include <stdio.h> | |
7 #include <string.h> | |
8 | |
9 #include <string> | |
10 #include <vector> | |
11 | |
12 #include "base/bind.h" | |
13 #include "base/files/file_path.h" | |
14 #include "base/files/file_util.h" | |
15 #include "base/files/scoped_file.h" | |
16 #include "base/files/scoped_temp_dir.h" | |
17 #include "base/location.h" | |
18 #include "base/logging.h" | |
19 #include "base/test/test_io_thread.h" | |
20 #include "build/build_config.h" // TODO(vtl): Remove this. | |
21 #include "mojo/edk/embedder/embedder.h" | |
22 #include "mojo/edk/embedder/platform_channel_pair.h" | |
23 #include "mojo/edk/embedder/platform_shared_buffer.h" | |
24 #include "mojo/edk/embedder/scoped_platform_handle.h" | |
25 #include "mojo/edk/system/dispatcher.h" | |
26 #include "mojo/edk/system/message_pipe_test_utils.h" | |
27 #include "mojo/edk/system/platform_handle_dispatcher.h" | |
28 #include "mojo/edk/system/raw_channel.h" | |
29 #include "mojo/edk/system/shared_buffer_dispatcher.h" | |
30 #include "mojo/edk/system/test_utils.h" | |
31 #include "mojo/edk/test/test_utils.h" | |
32 #include "testing/gtest/include/gtest/gtest.h" | |
33 | |
34 | |
35 namespace mojo { | |
36 namespace edk { | |
37 namespace { | |
38 | |
39 class MultiprocessMessagePipeTest | |
40 : public test::MultiprocessMessagePipeTestBase {}; | |
41 | |
42 // For each message received, sends a reply message with the same contents | |
43 // repeated twice, until the other end is closed or it receives "quitquitquit" | |
44 // (which it doesn't reply to). It'll return the number of messages received, | |
45 // not including any "quitquitquit" message, modulo 100. | |
46 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) { | |
47 SimplePlatformSupport platform_support; | |
48 base::MessageLoop message_loop; | |
49 base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); | |
50 test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); | |
51 | |
52 ScopedPlatformHandle client_platform_handle = | |
53 test::MultiprocessTestHelper::client_platform_handle.Pass(); | |
54 CHECK(client_platform_handle.is_valid()); | |
55 ScopedMessagePipeHandle mp = | |
56 CreateMessagePipe(client_platform_handle.Pass()); | |
57 | |
58 const std::string quitquitquit("quitquitquit"); | |
59 int rv = 0; | |
60 for (;; rv = (rv + 1) % 100) { | |
61 // Wait for our end of the message pipe to be readable. | |
62 HandleSignalsState hss; | |
63 MojoResult result = | |
64 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
65 MOJO_DEADLINE_INDEFINITE, &hss); | |
66 if (result != MOJO_RESULT_OK) { | |
67 // It was closed, probably. | |
68 CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION); | |
69 CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
70 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
71 break; | |
72 } else { | |
73 CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
74 CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
75 } | |
76 | |
77 std::string read_buffer(1000, '\0'); | |
78 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
79 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | |
80 &read_buffer_size, nullptr, | |
81 0, MOJO_READ_MESSAGE_FLAG_NONE), | |
82 MOJO_RESULT_OK); | |
83 read_buffer.resize(read_buffer_size); | |
84 VLOG(2) << "Child got: " << read_buffer; | |
85 | |
86 if (read_buffer == quitquitquit) { | |
87 VLOG(2) << "Child quitting."; | |
88 break; | |
89 } | |
90 | |
91 std::string write_buffer = read_buffer + read_buffer; | |
92 CHECK_EQ(MojoWriteMessage(mp.get().value(), write_buffer.data(), | |
93 write_buffer.size(), | |
94 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE), | |
95 MOJO_RESULT_OK); | |
96 } | |
97 | |
98 return rv; | |
99 } | |
100 | |
101 // Sends "hello" to child, and expects "hellohello" back. | |
102 #if defined(OS_ANDROID) | |
103 // Android multi-process tests are not executing the new process. This is flaky. | |
104 #define MAYBE_Basic DISABLED_Basic | |
105 #else | |
106 #define MAYBE_Basic Basic | |
107 #endif // defined(OS_ANDROID) | |
108 TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { | |
109 helper()->StartChild("EchoEcho"); | |
110 | |
111 ScopedMessagePipeHandle mp = CreateMessagePipe( | |
112 helper()->server_platform_handle.Pass()); | |
113 | |
114 std::string hello("hello"); | |
115 ASSERT_EQ(MOJO_RESULT_OK, | |
116 MojoWriteMessage(mp.get().value(), hello.data(), | |
117 hello.size(), nullptr, 0, | |
118 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
119 | |
120 HandleSignalsState hss; | |
121 ASSERT_EQ(MOJO_RESULT_OK, | |
122 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
123 MOJO_DEADLINE_INDEFINITE, &hss)); | |
124 // The child may or may not have closed its end of the message pipe and died | |
125 // (and we may or may not know it yet), so our end may or may not appear as | |
126 // writable. | |
127 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
128 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
129 | |
130 std::string read_buffer(1000, '\0'); | |
131 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
132 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | |
133 &read_buffer_size, nullptr, 0, | |
134 MOJO_READ_MESSAGE_FLAG_NONE), | |
135 MOJO_RESULT_OK); | |
136 read_buffer.resize(read_buffer_size); | |
137 VLOG(2) << "Parent got: " << read_buffer; | |
138 ASSERT_EQ(hello + hello, read_buffer); | |
139 | |
140 MojoClose(mp.release().value()); | |
141 | |
142 // We sent one message. | |
143 ASSERT_EQ(1 % 100, helper()->WaitForChildShutdown()); | |
144 } | |
145 | |
146 // Sends a bunch of messages to the child. Expects them "repeated" back. Waits | |
147 // for the child to close its end before quitting. | |
148 #if defined(OS_ANDROID) | |
149 // Android multi-process tests are not executing the new process. This is flaky. | |
150 #define MAYBE_QueueMessages DISABLED_QueueMessages | |
151 #else | |
152 #define MAYBE_QueueMessages QueueMessages | |
153 #endif // defined(OS_ANDROID) | |
154 TEST_F(MultiprocessMessagePipeTest, MAYBE_QueueMessages) { | |
155 helper()->StartChild("EchoEcho"); | |
156 | |
157 ScopedMessagePipeHandle mp = CreateMessagePipe( | |
158 helper()->server_platform_handle.Pass()); | |
159 | |
160 static const size_t kNumMessages = 1001; | |
161 for (size_t i = 0; i < kNumMessages; i++) { | |
162 std::string write_buffer(i, 'A' + (i % 26)); | |
163 ASSERT_EQ(MOJO_RESULT_OK, | |
164 MojoWriteMessage(mp.get().value(), write_buffer.data(), | |
165 write_buffer.size(), nullptr, 0, | |
166 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
167 } | |
168 | |
169 const std::string quitquitquit("quitquitquit"); | |
170 ASSERT_EQ(MOJO_RESULT_OK, | |
171 MojoWriteMessage(mp.get().value(), quitquitquit.data(), | |
172 quitquitquit.size(), nullptr, 0, | |
173 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
174 | |
175 for (size_t i = 0; i < kNumMessages; i++) { | |
176 HandleSignalsState hss; | |
177 ASSERT_EQ(MOJO_RESULT_OK, | |
178 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
179 MOJO_DEADLINE_INDEFINITE, &hss)); | |
180 // The child may or may not have closed its end of the message pipe and died | |
181 // (and we may or may not know it yet), so our end may or may not appear as | |
182 // writable. | |
183 ASSERT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
184 ASSERT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
185 | |
186 std::string read_buffer(kNumMessages * 2, '\0'); | |
187 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
188 ASSERT_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | |
189 &read_buffer_size, nullptr, 0, | |
190 MOJO_READ_MESSAGE_FLAG_NONE), | |
191 MOJO_RESULT_OK); | |
192 read_buffer.resize(read_buffer_size); | |
193 | |
194 ASSERT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer); | |
195 } | |
196 | |
197 // Wait for it to become readable, which should fail (since we sent | |
198 // "quitquitquit"). | |
199 HandleSignalsState hss; | |
200 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
201 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
202 MOJO_DEADLINE_INDEFINITE, &hss)); | |
203 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | |
204 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | |
205 | |
206 ASSERT_EQ(static_cast<int>(kNumMessages % 100), | |
207 helper()->WaitForChildShutdown()); | |
208 } | |
209 | |
210 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { | |
211 SimplePlatformSupport platform_support; | |
212 base::MessageLoop message_loop; | |
213 base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); | |
214 test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); | |
215 | |
216 ScopedPlatformHandle client_platform_handle = | |
217 test::MultiprocessTestHelper::client_platform_handle.Pass(); | |
218 CHECK(client_platform_handle.is_valid()); | |
219 ScopedMessagePipeHandle mp = | |
220 CreateMessagePipe(client_platform_handle.Pass()); | |
221 | |
222 // Wait for the first message from our parent. | |
223 HandleSignalsState hss; | |
224 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
225 MOJO_DEADLINE_INDEFINITE, &hss), | |
226 MOJO_RESULT_OK); | |
227 // In this test, the parent definitely doesn't close its end of the message | |
228 // pipe before we do. | |
229 CHECK_EQ(hss.satisfied_signals, | |
230 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | |
231 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | |
232 MOJO_HANDLE_SIGNAL_WRITABLE | | |
233 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
234 | |
235 // It should have a shared buffer. | |
236 std::string read_buffer(100, '\0'); | |
237 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); | |
238 MojoHandle handles[10]; | |
239 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); // Maximum number to receive | |
240 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | |
241 &num_bytes, &handles[0], | |
242 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | |
243 MOJO_RESULT_OK); | |
244 read_buffer.resize(num_bytes); | |
245 CHECK_EQ(read_buffer, std::string("go 1")); | |
246 CHECK_EQ(num_handlers, 1u); | |
247 | |
248 // Make a mapping. | |
249 void* buffer; | |
250 CHECK_EQ(MojoMapBuffer(handles[0], 0, 100, &buffer, | |
251 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), | |
252 MOJO_RESULT_OK); | |
253 | |
254 // Write some stuff to the shared buffer. | |
255 static const char kHello[] = "hello"; | |
256 memcpy(buffer, kHello, sizeof(kHello)); | |
257 | |
258 // We should be able to close the dispatcher now. | |
259 MojoClose(handles[0]); | |
260 | |
261 // And send a message to signal that we've written stuff. | |
262 const std::string go2("go 2"); | |
263 CHECK_EQ(MojoWriteMessage(mp.get().value(), go2.data(), | |
264 go2.size(), nullptr, 0, | |
265 MOJO_WRITE_MESSAGE_FLAG_NONE), | |
266 MOJO_RESULT_OK); | |
267 | |
268 // Now wait for our parent to send us a message. | |
269 hss = HandleSignalsState(); | |
270 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
271 MOJO_DEADLINE_INDEFINITE, &hss), | |
272 MOJO_RESULT_OK); | |
273 CHECK_EQ(hss.satisfied_signals, | |
274 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | |
275 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | |
276 MOJO_HANDLE_SIGNAL_WRITABLE | | |
277 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
278 | |
279 read_buffer = std::string(100, '\0'); | |
280 num_bytes = static_cast<uint32_t>(read_buffer.size()); | |
281 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], &num_bytes, | |
282 nullptr, 0, MOJO_READ_MESSAGE_FLAG_NONE), | |
283 MOJO_RESULT_OK); | |
284 read_buffer.resize(num_bytes); | |
285 CHECK_EQ(read_buffer, std::string("go 3")); | |
286 | |
287 // It should have written something to the shared buffer. | |
288 static const char kWorld[] = "world!!!"; | |
289 CHECK_EQ(memcmp(buffer, kWorld, sizeof(kWorld)), 0); | |
290 | |
291 // And we're done. | |
292 | |
293 return 0; | |
294 } | |
295 | |
296 #if defined(OS_ANDROID) | |
297 // Android multi-process tests are not executing the new process. This is flaky. | |
298 #define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing | |
299 #else | |
300 #define MAYBE_SharedBufferPassing SharedBufferPassing | |
301 #endif | |
302 TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { | |
303 helper()->StartChild("CheckSharedBuffer"); | |
304 | |
305 ScopedMessagePipeHandle mp = CreateMessagePipe( | |
306 helper()->server_platform_handle.Pass()); | |
307 | |
308 // Make a shared buffer. | |
309 MojoCreateSharedBufferOptions options; | |
310 options.struct_size = sizeof(options); | |
311 options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; | |
312 | |
313 MojoHandle shared_buffer; | |
314 ASSERT_EQ(MOJO_RESULT_OK, | |
315 MojoCreateSharedBuffer(&options, 100, &shared_buffer)); | |
316 | |
317 // Send the shared buffer. | |
318 const std::string go1("go 1"); | |
319 | |
320 MojoHandle duplicated_shared_buffer; | |
321 ASSERT_EQ(MOJO_RESULT_OK, | |
322 MojoDuplicateBufferHandle( | |
323 shared_buffer, | |
324 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE, | |
Ken Rockot(use gerrit already)
2015/09/23 22:32:17
I believe you just want nullptr here rather than a
| |
325 &duplicated_shared_buffer)); | |
326 MojoHandle handles[1]; | |
327 handles[0] = duplicated_shared_buffer; | |
328 ASSERT_EQ(MOJO_RESULT_OK, | |
329 MojoWriteMessage(mp.get().value(), &go1[0], go1.size(), &handles[0], | |
330 MOJO_ARRAYSIZE(handles), | |
331 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
332 | |
333 // Wait for a message from the child. | |
334 HandleSignalsState hss; | |
335 ASSERT_EQ(MOJO_RESULT_OK, | |
336 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
337 MOJO_DEADLINE_INDEFINITE, &hss)); | |
338 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
339 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
340 | |
341 std::string read_buffer(100, '\0'); | |
342 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); | |
343 ASSERT_EQ(MOJO_RESULT_OK, | |
344 MojoReadMessage(mp.get().value(), &read_buffer[0], | |
345 &num_bytes, nullptr, 0, | |
346 MOJO_READ_MESSAGE_FLAG_NONE)); | |
347 read_buffer.resize(num_bytes); | |
348 ASSERT_EQ(std::string("go 2"), read_buffer); | |
349 | |
350 // After we get it, the child should have written something to the shared | |
351 // buffer. | |
352 static const char kHello[] = "hello"; | |
353 void* buffer; | |
354 CHECK_EQ(MojoMapBuffer(shared_buffer, 0, 100, &buffer, | |
355 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), | |
356 MOJO_RESULT_OK); | |
357 ASSERT_EQ(0, memcmp(buffer, kHello, sizeof(kHello))); | |
358 | |
359 // Now we'll write some stuff to the shared buffer. | |
360 static const char kWorld[] = "world!!!"; | |
361 memcpy(buffer, kWorld, sizeof(kWorld)); | |
362 | |
363 // And send a message to signal that we've written stuff. | |
364 const std::string go3("go 3"); | |
365 ASSERT_EQ(MOJO_RESULT_OK, | |
366 MojoWriteMessage(mp.get().value(), &go3[0], | |
367 go3.size(), nullptr, 0, | |
368 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
369 | |
370 // Wait for |mp| to become readable, which should fail. | |
371 hss = HandleSignalsState(); | |
372 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
373 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
374 MOJO_DEADLINE_INDEFINITE, &hss)); | |
375 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | |
376 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | |
377 | |
378 MojoClose(mp.release().value()); | |
379 | |
380 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | |
381 } | |
382 | |
383 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { | |
384 SimplePlatformSupport platform_support; | |
385 base::MessageLoop message_loop; | |
386 base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); | |
387 test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); | |
388 | |
389 ScopedPlatformHandle client_platform_handle = | |
390 test::MultiprocessTestHelper::client_platform_handle.Pass(); | |
391 CHECK(client_platform_handle.is_valid()); | |
392 ScopedMessagePipeHandle mp = | |
393 CreateMessagePipe(client_platform_handle.Pass()); | |
394 | |
395 HandleSignalsState hss; | |
396 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
397 MOJO_DEADLINE_INDEFINITE, &hss), | |
398 MOJO_RESULT_OK); | |
399 CHECK_EQ(hss.satisfied_signals, | |
400 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | |
401 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | |
402 MOJO_HANDLE_SIGNAL_WRITABLE | | |
403 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
404 | |
405 std::string read_buffer(100, '\0'); | |
406 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); | |
407 MojoHandle handles[255]; // Maximum number to receive. | |
408 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); | |
409 | |
410 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | |
411 &num_bytes, &handles[0], | |
412 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | |
413 MOJO_RESULT_OK); | |
414 MojoClose(mp.release().value()); | |
415 | |
416 read_buffer.resize(num_bytes); | |
417 char hello[32]; | |
418 int num_handles = 0; | |
419 sscanf(read_buffer.c_str(), "%s %d", hello, &num_handles); | |
420 CHECK_EQ(std::string("hello"), std::string(hello)); | |
421 CHECK_GT(num_handles, 0); | |
422 | |
423 for (int i = 0; i < num_handles; ++i) { | |
424 ScopedPlatformHandle h; | |
425 CHECK_EQ(PassWrappedPlatformHandle( | |
426 handles[i], &h), | |
427 MOJO_RESULT_OK); | |
428 CHECK(h.is_valid()); | |
429 MojoClose(handles[i]); | |
430 | |
431 base::ScopedFILE fp(test::FILEFromPlatformHandle(h.Pass(), "r")); | |
432 CHECK(fp); | |
433 std::string fread_buffer(100, '\0'); | |
434 size_t bytes_read = | |
435 fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get()); | |
436 fread_buffer.resize(bytes_read); | |
437 CHECK_EQ(fread_buffer, "world"); | |
438 } | |
439 | |
440 return 0; | |
441 } | |
442 | |
443 class MultiprocessMessagePipeTestWithPipeCount | |
444 : public test::MultiprocessMessagePipeTestBase, | |
445 public testing::WithParamInterface<size_t> {}; | |
446 | |
447 TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { | |
448 base::ScopedTempDir temp_dir; | |
449 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
450 | |
451 helper()->StartChild("CheckPlatformHandleFile"); | |
452 ScopedMessagePipeHandle mp = CreateMessagePipe( | |
453 helper()->server_platform_handle.Pass()); | |
454 | |
455 std::vector<MojoHandle> handles; | |
456 | |
457 size_t pipe_count = GetParam(); | |
458 for (size_t i = 0; i < pipe_count; ++i) { | |
459 base::FilePath unused; | |
460 base::ScopedFILE fp( | |
461 CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); | |
462 const std::string world("world"); | |
463 CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size()); | |
464 fflush(fp.get()); | |
465 rewind(fp.get()); | |
466 MojoHandle handle; | |
467 ASSERT_EQ(CreatePlatformHandleWrapper( | |
468 ScopedPlatformHandle(test::PlatformHandleFromFILE(fp.Pass())), | |
469 &handle), | |
470 MOJO_RESULT_OK); | |
471 handles.push_back(handle); | |
472 } | |
473 | |
474 char message[128]; | |
475 sprintf(message, "hello %d", static_cast<int>(pipe_count)); | |
476 ASSERT_EQ(MOJO_RESULT_OK, | |
477 MojoWriteMessage(mp.get().value(), message, | |
478 strlen(message), | |
479 &handles[0], handles.size(), | |
480 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
481 | |
482 // Wait for it to become readable, which should fail. | |
483 HandleSignalsState hss; | |
484 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
485 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
486 MOJO_DEADLINE_INDEFINITE, &hss)); | |
487 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | |
488 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | |
489 | |
490 MojoClose(mp.release().value()); | |
491 | |
492 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | |
493 } | |
494 | |
495 // Android multi-process tests are not executing the new process. This is flaky. | |
496 #if !defined(OS_ANDROID) | |
497 INSTANTIATE_TEST_CASE_P(PipeCount, | |
498 MultiprocessMessagePipeTestWithPipeCount, | |
499 testing::Values(1u, 128u, 140u)); | |
500 #endif | |
501 | |
502 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckMessagePipe) { | |
503 SimplePlatformSupport platform_support; | |
504 base::MessageLoop message_loop; | |
505 base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); | |
506 test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); | |
507 | |
508 ScopedPlatformHandle client_platform_handle = | |
509 test::MultiprocessTestHelper::client_platform_handle.Pass(); | |
510 CHECK(client_platform_handle.is_valid()); | |
511 | |
512 ScopedMessagePipeHandle mp = | |
513 CreateMessagePipe(client_platform_handle.Pass()); | |
514 | |
515 // Wait for the first message from our parent. | |
516 HandleSignalsState hss; | |
517 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
518 MOJO_DEADLINE_INDEFINITE, &hss), | |
519 MOJO_RESULT_OK); | |
520 // In this test, the parent definitely doesn't close its end of the message | |
521 // pipe before we do. | |
522 CHECK_EQ(hss.satisfied_signals, | |
523 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | |
524 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | |
525 MOJO_HANDLE_SIGNAL_WRITABLE | | |
526 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
527 | |
528 // It should have a message pipe. | |
529 MojoHandle handles[10]; | |
530 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); | |
531 CHECK_EQ(MojoReadMessage(mp.get().value(), nullptr, | |
532 nullptr, &handles[0], | |
533 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | |
534 MOJO_RESULT_OK); | |
535 CHECK_EQ(num_handlers, 1u); | |
536 | |
537 // Read data from the received message pipe. | |
538 CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, | |
539 MOJO_DEADLINE_INDEFINITE, &hss), | |
540 MOJO_RESULT_OK); | |
541 CHECK_EQ(hss.satisfied_signals, | |
542 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | |
543 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | |
544 MOJO_HANDLE_SIGNAL_WRITABLE | | |
545 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
546 | |
547 std::string read_buffer(100, '\0'); | |
548 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
549 CHECK_EQ(MojoReadMessage(handles[0], &read_buffer[0], | |
550 &read_buffer_size, nullptr, | |
551 0, MOJO_READ_MESSAGE_FLAG_NONE), | |
552 MOJO_RESULT_OK); | |
553 read_buffer.resize(read_buffer_size); | |
554 CHECK_EQ(read_buffer, std::string("hello")); | |
555 | |
556 // Now write some data into the message pipe. | |
557 std::string write_buffer = "world"; | |
558 CHECK_EQ(MojoWriteMessage(handles[0], write_buffer.data(), | |
559 write_buffer.size(), | |
560 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE), | |
561 MOJO_RESULT_OK); | |
562 MojoClose(handles[0]); | |
563 return 0; | |
564 } | |
565 | |
566 #if defined(OS_ANDROID) | |
567 // Android multi-process tests are not executing the new process. This is flaky. | |
568 #define MAYBE_MessagePipePassing DISABLED_MessagePipePassing | |
569 #else | |
570 #define MAYBE_MessagePipePassing MessagePipePassing | |
571 #endif | |
572 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipePassing) { | |
573 helper()->StartChild("CheckMessagePipe"); | |
574 | |
575 ScopedMessagePipeHandle mp = | |
576 CreateMessagePipe(helper()->server_platform_handle.Pass()); | |
577 MojoCreateSharedBufferOptions options; | |
578 options.struct_size = sizeof(options); | |
579 options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; | |
580 | |
581 MojoHandle mp1, mp2; | |
582 ASSERT_EQ(MOJO_RESULT_OK, | |
583 MojoCreateMessagePipe(nullptr, &mp1, &mp2)); | |
584 | |
585 // Write a string into one end of the new message pipe and send the other end. | |
586 const std::string hello("hello"); | |
587 ASSERT_EQ(MOJO_RESULT_OK, | |
588 MojoWriteMessage(mp1, &hello[0], hello.size(), nullptr, 0, | |
589 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
590 ASSERT_EQ(MOJO_RESULT_OK, | |
591 MojoWriteMessage(mp.get().value(), nullptr, 0, &mp2, 1, | |
592 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
593 | |
594 // Wait for a message from the child. | |
595 HandleSignalsState hss; | |
596 ASSERT_EQ(MOJO_RESULT_OK, | |
597 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | |
598 MOJO_DEADLINE_INDEFINITE, &hss)); | |
599 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
600 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
601 | |
602 std::string read_buffer(100, '\0'); | |
603 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
604 CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], | |
605 &read_buffer_size, nullptr, | |
606 0, MOJO_READ_MESSAGE_FLAG_NONE), | |
607 MOJO_RESULT_OK); | |
608 read_buffer.resize(read_buffer_size); | |
609 CHECK_EQ(read_buffer, std::string("world")); | |
610 | |
611 MojoClose(mp1); | |
612 MojoClose(mp.release().value()); | |
613 | |
614 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | |
615 } | |
616 | |
617 // Like above test, but verifies passing the other MP handle works as well. | |
618 #if defined(OS_ANDROID) | |
619 // Android multi-process tests are not executing the new process. This is flaky. | |
620 #define MAYBE_MessagePipeTwoPassing DISABLED_MessagePipeTwoPassing | |
621 #else | |
622 #define MAYBE_MessagePipeTwoPassing MessagePipeTwoPassing | |
623 #endif | |
624 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipeTwoPassing) { | |
625 helper()->StartChild("CheckMessagePipe"); | |
626 | |
627 ScopedMessagePipeHandle mp = | |
628 CreateMessagePipe(helper()->server_platform_handle.Pass()); | |
629 | |
630 MojoHandle mp1, mp2; | |
631 ASSERT_EQ(MOJO_RESULT_OK, | |
632 MojoCreateMessagePipe(nullptr, &mp2, &mp1)); | |
633 | |
634 // Write a string into one end of the new message pipe and send the other end. | |
635 const std::string hello("hello"); | |
636 ASSERT_EQ(MOJO_RESULT_OK, | |
637 MojoWriteMessage(mp1, &hello[0], hello.size(), nullptr, 0, | |
638 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
639 ASSERT_EQ(MOJO_RESULT_OK, | |
640 MojoWriteMessage(mp.get().value(), nullptr, 0, &mp2, 1, | |
641 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
642 | |
643 // Wait for a message from the child. | |
644 HandleSignalsState hss; | |
645 ASSERT_EQ(MOJO_RESULT_OK, | |
646 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | |
647 MOJO_DEADLINE_INDEFINITE, &hss)); | |
648 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
649 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
650 | |
651 std::string read_buffer(100, '\0'); | |
652 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
653 CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], | |
654 &read_buffer_size, nullptr, | |
655 0, MOJO_READ_MESSAGE_FLAG_NONE), | |
656 MOJO_RESULT_OK); | |
657 read_buffer.resize(read_buffer_size); | |
658 CHECK_EQ(read_buffer, std::string("world")); | |
659 | |
660 MojoClose(mp.release().value()); | |
661 | |
662 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | |
663 } | |
664 | |
665 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(DataPipeConsumer) { | |
666 SimplePlatformSupport platform_support; | |
667 base::MessageLoop message_loop; | |
668 base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); | |
669 test::ScopedIPCSupport ipc_support(test_io_thread.task_runner()); | |
670 | |
671 ScopedPlatformHandle client_platform_handle = | |
672 test::MultiprocessTestHelper::client_platform_handle.Pass(); | |
673 CHECK(client_platform_handle.is_valid()); | |
674 | |
675 ScopedMessagePipeHandle mp = | |
676 CreateMessagePipe(client_platform_handle.Pass()); | |
677 | |
678 // Wait for the first message from our parent. | |
679 HandleSignalsState hss; | |
680 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
681 MOJO_DEADLINE_INDEFINITE, &hss), | |
682 MOJO_RESULT_OK); | |
683 // In this test, the parent definitely doesn't close its end of the message | |
684 // pipe before we do. | |
685 CHECK_EQ(hss.satisfied_signals, | |
686 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | |
687 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | |
688 MOJO_HANDLE_SIGNAL_WRITABLE | | |
689 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
690 | |
691 // It should have a message pipe. | |
692 MojoHandle handles[10]; | |
693 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); | |
694 CHECK_EQ(MojoReadMessage(mp.get().value(), nullptr, | |
695 nullptr, &handles[0], | |
696 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | |
697 MOJO_RESULT_OK); | |
698 CHECK_EQ(num_handlers, 1u); | |
699 | |
700 // Read data from the received message pipe. | |
701 CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, | |
702 MOJO_DEADLINE_INDEFINITE, &hss), | |
703 MOJO_RESULT_OK); | |
704 CHECK_EQ(hss.satisfied_signals, | |
705 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | |
706 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | |
707 MOJO_HANDLE_SIGNAL_WRITABLE | | |
708 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
709 | |
710 std::string read_buffer(100, '\0'); | |
711 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
712 CHECK_EQ(MojoReadMessage(handles[0], &read_buffer[0], | |
713 &read_buffer_size, nullptr, | |
714 0, MOJO_READ_MESSAGE_FLAG_NONE), | |
715 MOJO_RESULT_OK); | |
716 read_buffer.resize(read_buffer_size); | |
717 CHECK_EQ(read_buffer, std::string("hello")); | |
718 | |
719 // Now write some data into the message pipe. | |
720 std::string write_buffer = "world"; | |
721 CHECK_EQ(MojoWriteMessage(handles[0], write_buffer.data(), | |
722 write_buffer.size(), | |
723 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE), | |
724 MOJO_RESULT_OK); | |
725 MojoClose(handles[0]); | |
726 return 0; | |
727 } | |
728 | |
729 #if defined(OS_ANDROID) | |
730 // Android multi-process tests are not executing the new process. This is flaky. | |
731 #define MAYBE_DataPipeConsumer DISABLED_DataPipeConsumer | |
732 #else | |
733 #define MAYBE_DataPipeConsumer DataPipeConsumer | |
734 #endif | |
735 TEST_F(MultiprocessMessagePipeTest, MAYBE_DataPipeConsumer) { | |
736 helper()->StartChild("DataPipeConsumer"); | |
737 | |
738 ScopedMessagePipeHandle mp = | |
739 CreateMessagePipe(helper()->server_platform_handle.Pass()); | |
740 MojoCreateSharedBufferOptions options; | |
741 options.struct_size = sizeof(options); | |
742 options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; | |
743 | |
744 MojoHandle mp1, mp2; | |
745 ASSERT_EQ(MOJO_RESULT_OK, | |
746 MojoCreateMessagePipe(nullptr, &mp2, &mp1)); | |
747 | |
748 // Write a string into one end of the new message pipe and send the other end. | |
749 const std::string hello("hello"); | |
750 ASSERT_EQ(MOJO_RESULT_OK, | |
751 MojoWriteMessage(mp1, &hello[0], hello.size(), nullptr, 0, | |
752 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
753 ASSERT_EQ(MOJO_RESULT_OK, | |
754 MojoWriteMessage(mp.get().value(), nullptr, 0, &mp2, 1, | |
755 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
756 | |
757 // Wait for a message from the child. | |
758 HandleSignalsState hss; | |
759 ASSERT_EQ(MOJO_RESULT_OK, | |
760 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | |
761 MOJO_DEADLINE_INDEFINITE, &hss)); | |
762 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
763 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
764 | |
765 std::string read_buffer(100, '\0'); | |
766 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
767 CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], | |
768 &read_buffer_size, nullptr, | |
769 0, MOJO_READ_MESSAGE_FLAG_NONE), | |
770 MOJO_RESULT_OK); | |
771 read_buffer.resize(read_buffer_size); | |
772 CHECK_EQ(read_buffer, std::string("world")); | |
773 | |
774 MojoClose(mp1); | |
775 MojoClose(mp.release().value()); | |
776 | |
777 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | |
778 } | |
779 | |
780 } // namespace | |
781 } // namespace edk | |
782 } // namespace mojo | |
OLD | NEW |