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

Side by Side Diff: base/task_scheduler/scheduler_lock_unittest.cc

Issue 1706123002: TaskScheduler [2/9] Scheduler Lock (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Check GTEST_HAS_DEATH_TEST and Disable Death Tests on Android Created 4 years, 9 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
(Empty)
1 // Copyright 2016 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/task_scheduler/scheduler_lock.h"
6
7 #include <stdlib.h>
8
9 #include "base/compiler_specific.h"
10 #include "base/macros.h"
11 #include "base/rand_util.h"
12 #include "base/synchronization/waitable_event.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/threading/simple_thread.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace base {
18 namespace internal {
19 namespace {
20
21 // Death tests misbehave on Android.
22 #if DCHECK_IS_ON() && defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
23 #define EXPECT_DCHECK_DEATH(statement, regex) EXPECT_DEATH(statement, regex)
24 #else
25 #define EXPECT_DCHECK_DEATH(statement, regex)
gab 2016/03/14 18:26:04 Shouldn't this be #define EXPECT_DCHECK_DEATH(sta
fdoray 2016/03/14 18:55:52 Note that on Posix, the |statement| of EXPECT_DCHE
robliao 2016/03/14 19:09:52 The way we've structured the tests, we expect deat
gab 2016/03/14 19:51:13 Ok, re-lgtm. PS: Would be nice to confirm that tr
robliao 2016/03/14 19:55:41 From the tests so far, the mobile ones at least do
gab 2016/03/14 20:02:52 I seem to recall a surprising episode on chromium-
robliao 2016/03/14 20:25:07 Sounds good. Feel free to monitor https://coderevi
robliao 2016/03/14 20:37:13 And the fireworks have started (tests going red),
26 #endif
27
28 // Adapted from base::Lock's BasicLockTestThread to make sure
29 // Acquire()/Release() don't crash.
30 class BasicLockTestThread : public SimpleThread {
31 public:
32 explicit BasicLockTestThread(SchedulerLock* lock)
33 : SimpleThread("BasicLockTestThread"),
34 lock_(lock),
35 acquired_(0) {}
36
37 int acquired() const { return acquired_; }
38
39 private:
40 void Run() override {
41 for (int i = 0; i < 10; i++) {
42 lock_->Acquire();
43 acquired_++;
44 lock_->Release();
45 }
46 for (int i = 0; i < 10; i++) {
47 lock_->Acquire();
48 acquired_++;
49 PlatformThread::Sleep(TimeDelta::FromMilliseconds(base::RandInt(0, 19)));
50 lock_->Release();
51 }
52 }
53
54 SchedulerLock* const lock_;
55 int acquired_;
56
57 DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread);
58 };
59
60 class BasicLockAcquireAndWaitThread : public SimpleThread {
61 public:
62 explicit BasicLockAcquireAndWaitThread(SchedulerLock* lock)
63 : SimpleThread("BasicLockAcquireAndWaitThread"),
64 lock_(lock),
65 lock_acquire_event_(false, false),
66 main_thread_continue_event_(false, false) {}
67
68 void WaitForLockAcquisition() {
69 lock_acquire_event_.Wait();
70 }
71
72 void ContinueMain() {
73 main_thread_continue_event_.Signal();
74 }
75
76 private:
77 void Run() override {
78 lock_->Acquire();
79 lock_acquire_event_.Signal();
80 main_thread_continue_event_.Wait();
81 lock_->Release();
82 }
83
84 SchedulerLock* const lock_;
85 WaitableEvent lock_acquire_event_;
86 WaitableEvent main_thread_continue_event_;
87
88 DISALLOW_COPY_AND_ASSIGN(BasicLockAcquireAndWaitThread);
89 };
90
91 TEST(TaskSchedulerLock, Basic) {
92 SchedulerLock lock;
93 BasicLockTestThread thread(&lock);
94
95 thread.Start();
96
97 int acquired = 0;
98 for (int i = 0; i < 5; i++) {
99 lock.Acquire();
100 acquired++;
101 lock.Release();
102 }
103 for (int i = 0; i < 10; i++) {
104 lock.Acquire();
105 acquired++;
106 PlatformThread::Sleep(TimeDelta::FromMilliseconds(base::RandInt(0, 19)));
107 lock.Release();
108 }
109 for (int i = 0; i < 5; i++) {
110 lock.Acquire();
111 acquired++;
112 PlatformThread::Sleep(TimeDelta::FromMilliseconds(base::RandInt(0, 19)));
113 lock.Release();
114 }
115
116 thread.Join();
117
118 EXPECT_EQ(acquired, 20);
119 EXPECT_EQ(thread.acquired(), 20);
120 }
121
122 TEST(TaskSchedulerLock, AcquirePredecessor) {
123 SchedulerLock predecessor;
124 SchedulerLock lock(&predecessor);
125 predecessor.Acquire();
126 lock.Acquire();
127 lock.Release();
128 predecessor.Release();
129 }
130
131 TEST(TaskSchedulerLock, AcquirePredecessorWrongOrder) {
132 SchedulerLock predecessor;
133 SchedulerLock lock(&predecessor);
134 EXPECT_DCHECK_DEATH({
135 lock.Acquire();
136 predecessor.Acquire();
137 }, "");
138 }
139
140 TEST(TaskSchedulerLock, AcquireNonPredecessor) {
141 SchedulerLock lock1;
142 SchedulerLock lock2;
143 EXPECT_DCHECK_DEATH({
144 lock1.Acquire();
145 lock2.Acquire();
146 }, "");
147 }
148
149 TEST(TaskSchedulerLock, AcquireMultipleLocksInOrder) {
150 SchedulerLock lock1;
151 SchedulerLock lock2(&lock1);
152 SchedulerLock lock3(&lock2);
153 lock1.Acquire();
154 lock2.Acquire();
155 lock3.Acquire();
156 lock3.Release();
157 lock2.Release();
158 lock1.Release();
159 }
160
161 TEST(TaskSchedulerLock, AcquireMultipleLocksInTheMiddleOfAChain) {
162 SchedulerLock lock1;
163 SchedulerLock lock2(&lock1);
164 SchedulerLock lock3(&lock2);
165 lock2.Acquire();
166 lock3.Acquire();
167 lock3.Release();
168 lock2.Release();
169 }
170
171 TEST(TaskSchedulerLock, AcquireMultipleLocksNoTransitivity) {
172 SchedulerLock lock1;
173 SchedulerLock lock2(&lock1);
174 SchedulerLock lock3(&lock2);
175 EXPECT_DCHECK_DEATH({
176 lock1.Acquire();
177 lock3.Acquire();
178 }, "");
179 }
180
181 TEST(TaskSchedulerLock, AcquireLocksDifferentThreadsSafely) {
182 SchedulerLock lock1;
183 SchedulerLock lock2;
184 BasicLockAcquireAndWaitThread thread(&lock1);
185 thread.Start();
186
187 lock2.Acquire();
188 thread.WaitForLockAcquisition();
189 thread.ContinueMain();
190 thread.Join();
191 lock2.Release();
192 }
193
194 TEST(TaskSchedulerLock,
195 AcquireLocksWithPredecessorDifferentThreadsSafelyPredecessorFirst) {
196 // A lock and its predecessor may be safely acquired on different threads.
197 // This Thread Other Thread
198 // predecessor.Acquire()
199 // lock.Acquire()
200 // predecessor.Release()
201 // lock.Release()
202 SchedulerLock predecessor;
203 SchedulerLock lock(&predecessor);
204 predecessor.Acquire();
205 BasicLockAcquireAndWaitThread thread(&lock);
206 thread.Start();
207 thread.WaitForLockAcquisition();
208 predecessor.Release();
209 thread.ContinueMain();
210 thread.Join();
211 }
212
213 TEST(TaskSchedulerLock,
214 AcquireLocksWithPredecessorDifferentThreadsSafelyPredecessorLast) {
215 // A lock and its predecessor may be safely acquired on different threads.
216 // This Thread Other Thread
217 // lock.Acquire()
218 // predecessor.Acquire()
219 // lock.Release()
220 // predecessor.Release()
221 SchedulerLock predecessor;
222 SchedulerLock lock(&predecessor);
223 lock.Acquire();
224 BasicLockAcquireAndWaitThread thread(&predecessor);
225 thread.Start();
226 thread.WaitForLockAcquisition();
227 lock.Release();
228 thread.ContinueMain();
229 thread.Join();
230 }
231
232 TEST(TaskSchedulerLock,
233 AcquireLocksWithPredecessorDifferentThreadsSafelyNoInterference) {
234 // Acquisition of an unrelated lock on another thread should not affect a
235 // legal lock acquisition with a predecessor on this thread.
236 // This Thread Other Thread
237 // predecessor.Acquire()
238 // unrelated.Acquire()
239 // lock.Acquire()
240 // unrelated.Release()
241 // lock.Release()
242 // predecessor.Release();
243 SchedulerLock predecessor;
244 SchedulerLock lock(&predecessor);
245 predecessor.Acquire();
246 SchedulerLock unrelated;
247 BasicLockAcquireAndWaitThread thread(&unrelated);
248 thread.Start();
249 thread.WaitForLockAcquisition();
250 lock.Acquire();
251 thread.ContinueMain();
252 thread.Join();
253 lock.Release();
254 predecessor.Release();
255 }
256
257 TEST(TaskSchedulerLock, SelfReferentialLock) {
258 struct SelfReferentialLock {
259 SelfReferentialLock() : lock(&lock) {}
260
261 SchedulerLock lock;
262 };
263
264 EXPECT_DCHECK_DEATH({ SelfReferentialLock lock; }, "");
265 }
266
267 TEST(TaskSchedulerLock, PredecessorCycle) {
268 struct LockCycle {
269 LockCycle() : lock1(&lock2), lock2(&lock1) {}
270
271 SchedulerLock lock1;
272 SchedulerLock lock2;
273 };
274
275 EXPECT_DCHECK_DEATH({ LockCycle cycle; }, "");
276 }
277
278 TEST(TaskSchedulerLock, PredecessorLongerCycle) {
279 struct LockCycle {
280 LockCycle()
281 : lock1(&lock5),
282 lock2(&lock1),
283 lock3(&lock2),
284 lock4(&lock3),
285 lock5(&lock4) {}
286
287 SchedulerLock lock1;
288 SchedulerLock lock2;
289 SchedulerLock lock3;
290 SchedulerLock lock4;
291 SchedulerLock lock5;
292 };
293
294 EXPECT_DCHECK_DEATH({ LockCycle cycle; }, "");
295 }
296
297 } // namespace
298 } // namespace internal
299 } // namespace base
OLDNEW
« base/task_scheduler/scheduler_lock_impl.cc ('K') | « base/task_scheduler/scheduler_lock_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698