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