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

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

Issue 2019763002: TaskScheduler: Atomic operations in TaskTracker (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR gab #10 Created 4 years, 6 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 2016 The Chromium Authors. All rights reserved. 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 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/task_scheduler/task_tracker.h" 5 #include "base/task_scheduler/task_tracker.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <vector>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/macros.h" 12 #include "base/macros.h"
12 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
13 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
14 #include "base/sequenced_task_runner.h" 15 #include "base/sequenced_task_runner.h"
15 #include "base/single_thread_task_runner.h" 16 #include "base/single_thread_task_runner.h"
16 #include "base/synchronization/waitable_event.h" 17 #include "base/synchronization/waitable_event.h"
18 #include "base/task_scheduler/scheduler_lock.h"
17 #include "base/task_scheduler/task.h" 19 #include "base/task_scheduler/task.h"
18 #include "base/task_scheduler/task_traits.h" 20 #include "base/task_scheduler/task_traits.h"
19 #include "base/task_scheduler/test_utils.h" 21 #include "base/task_scheduler/test_utils.h"
20 #include "base/test/test_simple_task_runner.h" 22 #include "base/test/test_simple_task_runner.h"
21 #include "base/threading/platform_thread.h" 23 #include "base/threading/platform_thread.h"
22 #include "base/threading/sequenced_task_runner_handle.h" 24 #include "base/threading/sequenced_task_runner_handle.h"
23 #include "base/threading/simple_thread.h" 25 #include "base/threading/simple_thread.h"
24 #include "base/threading/thread_restrictions.h" 26 #include "base/threading/thread_restrictions.h"
25 #include "base/threading/thread_task_runner_handle.h" 27 #include "base/threading/thread_task_runner_handle.h"
26 #include "testing/gtest/include/gtest/gtest.h" 28 #include "testing/gtest/include/gtest/gtest.h"
27 29
28 namespace base { 30 namespace base {
29 namespace internal { 31 namespace internal {
30 32
31 namespace { 33 namespace {
32 34
35 constexpr size_t kLoadTestNumIterations = 100;
36
33 // Calls TaskTracker::Shutdown() asynchronously. 37 // Calls TaskTracker::Shutdown() asynchronously.
34 class ThreadCallingShutdown : public SimpleThread { 38 class ThreadCallingShutdown : public SimpleThread {
35 public: 39 public:
36 explicit ThreadCallingShutdown(TaskTracker* tracker) 40 explicit ThreadCallingShutdown(TaskTracker* tracker)
37 : SimpleThread("ThreadCallingShutdown"), 41 : SimpleThread("ThreadCallingShutdown"),
38 tracker_(tracker), 42 tracker_(tracker),
39 has_returned_(WaitableEvent::ResetPolicy::MANUAL, 43 has_returned_(WaitableEvent::ResetPolicy::MANUAL,
40 WaitableEvent::InitialState::NOT_SIGNALED) {} 44 WaitableEvent::InitialState::NOT_SIGNALED) {}
41 45
42 // Returns true once the async call to Shutdown() has returned. 46 // Returns true once the async call to Shutdown() has returned.
43 bool has_returned() { return has_returned_.IsSignaled(); } 47 bool has_returned() { return has_returned_.IsSignaled(); }
44 48
45 private: 49 private:
46 void Run() override { 50 void Run() override {
47 tracker_->Shutdown(); 51 tracker_->Shutdown();
48 has_returned_.Signal(); 52 has_returned_.Signal();
49 } 53 }
50 54
51 TaskTracker* const tracker_; 55 TaskTracker* const tracker_;
52 WaitableEvent has_returned_; 56 WaitableEvent has_returned_;
53 57
54 DISALLOW_COPY_AND_ASSIGN(ThreadCallingShutdown); 58 DISALLOW_COPY_AND_ASSIGN(ThreadCallingShutdown);
55 }; 59 };
56 60
57 // Runs a task asynchronously. 61 class ThreadPostingAndRunningTask : public SimpleThread {
58 class ThreadRunningTask : public SimpleThread {
59 public: 62 public:
60 ThreadRunningTask(TaskTracker* tracker, const Task* task) 63 enum Action {
61 : SimpleThread("ThreadRunningTask"), tracker_(tracker), task_(task) {} 64 WILL_POST = 0x1,
65 RUN = 0x2,
66 WILL_POST_AND_RUN = WILL_POST | RUN,
67 };
68
69 ThreadPostingAndRunningTask(TaskTracker* tracker,
70 const Task* task,
71 Action action,
72 bool expect_post_succeeds)
73 : SimpleThread("ThreadPostingAndRunningTask"),
74 tracker_(tracker),
75 task_(task),
76 action_(action),
77 expect_post_succeeds_(expect_post_succeeds) {}
62 78
63 private: 79 private:
64 void Run() override { tracker_->RunTask(task_); } 80 void Run() override {
81 bool post_succeeded = true;
82 if (action_ & WILL_POST) {
83 post_succeeded = tracker_->WillPostTask(task_);
84 EXPECT_EQ(expect_post_succeeds_, post_succeeded);
85 }
86 if (post_succeeded && action_ & RUN)
87 tracker_->RunTask(task_);
88 }
65 89
66 TaskTracker* const tracker_; 90 TaskTracker* const tracker_;
67 const Task* const task_; 91 const Task* const task_;
92 const Action action_;
93 const bool expect_post_succeeds_;
68 94
69 DISALLOW_COPY_AND_ASSIGN(ThreadRunningTask); 95 DISALLOW_COPY_AND_ASSIGN(ThreadPostingAndRunningTask);
96 ;
gab 2016/06/20 16:46:21 rm
fdoray 2016/06/20 19:31:35 Done.
70 }; 97 };
71 98
72 class ScopedSetSingletonAllowed { 99 class ScopedSetSingletonAllowed {
73 public: 100 public:
74 ScopedSetSingletonAllowed(bool singleton_allowed) 101 ScopedSetSingletonAllowed(bool singleton_allowed)
75 : previous_value_( 102 : previous_value_(
76 ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {} 103 ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {}
77 ~ScopedSetSingletonAllowed() { 104 ~ScopedSetSingletonAllowed() {
78 ThreadRestrictions::SetSingletonAllowed(previous_value_); 105 ThreadRestrictions::SetSingletonAllowed(previous_value_);
79 } 106 }
(...skipping 16 matching lines...) Expand all
96 } 123 }
97 124
98 // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown() 125 // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown()
99 // method has been entered on the new thread, but it hasn't necessarily 126 // method has been entered on the new thread, but it hasn't necessarily
100 // returned. 127 // returned.
101 void CallShutdownAsync() { 128 void CallShutdownAsync() {
102 ASSERT_FALSE(thread_calling_shutdown_); 129 ASSERT_FALSE(thread_calling_shutdown_);
103 thread_calling_shutdown_.reset(new ThreadCallingShutdown(&tracker_)); 130 thread_calling_shutdown_.reset(new ThreadCallingShutdown(&tracker_));
104 thread_calling_shutdown_->Start(); 131 thread_calling_shutdown_->Start();
105 while (!tracker_.IsShuttingDownForTesting() && 132 while (!tracker_.IsShuttingDownForTesting() &&
106 !tracker_.shutdown_completed()) { 133 !tracker_.ShutdownCompleted()) {
107 PlatformThread::YieldCurrentThread(); 134 PlatformThread::YieldCurrentThread();
108 } 135 }
109 } 136 }
110 137
111 void WaitForAsyncShutdownCompleted() { 138 void WaitForAsyncShutdownCompleted() {
112 ASSERT_TRUE(thread_calling_shutdown_); 139 ASSERT_TRUE(thread_calling_shutdown_);
113 thread_calling_shutdown_->Join(); 140 thread_calling_shutdown_->Join();
114 EXPECT_TRUE(thread_calling_shutdown_->has_returned()); 141 EXPECT_TRUE(thread_calling_shutdown_->has_returned());
115 EXPECT_TRUE(tracker_.shutdown_completed()); 142 EXPECT_TRUE(tracker_.ShutdownCompleted());
116 } 143 }
117 144
118 void VerifyAsyncShutdownInProgress() { 145 void VerifyAsyncShutdownInProgress() {
119 ASSERT_TRUE(thread_calling_shutdown_); 146 ASSERT_TRUE(thread_calling_shutdown_);
120 EXPECT_FALSE(thread_calling_shutdown_->has_returned()); 147 EXPECT_FALSE(thread_calling_shutdown_->has_returned());
121 EXPECT_FALSE(tracker_.shutdown_completed()); 148 EXPECT_FALSE(tracker_.ShutdownCompleted());
122 EXPECT_TRUE(tracker_.IsShuttingDownForTesting()); 149 EXPECT_TRUE(tracker_.IsShuttingDownForTesting());
123 } 150 }
124 151
152 size_t NumTasksExecuted() {
153 AutoSchedulerLock auto_lock(lock_);
154 return num_tasks_executed_;
155 }
156
125 TaskTracker tracker_; 157 TaskTracker tracker_;
126 size_t num_tasks_executed_ = 0;
127 158
128 private: 159 private:
129 void RunTaskCallback() { ++num_tasks_executed_; } 160 void RunTaskCallback() {
161 AutoSchedulerLock auto_lock(lock_);
162 ++num_tasks_executed_;
163 }
130 164
131 std::unique_ptr<ThreadCallingShutdown> thread_calling_shutdown_; 165 std::unique_ptr<ThreadCallingShutdown> thread_calling_shutdown_;
132 166
167 // Synchronizes accesses to |num_tasks_executed_|.
168 SchedulerLock lock_;
169
170 size_t num_tasks_executed_ = 0;
171
133 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest); 172 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest);
134 }; 173 };
135 174
136 #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \ 175 #define WAIT_FOR_ASYNC_ShutdownCompleted() \
gab 2016/06/20 16:46:21 CAPS
fdoray 2016/06/20 19:31:35 Done.
137 do { \ 176 do { \
138 SCOPED_TRACE(""); \ 177 SCOPED_TRACE(""); \
139 WaitForAsyncShutdownCompleted(); \ 178 WaitForAsyncShutdownCompleted(); \
140 } while (false) 179 } while (false)
141 180
142 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \ 181 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \
143 do { \ 182 do { \
144 SCOPED_TRACE(""); \ 183 SCOPED_TRACE(""); \
145 VerifyAsyncShutdownInProgress(); \ 184 VerifyAsyncShutdownInProgress(); \
146 } while (false) 185 } while (false)
147 186
148 } // namespace 187 } // namespace
149 188
150 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) { 189 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) {
151 std::unique_ptr<Task> task(CreateTask(GetParam())); 190 std::unique_ptr<Task> task(CreateTask(GetParam()));
152 191
153 // Inform |task_tracker_| that |task| will be posted. 192 // Inform |task_tracker_| that |task| will be posted.
154 EXPECT_TRUE(tracker_.WillPostTask(task.get())); 193 EXPECT_TRUE(tracker_.WillPostTask(task.get()));
155 194
156 // Run the task. 195 // Run the task.
157 EXPECT_EQ(0U, num_tasks_executed_); 196 EXPECT_EQ(0U, NumTasksExecuted());
158 tracker_.RunTask(task.get()); 197 tracker_.RunTask(task.get());
159 EXPECT_EQ(1U, num_tasks_executed_); 198 EXPECT_EQ(1U, NumTasksExecuted());
160 199
161 // Shutdown() shouldn't block. 200 // Shutdown() shouldn't block.
162 tracker_.Shutdown(); 201 tracker_.Shutdown();
163 } 202 }
164 203
165 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) { 204 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) {
166 // Create a task that will block until |event| is signaled. 205 // Create a task that will block until |event| is signaled.
167 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC, 206 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
168 WaitableEvent::InitialState::NOT_SIGNALED); 207 WaitableEvent::InitialState::NOT_SIGNALED);
169 std::unique_ptr<Task> blocked_task( 208 std::unique_ptr<Task> blocked_task(
170 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)), 209 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)),
171 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); 210 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta()));
172 211
173 // Inform |task_tracker_| that |blocked_task| will be posted. 212 // Inform |task_tracker_| that |blocked_task| will be posted.
174 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get())); 213 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get()));
175 214
176 // Run the task asynchronouly. 215 // Run the task asynchronouly.
177 ThreadRunningTask thread_running_task(&tracker_, blocked_task.get()); 216 ThreadPostingAndRunningTask thread_running_task(
217 &tracker_, blocked_task.get(), ThreadPostingAndRunningTask::RUN, false);
178 thread_running_task.Start(); 218 thread_running_task.Start();
179 219
180 // Initiate shutdown while the task is running. 220 // Initiate shutdown while the task is running.
181 CallShutdownAsync(); 221 CallShutdownAsync();
182 222
183 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { 223 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) {
184 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. 224 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress.
185 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 225 WAIT_FOR_ASYNC_ShutdownCompleted();
186 } else { 226 } else {
187 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. 227 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress.
188 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 228 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
189 } 229 }
190 230
191 // Unblock the task. 231 // Unblock the task.
192 event.Signal(); 232 event.Signal();
193 thread_running_task.Join(); 233 thread_running_task.Join();
194 234
195 // Shutdown should now complete for a non CONTINUE_ON_SHUTDOWN task. 235 // Shutdown should now complete for a non CONTINUE_ON_SHUTDOWN task.
196 if (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) 236 if (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
197 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 237 WAIT_FOR_ASYNC_ShutdownCompleted();
198 } 238 }
199 239
200 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) { 240 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) {
201 // Inform |task_tracker_| that a task will be posted. 241 // Inform |task_tracker_| that a task will be posted.
202 std::unique_ptr<Task> task(CreateTask(GetParam())); 242 std::unique_ptr<Task> task(CreateTask(GetParam()));
203 EXPECT_TRUE(tracker_.WillPostTask(task.get())); 243 EXPECT_TRUE(tracker_.WillPostTask(task.get()));
204 244
205 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to 245 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
206 // block shutdown. 246 // block shutdown.
207 std::unique_ptr<Task> block_shutdown_task( 247 std::unique_ptr<Task> block_shutdown_task(
208 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); 248 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
209 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); 249 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get()));
210 250
211 // Call Shutdown() asynchronously. 251 // Call Shutdown() asynchronously.
212 CallShutdownAsync(); 252 CallShutdownAsync();
213 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 253 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
214 254
215 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it 255 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it
216 // should be discarded. 256 // should be discarded.
217 EXPECT_EQ(0U, num_tasks_executed_); 257 EXPECT_EQ(0U, NumTasksExecuted());
218 tracker_.RunTask(task.get()); 258 tracker_.RunTask(task.get());
219 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 1U : 0U, 259 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 1U : 0U,
220 num_tasks_executed_); 260 NumTasksExecuted());
221 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 261 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
222 262
223 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. 263 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task.
224 tracker_.RunTask(block_shutdown_task.get()); 264 tracker_.RunTask(block_shutdown_task.get());
225 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, 265 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U,
226 num_tasks_executed_); 266 NumTasksExecuted());
227 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 267 WAIT_FOR_ASYNC_ShutdownCompleted();
228 } 268 }
229 269
230 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) { 270 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) {
231 // Inform |task_tracker_| that a task will be posted. 271 // Inform |task_tracker_| that a task will be posted.
232 std::unique_ptr<Task> task(CreateTask(GetParam())); 272 std::unique_ptr<Task> task(CreateTask(GetParam()));
233 EXPECT_TRUE(tracker_.WillPostTask(task.get())); 273 EXPECT_TRUE(tracker_.WillPostTask(task.get()));
234 274
235 // Call Shutdown() asynchronously. 275 // Call Shutdown() asynchronously.
236 CallShutdownAsync(); 276 CallShutdownAsync();
237 EXPECT_EQ(0U, num_tasks_executed_); 277 EXPECT_EQ(0U, NumTasksExecuted());
238 278
239 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { 279 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
240 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 280 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
241 281
242 // Run the task to unblock shutdown. 282 // Run the task to unblock shutdown.
243 tracker_.RunTask(task.get()); 283 tracker_.RunTask(task.get());
244 EXPECT_EQ(1U, num_tasks_executed_); 284 EXPECT_EQ(1U, NumTasksExecuted());
245 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 285 WAIT_FOR_ASYNC_ShutdownCompleted();
246 286
247 // It is not possible to test running a BLOCK_SHUTDOWN task posted before 287 // It is not possible to test running a BLOCK_SHUTDOWN task posted before
248 // shutdown after shutdown because Shutdown() won't return if there are 288 // shutdown after shutdown because Shutdown() won't return if there are
249 // pending BLOCK_SHUTDOWN tasks. 289 // pending BLOCK_SHUTDOWN tasks.
250 } else { 290 } else {
251 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 291 WAIT_FOR_ASYNC_ShutdownCompleted();
252 292
253 // The task shouldn't be allowed to run after shutdown. 293 // The task shouldn't be allowed to run after shutdown.
254 tracker_.RunTask(task.get()); 294 tracker_.RunTask(task.get());
255 EXPECT_EQ(0U, num_tasks_executed_); 295 EXPECT_EQ(0U, NumTasksExecuted());
256 } 296 }
257 } 297 }
258 298
259 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) { 299 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) {
260 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to 300 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
261 // block shutdown. 301 // block shutdown.
262 std::unique_ptr<Task> block_shutdown_task( 302 std::unique_ptr<Task> block_shutdown_task(
263 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); 303 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
264 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); 304 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get()));
265 305
266 // Call Shutdown() asynchronously. 306 // Call Shutdown() asynchronously.
267 CallShutdownAsync(); 307 CallShutdownAsync();
268 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 308 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
269 309
270 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { 310 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
271 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. 311 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted.
272 std::unique_ptr<Task> task(CreateTask(GetParam())); 312 std::unique_ptr<Task> task(CreateTask(GetParam()));
273 EXPECT_TRUE(tracker_.WillPostTask(task.get())); 313 EXPECT_TRUE(tracker_.WillPostTask(task.get()));
274 314
275 // Run the BLOCK_SHUTDOWN task. 315 // Run the BLOCK_SHUTDOWN task.
276 EXPECT_EQ(0U, num_tasks_executed_); 316 EXPECT_EQ(0U, NumTasksExecuted());
277 tracker_.RunTask(task.get()); 317 tracker_.RunTask(task.get());
278 EXPECT_EQ(1U, num_tasks_executed_); 318 EXPECT_EQ(1U, NumTasksExecuted());
279 } else { 319 } else {
280 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task. 320 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task.
281 std::unique_ptr<Task> task(CreateTask(GetParam())); 321 std::unique_ptr<Task> task(CreateTask(GetParam()));
282 EXPECT_FALSE(tracker_.WillPostTask(task.get())); 322 EXPECT_FALSE(tracker_.WillPostTask(task.get()));
283 323
284 // Don't try to run the task, because it wasn't allowed to be posted. 324 // Don't try to run the task, because it wasn't allowed to be posted.
285 } 325 }
286 326
287 // Unblock shutdown by running |block_shutdown_task|. 327 // Unblock shutdown by running |block_shutdown_task|.
288 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); 328 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
289 tracker_.RunTask(block_shutdown_task.get()); 329 tracker_.RunTask(block_shutdown_task.get());
290 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, 330 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U,
291 num_tasks_executed_); 331 NumTasksExecuted());
292 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); 332 WAIT_FOR_ASYNC_ShutdownCompleted();
293 } 333 }
294 334
295 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) { 335 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) {
296 tracker_.Shutdown(); 336 tracker_.Shutdown();
297 337
298 std::unique_ptr<Task> task(CreateTask(GetParam())); 338 std::unique_ptr<Task> task(CreateTask(GetParam()));
299 339
300 // |task_tracker_| shouldn't allow a task to be posted after shutdown. 340 // |task_tracker_| shouldn't allow a task to be posted after shutdown.
301 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { 341 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
302 EXPECT_DCHECK_DEATH({ tracker_.WillPostTask(task.get()); }, ""); 342 EXPECT_DCHECK_DEATH({ tracker_.WillPostTask(task.get()); }, "");
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); 455 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
416 INSTANTIATE_TEST_CASE_P( 456 INSTANTIATE_TEST_CASE_P(
417 SkipOnShutdown, 457 SkipOnShutdown,
418 TaskSchedulerTaskTrackerTest, 458 TaskSchedulerTaskTrackerTest,
419 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); 459 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
420 INSTANTIATE_TEST_CASE_P( 460 INSTANTIATE_TEST_CASE_P(
421 BlockShutdown, 461 BlockShutdown,
422 TaskSchedulerTaskTrackerTest, 462 TaskSchedulerTaskTrackerTest,
423 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN)); 463 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN));
424 464
465 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) {
466 // Post and run tasks asynchronously.
467 std::vector<std::unique_ptr<Task>> tasks;
468 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
469
470 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
471 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
472 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
473 &tracker_, tasks.back().get(),
474 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true)));
475 threads.back()->Start();
476
477 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
478 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
479 &tracker_, tasks.back().get(),
480 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true)));
481 threads.back()->Start();
482
483 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
484 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
485 &tracker_, tasks.back().get(),
486 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true)));
487 threads.back()->Start();
488 }
489
490 for (const auto& thread : threads)
491 thread->Join();
492
493 // Expect all tasks to be executed.
494 EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted());
495
496 // Should return immediately because no tasks are blocking shutdown.
497 tracker_.Shutdown();
498 }
499
500 TEST_F(TaskSchedulerTaskTrackerTest,
501 LoadWillPostBeforeShutdownAndRunDuringShutdown) {
502 // Post tasks asynchronously.
503 std::vector<std::unique_ptr<Task>> tasks;
504 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads;
505
506 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
507 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
508 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
509 &tracker_, tasks.back().get(), ThreadPostingAndRunningTask::WILL_POST,
510 true)));
511 post_threads.back()->Start();
512
513 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
514 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
515 &tracker_, tasks.back().get(), ThreadPostingAndRunningTask::WILL_POST,
516 true)));
517 post_threads.back()->Start();
518
519 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
520 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
521 &tracker_, tasks.back().get(), ThreadPostingAndRunningTask::WILL_POST,
522 true)));
523 post_threads.back()->Start();
524 }
525
526 for (const auto& thread : post_threads)
527 thread->Join();
528
529 // Call Shutdown() asynchronously.
530 CallShutdownAsync();
531
532 // Run tasks asynchronously.
533 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads;
534
535 for (const auto& task : tasks) {
536 run_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
537 &tracker_, task.get(), ThreadPostingAndRunningTask::RUN, false)));
538 run_threads.back()->Start();
539 }
540
541 for (const auto& thread : run_threads)
542 thread->Join();
543
544 WAIT_FOR_ASYNC_ShutdownCompleted();
545
546 // Expect BLOCK_SHUTDOWN tasks to have been executed.
547 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
548 }
549
550 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) {
551 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
552 // block shutdown.
553 std::unique_ptr<Task> block_shutdown_task(
554 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
555 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get()));
556
557 // Call Shutdown() asynchronously.
558 CallShutdownAsync();
559
560 // Post and run tasks asynchronously.
561 std::vector<std::unique_ptr<Task>> tasks;
562 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
563
564 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
565 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
566 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
567 &tracker_, tasks.back().get(),
568 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, false)));
569 threads.back()->Start();
570
571 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
572 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
573 &tracker_, tasks.back().get(),
574 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, false)));
575 threads.back()->Start();
576
577 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
578 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask(
579 &tracker_, tasks.back().get(),
580 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true)));
581 threads.back()->Start();
582 }
583
584 for (const auto& thread : threads)
585 thread->Join();
586
587 // Expect BLOCK_SHUTDOWN tasks to have been executed.
588 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
589
590 // Shutdown() shouldn't return before |block_shutdown_task| is executed.
591 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
592
593 // Unblock shutdown by running |block_shutdown_task|.
594 tracker_.RunTask(block_shutdown_task.get());
595 EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted());
596 WAIT_FOR_ASYNC_ShutdownCompleted();
597 }
598
425 } // namespace internal 599 } // namespace internal
426 } // namespace base 600 } // namespace base
OLDNEW
« base/task_scheduler/task_tracker.cc ('K') | « base/task_scheduler/task_tracker.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698