diff options
Diffstat (limited to 'mojo/edk/system/simple_dispatcher_unittest.cc')
-rw-r--r-- | mojo/edk/system/simple_dispatcher_unittest.cc | 609 |
1 files changed, 0 insertions, 609 deletions
diff --git a/mojo/edk/system/simple_dispatcher_unittest.cc b/mojo/edk/system/simple_dispatcher_unittest.cc deleted file mode 100644 index b8e57e9..0000000 --- a/mojo/edk/system/simple_dispatcher_unittest.cc +++ /dev/null @@ -1,609 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a -// heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to -// increase tolerance and reduce observed flakiness (though doing so reduces the -// meaningfulness of the test). - -#include "mojo/edk/system/simple_dispatcher.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" -#include "base/threading/platform_thread.h" // For |Sleep()|. -#include "base/time/time.h" -#include "mojo/edk/system/test_utils.h" -#include "mojo/edk/system/waiter.h" -#include "mojo/edk/system/waiter_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace system { -namespace { - -class MockSimpleDispatcher : public SimpleDispatcher { - public: - MockSimpleDispatcher() - : state_(MOJO_HANDLE_SIGNAL_NONE, - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE) {} - - void SetSatisfiedSignals(MojoHandleSignals new_satisfied_signals) { - base::AutoLock locker(lock()); - - // Any new signals that are set should be satisfiable. - CHECK_EQ(new_satisfied_signals & ~state_.satisfied_signals, - new_satisfied_signals & ~state_.satisfied_signals & - state_.satisfiable_signals); - - if (new_satisfied_signals == state_.satisfied_signals) - return; - - state_.satisfied_signals = new_satisfied_signals; - HandleSignalsStateChangedNoLock(); - } - - void SetSatisfiableSignals(MojoHandleSignals new_satisfiable_signals) { - base::AutoLock locker(lock()); - - // Satisfied implies satisfiable. - CHECK_EQ(new_satisfiable_signals & state_.satisfied_signals, - state_.satisfied_signals); - - if (new_satisfiable_signals == state_.satisfiable_signals) - return; - - state_.satisfiable_signals = new_satisfiable_signals; - HandleSignalsStateChangedNoLock(); - } - - Type GetType() const override { return kTypeUnknown; } - - private: - friend class base::RefCountedThreadSafe<MockSimpleDispatcher>; - ~MockSimpleDispatcher() override {} - - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() - override { - scoped_refptr<MockSimpleDispatcher> rv(new MockSimpleDispatcher()); - rv->state_ = state_; - return scoped_refptr<Dispatcher>(rv.get()); - } - - // |Dispatcher| override: - HandleSignalsState GetHandleSignalsStateImplNoLock() const override { - lock().AssertAcquired(); - return state_; - } - - // Protected by |lock()|: - HandleSignalsState state_; - - DISALLOW_COPY_AND_ASSIGN(MockSimpleDispatcher); -}; - -#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->AddAwakable(&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); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, nullptr)); - 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); - hss = HandleSignalsState(); - d->RemoveAwakable(&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); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); - 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); - hss = HandleSignalsState(); - d->RemoveAwakable(&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); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); - 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); - hss = HandleSignalsState(); - d->RemoveAwakable(&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); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); - hss = HandleSignalsState(); - d->RemoveAwakable(&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); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5, nullptr)); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), nullptr)); - base::TimeDelta elapsed = stopwatch.Elapsed(); - EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); - EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); - hss = HandleSignalsState(); - d->RemoveAwakable(&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()); -} - -TEST(SimpleDispatcherTest, BasicUnsatisfiable) { - test::Stopwatch stopwatch; - - 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->AddAwakable(&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); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); - 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); - hss = HandleSignalsState(); - d->RemoveAwakable(&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); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); - 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); - hss = HandleSignalsState(); - d->RemoveAwakable(&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); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); - 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); - hss = HandleSignalsState(); - d->RemoveAwakable(&w, &hss); - EXPECT_EQ(0u, hss.satisfied_signals); - EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); - - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); -} - -TEST(SimpleDispatcherTest, BasicClosed) { - test::Stopwatch stopwatch; - - 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->AddAwakable(&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(); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); - EXPECT_EQ(2u, context); - // Don't need to remove waiters from closed dispatchers. - - // Wait for zero time for writable and then the dispatcher is closed. - d = new MockSimpleDispatcher(); - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); - EXPECT_EQ(3u, context); - // Don't need to remove waiters from closed dispatchers. - - // Wait for non-zero, finite time for writable and then the dispatcher is - // closed. - d = new MockSimpleDispatcher(); - w.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - stopwatch.Start(); - EXPECT_EQ(MOJO_RESULT_CANCELLED, - w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context)); - EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); - EXPECT_EQ(4u, context); - // Don't need to remove waiters from closed dispatchers. -} - -#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). - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - { - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 1, &did_wait, &result, - &context, &hss); - stopwatch.Start(); - thread.Start(); - } // Joins the thread. - // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } - 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, &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()); - } - base::TimeDelta elapsed = stopwatch.Elapsed(); - 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, &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()); - } - elapsed = stopwatch.Elapsed(); - 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. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, 4, &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_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. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - { - test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, - 2 * test::EpsilonTimeout().InMicroseconds(), 5, - &did_wait, &result, &context, &hss); - stopwatch.Start(); - thread.Start(); - base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); - // Not what we're waiting for. - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); - } // Joins the thread (after its wait times out). - // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. - 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_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); -} - -#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. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - ScopedVector<test::WaiterThread> threads; - for (uint32_t i = 0; i < kNumWaiters; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } // Joins the threads. - for (uint32_t i = 0; i < kNumWaiters; 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 - // time. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - ScopedVector<test::WaiterThread> threads; - for (uint32_t i = 0; i < kNumWaiters / 2; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - // This will wake up the ones waiting to write. - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } // Joins the threads. - for (uint32_t i = 0; i < kNumWaiters / 2; 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]) << 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 - // never-writable after some time. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - ScopedVector<test::WaiterThread> threads; - for (uint32_t i = 0; i < kNumWaiters / 2; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i, - &did_wait[i], &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); - d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); - base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } // Joins the threads. - for (uint32_t i = 0; i < kNumWaiters / 2; 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]) << 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 - // time. - { - scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); - ScopedVector<test::WaiterThread> threads; - for (uint32_t i = 0; i < kNumWaiters / 2; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_READABLE, - 3 * test::EpsilonTimeout().InMicroseconds(), i, &did_wait[i], - &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { - threads.push_back(new test::WaiterThread( - d, MOJO_HANDLE_SIGNAL_WRITABLE, - 1 * test::EpsilonTimeout().InMicroseconds(), i, &did_wait[i], - &result[i], &context[i], &hss[i])); - threads.back()->Start(); - } - base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); - d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); - // All those waiting for writable should have timed out. - EXPECT_EQ(MOJO_RESULT_OK, d->Close()); - } // Joins the threads. - for (uint32_t i = 0; i < kNumWaiters / 2; 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]) << 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. - } -} - -// TODO(vtl): Stress test? - -} // namespace -} // namespace system -} // namespace mojo |