blob: 5fbbc5284a78d9615401d83d006d1cc64aeb076c [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
gabd52c912a2017-05-11 04:15:595#include "base/threading/thread_checker.h"
6
dcheng093de9b2016-04-04 21:25:517#include <memory>
8
fdoray59fbfc42016-08-03 01:53:069#include "base/bind.h"
10#include "base/bind_helpers.h"
avi9ceb8b82015-12-24 21:53:5911#include "base/macros.h"
fdoray59fbfc42016-08-03 01:53:0612#include "base/memory/ref_counted.h"
13#include "base/sequence_token.h"
gabd52c912a2017-05-11 04:15:5914#include "base/test/gtest_util.h"
fdoray59fbfc42016-08-03 01:53:0615#include "base/test/test_simple_task_runner.h"
[email protected]ac9ba8fe2010-12-30 18:08:3616#include "base/threading/simple_thread.h"
fdoray59fbfc42016-08-03 01:53:0617#include "base/threading/thread_task_runner_handle.h"
[email protected]d9ddc962010-08-24 04:29:5618#include "testing/gtest/include/gtest/gtest.h"
19
[email protected]ce072a72010-12-31 20:02:1620namespace base {
[email protected]85588412012-06-27 01:39:5221namespace {
22
fdoray59fbfc42016-08-03 01:53:0623// A thread that runs a callback.
24class RunCallbackThread : public SimpleThread {
[email protected]d9ddc962010-08-24 04:29:5625 public:
fdoray59fbfc42016-08-03 01:53:0626 explicit RunCallbackThread(const Closure& callback)
27 : SimpleThread("RunCallbackThread"), callback_(callback) {}
[email protected]40064482011-03-03 23:38:5128
[email protected]d9ddc962010-08-24 04:29:5629 private:
fdoray59fbfc42016-08-03 01:53:0630 // SimpleThread:
31 void Run() override { callback_.Run(); }
32
33 const Closure callback_;
34
35 DISALLOW_COPY_AND_ASSIGN(RunCallbackThread);
[email protected]d9ddc962010-08-24 04:29:5636};
37
fdoray59fbfc42016-08-03 01:53:0638// Runs a callback on a new thread synchronously.
39void RunCallbackOnNewThreadSynchronously(const Closure& callback) {
40 RunCallbackThread run_callback_thread(callback);
41 run_callback_thread.Start();
42 run_callback_thread.Join();
43}
[email protected]d9ddc962010-08-24 04:29:5644
fdoray59fbfc42016-08-03 01:53:0645void ExpectCalledOnValidThread(ThreadCheckerImpl* thread_checker) {
46 ASSERT_TRUE(thread_checker);
[email protected]d9ddc962010-08-24 04:29:5647
fdoray59fbfc42016-08-03 01:53:0648 // This should bind |thread_checker| to the current thread if it wasn't
49 // already bound to a thread.
50 EXPECT_TRUE(thread_checker->CalledOnValidThread());
[email protected]d9ddc962010-08-24 04:29:5651
fdoray59fbfc42016-08-03 01:53:0652 // Since |thread_checker| is now bound to the current thread, another call to
53 // CalledOnValidThread() should return true.
54 EXPECT_TRUE(thread_checker->CalledOnValidThread());
55}
[email protected]d9ddc962010-08-24 04:29:5656
fdoray59fbfc42016-08-03 01:53:0657void ExpectNotCalledOnValidThread(ThreadCheckerImpl* thread_checker) {
58 ASSERT_TRUE(thread_checker);
59 EXPECT_FALSE(thread_checker->CalledOnValidThread());
60}
[email protected]d9ddc962010-08-24 04:29:5661
fdoray59fbfc42016-08-03 01:53:0662void ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle(
63 ThreadCheckerImpl* thread_checker,
64 SequenceToken sequence_token) {
65 ThreadTaskRunnerHandle thread_task_runner_handle(
kylechar96f3eba2017-09-25 20:23:5666 MakeRefCounted<TestSimpleTaskRunner>());
fdoray59fbfc42016-08-03 01:53:0667 ScopedSetSequenceTokenForCurrentThread
68 scoped_set_sequence_token_for_current_thread(sequence_token);
69 ExpectNotCalledOnValidThread(thread_checker);
70}
[email protected]d9ddc962010-08-24 04:29:5671
[email protected]85588412012-06-27 01:39:5272} // namespace
73
fdorayb339954b2016-08-09 21:49:2674TEST(ThreadCheckerTest, AllowedSameThreadNoSequenceToken) {
fdoray59fbfc42016-08-03 01:53:0675 ThreadCheckerImpl thread_checker;
76 EXPECT_TRUE(thread_checker.CalledOnValidThread());
[email protected]d9ddc962010-08-24 04:29:5677}
78
fdoray59fbfc42016-08-03 01:53:0679TEST(ThreadCheckerTest,
fdorayb339954b2016-08-09 21:49:2680 AllowedSameThreadAndSequenceDifferentTasksWithThreadTaskRunnerHandle) {
fdoray59fbfc42016-08-03 01:53:0681 ThreadTaskRunnerHandle thread_task_runner_handle(
kylechar96f3eba2017-09-25 20:23:5682 MakeRefCounted<TestSimpleTaskRunner>());
fdorayb339954b2016-08-09 21:49:2683
84 std::unique_ptr<ThreadCheckerImpl> thread_checker;
85 const SequenceToken sequence_token = SequenceToken::Create();
86
87 {
88 ScopedSetSequenceTokenForCurrentThread
89 scoped_set_sequence_token_for_current_thread(sequence_token);
90 thread_checker.reset(new ThreadCheckerImpl);
91 }
92
93 {
94 ScopedSetSequenceTokenForCurrentThread
95 scoped_set_sequence_token_for_current_thread(sequence_token);
96 EXPECT_TRUE(thread_checker->CalledOnValidThread());
97 }
98}
99
100TEST(ThreadCheckerTest,
101 AllowedSameThreadSequenceAndTaskNoThreadTaskRunnerHandle) {
fdoray59fbfc42016-08-03 01:53:06102 ScopedSetSequenceTokenForCurrentThread
103 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
104 ThreadCheckerImpl thread_checker;
105 EXPECT_TRUE(thread_checker.CalledOnValidThread());
106}
[email protected]d9ddc962010-08-24 04:29:56107
fdoray59fbfc42016-08-03 01:53:06108TEST(ThreadCheckerTest,
fdorayb339954b2016-08-09 21:49:26109 DisallowedSameThreadAndSequenceDifferentTasksNoThreadTaskRunnerHandle) {
110 std::unique_ptr<ThreadCheckerImpl> thread_checker;
111
112 {
113 ScopedSetSequenceTokenForCurrentThread
114 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
115 thread_checker.reset(new ThreadCheckerImpl);
116 }
117
118 {
119 ScopedSetSequenceTokenForCurrentThread
120 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
121 EXPECT_FALSE(thread_checker->CalledOnValidThread());
122 }
fdoray59fbfc42016-08-03 01:53:06123}
[email protected]d9ddc962010-08-24 04:29:56124
fdorayb339954b2016-08-09 21:49:26125TEST(ThreadCheckerTest, DisallowedDifferentThreadsNoSequenceToken) {
fdoray59fbfc42016-08-03 01:53:06126 ThreadCheckerImpl thread_checker;
127 RunCallbackOnNewThreadSynchronously(
128 Bind(&ExpectNotCalledOnValidThread, Unretained(&thread_checker)));
129}
130
fdorayb339954b2016-08-09 21:49:26131TEST(ThreadCheckerTest, DisallowedDifferentThreadsSameSequence) {
fdoray59fbfc42016-08-03 01:53:06132 ThreadTaskRunnerHandle thread_task_runner_handle(
kylechar96f3eba2017-09-25 20:23:56133 MakeRefCounted<TestSimpleTaskRunner>());
fdoray59fbfc42016-08-03 01:53:06134 const SequenceToken sequence_token(SequenceToken::Create());
135
136 ScopedSetSequenceTokenForCurrentThread
137 scoped_set_sequence_token_for_current_thread(sequence_token);
138 ThreadCheckerImpl thread_checker;
139 EXPECT_TRUE(thread_checker.CalledOnValidThread());
140
141 RunCallbackOnNewThreadSynchronously(Bind(
142 &ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle,
143 Unretained(&thread_checker), sequence_token));
144}
145
fdorayb339954b2016-08-09 21:49:26146TEST(ThreadCheckerTest, DisallowedSameThreadDifferentSequence) {
fdoray59fbfc42016-08-03 01:53:06147 std::unique_ptr<ThreadCheckerImpl> thread_checker;
148
149 ThreadTaskRunnerHandle thread_task_runner_handle(
kylechar96f3eba2017-09-25 20:23:56150 MakeRefCounted<TestSimpleTaskRunner>());
fdoray59fbfc42016-08-03 01:53:06151
152 {
153 ScopedSetSequenceTokenForCurrentThread
154 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
155 thread_checker.reset(new ThreadCheckerImpl);
156 }
157
158 {
159 // Different SequenceToken.
160 ScopedSetSequenceTokenForCurrentThread
161 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
162 EXPECT_FALSE(thread_checker->CalledOnValidThread());
163 }
164
165 // No SequenceToken.
166 EXPECT_FALSE(thread_checker->CalledOnValidThread());
[email protected]d9ddc962010-08-24 04:29:56167}
168
[email protected]8ff672512010-10-07 20:17:33169TEST(ThreadCheckerTest, DetachFromThread) {
fdoray59fbfc42016-08-03 01:53:06170 ThreadCheckerImpl thread_checker;
171 thread_checker.DetachFromThread();
[email protected]8ff672512010-10-07 20:17:33172
fdoray59fbfc42016-08-03 01:53:06173 // Verify that CalledOnValidThread() returns true when called on a different
174 // thread after a call to DetachFromThread().
175 RunCallbackOnNewThreadSynchronously(
176 Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker)));
[email protected]8ff672512010-10-07 20:17:33177
fdoray59fbfc42016-08-03 01:53:06178 EXPECT_FALSE(thread_checker.CalledOnValidThread());
[email protected]8ff672512010-10-07 20:17:33179}
180
fdoray59fbfc42016-08-03 01:53:06181TEST(ThreadCheckerTest, DetachFromThreadWithSequenceToken) {
182 ThreadTaskRunnerHandle thread_task_runner_handle(
kylechar96f3eba2017-09-25 20:23:56183 MakeRefCounted<TestSimpleTaskRunner>());
fdoray59fbfc42016-08-03 01:53:06184 ScopedSetSequenceTokenForCurrentThread
185 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
186 ThreadCheckerImpl thread_checker;
187 thread_checker.DetachFromThread();
[email protected]d9ddc962010-08-24 04:29:56188
fdoray59fbfc42016-08-03 01:53:06189 // Verify that CalledOnValidThread() returns true when called on a different
190 // thread after a call to DetachFromThread().
191 RunCallbackOnNewThreadSynchronously(
192 Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker)));
[email protected]d9ddc962010-08-24 04:29:56193
fdoray59fbfc42016-08-03 01:53:06194 EXPECT_FALSE(thread_checker.CalledOnValidThread());
[email protected]d9ddc962010-08-24 04:29:56195}
196
gabd52c912a2017-05-11 04:15:59197namespace {
198
199// This fixture is a helper for unit testing the thread checker macros as it is
200// not possible to inline ExpectDeathOnOtherThread() and
201// ExpectNoDeathOnOtherThreadAfterDetach() as lambdas since binding
202// |Unretained(&my_sequence_checker)| wouldn't compile on non-dcheck builds
203// where it won't be defined.
204class ThreadCheckerMacroTest : public testing::Test {
205 public:
206 ThreadCheckerMacroTest() = default;
207
208 void ExpectDeathOnOtherThread() {
209#if DCHECK_IS_ON()
210 EXPECT_DCHECK_DEATH({ DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_); });
211#else
212 // Happily no-ops on non-dcheck builds.
213 DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
214#endif
215 }
216
217 void ExpectNoDeathOnOtherThreadAfterDetach() {
218 DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
Olga Sharonovab2c3af622017-11-17 20:48:31219 DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_)
220 << "Make sure it compiles when DCHECK is off";
gabd52c912a2017-05-11 04:15:59221 }
222
223 protected:
224 THREAD_CHECKER(my_thread_checker_);
225
226 private:
227 DISALLOW_COPY_AND_ASSIGN(ThreadCheckerMacroTest);
228};
229
230} // namespace
231
232TEST_F(ThreadCheckerMacroTest, Macros) {
233 THREAD_CHECKER(my_thread_checker);
234
235 RunCallbackOnNewThreadSynchronously(Bind(
236 &ThreadCheckerMacroTest::ExpectDeathOnOtherThread, Unretained(this)));
237
238 DETACH_FROM_THREAD(my_thread_checker_);
239
240 RunCallbackOnNewThreadSynchronously(
241 Bind(&ThreadCheckerMacroTest::ExpectNoDeathOnOtherThreadAfterDetach,
242 Unretained(this)));
243}
244
[email protected]ce072a72010-12-31 20:02:16245} // namespace base