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