Fix emulator build error
[platform/framework/web/chromium-efl.git] / base / sequence_checker_unittest.cc
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.
4
5 #include "base/sequence_checker.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <string>
11 #include <utility>
12
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"
24
25 namespace base {
26
27 namespace {
28
29 // Runs a callback on another thread.
30 class RunCallbackThread : public SimpleThread {
31  public:
32   explicit RunCallbackThread(OnceClosure callback)
33       : SimpleThread("RunCallbackThread"), callback_(std::move(callback)) {
34     Start();
35     Join();
36   }
37   RunCallbackThread(const RunCallbackThread&) = delete;
38   RunCallbackThread& operator=(const RunCallbackThread&) = delete;
39
40  private:
41   // SimpleThread:
42   void Run() override { std::move(callback_).Run(); }
43
44   OnceClosure callback_;
45 };
46
47 void ExpectCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
48   ASSERT_TRUE(sequence_checker);
49
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());
53
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());
57 }
58
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);
65 }
66
67 void ExpectNotCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
68   ASSERT_TRUE(sequence_checker);
69   EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
70 }
71
72 }  // namespace
73
74 TEST(SequenceCheckerTest, CallsAllowedOnSameThreadNoSequenceToken) {
75   SequenceCheckerImpl sequence_checker;
76   EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
77 }
78
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());
84 }
85
86 TEST(SequenceCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) {
87   SequenceCheckerImpl sequence_checker;
88   RunCallbackThread thread(
89       BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker)));
90 }
91
92 TEST(SequenceCheckerTest, CallsAllowedOnDifferentThreadsSameSequenceToken) {
93   const SequenceToken sequence_token(SequenceToken::Create());
94
95   ScopedSetSequenceTokenForCurrentThread
96       scoped_set_sequence_token_for_current_thread(sequence_token);
97   SequenceCheckerImpl sequence_checker;
98   EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
99
100   RunCallbackThread thread(
101       BindOnce(&ExpectCalledOnValidSequenceWithSequenceToken,
102                Unretained(&sequence_checker), sequence_token));
103 }
104
105 TEST(SequenceCheckerTest, CallsDisallowedOnSameThreadDifferentSequenceToken) {
106   std::unique_ptr<SequenceCheckerImpl> sequence_checker;
107
108   {
109     ScopedSetSequenceTokenForCurrentThread
110         scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
111     sequence_checker = std::make_unique<SequenceCheckerImpl>();
112   }
113
114   {
115     // Different SequenceToken.
116     ScopedSetSequenceTokenForCurrentThread
117         scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
118     EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
119   }
120
121   // No SequenceToken.
122   EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
123 }
124
125 TEST(SequenceCheckerTest, DetachFromSequence) {
126   std::unique_ptr<SequenceCheckerImpl> sequence_checker;
127
128   {
129     ScopedSetSequenceTokenForCurrentThread
130         scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
131     sequence_checker = std::make_unique<SequenceCheckerImpl>();
132   }
133
134   sequence_checker->DetachFromSequence();
135
136   {
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());
142   }
143 }
144
145 TEST(SequenceCheckerTest, DetachFromSequenceNoSequenceToken) {
146   SequenceCheckerImpl sequence_checker;
147   sequence_checker.DetachFromSequence();
148
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)));
153
154   EXPECT_FALSE(sequence_checker.CalledOnValidSequence());
155 }
156
157 TEST(SequenceCheckerTest, Move) {
158   SequenceCheckerImpl initial;
159   EXPECT_TRUE(initial.CalledOnValidSequence());
160
161   SequenceCheckerImpl move_constructed(std::move(initial));
162   EXPECT_TRUE(move_constructed.CalledOnValidSequence());
163
164   SequenceCheckerImpl move_assigned;
165   move_assigned = std::move(move_constructed);
166
167   // The two SequenceCheckerImpls moved from should be able to rebind to another
168   // sequence.
169   RunCallbackThread thread1(
170       BindOnce(&ExpectCalledOnValidSequence, Unretained(&initial)));
171   RunCallbackThread thread2(
172       BindOnce(&ExpectCalledOnValidSequence, Unretained(&move_constructed)));
173
174   // But the latest one shouldn't be able to run on another sequence.
175   RunCallbackThread thread(
176       BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&move_assigned)));
177
178   EXPECT_TRUE(move_assigned.CalledOnValidSequence());
179 }
180
181 TEST(SequenceCheckerTest, MoveAssignIntoDetached) {
182   SequenceCheckerImpl initial;
183
184   SequenceCheckerImpl move_assigned;
185   move_assigned.DetachFromSequence();
186   move_assigned = std::move(initial);
187
188   // |initial| is detached after move.
189   RunCallbackThread thread1(
190       BindOnce(&ExpectCalledOnValidSequence, Unretained(&initial)));
191
192   // |move_assigned| should be associated with the main thread.
193   RunCallbackThread thread2(
194       BindOnce(&ExpectNotCalledOnValidSequence, Unretained(&move_assigned)));
195
196   EXPECT_TRUE(move_assigned.CalledOnValidSequence());
197 }
198
199 TEST(SequenceCheckerTest, MoveFromDetachedRebinds) {
200   SequenceCheckerImpl initial;
201   initial.DetachFromSequence();
202
203   SequenceCheckerImpl moved_into(std::move(initial));
204
205   // |initial| is still detached after move.
206   RunCallbackThread thread1(
207       BindOnce(&ExpectCalledOnValidSequence, Unretained(&initial)));
208
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());
213 }
214
215 TEST(SequenceCheckerTest, MoveOffSequenceBanned) {
216   testing::GTEST_FLAG(death_test_style) = "threadsafe";
217
218   SequenceCheckerImpl other_sequence;
219   other_sequence.DetachFromSequence();
220   RunCallbackThread thread(
221       BindOnce(&ExpectCalledOnValidSequence, Unretained(&other_sequence)));
222
223   EXPECT_DCHECK_DEATH(
224       SequenceCheckerImpl main_sequence(std::move(other_sequence)));
225 }
226
227 TEST(SequenceCheckerMacroTest, Macros) {
228   auto scope = std::make_unique<ScopedSetSequenceTokenForCurrentThread>(
229       SequenceToken::Create());
230   SEQUENCE_CHECKER(my_sequence_checker);
231
232   {
233     // Don't expect a DCHECK death when a SequenceChecker is used on the right
234     // sequence.
235     DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker);
236   }
237   scope.reset();
238
239 #if DCHECK_IS_ON()
240   // Expect DCHECK death when used on a different sequence.
241   EXPECT_DCHECK_DEATH(
242       { DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker); });
243 #else
244     // Happily no-ops on non-dcheck builds.
245   DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker);
246 #endif
247
248   DETACH_FROM_SEQUENCE(my_sequence_checker);
249
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);
253 }
254
255 // Owns a SequenceCheckerImpl, and asserts that CalledOnValidSequence() is valid
256 // in ~SequenceCheckerOwner.
257 class SequenceCheckerOwner {
258  public:
259   SequenceCheckerOwner() = default;
260   SequenceCheckerOwner(const SequenceCheckerOwner&) = delete;
261   SequenceCheckerOwner& operator=(const SequenceCheckerOwner&) = delete;
262   ~SequenceCheckerOwner() { EXPECT_TRUE(checker_.CalledOnValidSequence()); }
263
264  private:
265   SequenceCheckerImpl checker_;
266 };
267
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;
273   {
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>());
279         }));
280     task_runner = nullptr;
281     task_environment.RunUntilIdle();
282   }
283 }
284
285 }  // namespace base