Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(578)

Side by Side Diff: base/sequence_checker_unittest.cc

Issue 18231002: base: Change WeakPtr to use SequenceChecker instead of ThreadChecker. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/basictypes.h"
6 #include "base/bind.h"
7 #include "base/bind_helpers.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop.h"
5 #include "base/sequence_checker.h" 13 #include "base/sequence_checker.h"
6 14 #include "base/test/sequenced_worker_pool_owner.h"
7 #include <cstddef> 15 #include "base/threading/simple_thread.h"
8
9 #include "base/compiler_specific.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/test/null_task_runner.h"
12 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
13 17
18 // Duplicated from base/sequence_checker.h so that we can be good citizens
19 // there and undef the macro.
20 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
21 #define ENABLE_SEQUENCE_CHECKER 1
22 #else
23 #define ENABLE_SEQUENCE_CHECKER 0
24 #endif
25
14 namespace base { 26 namespace base {
15 27
16 namespace { 28 namespace {
17 29
18 // Call various methods of SequenceChecker to make sure nothing blows 30 const size_t kNumWorkerThreads = 3;
19 // up in either debug or release mode. 31
20 TEST(SequenceCheckerTest, Basic) { 32 // Simple class to exercise the basics of SequenceChecker.
21 SequenceChecker sequence_checker(new NullTaskRunner()); 33 // Both the destructor and DoStuff should verify that they were
22 sequence_checker.CalledOnValidSequence(); 34 // called on the same thread as the constructor.
23 sequence_checker.ChangeSequence(NULL); 35 class SequenceCheckerClass : public SequenceChecker {
24 sequence_checker.CalledOnValidSequence(); 36 public:
25 } 37 SequenceCheckerClass() {}
38 ~SequenceCheckerClass() {}
39
40 // Verifies that it was called on the same thread as the constructor.
41 void DoStuff() {
42 DCHECK(CalledOnValidSequence());
43 }
44
45 private:
46 DISALLOW_COPY_AND_ASSIGN(SequenceCheckerClass);
47 };
48
49 // Calls ThreadCheckerClass::DoStuff on another thread.
vandebo (ex-Chrome) 2013/06/28 21:00:06 nit: this doesn't do it on a different thread, but
tommycli 2013/06/28 22:37:07 Done.
50 class CallDoStuffOnThread : public base::SimpleThread {
51 public:
52 explicit CallDoStuffOnThread(SequenceCheckerClass* sequence_checker_class)
53 : SimpleThread("call_do_stuff_on_thread"),
54 sequence_checker_class_(sequence_checker_class) {
55 }
56
57 virtual void Run() OVERRIDE {
58 sequence_checker_class_->DoStuff();
59 }
60
61 private:
62 SequenceCheckerClass* sequence_checker_class_;
63
64 DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
65 };
66
67 // Deletes ThreadCheckerClass on a different thread.
68 class DeleteThreadCheckerClassOnThread : public base::SimpleThread {
69 public:
70 explicit DeleteThreadCheckerClassOnThread(
71 SequenceCheckerClass* sequence_checker_class)
72 : SimpleThread("delete_sequence_checker_class_on_thread"),
73 sequence_checker_class_(sequence_checker_class) {
74 }
75
76 virtual void Run() OVERRIDE {
77 sequence_checker_class_.reset();
78 }
79
80 private:
81 scoped_ptr<SequenceCheckerClass> sequence_checker_class_;
vandebo (ex-Chrome) 2013/06/28 21:00:06 nit: why is this one a scope_ptr, but CallDoStuffO
tommycli 2013/06/28 22:37:07 DeleteThreadCheckerClassThread must take possessio
82
83 DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread);
84 };
85
86 class SequenceCheckerTest : public testing::Test {
87 public:
88 SequenceCheckerTest() {
89 ResetPool();
90 }
91
92 virtual ~SequenceCheckerTest() {}
93
94 virtual void SetUp() OVERRIDE {}
95
96 virtual void TearDown() OVERRIDE {
97 pool()->Shutdown();
98 }
99
100 protected:
101 const scoped_refptr<SequencedWorkerPool>& pool() {
102 return pool_owner_->pool();
103 }
104
105 void PostDoStuffToWorkerPool(SequenceCheckerClass* sequence_checker,
106 const std::string& token_name) {
107 pool()->PostNamedSequencedWorkerTask(
108 token_name,
109 FROM_HERE,
110 base::Bind(&SequenceCheckerClass::DoStuff,
111 base::Unretained(sequence_checker)));
112 }
113
114 // Destroys the SequencedWorkerPool instance, blocking until it is fully shut
115 // down, and creates a new instance.
116 void ResetPool() {
117 pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test"));
118 }
119
120 void DifferentSequenceTokensDeathTest();
121 void WorkerPoolAndSimpleThreadDeathTest();
122 void TwoDifferentWorkerPoolsDeathTest();
123
124 private:
125 MessageLoop message_loop_;
126 scoped_ptr<SequencedWorkerPoolOwner> pool_owner_;
127 };
26 128
27 } // namespace 129 } // namespace
28 130
131 TEST(SequenceCheckerNoWorkerPoolTest, CallsAllowedOnSameThread) {
132 scoped_ptr<SequenceCheckerClass> sequence_checker_class(
133 new SequenceCheckerClass);
134
135 // Verify that DoStuff doesn't assert.
136 sequence_checker_class->DoStuff();
137
138 // Verify that the destructor doesn't assert.
139 sequence_checker_class.reset();
140 }
141
142 TEST(SequenceCheckerNoWorkerPoolTest, DestructorAllowedOnDifferentThread) {
143 scoped_ptr<SequenceCheckerClass> sequence_checker_class(
144 new SequenceCheckerClass);
145
146 // Verify that the destructor doesn't assert
147 // when called on a different thread.
148 DeleteThreadCheckerClassOnThread delete_on_thread(
149 sequence_checker_class.release());
150
151 delete_on_thread.Start();
152 delete_on_thread.Join();
153 }
154
155 TEST(SequenceCheckerNoWorkerPoolTest, DetachFromSequence) {
156 scoped_ptr<SequenceCheckerClass> sequence_checker_class(
157 new SequenceCheckerClass);
158
159 // Verify that DoStuff doesn't assert when called on a different thread after
160 // a call to DetachFromSequence.
161 sequence_checker_class->DetachFromSequence();
162 CallDoStuffOnThread call_on_thread(sequence_checker_class.get());
163
164 call_on_thread.Start();
165 call_on_thread.Join();
166 }
167
168 void MethodOnDifferentThreadImpl() {
169 scoped_ptr<SequenceCheckerClass> sequence_checker_class(
170 new SequenceCheckerClass);
171
172 // DoStuff should assert in debug builds only when called on a
173 // different thread.
174 CallDoStuffOnThread call_on_thread(sequence_checker_class.get());
175
176 call_on_thread.Start();
177 call_on_thread.Join();
178 }
179
180 #if GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
181 TEST(SequenceCheckerNoWorkerPoolDeathTest,
182 MethodNotAllowedOnDifferentThreadInDebug) {
183 ASSERT_DEATH({
184 MethodOnDifferentThreadImpl();
185 }, "");
186 }
187 #else
188 TEST(SequenceCheckerNoWorkerPoolTest, MethodAllowedOnDifferentThreadInRelease) {
189 MethodOnDifferentThreadImpl();
190 }
191 #endif // GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
192
193 void DetachThenCallFromDifferentThreadImpl() {
194 scoped_ptr<SequenceCheckerClass> sequence_checker_class(
195 new SequenceCheckerClass);
196
197 // DoStuff doesn't assert when called on a different thread
198 // after a call to DetachFromSequence.
199 sequence_checker_class->DetachFromSequence();
200 CallDoStuffOnThread call_on_thread(sequence_checker_class.get());
201
202 call_on_thread.Start();
203 call_on_thread.Join();
204
205 // DoStuff should assert in debug builds only after moving to
206 // another thread.
207 sequence_checker_class->DoStuff();
208 }
209
210 #if GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
211 TEST(SequenceCheckerNoWorkerPoolDeathTest, DetachFromSequenceInDebug) {
212 ASSERT_DEATH({
213 DetachThenCallFromDifferentThreadImpl();
214 }, "");
215 }
216 #else
217 TEST(SequenceCheckerNoWorkerPoolTest, DetachFromThreadInRelease) {
218 DetachThenCallFromDifferentThreadImpl();
219 }
220 #endif // GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
221
222 TEST_F(SequenceCheckerTest, SameSequenceTokenValid) {
223 SequenceCheckerClass checker;
224
225 checker.DetachFromSequence();
226 PostDoStuffToWorkerPool(&checker, "A");
227 PostDoStuffToWorkerPool(&checker, "A");
228 PostDoStuffToWorkerPool(&checker, "A");
229 PostDoStuffToWorkerPool(&checker, "A");
230 pool()->FlushForTesting();
231 }
232
233 TEST_F(SequenceCheckerTest, DetachSequenceTokenValid) {
234 SequenceCheckerClass checker;
235
236 checker.DetachFromSequence();
237 PostDoStuffToWorkerPool(&checker, "A");
238 PostDoStuffToWorkerPool(&checker, "A");
239 pool()->FlushForTesting();
240
241 checker.DetachFromSequence();
242 PostDoStuffToWorkerPool(&checker, "B");
243 PostDoStuffToWorkerPool(&checker, "B");
244 pool()->FlushForTesting();
245 }
246
247 void SequenceCheckerTest::DifferentSequenceTokensDeathTest() {
248 SequenceCheckerClass checker;
249
250 checker.DetachFromSequence();
251 PostDoStuffToWorkerPool(&checker, "A");
252 PostDoStuffToWorkerPool(&checker, "A");
253 PostDoStuffToWorkerPool(&checker, "B");
254 PostDoStuffToWorkerPool(&checker, "B");
255 pool()->FlushForTesting();
256 }
257
258 #if GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
259 TEST_F(SequenceCheckerTest, DifferentSequenceTokensDeathTestInDebug) {
260 ASSERT_DEATH({
261 DifferentSequenceTokensDeathTest();
262 }, "");
263 }
264 #else
265 TEST(SequenceCheckerNoWorkerPoolTest,
266 DifferentSequenceTokensDeathTestInRelease) {
267 DifferentSequenceTokensDeathTest();
268 }
269 #endif // GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
270
271 void SequenceCheckerTest::WorkerPoolAndSimpleThreadDeathTest() {
272 SequenceCheckerClass checker;
273
274 checker.DetachFromSequence();
275 PostDoStuffToWorkerPool(&checker, "A");
276 PostDoStuffToWorkerPool(&checker, "A");
277 pool()->FlushForTesting();
278
279 CallDoStuffOnThread call_on_thread(&checker);
280 call_on_thread.Start();
281 call_on_thread.Join();
282 }
283
284 #if GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
285 TEST_F(SequenceCheckerTest, WorkerPoolAndSimpleThreadDeathTestInDebug) {
286 ASSERT_DEATH({
287 WorkerPoolAndSimpleThreadDeathTest();
288 }, "");
289 }
290 #else
291 TEST(SequenceCheckerNoWorkerPoolTest,
292 WorkerPoolAndSimpleThreadDeathTestInRelease) {
293 WorkerPoolAndSimpleThreadDeathTest();
294 }
295 #endif // GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
296
297 void SequenceCheckerTest::TwoDifferentWorkerPoolsDeathTest() {
298 SequenceCheckerClass checker;
299
300 checker.DetachFromSequence();
301 PostDoStuffToWorkerPool(&checker, "A");
302 PostDoStuffToWorkerPool(&checker, "A");
303 pool()->FlushForTesting();
304
305 SequencedWorkerPoolOwner second_pool_owner(kNumWorkerThreads, "test2");
306 second_pool_owner.pool()->PostNamedSequencedWorkerTask(
307 "A",
308 FROM_HERE,
309 base::Bind(&SequenceCheckerClass::DoStuff,
310 base::Unretained(&checker)));
311 second_pool_owner.pool()->FlushForTesting();
312 second_pool_owner.pool()->Shutdown();
313 }
314
315 #if GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
316 TEST_F(SequenceCheckerTest, TwoDifferentWorkerPoolsDeathTestInDebug) {
317 ASSERT_DEATH({
318 TwoDifferentWorkerPoolsDeathTest();
319 }, "");
320 }
321 #else
322 TEST(SequenceCheckerNoWorkerPoolTest,
323 TwoDifferentWorkerPoolsDeathTestInRelease) {
324 TwoDifferentWorkerPoolsDeathTest();
325 }
326 #endif // GTEST_HAS_DEATH_TEST && ENABLE_SEQUENCE_CHECKER
327
328 // Just in case we ever get lumped together with other compilation units.
329 #undef ENABLE_SEQUENCE_CHECKER
330
29 } // namespace base 331 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698