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 <stdint.h> | |
6 #include <stdio.h> | |
7 #include <string.h> | |
8 | |
9 #include <vector> | |
10 | |
11 #include "base/bind.h" | |
12 #include "base/files/file_path.h" | |
13 #include "base/files/file_util.h" | |
14 #include "base/files/scoped_file.h" | |
15 #include "base/files/scoped_temp_dir.h" | |
16 #include "base/location.h" | |
17 #include "base/logging.h" | |
18 #include "base/macros.h" | |
19 #include "base/message_loop/message_loop.h" | |
20 #include "base/test/test_io_thread.h" | |
21 #include "base/threading/platform_thread.h" // For |Sleep()|. | |
22 #include "build/build_config.h" // TODO(vtl): Remove this. | |
23 #include "mojo/edk/embedder/platform_channel_pair.h" | |
24 #include "mojo/edk/embedder/platform_shared_buffer.h" | |
25 #include "mojo/edk/embedder/scoped_platform_handle.h" | |
26 #include "mojo/edk/embedder/simple_platform_support.h" | |
27 #include "mojo/edk/system/channel.h" | |
28 #include "mojo/edk/system/channel_endpoint.h" | |
29 #include "mojo/edk/system/channel_endpoint_id.h" | |
30 #include "mojo/edk/system/incoming_endpoint.h" | |
31 #include "mojo/edk/system/message_pipe.h" | |
32 #include "mojo/edk/system/message_pipe_dispatcher.h" | |
33 #include "mojo/edk/system/platform_handle_dispatcher.h" | |
34 #include "mojo/edk/system/raw_channel.h" | |
35 #include "mojo/edk/system/shared_buffer_dispatcher.h" | |
36 #include "mojo/edk/system/test_utils.h" | |
37 #include "mojo/edk/system/waiter.h" | |
38 #include "mojo/edk/test/test_utils.h" | |
39 #include "testing/gtest/include/gtest/gtest.h" | |
40 | |
41 namespace mojo { | |
42 namespace system { | |
43 namespace { | |
44 | |
45 const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE | | |
46 MOJO_HANDLE_SIGNAL_WRITABLE | | |
47 MOJO_HANDLE_SIGNAL_PEER_CLOSED; | |
48 | |
49 class RemoteMessagePipeTest : public testing::Test { | |
50 public: | |
51 RemoteMessagePipeTest() : io_thread_(base::TestIOThread::kAutoStart) {} | |
52 ~RemoteMessagePipeTest() override {} | |
53 | |
54 void SetUp() override { | |
55 io_thread_.PostTaskAndWait( | |
56 FROM_HERE, base::Bind(&RemoteMessagePipeTest::SetUpOnIOThread, | |
57 base::Unretained(this))); | |
58 } | |
59 | |
60 void TearDown() override { | |
61 io_thread_.PostTaskAndWait( | |
62 FROM_HERE, base::Bind(&RemoteMessagePipeTest::TearDownOnIOThread, | |
63 base::Unretained(this))); | |
64 } | |
65 | |
66 protected: | |
67 // This connects the two given |ChannelEndpoint|s. It assumes/requires that | |
68 // this is the bootstrap case (i.e., no other message pipes have ever been | |
69 // hosted on the channel). | |
70 void BootstrapChannelEndpoints(scoped_refptr<ChannelEndpoint> ep0, | |
71 scoped_refptr<ChannelEndpoint> ep1) { | |
72 io_thread_.PostTaskAndWait( | |
73 FROM_HERE, | |
74 base::Bind(&RemoteMessagePipeTest::BootstrapChannelEndpointsOnIOThread, | |
75 base::Unretained(this), ep0, ep1)); | |
76 } | |
77 | |
78 // This bootstraps |ep| on |channels_[channel_index]|. It assumes/requires | |
79 // that this is the bootstrap case (i.e., no message pipes have ever been | |
80 // hosted on the channel). This returns *without* waiting. | |
81 void BootstrapChannelEndpointNoWait(unsigned channel_index, | |
82 scoped_refptr<ChannelEndpoint> ep) { | |
83 io_thread_.PostTask( | |
84 FROM_HERE, | |
85 base::Bind(&RemoteMessagePipeTest::BootstrapChannelEndpointOnIOThread, | |
86 base::Unretained(this), channel_index, ep)); | |
87 } | |
88 | |
89 void RestoreInitialState() { | |
90 io_thread_.PostTaskAndWait( | |
91 FROM_HERE, | |
92 base::Bind(&RemoteMessagePipeTest::RestoreInitialStateOnIOThread, | |
93 base::Unretained(this))); | |
94 } | |
95 | |
96 embedder::PlatformSupport* platform_support() { return &platform_support_; } | |
97 base::TestIOThread* io_thread() { return &io_thread_; } | |
98 // Warning: It's up to the caller to ensure that the returned channel | |
99 // is/remains valid. | |
100 Channel* channels(size_t i) { return channels_[i].get(); } | |
101 | |
102 private: | |
103 void SetUpOnIOThread() { | |
104 CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); | |
105 | |
106 embedder::PlatformChannelPair channel_pair; | |
107 platform_handles_[0] = channel_pair.PassServerHandle(); | |
108 platform_handles_[1] = channel_pair.PassClientHandle(); | |
109 } | |
110 | |
111 void TearDownOnIOThread() { | |
112 CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); | |
113 | |
114 if (channels_[0]) { | |
115 channels_[0]->Shutdown(); | |
116 channels_[0] = nullptr; | |
117 } | |
118 if (channels_[1]) { | |
119 channels_[1]->Shutdown(); | |
120 channels_[1] = nullptr; | |
121 } | |
122 } | |
123 | |
124 void CreateAndInitChannel(unsigned channel_index) { | |
125 CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); | |
126 CHECK(channel_index == 0 || channel_index == 1); | |
127 CHECK(!channels_[channel_index]); | |
128 | |
129 channels_[channel_index] = new Channel(&platform_support_); | |
130 channels_[channel_index]->Init( | |
131 RawChannel::Create(platform_handles_[channel_index].Pass())); | |
132 } | |
133 | |
134 void BootstrapChannelEndpointsOnIOThread(scoped_refptr<ChannelEndpoint> ep0, | |
135 scoped_refptr<ChannelEndpoint> ep1) { | |
136 CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); | |
137 | |
138 if (!channels_[0]) | |
139 CreateAndInitChannel(0); | |
140 if (!channels_[1]) | |
141 CreateAndInitChannel(1); | |
142 | |
143 channels_[0]->SetBootstrapEndpoint(ep0); | |
144 channels_[1]->SetBootstrapEndpoint(ep1); | |
145 } | |
146 | |
147 void BootstrapChannelEndpointOnIOThread(unsigned channel_index, | |
148 scoped_refptr<ChannelEndpoint> ep) { | |
149 CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); | |
150 CHECK(channel_index == 0 || channel_index == 1); | |
151 | |
152 CreateAndInitChannel(channel_index); | |
153 channels_[channel_index]->SetBootstrapEndpoint(ep); | |
154 } | |
155 | |
156 void RestoreInitialStateOnIOThread() { | |
157 CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); | |
158 | |
159 TearDownOnIOThread(); | |
160 SetUpOnIOThread(); | |
161 } | |
162 | |
163 embedder::SimplePlatformSupport platform_support_; | |
164 base::TestIOThread io_thread_; | |
165 embedder::ScopedPlatformHandle platform_handles_[2]; | |
166 scoped_refptr<Channel> channels_[2]; | |
167 | |
168 DISALLOW_COPY_AND_ASSIGN(RemoteMessagePipeTest); | |
169 }; | |
170 | |
171 TEST_F(RemoteMessagePipeTest, Basic) { | |
172 static const char kHello[] = "hello"; | |
173 static const char kWorld[] = "world!!!1!!!1!"; | |
174 char buffer[100] = {0}; | |
175 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
176 Waiter waiter; | |
177 HandleSignalsState hss; | |
178 uint32_t context = 0; | |
179 | |
180 // Connect message pipes. MP 0, port 1 will be attached to channel 0 and | |
181 // connected to MP 1, port 0, which will be attached to channel 1. This leaves | |
182 // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints. | |
183 | |
184 scoped_refptr<ChannelEndpoint> ep0; | |
185 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
186 scoped_refptr<ChannelEndpoint> ep1; | |
187 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
188 BootstrapChannelEndpoints(ep0, ep1); | |
189 | |
190 // Write in one direction: MP 0, port 0 -> ... -> MP 1, port 1. | |
191 | |
192 // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do | |
193 // it later, it might already be readable.) | |
194 waiter.Init(); | |
195 ASSERT_EQ( | |
196 MOJO_RESULT_OK, | |
197 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
198 | |
199 // Write to MP 0, port 0. | |
200 EXPECT_EQ( | |
201 MOJO_RESULT_OK, | |
202 mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), | |
203 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
204 | |
205 // Wait. | |
206 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
207 EXPECT_EQ(123u, context); | |
208 hss = HandleSignalsState(); | |
209 mp1->RemoveAwakable(1, &waiter, &hss); | |
210 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
211 hss.satisfied_signals); | |
212 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
213 | |
214 // Read from MP 1, port 1. | |
215 EXPECT_EQ(MOJO_RESULT_OK, | |
216 mp1->ReadMessage(1, UserPointer<void>(buffer), | |
217 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
218 MOJO_READ_MESSAGE_FLAG_NONE)); | |
219 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size)); | |
220 EXPECT_STREQ(kHello, buffer); | |
221 | |
222 // Write in the other direction: MP 1, port 1 -> ... -> MP 0, port 0. | |
223 | |
224 waiter.Init(); | |
225 ASSERT_EQ( | |
226 MOJO_RESULT_OK, | |
227 mp0->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr)); | |
228 | |
229 EXPECT_EQ( | |
230 MOJO_RESULT_OK, | |
231 mp1->WriteMessage(1, UserPointer<const void>(kWorld), sizeof(kWorld), | |
232 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
233 | |
234 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
235 EXPECT_EQ(456u, context); | |
236 hss = HandleSignalsState(); | |
237 mp0->RemoveAwakable(0, &waiter, &hss); | |
238 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
239 hss.satisfied_signals); | |
240 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
241 | |
242 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
243 EXPECT_EQ(MOJO_RESULT_OK, | |
244 mp0->ReadMessage(0, UserPointer<void>(buffer), | |
245 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
246 MOJO_READ_MESSAGE_FLAG_NONE)); | |
247 EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(buffer_size)); | |
248 EXPECT_STREQ(kWorld, buffer); | |
249 | |
250 // Close MP 0, port 0. | |
251 mp0->Close(0); | |
252 | |
253 // Try to wait for MP 1, port 1 to become readable. This will eventually fail | |
254 // when it realizes that MP 0, port 0 has been closed. (It may also fail | |
255 // immediately.) | |
256 waiter.Init(); | |
257 hss = HandleSignalsState(); | |
258 MojoResult result = | |
259 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, &hss); | |
260 if (result == MOJO_RESULT_OK) { | |
261 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
262 waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
263 EXPECT_EQ(789u, context); | |
264 hss = HandleSignalsState(); | |
265 mp1->RemoveAwakable(1, &waiter, &hss); | |
266 } | |
267 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | |
268 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | |
269 | |
270 // And MP 1, port 1. | |
271 mp1->Close(1); | |
272 } | |
273 | |
274 TEST_F(RemoteMessagePipeTest, PeerClosed) { | |
275 Waiter waiter; | |
276 HandleSignalsState hss; | |
277 uint32_t context = 0; | |
278 | |
279 // Connect message pipes. MP 0, port 1 will be attached to channel 0 and | |
280 // connected to MP 1, port 0, which will be attached to channel 1. This leaves | |
281 // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints. | |
282 | |
283 scoped_refptr<ChannelEndpoint> ep0; | |
284 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
285 scoped_refptr<ChannelEndpoint> ep1; | |
286 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
287 BootstrapChannelEndpoints(ep0, ep1); | |
288 | |
289 // Close MP 0, port 0. | |
290 mp0->Close(0); | |
291 | |
292 // Try to wait for MP 1, port 1 to be signaled with peer closed. | |
293 waiter.Init(); | |
294 hss = HandleSignalsState(); | |
295 MojoResult result = | |
296 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 101, &hss); | |
297 if (result == MOJO_RESULT_OK) { | |
298 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
299 EXPECT_EQ(101u, context); | |
300 hss = HandleSignalsState(); | |
301 mp1->RemoveAwakable(1, &waiter, &hss); | |
302 } | |
303 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | |
304 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | |
305 | |
306 // And MP 1, port 1. | |
307 mp1->Close(1); | |
308 } | |
309 | |
310 TEST_F(RemoteMessagePipeTest, Multiplex) { | |
311 static const char kHello[] = "hello"; | |
312 static const char kWorld[] = "world!!!1!!!1!"; | |
313 char buffer[100] = {0}; | |
314 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
315 Waiter waiter; | |
316 HandleSignalsState hss; | |
317 uint32_t context = 0; | |
318 | |
319 // Connect message pipes as in the |Basic| test. | |
320 | |
321 scoped_refptr<ChannelEndpoint> ep0; | |
322 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
323 scoped_refptr<ChannelEndpoint> ep1; | |
324 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
325 BootstrapChannelEndpoints(ep0, ep1); | |
326 | |
327 // Now put another message pipe on the channel. | |
328 | |
329 // Do this by creating a message pipe (for the |channels(0)| side) and | |
330 // attaching and running it, yielding the remote ID. A message is then sent | |
331 // via |ep0| (i.e., sent using |mp0|, port 0) with this remote ID. Upon | |
332 // receiving this message, |PassIncomingMessagePipe()| is used to obtain the | |
333 // message pipe on the other side. | |
334 scoped_refptr<MessagePipe> mp2(MessagePipe::CreateLocalLocal()); | |
335 ASSERT_TRUE(channels(0)); | |
336 size_t max_endpoint_info_size; | |
337 size_t max_platform_handle_count; | |
338 mp2->StartSerialize(1, channels(0), &max_endpoint_info_size, | |
339 &max_platform_handle_count); | |
340 EXPECT_GT(max_endpoint_info_size, 0u); | |
341 ASSERT_EQ(0u, max_platform_handle_count); | |
342 scoped_ptr<char[]> endpoint_info(new char[max_endpoint_info_size]); | |
343 size_t endpoint_info_size; | |
344 mp2->EndSerialize(1, channels(0), endpoint_info.get(), &endpoint_info_size, | |
345 nullptr); | |
346 EXPECT_EQ(max_endpoint_info_size, endpoint_info_size); | |
347 | |
348 waiter.Init(); | |
349 ASSERT_EQ( | |
350 MOJO_RESULT_OK, | |
351 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
352 | |
353 EXPECT_EQ(MOJO_RESULT_OK, | |
354 mp0->WriteMessage(0, UserPointer<const void>(endpoint_info.get()), | |
355 static_cast<uint32_t>(endpoint_info_size), | |
356 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
357 | |
358 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
359 EXPECT_EQ(123u, context); | |
360 hss = HandleSignalsState(); | |
361 mp1->RemoveAwakable(1, &waiter, &hss); | |
362 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
363 hss.satisfied_signals); | |
364 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
365 | |
366 EXPECT_EQ(endpoint_info_size, channels(1)->GetSerializedEndpointSize()); | |
367 scoped_ptr<char[]> received_endpoint_info(new char[endpoint_info_size]); | |
368 buffer_size = static_cast<uint32_t>(endpoint_info_size); | |
369 EXPECT_EQ(MOJO_RESULT_OK, | |
370 mp1->ReadMessage(1, UserPointer<void>(received_endpoint_info.get()), | |
371 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
372 MOJO_READ_MESSAGE_FLAG_NONE)); | |
373 EXPECT_EQ(endpoint_info_size, static_cast<size_t>(buffer_size)); | |
374 EXPECT_EQ(0, memcmp(received_endpoint_info.get(), endpoint_info.get(), | |
375 endpoint_info_size)); | |
376 | |
377 // Warning: The local side of mp3 is port 0, not port 1. | |
378 scoped_refptr<IncomingEndpoint> incoming_endpoint = | |
379 channels(1)->DeserializeEndpoint(received_endpoint_info.get()); | |
380 ASSERT_TRUE(incoming_endpoint); | |
381 scoped_refptr<MessagePipe> mp3 = incoming_endpoint->ConvertToMessagePipe(); | |
382 ASSERT_TRUE(mp3); | |
383 | |
384 // Write: MP 2, port 0 -> MP 3, port 1. | |
385 | |
386 waiter.Init(); | |
387 ASSERT_EQ( | |
388 MOJO_RESULT_OK, | |
389 mp3->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, nullptr)); | |
390 | |
391 EXPECT_EQ( | |
392 MOJO_RESULT_OK, | |
393 mp2->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), | |
394 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
395 | |
396 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
397 EXPECT_EQ(789u, context); | |
398 hss = HandleSignalsState(); | |
399 mp3->RemoveAwakable(0, &waiter, &hss); | |
400 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
401 hss.satisfied_signals); | |
402 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
403 | |
404 // Make sure there's nothing on MP 0, port 0 or MP 1, port 1 or MP 2, port 0. | |
405 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
406 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | |
407 mp0->ReadMessage(0, UserPointer<void>(buffer), | |
408 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
409 MOJO_READ_MESSAGE_FLAG_NONE)); | |
410 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
411 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | |
412 mp1->ReadMessage(1, UserPointer<void>(buffer), | |
413 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
414 MOJO_READ_MESSAGE_FLAG_NONE)); | |
415 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
416 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | |
417 mp2->ReadMessage(0, UserPointer<void>(buffer), | |
418 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
419 MOJO_READ_MESSAGE_FLAG_NONE)); | |
420 | |
421 // Read from MP 3, port 1. | |
422 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
423 EXPECT_EQ(MOJO_RESULT_OK, | |
424 mp3->ReadMessage(0, UserPointer<void>(buffer), | |
425 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
426 MOJO_READ_MESSAGE_FLAG_NONE)); | |
427 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size)); | |
428 EXPECT_STREQ(kHello, buffer); | |
429 | |
430 // Write: MP 0, port 0 -> MP 1, port 1 again. | |
431 | |
432 waiter.Init(); | |
433 ASSERT_EQ( | |
434 MOJO_RESULT_OK, | |
435 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
436 | |
437 EXPECT_EQ( | |
438 MOJO_RESULT_OK, | |
439 mp0->WriteMessage(0, UserPointer<const void>(kWorld), sizeof(kWorld), | |
440 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
441 | |
442 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
443 EXPECT_EQ(123u, context); | |
444 hss = HandleSignalsState(); | |
445 mp1->RemoveAwakable(1, &waiter, &hss); | |
446 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
447 hss.satisfied_signals); | |
448 EXPECT_EQ(kAllSignals | MOJO_HANDLE_SIGNAL_PEER_CLOSED, | |
449 hss.satisfiable_signals); | |
450 | |
451 // Make sure there's nothing on the other ports. | |
452 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
453 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | |
454 mp0->ReadMessage(0, UserPointer<void>(buffer), | |
455 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
456 MOJO_READ_MESSAGE_FLAG_NONE)); | |
457 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
458 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | |
459 mp2->ReadMessage(0, UserPointer<void>(buffer), | |
460 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
461 MOJO_READ_MESSAGE_FLAG_NONE)); | |
462 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
463 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | |
464 mp3->ReadMessage(0, UserPointer<void>(buffer), | |
465 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
466 MOJO_READ_MESSAGE_FLAG_NONE)); | |
467 | |
468 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
469 EXPECT_EQ(MOJO_RESULT_OK, | |
470 mp1->ReadMessage(1, UserPointer<void>(buffer), | |
471 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
472 MOJO_READ_MESSAGE_FLAG_NONE)); | |
473 EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(buffer_size)); | |
474 EXPECT_STREQ(kWorld, buffer); | |
475 | |
476 mp0->Close(0); | |
477 mp1->Close(1); | |
478 mp2->Close(0); | |
479 mp3->Close(0); | |
480 } | |
481 | |
482 TEST_F(RemoteMessagePipeTest, CloseBeforeAttachAndRun) { | |
483 static const char kHello[] = "hello"; | |
484 char buffer[100] = {0}; | |
485 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
486 Waiter waiter; | |
487 HandleSignalsState hss; | |
488 uint32_t context = 0; | |
489 | |
490 // Connect message pipes. MP 0, port 1 will be attached to channel 0 and | |
491 // connected to MP 1, port 0, which will be attached to channel 1. This leaves | |
492 // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints. | |
493 | |
494 scoped_refptr<ChannelEndpoint> ep0; | |
495 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
496 | |
497 // Write to MP 0, port 0. | |
498 EXPECT_EQ( | |
499 MOJO_RESULT_OK, | |
500 mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), | |
501 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
502 | |
503 // Close MP 0, port 0 before it's even been attached to the channel and run. | |
504 mp0->Close(0); | |
505 | |
506 BootstrapChannelEndpointNoWait(0, ep0); | |
507 | |
508 scoped_refptr<ChannelEndpoint> ep1; | |
509 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
510 | |
511 // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do | |
512 // it later, it might already be readable.) | |
513 waiter.Init(); | |
514 ASSERT_EQ( | |
515 MOJO_RESULT_OK, | |
516 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
517 | |
518 BootstrapChannelEndpointNoWait(1, ep1); | |
519 | |
520 // Wait. | |
521 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
522 EXPECT_EQ(123u, context); | |
523 hss = HandleSignalsState(); | |
524 // Note: MP 1, port 1 should definitely should be readable, but it may or may | |
525 // not appear as writable (there's a race, and it may not have noticed that | |
526 // the other side was closed yet -- e.g., inserting a sleep here would make it | |
527 // much more likely to notice that it's no longer writable). | |
528 mp1->RemoveAwakable(1, &waiter, &hss); | |
529 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
530 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
531 | |
532 // Read from MP 1, port 1. | |
533 EXPECT_EQ(MOJO_RESULT_OK, | |
534 mp1->ReadMessage(1, UserPointer<void>(buffer), | |
535 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
536 MOJO_READ_MESSAGE_FLAG_NONE)); | |
537 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size)); | |
538 EXPECT_STREQ(kHello, buffer); | |
539 | |
540 // And MP 1, port 1. | |
541 mp1->Close(1); | |
542 } | |
543 | |
544 TEST_F(RemoteMessagePipeTest, CloseBeforeConnect) { | |
545 static const char kHello[] = "hello"; | |
546 char buffer[100] = {0}; | |
547 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
548 Waiter waiter; | |
549 HandleSignalsState hss; | |
550 uint32_t context = 0; | |
551 | |
552 // Connect message pipes. MP 0, port 1 will be attached to channel 0 and | |
553 // connected to MP 1, port 0, which will be attached to channel 1. This leaves | |
554 // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints. | |
555 | |
556 scoped_refptr<ChannelEndpoint> ep0; | |
557 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
558 | |
559 // Write to MP 0, port 0. | |
560 EXPECT_EQ( | |
561 MOJO_RESULT_OK, | |
562 mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), | |
563 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
564 | |
565 BootstrapChannelEndpointNoWait(0, ep0); | |
566 | |
567 // Close MP 0, port 0 before channel 1 is even connected. | |
568 mp0->Close(0); | |
569 | |
570 scoped_refptr<ChannelEndpoint> ep1; | |
571 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
572 | |
573 // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do | |
574 // it later, it might already be readable.) | |
575 waiter.Init(); | |
576 ASSERT_EQ( | |
577 MOJO_RESULT_OK, | |
578 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
579 | |
580 BootstrapChannelEndpointNoWait(1, ep1); | |
581 | |
582 // Wait. | |
583 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
584 EXPECT_EQ(123u, context); | |
585 hss = HandleSignalsState(); | |
586 // Note: MP 1, port 1 should definitely should be readable, but it may or may | |
587 // not appear as writable (there's a race, and it may not have noticed that | |
588 // the other side was closed yet -- e.g., inserting a sleep here would make it | |
589 // much more likely to notice that it's no longer writable). | |
590 mp1->RemoveAwakable(1, &waiter, &hss); | |
591 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
592 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
593 | |
594 // Read from MP 1, port 1. | |
595 EXPECT_EQ(MOJO_RESULT_OK, | |
596 mp1->ReadMessage(1, UserPointer<void>(buffer), | |
597 MakeUserPointer(&buffer_size), nullptr, nullptr, | |
598 MOJO_READ_MESSAGE_FLAG_NONE)); | |
599 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(buffer_size)); | |
600 EXPECT_STREQ(kHello, buffer); | |
601 | |
602 // And MP 1, port 1. | |
603 mp1->Close(1); | |
604 } | |
605 | |
606 TEST_F(RemoteMessagePipeTest, HandlePassing) { | |
607 static const char kHello[] = "hello"; | |
608 Waiter waiter; | |
609 HandleSignalsState hss; | |
610 uint32_t context = 0; | |
611 | |
612 scoped_refptr<ChannelEndpoint> ep0; | |
613 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
614 scoped_refptr<ChannelEndpoint> ep1; | |
615 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
616 BootstrapChannelEndpoints(ep0, ep1); | |
617 | |
618 // We'll try to pass this dispatcher. | |
619 scoped_refptr<MessagePipeDispatcher> dispatcher( | |
620 new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions)); | |
621 scoped_refptr<MessagePipe> local_mp(MessagePipe::CreateLocalLocal()); | |
622 dispatcher->Init(local_mp, 0); | |
623 | |
624 // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do | |
625 // it later, it might already be readable.) | |
626 waiter.Init(); | |
627 ASSERT_EQ( | |
628 MOJO_RESULT_OK, | |
629 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
630 | |
631 // Write to MP 0, port 0. | |
632 { | |
633 DispatcherTransport transport( | |
634 test::DispatcherTryStartTransport(dispatcher.get())); | |
635 EXPECT_TRUE(transport.is_valid()); | |
636 | |
637 std::vector<DispatcherTransport> transports; | |
638 transports.push_back(transport); | |
639 EXPECT_EQ( | |
640 MOJO_RESULT_OK, | |
641 mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), | |
642 &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
643 transport.End(); | |
644 | |
645 // |dispatcher| should have been closed. This is |DCHECK()|ed when the | |
646 // |dispatcher| is destroyed. | |
647 EXPECT_TRUE(dispatcher->HasOneRef()); | |
648 dispatcher = nullptr; | |
649 } | |
650 | |
651 // Wait. | |
652 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
653 EXPECT_EQ(123u, context); | |
654 hss = HandleSignalsState(); | |
655 mp1->RemoveAwakable(1, &waiter, &hss); | |
656 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
657 hss.satisfied_signals); | |
658 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
659 | |
660 // Read from MP 1, port 1. | |
661 char read_buffer[100] = {0}; | |
662 uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
663 DispatcherVector read_dispatchers; | |
664 uint32_t read_num_dispatchers = 10; // Maximum to get. | |
665 EXPECT_EQ( | |
666 MOJO_RESULT_OK, | |
667 mp1->ReadMessage(1, UserPointer<void>(read_buffer), | |
668 MakeUserPointer(&read_buffer_size), &read_dispatchers, | |
669 &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); | |
670 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); | |
671 EXPECT_STREQ(kHello, read_buffer); | |
672 EXPECT_EQ(1u, read_dispatchers.size()); | |
673 EXPECT_EQ(1u, read_num_dispatchers); | |
674 ASSERT_TRUE(read_dispatchers[0]); | |
675 EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); | |
676 | |
677 EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); | |
678 dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); | |
679 | |
680 // Add the waiter now, before it becomes readable to avoid a race. | |
681 waiter.Init(); | |
682 ASSERT_EQ(MOJO_RESULT_OK, | |
683 dispatcher->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, | |
684 nullptr)); | |
685 | |
686 // Write to "local_mp", port 1. | |
687 EXPECT_EQ( | |
688 MOJO_RESULT_OK, | |
689 local_mp->WriteMessage(1, UserPointer<const void>(kHello), sizeof(kHello), | |
690 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
691 | |
692 // TODO(vtl): FIXME -- We (racily) crash if I close |dispatcher| immediately | |
693 // here. (We don't crash if I sleep and then close.) | |
694 | |
695 // Wait for the dispatcher to become readable. | |
696 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
697 EXPECT_EQ(456u, context); | |
698 hss = HandleSignalsState(); | |
699 dispatcher->RemoveAwakable(&waiter, &hss); | |
700 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
701 hss.satisfied_signals); | |
702 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
703 | |
704 // Read from the dispatcher. | |
705 memset(read_buffer, 0, sizeof(read_buffer)); | |
706 read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
707 EXPECT_EQ(MOJO_RESULT_OK, | |
708 dispatcher->ReadMessage(UserPointer<void>(read_buffer), | |
709 MakeUserPointer(&read_buffer_size), 0, | |
710 nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); | |
711 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); | |
712 EXPECT_STREQ(kHello, read_buffer); | |
713 | |
714 // Prepare to wait on "local_mp", port 1. | |
715 waiter.Init(); | |
716 ASSERT_EQ(MOJO_RESULT_OK, | |
717 local_mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, | |
718 nullptr)); | |
719 | |
720 // Write to the dispatcher. | |
721 EXPECT_EQ(MOJO_RESULT_OK, dispatcher->WriteMessage( | |
722 UserPointer<const void>(kHello), sizeof(kHello), | |
723 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
724 | |
725 // Wait. | |
726 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
727 EXPECT_EQ(789u, context); | |
728 hss = HandleSignalsState(); | |
729 local_mp->RemoveAwakable(1, &waiter, &hss); | |
730 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
731 hss.satisfied_signals); | |
732 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
733 | |
734 // Read from "local_mp", port 1. | |
735 memset(read_buffer, 0, sizeof(read_buffer)); | |
736 read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
737 EXPECT_EQ(MOJO_RESULT_OK, | |
738 local_mp->ReadMessage(1, UserPointer<void>(read_buffer), | |
739 MakeUserPointer(&read_buffer_size), nullptr, | |
740 nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); | |
741 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); | |
742 EXPECT_STREQ(kHello, read_buffer); | |
743 | |
744 // TODO(vtl): Also test that messages queued up before the handle was sent are | |
745 // delivered properly. | |
746 | |
747 // Close everything that belongs to us. | |
748 mp0->Close(0); | |
749 mp1->Close(1); | |
750 EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); | |
751 // Note that |local_mp|'s port 0 belong to |dispatcher|, which was closed. | |
752 local_mp->Close(1); | |
753 } | |
754 | |
755 TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) { | |
756 static const char kHello[] = "hello"; | |
757 static const char kWorld[] = "world!"; | |
758 Waiter waiter; | |
759 HandleSignalsState hss; | |
760 uint32_t context = 0; | |
761 | |
762 // We'll try to pass this dispatcher. | |
763 scoped_refptr<MessagePipeDispatcher> dispatcher( | |
764 new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions)); | |
765 scoped_refptr<MessagePipe> local_mp(MessagePipe::CreateLocalLocal()); | |
766 dispatcher->Init(local_mp, 0); | |
767 | |
768 hss = local_mp->GetHandleSignalsState(0); | |
769 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | |
770 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
771 // Write to the other end (|local_mp|, port 1), and then close it. | |
772 EXPECT_EQ( | |
773 MOJO_RESULT_OK, | |
774 local_mp->WriteMessage(1, UserPointer<const void>(kHello), sizeof(kHello), | |
775 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
776 hss = local_mp->GetHandleSignalsState(0); | |
777 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
778 hss.satisfied_signals); | |
779 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
780 // Then the second message.... | |
781 EXPECT_EQ( | |
782 MOJO_RESULT_OK, | |
783 local_mp->WriteMessage(1, UserPointer<const void>(kWorld), sizeof(kWorld), | |
784 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
785 hss = local_mp->GetHandleSignalsState(0); | |
786 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
787 hss.satisfied_signals); | |
788 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
789 // Then close it. | |
790 local_mp->Close(1); | |
791 | |
792 scoped_refptr<ChannelEndpoint> ep0; | |
793 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
794 scoped_refptr<ChannelEndpoint> ep1; | |
795 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
796 BootstrapChannelEndpoints(ep0, ep1); | |
797 | |
798 // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do | |
799 // it later, it might already be readable.) | |
800 waiter.Init(); | |
801 ASSERT_EQ( | |
802 MOJO_RESULT_OK, | |
803 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
804 | |
805 // Write to MP 0, port 0. | |
806 { | |
807 DispatcherTransport transport( | |
808 test::DispatcherTryStartTransport(dispatcher.get())); | |
809 EXPECT_TRUE(transport.is_valid()); | |
810 | |
811 std::vector<DispatcherTransport> transports; | |
812 transports.push_back(transport); | |
813 EXPECT_EQ( | |
814 MOJO_RESULT_OK, | |
815 mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), | |
816 &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
817 transport.End(); | |
818 | |
819 // |dispatcher| should have been closed. This is |DCHECK()|ed when the | |
820 // |dispatcher| is destroyed. | |
821 EXPECT_TRUE(dispatcher->HasOneRef()); | |
822 dispatcher = nullptr; | |
823 } | |
824 | |
825 // Wait. | |
826 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
827 EXPECT_EQ(123u, context); | |
828 hss = HandleSignalsState(); | |
829 mp1->RemoveAwakable(1, &waiter, &hss); | |
830 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
831 hss.satisfied_signals); | |
832 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
833 | |
834 // Read from MP 1, port 1. | |
835 char read_buffer[100] = {0}; | |
836 uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
837 DispatcherVector read_dispatchers; | |
838 uint32_t read_num_dispatchers = 10; // Maximum to get. | |
839 EXPECT_EQ( | |
840 MOJO_RESULT_OK, | |
841 mp1->ReadMessage(1, UserPointer<void>(read_buffer), | |
842 MakeUserPointer(&read_buffer_size), &read_dispatchers, | |
843 &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); | |
844 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); | |
845 EXPECT_STREQ(kHello, read_buffer); | |
846 EXPECT_EQ(1u, read_dispatchers.size()); | |
847 EXPECT_EQ(1u, read_num_dispatchers); | |
848 ASSERT_TRUE(read_dispatchers[0]); | |
849 EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); | |
850 | |
851 EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); | |
852 dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); | |
853 | |
854 // |dispatcher| should already be readable and not writable. | |
855 hss = dispatcher->GetHandleSignalsState(); | |
856 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, | |
857 hss.satisfied_signals); | |
858 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, | |
859 hss.satisfiable_signals); | |
860 // So read from it. | |
861 memset(read_buffer, 0, sizeof(read_buffer)); | |
862 read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
863 EXPECT_EQ(MOJO_RESULT_OK, | |
864 dispatcher->ReadMessage(UserPointer<void>(read_buffer), | |
865 MakeUserPointer(&read_buffer_size), 0, | |
866 nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); | |
867 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); | |
868 EXPECT_STREQ(kHello, read_buffer); | |
869 // It should still be readable. | |
870 hss = dispatcher->GetHandleSignalsState(); | |
871 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, | |
872 hss.satisfied_signals); | |
873 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, | |
874 hss.satisfiable_signals); | |
875 // So read from it. | |
876 memset(read_buffer, 0, sizeof(read_buffer)); | |
877 read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
878 EXPECT_EQ(MOJO_RESULT_OK, | |
879 dispatcher->ReadMessage(UserPointer<void>(read_buffer), | |
880 MakeUserPointer(&read_buffer_size), 0, | |
881 nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); | |
882 EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(read_buffer_size)); | |
883 EXPECT_STREQ(kWorld, read_buffer); | |
884 // Now it should no longer be readable. | |
885 hss = dispatcher->GetHandleSignalsState(); | |
886 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | |
887 EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | |
888 | |
889 // Close everything that belongs to us. | |
890 mp0->Close(0); | |
891 mp1->Close(1); | |
892 EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); | |
893 } | |
894 | |
895 #if defined(OS_POSIX) | |
896 #define MAYBE_SharedBufferPassing SharedBufferPassing | |
897 #else | |
898 // Not yet implemented (on Windows). | |
899 #define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing | |
900 #endif | |
901 TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { | |
902 static const char kHello[] = "hello"; | |
903 Waiter waiter; | |
904 HandleSignalsState hss; | |
905 uint32_t context = 0; | |
906 | |
907 scoped_refptr<ChannelEndpoint> ep0; | |
908 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
909 scoped_refptr<ChannelEndpoint> ep1; | |
910 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
911 BootstrapChannelEndpoints(ep0, ep1); | |
912 | |
913 // We'll try to pass this dispatcher. | |
914 scoped_refptr<SharedBufferDispatcher> dispatcher; | |
915 EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( | |
916 platform_support(), | |
917 SharedBufferDispatcher::kDefaultCreateOptions, | |
918 100, &dispatcher)); | |
919 ASSERT_TRUE(dispatcher); | |
920 | |
921 // Make a mapping. | |
922 scoped_ptr<embedder::PlatformSharedBufferMapping> mapping0; | |
923 EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( | |
924 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping0)); | |
925 ASSERT_TRUE(mapping0); | |
926 ASSERT_TRUE(mapping0->GetBase()); | |
927 ASSERT_EQ(100u, mapping0->GetLength()); | |
928 static_cast<char*>(mapping0->GetBase())[0] = 'A'; | |
929 static_cast<char*>(mapping0->GetBase())[50] = 'B'; | |
930 static_cast<char*>(mapping0->GetBase())[99] = 'C'; | |
931 | |
932 // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do | |
933 // it later, it might already be readable.) | |
934 waiter.Init(); | |
935 ASSERT_EQ( | |
936 MOJO_RESULT_OK, | |
937 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
938 | |
939 // Write to MP 0, port 0. | |
940 { | |
941 DispatcherTransport transport( | |
942 test::DispatcherTryStartTransport(dispatcher.get())); | |
943 EXPECT_TRUE(transport.is_valid()); | |
944 | |
945 std::vector<DispatcherTransport> transports; | |
946 transports.push_back(transport); | |
947 EXPECT_EQ( | |
948 MOJO_RESULT_OK, | |
949 mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), | |
950 &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
951 transport.End(); | |
952 | |
953 // |dispatcher| should have been closed. This is |DCHECK()|ed when the | |
954 // |dispatcher| is destroyed. | |
955 EXPECT_TRUE(dispatcher->HasOneRef()); | |
956 dispatcher = nullptr; | |
957 } | |
958 | |
959 // Wait. | |
960 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
961 EXPECT_EQ(123u, context); | |
962 hss = HandleSignalsState(); | |
963 mp1->RemoveAwakable(1, &waiter, &hss); | |
964 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
965 hss.satisfied_signals); | |
966 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
967 | |
968 // Read from MP 1, port 1. | |
969 char read_buffer[100] = {0}; | |
970 uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
971 DispatcherVector read_dispatchers; | |
972 uint32_t read_num_dispatchers = 10; // Maximum to get. | |
973 EXPECT_EQ( | |
974 MOJO_RESULT_OK, | |
975 mp1->ReadMessage(1, UserPointer<void>(read_buffer), | |
976 MakeUserPointer(&read_buffer_size), &read_dispatchers, | |
977 &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); | |
978 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); | |
979 EXPECT_STREQ(kHello, read_buffer); | |
980 EXPECT_EQ(1u, read_dispatchers.size()); | |
981 EXPECT_EQ(1u, read_num_dispatchers); | |
982 ASSERT_TRUE(read_dispatchers[0]); | |
983 EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); | |
984 | |
985 EXPECT_EQ(Dispatcher::kTypeSharedBuffer, read_dispatchers[0]->GetType()); | |
986 dispatcher = static_cast<SharedBufferDispatcher*>(read_dispatchers[0].get()); | |
987 | |
988 // Make another mapping. | |
989 scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1; | |
990 EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( | |
991 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); | |
992 ASSERT_TRUE(mapping1); | |
993 ASSERT_TRUE(mapping1->GetBase()); | |
994 ASSERT_EQ(100u, mapping1->GetLength()); | |
995 EXPECT_NE(mapping1->GetBase(), mapping0->GetBase()); | |
996 EXPECT_EQ('A', static_cast<char*>(mapping1->GetBase())[0]); | |
997 EXPECT_EQ('B', static_cast<char*>(mapping1->GetBase())[50]); | |
998 EXPECT_EQ('C', static_cast<char*>(mapping1->GetBase())[99]); | |
999 | |
1000 // Write stuff either way. | |
1001 static_cast<char*>(mapping1->GetBase())[1] = 'x'; | |
1002 EXPECT_EQ('x', static_cast<char*>(mapping0->GetBase())[1]); | |
1003 static_cast<char*>(mapping0->GetBase())[2] = 'y'; | |
1004 EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[2]); | |
1005 | |
1006 // Kill the first mapping; the second should still be valid. | |
1007 mapping0.reset(); | |
1008 EXPECT_EQ('A', static_cast<char*>(mapping1->GetBase())[0]); | |
1009 | |
1010 // Close everything that belongs to us. | |
1011 mp0->Close(0); | |
1012 mp1->Close(1); | |
1013 EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); | |
1014 | |
1015 // The second mapping should still be good. | |
1016 EXPECT_EQ('x', static_cast<char*>(mapping1->GetBase())[1]); | |
1017 } | |
1018 | |
1019 #if defined(OS_POSIX) | |
1020 #define MAYBE_PlatformHandlePassing PlatformHandlePassing | |
1021 #else | |
1022 // Not yet implemented (on Windows). | |
1023 #define MAYBE_PlatformHandlePassing DISABLED_PlatformHandlePassing | |
1024 #endif | |
1025 TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) { | |
1026 base::ScopedTempDir temp_dir; | |
1027 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
1028 | |
1029 static const char kHello[] = "hello"; | |
1030 static const char kWorld[] = "world"; | |
1031 Waiter waiter; | |
1032 uint32_t context = 0; | |
1033 HandleSignalsState hss; | |
1034 | |
1035 scoped_refptr<ChannelEndpoint> ep0; | |
1036 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
1037 scoped_refptr<ChannelEndpoint> ep1; | |
1038 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
1039 BootstrapChannelEndpoints(ep0, ep1); | |
1040 | |
1041 base::FilePath unused; | |
1042 base::ScopedFILE fp( | |
1043 base::CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); | |
1044 EXPECT_EQ(sizeof(kHello), fwrite(kHello, 1, sizeof(kHello), fp.get())); | |
1045 // We'll try to pass this dispatcher, which will cause a |PlatformHandle| to | |
1046 // be passed. | |
1047 scoped_refptr<PlatformHandleDispatcher> dispatcher( | |
1048 new PlatformHandleDispatcher( | |
1049 mojo::test::PlatformHandleFromFILE(fp.Pass()))); | |
1050 | |
1051 // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do | |
1052 // it later, it might already be readable.) | |
1053 waiter.Init(); | |
1054 ASSERT_EQ( | |
1055 MOJO_RESULT_OK, | |
1056 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
1057 | |
1058 // Write to MP 0, port 0. | |
1059 { | |
1060 DispatcherTransport transport( | |
1061 test::DispatcherTryStartTransport(dispatcher.get())); | |
1062 EXPECT_TRUE(transport.is_valid()); | |
1063 | |
1064 std::vector<DispatcherTransport> transports; | |
1065 transports.push_back(transport); | |
1066 EXPECT_EQ( | |
1067 MOJO_RESULT_OK, | |
1068 mp0->WriteMessage(0, UserPointer<const void>(kWorld), sizeof(kWorld), | |
1069 &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
1070 transport.End(); | |
1071 | |
1072 // |dispatcher| should have been closed. This is |DCHECK()|ed when the | |
1073 // |dispatcher| is destroyed. | |
1074 EXPECT_TRUE(dispatcher->HasOneRef()); | |
1075 dispatcher = nullptr; | |
1076 } | |
1077 | |
1078 // Wait. | |
1079 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
1080 EXPECT_EQ(123u, context); | |
1081 hss = HandleSignalsState(); | |
1082 mp1->RemoveAwakable(1, &waiter, &hss); | |
1083 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
1084 hss.satisfied_signals); | |
1085 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
1086 | |
1087 // Read from MP 1, port 1. | |
1088 char read_buffer[100] = {0}; | |
1089 uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
1090 DispatcherVector read_dispatchers; | |
1091 uint32_t read_num_dispatchers = 10; // Maximum to get. | |
1092 EXPECT_EQ( | |
1093 MOJO_RESULT_OK, | |
1094 mp1->ReadMessage(1, UserPointer<void>(read_buffer), | |
1095 MakeUserPointer(&read_buffer_size), &read_dispatchers, | |
1096 &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); | |
1097 EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(read_buffer_size)); | |
1098 EXPECT_STREQ(kWorld, read_buffer); | |
1099 EXPECT_EQ(1u, read_dispatchers.size()); | |
1100 EXPECT_EQ(1u, read_num_dispatchers); | |
1101 ASSERT_TRUE(read_dispatchers[0]); | |
1102 EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); | |
1103 | |
1104 EXPECT_EQ(Dispatcher::kTypePlatformHandle, read_dispatchers[0]->GetType()); | |
1105 dispatcher = | |
1106 static_cast<PlatformHandleDispatcher*>(read_dispatchers[0].get()); | |
1107 | |
1108 embedder::ScopedPlatformHandle h = dispatcher->PassPlatformHandle().Pass(); | |
1109 EXPECT_TRUE(h.is_valid()); | |
1110 | |
1111 fp = mojo::test::FILEFromPlatformHandle(h.Pass(), "rb").Pass(); | |
1112 EXPECT_FALSE(h.is_valid()); | |
1113 EXPECT_TRUE(fp); | |
1114 | |
1115 rewind(fp.get()); | |
1116 memset(read_buffer, 0, sizeof(read_buffer)); | |
1117 EXPECT_EQ(sizeof(kHello), | |
1118 fread(read_buffer, 1, sizeof(read_buffer), fp.get())); | |
1119 EXPECT_STREQ(kHello, read_buffer); | |
1120 | |
1121 // Close everything that belongs to us. | |
1122 mp0->Close(0); | |
1123 mp1->Close(1); | |
1124 EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); | |
1125 } | |
1126 | |
1127 // Test racing closes (on each end). | |
1128 // Note: A flaky failure would almost certainly indicate a problem in the code | |
1129 // itself (not in the test). Also, any logged warnings/errors would also | |
1130 // probably be indicative of bugs. | |
1131 TEST_F(RemoteMessagePipeTest, RacingClosesStress) { | |
1132 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(5); | |
1133 | |
1134 for (unsigned i = 0; i < 256; i++) { | |
1135 DVLOG(2) << "---------------------------------------- " << i; | |
1136 scoped_refptr<ChannelEndpoint> ep0; | |
1137 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
1138 BootstrapChannelEndpointNoWait(0, ep0); | |
1139 | |
1140 scoped_refptr<ChannelEndpoint> ep1; | |
1141 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
1142 BootstrapChannelEndpointNoWait(1, ep1); | |
1143 | |
1144 if (i & 1u) { | |
1145 io_thread()->task_runner()->PostTask( | |
1146 FROM_HERE, base::Bind(&base::PlatformThread::Sleep, delay)); | |
1147 } | |
1148 if (i & 2u) | |
1149 base::PlatformThread::Sleep(delay); | |
1150 | |
1151 mp0->Close(0); | |
1152 | |
1153 if (i & 4u) { | |
1154 io_thread()->task_runner()->PostTask( | |
1155 FROM_HERE, base::Bind(&base::PlatformThread::Sleep, delay)); | |
1156 } | |
1157 if (i & 8u) | |
1158 base::PlatformThread::Sleep(delay); | |
1159 | |
1160 mp1->Close(1); | |
1161 | |
1162 RestoreInitialState(); | |
1163 } | |
1164 } | |
1165 | |
1166 // Tests passing an end of a message pipe over a remote message pipe, and then | |
1167 // passing that end back. | |
1168 // TODO(vtl): Also test passing a message pipe across two remote message pipes. | |
1169 TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { | |
1170 static const char kHello[] = "hello"; | |
1171 static const char kWorld[] = "world"; | |
1172 Waiter waiter; | |
1173 HandleSignalsState hss; | |
1174 uint32_t context = 0; | |
1175 | |
1176 scoped_refptr<ChannelEndpoint> ep0; | |
1177 scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0)); | |
1178 scoped_refptr<ChannelEndpoint> ep1; | |
1179 scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1)); | |
1180 BootstrapChannelEndpoints(ep0, ep1); | |
1181 | |
1182 // We'll try to pass this dispatcher. | |
1183 scoped_refptr<MessagePipeDispatcher> dispatcher( | |
1184 new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions)); | |
1185 scoped_refptr<MessagePipe> local_mp(MessagePipe::CreateLocalLocal()); | |
1186 dispatcher->Init(local_mp, 0); | |
1187 | |
1188 // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do | |
1189 // it later, it might already be readable.) | |
1190 waiter.Init(); | |
1191 ASSERT_EQ( | |
1192 MOJO_RESULT_OK, | |
1193 mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); | |
1194 | |
1195 // Write to MP 0, port 0. | |
1196 { | |
1197 DispatcherTransport transport( | |
1198 test::DispatcherTryStartTransport(dispatcher.get())); | |
1199 EXPECT_TRUE(transport.is_valid()); | |
1200 | |
1201 std::vector<DispatcherTransport> transports; | |
1202 transports.push_back(transport); | |
1203 EXPECT_EQ( | |
1204 MOJO_RESULT_OK, | |
1205 mp0->WriteMessage(0, UserPointer<const void>(kHello), sizeof(kHello), | |
1206 &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
1207 transport.End(); | |
1208 | |
1209 // |dispatcher| should have been closed. This is |DCHECK()|ed when the | |
1210 // |dispatcher| is destroyed. | |
1211 EXPECT_TRUE(dispatcher->HasOneRef()); | |
1212 dispatcher = nullptr; | |
1213 } | |
1214 | |
1215 // Wait. | |
1216 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
1217 EXPECT_EQ(123u, context); | |
1218 hss = HandleSignalsState(); | |
1219 mp1->RemoveAwakable(1, &waiter, &hss); | |
1220 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
1221 hss.satisfied_signals); | |
1222 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
1223 | |
1224 // Read from MP 1, port 1. | |
1225 char read_buffer[100] = {0}; | |
1226 uint32_t read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
1227 DispatcherVector read_dispatchers; | |
1228 uint32_t read_num_dispatchers = 10; // Maximum to get. | |
1229 EXPECT_EQ( | |
1230 MOJO_RESULT_OK, | |
1231 mp1->ReadMessage(1, UserPointer<void>(read_buffer), | |
1232 MakeUserPointer(&read_buffer_size), &read_dispatchers, | |
1233 &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); | |
1234 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); | |
1235 EXPECT_STREQ(kHello, read_buffer); | |
1236 EXPECT_EQ(1u, read_dispatchers.size()); | |
1237 EXPECT_EQ(1u, read_num_dispatchers); | |
1238 ASSERT_TRUE(read_dispatchers[0]); | |
1239 EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); | |
1240 | |
1241 EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); | |
1242 dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); | |
1243 read_dispatchers.clear(); | |
1244 | |
1245 // Now pass it back. | |
1246 | |
1247 // Prepare to wait on MP 0, port 0. (Add the waiter now. Otherwise, if we do | |
1248 // it later, it might already be readable.) | |
1249 waiter.Init(); | |
1250 ASSERT_EQ( | |
1251 MOJO_RESULT_OK, | |
1252 mp0->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr)); | |
1253 | |
1254 // Write to MP 1, port 1. | |
1255 { | |
1256 DispatcherTransport transport( | |
1257 test::DispatcherTryStartTransport(dispatcher.get())); | |
1258 EXPECT_TRUE(transport.is_valid()); | |
1259 | |
1260 std::vector<DispatcherTransport> transports; | |
1261 transports.push_back(transport); | |
1262 EXPECT_EQ( | |
1263 MOJO_RESULT_OK, | |
1264 mp1->WriteMessage(1, UserPointer<const void>(kWorld), sizeof(kWorld), | |
1265 &transports, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
1266 transport.End(); | |
1267 | |
1268 // |dispatcher| should have been closed. This is |DCHECK()|ed when the | |
1269 // |dispatcher| is destroyed. | |
1270 EXPECT_TRUE(dispatcher->HasOneRef()); | |
1271 dispatcher = nullptr; | |
1272 } | |
1273 | |
1274 // Wait. | |
1275 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
1276 EXPECT_EQ(456u, context); | |
1277 hss = HandleSignalsState(); | |
1278 mp0->RemoveAwakable(0, &waiter, &hss); | |
1279 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
1280 hss.satisfied_signals); | |
1281 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
1282 | |
1283 // Read from MP 0, port 0. | |
1284 read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
1285 read_num_dispatchers = 10; // Maximum to get. | |
1286 EXPECT_EQ( | |
1287 MOJO_RESULT_OK, | |
1288 mp0->ReadMessage(0, UserPointer<void>(read_buffer), | |
1289 MakeUserPointer(&read_buffer_size), &read_dispatchers, | |
1290 &read_num_dispatchers, MOJO_READ_MESSAGE_FLAG_NONE)); | |
1291 EXPECT_EQ(sizeof(kWorld), static_cast<size_t>(read_buffer_size)); | |
1292 EXPECT_STREQ(kWorld, read_buffer); | |
1293 EXPECT_EQ(1u, read_dispatchers.size()); | |
1294 EXPECT_EQ(1u, read_num_dispatchers); | |
1295 ASSERT_TRUE(read_dispatchers[0]); | |
1296 EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); | |
1297 | |
1298 EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); | |
1299 dispatcher = static_cast<MessagePipeDispatcher*>(read_dispatchers[0].get()); | |
1300 read_dispatchers.clear(); | |
1301 | |
1302 // Add the waiter now, before it becomes readable to avoid a race. | |
1303 waiter.Init(); | |
1304 ASSERT_EQ(MOJO_RESULT_OK, | |
1305 dispatcher->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, | |
1306 nullptr)); | |
1307 | |
1308 // Write to "local_mp", port 1. | |
1309 EXPECT_EQ( | |
1310 MOJO_RESULT_OK, | |
1311 local_mp->WriteMessage(1, UserPointer<const void>(kHello), sizeof(kHello), | |
1312 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
1313 | |
1314 // Wait for the dispatcher to become readable. | |
1315 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
1316 EXPECT_EQ(789u, context); | |
1317 hss = HandleSignalsState(); | |
1318 dispatcher->RemoveAwakable(&waiter, &hss); | |
1319 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
1320 hss.satisfied_signals); | |
1321 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
1322 | |
1323 // Read from the dispatcher. | |
1324 memset(read_buffer, 0, sizeof(read_buffer)); | |
1325 read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
1326 EXPECT_EQ(MOJO_RESULT_OK, | |
1327 dispatcher->ReadMessage(UserPointer<void>(read_buffer), | |
1328 MakeUserPointer(&read_buffer_size), 0, | |
1329 nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); | |
1330 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); | |
1331 EXPECT_STREQ(kHello, read_buffer); | |
1332 | |
1333 // Prepare to wait on "local_mp", port 1. | |
1334 waiter.Init(); | |
1335 ASSERT_EQ(MOJO_RESULT_OK, | |
1336 local_mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, | |
1337 nullptr)); | |
1338 | |
1339 // Write to the dispatcher. | |
1340 EXPECT_EQ(MOJO_RESULT_OK, dispatcher->WriteMessage( | |
1341 UserPointer<const void>(kHello), sizeof(kHello), | |
1342 nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
1343 | |
1344 // Wait. | |
1345 EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
1346 EXPECT_EQ(789u, context); | |
1347 hss = HandleSignalsState(); | |
1348 local_mp->RemoveAwakable(1, &waiter, &hss); | |
1349 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
1350 hss.satisfied_signals); | |
1351 EXPECT_EQ(kAllSignals, hss.satisfiable_signals); | |
1352 | |
1353 // Read from "local_mp", port 1. | |
1354 memset(read_buffer, 0, sizeof(read_buffer)); | |
1355 read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer)); | |
1356 EXPECT_EQ(MOJO_RESULT_OK, | |
1357 local_mp->ReadMessage(1, UserPointer<void>(read_buffer), | |
1358 MakeUserPointer(&read_buffer_size), nullptr, | |
1359 nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); | |
1360 EXPECT_EQ(sizeof(kHello), static_cast<size_t>(read_buffer_size)); | |
1361 EXPECT_STREQ(kHello, read_buffer); | |
1362 | |
1363 // TODO(vtl): Also test the cases where messages are written and read (at | |
1364 // various points) on the message pipe being passed around. | |
1365 | |
1366 // Close everything that belongs to us. | |
1367 mp0->Close(0); | |
1368 mp1->Close(1); | |
1369 EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); | |
1370 // Note that |local_mp|'s port 0 belong to |dispatcher|, which was closed. | |
1371 local_mp->Close(1); | |
1372 } | |
1373 | |
1374 } // namespace | |
1375 } // namespace system | |
1376 } // namespace mojo | |
OLD | NEW |