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

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
« no previous file with comments | « mojo/edk/system/watcher_set.cc ('k') | mojo/public/c/system/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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
OLDNEW
« no previous file with comments | « mojo/edk/system/watcher_set.cc ('k') | mojo/public/c/system/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698