| Index: mojo/public/cpp/utility/tests/mutex_unittest.cc
|
| diff --git a/mojo/public/cpp/utility/tests/mutex_unittest.cc b/mojo/public/cpp/utility/tests/mutex_unittest.cc
|
| deleted file mode 100644
|
| index 1604c8d072e2043158f280b9e691c18e880277ac..0000000000000000000000000000000000000000
|
| --- a/mojo/public/cpp/utility/tests/mutex_unittest.cc
|
| +++ /dev/null
|
| @@ -1,261 +0,0 @@
|
| -// Copyright 2014 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/public/cpp/utility/mutex.h"
|
| -
|
| -#include <stddef.h>
|
| -#include <stdlib.h> // For |rand()|.
|
| -#include <time.h> // For |nanosleep()| (defined by POSIX).
|
| -
|
| -#include <vector>
|
| -
|
| -#include "base/compiler_specific.h"
|
| -#include "mojo/public/cpp/system/macros.h"
|
| -#include "mojo/public/cpp/utility/thread.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -namespace mojo {
|
| -namespace {
|
| -
|
| -TEST(MutexTest, TrivialSingleThreaded) {
|
| - Mutex mutex;
|
| -
|
| - mutex.Lock();
|
| - mutex.AssertHeld();
|
| - mutex.Unlock();
|
| -
|
| - EXPECT_TRUE(mutex.TryLock());
|
| - mutex.AssertHeld();
|
| - mutex.Unlock();
|
| -
|
| - {
|
| - MutexLock lock(&mutex);
|
| - mutex.AssertHeld();
|
| - }
|
| -
|
| - EXPECT_TRUE(mutex.TryLock());
|
| - mutex.Unlock();
|
| -}
|
| -
|
| -class Fiddler {
|
| - public:
|
| - enum Type { kTypeLock, kTypeTry };
|
| - Fiddler(size_t times_to_lock,
|
| - Type type,
|
| - bool should_sleep,
|
| - Mutex* mutex,
|
| - int* shared_value)
|
| - : times_to_lock_(times_to_lock),
|
| - type_(type),
|
| - should_sleep_(should_sleep),
|
| - mutex_(mutex),
|
| - shared_value_(shared_value) {
|
| - }
|
| -
|
| - ~Fiddler() {
|
| - }
|
| -
|
| - void Fiddle() {
|
| - for (size_t i = 0; i < times_to_lock_;) {
|
| - switch (type_) {
|
| - case kTypeLock: {
|
| - mutex_->Lock();
|
| - int old_shared_value = *shared_value_;
|
| - if (should_sleep_)
|
| - SleepALittle();
|
| - *shared_value_ = old_shared_value + 1;
|
| - mutex_->Unlock();
|
| - i++;
|
| - break;
|
| - }
|
| - case kTypeTry:
|
| - if (mutex_->TryLock()) {
|
| - int old_shared_value = *shared_value_;
|
| - if (should_sleep_)
|
| - SleepALittle();
|
| - *shared_value_ = old_shared_value + 1;
|
| - mutex_->Unlock();
|
| - i++;
|
| - } else {
|
| - SleepALittle(); // Don't spin.
|
| - }
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - private:
|
| - static void SleepALittle() {
|
| - static const long kNanosPerMilli = 1000000;
|
| - struct timespec req = {
|
| - 0, // Seconds.
|
| - (rand() % 10) * kNanosPerMilli // Nanoseconds.
|
| - };
|
| - int rv = nanosleep(&req, nullptr);
|
| - ALLOW_UNUSED_LOCAL(rv);
|
| - assert(rv == 0);
|
| - }
|
| -
|
| - const size_t times_to_lock_;
|
| - const Type type_;
|
| - const bool should_sleep_;
|
| - Mutex* const mutex_;
|
| - int* const shared_value_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(Fiddler);
|
| -};
|
| -
|
| -class FiddlerThread : public Thread {
|
| - public:
|
| - // Takes ownership of |fiddler|.
|
| - FiddlerThread(Fiddler* fiddler)
|
| - : fiddler_(fiddler) {
|
| - }
|
| -
|
| - ~FiddlerThread() override { delete fiddler_; }
|
| -
|
| - void Run() override { fiddler_->Fiddle(); }
|
| -
|
| - private:
|
| - Fiddler* const fiddler_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(FiddlerThread);
|
| -};
|
| -
|
| -// This does a stress test (that also checks exclusion).
|
| -TEST(MutexTest, ThreadedStress) {
|
| - static const size_t kNumThreads = 20;
|
| - static const int kTimesToLockEach = 20;
|
| - assert(kNumThreads % 4 == 0);
|
| -
|
| - Mutex mutex;
|
| - int shared_value = 0;
|
| -
|
| - std::vector<FiddlerThread*> fiddler_threads;
|
| -
|
| - for (size_t i = 0; i < kNumThreads; i += 4) {
|
| - fiddler_threads.push_back(new FiddlerThread(new Fiddler(
|
| - kTimesToLockEach, Fiddler::kTypeLock, false, &mutex, &shared_value)));
|
| - fiddler_threads.push_back(new FiddlerThread(new Fiddler(
|
| - kTimesToLockEach, Fiddler::kTypeTry, false, &mutex, &shared_value)));
|
| - fiddler_threads.push_back(new FiddlerThread(new Fiddler(
|
| - kTimesToLockEach, Fiddler::kTypeLock, true, &mutex, &shared_value)));
|
| - fiddler_threads.push_back(new FiddlerThread(new Fiddler(
|
| - kTimesToLockEach, Fiddler::kTypeTry, true, &mutex, &shared_value)));
|
| - }
|
| -
|
| - for (size_t i = 0; i < kNumThreads; i++)
|
| - fiddler_threads[i]->Start();
|
| -
|
| - // Do some fiddling ourselves.
|
| - Fiddler(kTimesToLockEach, Fiddler::kTypeLock, true, &mutex, &shared_value)
|
| - .Fiddle();
|
| -
|
| - // Join.
|
| - for (size_t i = 0; i < kNumThreads; i++)
|
| - fiddler_threads[i]->Join();
|
| -
|
| - EXPECT_EQ(static_cast<int>(kNumThreads + 1) * kTimesToLockEach, shared_value);
|
| -
|
| - // Delete.
|
| - for (size_t i = 0; i < kNumThreads; i++)
|
| - delete fiddler_threads[i];
|
| - fiddler_threads.clear();
|
| -}
|
| -
|
| -class TryThread : public Thread {
|
| - public:
|
| - explicit TryThread(Mutex* mutex) : mutex_(mutex), try_lock_succeeded_() {}
|
| - ~TryThread() override {}
|
| -
|
| - void Run() override {
|
| - try_lock_succeeded_ = mutex_->TryLock();
|
| - if (try_lock_succeeded_)
|
| - mutex_->Unlock();
|
| - }
|
| -
|
| - bool try_lock_succeeded() const { return try_lock_succeeded_; }
|
| -
|
| - private:
|
| - Mutex* const mutex_;
|
| - bool try_lock_succeeded_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(TryThread);
|
| -};
|
| -
|
| -TEST(MutexTest, TryLock) {
|
| - Mutex mutex;
|
| -
|
| - // |TryLock()| should succeed -- we don't have the lock.
|
| - {
|
| - TryThread thread(&mutex);
|
| - thread.Start();
|
| - thread.Join();
|
| - EXPECT_TRUE(thread.try_lock_succeeded());
|
| - }
|
| -
|
| - // Take the lock.
|
| - ASSERT_TRUE(mutex.TryLock());
|
| -
|
| - // Now it should fail.
|
| - {
|
| - TryThread thread(&mutex);
|
| - thread.Start();
|
| - thread.Join();
|
| - EXPECT_FALSE(thread.try_lock_succeeded());
|
| - }
|
| -
|
| - // Release the lock.
|
| - mutex.Unlock();
|
| -
|
| - // It should succeed again.
|
| - {
|
| - TryThread thread(&mutex);
|
| - thread.Start();
|
| - thread.Join();
|
| - EXPECT_TRUE(thread.try_lock_succeeded());
|
| - }
|
| -}
|
| -
|
| -
|
| -// Tests of assertions for Debug builds.
|
| -#if !defined(NDEBUG)
|
| -// Test |AssertHeld()| (which is an actual user API).
|
| -TEST(MutexTest, DebugAssertHeldFailure) {
|
| - Mutex mutex;
|
| - EXPECT_DEATH_IF_SUPPORTED(mutex.AssertHeld(), "");
|
| -}
|
| -
|
| -// Test other consistency checks.
|
| -TEST(MutexTest, DebugAssertionFailures) {
|
| - // Unlock without lock held.
|
| - EXPECT_DEATH_IF_SUPPORTED({
|
| - Mutex mutex;
|
| - mutex.Unlock();
|
| - }, "");
|
| -
|
| - // Lock with lock held (on same thread).
|
| - EXPECT_DEATH_IF_SUPPORTED({
|
| - Mutex mutex;
|
| - mutex.Lock();
|
| - mutex.Lock();
|
| - }, "");
|
| -
|
| - // Try lock with lock held.
|
| - EXPECT_DEATH_IF_SUPPORTED({
|
| - Mutex mutex;
|
| - mutex.Lock();
|
| - mutex.TryLock();
|
| - }, "");
|
| -
|
| - // Destroy lock with lock held.
|
| - EXPECT_DEATH_IF_SUPPORTED({
|
| - Mutex mutex;
|
| - mutex.Lock();
|
| - }, "");
|
| -}
|
| -#endif // !defined(NDEBUG)
|
| -
|
| -} // namespace
|
| -} // namespace mojo
|
|
|