Index: mojo/edk/system/dispatcher_unittest.cc |
diff --git a/mojo/edk/system/dispatcher_unittest.cc b/mojo/edk/system/dispatcher_unittest.cc |
deleted file mode 100644 |
index 97e2eed9c6b1016555c4b7d4eea9e72fb099426c..0000000000000000000000000000000000000000 |
--- a/mojo/edk/system/dispatcher_unittest.cc |
+++ /dev/null |
@@ -1,307 +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. |
- |
-#include "mojo/edk/system/dispatcher.h" |
- |
-#include "base/macros.h" |
-#include "base/memory/ref_counted.h" |
-#include "base/memory/scoped_vector.h" |
-#include "base/synchronization/waitable_event.h" |
-#include "base/threading/simple_thread.h" |
-#include "mojo/edk/embedder/platform_shared_buffer.h" |
-#include "mojo/edk/system/memory.h" |
-#include "mojo/edk/system/waiter.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-namespace mojo { |
-namespace system { |
-namespace { |
- |
-// Trivial subclass that makes the constructor public. |
-class TrivialDispatcher : public Dispatcher { |
- public: |
- TrivialDispatcher() {} |
- |
- Type GetType() const override { return kTypeUnknown; } |
- |
- private: |
- friend class base::RefCountedThreadSafe<TrivialDispatcher>; |
- ~TrivialDispatcher() override {} |
- |
- scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() |
- override { |
- lock().AssertAcquired(); |
- return scoped_refptr<Dispatcher>(new TrivialDispatcher()); |
- } |
- |
- DISALLOW_COPY_AND_ASSIGN(TrivialDispatcher); |
-}; |
- |
-TEST(DispatcherTest, Basic) { |
- scoped_refptr<Dispatcher> d(new TrivialDispatcher()); |
- |
- EXPECT_EQ(Dispatcher::kTypeUnknown, d->GetType()); |
- |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->WriteMessage(NullUserPointer(), 0, nullptr, |
- MOJO_WRITE_MESSAGE_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->ReadMessage(NullUserPointer(), NullUserPointer(), nullptr, |
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->WriteData(NullUserPointer(), NullUserPointer(), |
- MOJO_WRITE_DATA_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->BeginWriteData(NullUserPointer(), NullUserPointer(), |
- MOJO_WRITE_DATA_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->ReadData(NullUserPointer(), NullUserPointer(), |
- MOJO_READ_DATA_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->BeginReadData(NullUserPointer(), NullUserPointer(), |
- MOJO_READ_DATA_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0)); |
- Waiter w; |
- w.Init(); |
- HandleSignalsState hss; |
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
- d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); |
- EXPECT_EQ(0u, hss.satisfied_signals); |
- EXPECT_EQ(0u, hss.satisfiable_signals); |
- // Okay to remove even if it wasn't added (or was already removed). |
- hss = HandleSignalsState(); |
- d->RemoveAwakable(&w, &hss); |
- EXPECT_EQ(0u, hss.satisfied_signals); |
- EXPECT_EQ(0u, hss.satisfiable_signals); |
- hss = HandleSignalsState(); |
- d->RemoveAwakable(&w, &hss); |
- EXPECT_EQ(0u, hss.satisfied_signals); |
- EXPECT_EQ(0u, hss.satisfiable_signals); |
- |
- EXPECT_EQ(MOJO_RESULT_OK, d->Close()); |
- |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->WriteMessage(NullUserPointer(), 0, nullptr, |
- MOJO_WRITE_MESSAGE_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->ReadMessage(NullUserPointer(), NullUserPointer(), nullptr, |
- nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->WriteData(NullUserPointer(), NullUserPointer(), |
- MOJO_WRITE_DATA_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->BeginWriteData(NullUserPointer(), NullUserPointer(), |
- MOJO_WRITE_DATA_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->ReadData(NullUserPointer(), NullUserPointer(), |
- MOJO_READ_DATA_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->BeginReadData(NullUserPointer(), NullUserPointer(), |
- MOJO_READ_DATA_FLAG_NONE)); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0)); |
- hss = HandleSignalsState(); |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); |
- EXPECT_EQ(0u, hss.satisfied_signals); |
- EXPECT_EQ(0u, hss.satisfiable_signals); |
- hss = HandleSignalsState(); |
- d->RemoveAwakable(&w, &hss); |
- EXPECT_EQ(0u, hss.satisfied_signals); |
- EXPECT_EQ(0u, hss.satisfiable_signals); |
-} |
- |
-class ThreadSafetyStressThread : public base::SimpleThread { |
- public: |
- enum DispatcherOp { |
- CLOSE = 0, |
- WRITE_MESSAGE, |
- READ_MESSAGE, |
- WRITE_DATA, |
- BEGIN_WRITE_DATA, |
- END_WRITE_DATA, |
- READ_DATA, |
- BEGIN_READ_DATA, |
- END_READ_DATA, |
- DUPLICATE_BUFFER_HANDLE, |
- MAP_BUFFER, |
- ADD_WAITER, |
- REMOVE_WAITER, |
- DISPATCHER_OP_COUNT |
- }; |
- |
- ThreadSafetyStressThread(base::WaitableEvent* event, |
- scoped_refptr<Dispatcher> dispatcher, |
- DispatcherOp op) |
- : base::SimpleThread("thread_safety_stress_thread"), |
- event_(event), |
- dispatcher_(dispatcher), |
- op_(op) { |
- CHECK_LE(0, op_); |
- CHECK_LT(op_, DISPATCHER_OP_COUNT); |
- } |
- |
- ~ThreadSafetyStressThread() override { Join(); } |
- |
- private: |
- void Run() override { |
- event_->Wait(); |
- |
- waiter_.Init(); |
- switch (op_) { |
- case CLOSE: { |
- MojoResult r = dispatcher_->Close(); |
- EXPECT_TRUE(r == MOJO_RESULT_OK || r == MOJO_RESULT_INVALID_ARGUMENT) |
- << "Result: " << r; |
- break; |
- } |
- case WRITE_MESSAGE: |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- dispatcher_->WriteMessage(NullUserPointer(), 0, nullptr, |
- MOJO_WRITE_MESSAGE_FLAG_NONE)); |
- break; |
- case READ_MESSAGE: |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- dispatcher_->ReadMessage(NullUserPointer(), NullUserPointer(), |
- nullptr, nullptr, |
- MOJO_WRITE_MESSAGE_FLAG_NONE)); |
- break; |
- case WRITE_DATA: |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- dispatcher_->WriteData(NullUserPointer(), NullUserPointer(), |
- MOJO_WRITE_DATA_FLAG_NONE)); |
- break; |
- case BEGIN_WRITE_DATA: |
- EXPECT_EQ( |
- MOJO_RESULT_INVALID_ARGUMENT, |
- dispatcher_->BeginWriteData(NullUserPointer(), NullUserPointer(), |
- MOJO_WRITE_DATA_FLAG_NONE)); |
- break; |
- case END_WRITE_DATA: |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndWriteData(0)); |
- break; |
- case READ_DATA: |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
- dispatcher_->ReadData(NullUserPointer(), NullUserPointer(), |
- MOJO_READ_DATA_FLAG_NONE)); |
- break; |
- case BEGIN_READ_DATA: |
- EXPECT_EQ( |
- MOJO_RESULT_INVALID_ARGUMENT, |
- dispatcher_->BeginReadData(NullUserPointer(), NullUserPointer(), |
- MOJO_READ_DATA_FLAG_NONE)); |
- break; |
- case END_READ_DATA: |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher_->EndReadData(0)); |
- break; |
- case DUPLICATE_BUFFER_HANDLE: { |
- scoped_refptr<Dispatcher> unused; |
- EXPECT_EQ( |
- MOJO_RESULT_INVALID_ARGUMENT, |
- dispatcher_->DuplicateBufferHandle(NullUserPointer(), &unused)); |
- break; |
- } |
- case MAP_BUFFER: { |
- scoped_ptr<embedder::PlatformSharedBufferMapping> unused; |
- EXPECT_EQ( |
- MOJO_RESULT_INVALID_ARGUMENT, |
- dispatcher_->MapBuffer(0u, 0u, MOJO_MAP_BUFFER_FLAG_NONE, &unused)); |
- break; |
- } |
- case ADD_WAITER: { |
- HandleSignalsState hss; |
- MojoResult r = dispatcher_->AddAwakable( |
- &waiter_, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss); |
- EXPECT_TRUE(r == MOJO_RESULT_FAILED_PRECONDITION || |
- r == MOJO_RESULT_INVALID_ARGUMENT); |
- EXPECT_EQ(0u, hss.satisfied_signals); |
- EXPECT_EQ(0u, hss.satisfiable_signals); |
- break; |
- } |
- case REMOVE_WAITER: { |
- HandleSignalsState hss; |
- dispatcher_->RemoveAwakable(&waiter_, &hss); |
- EXPECT_EQ(0u, hss.satisfied_signals); |
- EXPECT_EQ(0u, hss.satisfiable_signals); |
- break; |
- } |
- default: |
- NOTREACHED(); |
- break; |
- } |
- |
- // Always try to remove the waiter, in case we added it. |
- HandleSignalsState hss; |
- dispatcher_->RemoveAwakable(&waiter_, &hss); |
- EXPECT_EQ(0u, hss.satisfied_signals); |
- EXPECT_EQ(0u, hss.satisfiable_signals); |
- } |
- |
- base::WaitableEvent* const event_; |
- const scoped_refptr<Dispatcher> dispatcher_; |
- const DispatcherOp op_; |
- |
- Waiter waiter_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ThreadSafetyStressThread); |
-}; |
- |
-TEST(DispatcherTest, ThreadSafetyStress) { |
- static const size_t kRepeatCount = 20; |
- static const size_t kNumThreads = 100; |
- |
- for (size_t i = 0; i < kRepeatCount; i++) { |
- // Manual reset, not initially signalled. |
- base::WaitableEvent event(true, false); |
- scoped_refptr<Dispatcher> d(new TrivialDispatcher()); |
- |
- { |
- ScopedVector<ThreadSafetyStressThread> threads; |
- for (size_t j = 0; j < kNumThreads; j++) { |
- ThreadSafetyStressThread::DispatcherOp op = |
- static_cast<ThreadSafetyStressThread::DispatcherOp>( |
- (i + j) % ThreadSafetyStressThread::DISPATCHER_OP_COUNT); |
- threads.push_back(new ThreadSafetyStressThread(&event, d, op)); |
- threads.back()->Start(); |
- } |
- // Kicks off real work on the threads: |
- event.Signal(); |
- } // Joins all the threads. |
- |
- // One of the threads should already have closed the dispatcher. |
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->Close()); |
- } |
-} |
- |
-TEST(DispatcherTest, ThreadSafetyStressNoClose) { |
- static const size_t kRepeatCount = 20; |
- static const size_t kNumThreads = 100; |
- |
- for (size_t i = 0; i < kRepeatCount; i++) { |
- // Manual reset, not initially signalled. |
- base::WaitableEvent event(true, false); |
- scoped_refptr<Dispatcher> d(new TrivialDispatcher()); |
- |
- { |
- ScopedVector<ThreadSafetyStressThread> threads; |
- for (size_t j = 0; j < kNumThreads; j++) { |
- ThreadSafetyStressThread::DispatcherOp op = |
- static_cast<ThreadSafetyStressThread::DispatcherOp>( |
- (i + j) % (ThreadSafetyStressThread::DISPATCHER_OP_COUNT - 1) + |
- 1); |
- threads.push_back(new ThreadSafetyStressThread(&event, d, op)); |
- threads.back()->Start(); |
- } |
- // Kicks off real work on the threads: |
- event.Signal(); |
- } // Joins all the threads. |
- |
- EXPECT_EQ(MOJO_RESULT_OK, d->Close()); |
- } |
-} |
- |
-} // namespace |
-} // namespace system |
-} // namespace mojo |