Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: mojo/edk/system/multiprocess_message_pipe_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698