00c39654ef584cd0ded979ab4d5c6173f08727bf
[platform/framework/web/crosswalk.git] / src / mojo / system / simple_dispatcher_unittest.cc
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:
30   MockSimpleDispatcher()
31       : state_(MOJO_HANDLE_SIGNAL_NONE,
32                MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE) {}
33
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
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
63   virtual Type GetType() const OVERRIDE {
64     return kTypeUnknown;
65   }
66
67  private:
68   friend class base::RefCountedThreadSafe<MockSimpleDispatcher>;
69   virtual ~MockSimpleDispatcher() {}
70
71   virtual scoped_refptr<Dispatcher>
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:
79   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
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
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
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
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
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