1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/sequence_checker.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <string>
11
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/callback_forward.h"
15 #include "base/macros.h"
16 #include "base/sequence_token.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/test/gtest_util.h"
19 #include "base/threading/simple_thread.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace base {
23
24 namespace {
25
26 // Runs a callback on another thread.
27 class RunCallbackThread : public SimpleThread {
28 public:
RunCallbackThread(const Closure & callback)29 explicit RunCallbackThread(const Closure& callback)
30 : SimpleThread("RunCallbackThread"), callback_(callback) {
31 Start();
32 Join();
33 }
34
35 private:
36 // SimpleThread:
Run()37 void Run() override { callback_.Run(); }
38
39 const Closure callback_;
40
41 DISALLOW_COPY_AND_ASSIGN(RunCallbackThread);
42 };
43
ExpectCalledOnValidSequence(SequenceCheckerImpl * sequence_checker)44 void ExpectCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
45 ASSERT_TRUE(sequence_checker);
46
47 // This should bind |sequence_checker| to the current sequence if it wasn't
48 // already bound to a sequence.
49 EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
50
51 // Since |sequence_checker| is now bound to the current sequence, another call
52 // to CalledOnValidSequence() should return true.
53 EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
54 }
55
ExpectCalledOnValidSequenceWithSequenceToken(SequenceCheckerImpl * sequence_checker,SequenceToken sequence_token)56 void ExpectCalledOnValidSequenceWithSequenceToken(
57 SequenceCheckerImpl* sequence_checker,
58 SequenceToken sequence_token) {
59 ScopedSetSequenceTokenForCurrentThread
60 scoped_set_sequence_token_for_current_thread(sequence_token);
61 ExpectCalledOnValidSequence(sequence_checker);
62 }
63
ExpectNotCalledOnValidSequence(SequenceCheckerImpl * sequence_checker)64 void ExpectNotCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
65 ASSERT_TRUE(sequence_checker);
66 EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
67 }
68
69 } // namespace
70
TEST(SequenceCheckerTest,CallsAllowedOnSameThreadNoSequenceToken)71 TEST(SequenceCheckerTest, CallsAllowedOnSameThreadNoSequenceToken) {
72 SequenceCheckerImpl sequence_checker;
73 EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
74 }
75
TEST(SequenceCheckerTest,CallsAllowedOnSameThreadSameSequenceToken)76 TEST(SequenceCheckerTest, CallsAllowedOnSameThreadSameSequenceToken) {
77 ScopedSetSequenceTokenForCurrentThread
78 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
79 SequenceCheckerImpl sequence_checker;
80 EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
81 }
82
TEST(SequenceCheckerTest,CallsDisallowedOnDifferentThreadsNoSequenceToken)83 TEST(SequenceCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) {
84 SequenceCheckerImpl sequence_checker;
85 RunCallbackThread thread(
86 Bind(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker)));
87 }
88
TEST(SequenceCheckerTest,CallsAllowedOnDifferentThreadsSameSequenceToken)89 TEST(SequenceCheckerTest, CallsAllowedOnDifferentThreadsSameSequenceToken) {
90 const SequenceToken sequence_token(SequenceToken::Create());
91
92 ScopedSetSequenceTokenForCurrentThread
93 scoped_set_sequence_token_for_current_thread(sequence_token);
94 SequenceCheckerImpl sequence_checker;
95 EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
96
97 RunCallbackThread thread(Bind(&ExpectCalledOnValidSequenceWithSequenceToken,
98 Unretained(&sequence_checker), sequence_token));
99 }
100
TEST(SequenceCheckerTest,CallsDisallowedOnSameThreadDifferentSequenceToken)101 TEST(SequenceCheckerTest, CallsDisallowedOnSameThreadDifferentSequenceToken) {
102 std::unique_ptr<SequenceCheckerImpl> sequence_checker;
103
104 {
105 ScopedSetSequenceTokenForCurrentThread
106 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
107 sequence_checker.reset(new SequenceCheckerImpl);
108 }
109
110 {
111 // Different SequenceToken.
112 ScopedSetSequenceTokenForCurrentThread
113 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
114 EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
115 }
116
117 // No SequenceToken.
118 EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
119 }
120
TEST(SequenceCheckerTest,DetachFromSequence)121 TEST(SequenceCheckerTest, DetachFromSequence) {
122 std::unique_ptr<SequenceCheckerImpl> sequence_checker;
123
124 {
125 ScopedSetSequenceTokenForCurrentThread
126 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
127 sequence_checker.reset(new SequenceCheckerImpl);
128 }
129
130 sequence_checker->DetachFromSequence();
131
132 {
133 // Verify that CalledOnValidSequence() returns true when called with
134 // a different sequence token after a call to DetachFromSequence().
135 ScopedSetSequenceTokenForCurrentThread
136 scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
137 EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
138 }
139 }
140
TEST(SequenceCheckerTest,DetachFromSequenceNoSequenceToken)141 TEST(SequenceCheckerTest, DetachFromSequenceNoSequenceToken) {
142 SequenceCheckerImpl sequence_checker;
143 sequence_checker.DetachFromSequence();
144
145 // Verify that CalledOnValidSequence() returns true when called on a
146 // different thread after a call to DetachFromSequence().
147 RunCallbackThread thread(
148 Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)));
149
150 EXPECT_FALSE(sequence_checker.CalledOnValidSequence());
151 }
152
TEST(SequenceCheckerMacroTest,Macros)153 TEST(SequenceCheckerMacroTest, Macros) {
154 auto scope = std::make_unique<ScopedSetSequenceTokenForCurrentThread>(
155 SequenceToken::Create());
156 SEQUENCE_CHECKER(my_sequence_checker);
157
158 // Don't expect a DCHECK death when a SequenceChecker is used on the right
159 // sequence.
160 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
161
162 scope.reset();
163
164 #if DCHECK_IS_ON()
165 // Expect DCHECK death when used on a different sequence.
166 EXPECT_DCHECK_DEATH({
167 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
168 });
169 #else
170 // Happily no-ops on non-dcheck builds.
171 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
172 #endif
173
174 DETACH_FROM_SEQUENCE(my_sequence_checker);
175
176 // Don't expect a DCHECK death when a SequenceChecker is used for the first
177 // time after having been detached.
178 DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
179 }
180
181 } // namespace base
182