OLD | NEW |
1 // Copyright 2013 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/sequence_checker.h" | 5 #include "base/sequence_checker.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
| 9 #include <memory> |
9 #include <utility> | 10 #include <utility> |
10 | 11 |
11 #include "base/bind.h" | 12 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
13 #include "base/location.h" | 14 #include "base/location.h" |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
15 #include "base/macros.h" | 16 #include "base/macros.h" |
16 #include "base/memory/ref_counted.h" | 17 #include "base/memory/ref_counted.h" |
17 #include "base/memory/scoped_ptr.h" | |
18 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
19 #include "base/test/sequenced_worker_pool_owner.h" | 19 #include "base/test/sequenced_worker_pool_owner.h" |
20 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
22 | 22 |
23 // Duplicated from base/sequence_checker.h so that we can be good citizens | 23 // Duplicated from base/sequence_checker.h so that we can be good citizens |
24 // there and undef the macro. | 24 // there and undef the macro. |
25 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) | 25 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) |
26 #define ENABLE_SEQUENCE_CHECKER 1 | 26 #define ENABLE_SEQUENCE_CHECKER 1 |
27 #else | 27 #else |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 } | 87 } |
88 | 88 |
89 void PostDoStuffToOtherThread( | 89 void PostDoStuffToOtherThread( |
90 SequenceCheckedObject* sequence_checked_object) { | 90 SequenceCheckedObject* sequence_checked_object) { |
91 other_thread()->task_runner()->PostTask( | 91 other_thread()->task_runner()->PostTask( |
92 FROM_HERE, base::Bind(&SequenceCheckedObject::DoStuff, | 92 FROM_HERE, base::Bind(&SequenceCheckedObject::DoStuff, |
93 base::Unretained(sequence_checked_object))); | 93 base::Unretained(sequence_checked_object))); |
94 } | 94 } |
95 | 95 |
96 void PostDeleteToOtherThread( | 96 void PostDeleteToOtherThread( |
97 scoped_ptr<SequenceCheckedObject> sequence_checked_object) { | 97 std::unique_ptr<SequenceCheckedObject> sequence_checked_object) { |
98 other_thread()->message_loop()->DeleteSoon( | 98 other_thread()->message_loop()->DeleteSoon( |
99 FROM_HERE, | 99 FROM_HERE, |
100 sequence_checked_object.release()); | 100 sequence_checked_object.release()); |
101 } | 101 } |
102 | 102 |
103 // Destroys the SequencedWorkerPool instance, blocking until it is fully shut | 103 // Destroys the SequencedWorkerPool instance, blocking until it is fully shut |
104 // down, and creates a new instance. | 104 // down, and creates a new instance. |
105 void ResetPool() { | 105 void ResetPool() { |
106 pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test")); | 106 pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test")); |
107 } | 107 } |
108 | 108 |
109 void MethodOnDifferentThreadDeathTest(); | 109 void MethodOnDifferentThreadDeathTest(); |
110 void DetachThenCallFromDifferentThreadDeathTest(); | 110 void DetachThenCallFromDifferentThreadDeathTest(); |
111 void DifferentSequenceTokensDeathTest(); | 111 void DifferentSequenceTokensDeathTest(); |
112 void WorkerPoolAndSimpleThreadDeathTest(); | 112 void WorkerPoolAndSimpleThreadDeathTest(); |
113 void TwoDifferentWorkerPoolsDeathTest(); | 113 void TwoDifferentWorkerPoolsDeathTest(); |
114 | 114 |
115 private: | 115 private: |
116 MessageLoop message_loop_; // Needed by SequencedWorkerPool to function. | 116 MessageLoop message_loop_; // Needed by SequencedWorkerPool to function. |
117 base::Thread other_thread_; | 117 base::Thread other_thread_; |
118 scoped_ptr<SequencedWorkerPoolOwner> pool_owner_; | 118 std::unique_ptr<SequencedWorkerPoolOwner> pool_owner_; |
119 }; | 119 }; |
120 | 120 |
121 TEST_F(SequenceCheckerTest, CallsAllowedOnSameThread) { | 121 TEST_F(SequenceCheckerTest, CallsAllowedOnSameThread) { |
122 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 122 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
123 new SequenceCheckedObject); | 123 new SequenceCheckedObject); |
124 | 124 |
125 // Verify that DoStuff doesn't assert. | 125 // Verify that DoStuff doesn't assert. |
126 sequence_checked_object->DoStuff(); | 126 sequence_checked_object->DoStuff(); |
127 | 127 |
128 // Verify that the destructor doesn't assert. | 128 // Verify that the destructor doesn't assert. |
129 sequence_checked_object.reset(); | 129 sequence_checked_object.reset(); |
130 } | 130 } |
131 | 131 |
132 TEST_F(SequenceCheckerTest, DestructorAllowedOnDifferentThread) { | 132 TEST_F(SequenceCheckerTest, DestructorAllowedOnDifferentThread) { |
133 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 133 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
134 new SequenceCheckedObject); | 134 new SequenceCheckedObject); |
135 | 135 |
136 // Verify the destructor doesn't assert when called on a different thread. | 136 // Verify the destructor doesn't assert when called on a different thread. |
137 PostDeleteToOtherThread(std::move(sequence_checked_object)); | 137 PostDeleteToOtherThread(std::move(sequence_checked_object)); |
138 other_thread()->Stop(); | 138 other_thread()->Stop(); |
139 } | 139 } |
140 | 140 |
141 TEST_F(SequenceCheckerTest, DetachFromSequence) { | 141 TEST_F(SequenceCheckerTest, DetachFromSequence) { |
142 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 142 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
143 new SequenceCheckedObject); | 143 new SequenceCheckedObject); |
144 | 144 |
145 // Verify that DoStuff doesn't assert when called on a different thread after | 145 // Verify that DoStuff doesn't assert when called on a different thread after |
146 // a call to DetachFromSequence. | 146 // a call to DetachFromSequence. |
147 sequence_checked_object->DetachFromSequence(); | 147 sequence_checked_object->DetachFromSequence(); |
148 | 148 |
149 PostDoStuffToOtherThread(sequence_checked_object.get()); | 149 PostDoStuffToOtherThread(sequence_checked_object.get()); |
150 other_thread()->Stop(); | 150 other_thread()->Stop(); |
151 } | 151 } |
152 | 152 |
153 TEST_F(SequenceCheckerTest, SameSequenceTokenValid) { | 153 TEST_F(SequenceCheckerTest, SameSequenceTokenValid) { |
154 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 154 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
155 new SequenceCheckedObject); | 155 new SequenceCheckedObject); |
156 | 156 |
157 sequence_checked_object->DetachFromSequence(); | 157 sequence_checked_object->DetachFromSequence(); |
158 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 158 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
159 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 159 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
160 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 160 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
161 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 161 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
162 pool()->FlushForTesting(); | 162 pool()->FlushForTesting(); |
163 | 163 |
164 PostDeleteToOtherThread(std::move(sequence_checked_object)); | 164 PostDeleteToOtherThread(std::move(sequence_checked_object)); |
165 other_thread()->Stop(); | 165 other_thread()->Stop(); |
166 } | 166 } |
167 | 167 |
168 TEST_F(SequenceCheckerTest, DetachSequenceTokenValid) { | 168 TEST_F(SequenceCheckerTest, DetachSequenceTokenValid) { |
169 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 169 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
170 new SequenceCheckedObject); | 170 new SequenceCheckedObject); |
171 | 171 |
172 sequence_checked_object->DetachFromSequence(); | 172 sequence_checked_object->DetachFromSequence(); |
173 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 173 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
174 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 174 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
175 pool()->FlushForTesting(); | 175 pool()->FlushForTesting(); |
176 | 176 |
177 sequence_checked_object->DetachFromSequence(); | 177 sequence_checked_object->DetachFromSequence(); |
178 PostDoStuffToWorkerPool(sequence_checked_object.get(), "B"); | 178 PostDoStuffToWorkerPool(sequence_checked_object.get(), "B"); |
179 PostDoStuffToWorkerPool(sequence_checked_object.get(), "B"); | 179 PostDoStuffToWorkerPool(sequence_checked_object.get(), "B"); |
180 pool()->FlushForTesting(); | 180 pool()->FlushForTesting(); |
181 | 181 |
182 PostDeleteToOtherThread(std::move(sequence_checked_object)); | 182 PostDeleteToOtherThread(std::move(sequence_checked_object)); |
183 other_thread()->Stop(); | 183 other_thread()->Stop(); |
184 } | 184 } |
185 | 185 |
186 #if GTEST_HAS_DEATH_TEST || !ENABLE_SEQUENCE_CHECKER | 186 #if GTEST_HAS_DEATH_TEST || !ENABLE_SEQUENCE_CHECKER |
187 | 187 |
188 void SequenceCheckerTest::MethodOnDifferentThreadDeathTest() { | 188 void SequenceCheckerTest::MethodOnDifferentThreadDeathTest() { |
189 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 189 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
190 new SequenceCheckedObject); | 190 new SequenceCheckedObject); |
191 | 191 |
192 // DoStuff should assert in debug builds only when called on a | 192 // DoStuff should assert in debug builds only when called on a |
193 // different thread. | 193 // different thread. |
194 PostDoStuffToOtherThread(sequence_checked_object.get()); | 194 PostDoStuffToOtherThread(sequence_checked_object.get()); |
195 other_thread()->Stop(); | 195 other_thread()->Stop(); |
196 } | 196 } |
197 | 197 |
198 #if ENABLE_SEQUENCE_CHECKER | 198 #if ENABLE_SEQUENCE_CHECKER |
199 TEST_F(SequenceCheckerTest, MethodNotAllowedOnDifferentThreadDeathTestInDebug) { | 199 TEST_F(SequenceCheckerTest, MethodNotAllowedOnDifferentThreadDeathTestInDebug) { |
200 // The default style "fast" does not support multi-threaded tests. | 200 // The default style "fast" does not support multi-threaded tests. |
201 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 201 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
202 ASSERT_DEATH({ | 202 ASSERT_DEATH({ |
203 MethodOnDifferentThreadDeathTest(); | 203 MethodOnDifferentThreadDeathTest(); |
204 }, ""); | 204 }, ""); |
205 } | 205 } |
206 #else | 206 #else |
207 TEST_F(SequenceCheckerTest, MethodAllowedOnDifferentThreadDeathTestInRelease) { | 207 TEST_F(SequenceCheckerTest, MethodAllowedOnDifferentThreadDeathTestInRelease) { |
208 MethodOnDifferentThreadDeathTest(); | 208 MethodOnDifferentThreadDeathTest(); |
209 } | 209 } |
210 #endif // ENABLE_SEQUENCE_CHECKER | 210 #endif // ENABLE_SEQUENCE_CHECKER |
211 | 211 |
212 void SequenceCheckerTest::DetachThenCallFromDifferentThreadDeathTest() { | 212 void SequenceCheckerTest::DetachThenCallFromDifferentThreadDeathTest() { |
213 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 213 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
214 new SequenceCheckedObject); | 214 new SequenceCheckedObject); |
215 | 215 |
216 // DoStuff doesn't assert when called on a different thread | 216 // DoStuff doesn't assert when called on a different thread |
217 // after a call to DetachFromSequence. | 217 // after a call to DetachFromSequence. |
218 sequence_checked_object->DetachFromSequence(); | 218 sequence_checked_object->DetachFromSequence(); |
219 PostDoStuffToOtherThread(sequence_checked_object.get()); | 219 PostDoStuffToOtherThread(sequence_checked_object.get()); |
220 other_thread()->Stop(); | 220 other_thread()->Stop(); |
221 | 221 |
222 // DoStuff should assert in debug builds only after moving to | 222 // DoStuff should assert in debug builds only after moving to |
223 // another thread. | 223 // another thread. |
224 sequence_checked_object->DoStuff(); | 224 sequence_checked_object->DoStuff(); |
225 } | 225 } |
226 | 226 |
227 #if ENABLE_SEQUENCE_CHECKER | 227 #if ENABLE_SEQUENCE_CHECKER |
228 TEST_F(SequenceCheckerTest, DetachFromSequenceDeathTestInDebug) { | 228 TEST_F(SequenceCheckerTest, DetachFromSequenceDeathTestInDebug) { |
229 // The default style "fast" does not support multi-threaded tests. | 229 // The default style "fast" does not support multi-threaded tests. |
230 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 230 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
231 ASSERT_DEATH({ | 231 ASSERT_DEATH({ |
232 DetachThenCallFromDifferentThreadDeathTest(); | 232 DetachThenCallFromDifferentThreadDeathTest(); |
233 }, ""); | 233 }, ""); |
234 } | 234 } |
235 #else | 235 #else |
236 TEST_F(SequenceCheckerTest, DetachFromThreadDeathTestInRelease) { | 236 TEST_F(SequenceCheckerTest, DetachFromThreadDeathTestInRelease) { |
237 DetachThenCallFromDifferentThreadDeathTest(); | 237 DetachThenCallFromDifferentThreadDeathTest(); |
238 } | 238 } |
239 #endif // ENABLE_SEQUENCE_CHECKER | 239 #endif // ENABLE_SEQUENCE_CHECKER |
240 | 240 |
241 void SequenceCheckerTest::DifferentSequenceTokensDeathTest() { | 241 void SequenceCheckerTest::DifferentSequenceTokensDeathTest() { |
242 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 242 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
243 new SequenceCheckedObject); | 243 new SequenceCheckedObject); |
244 | 244 |
245 sequence_checked_object->DetachFromSequence(); | 245 sequence_checked_object->DetachFromSequence(); |
246 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 246 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
247 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 247 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
248 PostDoStuffToWorkerPool(sequence_checked_object.get(), "B"); | 248 PostDoStuffToWorkerPool(sequence_checked_object.get(), "B"); |
249 PostDoStuffToWorkerPool(sequence_checked_object.get(), "B"); | 249 PostDoStuffToWorkerPool(sequence_checked_object.get(), "B"); |
250 pool()->FlushForTesting(); | 250 pool()->FlushForTesting(); |
251 | 251 |
252 PostDeleteToOtherThread(std::move(sequence_checked_object)); | 252 PostDeleteToOtherThread(std::move(sequence_checked_object)); |
253 other_thread()->Stop(); | 253 other_thread()->Stop(); |
254 } | 254 } |
255 | 255 |
256 #if ENABLE_SEQUENCE_CHECKER | 256 #if ENABLE_SEQUENCE_CHECKER |
257 TEST_F(SequenceCheckerTest, DifferentSequenceTokensDeathTestInDebug) { | 257 TEST_F(SequenceCheckerTest, DifferentSequenceTokensDeathTestInDebug) { |
258 // The default style "fast" does not support multi-threaded tests. | 258 // The default style "fast" does not support multi-threaded tests. |
259 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 259 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
260 ASSERT_DEATH({ | 260 ASSERT_DEATH({ |
261 DifferentSequenceTokensDeathTest(); | 261 DifferentSequenceTokensDeathTest(); |
262 }, ""); | 262 }, ""); |
263 } | 263 } |
264 #else | 264 #else |
265 TEST_F(SequenceCheckerTest, DifferentSequenceTokensDeathTestInRelease) { | 265 TEST_F(SequenceCheckerTest, DifferentSequenceTokensDeathTestInRelease) { |
266 DifferentSequenceTokensDeathTest(); | 266 DifferentSequenceTokensDeathTest(); |
267 } | 267 } |
268 #endif // ENABLE_SEQUENCE_CHECKER | 268 #endif // ENABLE_SEQUENCE_CHECKER |
269 | 269 |
270 void SequenceCheckerTest::WorkerPoolAndSimpleThreadDeathTest() { | 270 void SequenceCheckerTest::WorkerPoolAndSimpleThreadDeathTest() { |
271 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 271 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
272 new SequenceCheckedObject); | 272 new SequenceCheckedObject); |
273 | 273 |
274 sequence_checked_object->DetachFromSequence(); | 274 sequence_checked_object->DetachFromSequence(); |
275 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 275 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
276 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 276 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
277 pool()->FlushForTesting(); | 277 pool()->FlushForTesting(); |
278 | 278 |
279 PostDoStuffToOtherThread(sequence_checked_object.get()); | 279 PostDoStuffToOtherThread(sequence_checked_object.get()); |
280 other_thread()->Stop(); | 280 other_thread()->Stop(); |
281 } | 281 } |
282 | 282 |
283 #if ENABLE_SEQUENCE_CHECKER | 283 #if ENABLE_SEQUENCE_CHECKER |
284 TEST_F(SequenceCheckerTest, WorkerPoolAndSimpleThreadDeathTestInDebug) { | 284 TEST_F(SequenceCheckerTest, WorkerPoolAndSimpleThreadDeathTestInDebug) { |
285 // The default style "fast" does not support multi-threaded tests. | 285 // The default style "fast" does not support multi-threaded tests. |
286 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 286 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
287 ASSERT_DEATH({ | 287 ASSERT_DEATH({ |
288 WorkerPoolAndSimpleThreadDeathTest(); | 288 WorkerPoolAndSimpleThreadDeathTest(); |
289 }, ""); | 289 }, ""); |
290 } | 290 } |
291 #else | 291 #else |
292 TEST_F(SequenceCheckerTest, WorkerPoolAndSimpleThreadDeathTestInRelease) { | 292 TEST_F(SequenceCheckerTest, WorkerPoolAndSimpleThreadDeathTestInRelease) { |
293 WorkerPoolAndSimpleThreadDeathTest(); | 293 WorkerPoolAndSimpleThreadDeathTest(); |
294 } | 294 } |
295 #endif // ENABLE_SEQUENCE_CHECKER | 295 #endif // ENABLE_SEQUENCE_CHECKER |
296 | 296 |
297 void SequenceCheckerTest::TwoDifferentWorkerPoolsDeathTest() { | 297 void SequenceCheckerTest::TwoDifferentWorkerPoolsDeathTest() { |
298 scoped_ptr<SequenceCheckedObject> sequence_checked_object( | 298 std::unique_ptr<SequenceCheckedObject> sequence_checked_object( |
299 new SequenceCheckedObject); | 299 new SequenceCheckedObject); |
300 | 300 |
301 sequence_checked_object->DetachFromSequence(); | 301 sequence_checked_object->DetachFromSequence(); |
302 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 302 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
303 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); | 303 PostDoStuffToWorkerPool(sequence_checked_object.get(), "A"); |
304 pool()->FlushForTesting(); | 304 pool()->FlushForTesting(); |
305 | 305 |
306 SequencedWorkerPoolOwner second_pool_owner(kNumWorkerThreads, "test2"); | 306 SequencedWorkerPoolOwner second_pool_owner(kNumWorkerThreads, "test2"); |
307 second_pool_owner.pool()->PostNamedSequencedWorkerTask( | 307 second_pool_owner.pool()->PostNamedSequencedWorkerTask( |
308 "A", | 308 "A", |
(...skipping 18 matching lines...) Expand all Loading... |
327 #endif // ENABLE_SEQUENCE_CHECKER | 327 #endif // ENABLE_SEQUENCE_CHECKER |
328 | 328 |
329 #endif // GTEST_HAS_DEATH_TEST || !ENABLE_SEQUENCE_CHECKER | 329 #endif // GTEST_HAS_DEATH_TEST || !ENABLE_SEQUENCE_CHECKER |
330 | 330 |
331 } // namespace | 331 } // namespace |
332 | 332 |
333 } // namespace base | 333 } // namespace base |
334 | 334 |
335 // Just in case we ever get lumped together with other compilation units. | 335 // Just in case we ever get lumped together with other compilation units. |
336 #undef ENABLE_SEQUENCE_CHECKER | 336 #undef ENABLE_SEQUENCE_CHECKER |
OLD | NEW |