1 // Copyright 2016 The Chromium Authors
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/thread_pool/task_tracker.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "base/barrier_closure.h"
14 #include "base/check_op.h"
15 #include "base/functional/bind.h"
16 #include "base/functional/callback.h"
17 #include "base/functional/callback_helpers.h"
18 #include "base/memory/ptr_util.h"
19 #include "base/memory/raw_ptr.h"
20 #include "base/memory/ref_counted.h"
21 #include "base/metrics/histogram_base.h"
22 #include "base/metrics/histogram_samples.h"
23 #include "base/sequence_token.h"
24 #include "base/synchronization/atomic_flag.h"
25 #include "base/task/common/checked_lock.h"
26 #include "base/task/sequenced_task_runner.h"
27 #include "base/task/single_thread_task_runner.h"
28 #include "base/task/task_traits.h"
29 #include "base/task/thread_pool/task.h"
30 #include "base/task/thread_pool/test_utils.h"
31 #include "base/test/bind.h"
32 #include "base/test/gtest_util.h"
33 #include "base/test/metrics/histogram_tester.h"
34 #include "base/test/test_simple_task_runner.h"
35 #include "base/test/test_timeouts.h"
36 #include "base/test/test_waitable_event.h"
37 #include "base/threading/platform_thread.h"
38 #include "base/threading/scoped_blocking_call.h"
39 #include "base/threading/simple_thread.h"
40 #include "base/threading/thread_restrictions.h"
41 #include "testing/gmock/include/gmock/gmock.h"
42 #include "testing/gtest/include/gtest/gtest.h"
43
44 namespace base {
45 namespace internal {
46
47 namespace {
48
49 constexpr size_t kLoadTestNumIterations = 75;
50
51 // Invokes a closure asynchronously.
52 class CallbackThread : public SimpleThread {
53 public:
CallbackThread(OnceClosure closure)54 explicit CallbackThread(OnceClosure closure)
55 : SimpleThread("CallbackThread"), closure_(std::move(closure)) {}
56 CallbackThread(const CallbackThread&) = delete;
57 CallbackThread& operator=(const CallbackThread&) = delete;
58
59 // Returns true once the callback returns.
has_returned()60 bool has_returned() { return has_returned_.IsSet(); }
61
62 private:
Run()63 void Run() override {
64 std::move(closure_).Run();
65 has_returned_.Set();
66 }
67
68 OnceClosure closure_;
69 AtomicFlag has_returned_;
70 };
71
72 class ThreadPostingAndRunningTask : public SimpleThread {
73 public:
74 enum class Action {
75 WILL_POST,
76 RUN,
77 WILL_POST_AND_RUN,
78 };
79
80 // |action| must be either WILL_POST or WILL_POST_AND_RUN.
81 // |task| will be pushed to |sequence| and |sequence| will be registered. If
82 // |action| is WILL_POST_AND_RUN, a task from |sequence| will run.
ThreadPostingAndRunningTask(TaskTracker * tracker,scoped_refptr<Sequence> sequence,Action action,bool expect_post_succeeds,Task task)83 ThreadPostingAndRunningTask(TaskTracker* tracker,
84 scoped_refptr<Sequence> sequence,
85 Action action,
86 bool expect_post_succeeds,
87 Task task)
88 : SimpleThread("ThreadPostingAndRunningTask"),
89 tracker_(tracker),
90 task_(std::move(task)),
91 sequence_(std::move(sequence)),
92 action_(action),
93 expect_post_succeeds_(expect_post_succeeds) {
94 EXPECT_TRUE(task_.task);
95 EXPECT_TRUE(sequence_);
96 EXPECT_NE(Action::RUN, action_);
97 }
98
99 // A task from |task_source| will run.
ThreadPostingAndRunningTask(TaskTracker * tracker,RegisteredTaskSource task_source)100 ThreadPostingAndRunningTask(TaskTracker* tracker,
101 RegisteredTaskSource task_source)
102 : SimpleThread("ThreadPostingAndRunningTask"),
103 tracker_(tracker),
104 task_source_(std::move(task_source)),
105 action_(Action::RUN),
106 expect_post_succeeds_(false) {
107 EXPECT_TRUE(task_source_);
108 }
109 ThreadPostingAndRunningTask(const ThreadPostingAndRunningTask&) = delete;
110 ThreadPostingAndRunningTask& operator=(const ThreadPostingAndRunningTask&) =
111 delete;
112
TakeTaskSource()113 RegisteredTaskSource TakeTaskSource() { return std::move(task_source_); }
114
115 private:
Run()116 void Run() override {
117 bool post_and_queue_succeeded = true;
118 if (action_ == Action::WILL_POST || action_ == Action::WILL_POST_AND_RUN) {
119 EXPECT_TRUE(task_.task);
120
121 post_and_queue_succeeded =
122 tracker_->WillPostTask(&task_, sequence_->shutdown_behavior());
123 {
124 auto transaction = sequence_->BeginTransaction();
125 transaction.WillPushImmediateTask();
126 transaction.PushImmediateTask(std::move(task_));
127 }
128 task_source_ = tracker_->RegisterTaskSource(std::move(sequence_));
129
130 post_and_queue_succeeded &= !!task_source_;
131
132 EXPECT_EQ(expect_post_succeeds_, post_and_queue_succeeded);
133 }
134 if (post_and_queue_succeeded &&
135 (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) {
136 EXPECT_TRUE(task_source_);
137 task_source_.WillRunTask();
138
139 // Expect RunAndPopNextTask to return nullptr since |sequence| is empty
140 // after popping a task from it.
141 EXPECT_FALSE(tracker_->RunAndPopNextTask(std::move(task_source_)));
142 }
143 }
144
145 const raw_ptr<TaskTracker> tracker_;
146 Task task_;
147 scoped_refptr<Sequence> sequence_;
148 RegisteredTaskSource task_source_;
149 const Action action_;
150 const bool expect_post_succeeds_;
151 };
152
153 class ThreadPoolTaskTrackerTest
154 : public testing::TestWithParam<TaskShutdownBehavior> {
155 public:
156 ThreadPoolTaskTrackerTest(const ThreadPoolTaskTrackerTest&) = delete;
157 ThreadPoolTaskTrackerTest& operator=(const ThreadPoolTaskTrackerTest&) =
158 delete;
159
160 protected:
161 ThreadPoolTaskTrackerTest() = default;
162
163 // Creates a task.
CreateTask()164 Task CreateTask() {
165 return Task(
166 FROM_HERE,
167 BindOnce(&ThreadPoolTaskTrackerTest::RunTaskCallback, Unretained(this)),
168 TimeTicks::Now(), TimeDelta());
169 }
170
WillPostTaskAndQueueTaskSource(Task task,const TaskTraits & traits)171 RegisteredTaskSource WillPostTaskAndQueueTaskSource(
172 Task task,
173 const TaskTraits& traits) {
174 if (!tracker_.WillPostTask(&task, traits.shutdown_behavior()))
175 return nullptr;
176 auto sequence = test::CreateSequenceWithTask(std::move(task), traits);
177 return tracker_.RegisterTaskSource(std::move(sequence));
178 }
RunAndPopNextTask(RegisteredTaskSource task_source)179 RegisteredTaskSource RunAndPopNextTask(RegisteredTaskSource task_source) {
180 task_source.WillRunTask();
181 return tracker_.RunAndPopNextTask(std::move(task_source));
182 }
183
184 // Calls tracker_->CompleteShutdown() on a new thread and expects it to block.
ExpectAsyncCompleteShutdownBlocks()185 void ExpectAsyncCompleteShutdownBlocks() {
186 ASSERT_FALSE(thread_calling_shutdown_);
187 ASSERT_TRUE(tracker_.HasShutdownStarted());
188 thread_calling_shutdown_ = std::make_unique<CallbackThread>(
189 BindOnce(&TaskTracker::CompleteShutdown, Unretained(&tracker_)));
190 thread_calling_shutdown_->Start();
191 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
192 VerifyAsyncShutdownInProgress();
193 }
194
WaitForAsyncIsShutdownComplete()195 void WaitForAsyncIsShutdownComplete() {
196 ASSERT_TRUE(thread_calling_shutdown_);
197 thread_calling_shutdown_->Join();
198 EXPECT_TRUE(thread_calling_shutdown_->has_returned());
199 EXPECT_TRUE(tracker_.IsShutdownComplete());
200 }
201
VerifyAsyncShutdownInProgress()202 void VerifyAsyncShutdownInProgress() {
203 ASSERT_TRUE(thread_calling_shutdown_);
204 EXPECT_FALSE(thread_calling_shutdown_->has_returned());
205 EXPECT_TRUE(tracker_.HasShutdownStarted());
206 EXPECT_FALSE(tracker_.IsShutdownComplete());
207 }
208
209 // Calls tracker_->FlushForTesting() on a new thread.
CallFlushFromAnotherThread()210 void CallFlushFromAnotherThread() {
211 threads_calling_flush_.push_back(std::make_unique<CallbackThread>(
212 BindOnce(&TaskTracker::FlushForTesting, Unretained(&tracker_))));
213 threads_calling_flush_.back()->Start();
214 }
215
WaitForAsyncFlushesReturned()216 void WaitForAsyncFlushesReturned() {
217 ASSERT_GE(threads_calling_flush_.size(), 1U);
218 for (auto& thread_calling_flush : threads_calling_flush_) {
219 thread_calling_flush->Join();
220 EXPECT_TRUE(thread_calling_flush->has_returned());
221 }
222 }
223
VerifyAsyncFlushesInProgress()224 void VerifyAsyncFlushesInProgress() {
225 ASSERT_GE(threads_calling_flush_.size(), 1U);
226 for (auto& thread_calling_flush : threads_calling_flush_) {
227 EXPECT_FALSE(thread_calling_flush->has_returned());
228 }
229 }
230
NumTasksExecuted()231 size_t NumTasksExecuted() {
232 CheckedAutoLock auto_lock(lock_);
233 return num_tasks_executed_;
234 }
235
236 TaskTracker tracker_;
237
238 private:
RunTaskCallback()239 void RunTaskCallback() {
240 CheckedAutoLock auto_lock(lock_);
241 ++num_tasks_executed_;
242 }
243
244 std::unique_ptr<CallbackThread> thread_calling_shutdown_;
245 std::vector<std::unique_ptr<CallbackThread>> threads_calling_flush_;
246
247 // Synchronizes accesses to |num_tasks_executed_|.
248 CheckedLock lock_;
249
250 size_t num_tasks_executed_ = 0;
251 };
252
253 #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \
254 do { \
255 SCOPED_TRACE(""); \
256 WaitForAsyncIsShutdownComplete(); \
257 } while (false)
258
259 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \
260 do { \
261 SCOPED_TRACE(""); \
262 VerifyAsyncShutdownInProgress(); \
263 } while (false)
264
265 #define WAIT_FOR_ASYNC_FLUSHES_RETURNED() \
266 do { \
267 SCOPED_TRACE(""); \
268 WaitForAsyncFlushesReturned(); \
269 } while (false)
270
271 #define VERIFY_ASYNC_FLUSHES_IN_PROGRESS() \
272 do { \
273 SCOPED_TRACE(""); \
274 VerifyAsyncFlushesInProgress(); \
275 } while (false)
276
277 } // namespace
278
TEST_P(ThreadPoolTaskTrackerTest,WillPostAndRunBeforeShutdown)279 TEST_P(ThreadPoolTaskTrackerTest, WillPostAndRunBeforeShutdown) {
280 Task task(CreateTask());
281
282 // Inform |task_tracker_| that |task| will be posted.
283 EXPECT_TRUE(tracker_.WillPostTask(&task, GetParam()));
284
285 // Run the task.
286 EXPECT_EQ(0U, NumTasksExecuted());
287
288 test::QueueAndRunTaskSource(
289 &tracker_, test::CreateSequenceWithTask(std::move(task), {GetParam()}));
290 EXPECT_EQ(1U, NumTasksExecuted());
291
292 // Shutdown() shouldn't block.
293 test::ShutdownTaskTracker(&tracker_);
294 }
295
TEST_P(ThreadPoolTaskTrackerTest,WillPostAndRunLongTaskBeforeShutdown)296 TEST_P(ThreadPoolTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) {
297 // Create a task that signals |task_running| and blocks until |task_barrier|
298 // is signaled.
299 TestWaitableEvent task_running;
300 TestWaitableEvent task_barrier;
301 Task blocked_task(FROM_HERE, BindLambdaForTesting([&]() {
302 task_running.Signal();
303 task_barrier.Wait();
304 }),
305 TimeTicks::Now(), TimeDelta());
306
307 // Inform |task_tracker_| that |blocked_task| will be posted.
308 auto sequence =
309 WillPostTaskAndQueueTaskSource(std::move(blocked_task), {GetParam()});
310 EXPECT_TRUE(sequence);
311
312 // Create a thread to run the task. Wait until the task starts running.
313 ThreadPostingAndRunningTask thread_running_task(&tracker_,
314 std::move(sequence));
315 thread_running_task.Start();
316 task_running.Wait();
317
318 // Initiate shutdown after the task has started to run.
319 tracker_.StartShutdown();
320
321 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) {
322 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress.
323 tracker_.CompleteShutdown();
324 } else {
325 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress.
326 ExpectAsyncCompleteShutdownBlocks();
327 }
328
329 // Unblock the task.
330 task_barrier.Signal();
331 thread_running_task.Join();
332
333 // Shutdown should now complete for a non CONTINUE_ON_SHUTDOWN task.
334 if (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
335 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
336 }
337
338 // Posting a BLOCK_SHUTDOWN task after shutdown must be allowed from a
339 // CONTINUE_ON_SHUTDOWN. Ref. https://crbug.com/1499644#c9 - #c16.
340 // Note: This test can't be TEST_P as non-CONTINUE_ON_SHUTDOWN `poster` would
341 // hang in CompleteShutdown().
TEST_F(ThreadPoolTaskTrackerTest,PostAfterShutdownFromContinueOnShutdown)342 TEST_F(ThreadPoolTaskTrackerTest, PostAfterShutdownFromContinueOnShutdown) {
343 // Dummy.
344 Task task{CreateTask()};
345
346 // Create a task that verifies the properties of this test.
347 TestWaitableEvent task_running;
348 TestWaitableEvent task_barrier;
349 Task poster(FROM_HERE, BindLambdaForTesting([&]() {
350 task_running.Signal();
351 task_barrier.Wait();
352
353 // No death when posting BLOCK_SHUTDOWN from
354 // CONTINUE_ON_SHUTDOWN.
355 EXPECT_TRUE(tracker_.IsShutdownComplete());
356 EXPECT_FALSE(tracker_.WillPostTask(
357 &task, TaskShutdownBehavior::BLOCK_SHUTDOWN));
358 }),
359 TimeTicks::Now(), TimeDelta());
360
361 // Inform |task_tracker_| that |blocked_task| will be posted.
362 auto sequence = WillPostTaskAndQueueTaskSource(
363 std::move(poster), TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN);
364 EXPECT_TRUE(sequence);
365
366 // Create a thread to run the task. Wait until the task starts running.
367 ThreadPostingAndRunningTask thread_running_task(&tracker_,
368 std::move(sequence));
369 thread_running_task.Start();
370 task_running.Wait();
371
372 // Fully shutdown `tracker_` Make sure it's complete before releasing the task
373 // to perform its test for CONTINUE_ON_SHUTDOWN.
374 test::ShutdownTaskTracker(&tracker_);
375
376 // Unblock the task and wait for it to perform its test.
377 task_barrier.Signal();
378 thread_running_task.Join();
379 }
380
381 // Verify that an undelayed task whose sequence wasn't queued does not block
382 // shutdown, regardless of its shutdown behavior.
TEST_P(ThreadPoolTaskTrackerTest,WillPostBeforeShutdownQueueDuringShutdown)383 TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownQueueDuringShutdown) {
384 // Simulate posting a undelayed task.
385 Task task{CreateTask()};
386 EXPECT_TRUE(tracker_.WillPostTask(&task, GetParam()));
387 auto sequence = test::CreateSequenceWithTask(std::move(task), {GetParam()});
388
389 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
390 // block shutdown.
391 auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource(
392 CreateTask(), {TaskShutdownBehavior::BLOCK_SHUTDOWN});
393 EXPECT_TRUE(block_shutdown_sequence);
394
395 // Start shutdown and try to complete it asynchronously.
396 tracker_.StartShutdown();
397 ExpectAsyncCompleteShutdownBlocks();
398
399 const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN;
400 if (should_run) {
401 test::QueueAndRunTaskSource(&tracker_, std::move(sequence));
402 EXPECT_EQ(1U, NumTasksExecuted());
403 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
404 } else {
405 EXPECT_FALSE(tracker_.RegisterTaskSource(std::move(sequence)));
406 }
407
408 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task.
409 RunAndPopNextTask(std::move(block_shutdown_sequence));
410 EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted());
411 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
412 }
413
TEST_P(ThreadPoolTaskTrackerTest,WillPostBeforeShutdownRunDuringShutdown)414 TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) {
415 // Inform |task_tracker_| that a task will be posted.
416 auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), {GetParam()});
417 EXPECT_TRUE(sequence);
418
419 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
420 // block shutdown.
421 auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource(
422 CreateTask(), {TaskShutdownBehavior::BLOCK_SHUTDOWN});
423 EXPECT_TRUE(block_shutdown_sequence);
424
425 // Start shutdown and try to complete it asynchronously.
426 tracker_.StartShutdown();
427 ExpectAsyncCompleteShutdownBlocks();
428
429 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it
430 // should be discarded.
431 EXPECT_EQ(0U, NumTasksExecuted());
432 const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN;
433
434 RunAndPopNextTask(std::move(sequence));
435 EXPECT_EQ(should_run ? 1U : 0U, NumTasksExecuted());
436 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
437
438 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task.
439 RunAndPopNextTask(std::move(block_shutdown_sequence));
440 EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted());
441 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
442 }
443
TEST_P(ThreadPoolTaskTrackerTest,WillPostBeforeShutdownRunAfterShutdown)444 TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) {
445 // Inform |task_tracker_| that a task will be posted.
446 auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), {GetParam()});
447 EXPECT_TRUE(sequence);
448
449 // Start shutdown.
450 tracker_.StartShutdown();
451 EXPECT_EQ(0U, NumTasksExecuted());
452
453 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
454 // Verify that CompleteShutdown() blocks.
455 ExpectAsyncCompleteShutdownBlocks();
456
457 // Run the task to unblock shutdown.
458 RunAndPopNextTask(std::move(sequence));
459 EXPECT_EQ(1U, NumTasksExecuted());
460 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
461
462 // It is not possible to test running a BLOCK_SHUTDOWN task posted before
463 // shutdown after shutdown because Shutdown() won't return if there are
464 // pending BLOCK_SHUTDOWN tasks.
465 } else {
466 tracker_.CompleteShutdown();
467
468 // The task shouldn't be allowed to run after shutdown.
469 RunAndPopNextTask(std::move(sequence));
470 EXPECT_EQ(0U, NumTasksExecuted());
471 }
472 }
473
TEST_P(ThreadPoolTaskTrackerTest,WillPostAndRunDuringShutdown)474 TEST_P(ThreadPoolTaskTrackerTest, WillPostAndRunDuringShutdown) {
475 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
476 // block shutdown.
477 auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource(
478 CreateTask(), {TaskShutdownBehavior::BLOCK_SHUTDOWN});
479 EXPECT_TRUE(block_shutdown_sequence);
480
481 // Start shutdown.
482 tracker_.StartShutdown();
483
484 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
485 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted.
486 auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), {GetParam()});
487 EXPECT_TRUE(sequence);
488
489 // Run the BLOCK_SHUTDOWN task.
490 EXPECT_EQ(0U, NumTasksExecuted());
491 RunAndPopNextTask(std::move(sequence));
492 EXPECT_EQ(1U, NumTasksExecuted());
493 } else {
494 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task.
495 auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), {GetParam()});
496 EXPECT_FALSE(sequence);
497
498 // Don't try to run the task, because it wasn't allowed to be posted.
499 }
500
501 // Verify that CompleteShutdown() blocks.
502 ExpectAsyncCompleteShutdownBlocks();
503
504 // Unblock shutdown by running |block_shutdown_task|.
505 RunAndPopNextTask(std::move(block_shutdown_sequence));
506 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U,
507 NumTasksExecuted());
508 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
509 }
510
TEST_P(ThreadPoolTaskTrackerTest,WillPostAfterShutdown)511 TEST_P(ThreadPoolTaskTrackerTest, WillPostAfterShutdown) {
512 test::ShutdownTaskTracker(&tracker_);
513
514 Task task(CreateTask());
515
516 // |task_tracker_| shouldn't allow a task to be posted after shutdown.
517 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
518 // When the task tracker is allowed to fizzle block shutdown tasks,
519 // WillPostTask will return false and leak the task.
520 tracker_.BeginFizzlingBlockShutdownTasks();
521 EXPECT_FALSE(tracker_.WillPostTask(&task, GetParam()));
522 tracker_.EndFizzlingBlockShutdownTasks();
523
524 // If a BLOCK_SHUTDOWN task is posted after shutdown without explicitly
525 // allowing BLOCK_SHUTDOWN task fizzling, WillPostTask DCHECKs to find
526 // ordering bugs.
527 EXPECT_DCHECK_DEATH(tracker_.WillPostTask(&task, GetParam()));
528 } else {
529 EXPECT_FALSE(tracker_.WillPostTask(&task, GetParam()));
530 }
531 }
532
533 // Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can
534 // AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't.
TEST_P(ThreadPoolTaskTrackerTest,SingletonAllowed)535 TEST_P(ThreadPoolTaskTrackerTest, SingletonAllowed) {
536 const bool can_use_singletons =
537 (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN);
538
539 Task task(FROM_HERE, BindOnce(&internal::AssertSingletonAllowed),
540 TimeTicks::Now(), TimeDelta());
541 auto sequence = WillPostTaskAndQueueTaskSource(std::move(task), {GetParam()});
542 EXPECT_TRUE(sequence);
543
544 // Running the task should fail iff the task isn't allowed to use singletons.
545 if (can_use_singletons) {
546 EXPECT_FALSE(RunAndPopNextTask(std::move(sequence)));
547 } else {
548 EXPECT_DCHECK_DEATH({ RunAndPopNextTask(std::move(sequence)); });
549 }
550 }
551
552 // Verify that AssertIOAllowed() succeeds only for a MayBlock() task.
TEST_P(ThreadPoolTaskTrackerTest,IOAllowed)553 TEST_P(ThreadPoolTaskTrackerTest, IOAllowed) {
554 // Allowed with MayBlock().
555 Task task_with_may_block(FROM_HERE, BindOnce([]() {
556 // Shouldn't fail.
557 ScopedBlockingCall scope_blocking_call(
558 FROM_HERE, BlockingType::WILL_BLOCK);
559 }),
560 TimeTicks::Now(), TimeDelta());
561 TaskTraits traits_with_may_block{MayBlock(), GetParam()};
562 auto sequence_with_may_block = WillPostTaskAndQueueTaskSource(
563 std::move(task_with_may_block), traits_with_may_block);
564 EXPECT_TRUE(sequence_with_may_block);
565 RunAndPopNextTask(std::move(sequence_with_may_block));
566
567 // Disallowed in the absence of MayBlock().
568 Task task_without_may_block(FROM_HERE, BindOnce([]() {
569 EXPECT_DCHECK_DEATH({
570 ScopedBlockingCall scope_blocking_call(
571 FROM_HERE, BlockingType::WILL_BLOCK);
572 });
573 }),
574 TimeTicks::Now(), TimeDelta());
575 TaskTraits traits_without_may_block = TaskTraits(GetParam());
576 auto sequence_without_may_block = WillPostTaskAndQueueTaskSource(
577 std::move(task_without_may_block), traits_without_may_block);
578 EXPECT_TRUE(sequence_without_may_block);
579 RunAndPopNextTask(std::move(sequence_without_may_block));
580 }
581
RunTaskRunnerCurrentDefaultHandleVerificationTask(TaskTracker * tracker,Task verify_task,TaskTraits traits,scoped_refptr<SequencedTaskRunner> task_runner,TaskSourceExecutionMode execution_mode)582 static void RunTaskRunnerCurrentDefaultHandleVerificationTask(
583 TaskTracker* tracker,
584 Task verify_task,
585 TaskTraits traits,
586 scoped_refptr<SequencedTaskRunner> task_runner,
587 TaskSourceExecutionMode execution_mode) {
588 // Pretend |verify_task| is posted to respect TaskTracker's contract.
589 EXPECT_TRUE(tracker->WillPostTask(&verify_task, traits.shutdown_behavior()));
590
591 // Confirm that the test conditions are right (no
592 // task runner CurrentDefaultHandles set already).
593 EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
594 EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
595
596 test::QueueAndRunTaskSource(
597 tracker,
598 test::CreateSequenceWithTask(std::move(verify_task), traits,
599 std::move(task_runner), execution_mode));
600
601 // task runner CurrentDefaultHandle state is reset outside of task's scope.
602 EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
603 EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
604 }
605
VerifyNoTaskRunnerCurrentDefaultHandle()606 static void VerifyNoTaskRunnerCurrentDefaultHandle() {
607 EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
608 EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
609 }
610
TEST_P(ThreadPoolTaskTrackerTest,TaskRunnerHandleIsNotSetOnParallel)611 TEST_P(ThreadPoolTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) {
612 // Create a task that will verify that TaskRunnerHandles are not set in its
613 // scope per no TaskRunner ref being set to it.
614 Task verify_task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerCurrentDefaultHandle),
615 TimeTicks::Now(), TimeDelta());
616
617 RunTaskRunnerCurrentDefaultHandleVerificationTask(
618 &tracker_, std::move(verify_task), TaskTraits(GetParam()), nullptr,
619 TaskSourceExecutionMode::kParallel);
620 }
621
VerifySequencedTaskRunnerCurrentDefaultHandle(const SequencedTaskRunner * expected_task_runner)622 static void VerifySequencedTaskRunnerCurrentDefaultHandle(
623 const SequencedTaskRunner* expected_task_runner) {
624 EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
625 EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
626 EXPECT_EQ(expected_task_runner, SequencedTaskRunner::GetCurrentDefault());
627 }
628
TEST_P(ThreadPoolTaskTrackerTest,SequencedTaskRunnerHasCurrentDefaultOnSequenced)629 TEST_P(ThreadPoolTaskTrackerTest,
630 SequencedTaskRunnerHasCurrentDefaultOnSequenced) {
631 scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner);
632
633 // Create a task that will verify that
634 // SequencedTaskRunner::CurrentDefaultHandle is properly set to
635 // |test_task_runner| in its scope per |sequenced_task_runner_ref| being set
636 // to it.
637 Task verify_task(FROM_HERE,
638 BindOnce(&VerifySequencedTaskRunnerCurrentDefaultHandle,
639 Unretained(test_task_runner.get())),
640 TimeTicks::Now(), TimeDelta());
641
642 RunTaskRunnerCurrentDefaultHandleVerificationTask(
643 &tracker_, std::move(verify_task), TaskTraits(GetParam()),
644 std::move(test_task_runner), TaskSourceExecutionMode::kSequenced);
645 }
646
VerifySingleThreadTaskRunnerCurrentDefaultHandle(const SingleThreadTaskRunner * expected_task_runner)647 static void VerifySingleThreadTaskRunnerCurrentDefaultHandle(
648 const SingleThreadTaskRunner* expected_task_runner) {
649 EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault());
650 // SequencedTaskRunner::CurrentDefaultHandle inherits
651 // SingleThreadTaskRunner::CurrentDefaultHandle for thread.
652 EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
653 EXPECT_EQ(expected_task_runner, SingleThreadTaskRunner::GetCurrentDefault());
654 }
655
TEST_P(ThreadPoolTaskTrackerTest,SingleThreadTaskRunnerCurrentDefaultHandleIsSetOnSingleThreaded)656 TEST_P(ThreadPoolTaskTrackerTest,
657 SingleThreadTaskRunnerCurrentDefaultHandleIsSetOnSingleThreaded) {
658 scoped_refptr<SingleThreadTaskRunner> test_task_runner(
659 new TestSimpleTaskRunner);
660
661 // Create a task that will verify that
662 // SingleThreadTaskRunner::CurrentDefaultHandle is properly set to
663 // |test_task_runner| in its scope per |single_thread_task_runner_ref| being
664 // set on it.
665 Task verify_task(FROM_HERE,
666 BindOnce(&VerifySingleThreadTaskRunnerCurrentDefaultHandle,
667 Unretained(test_task_runner.get())),
668 TimeTicks::Now(), TimeDelta());
669
670 RunTaskRunnerCurrentDefaultHandleVerificationTask(
671 &tracker_, std::move(verify_task), TaskTraits(GetParam()),
672 std::move(test_task_runner), TaskSourceExecutionMode::kSingleThread);
673 }
674
TEST_P(ThreadPoolTaskTrackerTest,FlushPendingDelayedTask)675 TEST_P(ThreadPoolTaskTrackerTest, FlushPendingDelayedTask) {
676 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
677 tracker_.WillPostTask(&delayed_task, GetParam());
678 // FlushForTesting() should return even if the delayed task didn't run.
679 tracker_.FlushForTesting();
680 }
681
TEST_P(ThreadPoolTaskTrackerTest,FlushAsyncForTestingPendingDelayedTask)682 TEST_P(ThreadPoolTaskTrackerTest, FlushAsyncForTestingPendingDelayedTask) {
683 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
684 tracker_.WillPostTask(&delayed_task, GetParam());
685 // FlushAsyncForTesting() should callback even if the delayed task didn't run.
686 bool called_back = false;
687 tracker_.FlushAsyncForTesting(
688 BindOnce([](bool* called_back) { *called_back = true; },
689 Unretained(&called_back)));
690 EXPECT_TRUE(called_back);
691 }
692
TEST_P(ThreadPoolTaskTrackerTest,FlushPendingUndelayedTask)693 TEST_P(ThreadPoolTaskTrackerTest, FlushPendingUndelayedTask) {
694 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
695 auto undelayed_sequence =
696 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
697
698 // FlushForTesting() shouldn't return before the undelayed task runs.
699 CallFlushFromAnotherThread();
700 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
701 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
702
703 // FlushForTesting() should return after the undelayed task runs.
704 RunAndPopNextTask(std::move(undelayed_sequence));
705 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
706 }
707
TEST_P(ThreadPoolTaskTrackerTest,MultipleFlushes)708 TEST_P(ThreadPoolTaskTrackerTest, MultipleFlushes) {
709 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
710 auto undelayed_sequence =
711 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
712
713 // Multiple flushes should all unwind after the task runs.
714 CallFlushFromAnotherThread();
715 CallFlushFromAnotherThread();
716 CallFlushFromAnotherThread();
717 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
718 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
719
720 RunAndPopNextTask(std::move(undelayed_sequence));
721 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
722 }
723
TEST_P(ThreadPoolTaskTrackerTest,FlushAsyncForTestingPendingUndelayedTask)724 TEST_P(ThreadPoolTaskTrackerTest, FlushAsyncForTestingPendingUndelayedTask) {
725 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
726 auto undelayed_sequence =
727 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
728
729 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
730 TestWaitableEvent event;
731 tracker_.FlushAsyncForTesting(
732 BindOnce(&TestWaitableEvent::Signal, Unretained(&event)));
733 EXPECT_FALSE(event.IsSignaled());
734
735 // FlushAsyncForTesting() should callback after the undelayed task runs.
736 RunAndPopNextTask(std::move(undelayed_sequence));
737 event.Wait();
738 }
739
TEST_P(ThreadPoolTaskTrackerTest,MultipleFlushAsyncForTesting)740 TEST_P(ThreadPoolTaskTrackerTest, MultipleFlushAsyncForTesting) {
741 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
742 auto undelayed_sequence =
743 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
744
745 TestWaitableEvent three_callbacks_ran;
746 auto on_flush_done = BarrierClosure(
747 3,
748 BindOnce(&TestWaitableEvent::Signal, Unretained(&three_callbacks_ran)));
749 tracker_.FlushAsyncForTesting(on_flush_done);
750 tracker_.FlushAsyncForTesting(on_flush_done);
751 tracker_.FlushAsyncForTesting(on_flush_done);
752 EXPECT_FALSE(three_callbacks_ran.IsSignaled());
753
754 // FlushAsyncForTesting() should callback after the undelayed task runs.
755 RunAndPopNextTask(std::move(undelayed_sequence));
756 three_callbacks_ran.Wait();
757 }
758
TEST_P(ThreadPoolTaskTrackerTest,PostTaskDuringFlush)759 TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlush) {
760 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
761 auto undelayed_sequence =
762 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
763
764 // FlushForTesting() shouldn't return before the undelayed task runs.
765 CallFlushFromAnotherThread();
766 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
767 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
768
769 // Simulate posting another undelayed task.
770 Task other_undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(),
771 TimeDelta());
772 auto other_undelayed_sequence = WillPostTaskAndQueueTaskSource(
773 std::move(other_undelayed_task), {GetParam()});
774
775 // Run the first undelayed task.
776 RunAndPopNextTask(std::move(undelayed_sequence));
777
778 // FlushForTesting() shouldn't return before the second undelayed task runs.
779 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
780 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
781
782 // FlushForTesting() should return after the second undelayed task runs.
783 RunAndPopNextTask(std::move(other_undelayed_sequence));
784 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
785 }
786
TEST_P(ThreadPoolTaskTrackerTest,PostTaskDuringFlushAsyncForTesting)787 TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) {
788 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
789 auto undelayed_sequence =
790 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
791
792 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
793 TestWaitableEvent event;
794 tracker_.FlushAsyncForTesting(
795 BindOnce(&TestWaitableEvent::Signal, Unretained(&event)));
796 EXPECT_FALSE(event.IsSignaled());
797
798 // Simulate posting another undelayed task.
799 Task other_undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(),
800 TimeDelta());
801 auto other_undelayed_sequence = WillPostTaskAndQueueTaskSource(
802 std::move(other_undelayed_task), {GetParam()});
803
804 // Run the first undelayed task.
805 RunAndPopNextTask(std::move(undelayed_sequence));
806
807 // FlushAsyncForTesting() shouldn't callback before the second undelayed task
808 // runs.
809 EXPECT_FALSE(event.IsSignaled());
810
811 // FlushAsyncForTesting() should callback after the second undelayed task
812 // runs.
813 RunAndPopNextTask(std::move(other_undelayed_sequence));
814 event.Wait();
815 }
816
TEST_P(ThreadPoolTaskTrackerTest,RunDelayedTaskDuringFlush)817 TEST_P(ThreadPoolTaskTrackerTest, RunDelayedTaskDuringFlush) {
818 // Simulate posting a delayed and an undelayed task.
819 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
820 auto delayed_sequence =
821 WillPostTaskAndQueueTaskSource(std::move(delayed_task), {GetParam()});
822 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
823 auto undelayed_sequence =
824 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
825
826 // FlushForTesting() shouldn't return before the undelayed task runs.
827 CallFlushFromAnotherThread();
828 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
829 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
830
831 // Run the delayed task.
832 RunAndPopNextTask(std::move(delayed_sequence));
833
834 // FlushForTesting() shouldn't return since there is still a pending undelayed
835 // task.
836 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
837 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
838
839 // Run the undelayed task.
840 RunAndPopNextTask(std::move(undelayed_sequence));
841
842 // FlushForTesting() should now ESreturn.
843 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
844 }
845
TEST_P(ThreadPoolTaskTrackerTest,RunDelayedTaskDuringFlushAsyncForTesting)846 TEST_P(ThreadPoolTaskTrackerTest, RunDelayedTaskDuringFlushAsyncForTesting) {
847 // Simulate posting a delayed and an undelayed task.
848 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
849 auto delayed_sequence =
850 WillPostTaskAndQueueTaskSource(std::move(delayed_task), {GetParam()});
851 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
852 auto undelayed_sequence =
853 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
854
855 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
856 TestWaitableEvent event;
857 tracker_.FlushAsyncForTesting(
858 BindOnce(&TestWaitableEvent::Signal, Unretained(&event)));
859 EXPECT_FALSE(event.IsSignaled());
860
861 // Run the delayed task.
862 RunAndPopNextTask(std::move(delayed_sequence));
863
864 // FlushAsyncForTesting() shouldn't callback since there is still a pending
865 // undelayed task.
866 EXPECT_FALSE(event.IsSignaled());
867
868 // Run the undelayed task.
869 RunAndPopNextTask(std::move(undelayed_sequence));
870
871 // FlushAsyncForTesting() should now callback.
872 event.Wait();
873 }
874
TEST_P(ThreadPoolTaskTrackerTest,FlushAfterShutdown)875 TEST_P(ThreadPoolTaskTrackerTest, FlushAfterShutdown) {
876 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
877 return;
878
879 // Simulate posting a task.
880 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
881 tracker_.WillPostTask(&undelayed_task, GetParam());
882
883 // Shutdown() should return immediately since there are no pending
884 // BLOCK_SHUTDOWN tasks.
885 test::ShutdownTaskTracker(&tracker_);
886
887 // FlushForTesting() should return immediately after shutdown, even if an
888 // undelayed task hasn't run.
889 tracker_.FlushForTesting();
890 }
891
TEST_P(ThreadPoolTaskTrackerTest,FlushAfterShutdownAsync)892 TEST_P(ThreadPoolTaskTrackerTest, FlushAfterShutdownAsync) {
893 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
894 return;
895
896 // Simulate posting a task.
897 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
898 tracker_.WillPostTask(&undelayed_task, GetParam());
899
900 // Shutdown() should return immediately since there are no pending
901 // BLOCK_SHUTDOWN tasks.
902 test::ShutdownTaskTracker(&tracker_);
903
904 // FlushForTesting() should callback immediately after shutdown, even if an
905 // undelayed task hasn't run.
906 bool called_back = false;
907 tracker_.FlushAsyncForTesting(
908 BindOnce([](bool* called_back) { *called_back = true; },
909 Unretained(&called_back)));
910 EXPECT_TRUE(called_back);
911 }
912
TEST_P(ThreadPoolTaskTrackerTest,ShutdownDuringFlush)913 TEST_P(ThreadPoolTaskTrackerTest, ShutdownDuringFlush) {
914 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
915 return;
916
917 // Simulate posting a task.
918 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
919 auto undelayed_sequence =
920 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
921
922 // FlushForTesting() shouldn't return before the undelayed task runs or
923 // shutdown completes.
924 CallFlushFromAnotherThread();
925 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
926 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
927
928 // Shutdown() should return immediately since there are no pending
929 // BLOCK_SHUTDOWN tasks.
930 test::ShutdownTaskTracker(&tracker_);
931
932 // FlushForTesting() should now return, even if an undelayed task hasn't run.
933 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
934 }
935
TEST_P(ThreadPoolTaskTrackerTest,ShutdownDuringFlushAsyncForTesting)936 TEST_P(ThreadPoolTaskTrackerTest, ShutdownDuringFlushAsyncForTesting) {
937 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
938 return;
939
940 // Simulate posting a task.
941 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
942 auto undelayed_sequence =
943 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
944
945 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs or
946 // shutdown completes.
947 TestWaitableEvent event;
948 tracker_.FlushAsyncForTesting(
949 BindOnce(&TestWaitableEvent::Signal, Unretained(&event)));
950 EXPECT_FALSE(event.IsSignaled());
951
952 // Shutdown() should return immediately since there are no pending
953 // BLOCK_SHUTDOWN tasks.
954 test::ShutdownTaskTracker(&tracker_);
955
956 // FlushAsyncForTesting() should now callback, even if an undelayed task
957 // hasn't run.
958 event.Wait();
959 }
960
TEST_P(ThreadPoolTaskTrackerTest,PostTasksDoNotBlockShutdown)961 TEST_P(ThreadPoolTaskTrackerTest, PostTasksDoNotBlockShutdown) {
962 // Simulate posting an undelayed task.
963 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
964 EXPECT_TRUE(tracker_.WillPostTask(&undelayed_task, GetParam()));
965
966 // Since no sequence was queued, a call to Shutdown() should not hang.
967 test::ShutdownTaskTracker(&tracker_);
968 }
969
970 // Verify that a delayed task does not block shutdown once it's run, regardless
971 // of its shutdown behavior.
TEST_P(ThreadPoolTaskTrackerTest,DelayedRunTasks)972 TEST_P(ThreadPoolTaskTrackerTest, DelayedRunTasks) {
973 // Simulate posting a delayed task.
974 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
975 auto sequence =
976 WillPostTaskAndQueueTaskSource(std::move(delayed_task), {GetParam()});
977 EXPECT_TRUE(sequence);
978
979 RunAndPopNextTask(std::move(sequence));
980
981 // Since the delayed task doesn't block shutdown, a call to Shutdown() should
982 // not hang.
983 test::ShutdownTaskTracker(&tracker_);
984 }
985
986 INSTANTIATE_TEST_SUITE_P(
987 ContinueOnShutdown,
988 ThreadPoolTaskTrackerTest,
989 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
990 INSTANTIATE_TEST_SUITE_P(
991 SkipOnShutdown,
992 ThreadPoolTaskTrackerTest,
993 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
994 INSTANTIATE_TEST_SUITE_P(
995 BlockShutdown,
996 ThreadPoolTaskTrackerTest,
997 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN));
998
999 namespace {
1000
ExpectSequenceToken(SequenceToken sequence_token)1001 void ExpectSequenceToken(SequenceToken sequence_token) {
1002 EXPECT_EQ(sequence_token, SequenceToken::GetForCurrentThread());
1003 }
1004
1005 } // namespace
1006
1007 // Verify that SequenceToken::GetForCurrentThread() returns the Sequence's token
1008 // when a Task runs.
TEST_F(ThreadPoolTaskTrackerTest,CurrentSequenceToken)1009 TEST_F(ThreadPoolTaskTrackerTest, CurrentSequenceToken) {
1010 scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(
1011 TaskTraits(), nullptr, TaskSourceExecutionMode::kParallel);
1012
1013 const SequenceToken sequence_token = sequence->token();
1014 Task task(FROM_HERE, BindOnce(&ExpectSequenceToken, sequence_token),
1015 TimeTicks::Now(), TimeDelta());
1016 tracker_.WillPostTask(&task, sequence->shutdown_behavior());
1017
1018 {
1019 Sequence::Transaction sequence_transaction(sequence->BeginTransaction());
1020 sequence_transaction.WillPushImmediateTask();
1021 sequence_transaction.PushImmediateTask(std::move(task));
1022
1023 EXPECT_NE(SequenceToken::GetForCurrentThread(), sequence_token);
1024 }
1025
1026 test::QueueAndRunTaskSource(&tracker_, std::move(sequence));
1027 EXPECT_NE(SequenceToken::GetForCurrentThread(), sequence_token);
1028 }
1029
TEST_F(ThreadPoolTaskTrackerTest,LoadWillPostAndRunBeforeShutdown)1030 TEST_F(ThreadPoolTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) {
1031 // Post and run tasks asynchronously.
1032 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
1033
1034 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1035 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1036 &tracker_,
1037 MakeRefCounted<Sequence>(
1038 TaskTraits{TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, nullptr,
1039 TaskSourceExecutionMode::kParallel),
1040 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true,
1041 CreateTask()));
1042 threads.back()->Start();
1043
1044 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1045 &tracker_,
1046 MakeRefCounted<Sequence>(
1047 TaskTraits{TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, nullptr,
1048 TaskSourceExecutionMode::kParallel),
1049 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true,
1050 CreateTask()));
1051 threads.back()->Start();
1052
1053 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1054 &tracker_,
1055 MakeRefCounted<Sequence>(
1056 TaskTraits{TaskShutdownBehavior::BLOCK_SHUTDOWN}, nullptr,
1057 TaskSourceExecutionMode::kParallel),
1058 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true,
1059 CreateTask()));
1060 threads.back()->Start();
1061 }
1062
1063 for (const auto& thread : threads)
1064 thread->Join();
1065
1066 // Expect all tasks to be executed.
1067 EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted());
1068
1069 // Should return immediately because no tasks are blocking shutdown.
1070 test::ShutdownTaskTracker(&tracker_);
1071 }
1072
TEST_F(ThreadPoolTaskTrackerTest,LoadWillPostBeforeShutdownAndRunDuringShutdown)1073 TEST_F(ThreadPoolTaskTrackerTest,
1074 LoadWillPostBeforeShutdownAndRunDuringShutdown) {
1075 constexpr TaskTraits traits_continue_on_shutdown =
1076 TaskTraits(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN);
1077 constexpr TaskTraits traits_skip_on_shutdown =
1078 TaskTraits(TaskShutdownBehavior::SKIP_ON_SHUTDOWN);
1079 constexpr TaskTraits traits_block_shutdown =
1080 TaskTraits(TaskShutdownBehavior::BLOCK_SHUTDOWN);
1081
1082 // Post tasks asynchronously.
1083 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads;
1084 {
1085 std::vector<scoped_refptr<Sequence>> sequences_continue_on_shutdown;
1086 std::vector<scoped_refptr<Sequence>> sequences_skip_on_shutdown;
1087 std::vector<scoped_refptr<Sequence>> sequences_block_shutdown;
1088 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1089 sequences_continue_on_shutdown.push_back(
1090 MakeRefCounted<Sequence>(traits_continue_on_shutdown, nullptr,
1091 TaskSourceExecutionMode::kParallel));
1092 sequences_skip_on_shutdown.push_back(
1093 MakeRefCounted<Sequence>(traits_skip_on_shutdown, nullptr,
1094 TaskSourceExecutionMode::kParallel));
1095 sequences_block_shutdown.push_back(MakeRefCounted<Sequence>(
1096 traits_block_shutdown, nullptr, TaskSourceExecutionMode::kParallel));
1097 }
1098
1099 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1100 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1101 &tracker_, sequences_continue_on_shutdown[i],
1102 ThreadPostingAndRunningTask::Action::WILL_POST, true, CreateTask()));
1103 post_threads.back()->Start();
1104
1105 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1106 &tracker_, sequences_skip_on_shutdown[i],
1107 ThreadPostingAndRunningTask::Action::WILL_POST, true, CreateTask()));
1108 post_threads.back()->Start();
1109
1110 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1111 &tracker_, sequences_block_shutdown[i],
1112 ThreadPostingAndRunningTask::Action::WILL_POST, true, CreateTask()));
1113 post_threads.back()->Start();
1114 }
1115 }
1116
1117 for (const auto& thread : post_threads)
1118 thread->Join();
1119
1120 // Start shutdown and try to complete shutdown asynchronously.
1121 tracker_.StartShutdown();
1122 ExpectAsyncCompleteShutdownBlocks();
1123
1124 // Run tasks asynchronously.
1125 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads;
1126 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1127 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1128 &tracker_, post_threads[i * 3]->TakeTaskSource()));
1129 run_threads.back()->Start();
1130
1131 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1132 &tracker_, post_threads[i * 3 + 1]->TakeTaskSource()));
1133 run_threads.back()->Start();
1134
1135 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1136 &tracker_, post_threads[i * 3 + 2]->TakeTaskSource()));
1137 run_threads.back()->Start();
1138 }
1139
1140 for (const auto& thread : run_threads)
1141 thread->Join();
1142
1143 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
1144
1145 // Expect BLOCK_SHUTDOWN tasks to have been executed.
1146 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
1147 }
1148
TEST_F(ThreadPoolTaskTrackerTest,LoadWillPostAndRunDuringShutdown)1149 TEST_F(ThreadPoolTaskTrackerTest, LoadWillPostAndRunDuringShutdown) {
1150 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
1151 // block shutdown.
1152 auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource(
1153 CreateTask(), {TaskShutdownBehavior::BLOCK_SHUTDOWN});
1154 EXPECT_TRUE(block_shutdown_sequence);
1155
1156 // Start shutdown and try to complete it asynchronously.
1157 tracker_.StartShutdown();
1158 ExpectAsyncCompleteShutdownBlocks();
1159
1160 // Post and run tasks asynchronously.
1161 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
1162
1163 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1164 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1165 &tracker_,
1166 MakeRefCounted<Sequence>(
1167 TaskTraits{TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, nullptr,
1168 TaskSourceExecutionMode::kParallel),
1169 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false,
1170 CreateTask()));
1171 threads.back()->Start();
1172
1173 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1174 &tracker_,
1175 MakeRefCounted<Sequence>(
1176 TaskTraits{TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, nullptr,
1177 TaskSourceExecutionMode::kParallel),
1178 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false,
1179 CreateTask()));
1180 threads.back()->Start();
1181
1182 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1183 &tracker_,
1184 MakeRefCounted<Sequence>(
1185 TaskTraits{TaskShutdownBehavior::BLOCK_SHUTDOWN}, nullptr,
1186 TaskSourceExecutionMode::kParallel),
1187 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true,
1188 CreateTask()));
1189 threads.back()->Start();
1190 }
1191
1192 for (const auto& thread : threads)
1193 thread->Join();
1194
1195 // Expect BLOCK_SHUTDOWN tasks to have been executed.
1196 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
1197
1198 // Shutdown() shouldn't return before |block_shutdown_task| is executed.
1199 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
1200
1201 // Unblock shutdown by running |block_shutdown_task|.
1202 RunAndPopNextTask(std::move(block_shutdown_sequence));
1203 EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted());
1204 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
1205 }
1206
1207 // Verify that RunAndPopNextTask() returns the sequence from which it ran a task
1208 // when it can be rescheduled.
TEST_F(ThreadPoolTaskTrackerTest,RunAndPopNextTaskReturnsSequenceToReschedule)1209 TEST_F(ThreadPoolTaskTrackerTest,
1210 RunAndPopNextTaskReturnsSequenceToReschedule) {
1211 TaskTraits default_traits;
1212 Task task_1(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
1213 EXPECT_TRUE(
1214 tracker_.WillPostTask(&task_1, default_traits.shutdown_behavior()));
1215 Task task_2(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
1216 EXPECT_TRUE(
1217 tracker_.WillPostTask(&task_2, default_traits.shutdown_behavior()));
1218
1219 scoped_refptr<Sequence> sequence =
1220 test::CreateSequenceWithTask(std::move(task_1), default_traits);
1221 {
1222 auto transaction = sequence->BeginTransaction();
1223 transaction.WillPushImmediateTask();
1224 transaction.PushImmediateTask(std::move(task_2));
1225 }
1226 EXPECT_EQ(sequence,
1227 test::QueueAndRunTaskSource(&tracker_, sequence).Unregister());
1228 }
1229
1230 namespace {
1231
1232 class WaitAllowedTestThread : public SimpleThread {
1233 public:
WaitAllowedTestThread()1234 WaitAllowedTestThread() : SimpleThread("WaitAllowedTestThread") {}
1235 WaitAllowedTestThread(const WaitAllowedTestThread&) = delete;
1236 WaitAllowedTestThread& operator=(const WaitAllowedTestThread&) = delete;
1237
1238 private:
Run()1239 void Run() override {
1240 auto task_tracker = std::make_unique<TaskTracker>();
1241
1242 // Waiting is allowed by default. Expect TaskTracker to disallow it before
1243 // running a task without the WithBaseSyncPrimitives() trait.
1244 internal::AssertBaseSyncPrimitivesAllowed();
1245 Task task_without_sync_primitives(
1246 FROM_HERE, BindOnce([]() {
1247 EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
1248 }),
1249 TimeTicks::Now(), TimeDelta());
1250 TaskTraits default_traits;
1251 EXPECT_TRUE(task_tracker->WillPostTask(&task_without_sync_primitives,
1252 default_traits.shutdown_behavior()));
1253 auto sequence_without_sync_primitives = test::CreateSequenceWithTask(
1254 std::move(task_without_sync_primitives), default_traits);
1255 test::QueueAndRunTaskSource(task_tracker.get(),
1256 std::move(sequence_without_sync_primitives));
1257
1258 // Expect TaskTracker to keep waiting allowed when running a task with the
1259 // WithBaseSyncPrimitives() trait.
1260 internal::AssertBaseSyncPrimitivesAllowed();
1261 Task task_with_sync_primitives(
1262 FROM_HERE, BindOnce([]() {
1263 // Shouldn't fail.
1264 internal::AssertBaseSyncPrimitivesAllowed();
1265 }),
1266 TimeTicks::Now(), TimeDelta());
1267 TaskTraits traits_with_sync_primitives =
1268 TaskTraits(WithBaseSyncPrimitives());
1269 EXPECT_TRUE(task_tracker->WillPostTask(
1270 &task_with_sync_primitives,
1271 traits_with_sync_primitives.shutdown_behavior()));
1272 auto sequence_with_sync_primitives = test::CreateSequenceWithTask(
1273 std::move(task_with_sync_primitives), traits_with_sync_primitives);
1274 test::QueueAndRunTaskSource(task_tracker.get(),
1275 std::move(sequence_with_sync_primitives));
1276
1277 ScopedAllowBaseSyncPrimitivesForTesting
1278 allow_wait_in_task_tracker_destructor;
1279 task_tracker.reset();
1280 }
1281 };
1282
1283 } // namespace
1284
1285 // Verify that AssertIOAllowed() succeeds only for a WithBaseSyncPrimitives()
1286 // task.
TEST(ThreadPoolTaskTrackerWaitAllowedTest,WaitAllowed)1287 TEST(ThreadPoolTaskTrackerWaitAllowedTest, WaitAllowed) {
1288 // Run the test on the separate thread since it is not possible to reset the
1289 // "wait allowed" bit of a thread without being a friend of
1290 // ThreadRestrictions.
1291 GTEST_FLAG_SET(death_test_style, "threadsafe");
1292 WaitAllowedTestThread wait_allowed_test_thread;
1293 wait_allowed_test_thread.Start();
1294 wait_allowed_test_thread.Join();
1295 }
1296
1297 } // namespace internal
1298 } // namespace base
1299