OLD | NEW |
| (Empty) |
1 // Copyright 2017 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 | |
7 #include <map> | |
8 #include <memory> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/callback.h" | |
12 #include "base/macros.h" | |
13 #include "base/memory/ptr_util.h" | |
14 #include "base/synchronization/waitable_event.h" | |
15 #include "base/threading/platform_thread.h" | |
16 #include "base/threading/simple_thread.h" | |
17 #include "base/time/time.h" | |
18 #include "mojo/edk/test/mojo_test_base.h" | |
19 #include "mojo/public/c/system/data_pipe.h" | |
20 #include "mojo/public/c/system/types.h" | |
21 #include "mojo/public/c/system/watcher.h" | |
22 #include "testing/gtest/include/gtest/gtest.h" | |
23 | |
24 namespace mojo { | |
25 namespace edk { | |
26 namespace { | |
27 | |
28 using WatcherTest = test::MojoTestBase; | |
29 | |
30 class WatchHelper { | |
31 public: | |
32 using ContextCallback = | |
33 base::Callback<void(MojoResult, MojoHandleSignalsState)>; | |
34 | |
35 WatchHelper() {} | |
36 ~WatchHelper() {} | |
37 | |
38 MojoResult CreateWatcher(MojoHandle* handle) { | |
39 return MojoCreateWatcher(&Notify, handle); | |
40 } | |
41 | |
42 uintptr_t CreateContext(const ContextCallback& callback) { | |
43 return CreateContextWithCancel(callback, base::Closure()); | |
44 } | |
45 | |
46 uintptr_t CreateContextWithCancel(const ContextCallback& callback, | |
47 const base::Closure& cancel_callback) { | |
48 auto context = base::MakeUnique<NotificationContext>(callback); | |
49 NotificationContext* raw_context = context.get(); | |
50 raw_context->SetCancelCallback(base::Bind( | |
51 [](std::unique_ptr<NotificationContext> context, | |
52 const base::Closure& cancel_callback) { | |
53 if (cancel_callback) | |
54 cancel_callback.Run(); | |
55 }, | |
56 base::Passed(&context), cancel_callback)); | |
57 return reinterpret_cast<uintptr_t>(raw_context); | |
58 } | |
59 | |
60 private: | |
61 class NotificationContext { | |
62 public: | |
63 explicit NotificationContext(const ContextCallback& callback) | |
64 : callback_(callback) {} | |
65 | |
66 ~NotificationContext() {} | |
67 | |
68 void SetCancelCallback(const base::Closure& cancel_callback) { | |
69 cancel_callback_ = cancel_callback; | |
70 } | |
71 | |
72 void Notify(MojoResult result, MojoHandleSignalsState state) { | |
73 if (result == MOJO_RESULT_CANCELLED) | |
74 cancel_callback_.Run(); | |
75 else | |
76 callback_.Run(result, state); | |
77 } | |
78 | |
79 private: | |
80 const ContextCallback callback_; | |
81 base::Closure cancel_callback_; | |
82 | |
83 DISALLOW_COPY_AND_ASSIGN(NotificationContext); | |
84 }; | |
85 | |
86 static void Notify(uintptr_t context, | |
87 MojoResult result, | |
88 MojoHandleSignalsState state, | |
89 MojoWatcherNotificationFlags flags) { | |
90 reinterpret_cast<NotificationContext*>(context)->Notify(result, state); | |
91 } | |
92 | |
93 DISALLOW_COPY_AND_ASSIGN(WatchHelper); | |
94 }; | |
95 | |
96 class ThreadedRunner : public base::SimpleThread { | |
97 public: | |
98 explicit ThreadedRunner(const base::Closure& callback) | |
99 : SimpleThread("ThreadedRunner"), callback_(callback) {} | |
100 ~ThreadedRunner() override {} | |
101 | |
102 void Run() override { callback_.Run(); } | |
103 | |
104 private: | |
105 const base::Closure callback_; | |
106 | |
107 DISALLOW_COPY_AND_ASSIGN(ThreadedRunner); | |
108 }; | |
109 | |
110 void ExpectNoNotification(uintptr_t context, | |
111 MojoResult result, | |
112 MojoHandleSignalsState state, | |
113 MojoWatcherNotificationFlags flags) { | |
114 NOTREACHED(); | |
115 } | |
116 | |
117 void ExpectOnlyCancel(uintptr_t context, | |
118 MojoResult result, | |
119 MojoHandleSignalsState state, | |
120 MojoWatcherNotificationFlags flags) { | |
121 EXPECT_EQ(result, MOJO_RESULT_CANCELLED); | |
122 } | |
123 | |
124 TEST_F(WatcherTest, InvalidArguments) { | |
125 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
126 MojoCreateWatcher(&ExpectNoNotification, nullptr)); | |
127 MojoHandle w; | |
128 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectNoNotification, &w)); | |
129 | |
130 // Try to watch unwatchable handles. | |
131 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
132 MojoWatch(w, w, MOJO_HANDLE_SIGNAL_READABLE, 0)); | |
133 MojoHandle buffer_handle = CreateBuffer(42); | |
134 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
135 MojoWatch(w, buffer_handle, MOJO_HANDLE_SIGNAL_READABLE, 0)); | |
136 | |
137 // Try to cancel a watch on an invalid watcher handle. | |
138 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCancelWatch(buffer_handle, 0)); | |
139 | |
140 // Try to arm an invalid handle. | |
141 EXPECT_EQ( | |
142 MOJO_RESULT_INVALID_ARGUMENT, | |
143 MojoArmWatcher(MOJO_HANDLE_INVALID, nullptr, nullptr, nullptr, nullptr)); | |
144 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
145 MojoArmWatcher(buffer_handle, nullptr, nullptr, nullptr, nullptr)); | |
146 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(buffer_handle)); | |
147 | |
148 // Try to arm with a non-null count but at least one null output buffer. | |
149 uint32_t num_ready_contexts = 1; | |
150 uintptr_t ready_context; | |
151 MojoResult ready_result; | |
152 MojoHandleSignalsState ready_state; | |
153 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
154 MojoArmWatcher(w, &num_ready_contexts, nullptr, &ready_result, | |
155 &ready_state)); | |
156 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
157 MojoArmWatcher(w, &num_ready_contexts, &ready_context, nullptr, | |
158 &ready_state)); | |
159 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
160 MojoArmWatcher(w, &num_ready_contexts, &ready_context, | |
161 &ready_result, nullptr)); | |
162 | |
163 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
164 } | |
165 | |
166 TEST_F(WatcherTest, WatchMessagePipeReadable) { | |
167 MojoHandle a, b; | |
168 CreateMessagePipe(&a, &b); | |
169 | |
170 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
171 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
172 WatchHelper helper; | |
173 int num_expected_notifications = 1; | |
174 const uintptr_t readable_a_context = helper.CreateContext(base::Bind( | |
175 [](base::WaitableEvent* event, int* expected_count, MojoResult result, | |
176 MojoHandleSignalsState state) { | |
177 EXPECT_GT(*expected_count, 0); | |
178 *expected_count -= 1; | |
179 | |
180 EXPECT_EQ(MOJO_RESULT_OK, result); | |
181 event->Signal(); | |
182 }, | |
183 &event, &num_expected_notifications)); | |
184 | |
185 MojoHandle w; | |
186 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
187 EXPECT_EQ(MOJO_RESULT_OK, | |
188 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
189 EXPECT_EQ(MOJO_RESULT_OK, | |
190 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
191 | |
192 const char kMessage1[] = "hey hey hey hey"; | |
193 const char kMessage2[] = "i said hey"; | |
194 const char kMessage3[] = "what's goin' on?"; | |
195 | |
196 // Writing to |b| multiple times should notify exactly once. | |
197 WriteMessage(b, kMessage1); | |
198 WriteMessage(b, kMessage2); | |
199 event.Wait(); | |
200 | |
201 // This also shouldn't fire a notification; the watcher is still disarmed. | |
202 WriteMessage(b, kMessage3); | |
203 | |
204 // Arming should fail with relevant information. | |
205 constexpr size_t kMaxReadyContexts = 10; | |
206 uint32_t num_ready_contexts = kMaxReadyContexts; | |
207 uintptr_t ready_contexts[kMaxReadyContexts]; | |
208 MojoResult ready_results[kMaxReadyContexts]; | |
209 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
210 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
211 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
212 ready_results, ready_states)); | |
213 EXPECT_EQ(1u, num_ready_contexts); | |
214 EXPECT_EQ(readable_a_context, ready_contexts[0]); | |
215 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
216 | |
217 // Flush the three messages from above. | |
218 EXPECT_EQ(kMessage1, ReadMessage(a)); | |
219 EXPECT_EQ(kMessage2, ReadMessage(a)); | |
220 EXPECT_EQ(kMessage3, ReadMessage(a)); | |
221 | |
222 // Now we can rearm the watcher. | |
223 EXPECT_EQ(MOJO_RESULT_OK, | |
224 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
225 | |
226 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
227 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
228 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
229 } | |
230 | |
231 TEST_F(WatcherTest, CloseWatchedMessagePipeHandle) { | |
232 MojoHandle a, b; | |
233 CreateMessagePipe(&a, &b); | |
234 | |
235 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
236 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
237 WatchHelper helper; | |
238 const uintptr_t readable_a_context = helper.CreateContextWithCancel( | |
239 WatchHelper::ContextCallback(), | |
240 base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event)); | |
241 | |
242 MojoHandle w; | |
243 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
244 EXPECT_EQ(MOJO_RESULT_OK, | |
245 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
246 | |
247 // Test that closing a watched handle fires an appropriate notification, even | |
248 // when the watcher is unarmed. | |
249 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
250 event.Wait(); | |
251 | |
252 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
253 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
254 } | |
255 | |
256 TEST_F(WatcherTest, CloseWatchedMessagePipeHandlePeer) { | |
257 MojoHandle a, b; | |
258 CreateMessagePipe(&a, &b); | |
259 | |
260 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
261 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
262 WatchHelper helper; | |
263 const uintptr_t readable_a_context = helper.CreateContext(base::Bind( | |
264 [](base::WaitableEvent* event, MojoResult result, | |
265 MojoHandleSignalsState state) { | |
266 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | |
267 event->Signal(); | |
268 }, | |
269 &event)); | |
270 | |
271 MojoHandle w; | |
272 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
273 EXPECT_EQ(MOJO_RESULT_OK, | |
274 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
275 | |
276 // Test that closing a watched handle's peer with an armed watcher fires an | |
277 // appropriate notification. | |
278 EXPECT_EQ(MOJO_RESULT_OK, | |
279 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
280 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
281 event.Wait(); | |
282 | |
283 // And now arming should fail with correct information about |a|'s state. | |
284 constexpr size_t kMaxReadyContexts = 10; | |
285 uint32_t num_ready_contexts = kMaxReadyContexts; | |
286 uintptr_t ready_contexts[kMaxReadyContexts]; | |
287 MojoResult ready_results[kMaxReadyContexts]; | |
288 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
289 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
290 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
291 ready_results, ready_states)); | |
292 EXPECT_EQ(1u, num_ready_contexts); | |
293 EXPECT_EQ(readable_a_context, ready_contexts[0]); | |
294 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); | |
295 EXPECT_TRUE(ready_states[0].satisfied_signals & | |
296 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
297 EXPECT_FALSE(ready_states[0].satisfiable_signals & | |
298 MOJO_HANDLE_SIGNAL_READABLE); | |
299 | |
300 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
301 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
302 } | |
303 | |
304 TEST_F(WatcherTest, WatchDataPipeConsumerReadable) { | |
305 constexpr size_t kTestPipeCapacity = 64; | |
306 MojoHandle producer, consumer; | |
307 CreateDataPipe(&producer, &consumer, kTestPipeCapacity); | |
308 | |
309 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
310 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
311 WatchHelper helper; | |
312 int num_expected_notifications = 1; | |
313 const uintptr_t readable_consumer_context = helper.CreateContext(base::Bind( | |
314 [](base::WaitableEvent* event, int* expected_count, MojoResult result, | |
315 MojoHandleSignalsState state) { | |
316 EXPECT_GT(*expected_count, 0); | |
317 *expected_count -= 1; | |
318 | |
319 EXPECT_EQ(MOJO_RESULT_OK, result); | |
320 event->Signal(); | |
321 }, | |
322 &event, &num_expected_notifications)); | |
323 | |
324 MojoHandle w; | |
325 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
326 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE, | |
327 readable_consumer_context)); | |
328 EXPECT_EQ(MOJO_RESULT_OK, | |
329 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
330 | |
331 const char kMessage1[] = "hey hey hey hey"; | |
332 const char kMessage2[] = "i said hey"; | |
333 const char kMessage3[] = "what's goin' on?"; | |
334 | |
335 // Writing to |producer| multiple times should notify exactly once. | |
336 WriteData(producer, kMessage1); | |
337 WriteData(producer, kMessage2); | |
338 event.Wait(); | |
339 | |
340 // This also shouldn't fire a notification; the watcher is still disarmed. | |
341 WriteData(producer, kMessage3); | |
342 | |
343 // Arming should fail with relevant information. | |
344 constexpr size_t kMaxReadyContexts = 10; | |
345 uint32_t num_ready_contexts = kMaxReadyContexts; | |
346 uintptr_t ready_contexts[kMaxReadyContexts]; | |
347 MojoResult ready_results[kMaxReadyContexts]; | |
348 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
349 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
350 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
351 ready_results, ready_states)); | |
352 EXPECT_EQ(1u, num_ready_contexts); | |
353 EXPECT_EQ(readable_consumer_context, ready_contexts[0]); | |
354 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
355 | |
356 // Flush the three messages from above. | |
357 EXPECT_EQ(kMessage1, ReadData(consumer, sizeof(kMessage1) - 1)); | |
358 EXPECT_EQ(kMessage2, ReadData(consumer, sizeof(kMessage2) - 1)); | |
359 EXPECT_EQ(kMessage3, ReadData(consumer, sizeof(kMessage3) - 1)); | |
360 | |
361 // Now we can rearm the watcher. | |
362 EXPECT_EQ(MOJO_RESULT_OK, | |
363 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
364 | |
365 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
366 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); | |
367 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); | |
368 } | |
369 | |
370 TEST_F(WatcherTest, WatchDataPipeConsumerNewDataReadable) { | |
371 constexpr size_t kTestPipeCapacity = 64; | |
372 MojoHandle producer, consumer; | |
373 CreateDataPipe(&producer, &consumer, kTestPipeCapacity); | |
374 | |
375 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
376 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
377 WatchHelper helper; | |
378 int num_new_data_notifications = 0; | |
379 const uintptr_t new_data_context = helper.CreateContext(base::Bind( | |
380 [](base::WaitableEvent* event, int* notification_count, MojoResult result, | |
381 MojoHandleSignalsState state) { | |
382 *notification_count += 1; | |
383 | |
384 EXPECT_EQ(MOJO_RESULT_OK, result); | |
385 event->Signal(); | |
386 }, | |
387 &event, &num_new_data_notifications)); | |
388 | |
389 MojoHandle w; | |
390 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
391 EXPECT_EQ(MOJO_RESULT_OK, | |
392 MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE, | |
393 new_data_context)); | |
394 EXPECT_EQ(MOJO_RESULT_OK, | |
395 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
396 | |
397 const char kMessage1[] = "hey hey hey hey"; | |
398 const char kMessage2[] = "i said hey"; | |
399 const char kMessage3[] = "what's goin' on?"; | |
400 | |
401 // Writing to |producer| multiple times should notify exactly once. | |
402 WriteData(producer, kMessage1); | |
403 WriteData(producer, kMessage2); | |
404 event.Wait(); | |
405 | |
406 // This also shouldn't fire a notification; the watcher is still disarmed. | |
407 WriteData(producer, kMessage3); | |
408 | |
409 // Arming should fail with relevant information. | |
410 constexpr size_t kMaxReadyContexts = 10; | |
411 uint32_t num_ready_contexts = kMaxReadyContexts; | |
412 uintptr_t ready_contexts[kMaxReadyContexts]; | |
413 MojoResult ready_results[kMaxReadyContexts]; | |
414 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
415 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
416 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
417 ready_results, ready_states)); | |
418 EXPECT_EQ(1u, num_ready_contexts); | |
419 EXPECT_EQ(new_data_context, ready_contexts[0]); | |
420 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
421 | |
422 // Attempt to read more data than is available. Should fail but clear the | |
423 // NEW_DATA_READABLE signal. | |
424 char large_buffer[512]; | |
425 uint32_t large_read_size = 512; | |
426 EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, | |
427 MojoReadData(consumer, large_buffer, &large_read_size, | |
428 MOJO_READ_DATA_FLAG_ALL_OR_NONE)); | |
429 | |
430 // Attempt to arm again. Should succeed. | |
431 EXPECT_EQ(MOJO_RESULT_OK, | |
432 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
433 | |
434 // Write more data. Should notify. | |
435 event.Reset(); | |
436 WriteData(producer, kMessage1); | |
437 event.Wait(); | |
438 | |
439 // Reading some data should clear NEW_DATA_READABLE again so we can rearm. | |
440 EXPECT_EQ(kMessage1, ReadData(consumer, sizeof(kMessage1) - 1)); | |
441 | |
442 EXPECT_EQ(MOJO_RESULT_OK, | |
443 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
444 | |
445 EXPECT_EQ(2, num_new_data_notifications); | |
446 | |
447 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
448 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); | |
449 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); | |
450 } | |
451 | |
452 TEST_F(WatcherTest, WatchDataPipeProducerWritable) { | |
453 constexpr size_t kTestPipeCapacity = 8; | |
454 MojoHandle producer, consumer; | |
455 CreateDataPipe(&producer, &consumer, kTestPipeCapacity); | |
456 | |
457 // Half the capacity of the data pipe. | |
458 const char kTestData[] = "aaaa"; | |
459 static_assert((sizeof(kTestData) - 1) * 2 == kTestPipeCapacity, | |
460 "Invalid test data for this test."); | |
461 | |
462 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
463 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
464 WatchHelper helper; | |
465 int num_expected_notifications = 1; | |
466 const uintptr_t writable_producer_context = helper.CreateContext(base::Bind( | |
467 [](base::WaitableEvent* event, int* expected_count, MojoResult result, | |
468 MojoHandleSignalsState state) { | |
469 EXPECT_GT(*expected_count, 0); | |
470 *expected_count -= 1; | |
471 | |
472 EXPECT_EQ(MOJO_RESULT_OK, result); | |
473 event->Signal(); | |
474 }, | |
475 &event, &num_expected_notifications)); | |
476 | |
477 MojoHandle w; | |
478 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
479 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE, | |
480 writable_producer_context)); | |
481 | |
482 // The producer is already writable, so arming should fail with relevant | |
483 // information. | |
484 constexpr size_t kMaxReadyContexts = 10; | |
485 uint32_t num_ready_contexts = kMaxReadyContexts; | |
486 uintptr_t ready_contexts[kMaxReadyContexts]; | |
487 MojoResult ready_results[kMaxReadyContexts]; | |
488 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
489 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
490 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
491 ready_results, ready_states)); | |
492 EXPECT_EQ(1u, num_ready_contexts); | |
493 EXPECT_EQ(writable_producer_context, ready_contexts[0]); | |
494 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
495 EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); | |
496 | |
497 // Write some data, but don't fill the pipe yet. Arming should fail again. | |
498 WriteData(producer, kTestData); | |
499 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
500 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
501 ready_results, ready_states)); | |
502 EXPECT_EQ(1u, num_ready_contexts); | |
503 EXPECT_EQ(writable_producer_context, ready_contexts[0]); | |
504 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
505 EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); | |
506 | |
507 // Write more data, filling the pipe to capacity. Arming should succeed now. | |
508 WriteData(producer, kTestData); | |
509 EXPECT_EQ(MOJO_RESULT_OK, | |
510 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
511 | |
512 // Now read from the pipe, making the producer writable again. Should notify. | |
513 EXPECT_EQ(kTestData, ReadData(consumer, sizeof(kTestData) - 1)); | |
514 event.Wait(); | |
515 | |
516 // Arming should fail again. | |
517 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
518 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
519 ready_results, ready_states)); | |
520 EXPECT_EQ(1u, num_ready_contexts); | |
521 EXPECT_EQ(writable_producer_context, ready_contexts[0]); | |
522 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
523 EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); | |
524 | |
525 // Fill the pipe once more and arm the watcher. Should succeed. | |
526 WriteData(producer, kTestData); | |
527 EXPECT_EQ(MOJO_RESULT_OK, | |
528 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
529 | |
530 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
531 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); | |
532 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); | |
533 }; | |
534 | |
535 TEST_F(WatcherTest, CloseWatchedDataPipeConsumerHandle) { | |
536 constexpr size_t kTestPipeCapacity = 8; | |
537 MojoHandle producer, consumer; | |
538 CreateDataPipe(&producer, &consumer, kTestPipeCapacity); | |
539 | |
540 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
541 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
542 WatchHelper helper; | |
543 const uintptr_t readable_consumer_context = helper.CreateContextWithCancel( | |
544 WatchHelper::ContextCallback(), | |
545 base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event)); | |
546 | |
547 MojoHandle w; | |
548 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
549 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE, | |
550 readable_consumer_context)); | |
551 | |
552 // Closing the consumer should fire a cancellation notification. | |
553 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); | |
554 event.Wait(); | |
555 | |
556 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); | |
557 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
558 } | |
559 | |
560 TEST_F(WatcherTest, CloseWatcherDataPipeConsumerHandlePeer) { | |
561 constexpr size_t kTestPipeCapacity = 8; | |
562 MojoHandle producer, consumer; | |
563 CreateDataPipe(&producer, &consumer, kTestPipeCapacity); | |
564 | |
565 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
566 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
567 WatchHelper helper; | |
568 const uintptr_t readable_consumer_context = helper.CreateContext(base::Bind( | |
569 [](base::WaitableEvent* event, MojoResult result, | |
570 MojoHandleSignalsState state) { | |
571 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | |
572 event->Signal(); | |
573 }, | |
574 &event)); | |
575 | |
576 MojoHandle w; | |
577 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
578 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, consumer, MOJO_HANDLE_SIGNAL_READABLE, | |
579 readable_consumer_context)); | |
580 EXPECT_EQ(MOJO_RESULT_OK, | |
581 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
582 | |
583 // Closing the producer should fire a notification for an unsatisfiable watch. | |
584 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); | |
585 event.Wait(); | |
586 | |
587 // Now attempt to rearm and expect appropriate error feedback. | |
588 constexpr size_t kMaxReadyContexts = 10; | |
589 uint32_t num_ready_contexts = kMaxReadyContexts; | |
590 uintptr_t ready_contexts[kMaxReadyContexts]; | |
591 MojoResult ready_results[kMaxReadyContexts]; | |
592 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
593 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
594 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
595 ready_results, ready_states)); | |
596 EXPECT_EQ(1u, num_ready_contexts); | |
597 EXPECT_EQ(readable_consumer_context, ready_contexts[0]); | |
598 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); | |
599 EXPECT_FALSE(ready_states[0].satisfiable_signals & | |
600 MOJO_HANDLE_SIGNAL_READABLE); | |
601 | |
602 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
603 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); | |
604 } | |
605 | |
606 TEST_F(WatcherTest, CloseWatchedDataPipeProducerHandle) { | |
607 constexpr size_t kTestPipeCapacity = 8; | |
608 MojoHandle producer, consumer; | |
609 CreateDataPipe(&producer, &consumer, kTestPipeCapacity); | |
610 | |
611 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
612 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
613 WatchHelper helper; | |
614 const uintptr_t writable_producer_context = helper.CreateContextWithCancel( | |
615 WatchHelper::ContextCallback(), | |
616 base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event)); | |
617 | |
618 MojoHandle w; | |
619 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
620 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE, | |
621 writable_producer_context)); | |
622 | |
623 // Closing the consumer should fire a cancellation notification. | |
624 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); | |
625 event.Wait(); | |
626 | |
627 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); | |
628 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
629 } | |
630 | |
631 TEST_F(WatcherTest, CloseWatchedDataPipeProducerHandlePeer) { | |
632 constexpr size_t kTestPipeCapacity = 8; | |
633 MojoHandle producer, consumer; | |
634 CreateDataPipe(&producer, &consumer, kTestPipeCapacity); | |
635 | |
636 const char kTestMessageFullCapacity[] = "xxxxxxxx"; | |
637 static_assert(sizeof(kTestMessageFullCapacity) - 1 == kTestPipeCapacity, | |
638 "Invalid test message size for this test."); | |
639 | |
640 // Make the pipe unwritable initially. | |
641 WriteData(producer, kTestMessageFullCapacity); | |
642 | |
643 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
644 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
645 WatchHelper helper; | |
646 const uintptr_t writable_producer_context = helper.CreateContext(base::Bind( | |
647 [](base::WaitableEvent* event, MojoResult result, | |
648 MojoHandleSignalsState state) { | |
649 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | |
650 event->Signal(); | |
651 }, | |
652 &event)); | |
653 | |
654 MojoHandle w; | |
655 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
656 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, producer, MOJO_HANDLE_SIGNAL_WRITABLE, | |
657 writable_producer_context)); | |
658 EXPECT_EQ(MOJO_RESULT_OK, | |
659 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
660 | |
661 // Closing the consumer should fire a notification for an unsatisfiable watch, | |
662 // as the full data pipe can never be read from again and is therefore | |
663 // permanently full and unwritable. | |
664 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(consumer)); | |
665 event.Wait(); | |
666 | |
667 // Now attempt to rearm and expect appropriate error feedback. | |
668 constexpr size_t kMaxReadyContexts = 10; | |
669 uint32_t num_ready_contexts = kMaxReadyContexts; | |
670 uintptr_t ready_contexts[kMaxReadyContexts]; | |
671 MojoResult ready_results[kMaxReadyContexts]; | |
672 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
673 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
674 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
675 ready_results, ready_states)); | |
676 EXPECT_EQ(1u, num_ready_contexts); | |
677 EXPECT_EQ(writable_producer_context, ready_contexts[0]); | |
678 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); | |
679 EXPECT_FALSE(ready_states[0].satisfiable_signals & | |
680 MOJO_HANDLE_SIGNAL_WRITABLE); | |
681 | |
682 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
683 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(producer)); | |
684 } | |
685 | |
686 TEST_F(WatcherTest, ArmWithNoWatches) { | |
687 MojoHandle w; | |
688 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectNoNotification, &w)); | |
689 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, | |
690 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
691 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
692 } | |
693 | |
694 TEST_F(WatcherTest, WatchDuplicateContext) { | |
695 MojoHandle a, b; | |
696 CreateMessagePipe(&a, &b); | |
697 | |
698 MojoHandle w; | |
699 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); | |
700 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, 0)); | |
701 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, | |
702 MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, 0)); | |
703 | |
704 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
705 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
706 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
707 } | |
708 | |
709 TEST_F(WatcherTest, CancelUnknownWatch) { | |
710 MojoHandle w; | |
711 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectNoNotification, &w)); | |
712 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, MojoCancelWatch(w, 1234)); | |
713 } | |
714 | |
715 TEST_F(WatcherTest, ArmWithWatchAlreadySatisfied) { | |
716 MojoHandle a, b; | |
717 CreateMessagePipe(&a, &b); | |
718 | |
719 MojoHandle w; | |
720 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); | |
721 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_WRITABLE, 0)); | |
722 | |
723 // |a| is always writable, so we can never arm this watcher. | |
724 constexpr size_t kMaxReadyContexts = 10; | |
725 uint32_t num_ready_contexts = kMaxReadyContexts; | |
726 uintptr_t ready_contexts[kMaxReadyContexts]; | |
727 MojoResult ready_results[kMaxReadyContexts]; | |
728 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
729 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
730 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
731 ready_results, ready_states)); | |
732 EXPECT_EQ(1u, num_ready_contexts); | |
733 EXPECT_EQ(0u, ready_contexts[0]); | |
734 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
735 EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); | |
736 | |
737 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
738 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
739 } | |
740 | |
741 TEST_F(WatcherTest, ArmWithWatchAlreadyUnsatisfiable) { | |
742 MojoHandle a, b; | |
743 CreateMessagePipe(&a, &b); | |
744 | |
745 MojoHandle w; | |
746 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateWatcher(&ExpectOnlyCancel, &w)); | |
747 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, 0)); | |
748 | |
749 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
750 | |
751 // |b| is closed and never wrote any messages, so |a| won't be readable again. | |
752 // MojoArmWatcher() should fail, incidcating as much. | |
753 constexpr size_t kMaxReadyContexts = 10; | |
754 uint32_t num_ready_contexts = kMaxReadyContexts; | |
755 uintptr_t ready_contexts[kMaxReadyContexts]; | |
756 MojoResult ready_results[kMaxReadyContexts]; | |
757 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
758 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
759 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
760 ready_results, ready_states)); | |
761 EXPECT_EQ(1u, num_ready_contexts); | |
762 EXPECT_EQ(0u, ready_contexts[0]); | |
763 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]); | |
764 EXPECT_TRUE(ready_states[0].satisfied_signals & | |
765 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
766 EXPECT_FALSE(ready_states[0].satisfiable_signals & | |
767 MOJO_HANDLE_SIGNAL_READABLE); | |
768 | |
769 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
770 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
771 } | |
772 | |
773 TEST_F(WatcherTest, MultipleWatches) { | |
774 MojoHandle a, b; | |
775 CreateMessagePipe(&a, &b); | |
776 | |
777 base::WaitableEvent a_event(base::WaitableEvent::ResetPolicy::MANUAL, | |
778 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
779 base::WaitableEvent b_event(base::WaitableEvent::ResetPolicy::MANUAL, | |
780 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
781 WatchHelper helper; | |
782 int num_a_notifications = 0; | |
783 int num_b_notifications = 0; | |
784 auto notify_callback = | |
785 base::Bind([](base::WaitableEvent* event, int* notification_count, | |
786 MojoResult result, MojoHandleSignalsState state) { | |
787 *notification_count += 1; | |
788 EXPECT_EQ(MOJO_RESULT_OK, result); | |
789 event->Signal(); | |
790 }); | |
791 uintptr_t readable_a_context = helper.CreateContext( | |
792 base::Bind(notify_callback, &a_event, &num_a_notifications)); | |
793 uintptr_t readable_b_context = helper.CreateContext( | |
794 base::Bind(notify_callback, &b_event, &num_b_notifications)); | |
795 | |
796 MojoHandle w; | |
797 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
798 | |
799 // Add two independent watch contexts to watch for |a| or |b| readability. | |
800 EXPECT_EQ(MOJO_RESULT_OK, | |
801 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
802 EXPECT_EQ(MOJO_RESULT_OK, | |
803 MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, readable_b_context)); | |
804 | |
805 EXPECT_EQ(MOJO_RESULT_OK, | |
806 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
807 | |
808 const char kMessage1[] = "things are happening"; | |
809 const char kMessage2[] = "ok. ok. ok. ok."; | |
810 const char kMessage3[] = "plz wake up"; | |
811 | |
812 // Writing to |b| should signal |a|'s watch. | |
813 WriteMessage(b, kMessage1); | |
814 a_event.Wait(); | |
815 a_event.Reset(); | |
816 | |
817 // Subsequent messages on |b| should not trigger another notification. | |
818 WriteMessage(b, kMessage2); | |
819 WriteMessage(b, kMessage3); | |
820 | |
821 // Messages on |a| also shouldn't trigger |b|'s notification, since the | |
822 // watcher should be disarmed by now. | |
823 WriteMessage(a, kMessage1); | |
824 WriteMessage(a, kMessage2); | |
825 WriteMessage(a, kMessage3); | |
826 | |
827 // Arming should fail. Since we only ask for at most one context's information | |
828 // that's all we should get back. Which one we get is unspecified. | |
829 constexpr size_t kMaxReadyContexts = 10; | |
830 uint32_t num_ready_contexts = 1; | |
831 uintptr_t ready_contexts[kMaxReadyContexts]; | |
832 MojoResult ready_results[kMaxReadyContexts]; | |
833 MojoHandleSignalsState ready_states[kMaxReadyContexts]; | |
834 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
835 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
836 ready_results, ready_states)); | |
837 EXPECT_EQ(1u, num_ready_contexts); | |
838 EXPECT_TRUE(ready_contexts[0] == readable_a_context || | |
839 ready_contexts[0] == readable_b_context); | |
840 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
841 EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); | |
842 | |
843 // Now try arming again, verifying that both contexts are returned. | |
844 num_ready_contexts = kMaxReadyContexts; | |
845 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
846 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
847 ready_results, ready_states)); | |
848 EXPECT_EQ(2u, num_ready_contexts); | |
849 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
850 EXPECT_EQ(MOJO_RESULT_OK, ready_results[1]); | |
851 EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); | |
852 EXPECT_TRUE(ready_states[1].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); | |
853 EXPECT_TRUE((ready_contexts[0] == readable_a_context && | |
854 ready_contexts[1] == readable_b_context) || | |
855 (ready_contexts[0] == readable_b_context && | |
856 ready_contexts[1] == readable_a_context)); | |
857 | |
858 // Flush out the test messages so we should be able to successfully rearm. | |
859 EXPECT_EQ(kMessage1, ReadMessage(a)); | |
860 EXPECT_EQ(kMessage2, ReadMessage(a)); | |
861 EXPECT_EQ(kMessage3, ReadMessage(a)); | |
862 EXPECT_EQ(kMessage1, ReadMessage(b)); | |
863 EXPECT_EQ(kMessage2, ReadMessage(b)); | |
864 EXPECT_EQ(kMessage3, ReadMessage(b)); | |
865 | |
866 // Add a watch which is always satisfied, so we can't arm. Arming should fail | |
867 // with only this new watch's information. | |
868 uintptr_t writable_c_context = helper.CreateContext(base::Bind( | |
869 [](MojoResult result, MojoHandleSignalsState state) { NOTREACHED(); })); | |
870 MojoHandle c, d; | |
871 CreateMessagePipe(&c, &d); | |
872 | |
873 EXPECT_EQ(MOJO_RESULT_OK, | |
874 MojoWatch(w, c, MOJO_HANDLE_SIGNAL_WRITABLE, writable_c_context)); | |
875 num_ready_contexts = kMaxReadyContexts; | |
876 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
877 MojoArmWatcher(w, &num_ready_contexts, ready_contexts, | |
878 ready_results, ready_states)); | |
879 EXPECT_EQ(1u, num_ready_contexts); | |
880 EXPECT_EQ(writable_c_context, ready_contexts[0]); | |
881 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]); | |
882 EXPECT_TRUE(ready_states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE); | |
883 | |
884 // Cancel the new watch and arming should succeed once again. | |
885 EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, writable_c_context)); | |
886 EXPECT_EQ(MOJO_RESULT_OK, | |
887 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
888 | |
889 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
890 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
891 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
892 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); | |
893 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d)); | |
894 } | |
895 | |
896 TEST_F(WatcherTest, NotifyOtherFromNotificationCallback) { | |
897 MojoHandle a, b; | |
898 CreateMessagePipe(&a, &b); | |
899 | |
900 static const char kTestMessageToA[] = "hello a"; | |
901 static const char kTestMessageToB[] = "hello b"; | |
902 | |
903 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
904 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
905 | |
906 WatchHelper helper; | |
907 MojoHandle w; | |
908 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
909 | |
910 uintptr_t readable_a_context = helper.CreateContext(base::Bind( | |
911 [](MojoHandle w, MojoHandle a, MojoResult result, | |
912 MojoHandleSignalsState state) { | |
913 EXPECT_EQ(MOJO_RESULT_OK, result); | |
914 EXPECT_EQ("hello a", ReadMessage(a)); | |
915 | |
916 // Re-arm the watcher and signal |b|. | |
917 EXPECT_EQ(MOJO_RESULT_OK, | |
918 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
919 WriteMessage(a, kTestMessageToB); | |
920 }, | |
921 w, a)); | |
922 | |
923 uintptr_t readable_b_context = helper.CreateContext(base::Bind( | |
924 [](base::WaitableEvent* event, MojoHandle w, MojoHandle b, | |
925 MojoResult result, MojoHandleSignalsState state) { | |
926 EXPECT_EQ(MOJO_RESULT_OK, result); | |
927 EXPECT_EQ(kTestMessageToB, ReadMessage(b)); | |
928 EXPECT_EQ(MOJO_RESULT_OK, | |
929 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
930 event->Signal(); | |
931 }, | |
932 &event, w, b)); | |
933 | |
934 EXPECT_EQ(MOJO_RESULT_OK, | |
935 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
936 EXPECT_EQ(MOJO_RESULT_OK, | |
937 MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, readable_b_context)); | |
938 EXPECT_EQ(MOJO_RESULT_OK, | |
939 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
940 | |
941 // Send a message to |a|. The relevant watch context should be notified, and | |
942 // should in turn send a message to |b|, waking up the other context. The | |
943 // second context signals |event|. | |
944 WriteMessage(b, kTestMessageToA); | |
945 event.Wait(); | |
946 } | |
947 | |
948 TEST_F(WatcherTest, NotifySelfFromNotificationCallback) { | |
949 MojoHandle a, b; | |
950 CreateMessagePipe(&a, &b); | |
951 | |
952 static const char kTestMessageToA[] = "hello a"; | |
953 | |
954 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
955 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
956 | |
957 WatchHelper helper; | |
958 MojoHandle w; | |
959 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
960 | |
961 int expected_notifications = 10; | |
962 uintptr_t readable_a_context = helper.CreateContext(base::Bind( | |
963 [](int* expected_count, MojoHandle w, MojoHandle a, MojoHandle b, | |
964 base::WaitableEvent* event, MojoResult result, | |
965 MojoHandleSignalsState state) { | |
966 EXPECT_EQ(MOJO_RESULT_OK, result); | |
967 EXPECT_EQ("hello a", ReadMessage(a)); | |
968 | |
969 EXPECT_GT(*expected_count, 0); | |
970 *expected_count -= 1; | |
971 if (*expected_count == 0) { | |
972 event->Signal(); | |
973 return; | |
974 } else { | |
975 // Re-arm the watcher and signal |a| again. | |
976 EXPECT_EQ(MOJO_RESULT_OK, | |
977 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
978 WriteMessage(b, kTestMessageToA); | |
979 } | |
980 }, | |
981 &expected_notifications, w, a, b, &event)); | |
982 | |
983 EXPECT_EQ(MOJO_RESULT_OK, | |
984 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
985 EXPECT_EQ(MOJO_RESULT_OK, | |
986 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
987 | |
988 // Send a message to |a|. When the watch above is notified, it will rearm and | |
989 // send another message to |a|. This will happen until | |
990 // |expected_notifications| reaches 0. | |
991 WriteMessage(b, kTestMessageToA); | |
992 event.Wait(); | |
993 } | |
994 | |
995 TEST_F(WatcherTest, ImplicitCancelOtherFromNotificationCallback) { | |
996 MojoHandle a, b; | |
997 CreateMessagePipe(&a, &b); | |
998 | |
999 MojoHandle c, d; | |
1000 CreateMessagePipe(&c, &d); | |
1001 | |
1002 static const char kTestMessageToA[] = "hi a"; | |
1003 static const char kTestMessageToC[] = "hi c"; | |
1004 | |
1005 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
1006 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1007 | |
1008 WatchHelper helper; | |
1009 MojoHandle w; | |
1010 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
1011 | |
1012 uintptr_t readable_a_context = helper.CreateContextWithCancel( | |
1013 base::Bind([](MojoResult result, MojoHandleSignalsState state) { | |
1014 NOTREACHED(); | |
1015 }), | |
1016 base::Bind([](base::WaitableEvent* event) { event->Signal(); }, &event)); | |
1017 | |
1018 uintptr_t readable_c_context = helper.CreateContext(base::Bind( | |
1019 [](MojoHandle w, MojoHandle a, MojoHandle b, MojoHandle c, | |
1020 MojoResult result, MojoHandleSignalsState state) { | |
1021 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1022 EXPECT_EQ(kTestMessageToC, ReadMessage(c)); | |
1023 | |
1024 // Now rearm the watcher. | |
1025 EXPECT_EQ(MOJO_RESULT_OK, | |
1026 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1027 | |
1028 // Must result in exactly ONE notification on the above context, for | |
1029 // CANCELLED only. Because we cannot dispatch notifications until the | |
1030 // stack unwinds, and because we must never dispatch non-cancellation | |
1031 // notifications for a handle once it's been closed, we must be certain | |
1032 // that cancellation due to closure preemptively invalidates any | |
1033 // pending non-cancellation notifications queued on the current | |
1034 // RequestContext, such as the one resulting from the WriteMessage here. | |
1035 WriteMessage(b, kTestMessageToA); | |
1036 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
1037 | |
1038 // Rearming should be fine since |a|'s watch should already be | |
1039 // implicitly cancelled (even though the notification will not have | |
1040 // been invoked yet.) | |
1041 EXPECT_EQ(MOJO_RESULT_OK, | |
1042 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1043 | |
1044 // Nothing interesting should happen as a result of this. | |
1045 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
1046 }, | |
1047 w, a, b, c)); | |
1048 | |
1049 EXPECT_EQ(MOJO_RESULT_OK, | |
1050 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
1051 EXPECT_EQ(MOJO_RESULT_OK, | |
1052 MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE, readable_c_context)); | |
1053 EXPECT_EQ(MOJO_RESULT_OK, | |
1054 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1055 | |
1056 WriteMessage(d, kTestMessageToC); | |
1057 event.Wait(); | |
1058 | |
1059 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
1060 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); | |
1061 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d)); | |
1062 } | |
1063 | |
1064 TEST_F(WatcherTest, ExplicitCancelOtherFromNotificationCallback) { | |
1065 MojoHandle a, b; | |
1066 CreateMessagePipe(&a, &b); | |
1067 | |
1068 MojoHandle c, d; | |
1069 CreateMessagePipe(&c, &d); | |
1070 | |
1071 static const char kTestMessageToA[] = "hi a"; | |
1072 static const char kTestMessageToC[] = "hi c"; | |
1073 | |
1074 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
1075 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1076 | |
1077 WatchHelper helper; | |
1078 MojoHandle w; | |
1079 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
1080 | |
1081 uintptr_t readable_a_context = helper.CreateContext(base::Bind( | |
1082 [](MojoResult result, MojoHandleSignalsState state) { NOTREACHED(); })); | |
1083 | |
1084 uintptr_t readable_c_context = helper.CreateContext(base::Bind( | |
1085 [](base::WaitableEvent* event, uintptr_t readable_a_context, MojoHandle w, | |
1086 MojoHandle a, MojoHandle b, MojoHandle c, MojoResult result, | |
1087 MojoHandleSignalsState state) { | |
1088 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1089 EXPECT_EQ(kTestMessageToC, ReadMessage(c)); | |
1090 | |
1091 // Now rearm the watcher. | |
1092 EXPECT_EQ(MOJO_RESULT_OK, | |
1093 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1094 | |
1095 // Should result in no notifications on the above context, because the | |
1096 // watch will have been cancelled by the time the notification callback | |
1097 // can execute. | |
1098 WriteMessage(b, kTestMessageToA); | |
1099 WriteMessage(b, kTestMessageToA); | |
1100 EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, readable_a_context)); | |
1101 | |
1102 // Rearming should be fine now. | |
1103 EXPECT_EQ(MOJO_RESULT_OK, | |
1104 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1105 | |
1106 // Nothing interesting should happen as a result of these. | |
1107 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
1108 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
1109 | |
1110 event->Signal(); | |
1111 }, | |
1112 &event, readable_a_context, w, a, b, c)); | |
1113 | |
1114 EXPECT_EQ(MOJO_RESULT_OK, | |
1115 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
1116 EXPECT_EQ(MOJO_RESULT_OK, | |
1117 MojoWatch(w, c, MOJO_HANDLE_SIGNAL_READABLE, readable_c_context)); | |
1118 EXPECT_EQ(MOJO_RESULT_OK, | |
1119 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1120 | |
1121 WriteMessage(d, kTestMessageToC); | |
1122 event.Wait(); | |
1123 | |
1124 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
1125 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); | |
1126 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d)); | |
1127 } | |
1128 | |
1129 TEST_F(WatcherTest, NestedCancellation) { | |
1130 MojoHandle a, b; | |
1131 CreateMessagePipe(&a, &b); | |
1132 | |
1133 MojoHandle c, d; | |
1134 CreateMessagePipe(&c, &d); | |
1135 | |
1136 static const char kTestMessageToA[] = "hey a"; | |
1137 static const char kTestMessageToC[] = "hey c"; | |
1138 static const char kTestMessageToD[] = "hey d"; | |
1139 | |
1140 // This is a tricky test. It establishes a watch on |b| using one watcher and | |
1141 // watches on |c| and |d| using another watcher. | |
1142 // | |
1143 // A message is written to |d| to wake up |c|'s watch, and the notification | |
1144 // handler for that event does the following: | |
1145 // 1. Writes to |a| to eventually wake up |b|'s watcher. | |
1146 // 2. Rearms |c|'s watcher. | |
1147 // 3. Writes to |d| to eventually wake up |c|'s watcher again. | |
1148 // | |
1149 // Meanwhile, |b|'s watch notification handler cancels |c|'s watch altogether | |
1150 // before writing to |c| to wake up |d|. | |
1151 // | |
1152 // The net result should be that |c|'s context only gets notified once (from | |
1153 // the first write to |d| above) and everyone else gets notified as expected. | |
1154 | |
1155 MojoHandle b_watcher; | |
1156 MojoHandle cd_watcher; | |
1157 WatchHelper helper; | |
1158 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&b_watcher)); | |
1159 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&cd_watcher)); | |
1160 | |
1161 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
1162 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1163 uintptr_t readable_d_context = helper.CreateContext(base::Bind( | |
1164 [](base::WaitableEvent* event, MojoHandle d, MojoResult result, | |
1165 MojoHandleSignalsState state) { | |
1166 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1167 EXPECT_EQ(kTestMessageToD, ReadMessage(d)); | |
1168 event->Signal(); | |
1169 }, | |
1170 &event, d)); | |
1171 | |
1172 static int num_expected_c_notifications = 1; | |
1173 uintptr_t readable_c_context = helper.CreateContext(base::Bind( | |
1174 [](MojoHandle cd_watcher, MojoHandle a, MojoHandle c, MojoHandle d, | |
1175 MojoResult result, MojoHandleSignalsState state) { | |
1176 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1177 EXPECT_GT(num_expected_c_notifications--, 0); | |
1178 | |
1179 // Trigger an eventual |readable_b_context| notification. | |
1180 WriteMessage(a, kTestMessageToA); | |
1181 | |
1182 EXPECT_EQ(kTestMessageToC, ReadMessage(c)); | |
1183 EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(cd_watcher, nullptr, nullptr, | |
1184 nullptr, nullptr)); | |
1185 | |
1186 // Trigger another eventual |readable_c_context| notification. | |
1187 WriteMessage(d, kTestMessageToC); | |
1188 }, | |
1189 cd_watcher, a, c, d)); | |
1190 | |
1191 uintptr_t readable_b_context = helper.CreateContext(base::Bind( | |
1192 [](MojoHandle cd_watcher, uintptr_t readable_c_context, MojoHandle c, | |
1193 MojoResult result, MojoHandleSignalsState state) { | |
1194 EXPECT_EQ(MOJO_RESULT_OK, | |
1195 MojoCancelWatch(cd_watcher, readable_c_context)); | |
1196 | |
1197 EXPECT_EQ(MOJO_RESULT_OK, MojoArmWatcher(cd_watcher, nullptr, nullptr, | |
1198 nullptr, nullptr)); | |
1199 | |
1200 WriteMessage(c, kTestMessageToD); | |
1201 }, | |
1202 cd_watcher, readable_c_context, c)); | |
1203 | |
1204 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, | |
1205 readable_b_context)); | |
1206 EXPECT_EQ(MOJO_RESULT_OK, | |
1207 MojoWatch(cd_watcher, c, MOJO_HANDLE_SIGNAL_READABLE, | |
1208 readable_c_context)); | |
1209 EXPECT_EQ(MOJO_RESULT_OK, | |
1210 MojoWatch(cd_watcher, d, MOJO_HANDLE_SIGNAL_READABLE, | |
1211 readable_d_context)); | |
1212 | |
1213 EXPECT_EQ(MOJO_RESULT_OK, | |
1214 MojoArmWatcher(b_watcher, nullptr, nullptr, nullptr, nullptr)); | |
1215 EXPECT_EQ(MOJO_RESULT_OK, | |
1216 MojoArmWatcher(cd_watcher, nullptr, nullptr, nullptr, nullptr)); | |
1217 | |
1218 WriteMessage(d, kTestMessageToC); | |
1219 event.Wait(); | |
1220 | |
1221 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(cd_watcher)); | |
1222 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b_watcher)); | |
1223 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
1224 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
1225 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(c)); | |
1226 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d)); | |
1227 } | |
1228 | |
1229 TEST_F(WatcherTest, CancelSelfInNotificationCallback) { | |
1230 MojoHandle a, b; | |
1231 CreateMessagePipe(&a, &b); | |
1232 | |
1233 static const char kTestMessageToA[] = "hey a"; | |
1234 | |
1235 MojoHandle w; | |
1236 WatchHelper helper; | |
1237 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
1238 | |
1239 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
1240 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1241 | |
1242 static uintptr_t readable_a_context = helper.CreateContext(base::Bind( | |
1243 [](base::WaitableEvent* event, MojoHandle w, MojoHandle a, | |
1244 MojoResult result, MojoHandleSignalsState state) { | |
1245 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1246 | |
1247 // There should be no problem cancelling this watch from its own | |
1248 // notification invocation. | |
1249 EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, readable_a_context)); | |
1250 EXPECT_EQ(kTestMessageToA, ReadMessage(a)); | |
1251 | |
1252 // Arming should fail because there are no longer any registered | |
1253 // watches on the watcher. | |
1254 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, | |
1255 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1256 | |
1257 // And closing |a| should be fine (and should not invoke this | |
1258 // notification with MOJO_RESULT_CANCELLED) for the same reason. | |
1259 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
1260 | |
1261 event->Signal(); | |
1262 }, | |
1263 &event, w, a)); | |
1264 | |
1265 EXPECT_EQ(MOJO_RESULT_OK, | |
1266 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
1267 EXPECT_EQ(MOJO_RESULT_OK, | |
1268 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1269 | |
1270 WriteMessage(b, kTestMessageToA); | |
1271 event.Wait(); | |
1272 | |
1273 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
1274 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
1275 } | |
1276 | |
1277 TEST_F(WatcherTest, CloseWatcherInNotificationCallback) { | |
1278 MojoHandle a, b; | |
1279 CreateMessagePipe(&a, &b); | |
1280 | |
1281 static const char kTestMessageToA1[] = "hey a"; | |
1282 static const char kTestMessageToA2[] = "hey a again"; | |
1283 | |
1284 MojoHandle w; | |
1285 WatchHelper helper; | |
1286 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
1287 | |
1288 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
1289 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1290 | |
1291 uintptr_t readable_a_context = helper.CreateContext(base::Bind( | |
1292 [](base::WaitableEvent* event, MojoHandle w, MojoHandle a, MojoHandle b, | |
1293 MojoResult result, MojoHandleSignalsState state) { | |
1294 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1295 EXPECT_EQ(kTestMessageToA1, ReadMessage(a)); | |
1296 EXPECT_EQ(MOJO_RESULT_OK, | |
1297 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1298 | |
1299 // There should be no problem closing this watcher from its own | |
1300 // notification callback. | |
1301 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
1302 | |
1303 // And these should not trigger more notifications, because |w| has been | |
1304 // closed already. | |
1305 WriteMessage(b, kTestMessageToA2); | |
1306 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
1307 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
1308 | |
1309 event->Signal(); | |
1310 }, | |
1311 &event, w, a, b)); | |
1312 | |
1313 EXPECT_EQ(MOJO_RESULT_OK, | |
1314 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
1315 EXPECT_EQ(MOJO_RESULT_OK, | |
1316 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1317 | |
1318 WriteMessage(b, kTestMessageToA1); | |
1319 event.Wait(); | |
1320 } | |
1321 | |
1322 TEST_F(WatcherTest, CloseWatcherAfterImplicitCancel) { | |
1323 MojoHandle a, b; | |
1324 CreateMessagePipe(&a, &b); | |
1325 | |
1326 static const char kTestMessageToA[] = "hey a"; | |
1327 | |
1328 MojoHandle w; | |
1329 WatchHelper helper; | |
1330 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
1331 | |
1332 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
1333 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1334 | |
1335 uintptr_t readable_a_context = helper.CreateContext(base::Bind( | |
1336 [](base::WaitableEvent* event, MojoHandle w, MojoHandle a, | |
1337 MojoResult result, MojoHandleSignalsState state) { | |
1338 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1339 EXPECT_EQ(kTestMessageToA, ReadMessage(a)); | |
1340 EXPECT_EQ(MOJO_RESULT_OK, | |
1341 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1342 | |
1343 // This will cue up a notification for |MOJO_RESULT_CANCELLED|... | |
1344 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
1345 | |
1346 // ...but it should never fire because we close the watcher here. | |
1347 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
1348 | |
1349 event->Signal(); | |
1350 }, | |
1351 &event, w, a)); | |
1352 | |
1353 EXPECT_EQ(MOJO_RESULT_OK, | |
1354 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
1355 EXPECT_EQ(MOJO_RESULT_OK, | |
1356 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1357 | |
1358 WriteMessage(b, kTestMessageToA); | |
1359 event.Wait(); | |
1360 | |
1361 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
1362 } | |
1363 | |
1364 TEST_F(WatcherTest, OtherThreadCancelDuringNotification) { | |
1365 MojoHandle a, b; | |
1366 CreateMessagePipe(&a, &b); | |
1367 | |
1368 static const char kTestMessageToA[] = "hey a"; | |
1369 | |
1370 MojoHandle w; | |
1371 WatchHelper helper; | |
1372 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
1373 | |
1374 base::WaitableEvent wait_for_notification( | |
1375 base::WaitableEvent::ResetPolicy::MANUAL, | |
1376 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1377 | |
1378 base::WaitableEvent wait_for_cancellation( | |
1379 base::WaitableEvent::ResetPolicy::MANUAL, | |
1380 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1381 | |
1382 static bool callback_done = false; | |
1383 uintptr_t readable_a_context = helper.CreateContextWithCancel( | |
1384 base::Bind( | |
1385 [](base::WaitableEvent* wait_for_notification, MojoHandle w, | |
1386 MojoHandle a, MojoResult result, MojoHandleSignalsState state) { | |
1387 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1388 EXPECT_EQ(kTestMessageToA, ReadMessage(a)); | |
1389 | |
1390 wait_for_notification->Signal(); | |
1391 | |
1392 // Give the other thread sufficient time to race with the completion | |
1393 // of this callback. There should be no race, since the cancellation | |
1394 // notification must be mutually exclusive to this notification. | |
1395 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); | |
1396 | |
1397 callback_done = true; | |
1398 }, | |
1399 &wait_for_notification, w, a), | |
1400 base::Bind( | |
1401 [](base::WaitableEvent* wait_for_cancellation) { | |
1402 EXPECT_TRUE(callback_done); | |
1403 wait_for_cancellation->Signal(); | |
1404 }, | |
1405 &wait_for_cancellation)); | |
1406 | |
1407 ThreadedRunner runner(base::Bind( | |
1408 [](base::WaitableEvent* wait_for_notification, | |
1409 base::WaitableEvent* wait_for_cancellation, MojoHandle w, | |
1410 uintptr_t readable_a_context) { | |
1411 wait_for_notification->Wait(); | |
1412 | |
1413 // Cancel the watch while the notification is still running. | |
1414 EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, readable_a_context)); | |
1415 | |
1416 wait_for_cancellation->Wait(); | |
1417 | |
1418 EXPECT_TRUE(callback_done); | |
1419 }, | |
1420 &wait_for_notification, &wait_for_cancellation, w, readable_a_context)); | |
1421 runner.Start(); | |
1422 | |
1423 EXPECT_EQ(MOJO_RESULT_OK, | |
1424 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, readable_a_context)); | |
1425 EXPECT_EQ(MOJO_RESULT_OK, | |
1426 MojoArmWatcher(w, nullptr, nullptr, nullptr, nullptr)); | |
1427 | |
1428 WriteMessage(b, kTestMessageToA); | |
1429 runner.Join(); | |
1430 | |
1431 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
1432 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
1433 } | |
1434 | |
1435 TEST_F(WatcherTest, WatchesCancelEachOtherFromNotifications) { | |
1436 MojoHandle a, b; | |
1437 CreateMessagePipe(&a, &b); | |
1438 | |
1439 static const char kTestMessageToA[] = "hey a"; | |
1440 static const char kTestMessageToB[] = "hey b"; | |
1441 | |
1442 base::WaitableEvent wait_for_a_to_notify( | |
1443 base::WaitableEvent::ResetPolicy::MANUAL, | |
1444 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1445 base::WaitableEvent wait_for_b_to_notify( | |
1446 base::WaitableEvent::ResetPolicy::MANUAL, | |
1447 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1448 base::WaitableEvent wait_for_a_to_cancel( | |
1449 base::WaitableEvent::ResetPolicy::MANUAL, | |
1450 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1451 base::WaitableEvent wait_for_b_to_cancel( | |
1452 base::WaitableEvent::ResetPolicy::MANUAL, | |
1453 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1454 | |
1455 MojoHandle a_watcher; | |
1456 MojoHandle b_watcher; | |
1457 WatchHelper helper; | |
1458 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&a_watcher)); | |
1459 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&b_watcher)); | |
1460 | |
1461 // We set up two watchers, one on |a| and one on |b|. They cancel each other | |
1462 // from within their respective watch notifications. This should be safe, | |
1463 // i.e., it should not deadlock, in spite of the fact that we also guarantee | |
1464 // mutually exclusive notification execution (including cancellations) on any | |
1465 // given watch. | |
1466 bool a_cancelled = false; | |
1467 bool b_cancelled = false; | |
1468 static uintptr_t readable_b_context; | |
1469 uintptr_t readable_a_context = helper.CreateContextWithCancel( | |
1470 base::Bind( | |
1471 [](base::WaitableEvent* wait_for_a_to_notify, | |
1472 base::WaitableEvent* wait_for_b_to_notify, MojoHandle b_watcher, | |
1473 MojoHandle a, MojoResult result, MojoHandleSignalsState state) { | |
1474 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1475 EXPECT_EQ(kTestMessageToA, ReadMessage(a)); | |
1476 wait_for_a_to_notify->Signal(); | |
1477 wait_for_b_to_notify->Wait(); | |
1478 EXPECT_EQ(MOJO_RESULT_OK, | |
1479 MojoCancelWatch(b_watcher, readable_b_context)); | |
1480 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b_watcher)); | |
1481 }, | |
1482 &wait_for_a_to_notify, &wait_for_b_to_notify, b_watcher, a), | |
1483 base::Bind( | |
1484 [](base::WaitableEvent* wait_for_a_to_cancel, | |
1485 base::WaitableEvent* wait_for_b_to_cancel, bool* a_cancelled) { | |
1486 *a_cancelled = true; | |
1487 wait_for_a_to_cancel->Signal(); | |
1488 wait_for_b_to_cancel->Wait(); | |
1489 }, | |
1490 &wait_for_a_to_cancel, &wait_for_b_to_cancel, &a_cancelled)); | |
1491 | |
1492 readable_b_context = helper.CreateContextWithCancel( | |
1493 base::Bind( | |
1494 [](base::WaitableEvent* wait_for_a_to_notify, | |
1495 base::WaitableEvent* wait_for_b_to_notify, | |
1496 uintptr_t readable_a_context, MojoHandle a_watcher, MojoHandle b, | |
1497 MojoResult result, MojoHandleSignalsState state) { | |
1498 EXPECT_EQ(MOJO_RESULT_OK, result); | |
1499 EXPECT_EQ(kTestMessageToB, ReadMessage(b)); | |
1500 wait_for_b_to_notify->Signal(); | |
1501 wait_for_a_to_notify->Wait(); | |
1502 EXPECT_EQ(MOJO_RESULT_OK, | |
1503 MojoCancelWatch(a_watcher, readable_a_context)); | |
1504 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a_watcher)); | |
1505 }, | |
1506 &wait_for_a_to_notify, &wait_for_b_to_notify, readable_a_context, | |
1507 a_watcher, b), | |
1508 base::Bind( | |
1509 [](base::WaitableEvent* wait_for_a_to_cancel, | |
1510 base::WaitableEvent* wait_for_b_to_cancel, bool* b_cancelled) { | |
1511 *b_cancelled = true; | |
1512 wait_for_b_to_cancel->Signal(); | |
1513 wait_for_a_to_cancel->Wait(); | |
1514 }, | |
1515 &wait_for_a_to_cancel, &wait_for_b_to_cancel, &b_cancelled)); | |
1516 | |
1517 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(a_watcher, a, MOJO_HANDLE_SIGNAL_READABLE, | |
1518 readable_a_context)); | |
1519 EXPECT_EQ(MOJO_RESULT_OK, | |
1520 MojoArmWatcher(a_watcher, nullptr, nullptr, nullptr, nullptr)); | |
1521 EXPECT_EQ(MOJO_RESULT_OK, MojoWatch(b_watcher, b, MOJO_HANDLE_SIGNAL_READABLE, | |
1522 readable_b_context)); | |
1523 EXPECT_EQ(MOJO_RESULT_OK, | |
1524 MojoArmWatcher(b_watcher, nullptr, nullptr, nullptr, nullptr)); | |
1525 | |
1526 ThreadedRunner runner( | |
1527 base::Bind([](MojoHandle b) { WriteMessage(b, kTestMessageToA); }, b)); | |
1528 runner.Start(); | |
1529 | |
1530 WriteMessage(a, kTestMessageToB); | |
1531 | |
1532 wait_for_a_to_cancel.Wait(); | |
1533 wait_for_b_to_cancel.Wait(); | |
1534 runner.Join(); | |
1535 | |
1536 EXPECT_TRUE(a_cancelled); | |
1537 EXPECT_TRUE(b_cancelled); | |
1538 | |
1539 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
1540 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
1541 } | |
1542 | |
1543 TEST_F(WatcherTest, AlwaysCancel) { | |
1544 // Basic sanity check to ensure that all possible ways to cancel a watch | |
1545 // result in a final MOJO_RESULT_CANCELLED notification. | |
1546 | |
1547 MojoHandle a, b; | |
1548 CreateMessagePipe(&a, &b); | |
1549 | |
1550 MojoHandle w; | |
1551 WatchHelper helper; | |
1552 EXPECT_EQ(MOJO_RESULT_OK, helper.CreateWatcher(&w)); | |
1553 | |
1554 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | |
1555 base::WaitableEvent::InitialState::NOT_SIGNALED); | |
1556 const base::Closure signal_event = | |
1557 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)); | |
1558 | |
1559 // Cancel via |MojoCancelWatch()|. | |
1560 uintptr_t context = helper.CreateContextWithCancel( | |
1561 WatchHelper::ContextCallback(), signal_event); | |
1562 EXPECT_EQ(MOJO_RESULT_OK, | |
1563 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, context)); | |
1564 EXPECT_EQ(MOJO_RESULT_OK, MojoCancelWatch(w, context)); | |
1565 event.Wait(); | |
1566 event.Reset(); | |
1567 | |
1568 // Cancel by closing the watched handle. | |
1569 context = helper.CreateContextWithCancel(WatchHelper::ContextCallback(), | |
1570 signal_event); | |
1571 EXPECT_EQ(MOJO_RESULT_OK, | |
1572 MojoWatch(w, a, MOJO_HANDLE_SIGNAL_READABLE, context)); | |
1573 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); | |
1574 event.Wait(); | |
1575 event.Reset(); | |
1576 | |
1577 // Cancel by closing the watcher handle. | |
1578 context = helper.CreateContextWithCancel(WatchHelper::ContextCallback(), | |
1579 signal_event); | |
1580 EXPECT_EQ(MOJO_RESULT_OK, | |
1581 MojoWatch(w, b, MOJO_HANDLE_SIGNAL_READABLE, context)); | |
1582 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(w)); | |
1583 event.Wait(); | |
1584 | |
1585 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); | |
1586 } | |
1587 | |
1588 } // namespace | |
1589 } // namespace edk | |
1590 } // namespace mojo | |
OLD | NEW |