Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / system / simple_dispatcher_unittest.cc
index 00c3965..ecd991d 100644 (file)
@@ -9,8 +9,8 @@
 
 #include "mojo/system/simple_dispatcher.h"
 
-#include "base/basictypes.h"
 #include "base/logging.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_vector.h"
 #include "base/synchronization/lock.h"
@@ -60,23 +60,21 @@ class MockSimpleDispatcher : public SimpleDispatcher {
     HandleSignalsStateChangedNoLock();
   }
 
-  virtual Type GetType() const OVERRIDE {
-    return kTypeUnknown;
-  }
+  virtual Type GetType() const OVERRIDE { return kTypeUnknown; }
 
  private:
   friend class base::RefCountedThreadSafe<MockSimpleDispatcher>;
   virtual ~MockSimpleDispatcher() {}
 
   virtual scoped_refptr<Dispatcher>
-      CreateEquivalentDispatcherAndCloseImplNoLock() OVERRIDE {
+  CreateEquivalentDispatcherAndCloseImplNoLock() OVERRIDE {
     scoped_refptr<MockSimpleDispatcher> rv(new MockSimpleDispatcher());
     rv->state_ = state_;
     return scoped_refptr<Dispatcher>(rv.get());
   }
 
-  // |SimpleDispatcher| implementation:
-  virtual HandleSignalsState GetHandleSignalsStateNoLock() const OVERRIDE {
+  // |Dispatcher| override:
+  virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const OVERRIDE {
     lock().AssertAcquired();
     return state_;
   }
@@ -87,75 +85,111 @@ class MockSimpleDispatcher : public SimpleDispatcher {
   DISALLOW_COPY_AND_ASSIGN(MockSimpleDispatcher);
 };
 
-TEST(SimpleDispatcherTest, Basic) {
+#if defined(OS_WIN)
+// http://crbug.com/396404
+#define MAYBE_Basic DISABLED_Basic
+#else
+#define MAYBE_Basic Basic
+#endif
+TEST(SimpleDispatcherTest, MAYBE_Basic) {
   test::Stopwatch stopwatch;
 
   scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
   Waiter w;
   uint32_t context = 0;
+  HandleSignalsState hss;
 
   // Try adding a readable waiter when already readable.
   w.Init();
   d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
+  hss = HandleSignalsState();
   EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
-            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0));
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
   // Shouldn't need to remove the waiter (it was not added).
 
   // Wait (forever) for writable when already writable.
   w.Init();
   d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1));
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, NULL));
   d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
   EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
   EXPECT_EQ(1u, context);
-  d->RemoveWaiter(&w);
+  hss = HandleSignalsState();
+  d->RemoveWaiter(&w, &hss);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
 
   // Wait for zero time for writable when already writable.
   w.Init();
   d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2));
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, NULL));
   d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, &context));
   EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
   EXPECT_EQ(2u, context);
-  d->RemoveWaiter(&w);
+  hss = HandleSignalsState();
+  d->RemoveWaiter(&w, &hss);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
 
   // Wait for non-zero, finite time for writable when already writable.
   w.Init();
   d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3));
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, NULL));
   d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE);
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_OK,
             w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
   EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
   EXPECT_EQ(3u, context);
-  d->RemoveWaiter(&w);
+  hss = HandleSignalsState();
+  d->RemoveWaiter(&w, &hss);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
 
   // Wait for zero time for writable when not writable (will time out).
   w.Init();
   d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4));
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, NULL));
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, NULL));
   EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
-  d->RemoveWaiter(&w);
+  hss = HandleSignalsState();
+  d->RemoveWaiter(&w, &hss);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
 
   // Wait for non-zero, finite time for writable when not writable (will time
   // out).
   w.Init();
   d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5));
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5, NULL));
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
             w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), NULL));
   base::TimeDelta elapsed = stopwatch.Elapsed();
-  EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
-  EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
-  d->RemoveWaiter(&w);
+  EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
+  EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
+  hss = HandleSignalsState();
+  d->RemoveWaiter(&w, &hss);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
 
   EXPECT_EQ(MOJO_RESULT_OK, d->Close());
 }
@@ -166,53 +200,69 @@ TEST(SimpleDispatcherTest, BasicUnsatisfiable) {
   scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
   Waiter w;
   uint32_t context = 0;
+  HandleSignalsState hss;
 
   // Try adding a writable waiter when it can never be writable.
   w.Init();
   d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
   d->SetSatisfiedSignals(0);
+  hss = HandleSignalsState();
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1));
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss));
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
   // Shouldn't need to remove the waiter (it was not added).
 
   // Wait (forever) for writable and then it becomes never writable.
   w.Init();
-  d->SetSatisfiableSignals(
-      MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2));
+  d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE |
+                           MOJO_HANDLE_SIGNAL_WRITABLE);
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, NULL));
   d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
             w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
   EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
   EXPECT_EQ(2u, context);
-  d->RemoveWaiter(&w);
+  hss = HandleSignalsState();
+  d->RemoveWaiter(&w, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // Wait for zero time for writable and then it becomes never writable.
   w.Init();
-  d->SetSatisfiableSignals(
-      MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3));
+  d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE |
+                           MOJO_HANDLE_SIGNAL_WRITABLE);
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, NULL));
   d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0, &context));
   EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
   EXPECT_EQ(3u, context);
-  d->RemoveWaiter(&w);
+  hss = HandleSignalsState();
+  d->RemoveWaiter(&w, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // Wait for non-zero, finite time for writable and then it becomes never
   // writable.
   w.Init();
-  d->SetSatisfiableSignals(
-      MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4));
+  d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE |
+                           MOJO_HANDLE_SIGNAL_WRITABLE);
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, NULL));
   d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE);
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
             w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
   EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
   EXPECT_EQ(4u, context);
-  d->RemoveWaiter(&w);
+  hss = HandleSignalsState();
+  d->RemoveWaiter(&w, &hss);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   EXPECT_EQ(MOJO_RESULT_OK, d->Close());
 }
@@ -223,19 +273,24 @@ TEST(SimpleDispatcherTest, BasicClosed) {
   scoped_refptr<MockSimpleDispatcher> d;
   Waiter w;
   uint32_t context = 0;
+  HandleSignalsState hss;
 
   // Try adding a writable waiter when the dispatcher has been closed.
   d = new MockSimpleDispatcher();
   w.Init();
   EXPECT_EQ(MOJO_RESULT_OK, d->Close());
+  hss = HandleSignalsState();
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1));
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss));
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(0u, hss.satisfiable_signals);
   // Shouldn't need to remove the waiter (it was not added).
 
   // Wait (forever) for writable and then the dispatcher is closed.
   d = new MockSimpleDispatcher();
   w.Init();
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2));
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, NULL));
   EXPECT_EQ(MOJO_RESULT_OK, d->Close());
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
@@ -246,7 +301,8 @@ TEST(SimpleDispatcherTest, BasicClosed) {
   // Wait for zero time for writable and then the dispatcher is closed.
   d = new MockSimpleDispatcher();
   w.Init();
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3));
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, NULL));
   EXPECT_EQ(MOJO_RESULT_OK, d->Close());
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context));
@@ -258,7 +314,8 @@ TEST(SimpleDispatcherTest, BasicClosed) {
   // closed.
   d = new MockSimpleDispatcher();
   w.Init();
-  EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4));
+  ASSERT_EQ(MOJO_RESULT_OK,
+            d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, NULL));
   EXPECT_EQ(MOJO_RESULT_OK, d->Close());
   stopwatch.Start();
   EXPECT_EQ(MOJO_RESULT_CANCELLED,
@@ -268,11 +325,18 @@ TEST(SimpleDispatcherTest, BasicClosed) {
   // Don't need to remove waiters from closed dispatchers.
 }
 
-TEST(SimpleDispatcherTest, BasicThreaded) {
+#if defined(OS_WIN)
+// http://crbug.com/396393
+#define MAYBE_BasicThreaded DISABLED_BasicThreaded
+#else
+#define MAYBE_BasicThreaded BasicThreaded
+#endif
+TEST(SimpleDispatcherTest, MAYBE_BasicThreaded) {
   test::Stopwatch stopwatch;
   bool did_wait;
   MojoResult result;
   uint32_t context;
+  HandleSignalsState hss;
 
   // Wait for readable (already readable).
   {
@@ -283,7 +347,10 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
                                 MOJO_HANDLE_SIGNAL_READABLE,
                                 MOJO_DEADLINE_INDEFINITE,
                                 1,
-                                &did_wait, &result, &context);
+                                &did_wait,
+                                &result,
+                                &context,
+                                &hss);
       stopwatch.Start();
       thread.Start();
     }  // Joins the thread.
@@ -293,48 +360,66 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
   EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
   EXPECT_FALSE(did_wait);
   EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
 
   // Wait for readable and becomes readable after some time.
   {
     scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
-    test::WaiterThread thread(d,
-                              MOJO_HANDLE_SIGNAL_READABLE,
-                              MOJO_DEADLINE_INDEFINITE,
-                              2,
-                              &did_wait, &result, &context);
-    stopwatch.Start();
-    thread.Start();
-    base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
-    d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
+    {
+      test::WaiterThread thread(d,
+                                MOJO_HANDLE_SIGNAL_READABLE,
+                                MOJO_DEADLINE_INDEFINITE,
+                                2,
+                                &did_wait,
+                                &result,
+                                &context,
+                                &hss);
+      stopwatch.Start();
+      thread.Start();
+      base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
+      d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE);
+    }  // Joins the thread.
     EXPECT_EQ(MOJO_RESULT_OK, d->Close());
-  }  // Joins the thread.
+  }
   base::TimeDelta elapsed = stopwatch.Elapsed();
-  EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
-  EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
+  EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
+  EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
   EXPECT_TRUE(did_wait);
   EXPECT_EQ(MOJO_RESULT_OK, result);
   EXPECT_EQ(2u, context);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
 
   // Wait for readable and becomes never-readable after some time.
   {
     scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
-    test::WaiterThread thread(d,
-                              MOJO_HANDLE_SIGNAL_READABLE,
-                              MOJO_DEADLINE_INDEFINITE,
-                              3,
-                              &did_wait, &result, &context);
-    stopwatch.Start();
-    thread.Start();
-    base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
-    d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_NONE);
+    {
+      test::WaiterThread thread(d,
+                                MOJO_HANDLE_SIGNAL_READABLE,
+                                MOJO_DEADLINE_INDEFINITE,
+                                3,
+                                &did_wait,
+                                &result,
+                                &context,
+                                &hss);
+      stopwatch.Start();
+      thread.Start();
+      base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
+      d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_NONE);
+    }  // Joins the thread.
     EXPECT_EQ(MOJO_RESULT_OK, d->Close());
-  }  // Joins the thread.
+  }
   elapsed = stopwatch.Elapsed();
-  EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
-  EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
+  EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
+  EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
   EXPECT_TRUE(did_wait);
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
   EXPECT_EQ(3u, context);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(0u, hss.satisfiable_signals);
 
   // Wait for readable and dispatcher gets closed.
   {
@@ -343,18 +428,23 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
                               MOJO_HANDLE_SIGNAL_READABLE,
                               MOJO_DEADLINE_INDEFINITE,
                               4,
-                              &did_wait, &result, &context);
+                              &did_wait,
+                              &result,
+                              &context,
+                              &hss);
     stopwatch.Start();
     thread.Start();
     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
     EXPECT_EQ(MOJO_RESULT_OK, d->Close());
   }  // Joins the thread.
   elapsed = stopwatch.Elapsed();
-  EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
-  EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
+  EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
+  EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
   EXPECT_TRUE(did_wait);
   EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
   EXPECT_EQ(4u, context);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(0u, hss.satisfiable_signals);
 
   // Wait for readable and times out.
   {
@@ -364,7 +454,10 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
                                 MOJO_HANDLE_SIGNAL_READABLE,
                                 2 * test::EpsilonTimeout().InMicroseconds(),
                                 5,
-                                &did_wait, &result, &context);
+                                &did_wait,
+                                &result,
+                                &context,
+                                &hss);
       stopwatch.Start();
       thread.Start();
       base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
@@ -375,18 +468,28 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
     EXPECT_EQ(MOJO_RESULT_OK, d->Close());
   }
   elapsed = stopwatch.Elapsed();
-  EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
-  EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
+  EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
+  EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
   EXPECT_TRUE(did_wait);
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
 }
 
-TEST(SimpleDispatcherTest, MultipleWaiters) {
+#if defined(OS_WIN)
+// http://crbug.com/387124
+#define MAYBE_MultipleWaiters DISABLED_MultipleWaiters
+#else
+#define MAYBE_MultipleWaiters MultipleWaiters
+#endif
+TEST(SimpleDispatcherTest, MAYBE_MultipleWaiters) {
   static const uint32_t kNumWaiters = 20;
 
   bool did_wait[kNumWaiters];
   MojoResult result[kNumWaiters];
   uint32_t context[kNumWaiters];
+  HandleSignalsState hss[kNumWaiters];
 
   // All wait for readable and becomes readable after some time.
   {
@@ -399,7 +502,8 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
                                                i,
                                                &did_wait[i],
                                                &result[i],
-                                               &context[i]));
+                                               &context[i],
+                                               &hss[i]));
       threads.back()->Start();
     }
     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -407,9 +511,11 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
     EXPECT_EQ(MOJO_RESULT_OK, d->Close());
   }  // Joins the threads.
   for (uint32_t i = 0; i < kNumWaiters; i++) {
-    EXPECT_TRUE(did_wait[i]);
-    EXPECT_EQ(MOJO_RESULT_OK, result[i]);
-    EXPECT_EQ(i, context[i]);
+    EXPECT_TRUE(did_wait[i]) << i;
+    EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i;
+    EXPECT_EQ(i, context[i]) << i;
+    // Since we closed before joining, we can't say much about what each thread
+    // saw as the state.
   }
 
   // Some wait for readable, some for writable, and becomes readable after some
@@ -424,7 +530,8 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
                                                i,
                                                &did_wait[i],
                                                &result[i],
-                                               &context[i]));
+                                               &context[i],
+                                               &hss[i]));
       threads.back()->Start();
     }
     for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
@@ -434,7 +541,8 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
                                                i,
                                                &did_wait[i],
                                                &result[i],
-                                               &context[i]));
+                                               &context[i],
+                                               &hss[i]));
       threads.back()->Start();
     }
     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -443,14 +551,18 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
     EXPECT_EQ(MOJO_RESULT_OK, d->Close());
   }  // Joins the threads.
   for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
-    EXPECT_TRUE(did_wait[i]);
-    EXPECT_EQ(MOJO_RESULT_OK, result[i]);
-    EXPECT_EQ(i, context[i]);
+    EXPECT_TRUE(did_wait[i]) << i;
+    EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i;
+    EXPECT_EQ(i, context[i]) << i;
+    // Since we closed before joining, we can't say much about what each thread
+    // saw as the state.
   }
   for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
-    EXPECT_TRUE(did_wait[i]);
-    EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]);
-    EXPECT_EQ(i, context[i]);
+    EXPECT_TRUE(did_wait[i]) << i;
+    EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]) << i;
+    EXPECT_EQ(i, context[i]) << i;
+    // Since we closed before joining, we can't say much about what each thread
+    // saw as the state.
   }
 
   // Some wait for readable, some for writable, and becomes readable and
@@ -465,7 +577,8 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
                                                i,
                                                &did_wait[i],
                                                &result[i],
-                                               &context[i]));
+                                               &context[i],
+                                               &hss[i]));
       threads.back()->Start();
     }
     for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
@@ -475,7 +588,8 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
                                                i,
                                                &did_wait[i],
                                                &result[i],
-                                               &context[i]));
+                                               &context[i],
+                                               &hss[i]));
       threads.back()->Start();
     }
     base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
@@ -485,14 +599,18 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
     EXPECT_EQ(MOJO_RESULT_OK, d->Close());
   }  // Joins the threads.
   for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
-    EXPECT_TRUE(did_wait[i]);
-    EXPECT_EQ(MOJO_RESULT_OK, result[i]);
-    EXPECT_EQ(i, context[i]);
+    EXPECT_TRUE(did_wait[i]) << i;
+    EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i;
+    EXPECT_EQ(i, context[i]) << i;
+    // Since we closed before joining, we can't say much about what each thread
+    // saw as the state.
   }
   for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
-    EXPECT_TRUE(did_wait[i]);
-    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]);
-    EXPECT_EQ(i, context[i]);
+    EXPECT_TRUE(did_wait[i]) << i;
+    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]) << i;
+    EXPECT_EQ(i, context[i]) << i;
+    // Since we closed before joining, we can't say much about what each thread
+    // saw as the state.
   }
 
   // Some wait for readable, some for writable, and becomes readable after some
@@ -506,7 +624,10 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
                                  MOJO_HANDLE_SIGNAL_READABLE,
                                  3 * test::EpsilonTimeout().InMicroseconds(),
                                  i,
-                                 &did_wait[i], &result[i], &context[i]));
+                                 &did_wait[i],
+                                 &result[i],
+                                 &context[i],
+                                 &hss[i]));
       threads.back()->Start();
     }
     for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
@@ -515,7 +636,10 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
                                  MOJO_HANDLE_SIGNAL_WRITABLE,
                                  1 * test::EpsilonTimeout().InMicroseconds(),
                                  i,
-                                 &did_wait[i], &result[i], &context[i]));
+                                 &did_wait[i],
+                                 &result[i],
+                                 &context[i],
+                                 &hss[i]));
       threads.back()->Start();
     }
     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -524,13 +648,17 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
     EXPECT_EQ(MOJO_RESULT_OK, d->Close());
   }  // Joins the threads.
   for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
-    EXPECT_TRUE(did_wait[i]);
-    EXPECT_EQ(MOJO_RESULT_OK, result[i]);
-    EXPECT_EQ(i, context[i]);
+    EXPECT_TRUE(did_wait[i]) << i;
+    EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i;
+    EXPECT_EQ(i, context[i]) << i;
+    // Since we closed before joining, we can't say much about what each thread
+    // saw as the state.
   }
   for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
-    EXPECT_TRUE(did_wait[i]);
-    EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]);
+    EXPECT_TRUE(did_wait[i]) << i;
+    EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]) << i;
+    // Since we closed before joining, we can't say much about what each thread
+    // saw as the state.
   }
 }