1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_checker.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <memory>
8*635a8641SAndroid Build Coastguard Worker
9*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/bind_helpers.h"
11*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/memory/ref_counted.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/sequence_token.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/test/gtest_util.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/test/test_simple_task_runner.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/threading/simple_thread.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_task_runner_handle.h"
18*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
19*635a8641SAndroid Build Coastguard Worker
20*635a8641SAndroid Build Coastguard Worker namespace base {
21*635a8641SAndroid Build Coastguard Worker namespace {
22*635a8641SAndroid Build Coastguard Worker
23*635a8641SAndroid Build Coastguard Worker // A thread that runs a callback.
24*635a8641SAndroid Build Coastguard Worker class RunCallbackThread : public SimpleThread {
25*635a8641SAndroid Build Coastguard Worker public:
RunCallbackThread(const Closure & callback)26*635a8641SAndroid Build Coastguard Worker explicit RunCallbackThread(const Closure& callback)
27*635a8641SAndroid Build Coastguard Worker : SimpleThread("RunCallbackThread"), callback_(callback) {}
28*635a8641SAndroid Build Coastguard Worker
29*635a8641SAndroid Build Coastguard Worker private:
30*635a8641SAndroid Build Coastguard Worker // SimpleThread:
Run()31*635a8641SAndroid Build Coastguard Worker void Run() override { callback_.Run(); }
32*635a8641SAndroid Build Coastguard Worker
33*635a8641SAndroid Build Coastguard Worker const Closure callback_;
34*635a8641SAndroid Build Coastguard Worker
35*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(RunCallbackThread);
36*635a8641SAndroid Build Coastguard Worker };
37*635a8641SAndroid Build Coastguard Worker
38*635a8641SAndroid Build Coastguard Worker // Runs a callback on a new thread synchronously.
RunCallbackOnNewThreadSynchronously(const Closure & callback)39*635a8641SAndroid Build Coastguard Worker void RunCallbackOnNewThreadSynchronously(const Closure& callback) {
40*635a8641SAndroid Build Coastguard Worker RunCallbackThread run_callback_thread(callback);
41*635a8641SAndroid Build Coastguard Worker run_callback_thread.Start();
42*635a8641SAndroid Build Coastguard Worker run_callback_thread.Join();
43*635a8641SAndroid Build Coastguard Worker }
44*635a8641SAndroid Build Coastguard Worker
ExpectCalledOnValidThread(ThreadCheckerImpl * thread_checker)45*635a8641SAndroid Build Coastguard Worker void ExpectCalledOnValidThread(ThreadCheckerImpl* thread_checker) {
46*635a8641SAndroid Build Coastguard Worker ASSERT_TRUE(thread_checker);
47*635a8641SAndroid Build Coastguard Worker
48*635a8641SAndroid Build Coastguard Worker // This should bind |thread_checker| to the current thread if it wasn't
49*635a8641SAndroid Build Coastguard Worker // already bound to a thread.
50*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(thread_checker->CalledOnValidThread());
51*635a8641SAndroid Build Coastguard Worker
52*635a8641SAndroid Build Coastguard Worker // Since |thread_checker| is now bound to the current thread, another call to
53*635a8641SAndroid Build Coastguard Worker // CalledOnValidThread() should return true.
54*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(thread_checker->CalledOnValidThread());
55*635a8641SAndroid Build Coastguard Worker }
56*635a8641SAndroid Build Coastguard Worker
ExpectNotCalledOnValidThread(ThreadCheckerImpl * thread_checker)57*635a8641SAndroid Build Coastguard Worker void ExpectNotCalledOnValidThread(ThreadCheckerImpl* thread_checker) {
58*635a8641SAndroid Build Coastguard Worker ASSERT_TRUE(thread_checker);
59*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(thread_checker->CalledOnValidThread());
60*635a8641SAndroid Build Coastguard Worker }
61*635a8641SAndroid Build Coastguard Worker
ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle(ThreadCheckerImpl * thread_checker,SequenceToken sequence_token)62*635a8641SAndroid Build Coastguard Worker void ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle(
63*635a8641SAndroid Build Coastguard Worker ThreadCheckerImpl* thread_checker,
64*635a8641SAndroid Build Coastguard Worker SequenceToken sequence_token) {
65*635a8641SAndroid Build Coastguard Worker ThreadTaskRunnerHandle thread_task_runner_handle(
66*635a8641SAndroid Build Coastguard Worker MakeRefCounted<TestSimpleTaskRunner>());
67*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
68*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(sequence_token);
69*635a8641SAndroid Build Coastguard Worker ExpectNotCalledOnValidThread(thread_checker);
70*635a8641SAndroid Build Coastguard Worker }
71*635a8641SAndroid Build Coastguard Worker
72*635a8641SAndroid Build Coastguard Worker } // namespace
73*635a8641SAndroid Build Coastguard Worker
TEST(ThreadCheckerTest,AllowedSameThreadNoSequenceToken)74*635a8641SAndroid Build Coastguard Worker TEST(ThreadCheckerTest, AllowedSameThreadNoSequenceToken) {
75*635a8641SAndroid Build Coastguard Worker ThreadCheckerImpl thread_checker;
76*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(thread_checker.CalledOnValidThread());
77*635a8641SAndroid Build Coastguard Worker }
78*635a8641SAndroid Build Coastguard Worker
TEST(ThreadCheckerTest,AllowedSameThreadAndSequenceDifferentTasksWithThreadTaskRunnerHandle)79*635a8641SAndroid Build Coastguard Worker TEST(ThreadCheckerTest,
80*635a8641SAndroid Build Coastguard Worker AllowedSameThreadAndSequenceDifferentTasksWithThreadTaskRunnerHandle) {
81*635a8641SAndroid Build Coastguard Worker ThreadTaskRunnerHandle thread_task_runner_handle(
82*635a8641SAndroid Build Coastguard Worker MakeRefCounted<TestSimpleTaskRunner>());
83*635a8641SAndroid Build Coastguard Worker
84*635a8641SAndroid Build Coastguard Worker std::unique_ptr<ThreadCheckerImpl> thread_checker;
85*635a8641SAndroid Build Coastguard Worker const SequenceToken sequence_token = SequenceToken::Create();
86*635a8641SAndroid Build Coastguard Worker
87*635a8641SAndroid Build Coastguard Worker {
88*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
89*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(sequence_token);
90*635a8641SAndroid Build Coastguard Worker thread_checker.reset(new ThreadCheckerImpl);
91*635a8641SAndroid Build Coastguard Worker }
92*635a8641SAndroid Build Coastguard Worker
93*635a8641SAndroid Build Coastguard Worker {
94*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
95*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(sequence_token);
96*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(thread_checker->CalledOnValidThread());
97*635a8641SAndroid Build Coastguard Worker }
98*635a8641SAndroid Build Coastguard Worker }
99*635a8641SAndroid Build Coastguard Worker
TEST(ThreadCheckerTest,AllowedSameThreadSequenceAndTaskNoThreadTaskRunnerHandle)100*635a8641SAndroid Build Coastguard Worker TEST(ThreadCheckerTest,
101*635a8641SAndroid Build Coastguard Worker AllowedSameThreadSequenceAndTaskNoThreadTaskRunnerHandle) {
102*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
103*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
104*635a8641SAndroid Build Coastguard Worker ThreadCheckerImpl thread_checker;
105*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(thread_checker.CalledOnValidThread());
106*635a8641SAndroid Build Coastguard Worker }
107*635a8641SAndroid Build Coastguard Worker
TEST(ThreadCheckerTest,DisallowedSameThreadAndSequenceDifferentTasksNoThreadTaskRunnerHandle)108*635a8641SAndroid Build Coastguard Worker TEST(ThreadCheckerTest,
109*635a8641SAndroid Build Coastguard Worker DisallowedSameThreadAndSequenceDifferentTasksNoThreadTaskRunnerHandle) {
110*635a8641SAndroid Build Coastguard Worker std::unique_ptr<ThreadCheckerImpl> thread_checker;
111*635a8641SAndroid Build Coastguard Worker
112*635a8641SAndroid Build Coastguard Worker {
113*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
114*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
115*635a8641SAndroid Build Coastguard Worker thread_checker.reset(new ThreadCheckerImpl);
116*635a8641SAndroid Build Coastguard Worker }
117*635a8641SAndroid Build Coastguard Worker
118*635a8641SAndroid Build Coastguard Worker {
119*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
120*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
121*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(thread_checker->CalledOnValidThread());
122*635a8641SAndroid Build Coastguard Worker }
123*635a8641SAndroid Build Coastguard Worker }
124*635a8641SAndroid Build Coastguard Worker
TEST(ThreadCheckerTest,DisallowedDifferentThreadsNoSequenceToken)125*635a8641SAndroid Build Coastguard Worker TEST(ThreadCheckerTest, DisallowedDifferentThreadsNoSequenceToken) {
126*635a8641SAndroid Build Coastguard Worker ThreadCheckerImpl thread_checker;
127*635a8641SAndroid Build Coastguard Worker RunCallbackOnNewThreadSynchronously(
128*635a8641SAndroid Build Coastguard Worker Bind(&ExpectNotCalledOnValidThread, Unretained(&thread_checker)));
129*635a8641SAndroid Build Coastguard Worker }
130*635a8641SAndroid Build Coastguard Worker
TEST(ThreadCheckerTest,DisallowedDifferentThreadsSameSequence)131*635a8641SAndroid Build Coastguard Worker TEST(ThreadCheckerTest, DisallowedDifferentThreadsSameSequence) {
132*635a8641SAndroid Build Coastguard Worker ThreadTaskRunnerHandle thread_task_runner_handle(
133*635a8641SAndroid Build Coastguard Worker MakeRefCounted<TestSimpleTaskRunner>());
134*635a8641SAndroid Build Coastguard Worker const SequenceToken sequence_token(SequenceToken::Create());
135*635a8641SAndroid Build Coastguard Worker
136*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
137*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(sequence_token);
138*635a8641SAndroid Build Coastguard Worker ThreadCheckerImpl thread_checker;
139*635a8641SAndroid Build Coastguard Worker EXPECT_TRUE(thread_checker.CalledOnValidThread());
140*635a8641SAndroid Build Coastguard Worker
141*635a8641SAndroid Build Coastguard Worker RunCallbackOnNewThreadSynchronously(Bind(
142*635a8641SAndroid Build Coastguard Worker &ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle,
143*635a8641SAndroid Build Coastguard Worker Unretained(&thread_checker), sequence_token));
144*635a8641SAndroid Build Coastguard Worker }
145*635a8641SAndroid Build Coastguard Worker
TEST(ThreadCheckerTest,DisallowedSameThreadDifferentSequence)146*635a8641SAndroid Build Coastguard Worker TEST(ThreadCheckerTest, DisallowedSameThreadDifferentSequence) {
147*635a8641SAndroid Build Coastguard Worker std::unique_ptr<ThreadCheckerImpl> thread_checker;
148*635a8641SAndroid Build Coastguard Worker
149*635a8641SAndroid Build Coastguard Worker ThreadTaskRunnerHandle thread_task_runner_handle(
150*635a8641SAndroid Build Coastguard Worker MakeRefCounted<TestSimpleTaskRunner>());
151*635a8641SAndroid Build Coastguard Worker
152*635a8641SAndroid Build Coastguard Worker {
153*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
154*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
155*635a8641SAndroid Build Coastguard Worker thread_checker.reset(new ThreadCheckerImpl);
156*635a8641SAndroid Build Coastguard Worker }
157*635a8641SAndroid Build Coastguard Worker
158*635a8641SAndroid Build Coastguard Worker {
159*635a8641SAndroid Build Coastguard Worker // Different SequenceToken.
160*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
161*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
162*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(thread_checker->CalledOnValidThread());
163*635a8641SAndroid Build Coastguard Worker }
164*635a8641SAndroid Build Coastguard Worker
165*635a8641SAndroid Build Coastguard Worker // No SequenceToken.
166*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(thread_checker->CalledOnValidThread());
167*635a8641SAndroid Build Coastguard Worker }
168*635a8641SAndroid Build Coastguard Worker
TEST(ThreadCheckerTest,DetachFromThread)169*635a8641SAndroid Build Coastguard Worker TEST(ThreadCheckerTest, DetachFromThread) {
170*635a8641SAndroid Build Coastguard Worker ThreadCheckerImpl thread_checker;
171*635a8641SAndroid Build Coastguard Worker thread_checker.DetachFromThread();
172*635a8641SAndroid Build Coastguard Worker
173*635a8641SAndroid Build Coastguard Worker // Verify that CalledOnValidThread() returns true when called on a different
174*635a8641SAndroid Build Coastguard Worker // thread after a call to DetachFromThread().
175*635a8641SAndroid Build Coastguard Worker RunCallbackOnNewThreadSynchronously(
176*635a8641SAndroid Build Coastguard Worker Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker)));
177*635a8641SAndroid Build Coastguard Worker
178*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(thread_checker.CalledOnValidThread());
179*635a8641SAndroid Build Coastguard Worker }
180*635a8641SAndroid Build Coastguard Worker
TEST(ThreadCheckerTest,DetachFromThreadWithSequenceToken)181*635a8641SAndroid Build Coastguard Worker TEST(ThreadCheckerTest, DetachFromThreadWithSequenceToken) {
182*635a8641SAndroid Build Coastguard Worker ThreadTaskRunnerHandle thread_task_runner_handle(
183*635a8641SAndroid Build Coastguard Worker MakeRefCounted<TestSimpleTaskRunner>());
184*635a8641SAndroid Build Coastguard Worker ScopedSetSequenceTokenForCurrentThread
185*635a8641SAndroid Build Coastguard Worker scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
186*635a8641SAndroid Build Coastguard Worker ThreadCheckerImpl thread_checker;
187*635a8641SAndroid Build Coastguard Worker thread_checker.DetachFromThread();
188*635a8641SAndroid Build Coastguard Worker
189*635a8641SAndroid Build Coastguard Worker // Verify that CalledOnValidThread() returns true when called on a different
190*635a8641SAndroid Build Coastguard Worker // thread after a call to DetachFromThread().
191*635a8641SAndroid Build Coastguard Worker RunCallbackOnNewThreadSynchronously(
192*635a8641SAndroid Build Coastguard Worker Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker)));
193*635a8641SAndroid Build Coastguard Worker
194*635a8641SAndroid Build Coastguard Worker EXPECT_FALSE(thread_checker.CalledOnValidThread());
195*635a8641SAndroid Build Coastguard Worker }
196*635a8641SAndroid Build Coastguard Worker
197*635a8641SAndroid Build Coastguard Worker namespace {
198*635a8641SAndroid Build Coastguard Worker
199*635a8641SAndroid Build Coastguard Worker // This fixture is a helper for unit testing the thread checker macros as it is
200*635a8641SAndroid Build Coastguard Worker // not possible to inline ExpectDeathOnOtherThread() and
201*635a8641SAndroid Build Coastguard Worker // ExpectNoDeathOnOtherThreadAfterDetach() as lambdas since binding
202*635a8641SAndroid Build Coastguard Worker // |Unretained(&my_sequence_checker)| wouldn't compile on non-dcheck builds
203*635a8641SAndroid Build Coastguard Worker // where it won't be defined.
204*635a8641SAndroid Build Coastguard Worker class ThreadCheckerMacroTest : public testing::Test {
205*635a8641SAndroid Build Coastguard Worker public:
206*635a8641SAndroid Build Coastguard Worker ThreadCheckerMacroTest() = default;
207*635a8641SAndroid Build Coastguard Worker
ExpectDeathOnOtherThread()208*635a8641SAndroid Build Coastguard Worker void ExpectDeathOnOtherThread() {
209*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
210*635a8641SAndroid Build Coastguard Worker EXPECT_DCHECK_DEATH({ DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_); });
211*635a8641SAndroid Build Coastguard Worker #else
212*635a8641SAndroid Build Coastguard Worker // Happily no-ops on non-dcheck builds.
213*635a8641SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
214*635a8641SAndroid Build Coastguard Worker #endif
215*635a8641SAndroid Build Coastguard Worker }
216*635a8641SAndroid Build Coastguard Worker
ExpectNoDeathOnOtherThreadAfterDetach()217*635a8641SAndroid Build Coastguard Worker void ExpectNoDeathOnOtherThreadAfterDetach() {
218*635a8641SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
219*635a8641SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_)
220*635a8641SAndroid Build Coastguard Worker << "Make sure it compiles when DCHECK is off";
221*635a8641SAndroid Build Coastguard Worker }
222*635a8641SAndroid Build Coastguard Worker
223*635a8641SAndroid Build Coastguard Worker protected:
224*635a8641SAndroid Build Coastguard Worker THREAD_CHECKER(my_thread_checker_);
225*635a8641SAndroid Build Coastguard Worker
226*635a8641SAndroid Build Coastguard Worker private:
227*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ThreadCheckerMacroTest);
228*635a8641SAndroid Build Coastguard Worker };
229*635a8641SAndroid Build Coastguard Worker
230*635a8641SAndroid Build Coastguard Worker } // namespace
231*635a8641SAndroid Build Coastguard Worker
TEST_F(ThreadCheckerMacroTest,Macros)232*635a8641SAndroid Build Coastguard Worker TEST_F(ThreadCheckerMacroTest, Macros) {
233*635a8641SAndroid Build Coastguard Worker THREAD_CHECKER(my_thread_checker);
234*635a8641SAndroid Build Coastguard Worker
235*635a8641SAndroid Build Coastguard Worker RunCallbackOnNewThreadSynchronously(Bind(
236*635a8641SAndroid Build Coastguard Worker &ThreadCheckerMacroTest::ExpectDeathOnOtherThread, Unretained(this)));
237*635a8641SAndroid Build Coastguard Worker
238*635a8641SAndroid Build Coastguard Worker DETACH_FROM_THREAD(my_thread_checker_);
239*635a8641SAndroid Build Coastguard Worker
240*635a8641SAndroid Build Coastguard Worker RunCallbackOnNewThreadSynchronously(
241*635a8641SAndroid Build Coastguard Worker Bind(&ThreadCheckerMacroTest::ExpectNoDeathOnOtherThreadAfterDetach,
242*635a8641SAndroid Build Coastguard Worker Unretained(this)));
243*635a8641SAndroid Build Coastguard Worker }
244*635a8641SAndroid Build Coastguard Worker
245*635a8641SAndroid Build Coastguard Worker } // namespace base
246