1 // Copyright 2013 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 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
6 // heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to
7 // increase tolerance and reduce observed flakiness (though doing so reduces the
8 // meaningfulness of the test).
9
10 #include "mojo/system/simple_dispatcher.h"
11
12 #include "base/basictypes.h"
13 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/synchronization/lock.h"
17 #include "base/threading/platform_thread.h" // For |Sleep()|.
18 #include "base/time/time.h"
19 #include "mojo/system/test_utils.h"
20 #include "mojo/system/waiter.h"
21 #include "mojo/system/waiter_test_utils.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 namespace mojo {
25 namespace system {
26 namespace {
27
28 class MockSimpleDispatcher : public SimpleDispatcher {
29 public:
MockSimpleDispatcher()30 MockSimpleDispatcher()
31 : state_(MOJO_HANDLE_SIGNAL_NONE,
32 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE) {}
33
SetSatisfiedSignals(MojoHandleSignals new_satisfied_signals)34 void SetSatisfiedSignals(MojoHandleSignals new_satisfied_signals) {
35 base::AutoLock locker(lock());
36
37 // Any new signals that are set should be satisfiable.
38 CHECK_EQ(new_satisfied_signals & ~state_.satisfied_signals,
39 new_satisfied_signals & ~state_.satisfied_signals &
40 state_.satisfiable_signals);
41
42 if (new_satisfied_signals == state_.satisfied_signals)
43 return;
44
45 state_.satisfied_signals = new_satisfied_signals;
46 HandleSignalsStateChangedNoLock();
47 }
48
SetSatisfiableSignals(MojoHandleSignals new_satisfiable_signals)49 void SetSatisfiableSignals(MojoHandleSignals new_satisfiable_signals) {
50 base::AutoLock locker(lock());
51
52 // Satisfied implies satisfiable.
53 CHECK_EQ(new_satisfiable_signals & state_.satisfied_signals,
54 state_.satisfied_signals);
55
56 if (new_satisfiable_signals == state_.satisfiable_signals)
57 return;
58
59 state_.satisfiable_signals = new_satisfiable_signals;
60 HandleSignalsStateChangedNoLock();
61 }
62
GetType() const63 virtual Type GetType() const OVERRIDE {
64 return kTypeUnknown;
65 }
66
67 private:
68 friend class base::RefCountedThreadSafe<MockSimpleDispatcher>;
~MockSimpleDispatcher()69 virtual ~MockSimpleDispatcher() {}
70
71 virtual scoped_refptr<Dispatcher>
CreateEquivalentDispatcherAndCloseImplNoLock()72 CreateEquivalentDispatcherAndCloseImplNoLock() OVERRIDE {
73 scoped_refptr<MockSimpleDispatcher> rv(new MockSimpleDispatcher());
74 rv->state_ = state_;
75 return scoped_refptr<Dispatcher>(rv.get());
76 }
77
78 // |SimpleDispatcher| implementation:
GetHandleSignalsStateNoLock() const79 virtual HandleSignalsState GetHandleSignalsStateNoLock() const OVERRIDE {
80 lock().AssertAcquired();
81 return state_;
82 }
83
84 // Protected by |lock()|:
85 HandleSignalsState state_;
86
87 DISALLOW_COPY_AND_ASSIGN(MockSimpleDispatcher);
88 };
89
TEST(SimpleDispatcherTest,Basic)90 TEST(SimpleDispatcherTest, Basic) {
91 test::Stopwatch stopwatch;
92
93 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
94 Waiter w;
95 uint32_t context = 0;
96
97 // Try adding a readable waiter when already readable.
98 w.Init();
99 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
100 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
101 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0));
102 // Shouldn't need to remove the waiter (it was not added).
103
104 // Wait (forever) for writable when already writable.
105 w.Init();
106 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
107 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1));
108 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
109 stopwatch.Start();
110 EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
111 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
112 EXPECT_EQ(1u, context);
113 d->RemoveWaiter(&w);
114
115 // Wait for zero time for writable when already writable.
116 w.Init();
117 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
118 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2));
119 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
120 stopwatch.Start();
121 EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, &context));
122 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
123 EXPECT_EQ(2u, context);
124 d->RemoveWaiter(&w);
125
126 // Wait for non-zero, finite time for writable when already writable.
127 w.Init();
128 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
129 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3));
130 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
131 stopwatch.Start();
132 EXPECT_EQ(MOJO_RESULT_OK,
133 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
134 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
135 EXPECT_EQ(3u, context);
136 d->RemoveWaiter(&w);
137
138 // Wait for zero time for writable when not writable (will time out).
139 w.Init();
140 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
141 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4));
142 stopwatch.Start();
143 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, NULL));
144 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
145 d->RemoveWaiter(&w);
146
147 // Wait for non-zero, finite time for writable when not writable (will time
148 // out).
149 w.Init();
150 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
151 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5));
152 stopwatch.Start();
153 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
154 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), NULL));
155 base::TimeDelta elapsed = stopwatch.Elapsed();
156 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
157 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
158 d->RemoveWaiter(&w);
159
160 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
161 }
162
TEST(SimpleDispatcherTest,BasicUnsatisfiable)163 TEST(SimpleDispatcherTest, BasicUnsatisfiable) {
164 test::Stopwatch stopwatch;
165
166 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
167 Waiter w;
168 uint32_t context = 0;
169
170 // Try adding a writable waiter when it can never be writable.
171 w.Init();
172 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
173 d->SetSatisfiedSignals(0);
174 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
175 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1));
176 // Shouldn't need to remove the waiter (it was not added).
177
178 // Wait (forever) for writable and then it becomes never writable.
179 w.Init();
180 d->SetSatisfiableSignals(
181 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
182 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2));
183 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
184 stopwatch.Start();
185 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
186 w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
187 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
188 EXPECT_EQ(2u, context);
189 d->RemoveWaiter(&w);
190
191 // Wait for zero time for writable and then it becomes never writable.
192 w.Init();
193 d->SetSatisfiableSignals(
194 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
195 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3));
196 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
197 stopwatch.Start();
198 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0, &context));
199 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
200 EXPECT_EQ(3u, context);
201 d->RemoveWaiter(&w);
202
203 // Wait for non-zero, finite time for writable and then it becomes never
204 // writable.
205 w.Init();
206 d->SetSatisfiableSignals(
207 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
208 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4));
209 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
210 stopwatch.Start();
211 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
212 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
213 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
214 EXPECT_EQ(4u, context);
215 d->RemoveWaiter(&w);
216
217 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
218 }
219
TEST(SimpleDispatcherTest,BasicClosed)220 TEST(SimpleDispatcherTest, BasicClosed) {
221 test::Stopwatch stopwatch;
222
223 scoped_refptr<MockSimpleDispatcher> d;
224 Waiter w;
225 uint32_t context = 0;
226
227 // Try adding a writable waiter when the dispatcher has been closed.
228 d = new MockSimpleDispatcher();
229 w.Init();
230 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
231 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
232 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1));
233 // Shouldn't need to remove the waiter (it was not added).
234
235 // Wait (forever) for writable and then the dispatcher is closed.
236 d = new MockSimpleDispatcher();
237 w.Init();
238 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2));
239 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
240 stopwatch.Start();
241 EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
242 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
243 EXPECT_EQ(2u, context);
244 // Don't need to remove waiters from closed dispatchers.
245
246 // Wait for zero time for writable and then the dispatcher is closed.
247 d = new MockSimpleDispatcher();
248 w.Init();
249 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3));
250 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
251 stopwatch.Start();
252 EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context));
253 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
254 EXPECT_EQ(3u, context);
255 // Don't need to remove waiters from closed dispatchers.
256
257 // Wait for non-zero, finite time for writable and then the dispatcher is
258 // closed.
259 d = new MockSimpleDispatcher();
260 w.Init();
261 EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4));
262 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
263 stopwatch.Start();
264 EXPECT_EQ(MOJO_RESULT_CANCELLED,
265 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
266 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
267 EXPECT_EQ(4u, context);
268 // Don't need to remove waiters from closed dispatchers.
269 }
270
TEST(SimpleDispatcherTest,BasicThreaded)271 TEST(SimpleDispatcherTest, BasicThreaded) {
272 test::Stopwatch stopwatch;
273 bool did_wait;
274 MojoResult result;
275 uint32_t context;
276
277 // Wait for readable (already readable).
278 {
279 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
280 {
281 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
282 test::WaiterThread thread(d,
283 MOJO_HANDLE_SIGNAL_READABLE,
284 MOJO_DEADLINE_INDEFINITE,
285 1,
286 &did_wait, &result, &context);
287 stopwatch.Start();
288 thread.Start();
289 } // Joins the thread.
290 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|.
291 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
292 }
293 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
294 EXPECT_FALSE(did_wait);
295 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result);
296
297 // Wait for readable and becomes readable after some time.
298 {
299 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
300 test::WaiterThread thread(d,
301 MOJO_HANDLE_SIGNAL_READABLE,
302 MOJO_DEADLINE_INDEFINITE,
303 2,
304 &did_wait, &result, &context);
305 stopwatch.Start();
306 thread.Start();
307 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
308 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
309 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
310 } // Joins the thread.
311 base::TimeDelta elapsed = stopwatch.Elapsed();
312 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
313 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
314 EXPECT_TRUE(did_wait);
315 EXPECT_EQ(MOJO_RESULT_OK, result);
316 EXPECT_EQ(2u, context);
317
318 // Wait for readable and becomes never-readable after some time.
319 {
320 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
321 test::WaiterThread thread(d,
322 MOJO_HANDLE_SIGNAL_READABLE,
323 MOJO_DEADLINE_INDEFINITE,
324 3,
325 &did_wait, &result, &context);
326 stopwatch.Start();
327 thread.Start();
328 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
329 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_NONE);
330 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
331 } // Joins the thread.
332 elapsed = stopwatch.Elapsed();
333 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
334 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
335 EXPECT_TRUE(did_wait);
336 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
337 EXPECT_EQ(3u, context);
338
339 // Wait for readable and dispatcher gets closed.
340 {
341 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
342 test::WaiterThread thread(d,
343 MOJO_HANDLE_SIGNAL_READABLE,
344 MOJO_DEADLINE_INDEFINITE,
345 4,
346 &did_wait, &result, &context);
347 stopwatch.Start();
348 thread.Start();
349 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
350 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
351 } // Joins the thread.
352 elapsed = stopwatch.Elapsed();
353 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
354 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
355 EXPECT_TRUE(did_wait);
356 EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
357 EXPECT_EQ(4u, context);
358
359 // Wait for readable and times out.
360 {
361 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
362 {
363 test::WaiterThread thread(d,
364 MOJO_HANDLE_SIGNAL_READABLE,
365 2 * test::EpsilonTimeout().InMicroseconds(),
366 5,
367 &did_wait, &result, &context);
368 stopwatch.Start();
369 thread.Start();
370 base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
371 // Not what we're waiting for.
372 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
373 } // Joins the thread (after its wait times out).
374 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|.
375 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
376 }
377 elapsed = stopwatch.Elapsed();
378 EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
379 EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
380 EXPECT_TRUE(did_wait);
381 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result);
382 }
383
TEST(SimpleDispatcherTest,MultipleWaiters)384 TEST(SimpleDispatcherTest, MultipleWaiters) {
385 static const uint32_t kNumWaiters = 20;
386
387 bool did_wait[kNumWaiters];
388 MojoResult result[kNumWaiters];
389 uint32_t context[kNumWaiters];
390
391 // All wait for readable and becomes readable after some time.
392 {
393 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
394 ScopedVector<test::WaiterThread> threads;
395 for (uint32_t i = 0; i < kNumWaiters; i++) {
396 threads.push_back(new test::WaiterThread(d,
397 MOJO_HANDLE_SIGNAL_READABLE,
398 MOJO_DEADLINE_INDEFINITE,
399 i,
400 &did_wait[i],
401 &result[i],
402 &context[i]));
403 threads.back()->Start();
404 }
405 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
406 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
407 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
408 } // Joins the threads.
409 for (uint32_t i = 0; i < kNumWaiters; i++) {
410 EXPECT_TRUE(did_wait[i]);
411 EXPECT_EQ(MOJO_RESULT_OK, result[i]);
412 EXPECT_EQ(i, context[i]);
413 }
414
415 // Some wait for readable, some for writable, and becomes readable after some
416 // time.
417 {
418 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
419 ScopedVector<test::WaiterThread> threads;
420 for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
421 threads.push_back(new test::WaiterThread(d,
422 MOJO_HANDLE_SIGNAL_READABLE,
423 MOJO_DEADLINE_INDEFINITE,
424 i,
425 &did_wait[i],
426 &result[i],
427 &context[i]));
428 threads.back()->Start();
429 }
430 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
431 threads.push_back(new test::WaiterThread(d,
432 MOJO_HANDLE_SIGNAL_WRITABLE,
433 MOJO_DEADLINE_INDEFINITE,
434 i,
435 &did_wait[i],
436 &result[i],
437 &context[i]));
438 threads.back()->Start();
439 }
440 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
441 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
442 // This will wake up the ones waiting to write.
443 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
444 } // Joins the threads.
445 for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
446 EXPECT_TRUE(did_wait[i]);
447 EXPECT_EQ(MOJO_RESULT_OK, result[i]);
448 EXPECT_EQ(i, context[i]);
449 }
450 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
451 EXPECT_TRUE(did_wait[i]);
452 EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]);
453 EXPECT_EQ(i, context[i]);
454 }
455
456 // Some wait for readable, some for writable, and becomes readable and
457 // never-writable after some time.
458 {
459 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
460 ScopedVector<test::WaiterThread> threads;
461 for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
462 threads.push_back(new test::WaiterThread(d,
463 MOJO_HANDLE_SIGNAL_READABLE,
464 MOJO_DEADLINE_INDEFINITE,
465 i,
466 &did_wait[i],
467 &result[i],
468 &context[i]));
469 threads.back()->Start();
470 }
471 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
472 threads.push_back(new test::WaiterThread(d,
473 MOJO_HANDLE_SIGNAL_WRITABLE,
474 MOJO_DEADLINE_INDEFINITE,
475 i,
476 &did_wait[i],
477 &result[i],
478 &context[i]));
479 threads.back()->Start();
480 }
481 base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
482 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
483 base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
484 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
485 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
486 } // Joins the threads.
487 for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
488 EXPECT_TRUE(did_wait[i]);
489 EXPECT_EQ(MOJO_RESULT_OK, result[i]);
490 EXPECT_EQ(i, context[i]);
491 }
492 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
493 EXPECT_TRUE(did_wait[i]);
494 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]);
495 EXPECT_EQ(i, context[i]);
496 }
497
498 // Some wait for readable, some for writable, and becomes readable after some
499 // time.
500 {
501 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
502 ScopedVector<test::WaiterThread> threads;
503 for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
504 threads.push_back(
505 new test::WaiterThread(d,
506 MOJO_HANDLE_SIGNAL_READABLE,
507 3 * test::EpsilonTimeout().InMicroseconds(),
508 i,
509 &did_wait[i], &result[i], &context[i]));
510 threads.back()->Start();
511 }
512 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
513 threads.push_back(
514 new test::WaiterThread(d,
515 MOJO_HANDLE_SIGNAL_WRITABLE,
516 1 * test::EpsilonTimeout().InMicroseconds(),
517 i,
518 &did_wait[i], &result[i], &context[i]));
519 threads.back()->Start();
520 }
521 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
522 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
523 // All those waiting for writable should have timed out.
524 EXPECT_EQ(MOJO_RESULT_OK, d->Close());
525 } // Joins the threads.
526 for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
527 EXPECT_TRUE(did_wait[i]);
528 EXPECT_EQ(MOJO_RESULT_OK, result[i]);
529 EXPECT_EQ(i, context[i]);
530 }
531 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
532 EXPECT_TRUE(did_wait[i]);
533 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]);
534 }
535 }
536
537 // TODO(vtl): Stress test?
538
539 } // namespace
540 } // namespace system
541 } // namespace mojo
542