| 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 1dc454ae8603cccc7822c16b9d69d2056e8f484b..0000000000000000000000000000000000000000
|
| --- a/mojo/edk/system/dispatcher_unittest.cc
|
| +++ /dev/null
|
| @@ -1,297 +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 <stddef.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/waiter.h"
|
| -#include "mojo/public/cpp/system/macros.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -namespace mojo {
|
| -namespace edk {
|
| -namespace {
|
| -
|
| -// Trivial subclass that makes the constructor public.
|
| -class TrivialDispatcher final : public Dispatcher {
|
| - public:
|
| - TrivialDispatcher() {}
|
| -
|
| - Type GetType() const override { return Type::UNKNOWN; }
|
| -
|
| - private:
|
| - friend class base::RefCountedThreadSafe<TrivialDispatcher>;
|
| - ~TrivialDispatcher() override {}
|
| -
|
| - scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
|
| - override {
|
| - lock().AssertAcquired();
|
| - return scoped_refptr<Dispatcher>(new TrivialDispatcher());
|
| - }
|
| -
|
| - MOJO_DISALLOW_COPY_AND_ASSIGN(TrivialDispatcher);
|
| -};
|
| -
|
| -TEST(DispatcherTest, Basic) {
|
| - scoped_refptr<Dispatcher> d(new TrivialDispatcher());
|
| -
|
| - EXPECT_EQ(Dispatcher::Type::UNKNOWN, d->GetType());
|
| -
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->WriteMessage(nullptr, 0, nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->ReadMessage(nullptr, nullptr, nullptr, nullptr,
|
| - MOJO_WRITE_MESSAGE_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->WriteData(nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->BeginWriteData(nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->ReadData(nullptr, nullptr, MOJO_READ_DATA_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->BeginReadData(nullptr, nullptr, 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(nullptr, 0, nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->ReadMessage(nullptr, nullptr, nullptr, nullptr,
|
| - MOJO_WRITE_MESSAGE_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->WriteData(nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->BeginWriteData(nullptr, nullptr, MOJO_WRITE_DATA_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndWriteData(0));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->ReadData(nullptr, nullptr, MOJO_READ_DATA_FLAG_NONE));
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - d->BeginReadData(nullptr, nullptr, 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(nullptr, 0, nullptr,
|
| - MOJO_WRITE_MESSAGE_FLAG_NONE));
|
| - break;
|
| - case READ_MESSAGE:
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - dispatcher_->ReadMessage(nullptr, nullptr, nullptr, nullptr,
|
| - MOJO_WRITE_MESSAGE_FLAG_NONE));
|
| - break;
|
| - case WRITE_DATA:
|
| - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
|
| - dispatcher_->WriteData(nullptr, nullptr,
|
| - MOJO_WRITE_DATA_FLAG_NONE));
|
| - break;
|
| - case BEGIN_WRITE_DATA:
|
| - EXPECT_EQ(
|
| - MOJO_RESULT_INVALID_ARGUMENT,
|
| - dispatcher_->BeginWriteData(nullptr, nullptr,
|
| - 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(nullptr, nullptr,
|
| - MOJO_READ_DATA_FLAG_NONE));
|
| - break;
|
| - case BEGIN_READ_DATA:
|
| - EXPECT_EQ(
|
| - MOJO_RESULT_INVALID_ARGUMENT,
|
| - dispatcher_->BeginReadData(nullptr, nullptr,
|
| - 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(nullptr, &unused));
|
| - break;
|
| - }
|
| - case MAP_BUFFER: {
|
| - scoped_ptr<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_;
|
| -
|
| - MOJO_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 edk
|
| -} // namespace mojo
|
|
|