OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 "mojo/edk/embedder/embedder.h" | |
6 | |
7 #include <string.h> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/location.h" | |
11 #include "base/logging.h" | |
12 #include "base/macros.h" | |
13 #include "base/message_loop/message_loop.h" | |
14 #include "base/synchronization/waitable_event.h" | |
15 #include "base/test/test_io_thread.h" | |
16 #include "base/test/test_timeouts.h" | |
17 #include "mojo/edk/embedder/platform_channel_pair.h" | |
18 #include "mojo/edk/embedder/test_embedder.h" | |
19 #include "mojo/edk/system/test_utils.h" | |
20 #include "mojo/edk/test/multiprocess_test_helper.h" | |
21 #include "mojo/public/c/system/core.h" | |
22 #include "testing/gtest/include/gtest/gtest.h" | |
23 | |
24 namespace mojo { | |
25 namespace embedder { | |
26 namespace { | |
27 | |
28 const MojoHandleSignals kSignalReadadableWritable = | |
29 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; | |
30 | |
31 const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | | |
32 MOJO_HANDLE_SIGNAL_WRITABLE | | |
33 MOJO_HANDLE_SIGNAL_PEER_CLOSED; | |
34 | |
35 class ScopedTestChannel { | |
36 public: | |
37 // Creates a channel that lives on a given I/O thread (determined by the given | |
38 // |TaskRunner|) attached to the given |platform_handle|. After construction, | |
39 // |bootstrap_message_pipe()| gives the Mojo handle for the bootstrap message | |
40 // pipe on this channel; it is up to the caller to close this handle. | |
41 // Note: The I/O thread must outlive this object (and its message loop must | |
42 // continue pumping messages while this object is alive). | |
43 ScopedTestChannel(scoped_refptr<base::TaskRunner> io_thread_task_runner, | |
44 ScopedPlatformHandle platform_handle) | |
45 : io_thread_task_runner_(io_thread_task_runner), | |
46 bootstrap_message_pipe_(MOJO_HANDLE_INVALID), | |
47 did_create_channel_event_(true, false), | |
48 channel_info_(nullptr) { | |
49 bootstrap_message_pipe_ = | |
50 CreateChannel(platform_handle.Pass(), io_thread_task_runner_, | |
51 base::Bind(&ScopedTestChannel::DidCreateChannel, | |
52 base::Unretained(this)), | |
53 nullptr) | |
54 .release() | |
55 .value(); | |
56 CHECK_NE(bootstrap_message_pipe_, MOJO_HANDLE_INVALID); | |
57 } | |
58 | |
59 // Destructor: Shuts down the channel. (As noted above, for this to happen, | |
60 // the I/O thread must be alive and pumping messages.) | |
61 ~ScopedTestChannel() { DestroyChannel(channel_info_); } | |
62 | |
63 // Waits for channel creation to be completed. | |
64 void WaitForChannelCreationCompletion() { did_create_channel_event_.Wait(); } | |
65 | |
66 MojoHandle bootstrap_message_pipe() const { return bootstrap_message_pipe_; } | |
67 | |
68 // Call only after |WaitForChannelCreationCompletion()|. Use only to check | |
69 // that it's not null. | |
70 const ChannelInfo* channel_info() const { return channel_info_; } | |
71 | |
72 private: | |
73 void DidCreateChannel(ChannelInfo* channel_info) { | |
74 CHECK(channel_info); | |
75 CHECK(!channel_info_); | |
76 channel_info_ = channel_info; | |
77 did_create_channel_event_.Signal(); | |
78 } | |
79 | |
80 scoped_refptr<base::TaskRunner> io_thread_task_runner_; | |
81 | |
82 // Valid from creation until whenever it gets closed (by the "owner" of this | |
83 // object). | |
84 // Note: We don't want use the C++ wrappers here, since we want to test the | |
85 // API at the lowest level. | |
86 MojoHandle bootstrap_message_pipe_; | |
87 | |
88 // Set after channel creation has been completed (i.e., the callback to | |
89 // |CreateChannel()| has been called). | |
90 base::WaitableEvent did_create_channel_event_; | |
91 | |
92 // Valid after channel creation completion until destruction. | |
93 ChannelInfo* channel_info_; | |
94 | |
95 DISALLOW_COPY_AND_ASSIGN(ScopedTestChannel); | |
96 }; | |
97 | |
98 class EmbedderTest : public testing::Test { | |
99 public: | |
100 EmbedderTest() : test_io_thread_(base::TestIOThread::kAutoStart) {} | |
101 ~EmbedderTest() override {} | |
102 | |
103 protected: | |
104 base::TestIOThread* test_io_thread() { return &test_io_thread_; } | |
105 | |
106 private: | |
107 base::TestIOThread test_io_thread_; | |
108 | |
109 DISALLOW_COPY_AND_ASSIGN(EmbedderTest); | |
110 }; | |
111 | |
112 TEST_F(EmbedderTest, ChannelsBasic) { | |
113 mojo::embedder::test::InitWithSimplePlatformSupport(); | |
114 | |
115 { | |
116 PlatformChannelPair channel_pair; | |
117 ScopedTestChannel server_channel(test_io_thread()->task_runner(), | |
118 channel_pair.PassServerHandle()); | |
119 MojoHandle server_mp = server_channel.bootstrap_message_pipe(); | |
120 EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); | |
121 ScopedTestChannel client_channel(test_io_thread()->task_runner(), | |
122 channel_pair.PassClientHandle()); | |
123 MojoHandle client_mp = client_channel.bootstrap_message_pipe(); | |
124 EXPECT_NE(client_mp, MOJO_HANDLE_INVALID); | |
125 | |
126 // We can write to a message pipe handle immediately. | |
127 const char kHello[] = "hello"; | |
128 EXPECT_EQ(MOJO_RESULT_OK, | |
129 MojoWriteMessage(server_mp, kHello, | |
130 static_cast<uint32_t>(sizeof(kHello)), nullptr, | |
131 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
132 | |
133 // Now wait for the other side to become readable. | |
134 MojoHandleSignalsState state; | |
135 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, | |
136 MOJO_DEADLINE_INDEFINITE, &state)); | |
137 EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); | |
138 EXPECT_EQ(kSignalAll, state.satisfiable_signals); | |
139 | |
140 char buffer[1000] = {}; | |
141 uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
142 EXPECT_EQ(MOJO_RESULT_OK, | |
143 MojoReadMessage(client_mp, buffer, &num_bytes, nullptr, nullptr, | |
144 MOJO_READ_MESSAGE_FLAG_NONE)); | |
145 EXPECT_EQ(sizeof(kHello), num_bytes); | |
146 EXPECT_STREQ(kHello, buffer); | |
147 | |
148 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); | |
149 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); | |
150 | |
151 // By this point, these waits should basically be no-ops (since we've waited | |
152 // for the client message pipe to become readable, which implies that both | |
153 // the server and client channels were completely created). | |
154 server_channel.WaitForChannelCreationCompletion(); | |
155 client_channel.WaitForChannelCreationCompletion(); | |
156 EXPECT_TRUE(server_channel.channel_info()); | |
157 EXPECT_TRUE(client_channel.channel_info()); | |
158 } | |
159 | |
160 EXPECT_TRUE(test::Shutdown()); | |
161 } | |
162 | |
163 class TestAsyncWaiter { | |
164 public: | |
165 TestAsyncWaiter() : event_(true, false), wait_result_(MOJO_RESULT_UNKNOWN) {} | |
166 | |
167 void Awake(MojoResult result) { | |
168 base::AutoLock l(wait_result_lock_); | |
169 wait_result_ = result; | |
170 event_.Signal(); | |
171 } | |
172 | |
173 bool TryWait() { return event_.TimedWait(TestTimeouts::action_timeout()); } | |
174 | |
175 MojoResult wait_result() const { | |
176 base::AutoLock l(wait_result_lock_); | |
177 return wait_result_; | |
178 } | |
179 | |
180 private: | |
181 base::WaitableEvent event_; | |
182 | |
183 mutable base::Lock wait_result_lock_; | |
184 MojoResult wait_result_; | |
185 | |
186 DISALLOW_COPY_AND_ASSIGN(TestAsyncWaiter); | |
187 }; | |
188 | |
189 void WriteHello(MessagePipeHandle pipe) { | |
190 static const char kHello[] = "hello"; | |
191 CHECK_EQ(MOJO_RESULT_OK, | |
192 WriteMessageRaw(pipe, kHello, static_cast<uint32_t>(sizeof(kHello)), | |
193 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
194 } | |
195 | |
196 void CloseScopedHandle(ScopedMessagePipeHandle handle) { | |
197 // Do nothing and the destructor will close it. | |
198 } | |
199 | |
200 TEST_F(EmbedderTest, AsyncWait) { | |
201 mojo::embedder::test::InitWithSimplePlatformSupport(); | |
202 | |
203 { | |
204 ScopedMessagePipeHandle client_mp; | |
205 ScopedMessagePipeHandle server_mp; | |
206 EXPECT_EQ(MOJO_RESULT_OK, | |
207 mojo::CreateMessagePipe(nullptr, &client_mp, &server_mp)); | |
208 | |
209 TestAsyncWaiter waiter; | |
210 EXPECT_EQ(MOJO_RESULT_OK, | |
211 AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
212 base::Bind(&TestAsyncWaiter::Awake, | |
213 base::Unretained(&waiter)))); | |
214 | |
215 test_io_thread()->task_runner()->PostTask( | |
216 FROM_HERE, base::Bind(&WriteHello, server_mp.get())); | |
217 EXPECT_TRUE(waiter.TryWait()); | |
218 EXPECT_EQ(MOJO_RESULT_OK, waiter.wait_result()); | |
219 | |
220 // If message is in the queue, it does't allow us to wait. | |
221 TestAsyncWaiter waiter_that_doesnt_wait; | |
222 EXPECT_EQ( | |
223 MOJO_RESULT_ALREADY_EXISTS, | |
224 AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
225 base::Bind(&TestAsyncWaiter::Awake, | |
226 base::Unretained(&waiter_that_doesnt_wait)))); | |
227 | |
228 char buffer[1000]; | |
229 uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
230 CHECK_EQ(MOJO_RESULT_OK, | |
231 ReadMessageRaw(client_mp.get(), buffer, &num_bytes, nullptr, | |
232 nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); | |
233 | |
234 TestAsyncWaiter unsatisfiable_waiter; | |
235 EXPECT_EQ(MOJO_RESULT_OK, | |
236 AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
237 base::Bind(&TestAsyncWaiter::Awake, | |
238 base::Unretained(&unsatisfiable_waiter)))); | |
239 | |
240 test_io_thread()->task_runner()->PostTask( | |
241 FROM_HERE, | |
242 base::Bind(&CloseScopedHandle, base::Passed(server_mp.Pass()))); | |
243 | |
244 EXPECT_TRUE(unsatisfiable_waiter.TryWait()); | |
245 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
246 unsatisfiable_waiter.wait_result()); | |
247 } | |
248 | |
249 EXPECT_TRUE(test::Shutdown()); | |
250 } | |
251 | |
252 TEST_F(EmbedderTest, ChannelsHandlePassing) { | |
253 mojo::embedder::test::InitWithSimplePlatformSupport(); | |
254 | |
255 { | |
256 PlatformChannelPair channel_pair; | |
257 ScopedTestChannel server_channel(test_io_thread()->task_runner(), | |
258 channel_pair.PassServerHandle()); | |
259 MojoHandle server_mp = server_channel.bootstrap_message_pipe(); | |
260 EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); | |
261 ScopedTestChannel client_channel(test_io_thread()->task_runner(), | |
262 channel_pair.PassClientHandle()); | |
263 MojoHandle client_mp = client_channel.bootstrap_message_pipe(); | |
264 EXPECT_NE(client_mp, MOJO_HANDLE_INVALID); | |
265 | |
266 MojoHandle h0, h1; | |
267 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &h0, &h1)); | |
268 | |
269 // Write a message to |h0| (attaching nothing). | |
270 const char kHello[] = "hello"; | |
271 EXPECT_EQ( | |
272 MOJO_RESULT_OK, | |
273 MojoWriteMessage(h0, kHello, static_cast<uint32_t>(sizeof(kHello)), | |
274 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
275 | |
276 // Write one message to |server_mp|, attaching |h1|. | |
277 const char kWorld[] = "world!!!"; | |
278 EXPECT_EQ(MOJO_RESULT_OK, | |
279 MojoWriteMessage(server_mp, kWorld, | |
280 static_cast<uint32_t>(sizeof(kWorld)), &h1, 1, | |
281 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
282 h1 = MOJO_HANDLE_INVALID; | |
283 | |
284 // Write another message to |h0|. | |
285 const char kFoo[] = "foo"; | |
286 EXPECT_EQ(MOJO_RESULT_OK, | |
287 MojoWriteMessage(h0, kFoo, static_cast<uint32_t>(sizeof(kFoo)), | |
288 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
289 | |
290 // Wait for |client_mp| to become readable. | |
291 MojoHandleSignalsState state; | |
292 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, | |
293 MOJO_DEADLINE_INDEFINITE, &state)); | |
294 EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); | |
295 EXPECT_EQ(kSignalAll, state.satisfiable_signals); | |
296 | |
297 // Read a message from |client_mp|. | |
298 char buffer[1000] = {}; | |
299 uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
300 MojoHandle handles[10] = {}; | |
301 uint32_t num_handles = arraysize(handles); | |
302 EXPECT_EQ(MOJO_RESULT_OK, | |
303 MojoReadMessage(client_mp, buffer, &num_bytes, handles, | |
304 &num_handles, MOJO_READ_MESSAGE_FLAG_NONE)); | |
305 EXPECT_EQ(sizeof(kWorld), num_bytes); | |
306 EXPECT_STREQ(kWorld, buffer); | |
307 EXPECT_EQ(1u, num_handles); | |
308 EXPECT_NE(handles[0], MOJO_HANDLE_INVALID); | |
309 h1 = handles[0]; | |
310 | |
311 // Wait for |h1| to become readable. | |
312 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h1, MOJO_HANDLE_SIGNAL_READABLE, | |
313 MOJO_DEADLINE_INDEFINITE, &state)); | |
314 EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); | |
315 EXPECT_EQ(kSignalAll, state.satisfiable_signals); | |
316 | |
317 // Read a message from |h1|. | |
318 memset(buffer, 0, sizeof(buffer)); | |
319 num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
320 memset(handles, 0, sizeof(handles)); | |
321 num_handles = arraysize(handles); | |
322 EXPECT_EQ(MOJO_RESULT_OK, | |
323 MojoReadMessage(h1, buffer, &num_bytes, handles, &num_handles, | |
324 MOJO_READ_MESSAGE_FLAG_NONE)); | |
325 EXPECT_EQ(sizeof(kHello), num_bytes); | |
326 EXPECT_STREQ(kHello, buffer); | |
327 EXPECT_EQ(0u, num_handles); | |
328 | |
329 // Wait for |h1| to become readable (again). | |
330 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h1, MOJO_HANDLE_SIGNAL_READABLE, | |
331 MOJO_DEADLINE_INDEFINITE, &state)); | |
332 EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); | |
333 EXPECT_EQ(kSignalAll, state.satisfiable_signals); | |
334 | |
335 // Read the second message from |h1|. | |
336 memset(buffer, 0, sizeof(buffer)); | |
337 num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
338 EXPECT_EQ(MOJO_RESULT_OK, | |
339 MojoReadMessage(h1, buffer, &num_bytes, nullptr, nullptr, | |
340 MOJO_READ_MESSAGE_FLAG_NONE)); | |
341 EXPECT_EQ(sizeof(kFoo), num_bytes); | |
342 EXPECT_STREQ(kFoo, buffer); | |
343 | |
344 // Write a message to |h1|. | |
345 const char kBarBaz[] = "barbaz"; | |
346 EXPECT_EQ( | |
347 MOJO_RESULT_OK, | |
348 MojoWriteMessage(h1, kBarBaz, static_cast<uint32_t>(sizeof(kBarBaz)), | |
349 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
350 | |
351 // Wait for |h0| to become readable. | |
352 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h0, MOJO_HANDLE_SIGNAL_READABLE, | |
353 MOJO_DEADLINE_INDEFINITE, &state)); | |
354 EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); | |
355 EXPECT_EQ(kSignalAll, state.satisfiable_signals); | |
356 | |
357 // Read a message from |h0|. | |
358 memset(buffer, 0, sizeof(buffer)); | |
359 num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
360 EXPECT_EQ(MOJO_RESULT_OK, | |
361 MojoReadMessage(h0, buffer, &num_bytes, nullptr, nullptr, | |
362 MOJO_READ_MESSAGE_FLAG_NONE)); | |
363 EXPECT_EQ(sizeof(kBarBaz), num_bytes); | |
364 EXPECT_STREQ(kBarBaz, buffer); | |
365 | |
366 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); | |
367 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); | |
368 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0)); | |
369 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1)); | |
370 | |
371 server_channel.WaitForChannelCreationCompletion(); | |
372 client_channel.WaitForChannelCreationCompletion(); | |
373 EXPECT_TRUE(server_channel.channel_info()); | |
374 EXPECT_TRUE(client_channel.channel_info()); | |
375 } | |
376 | |
377 EXPECT_TRUE(test::Shutdown()); | |
378 } | |
379 | |
380 // The sequence of messages sent is: | |
381 // server_mp client_mp mp0 mp1 mp2 mp3 | |
382 // 1. "hello" | |
383 // 2. "world!" | |
384 // 3. "FOO" | |
385 // 4. "Bar"+mp1 | |
386 // 5. (close) | |
387 // 6. (close) | |
388 // 7. "baz" | |
389 // 8. (closed) | |
390 // 9. "quux"+mp2 | |
391 // 10. (close) | |
392 // 11. (wait/cl.) | |
393 // 12. (wait/cl.) | |
394 | |
395 #if defined(OS_ANDROID) | |
396 // Android multi-process tests are not executing the new process. This is flaky. | |
397 #define MAYBE_MultiprocessChannels DISABLED_MultiprocessChannels | |
398 #else | |
399 #define MAYBE_MultiprocessChannels MultiprocessChannels | |
400 #endif // defined(OS_ANDROID) | |
401 TEST_F(EmbedderTest, MAYBE_MultiprocessChannels) { | |
402 mojo::embedder::test::InitWithSimplePlatformSupport(); | |
403 mojo::test::MultiprocessTestHelper multiprocess_test_helper; | |
404 multiprocess_test_helper.StartChild("MultiprocessChannelsClient"); | |
405 | |
406 { | |
407 ScopedTestChannel server_channel( | |
408 test_io_thread()->task_runner(), | |
409 multiprocess_test_helper.server_platform_handle.Pass()); | |
410 MojoHandle server_mp = server_channel.bootstrap_message_pipe(); | |
411 EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); | |
412 server_channel.WaitForChannelCreationCompletion(); | |
413 EXPECT_TRUE(server_channel.channel_info()); | |
414 | |
415 // 1. Write a message to |server_mp| (attaching nothing). | |
416 const char kHello[] = "hello"; | |
417 EXPECT_EQ(MOJO_RESULT_OK, | |
418 MojoWriteMessage(server_mp, kHello, | |
419 static_cast<uint32_t>(sizeof(kHello)), nullptr, | |
420 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
421 | |
422 // TODO(vtl): If the scope were ended immediately here (maybe after closing | |
423 // |server_mp|), we die with a fatal error in |Channel::HandleLocalError()|. | |
424 | |
425 // 2. Read a message from |server_mp|. | |
426 MojoHandleSignalsState state; | |
427 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(server_mp, MOJO_HANDLE_SIGNAL_READABLE, | |
428 MOJO_DEADLINE_INDEFINITE, &state)); | |
429 EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); | |
430 EXPECT_EQ(kSignalAll, state.satisfiable_signals); | |
431 | |
432 char buffer[1000] = {}; | |
433 uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
434 EXPECT_EQ(MOJO_RESULT_OK, | |
435 MojoReadMessage(server_mp, buffer, &num_bytes, nullptr, nullptr, | |
436 MOJO_READ_MESSAGE_FLAG_NONE)); | |
437 const char kWorld[] = "world!"; | |
438 EXPECT_EQ(sizeof(kWorld), num_bytes); | |
439 EXPECT_STREQ(kWorld, buffer); | |
440 | |
441 // Create a new message pipe (endpoints |mp0| and |mp1|). | |
442 MojoHandle mp0, mp1; | |
443 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp0, &mp1)); | |
444 | |
445 // 3. Write something to |mp0|. | |
446 const char kFoo[] = "FOO"; | |
447 EXPECT_EQ(MOJO_RESULT_OK, | |
448 MojoWriteMessage(mp0, kFoo, static_cast<uint32_t>(sizeof(kFoo)), | |
449 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
450 | |
451 // 4. Write a message to |server_mp|, attaching |mp1|. | |
452 const char kBar[] = "Bar"; | |
453 EXPECT_EQ( | |
454 MOJO_RESULT_OK, | |
455 MojoWriteMessage(server_mp, kBar, static_cast<uint32_t>(sizeof(kBar)), | |
456 &mp1, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
457 mp1 = MOJO_HANDLE_INVALID; | |
458 | |
459 // 5. Close |server_mp|. | |
460 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); | |
461 | |
462 // 9. Read a message from |mp0|, which should have |mp2| attached. | |
463 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp0, MOJO_HANDLE_SIGNAL_READABLE, | |
464 MOJO_DEADLINE_INDEFINITE, &state)); | |
465 EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); | |
466 EXPECT_EQ(kSignalAll, state.satisfiable_signals); | |
467 | |
468 memset(buffer, 0, sizeof(buffer)); | |
469 num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
470 MojoHandle mp2 = MOJO_HANDLE_INVALID; | |
471 uint32_t num_handles = 1; | |
472 EXPECT_EQ(MOJO_RESULT_OK, | |
473 MojoReadMessage(mp0, buffer, &num_bytes, &mp2, &num_handles, | |
474 MOJO_READ_MESSAGE_FLAG_NONE)); | |
475 const char kQuux[] = "quux"; | |
476 EXPECT_EQ(sizeof(kQuux), num_bytes); | |
477 EXPECT_STREQ(kQuux, buffer); | |
478 EXPECT_EQ(1u, num_handles); | |
479 EXPECT_NE(mp2, MOJO_HANDLE_INVALID); | |
480 | |
481 // 7. Read a message from |mp2|. | |
482 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, | |
483 MOJO_DEADLINE_INDEFINITE, &state)); | |
484 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, | |
485 state.satisfied_signals); | |
486 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, | |
487 state.satisfiable_signals); | |
488 | |
489 memset(buffer, 0, sizeof(buffer)); | |
490 num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
491 EXPECT_EQ(MOJO_RESULT_OK, | |
492 MojoReadMessage(mp2, buffer, &num_bytes, nullptr, nullptr, | |
493 MOJO_READ_MESSAGE_FLAG_NONE)); | |
494 const char kBaz[] = "baz"; | |
495 EXPECT_EQ(sizeof(kBaz), num_bytes); | |
496 EXPECT_STREQ(kBaz, buffer); | |
497 | |
498 // 10. Close |mp0|. | |
499 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp0)); | |
500 | |
501 // 12. Wait on |mp2| (which should eventually fail) and then close it. | |
502 // TODO(vtl): crbug.com/351768 | |
503 #if 0 | |
504 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
505 MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, | |
506 MOJO_DEADLINE_INDEFINITE, | |
507 &state)); | |
508 EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals); | |
509 EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfiable_signals); | |
510 #endif | |
511 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp2)); | |
512 } | |
513 | |
514 EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown()); | |
515 EXPECT_TRUE(test::Shutdown()); | |
516 } | |
517 | |
518 MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { | |
519 ScopedPlatformHandle client_platform_handle = | |
520 mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); | |
521 EXPECT_TRUE(client_platform_handle.is_valid()); | |
522 | |
523 base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); | |
524 mojo::embedder::test::InitWithSimplePlatformSupport(); | |
525 | |
526 { | |
527 ScopedTestChannel client_channel(test_io_thread.task_runner(), | |
528 client_platform_handle.Pass()); | |
529 MojoHandle client_mp = client_channel.bootstrap_message_pipe(); | |
530 EXPECT_NE(client_mp, MOJO_HANDLE_INVALID); | |
531 client_channel.WaitForChannelCreationCompletion(); | |
532 CHECK(client_channel.channel_info() != nullptr); | |
533 | |
534 // 1. Read the first message from |client_mp|. | |
535 MojoHandleSignalsState state; | |
536 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, | |
537 MOJO_DEADLINE_INDEFINITE, &state)); | |
538 EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); | |
539 EXPECT_EQ(kSignalAll, state.satisfiable_signals); | |
540 | |
541 char buffer[1000] = {}; | |
542 uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
543 EXPECT_EQ(MOJO_RESULT_OK, | |
544 MojoReadMessage(client_mp, buffer, &num_bytes, nullptr, nullptr, | |
545 MOJO_READ_MESSAGE_FLAG_NONE)); | |
546 const char kHello[] = "hello"; | |
547 EXPECT_EQ(sizeof(kHello), num_bytes); | |
548 EXPECT_STREQ(kHello, buffer); | |
549 | |
550 // 2. Write a message to |client_mp| (attaching nothing). | |
551 const char kWorld[] = "world!"; | |
552 EXPECT_EQ(MOJO_RESULT_OK, | |
553 MojoWriteMessage(client_mp, kWorld, | |
554 static_cast<uint32_t>(sizeof(kWorld)), nullptr, | |
555 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
556 | |
557 // 4. Read a message from |client_mp|, which should have |mp1| attached. | |
558 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, | |
559 MOJO_DEADLINE_INDEFINITE, &state)); | |
560 // The other end of the handle may or may not be closed at this point, so we | |
561 // can't test MOJO_HANDLE_SIGNAL_WRITABLE or MOJO_HANDLE_SIGNAL_PEER_CLOSED. | |
562 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, | |
563 state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); | |
564 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, | |
565 state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE); | |
566 // TODO(vtl): If the scope were to end here (and |client_mp| closed), we'd | |
567 // die (again due to |Channel::HandleLocalError()|). | |
568 memset(buffer, 0, sizeof(buffer)); | |
569 num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
570 MojoHandle mp1 = MOJO_HANDLE_INVALID; | |
571 uint32_t num_handles = 1; | |
572 EXPECT_EQ(MOJO_RESULT_OK, | |
573 MojoReadMessage(client_mp, buffer, &num_bytes, &mp1, &num_handles, | |
574 MOJO_READ_MESSAGE_FLAG_NONE)); | |
575 const char kBar[] = "Bar"; | |
576 EXPECT_EQ(sizeof(kBar), num_bytes); | |
577 EXPECT_STREQ(kBar, buffer); | |
578 EXPECT_EQ(1u, num_handles); | |
579 EXPECT_NE(mp1, MOJO_HANDLE_INVALID); | |
580 // TODO(vtl): If the scope were to end here (and the two handles closed), | |
581 // we'd die due to |Channel::RunRemoteMessagePipeEndpoint()| not handling | |
582 // write errors (assuming the parent had closed the pipe). | |
583 | |
584 // 6. Close |client_mp|. | |
585 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); | |
586 | |
587 // Create a new message pipe (endpoints |mp2| and |mp3|). | |
588 MojoHandle mp2, mp3; | |
589 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp2, &mp3)); | |
590 | |
591 // 7. Write a message to |mp3|. | |
592 const char kBaz[] = "baz"; | |
593 EXPECT_EQ(MOJO_RESULT_OK, | |
594 MojoWriteMessage(mp3, kBaz, static_cast<uint32_t>(sizeof(kBaz)), | |
595 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
596 | |
597 // 8. Close |mp3|. | |
598 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp3)); | |
599 | |
600 // 9. Write a message to |mp1|, attaching |mp2|. | |
601 const char kQuux[] = "quux"; | |
602 EXPECT_EQ(MOJO_RESULT_OK, | |
603 MojoWriteMessage(mp1, kQuux, static_cast<uint32_t>(sizeof(kQuux)), | |
604 &mp2, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
605 mp2 = MOJO_HANDLE_INVALID; | |
606 | |
607 // 3. Read a message from |mp1|. | |
608 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | |
609 MOJO_DEADLINE_INDEFINITE, &state)); | |
610 EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); | |
611 EXPECT_EQ(kSignalAll, state.satisfiable_signals); | |
612 | |
613 memset(buffer, 0, sizeof(buffer)); | |
614 num_bytes = static_cast<uint32_t>(sizeof(buffer)); | |
615 EXPECT_EQ(MOJO_RESULT_OK, | |
616 MojoReadMessage(mp1, buffer, &num_bytes, nullptr, nullptr, | |
617 MOJO_READ_MESSAGE_FLAG_NONE)); | |
618 const char kFoo[] = "FOO"; | |
619 EXPECT_EQ(sizeof(kFoo), num_bytes); | |
620 EXPECT_STREQ(kFoo, buffer); | |
621 | |
622 // 11. Wait on |mp1| (which should eventually fail) and then close it. | |
623 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
624 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | |
625 MOJO_DEADLINE_INDEFINITE, &state)); | |
626 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); | |
627 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); | |
628 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp1)); | |
629 } | |
630 | |
631 EXPECT_TRUE(test::Shutdown()); | |
632 } | |
633 | |
634 // TODO(vtl): Test immediate write & close. | |
635 // TODO(vtl): Test broken-connection cases. | |
636 | |
637 } // namespace | |
638 } // namespace embedder | |
639 } // namespace mojo | |
OLD | NEW |