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

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

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

Powered by Google App Engine
This is Rietveld 408576698