Index: base/threading/thread_checker_unittest.cc |
diff --git a/base/threading/thread_checker_unittest.cc b/base/threading/thread_checker_unittest.cc |
index bc5b1e473a5fdc21ee01496a1e19f3fd66bde7c6..dedf5db07be4898861b884503375e0086c747580 100644 |
--- a/base/threading/thread_checker_unittest.cc |
+++ b/base/threading/thread_checker_unittest.cc |
@@ -2,180 +2,162 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "base/threading/thread_checker.h" |
- |
#include <memory> |
-#include "base/logging.h" |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
#include "base/macros.h" |
+#include "base/memory/ref_counted.h" |
+#include "base/sequence_token.h" |
+#include "base/test/test_simple_task_runner.h" |
#include "base/threading/simple_thread.h" |
+#include "base/threading/thread_checker_impl.h" |
+#include "base/threading/thread_task_runner_handle.h" |
#include "testing/gtest/include/gtest/gtest.h" |
-// Duplicated from base/threading/thread_checker.h so that we can be |
-// good citizens there and undef the macro. |
-#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) |
-#define ENABLE_THREAD_CHECKER 1 |
-#else |
-#define ENABLE_THREAD_CHECKER 0 |
-#endif |
- |
namespace base { |
- |
namespace { |
-// Simple class to exercise the basics of ThreadChecker. |
-// Both the destructor and DoStuff should verify that they were |
-// called on the same thread as the constructor. |
-class ThreadCheckerClass : public ThreadChecker { |
+// Runs a callback on another thread. |
+class RunCallbackThread : public SimpleThread { |
public: |
- ThreadCheckerClass() {} |
- |
- // Verifies that it was called on the same thread as the constructor. |
- void DoStuff() { |
- DCHECK(CalledOnValidThread()); |
+ explicit RunCallbackThread(const Closure& callback) |
+ : SimpleThread("RunCallbackThread"), callback_(callback) { |
+ Start(); |
+ Join(); |
} |
- void DetachFromThread() { |
- ThreadChecker::DetachFromThread(); |
- } |
- |
- static void MethodOnDifferentThreadImpl(); |
- static void DetachThenCallFromDifferentThreadImpl(); |
- |
private: |
- DISALLOW_COPY_AND_ASSIGN(ThreadCheckerClass); |
-}; |
- |
-// Calls ThreadCheckerClass::DoStuff on another thread. |
-class CallDoStuffOnThread : public base::SimpleThread { |
- public: |
- explicit CallDoStuffOnThread(ThreadCheckerClass* thread_checker_class) |
- : SimpleThread("call_do_stuff_on_thread"), |
- thread_checker_class_(thread_checker_class) { |
- } |
+ // SimpleThread: |
+ void Run() override { callback_.Run(); } |
- void Run() override { thread_checker_class_->DoStuff(); } |
+ const Closure callback_; |
- private: |
- ThreadCheckerClass* thread_checker_class_; |
- |
- DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread); |
+ DISALLOW_COPY_AND_ASSIGN(RunCallbackThread); |
}; |
-// Deletes ThreadCheckerClass on a different thread. |
-class DeleteThreadCheckerClassOnThread : public base::SimpleThread { |
- public: |
- explicit DeleteThreadCheckerClassOnThread( |
- ThreadCheckerClass* thread_checker_class) |
- : SimpleThread("delete_thread_checker_class_on_thread"), |
- thread_checker_class_(thread_checker_class) { |
- } |
- |
- void Run() override { thread_checker_class_.reset(); } |
+void ExpectCalledOnValidThread(ThreadCheckerImpl* thread_checker) { |
+ ASSERT_TRUE(thread_checker); |
- private: |
- std::unique_ptr<ThreadCheckerClass> thread_checker_class_; |
+ // This should bind |thread_checker| to the current thread if it wasn't |
+ // already bound to a thread. |
+ EXPECT_TRUE(thread_checker->CalledOnValidThread()); |
- DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread); |
-}; |
+ // Since |thread_checker| is now bound to the current thread, another call to |
+ // CalledOnValidThread() should return true. |
+ EXPECT_TRUE(thread_checker->CalledOnValidThread()); |
+} |
-} // namespace |
+void ExpectNotCalledOnValidThread(ThreadCheckerImpl* thread_checker) { |
+ ASSERT_TRUE(thread_checker); |
+ EXPECT_FALSE(thread_checker->CalledOnValidThread()); |
+} |
-TEST(ThreadCheckerTest, CallsAllowedOnSameThread) { |
- std::unique_ptr<ThreadCheckerClass> thread_checker_class( |
- new ThreadCheckerClass); |
+void ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle( |
+ ThreadCheckerImpl* thread_checker, |
+ internal::SequenceToken sequence_token) { |
+ ThreadTaskRunnerHandle thread_task_runner_handle( |
+ make_scoped_refptr(new TestSimpleTaskRunner)); |
+ internal::ScopedSetCurrentSequenceToken scoped_set_current_sequence_token( |
+ sequence_token); |
+ ExpectNotCalledOnValidThread(thread_checker); |
+} |
- // Verify that DoStuff doesn't assert. |
- thread_checker_class->DoStuff(); |
+} // namespace |
- // Verify that the destructor doesn't assert. |
- thread_checker_class.reset(); |
+TEST(ThreadCheckerTest, CallsAllowedSameThreadNoSequenceToken) { |
+ ThreadCheckerImpl thread_checker; |
+ EXPECT_TRUE(thread_checker.CalledOnValidThread()); |
} |
-TEST(ThreadCheckerTest, DestructorAllowedOnDifferentThread) { |
- std::unique_ptr<ThreadCheckerClass> thread_checker_class( |
- new ThreadCheckerClass); |
+TEST(ThreadCheckerTest, |
+ CallsAllowedSameThreadSameSequenceTokenWithThreadTaskRunnerHandle) { |
+ ThreadTaskRunnerHandle thread_task_runner_handle( |
+ make_scoped_refptr(new TestSimpleTaskRunner)); |
+ internal::ScopedSetCurrentSequenceToken scoped_set_current_sequence_token( |
+ internal::SequenceToken::Create()); |
+ ThreadCheckerImpl thread_checker; |
+ EXPECT_TRUE(thread_checker.CalledOnValidThread()); |
+} |
- // Verify that the destructor doesn't assert |
- // when called on a different thread. |
- DeleteThreadCheckerClassOnThread delete_on_thread( |
- thread_checker_class.release()); |
+TEST(ThreadCheckerTest, |
+ CallsDisallowedSameThreadSameSequenceTokenNoThreadTaskRunnerHandle) { |
+ internal::ScopedSetCurrentSequenceToken scoped_set_current_sequence_token( |
+ internal::SequenceToken::Create()); |
+ ThreadCheckerImpl thread_checker; |
+ EXPECT_FALSE(thread_checker.CalledOnValidThread()); |
+} |
- delete_on_thread.Start(); |
- delete_on_thread.Join(); |
+TEST(ThreadCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) { |
+ ThreadCheckerImpl thread_checker; |
+ RunCallbackThread thread( |
+ Bind(&ExpectNotCalledOnValidThread, Unretained(&thread_checker))); |
} |
-TEST(ThreadCheckerTest, DetachFromThread) { |
- std::unique_ptr<ThreadCheckerClass> thread_checker_class( |
- new ThreadCheckerClass); |
+TEST(ThreadCheckerTest, CallsDisallowedOnDifferentThreadsSameSequenceToken) { |
+ ThreadTaskRunnerHandle thread_task_runner_handle( |
+ make_scoped_refptr(new TestSimpleTaskRunner)); |
+ const internal::SequenceToken sequence_token( |
+ internal::SequenceToken::Create()); |
- // Verify that DoStuff doesn't assert when called on a different thread after |
- // a call to DetachFromThread. |
- thread_checker_class->DetachFromThread(); |
- CallDoStuffOnThread call_on_thread(thread_checker_class.get()); |
+ internal::ScopedSetCurrentSequenceToken scoped_set_current_sequence_token( |
+ sequence_token); |
+ ThreadCheckerImpl thread_checker; |
gab
2016/07/21 21:14:24
EXPECT_TRUE on this thread to drive essence of tes
fdoray
2016/07/25 13:24:28
Done.
|
- call_on_thread.Start(); |
- call_on_thread.Join(); |
+ RunCallbackThread thread(Bind( |
+ &ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle, |
+ Unretained(&thread_checker), sequence_token)); |
} |
-#if GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER |
+TEST(ThreadCheckerTest, CallsDisallowedSameThreadDifferentSequenceToken) { |
+ std::unique_ptr<ThreadCheckerImpl> thread_checker; |
-void ThreadCheckerClass::MethodOnDifferentThreadImpl() { |
- std::unique_ptr<ThreadCheckerClass> thread_checker_class( |
- new ThreadCheckerClass); |
+ ThreadTaskRunnerHandle thread_task_runner_handle( |
+ make_scoped_refptr(new TestSimpleTaskRunner)); |
- // DoStuff should assert in debug builds only when called on a |
- // different thread. |
- CallDoStuffOnThread call_on_thread(thread_checker_class.get()); |
+ { |
+ internal::ScopedSetCurrentSequenceToken scoped_set_current_sequence_token( |
+ internal::SequenceToken::Create()); |
+ thread_checker.reset(new ThreadCheckerImpl); |
+ } |
- call_on_thread.Start(); |
- call_on_thread.Join(); |
-} |
+ { |
+ // Different SequenceToken. |
+ internal::ScopedSetCurrentSequenceToken scoped_set_current_sequence_token( |
+ internal::SequenceToken::Create()); |
+ EXPECT_FALSE(thread_checker->CalledOnValidThread()); |
+ } |
-#if ENABLE_THREAD_CHECKER |
-TEST(ThreadCheckerDeathTest, MethodNotAllowedOnDifferentThreadInDebug) { |
- ASSERT_DEATH({ |
- ThreadCheckerClass::MethodOnDifferentThreadImpl(); |
- }, ""); |
+ // No SequenceToken. |
+ EXPECT_FALSE(thread_checker->CalledOnValidThread()); |
} |
-#else |
-TEST(ThreadCheckerTest, MethodAllowedOnDifferentThreadInRelease) { |
- ThreadCheckerClass::MethodOnDifferentThreadImpl(); |
-} |
-#endif // ENABLE_THREAD_CHECKER |
- |
-void ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl() { |
- std::unique_ptr<ThreadCheckerClass> thread_checker_class( |
- new ThreadCheckerClass); |
- // DoStuff doesn't assert when called on a different thread |
- // after a call to DetachFromThread. |
- thread_checker_class->DetachFromThread(); |
- CallDoStuffOnThread call_on_thread(thread_checker_class.get()); |
+TEST(ThreadCheckerTest, DetachFromThread) { |
+ ThreadCheckerImpl thread_checker; |
+ thread_checker.DetachFromThread(); |
- call_on_thread.Start(); |
- call_on_thread.Join(); |
+ // Verify that CalledOnValidThread() returns true when called on a different |
+ // thread after a call to DetachFromThread(). |
+ RunCallbackThread thread( |
+ Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker))); |
- // DoStuff should assert in debug builds only after moving to |
- // another thread. |
- thread_checker_class->DoStuff(); |
+ EXPECT_FALSE(thread_checker.CalledOnValidThread()); |
} |
-#if ENABLE_THREAD_CHECKER |
-TEST(ThreadCheckerDeathTest, DetachFromThreadInDebug) { |
- ASSERT_DEATH({ |
- ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl(); |
- }, ""); |
-} |
-#else |
-TEST(ThreadCheckerTest, DetachFromThreadInRelease) { |
- ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl(); |
-} |
-#endif // ENABLE_THREAD_CHECKER |
+TEST(ThreadCheckerTest, DetachFromThreadWithSequenceToken) { |
+ ThreadTaskRunnerHandle thread_task_runner_handle( |
+ make_scoped_refptr(new TestSimpleTaskRunner)); |
+ internal::ScopedSetCurrentSequenceToken scoped_set_current_sequence_token( |
+ internal::SequenceToken::Create()); |
+ ThreadCheckerImpl thread_checker; |
+ thread_checker.DetachFromThread(); |
-#endif // GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER |
+ // Verify that CalledOnValidThread() returns true when called on a different |
+ // thread after a call to DetachFromThread(). |
+ RunCallbackThread thread( |
+ Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker))); |
-// Just in case we ever get lumped together with other compilation units. |
-#undef ENABLE_THREAD_CHECKER |
+ EXPECT_FALSE(thread_checker.CalledOnValidThread()); |
+} |
} // namespace base |