Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(529)

Unified Diff: base/thread_collision_warner_unittest.cc

Issue 6258: This CL is due the thread I have made on chromium-dev:... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/thread_collision_warner.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/thread_collision_warner_unittest.cc
===================================================================
--- base/thread_collision_warner_unittest.cc (revision 0)
+++ base/thread_collision_warner_unittest.cc (revision 0)
@@ -0,0 +1,362 @@
+// Copyright (c) 2008 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 "base/platform_thread.h"
+#include "base/simple_thread.h"
+#include "base/thread_collision_warner.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+
+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.
+ D_BOOK_CRITICAL_SECTION(warner);
+ EXPECT_FALSE(local_reporter->fail_state());
+ { // Pin section.
+ D_BOOK_CRITICAL_SECTION(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.
+ D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(warner);
+ EXPECT_FALSE(local_reporter->fail_state());
+ { // Pin section again (allowed by D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION)
+ D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(warner);
+ EXPECT_FALSE(local_reporter->fail_state());
+ } // Unpin section.
+ } // Unpin section.
+
+ // Check that section is not pinned
+ { // Pin section.
+ D_SCOPED_BOOK_CRITICAL_SECTION(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.
+ D_SCOPED_BOOK_CRITICAL_SECTION(warner);
+ EXPECT_FALSE(local_reporter->fail_state());
+ } // Unpin section.
+
+ { // Pin section.
+ D_SCOPED_BOOK_CRITICAL_SECTION(warner);
+ EXPECT_FALSE(local_reporter->fail_state());
+ { // Pin section again (not allowed by D_SCOPED_BOOK_CRITICAL_SECTION)
+ D_SCOPED_BOOK_CRITICAL_SECTION(warner);
+ EXPECT_TRUE(local_reporter->fail_state());
+ // Reset the status of warner for further tests.
+ local_reporter->reset();
+ } // Unpin section.
+ } // Unpin section.
+
+ { // Pin section.
+ D_SCOPED_BOOK_CRITICAL_SECTION(warner);
+ EXPECT_FALSE(local_reporter->fail_state());
+ } // Unpin section.
+
+}
+
+TEST(ThreadCollisionTest, MTBookCriticalSectionTest) {
+ class NonThreadSafeQueue {
+ public:
+ NonThreadSafeQueue(base::AsserterBase* asserter)
+ : push_pop_(asserter) { }
+
+ void push(int) {
+ D_BOOK_CRITICAL_SECTION(push_pop_);
+ }
+
+ int pop() {
+ D_BOOK_CRITICAL_SECTION(push_pop_);
+ return 0;
+ }
+
+ private:
+ base::ThreadCollisionWarner push_pop_;
+
+ DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
+ };
+
+ class QueueUser : public base::DelegateSimpleThread::Delegate {
+ public:
+ 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_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:
+ NonThreadSafeQueue(base::AsserterBase* asserter)
+ : push_pop_(asserter) { }
+
+ void push(int) {
+ D_SCOPED_BOOK_CRITICAL_SECTION(push_pop_);
+ PlatformThread::Sleep(5000);
+ }
+
+ int pop() {
+ D_SCOPED_BOOK_CRITICAL_SECTION(push_pop_);
+ return 0;
+ }
+
+ private:
+ base::ThreadCollisionWarner push_pop_;
+
+ DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
+ };
+
+ class QueueUser : public base::DelegateSimpleThread::Delegate {
+ public:
+ 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_TRUE(local_reporter->fail_state());
+}
+
+TEST(ThreadCollisionTest, MTSynchedScopedBookCriticalSectionTest) {
+
+ // 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:
+ NonThreadSafeQueue(base::AsserterBase* asserter)
+ : push_pop_(asserter) { }
+
+ void push(int) {
+ D_SCOPED_BOOK_CRITICAL_SECTION(push_pop_);
+ PlatformThread::Sleep(5000);
+ }
+
+ int pop() {
+ D_SCOPED_BOOK_CRITICAL_SECTION(push_pop_);
+ return 0;
+ }
+
+ private:
+ base::ThreadCollisionWarner 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 5 seconds push execution time, hopefuly the two used threads
+ // in the test will enter the push at same time.
+ class NonThreadSafeQueue {
+ public:
+ NonThreadSafeQueue(base::AsserterBase* asserter)
+ : push_pop_(asserter) { }
+
+ void push(int) {
+ D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(push_pop_);
+ bar();
+ PlatformThread::Sleep(5000);
+ }
+
+ int pop() {
+ D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(push_pop_);
+ return 0;
+ }
+
+ void bar() {
+ D_SCOPED_RECURSIVE_BOOK_CRITICAL_SECTION(push_pop_);
+ }
+
+ private:
+ base::ThreadCollisionWarner 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());
+}
+
« no previous file with comments | « base/thread_collision_warner.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698