blob: bc5b1e473a5fdc21ee01496a1e19f3fd66bde7c6 [file] [log] [blame]
[email protected]8c3881ab2012-01-04 19:02:381// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]d9ddc962010-08-24 04:29:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
dcheng093de9b2016-04-04 21:25:515#include "base/threading/thread_checker.h"
6
7#include <memory>
8
[email protected]d9ddc962010-08-24 04:29:569#include "base/logging.h"
avi9ceb8b82015-12-24 21:53:5910#include "base/macros.h"
[email protected]ac9ba8fe2010-12-30 18:08:3611#include "base/threading/simple_thread.h"
[email protected]d9ddc962010-08-24 04:29:5612#include "testing/gtest/include/gtest/gtest.h"
13
[email protected]8c3881ab2012-01-04 19:02:3814// Duplicated from base/threading/thread_checker.h so that we can be
15// good citizens there and undef the macro.
[email protected]85588412012-06-27 01:39:5216#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
17#define ENABLE_THREAD_CHECKER 1
18#else
19#define ENABLE_THREAD_CHECKER 0
20#endif
[email protected]8c3881ab2012-01-04 19:02:3821
[email protected]ce072a72010-12-31 20:02:1622namespace base {
23
[email protected]85588412012-06-27 01:39:5224namespace {
25
[email protected]40064482011-03-03 23:38:5126// Simple class to exercise the basics of ThreadChecker.
[email protected]d9ddc962010-08-24 04:29:5627// Both the destructor and DoStuff should verify that they were
28// called on the same thread as the constructor.
29class ThreadCheckerClass : public ThreadChecker {
30 public:
31 ThreadCheckerClass() {}
32
33 // Verifies that it was called on the same thread as the constructor.
34 void DoStuff() {
[email protected]a42d4632011-10-26 21:48:0035 DCHECK(CalledOnValidThread());
[email protected]d9ddc962010-08-24 04:29:5636 }
37
[email protected]8ff672512010-10-07 20:17:3338 void DetachFromThread() {
39 ThreadChecker::DetachFromThread();
40 }
41
[email protected]40064482011-03-03 23:38:5142 static void MethodOnDifferentThreadImpl();
43 static void DetachThenCallFromDifferentThreadImpl();
44
[email protected]d9ddc962010-08-24 04:29:5645 private:
46 DISALLOW_COPY_AND_ASSIGN(ThreadCheckerClass);
47};
48
49// Calls ThreadCheckerClass::DoStuff on another thread.
50class CallDoStuffOnThread : public base::SimpleThread {
51 public:
[email protected]f3c697c52013-01-15 10:52:1152 explicit CallDoStuffOnThread(ThreadCheckerClass* thread_checker_class)
[email protected]d9ddc962010-08-24 04:29:5653 : SimpleThread("call_do_stuff_on_thread"),
54 thread_checker_class_(thread_checker_class) {
55 }
56
dcheng56488182014-10-21 10:54:5157 void Run() override { thread_checker_class_->DoStuff(); }
[email protected]d9ddc962010-08-24 04:29:5658
59 private:
60 ThreadCheckerClass* thread_checker_class_;
61
62 DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
63};
64
65// Deletes ThreadCheckerClass on a different thread.
66class DeleteThreadCheckerClassOnThread : public base::SimpleThread {
67 public:
[email protected]f3c697c52013-01-15 10:52:1168 explicit DeleteThreadCheckerClassOnThread(
69 ThreadCheckerClass* thread_checker_class)
[email protected]d9ddc962010-08-24 04:29:5670 : SimpleThread("delete_thread_checker_class_on_thread"),
71 thread_checker_class_(thread_checker_class) {
72 }
73
dcheng56488182014-10-21 10:54:5174 void Run() override { thread_checker_class_.reset(); }
[email protected]d9ddc962010-08-24 04:29:5675
76 private:
dcheng093de9b2016-04-04 21:25:5177 std::unique_ptr<ThreadCheckerClass> thread_checker_class_;
[email protected]d9ddc962010-08-24 04:29:5678
79 DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread);
80};
81
[email protected]85588412012-06-27 01:39:5282} // namespace
83
[email protected]d9ddc962010-08-24 04:29:5684TEST(ThreadCheckerTest, CallsAllowedOnSameThread) {
dcheng093de9b2016-04-04 21:25:5185 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
[email protected]d9ddc962010-08-24 04:29:5686 new ThreadCheckerClass);
87
88 // Verify that DoStuff doesn't assert.
89 thread_checker_class->DoStuff();
90
91 // Verify that the destructor doesn't assert.
92 thread_checker_class.reset();
93}
94
95TEST(ThreadCheckerTest, DestructorAllowedOnDifferentThread) {
dcheng093de9b2016-04-04 21:25:5196 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
[email protected]d9ddc962010-08-24 04:29:5697 new ThreadCheckerClass);
98
99 // Verify that the destructor doesn't assert
100 // when called on a different thread.
101 DeleteThreadCheckerClassOnThread delete_on_thread(
102 thread_checker_class.release());
103
104 delete_on_thread.Start();
105 delete_on_thread.Join();
106}
107
[email protected]8ff672512010-10-07 20:17:33108TEST(ThreadCheckerTest, DetachFromThread) {
dcheng093de9b2016-04-04 21:25:51109 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
[email protected]8ff672512010-10-07 20:17:33110 new ThreadCheckerClass);
111
112 // Verify that DoStuff doesn't assert when called on a different thread after
113 // a call to DetachFromThread.
114 thread_checker_class->DetachFromThread();
115 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
116
117 call_on_thread.Start();
118 call_on_thread.Join();
119}
120
[email protected]8c3881ab2012-01-04 19:02:38121#if GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
[email protected]d9ddc962010-08-24 04:29:56122
[email protected]40064482011-03-03 23:38:51123void ThreadCheckerClass::MethodOnDifferentThreadImpl() {
dcheng093de9b2016-04-04 21:25:51124 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
[email protected]40064482011-03-03 23:38:51125 new ThreadCheckerClass);
[email protected]d9ddc962010-08-24 04:29:56126
[email protected]40064482011-03-03 23:38:51127 // DoStuff should assert in debug builds only when called on a
128 // different thread.
129 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
[email protected]d9ddc962010-08-24 04:29:56130
[email protected]40064482011-03-03 23:38:51131 call_on_thread.Start();
132 call_on_thread.Join();
[email protected]d9ddc962010-08-24 04:29:56133}
134
[email protected]8c3881ab2012-01-04 19:02:38135#if ENABLE_THREAD_CHECKER
[email protected]40064482011-03-03 23:38:51136TEST(ThreadCheckerDeathTest, MethodNotAllowedOnDifferentThreadInDebug) {
[email protected]85588412012-06-27 01:39:52137 ASSERT_DEATH({
[email protected]40064482011-03-03 23:38:51138 ThreadCheckerClass::MethodOnDifferentThreadImpl();
[email protected]8ff672512010-10-07 20:17:33139 }, "");
140}
[email protected]40064482011-03-03 23:38:51141#else
142TEST(ThreadCheckerTest, MethodAllowedOnDifferentThreadInRelease) {
143 ThreadCheckerClass::MethodOnDifferentThreadImpl();
144}
[email protected]8c3881ab2012-01-04 19:02:38145#endif // ENABLE_THREAD_CHECKER
[email protected]8ff672512010-10-07 20:17:33146
[email protected]40064482011-03-03 23:38:51147void ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl() {
dcheng093de9b2016-04-04 21:25:51148 std::unique_ptr<ThreadCheckerClass> thread_checker_class(
[email protected]40064482011-03-03 23:38:51149 new ThreadCheckerClass);
150
151 // DoStuff doesn't assert when called on a different thread
152 // after a call to DetachFromThread.
153 thread_checker_class->DetachFromThread();
154 CallDoStuffOnThread call_on_thread(thread_checker_class.get());
155
156 call_on_thread.Start();
157 call_on_thread.Join();
158
159 // DoStuff should assert in debug builds only after moving to
160 // another thread.
161 thread_checker_class->DoStuff();
162}
163
[email protected]8c3881ab2012-01-04 19:02:38164#if ENABLE_THREAD_CHECKER
[email protected]40064482011-03-03 23:38:51165TEST(ThreadCheckerDeathTest, DetachFromThreadInDebug) {
[email protected]85588412012-06-27 01:39:52166 ASSERT_DEATH({
[email protected]40064482011-03-03 23:38:51167 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
168 }, "");
169}
170#else
171TEST(ThreadCheckerTest, DetachFromThreadInRelease) {
172 ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl();
173}
[email protected]8c3881ab2012-01-04 19:02:38174#endif // ENABLE_THREAD_CHECKER
[email protected]40064482011-03-03 23:38:51175
[email protected]8c3881ab2012-01-04 19:02:38176#endif // GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
177
178// Just in case we ever get lumped together with other compilation units.
179#undef ENABLE_THREAD_CHECKER
[email protected]d9ddc962010-08-24 04:29:56180
[email protected]ce072a72010-12-31 20:02:16181} // namespace base