xref: /aosp_15_r20/external/libchrome/base/threading/thread_checker_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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