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

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: Standardize Tests on SimpleThread 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
danakj 2016/03/08 21:24:50 Oh, can you wrap the whole test file in a nested a
robliao 2016/03/08 22:14:08 Done.
20 // Adapted from base::Lock's BasicLockTestThread to make sure
21 // Acquire()/Release() don't crash.
22 class BasicLockTestThread : public SimpleThread {
23 public:
24 explicit BasicLockTestThread(SchedulerLock* lock)
25 : SimpleThread("BasicLockTestThread"),
26 lock_(lock),
27 acquired_(0) {}
28
29 int acquired() const { return acquired_; }
30
31 private:
32 void Run() override {
33 for (int i = 0; i < 10; i++) {
34 lock_->Acquire();
35 acquired_++;
36 lock_->Release();
37 }
38 for (int i = 0; i < 10; i++) {
39 lock_->Acquire();
40 acquired_++;
41 PlatformThread::Sleep(TimeDelta::FromMilliseconds(base::RandInt(0, 19)));
42 lock_->Release();
43 }
44 }
45
46 SchedulerLock* const lock_;
47 int acquired_;
48
49 DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread);
50 };
51
52 class BasicLockAcquireAndWaitThread : public SimpleThread {
53 public:
54 explicit BasicLockAcquireAndWaitThread(SchedulerLock* lock)
55 : SimpleThread("BasicLockAcquireAndWaitThread"),
56 lock_(lock),
57 lock_acquire_event_(false, false),
58 main_thread_continue_event_(false, false) {}
59
60 void WaitForLockAcquisition() {
61 lock_acquire_event_.Wait();
62 }
63
64 void ContinueMain() {
65 main_thread_continue_event_.Signal();
66 }
67
68 private:
69 void Run() override {
70 lock_->Acquire();
71 lock_acquire_event_.Signal();
72 main_thread_continue_event_.Wait();
73 lock_->Release();
74 }
75
76 SchedulerLock* const lock_;
77 WaitableEvent lock_acquire_event_;
78 WaitableEvent main_thread_continue_event_;
79
80 DISALLOW_COPY_AND_ASSIGN(BasicLockAcquireAndWaitThread);
81 };
82
83 TEST(TaskSchedulerLock, Basic) {
84 SchedulerLock lock;
85 BasicLockTestThread thread(&lock);
86
87 thread.Start();
88
89 int acquired = 0;
90 for (int i = 0; i < 5; i++) {
91 lock.Acquire();
92 acquired++;
93 lock.Release();
94 }
95 for (int i = 0; i < 10; i++) {
96 lock.Acquire();
97 acquired++;
98 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
danakj 2016/03/08 21:22:56 Why is it base::RandInt(0, 19) above but rand() %
robliao 2016/03/08 22:14:08 Incomplete migration from the original lock unitte
99 lock.Release();
100 }
101 for (int i = 0; i < 5; i++) {
102 lock.Acquire();
103 acquired++;
104 PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
105 lock.Release();
106 }
107
108 thread.Join();
109
110 EXPECT_EQ(acquired, 20);
111 EXPECT_EQ(thread.acquired(), 20);
112 }
113
114 TEST(TaskSchedulerLock, AcquirePredecessor) {
115 SchedulerLock predecessor;
116 SchedulerLock lock(&predecessor);
117 predecessor.Acquire();
118 lock.Acquire();
119 lock.Release();
120 predecessor.Release();
121 }
122
123 TEST(TaskSchedulerLock, AcquirePredecessorWrongOrder) {
124 SchedulerLock predecessor;
125 SchedulerLock lock(&predecessor);
126 EXPECT_DEBUG_DEATH({
danakj 2016/03/08 21:22:56 EXPECT_DEBUG_DEATH asserts that the given statemen
robliao 2016/03/08 22:14:08 Changed to #if DCHECK_IS_ON() #define EXPECT_DCHEC
127 lock.Acquire();
128 predecessor.Acquire();
129 }, "");
130 }
131
132 TEST(TaskSchedulerLock, AcquireNonPredecessor) {
133 SchedulerLock lock1;
134 SchedulerLock lock2;
135 EXPECT_DEBUG_DEATH({
136 lock1.Acquire();
137 lock2.Acquire();
138 }, "");
139 }
140
141 TEST(TaskSchedulerLock, AcquireMultipleLocksInOrder) {
142 SchedulerLock lock1;
143 SchedulerLock lock2(&lock1);
144 SchedulerLock lock3(&lock2);
145 lock1.Acquire();
146 lock2.Acquire();
147 lock3.Acquire();
148 lock3.Release();
149 lock2.Release();
150 lock1.Release();
151 }
152
153 TEST(TaskSchedulerLock, AcquireMultipleLocksInTheMiddleOfAChain) {
154 SchedulerLock lock1;
155 SchedulerLock lock2(&lock1);
156 SchedulerLock lock3(&lock2);
157 lock2.Acquire();
158 lock3.Acquire();
159 lock3.Release();
160 lock2.Release();
161 }
162
163 TEST(TaskSchedulerLock, AcquireMultipleLocksNoTransitivity) {
164 SchedulerLock lock1;
165 SchedulerLock lock2(&lock1);
166 SchedulerLock lock3(&lock2);
167 EXPECT_DEBUG_DEATH({
168 lock1.Acquire();
169 lock3.Acquire();
170 }, "");
171 }
172
173 TEST(TaskSchedulerLock, AcquireLocksDifferentThreadsSafely) {
174 SchedulerLock lock1;
175 SchedulerLock lock2;
176 BasicLockAcquireAndWaitThread thread(&lock1);
177 thread.Start();
178
179 lock2.Acquire();
180 thread.WaitForLockAcquisition();
181 thread.ContinueMain();
182 thread.Join();
183 lock2.Release();
184 }
185
186 TEST(TaskSchedulerLock,
187 AcquireLocksWithPredecessorDifferentThreadsSafelyPredecessorFirst) {
188 // A lock and its predecessor may be safely acquired on different threads.
189 // This Thread Other Thread
190 // predecessor.Acquire()
191 // lock.Acquire()
192 // predecessor.Release()
193 // lock.Release()
194 SchedulerLock predecessor;
195 SchedulerLock lock(&predecessor);
196 predecessor.Acquire();
197 BasicLockAcquireAndWaitThread thread(&lock);
198 thread.Start();
199 thread.WaitForLockAcquisition();
200 predecessor.Release();
201 thread.ContinueMain();
202 thread.Join();
203 }
204
205 TEST(TaskSchedulerLock,
206 AcquireLocksWithPredecessorDifferentThreadsSafelyPredecessorLast) {
danakj 2016/03/08 21:22:56 One more test case worth mentioning maybe? This t
robliao 2016/03/08 22:14:08 I'll buy that. Added a case.
207 // A lock and its predecessor may be safely acquired on different threads.
208 // This Thread Other Thread
209 // lock.Acquire()
210 // predecessor.Acquire()
211 // lock.Release()
212 // predecessor.Release()
213 SchedulerLock predecessor;
214 SchedulerLock lock(&predecessor);
215 lock.Acquire();
216 BasicLockAcquireAndWaitThread thread(&predecessor);
217 thread.Start();
218 thread.WaitForLockAcquisition();
219 lock.Release();
220 thread.ContinueMain();
221 thread.Join();
222 }
223
224 TEST(TaskSchedulerLock, SelfReferentialLock) {
225 struct SelfReferentialLock {
226 SelfReferentialLock() : lock(&lock) {}
227
228 SchedulerLock lock;
229 };
230
231 EXPECT_DEBUG_DEATH({ SelfReferentialLock lock; }, "");
232 }
233
234 TEST(TaskSchedulerLock, PredecessorCycle) {
235 struct LockCycle {
236 LockCycle() : lock1(&lock2), lock2(&lock1) {}
237
238 SchedulerLock lock1;
239 SchedulerLock lock2;
240 };
241
242 EXPECT_DEBUG_DEATH({ LockCycle cycle; }, "");
243 }
244
245 TEST(TaskSchedulerLock, PredecessorLongerCycle) {
246 struct LockCycle {
247 LockCycle()
248 : lock1(&lock5),
249 lock2(&lock1),
250 lock3(&lock2),
251 lock4(&lock3),
252 lock5(&lock4) {}
253
254 SchedulerLock lock1;
255 SchedulerLock lock2;
256 SchedulerLock lock3;
257 SchedulerLock lock4;
258 SchedulerLock lock5;
259 };
260
261 EXPECT_DEBUG_DEATH({ LockCycle cycle; }, "");
262 }
263
264 } // namespace internal
265 } // 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