Home | History | Annotate | Download | only in system
      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
    542