summaryrefslogtreecommitdiffstats
path: root/base/lock_unittest.cc
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-30 05:50:42 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-30 05:50:42 +0000
commit5dd879a6fb6d07222d6a940643301a3e0d5bc010 (patch)
tree37361ad54875a7d2a419591c48ca43a40ced66b4 /base/lock_unittest.cc
parent587b40b6124aea9759b6b90ffb01e72fc2610935 (diff)
downloadchromium_src-5dd879a6fb6d07222d6a940643301a3e0d5bc010.zip
chromium_src-5dd879a6fb6d07222d6a940643301a3e0d5bc010.tar.gz
chromium_src-5dd879a6fb6d07222d6a940643301a3e0d5bc010.tar.bz2
Add unit tests for base/platform_thread.* and base/lock.*.
BUG=none TEST=base_unittests Review URL: http://codereview.chromium.org/3030025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54283 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/lock_unittest.cc')
-rw-r--r--base/lock_unittest.cc213
1 files changed, 213 insertions, 0 deletions
diff --git a/base/lock_unittest.cc b/base/lock_unittest.cc
new file mode 100644
index 0000000..cf99df9
--- /dev/null
+++ b/base/lock_unittest.cc
@@ -0,0 +1,213 @@
+// Copyright (c) 2010 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 "base/lock.h"
+
+#include <stdlib.h>
+
+#include "base/platform_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+typedef testing::Test LockTest;
+
+// Basic test to make sure that Acquire()/Release()/Try() don't crash ----------
+
+class BasicLockTestThread : public PlatformThread::Delegate {
+ public:
+ BasicLockTestThread(Lock* lock) : lock_(lock), acquired_(0) {}
+
+ virtual void ThreadMain() {
+ for (int i = 0; i < 10; i++) {
+ lock_->Acquire();
+ acquired_++;
+ lock_->Release();
+ }
+ for (int i = 0; i < 10; i++) {
+ lock_->Acquire();
+ acquired_++;
+ PlatformThread::Sleep(rand() % 20);
+ lock_->Release();
+ }
+ for (int i = 0; i < 10; i++) {
+ if (lock_->Try()) {
+ acquired_++;
+ PlatformThread::Sleep(rand() % 20);
+ lock_->Release();
+ }
+ }
+ }
+
+ int acquired() const { return acquired_; }
+
+ private:
+ Lock* lock_;
+ int acquired_;
+
+ DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread);
+};
+
+TEST_F(LockTest, Basic) {
+ Lock lock;
+ BasicLockTestThread thread(&lock);
+ PlatformThreadHandle handle = kNullThreadHandle;
+
+ ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+
+ int acquired = 0;
+ for (int i = 0; i < 5; i++) {
+ lock.Acquire();
+ acquired++;
+ lock.Release();
+ }
+ for (int i = 0; i < 10; i++) {
+ lock.Acquire();
+ acquired++;
+ PlatformThread::Sleep(rand() % 20);
+ lock.Release();
+ }
+ for (int i = 0; i < 10; i++) {
+ if (lock.Try()) {
+ acquired++;
+ PlatformThread::Sleep(rand() % 20);
+ lock.Release();
+ }
+ }
+ for (int i = 0; i < 5; i++) {
+ lock.Acquire();
+ acquired++;
+ PlatformThread::Sleep(rand() % 20);
+ lock.Release();
+ }
+
+ PlatformThread::Join(handle);
+
+ EXPECT_GE(acquired, 20);
+ EXPECT_GE(thread.acquired(), 20);
+}
+
+// Test that Try() works as expected -------------------------------------------
+
+class TryLockTestThread : public PlatformThread::Delegate {
+ public:
+ TryLockTestThread(Lock* lock) : lock_(lock), got_lock_(false) {}
+
+ virtual void ThreadMain() {
+ got_lock_ = lock_->Try();
+ if (got_lock_)
+ lock_->Release();
+ }
+
+ bool got_lock() const { return got_lock_; }
+
+ private:
+ Lock* lock_;
+ bool got_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(TryLockTestThread);
+};
+
+TEST_F(LockTest, TryLock) {
+ Lock lock;
+
+ ASSERT_TRUE(lock.Try());
+ // We now have the lock....
+
+ // This thread will not be able to get the lock.
+ {
+ TryLockTestThread thread(&lock);
+ PlatformThreadHandle handle = kNullThreadHandle;
+
+ ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+
+ PlatformThread::Join(handle);
+
+ ASSERT_FALSE(thread.got_lock());
+ }
+
+ lock.Release();
+
+ // This thread will....
+ {
+ TryLockTestThread thread(&lock);
+ PlatformThreadHandle handle = kNullThreadHandle;
+
+ ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+
+ PlatformThread::Join(handle);
+
+ ASSERT_TRUE(thread.got_lock());
+ // But it released it....
+ ASSERT_TRUE(lock.Try());
+ }
+
+ lock.Release();
+}
+
+// Tests that locks actually exclude -------------------------------------------
+
+class MutexLockTestThread : public PlatformThread::Delegate {
+ public:
+ MutexLockTestThread(Lock* lock, int* value) : lock_(lock), value_(value) {}
+
+ // Static helper which can also be called from the main thread.
+ static void DoStuff(Lock* lock, int* value) {
+ for (int i = 0; i < 40; i++) {
+ lock->Acquire();
+ int v = *value;
+ PlatformThread::Sleep(rand() % 10);
+ *value = v + 1;
+ lock->Release();
+ }
+ }
+
+ virtual void ThreadMain() {
+ DoStuff(lock_, value_);
+ }
+
+ private:
+ Lock* lock_;
+ int* value_;
+
+ DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread);
+};
+
+TEST_F(LockTest, MutexTwoThreads) {
+ Lock lock;
+ int value = 0;
+
+ MutexLockTestThread thread(&lock, &value);
+ PlatformThreadHandle handle = kNullThreadHandle;
+
+ ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+
+ MutexLockTestThread::DoStuff(&lock, &value);
+
+ PlatformThread::Join(handle);
+
+ EXPECT_EQ(2 * 40, value);
+}
+
+TEST_F(LockTest, MutexFourThreads) {
+ Lock lock;
+ int value = 0;
+
+ MutexLockTestThread thread1(&lock, &value);
+ MutexLockTestThread thread2(&lock, &value);
+ MutexLockTestThread thread3(&lock, &value);
+ PlatformThreadHandle handle1 = kNullThreadHandle;
+ PlatformThreadHandle handle2 = kNullThreadHandle;
+ PlatformThreadHandle handle3 = kNullThreadHandle;
+
+ ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1));
+ ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2));
+ ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3));
+
+ MutexLockTestThread::DoStuff(&lock, &value);
+
+ PlatformThread::Join(handle1);
+ PlatformThread::Join(handle2);
+ PlatformThread::Join(handle3);
+
+ EXPECT_EQ(4 * 40, value);
+}