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

Side by Side Diff: base/threading/thread_collision_warner_unittest.cc

Issue 1647803004: Move base to DEPS (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 4 years, 10 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
« no previous file with comments | « base/threading/thread_collision_warner.cc ('k') | base/threading/thread_id_name_manager.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/compiler_specific.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/synchronization/lock.h"
8 #include "base/threading/platform_thread.h"
9 #include "base/threading/simple_thread.h"
10 #include "base/threading/thread_collision_warner.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 // '' : local class member function does not have a body
14 MSVC_PUSH_DISABLE_WARNING(4822)
15
16
17 #if defined(NDEBUG)
18
19 // Would cause a memory leak otherwise.
20 #undef DFAKE_MUTEX
21 #define DFAKE_MUTEX(obj) scoped_ptr<base::AsserterBase> obj
22
23 // In Release, we expect the AsserterBase::warn() to not happen.
24 #define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_FALSE
25
26 #else
27
28 // In Debug, we expect the AsserterBase::warn() to happen.
29 #define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_TRUE
30
31 #endif
32
33
34 namespace {
35
36 // This is the asserter used with ThreadCollisionWarner instead of the default
37 // DCheckAsserter. The method fail_state is used to know if a collision took
38 // place.
39 class AssertReporter : public base::AsserterBase {
40 public:
41 AssertReporter()
42 : failed_(false) {}
43
44 void warn() override { failed_ = true; }
45
46 ~AssertReporter() override {}
47
48 bool fail_state() const { return failed_; }
49 void reset() { failed_ = false; }
50
51 private:
52 bool failed_;
53 };
54
55 } // namespace
56
57 TEST(ThreadCollisionTest, BookCriticalSection) {
58 AssertReporter* local_reporter = new AssertReporter();
59
60 base::ThreadCollisionWarner warner(local_reporter);
61 EXPECT_FALSE(local_reporter->fail_state());
62
63 { // Pin section.
64 DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
65 EXPECT_FALSE(local_reporter->fail_state());
66 { // Pin section.
67 DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
68 EXPECT_FALSE(local_reporter->fail_state());
69 }
70 }
71 }
72
73 TEST(ThreadCollisionTest, ScopedRecursiveBookCriticalSection) {
74 AssertReporter* local_reporter = new AssertReporter();
75
76 base::ThreadCollisionWarner warner(local_reporter);
77 EXPECT_FALSE(local_reporter->fail_state());
78
79 { // Pin section.
80 DFAKE_SCOPED_RECURSIVE_LOCK(warner);
81 EXPECT_FALSE(local_reporter->fail_state());
82 { // Pin section again (allowed by DFAKE_SCOPED_RECURSIVE_LOCK)
83 DFAKE_SCOPED_RECURSIVE_LOCK(warner);
84 EXPECT_FALSE(local_reporter->fail_state());
85 } // Unpin section.
86 } // Unpin section.
87
88 // Check that section is not pinned
89 { // Pin section.
90 DFAKE_SCOPED_LOCK(warner);
91 EXPECT_FALSE(local_reporter->fail_state());
92 } // Unpin section.
93 }
94
95 TEST(ThreadCollisionTest, ScopedBookCriticalSection) {
96 AssertReporter* local_reporter = new AssertReporter();
97
98 base::ThreadCollisionWarner warner(local_reporter);
99 EXPECT_FALSE(local_reporter->fail_state());
100
101 { // Pin section.
102 DFAKE_SCOPED_LOCK(warner);
103 EXPECT_FALSE(local_reporter->fail_state());
104 } // Unpin section.
105
106 { // Pin section.
107 DFAKE_SCOPED_LOCK(warner);
108 EXPECT_FALSE(local_reporter->fail_state());
109 {
110 // Pin section again (not allowed by DFAKE_SCOPED_LOCK)
111 DFAKE_SCOPED_LOCK(warner);
112 EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
113 // Reset the status of warner for further tests.
114 local_reporter->reset();
115 } // Unpin section.
116 } // Unpin section.
117
118 {
119 // Pin section.
120 DFAKE_SCOPED_LOCK(warner);
121 EXPECT_FALSE(local_reporter->fail_state());
122 } // Unpin section.
123 }
124
125 TEST(ThreadCollisionTest, MTBookCriticalSectionTest) {
126 class NonThreadSafeQueue {
127 public:
128 explicit NonThreadSafeQueue(base::AsserterBase* asserter)
129 : push_pop_(asserter) {
130 }
131
132 void push(int value) {
133 DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
134 }
135
136 int pop() {
137 DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
138 return 0;
139 }
140
141 private:
142 DFAKE_MUTEX(push_pop_);
143
144 DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
145 };
146
147 class QueueUser : public base::DelegateSimpleThread::Delegate {
148 public:
149 explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {}
150
151 void Run() override {
152 queue_->push(0);
153 queue_->pop();
154 }
155
156 private:
157 NonThreadSafeQueue* queue_;
158 };
159
160 AssertReporter* local_reporter = new AssertReporter();
161
162 NonThreadSafeQueue queue(local_reporter);
163
164 QueueUser queue_user_a(&queue);
165 QueueUser queue_user_b(&queue);
166
167 base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
168 base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
169
170 thread_a.Start();
171 thread_b.Start();
172
173 thread_a.Join();
174 thread_b.Join();
175
176 EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
177 }
178
179 TEST(ThreadCollisionTest, MTScopedBookCriticalSectionTest) {
180 // Queue with a 5 seconds push execution time, hopefuly the two used threads
181 // in the test will enter the push at same time.
182 class NonThreadSafeQueue {
183 public:
184 explicit NonThreadSafeQueue(base::AsserterBase* asserter)
185 : push_pop_(asserter) {
186 }
187
188 void push(int value) {
189 DFAKE_SCOPED_LOCK(push_pop_);
190 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(5));
191 }
192
193 int pop() {
194 DFAKE_SCOPED_LOCK(push_pop_);
195 return 0;
196 }
197
198 private:
199 DFAKE_MUTEX(push_pop_);
200
201 DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
202 };
203
204 class QueueUser : public base::DelegateSimpleThread::Delegate {
205 public:
206 explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {}
207
208 void Run() override {
209 queue_->push(0);
210 queue_->pop();
211 }
212
213 private:
214 NonThreadSafeQueue* queue_;
215 };
216
217 AssertReporter* local_reporter = new AssertReporter();
218
219 NonThreadSafeQueue queue(local_reporter);
220
221 QueueUser queue_user_a(&queue);
222 QueueUser queue_user_b(&queue);
223
224 base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
225 base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
226
227 thread_a.Start();
228 thread_b.Start();
229
230 thread_a.Join();
231 thread_b.Join();
232
233 EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
234 }
235
236 TEST(ThreadCollisionTest, MTSynchedScopedBookCriticalSectionTest) {
237 // Queue with a 2 seconds push execution time, hopefuly the two used threads
238 // in the test will enter the push at same time.
239 class NonThreadSafeQueue {
240 public:
241 explicit NonThreadSafeQueue(base::AsserterBase* asserter)
242 : push_pop_(asserter) {
243 }
244
245 void push(int value) {
246 DFAKE_SCOPED_LOCK(push_pop_);
247 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(2));
248 }
249
250 int pop() {
251 DFAKE_SCOPED_LOCK(push_pop_);
252 return 0;
253 }
254
255 private:
256 DFAKE_MUTEX(push_pop_);
257
258 DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
259 };
260
261 // This time the QueueUser class protects the non thread safe queue with
262 // a lock.
263 class QueueUser : public base::DelegateSimpleThread::Delegate {
264 public:
265 QueueUser(NonThreadSafeQueue* queue, base::Lock* lock)
266 : queue_(queue), lock_(lock) {}
267
268 void Run() override {
269 {
270 base::AutoLock auto_lock(*lock_);
271 queue_->push(0);
272 }
273 {
274 base::AutoLock auto_lock(*lock_);
275 queue_->pop();
276 }
277 }
278 private:
279 NonThreadSafeQueue* queue_;
280 base::Lock* lock_;
281 };
282
283 AssertReporter* local_reporter = new AssertReporter();
284
285 NonThreadSafeQueue queue(local_reporter);
286
287 base::Lock lock;
288
289 QueueUser queue_user_a(&queue, &lock);
290 QueueUser queue_user_b(&queue, &lock);
291
292 base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
293 base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
294
295 thread_a.Start();
296 thread_b.Start();
297
298 thread_a.Join();
299 thread_b.Join();
300
301 EXPECT_FALSE(local_reporter->fail_state());
302 }
303
304 TEST(ThreadCollisionTest, MTSynchedScopedRecursiveBookCriticalSectionTest) {
305 // Queue with a 2 seconds push execution time, hopefuly the two used threads
306 // in the test will enter the push at same time.
307 class NonThreadSafeQueue {
308 public:
309 explicit NonThreadSafeQueue(base::AsserterBase* asserter)
310 : push_pop_(asserter) {
311 }
312
313 void push(int) {
314 DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
315 bar();
316 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(2));
317 }
318
319 int pop() {
320 DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
321 return 0;
322 }
323
324 void bar() {
325 DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
326 }
327
328 private:
329 DFAKE_MUTEX(push_pop_);
330
331 DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
332 };
333
334 // This time the QueueUser class protects the non thread safe queue with
335 // a lock.
336 class QueueUser : public base::DelegateSimpleThread::Delegate {
337 public:
338 QueueUser(NonThreadSafeQueue* queue, base::Lock* lock)
339 : queue_(queue), lock_(lock) {}
340
341 void Run() override {
342 {
343 base::AutoLock auto_lock(*lock_);
344 queue_->push(0);
345 }
346 {
347 base::AutoLock auto_lock(*lock_);
348 queue_->bar();
349 }
350 {
351 base::AutoLock auto_lock(*lock_);
352 queue_->pop();
353 }
354 }
355 private:
356 NonThreadSafeQueue* queue_;
357 base::Lock* lock_;
358 };
359
360 AssertReporter* local_reporter = new AssertReporter();
361
362 NonThreadSafeQueue queue(local_reporter);
363
364 base::Lock lock;
365
366 QueueUser queue_user_a(&queue, &lock);
367 QueueUser queue_user_b(&queue, &lock);
368
369 base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
370 base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
371
372 thread_a.Start();
373 thread_b.Start();
374
375 thread_a.Join();
376 thread_b.Join();
377
378 EXPECT_FALSE(local_reporter->fail_state());
379 }
OLDNEW
« no previous file with comments | « base/threading/thread_collision_warner.cc ('k') | base/threading/thread_id_name_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698