Index: base/thread_collision_warner_unittest.cc |
=================================================================== |
--- base/thread_collision_warner_unittest.cc (revision 70342) |
+++ base/thread_collision_warner_unittest.cc (working copy) |
@@ -1,385 +0,0 @@ |
-// 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/compiler_specific.h" |
-#include "base/lock.h" |
-#include "base/scoped_ptr.h" |
-#include "base/threading/platform_thread.h" |
-#include "base/threading/simple_thread.h" |
-#include "base/thread_collision_warner.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-// '' : local class member function does not have a body |
-MSVC_PUSH_DISABLE_WARNING(4822) |
- |
- |
-#if defined(NDEBUG) |
- |
-// Would cause a memory leak otherwise. |
-#undef DFAKE_MUTEX |
-#define DFAKE_MUTEX(obj) scoped_ptr<base::AsserterBase> obj |
- |
-// In Release, we expect the AsserterBase::warn() to not happen. |
-#define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_FALSE |
- |
-#else |
- |
-// In Debug, we expect the AsserterBase::warn() to happen. |
-#define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_TRUE |
- |
-#endif |
- |
- |
-namespace { |
- |
-// This is the asserter used with ThreadCollisionWarner instead of the default |
-// DCheckAsserter. The method fail_state is used to know if a collision took |
-// place. |
-class AssertReporter : public base::AsserterBase { |
- public: |
- AssertReporter() |
- : failed_(false) {} |
- |
- virtual void warn() { |
- failed_ = true; |
- } |
- |
- virtual ~AssertReporter() {} |
- |
- bool fail_state() const { return failed_; } |
- void reset() { failed_ = false; } |
- |
- private: |
- bool failed_; |
-}; |
- |
-} // namespace |
- |
-TEST(ThreadCollisionTest, BookCriticalSection) { |
- AssertReporter* local_reporter = new AssertReporter(); |
- |
- base::ThreadCollisionWarner warner(local_reporter); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- |
- { // Pin section. |
- DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- { // Pin section. |
- DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- } |
- } |
-} |
- |
-TEST(ThreadCollisionTest, ScopedRecursiveBookCriticalSection) { |
- AssertReporter* local_reporter = new AssertReporter(); |
- |
- base::ThreadCollisionWarner warner(local_reporter); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- |
- { // Pin section. |
- DFAKE_SCOPED_RECURSIVE_LOCK(warner); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- { // Pin section again (allowed by DFAKE_SCOPED_RECURSIVE_LOCK) |
- DFAKE_SCOPED_RECURSIVE_LOCK(warner); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- } // Unpin section. |
- } // Unpin section. |
- |
- // Check that section is not pinned |
- { // Pin section. |
- DFAKE_SCOPED_LOCK(warner); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- } // Unpin section. |
-} |
- |
-TEST(ThreadCollisionTest, ScopedBookCriticalSection) { |
- AssertReporter* local_reporter = new AssertReporter(); |
- |
- base::ThreadCollisionWarner warner(local_reporter); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- |
- { // Pin section. |
- DFAKE_SCOPED_LOCK(warner); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- } // Unpin section. |
- |
- { // Pin section. |
- DFAKE_SCOPED_LOCK(warner); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- { |
- // Pin section again (not allowed by DFAKE_SCOPED_LOCK) |
- DFAKE_SCOPED_LOCK(warner); |
- EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state()); |
- // Reset the status of warner for further tests. |
- local_reporter->reset(); |
- } // Unpin section. |
- } // Unpin section. |
- |
- { |
- // Pin section. |
- DFAKE_SCOPED_LOCK(warner); |
- EXPECT_FALSE(local_reporter->fail_state()); |
- } // Unpin section. |
-} |
- |
-TEST(ThreadCollisionTest, MTBookCriticalSectionTest) { |
- class NonThreadSafeQueue { |
- public: |
- explicit NonThreadSafeQueue(base::AsserterBase* asserter) |
- : push_pop_(asserter) { |
- } |
- |
- void push(int value) { |
- DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); |
- } |
- |
- int pop() { |
- DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); |
- return 0; |
- } |
- |
- private: |
- DFAKE_MUTEX(push_pop_); |
- |
- DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue); |
- }; |
- |
- class QueueUser : public base::DelegateSimpleThread::Delegate { |
- public: |
- explicit QueueUser(NonThreadSafeQueue& queue) |
- : queue_(queue) {} |
- |
- virtual void Run() { |
- queue_.push(0); |
- queue_.pop(); |
- } |
- |
- private: |
- NonThreadSafeQueue& queue_; |
- }; |
- |
- AssertReporter* local_reporter = new AssertReporter(); |
- |
- NonThreadSafeQueue queue(local_reporter); |
- |
- QueueUser queue_user_a(queue); |
- QueueUser queue_user_b(queue); |
- |
- base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a"); |
- base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b"); |
- |
- thread_a.Start(); |
- thread_b.Start(); |
- |
- thread_a.Join(); |
- thread_b.Join(); |
- |
- EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state()); |
-} |
- |
-TEST(ThreadCollisionTest, MTScopedBookCriticalSectionTest) { |
- // Queue with a 5 seconds push execution time, hopefuly the two used threads |
- // in the test will enter the push at same time. |
- class NonThreadSafeQueue { |
- public: |
- explicit NonThreadSafeQueue(base::AsserterBase* asserter) |
- : push_pop_(asserter) { |
- } |
- |
- void push(int value) { |
- DFAKE_SCOPED_LOCK(push_pop_); |
- base::PlatformThread::Sleep(5000); |
- } |
- |
- int pop() { |
- DFAKE_SCOPED_LOCK(push_pop_); |
- return 0; |
- } |
- |
- private: |
- DFAKE_MUTEX(push_pop_); |
- |
- DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue); |
- }; |
- |
- class QueueUser : public base::DelegateSimpleThread::Delegate { |
- public: |
- explicit QueueUser(NonThreadSafeQueue& queue) |
- : queue_(queue) {} |
- |
- virtual void Run() { |
- queue_.push(0); |
- queue_.pop(); |
- } |
- |
- private: |
- NonThreadSafeQueue& queue_; |
- }; |
- |
- AssertReporter* local_reporter = new AssertReporter(); |
- |
- NonThreadSafeQueue queue(local_reporter); |
- |
- QueueUser queue_user_a(queue); |
- QueueUser queue_user_b(queue); |
- |
- base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a"); |
- base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b"); |
- |
- thread_a.Start(); |
- thread_b.Start(); |
- |
- thread_a.Join(); |
- thread_b.Join(); |
- |
- EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state()); |
-} |
- |
-TEST(ThreadCollisionTest, MTSynchedScopedBookCriticalSectionTest) { |
- // Queue with a 2 seconds push execution time, hopefuly the two used threads |
- // in the test will enter the push at same time. |
- class NonThreadSafeQueue { |
- public: |
- explicit NonThreadSafeQueue(base::AsserterBase* asserter) |
- : push_pop_(asserter) { |
- } |
- |
- void push(int value) { |
- DFAKE_SCOPED_LOCK(push_pop_); |
- base::PlatformThread::Sleep(2000); |
- } |
- |
- int pop() { |
- DFAKE_SCOPED_LOCK(push_pop_); |
- return 0; |
- } |
- |
- private: |
- DFAKE_MUTEX(push_pop_); |
- |
- DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue); |
- }; |
- |
- // This time the QueueUser class protects the non thread safe queue with |
- // a lock. |
- class QueueUser : public base::DelegateSimpleThread::Delegate { |
- public: |
- QueueUser(NonThreadSafeQueue& queue, Lock& lock) |
- : queue_(queue), |
- lock_(lock) {} |
- |
- virtual void Run() { |
- { |
- AutoLock auto_lock(lock_); |
- queue_.push(0); |
- } |
- { |
- AutoLock auto_lock(lock_); |
- queue_.pop(); |
- } |
- } |
- private: |
- NonThreadSafeQueue& queue_; |
- Lock& lock_; |
- }; |
- |
- AssertReporter* local_reporter = new AssertReporter(); |
- |
- NonThreadSafeQueue queue(local_reporter); |
- |
- Lock lock; |
- |
- QueueUser queue_user_a(queue, lock); |
- QueueUser queue_user_b(queue, lock); |
- |
- base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a"); |
- base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b"); |
- |
- thread_a.Start(); |
- thread_b.Start(); |
- |
- thread_a.Join(); |
- thread_b.Join(); |
- |
- EXPECT_FALSE(local_reporter->fail_state()); |
-} |
- |
-TEST(ThreadCollisionTest, MTSynchedScopedRecursiveBookCriticalSectionTest) { |
- // Queue with a 2 seconds push execution time, hopefuly the two used threads |
- // in the test will enter the push at same time. |
- class NonThreadSafeQueue { |
- public: |
- explicit NonThreadSafeQueue(base::AsserterBase* asserter) |
- : push_pop_(asserter) { |
- } |
- |
- void push(int) { |
- DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); |
- bar(); |
- base::PlatformThread::Sleep(2000); |
- } |
- |
- int pop() { |
- DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); |
- return 0; |
- } |
- |
- void bar() { |
- DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); |
- } |
- |
- private: |
- DFAKE_MUTEX(push_pop_); |
- |
- DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue); |
- }; |
- |
- // This time the QueueUser class protects the non thread safe queue with |
- // a lock. |
- class QueueUser : public base::DelegateSimpleThread::Delegate { |
- public: |
- QueueUser(NonThreadSafeQueue& queue, Lock& lock) |
- : queue_(queue), |
- lock_(lock) {} |
- |
- virtual void Run() { |
- { |
- AutoLock auto_lock(lock_); |
- queue_.push(0); |
- } |
- { |
- AutoLock auto_lock(lock_); |
- queue_.bar(); |
- } |
- { |
- AutoLock auto_lock(lock_); |
- queue_.pop(); |
- } |
- } |
- private: |
- NonThreadSafeQueue& queue_; |
- Lock& lock_; |
- }; |
- |
- AssertReporter* local_reporter = new AssertReporter(); |
- |
- NonThreadSafeQueue queue(local_reporter); |
- |
- Lock lock; |
- |
- QueueUser queue_user_a(queue, lock); |
- QueueUser queue_user_b(queue, lock); |
- |
- base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a"); |
- base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b"); |
- |
- thread_a.Start(); |
- thread_b.Start(); |
- |
- thread_a.Join(); |
- thread_b.Join(); |
- |
- EXPECT_FALSE(local_reporter->fail_state()); |
-} |