1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/sequence_checker.h"
13 #include "base/functional/bind.h"
14 #include "base/functional/callback_helpers.h"
15 #include "base/sequence_token.h"
16 #include "base/task/single_thread_task_runner.h"
17 #include "base/task/thread_pool.h"
18 #include "base/test/bind.h"
19 #include "base/test/gtest_util.h"
20 #include "base/test/task_environment.h"
21 #include "base/threading/simple_thread.h"
22 #include "base/threading/thread_local.h"
23 #include "testing/gtest/include/gtest/gtest.h"
29 // Runs a callback on another thread.
30 class RunCallbackThread : public SimpleThread {
32 explicit RunCallbackThread(OnceClosure callback)
33 : SimpleThread("RunCallbackThread"), callback_(std::move(callback)) {
37 RunCallbackThread(const RunCallbackThread&) = delete;
38 RunCallbackThread& operator=(const RunCallbackThread&) = delete;
42 void Run() override { std::move(callback_).Run(); }
44 OnceClosure callback_;
47 void ExpectCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
48 ASSERT_TRUE(sequence_checker);
50 // This should bind |sequence_checker| to the current sequence if it wasn't
51 // already bound to a sequence.
52 EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
54 // Since |sequence_checker| is now bound to the current sequence, another call
55 // to CalledOnValidSequence() should return true.
56 EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
59 void ExpectCalledOnValidSequenceWithSequenceToken(
60 SequenceCheckerImpl* sequence_checker,
61 SequenceToken sequence_token) {
62 ScopedSetSequenceTokenForCurrentThread
63 scoped_set_sequence_token_for_current_thread(sequence_token);
64 ExpectCalledOnValidSequence(sequence_checker);
67 void ExpectNotCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
68 ASSERT_TRUE(sequence_checker);
69 EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
74 TEST(SequenceCheckerTest, CallsAllowedOnSameThreadNoSequenceToken) {
75 SequenceCheckerImpl sequence_checker;
76 EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
79 TEST(SequenceCheckerTest, CallsAllowedOnSameThreadSameSequenceToken) {
80 ScopedSetSequenceTokenForCurrentThread
81 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
82 SequenceCheckerImpl sequence_checker;
83 EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
86 TEST(SequenceCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) {
87 SequenceCheckerImpl sequence_checker;
88 RunCallbackThread thread(
89 BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker)));
92 TEST(SequenceCheckerTest, CallsAllowedOnDifferentThreadsSameSequenceToken) {
93 const SequenceToken sequence_token(SequenceToken::Create());
95 ScopedSetSequenceTokenForCurrentThread
96 scoped_set_sequence_token_for_current_thread(sequence_token);
97 SequenceCheckerImpl sequence_checker;
98 EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
100 RunCallbackThread thread(
101 BindOnce(&ExpectCalledOnValidSequenceWithSequenceToken,
102 Unretained(&sequence_checker), sequence_token));
105 TEST(SequenceCheckerTest, CallsDisallowedOnSameThreadDifferentSequenceToken) {
106 std::unique_ptr<SequenceCheckerImpl> sequence_checker;
109 ScopedSetSequenceTokenForCurrentThread
110 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
111 sequence_checker = std::make_unique<SequenceCheckerImpl>();
115 // Different SequenceToken.
116 ScopedSetSequenceTokenForCurrentThread
117 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
118 EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
122 EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
125 TEST(SequenceCheckerTest, DetachFromSequence) {
126 std::unique_ptr<SequenceCheckerImpl> sequence_checker;
129 ScopedSetSequenceTokenForCurrentThread
130 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
131 sequence_checker = std::make_unique<SequenceCheckerImpl>();
134 sequence_checker->DetachFromSequence();
137 // Verify that CalledOnValidSequence() returns true when called with
138 // a different sequence token after a call to DetachFromSequence().
139 ScopedSetSequenceTokenForCurrentThread
140 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
141 EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
145 TEST(SequenceCheckerTest, DetachFromSequenceNoSequenceToken) {
146 SequenceCheckerImpl sequence_checker;
147 sequence_checker.DetachFromSequence();
149 // Verify that CalledOnValidSequence() returns true when called on a
150 // different thread after a call to DetachFromSequence().
151 RunCallbackThread thread(
152 BindOnce(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)));
154 EXPECT_FALSE(sequence_checker.CalledOnValidSequence());
157 TEST(SequenceCheckerTest, Move) {
158 SequenceCheckerImpl initial;
159 EXPECT_TRUE(initial.CalledOnValidSequence());
161 SequenceCheckerImpl move_constructed(std::move(initial));
162 EXPECT_TRUE(move_constructed.CalledOnValidSequence());
164 SequenceCheckerImpl move_assigned;
165 move_assigned = std::move(move_constructed);
167 // The two SequenceCheckerImpls moved from should be able to rebind to another
169 RunCallbackThread thread1(
170 BindOnce(&ExpectCalledOnValidSequence, Unretained(&initial)));
171 RunCallbackThread thread2(
172 BindOnce(&ExpectCalledOnValidSequence, Unretained(&move_constructed)));
174 // But the latest one shouldn't be able to run on another sequence.
175 RunCallbackThread thread(
176 BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&move_assigned)));
178 EXPECT_TRUE(move_assigned.CalledOnValidSequence());
181 TEST(SequenceCheckerTest, MoveAssignIntoDetached) {
182 SequenceCheckerImpl initial;
184 SequenceCheckerImpl move_assigned;
185 move_assigned.DetachFromSequence();
186 move_assigned = std::move(initial);
188 // |initial| is detached after move.
189 RunCallbackThread thread1(
190 BindOnce(&ExpectCalledOnValidSequence, Unretained(&initial)));
192 // |move_assigned| should be associated with the main thread.
193 RunCallbackThread thread2(
194 BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&move_assigned)));
196 EXPECT_TRUE(move_assigned.CalledOnValidSequence());
199 TEST(SequenceCheckerTest, MoveFromDetachedRebinds) {
200 SequenceCheckerImpl initial;
201 initial.DetachFromSequence();
203 SequenceCheckerImpl moved_into(std::move(initial));
205 // |initial| is still detached after move.
206 RunCallbackThread thread1(
207 BindOnce(&ExpectCalledOnValidSequence, Unretained(&initial)));
209 // |moved_into| is bound to the current sequence as part of the move.
210 RunCallbackThread thread2(
211 BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&moved_into)));
212 EXPECT_TRUE(moved_into.CalledOnValidSequence());
215 TEST(SequenceCheckerTest, MoveOffSequenceBanned) {
216 testing::GTEST_FLAG(death_test_style) = "threadsafe";
218 SequenceCheckerImpl other_sequence;
219 other_sequence.DetachFromSequence();
220 RunCallbackThread thread(
221 BindOnce(&ExpectCalledOnValidSequence, Unretained(&other_sequence)));
224 SequenceCheckerImpl main_sequence(std::move(other_sequence)));
227 TEST(SequenceCheckerMacroTest, Macros) {
228 auto scope = std::make_unique<ScopedSetSequenceTokenForCurrentThread>(
229 SequenceToken::Create());
230 SEQUENCE_CHECKER(my_sequence_checker);
233 // Don't expect a DCHECK death when a SequenceChecker is used on the right
235 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker);
240 // Expect DCHECK death when used on a different sequence.
242 { DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker); });
244 // Happily no-ops on non-dcheck builds.
245 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker);
248 DETACH_FROM_SEQUENCE(my_sequence_checker);
250 // Don't expect a DCHECK death when a SequenceChecker is used for the first
251 // time after having been detached.
252 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker);
255 // Owns a SequenceCheckerImpl, and asserts that CalledOnValidSequence() is valid
256 // in ~SequenceCheckerOwner.
257 class SequenceCheckerOwner {
259 SequenceCheckerOwner() = default;
260 SequenceCheckerOwner(const SequenceCheckerOwner&) = delete;
261 SequenceCheckerOwner& operator=(const SequenceCheckerOwner&) = delete;
262 ~SequenceCheckerOwner() { EXPECT_TRUE(checker_.CalledOnValidSequence()); }
265 SequenceCheckerImpl checker_;
268 // Verifies SequenceCheckerImpl::CalledOnValidSequence() returns true if called
269 // during thread destruction.
270 TEST(SequenceCheckerTest, CalledOnValidSequenceFromThreadDestruction) {
271 SequenceChecker::EnableStackLogging();
272 ThreadLocalOwnedPointer<SequenceCheckerOwner> thread_local_owner;
274 test::TaskEnvironment task_environment;
275 auto task_runner = ThreadPool::CreateSequencedTaskRunner({});
276 task_runner->PostTask(
277 FROM_HERE, BindLambdaForTesting([&]() {
278 thread_local_owner.Set(std::make_unique<SequenceCheckerOwner>());
280 task_runner = nullptr;
281 task_environment.RunUntilIdle();