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 of 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 // Verify that an undelayed task whose sequence wasn't queued does not block
339 // shutdown, regardless of its shutdown behavior.
TEST_P(ThreadPoolTaskTrackerTest,WillPostBeforeShutdownQueueDuringShutdown)340 TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownQueueDuringShutdown) {
341 // Simulate posting a undelayed task.
342 Task task{CreateTask()};
343 EXPECT_TRUE(tracker_.WillPostTask(&task, GetParam()));
344 auto sequence = test::CreateSequenceWithTask(std::move(task), {GetParam()});
345
346 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
347 // block shutdown.
348 auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource(
349 CreateTask(), {TaskShutdownBehavior::BLOCK_SHUTDOWN});
350 EXPECT_TRUE(block_shutdown_sequence);
351
352 // Start shutdown and try to complete it asynchronously.
353 tracker_.StartShutdown();
354 ExpectAsyncCompleteShutdownBlocks();
355
356 const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN;
357 if (should_run) {
358 test::QueueAndRunTaskSource(&tracker_, std::move(sequence));
359 EXPECT_EQ(1U, NumTasksExecuted());
360 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
361 } else {
362 EXPECT_FALSE(tracker_.RegisterTaskSource(std::move(sequence)));
363 }
364
365 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task.
366 RunAndPopNextTask(std::move(block_shutdown_sequence));
367 EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted());
368 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
369 }
370
TEST_P(ThreadPoolTaskTrackerTest,WillPostBeforeShutdownRunDuringShutdown)371 TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) {
372 // Inform |task_tracker_| that a task will be posted.
373 auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), {GetParam()});
374 EXPECT_TRUE(sequence);
375
376 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
377 // block shutdown.
378 auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource(
379 CreateTask(), {TaskShutdownBehavior::BLOCK_SHUTDOWN});
380 EXPECT_TRUE(block_shutdown_sequence);
381
382 // Start shutdown and try to complete it asynchronously.
383 tracker_.StartShutdown();
384 ExpectAsyncCompleteShutdownBlocks();
385
386 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it
387 // should be discarded.
388 EXPECT_EQ(0U, NumTasksExecuted());
389 const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN;
390
391 RunAndPopNextTask(std::move(sequence));
392 EXPECT_EQ(should_run ? 1U : 0U, NumTasksExecuted());
393 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
394
395 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task.
396 RunAndPopNextTask(std::move(block_shutdown_sequence));
397 EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted());
398 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
399 }
400
TEST_P(ThreadPoolTaskTrackerTest,WillPostBeforeShutdownRunAfterShutdown)401 TEST_P(ThreadPoolTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) {
402 // Inform |task_tracker_| that a task will be posted.
403 auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), {GetParam()});
404 EXPECT_TRUE(sequence);
405
406 // Start shutdown.
407 tracker_.StartShutdown();
408 EXPECT_EQ(0U, NumTasksExecuted());
409
410 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
411 // Verify that CompleteShutdown() blocks.
412 ExpectAsyncCompleteShutdownBlocks();
413
414 // Run the task to unblock shutdown.
415 RunAndPopNextTask(std::move(sequence));
416 EXPECT_EQ(1U, NumTasksExecuted());
417 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
418
419 // It is not possible to test running a BLOCK_SHUTDOWN task posted before
420 // shutdown after shutdown because Shutdown() won't return if there are
421 // pending BLOCK_SHUTDOWN tasks.
422 } else {
423 tracker_.CompleteShutdown();
424
425 // The task shouldn't be allowed to run after shutdown.
426 RunAndPopNextTask(std::move(sequence));
427 EXPECT_EQ(0U, NumTasksExecuted());
428 }
429 }
430
TEST_P(ThreadPoolTaskTrackerTest,WillPostAndRunDuringShutdown)431 TEST_P(ThreadPoolTaskTrackerTest, WillPostAndRunDuringShutdown) {
432 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
433 // block shutdown.
434 auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource(
435 CreateTask(), {TaskShutdownBehavior::BLOCK_SHUTDOWN});
436 EXPECT_TRUE(block_shutdown_sequence);
437
438 // Start shutdown.
439 tracker_.StartShutdown();
440
441 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
442 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted.
443 auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), {GetParam()});
444 EXPECT_TRUE(sequence);
445
446 // Run the BLOCK_SHUTDOWN task.
447 EXPECT_EQ(0U, NumTasksExecuted());
448 RunAndPopNextTask(std::move(sequence));
449 EXPECT_EQ(1U, NumTasksExecuted());
450 } else {
451 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task.
452 auto sequence = WillPostTaskAndQueueTaskSource(CreateTask(), {GetParam()});
453 EXPECT_FALSE(sequence);
454
455 // Don't try to run the task, because it wasn't allowed to be posted.
456 }
457
458 // Verify that CompleteShutdown() blocks.
459 ExpectAsyncCompleteShutdownBlocks();
460
461 // Unblock shutdown by running |block_shutdown_task|.
462 RunAndPopNextTask(std::move(block_shutdown_sequence));
463 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U,
464 NumTasksExecuted());
465 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
466 }
467
TEST_P(ThreadPoolTaskTrackerTest,WillPostAfterShutdown)468 TEST_P(ThreadPoolTaskTrackerTest, WillPostAfterShutdown) {
469 test::ShutdownTaskTracker(&tracker_);
470
471 Task task(CreateTask());
472
473 // |task_tracker_| shouldn't allow a task to be posted after shutdown.
474 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
475 // When the task tracker is allowed to fizzle block shutdown tasks,
476 // WillPostTask will return false and leak the task.
477 tracker_.BeginFizzlingBlockShutdownTasks();
478 EXPECT_FALSE(tracker_.WillPostTask(&task, GetParam()));
479 tracker_.EndFizzlingBlockShutdownTasks();
480
481 // If a BLOCK_SHUTDOWN task is posted after shutdown without explicitly
482 // allowing BLOCK_SHUTDOWN task fizzling, WillPostTask DCHECKs to find
483 // ordering bugs.
484 EXPECT_DCHECK_DEATH(tracker_.WillPostTask(&task, GetParam()));
485 } else {
486 EXPECT_FALSE(tracker_.WillPostTask(&task, GetParam()));
487 }
488 }
489
490 // Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can
491 // AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't.
TEST_P(ThreadPoolTaskTrackerTest,SingletonAllowed)492 TEST_P(ThreadPoolTaskTrackerTest, SingletonAllowed) {
493 const bool can_use_singletons =
494 (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN);
495
496 Task task(FROM_HERE, BindOnce(&internal::AssertSingletonAllowed),
497 TimeTicks::Now(), TimeDelta());
498 auto sequence = WillPostTaskAndQueueTaskSource(std::move(task), {GetParam()});
499 EXPECT_TRUE(sequence);
500
501 // Running the task should fail iff the task isn't allowed to use singletons.
502 if (can_use_singletons) {
503 EXPECT_FALSE(RunAndPopNextTask(std::move(sequence)));
504 } else {
505 EXPECT_DCHECK_DEATH({ RunAndPopNextTask(std::move(sequence)); });
506 }
507 }
508
509 // Verify that AssertIOAllowed() succeeds only for a MayBlock() task.
TEST_P(ThreadPoolTaskTrackerTest,IOAllowed)510 TEST_P(ThreadPoolTaskTrackerTest, IOAllowed) {
511 // Allowed with MayBlock().
512 Task task_with_may_block(FROM_HERE, BindOnce([]() {
513 // Shouldn't fail.
514 ScopedBlockingCall scope_blocking_call(
515 FROM_HERE, BlockingType::WILL_BLOCK);
516 }),
517 TimeTicks::Now(), TimeDelta());
518 TaskTraits traits_with_may_block{MayBlock(), GetParam()};
519 auto sequence_with_may_block = WillPostTaskAndQueueTaskSource(
520 std::move(task_with_may_block), traits_with_may_block);
521 EXPECT_TRUE(sequence_with_may_block);
522 RunAndPopNextTask(std::move(sequence_with_may_block));
523
524 // Disallowed in the absence of MayBlock().
525 Task task_without_may_block(FROM_HERE, BindOnce([]() {
526 EXPECT_DCHECK_DEATH({
527 ScopedBlockingCall scope_blocking_call(
528 FROM_HERE, BlockingType::WILL_BLOCK);
529 });
530 }),
531 TimeTicks::Now(), TimeDelta());
532 TaskTraits traits_without_may_block = TaskTraits(GetParam());
533 auto sequence_without_may_block = WillPostTaskAndQueueTaskSource(
534 std::move(task_without_may_block), traits_without_may_block);
535 EXPECT_TRUE(sequence_without_may_block);
536 RunAndPopNextTask(std::move(sequence_without_may_block));
537 }
538
RunTaskRunnerCurrentDefaultHandleVerificationTask(TaskTracker * tracker,Task verify_task,TaskTraits traits,scoped_refptr<TaskRunner> task_runner,TaskSourceExecutionMode execution_mode)539 static void RunTaskRunnerCurrentDefaultHandleVerificationTask(
540 TaskTracker* tracker,
541 Task verify_task,
542 TaskTraits traits,
543 scoped_refptr<TaskRunner> task_runner,
544 TaskSourceExecutionMode execution_mode) {
545 // Pretend |verify_task| is posted to respect TaskTracker's contract.
546 EXPECT_TRUE(tracker->WillPostTask(&verify_task, traits.shutdown_behavior()));
547
548 // Confirm that the test conditions are right (no
549 // task runner CurrentDefaultHandles set already).
550 EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
551 EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
552
553 test::QueueAndRunTaskSource(
554 tracker,
555 test::CreateSequenceWithTask(std::move(verify_task), traits,
556 std::move(task_runner), execution_mode));
557
558 // task runner CurrentDefaultHandle state is reset outside of task's scope.
559 EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
560 EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
561 }
562
VerifyNoTaskRunnerCurrentDefaultHandle()563 static void VerifyNoTaskRunnerCurrentDefaultHandle() {
564 EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
565 EXPECT_FALSE(SequencedTaskRunner::HasCurrentDefault());
566 }
567
TEST_P(ThreadPoolTaskTrackerTest,TaskRunnerHandleIsNotSetOnParallel)568 TEST_P(ThreadPoolTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) {
569 // Create a task that will verify that TaskRunnerHandles are not set in its
570 // scope per no TaskRunner ref being set to it.
571 Task verify_task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerCurrentDefaultHandle),
572 TimeTicks::Now(), TimeDelta());
573
574 RunTaskRunnerCurrentDefaultHandleVerificationTask(
575 &tracker_, std::move(verify_task), TaskTraits(GetParam()), nullptr,
576 TaskSourceExecutionMode::kParallel);
577 }
578
VerifySequencedTaskRunnerCurrentDefaultHandle(const SequencedTaskRunner * expected_task_runner)579 static void VerifySequencedTaskRunnerCurrentDefaultHandle(
580 const SequencedTaskRunner* expected_task_runner) {
581 EXPECT_FALSE(SingleThreadTaskRunner::HasCurrentDefault());
582 EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
583 EXPECT_EQ(expected_task_runner, SequencedTaskRunner::GetCurrentDefault());
584 }
585
TEST_P(ThreadPoolTaskTrackerTest,SequencedTaskRunnerHasCurrentDefaultOnSequenced)586 TEST_P(ThreadPoolTaskTrackerTest,
587 SequencedTaskRunnerHasCurrentDefaultOnSequenced) {
588 scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner);
589
590 // Create a task that will verify that
591 // SequencedTaskRunner::CurrentDefaultHandle is properly set to
592 // |test_task_runner| in its scope per |sequenced_task_runner_ref| being set
593 // to it.
594 Task verify_task(FROM_HERE,
595 BindOnce(&VerifySequencedTaskRunnerCurrentDefaultHandle,
596 Unretained(test_task_runner.get())),
597 TimeTicks::Now(), TimeDelta());
598
599 RunTaskRunnerCurrentDefaultHandleVerificationTask(
600 &tracker_, std::move(verify_task), TaskTraits(GetParam()),
601 std::move(test_task_runner), TaskSourceExecutionMode::kSequenced);
602 }
603
VerifySingleThreadTaskRunnerCurrentDefaultHandle(const SingleThreadTaskRunner * expected_task_runner)604 static void VerifySingleThreadTaskRunnerCurrentDefaultHandle(
605 const SingleThreadTaskRunner* expected_task_runner) {
606 EXPECT_TRUE(SingleThreadTaskRunner::HasCurrentDefault());
607 // SequencedTaskRunner::CurrentDefaultHandle inherits
608 // SingleThreadTaskRunner::CurrentDefaultHandle for thread.
609 EXPECT_TRUE(SequencedTaskRunner::HasCurrentDefault());
610 EXPECT_EQ(expected_task_runner, SingleThreadTaskRunner::GetCurrentDefault());
611 }
612
TEST_P(ThreadPoolTaskTrackerTest,SingleThreadTaskRunnerCurrentDefaultHandleIsSetOnSingleThreaded)613 TEST_P(ThreadPoolTaskTrackerTest,
614 SingleThreadTaskRunnerCurrentDefaultHandleIsSetOnSingleThreaded) {
615 scoped_refptr<SingleThreadTaskRunner> test_task_runner(
616 new TestSimpleTaskRunner);
617
618 // Create a task that will verify that
619 // SingleThreadTaskRunner::CurrentDefaultHandle is properly set to
620 // |test_task_runner| in its scope per |single_thread_task_runner_ref| being
621 // set on it.
622 Task verify_task(FROM_HERE,
623 BindOnce(&VerifySingleThreadTaskRunnerCurrentDefaultHandle,
624 Unretained(test_task_runner.get())),
625 TimeTicks::Now(), TimeDelta());
626
627 RunTaskRunnerCurrentDefaultHandleVerificationTask(
628 &tracker_, std::move(verify_task), TaskTraits(GetParam()),
629 std::move(test_task_runner), TaskSourceExecutionMode::kSingleThread);
630 }
631
TEST_P(ThreadPoolTaskTrackerTest,FlushPendingDelayedTask)632 TEST_P(ThreadPoolTaskTrackerTest, FlushPendingDelayedTask) {
633 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
634 tracker_.WillPostTask(&delayed_task, GetParam());
635 // FlushForTesting() should return even if the delayed task didn't run.
636 tracker_.FlushForTesting();
637 }
638
TEST_P(ThreadPoolTaskTrackerTest,FlushAsyncForTestingPendingDelayedTask)639 TEST_P(ThreadPoolTaskTrackerTest, FlushAsyncForTestingPendingDelayedTask) {
640 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
641 tracker_.WillPostTask(&delayed_task, GetParam());
642 // FlushAsyncForTesting() should callback even if the delayed task didn't run.
643 bool called_back = false;
644 tracker_.FlushAsyncForTesting(
645 BindOnce([](bool* called_back) { *called_back = true; },
646 Unretained(&called_back)));
647 EXPECT_TRUE(called_back);
648 }
649
TEST_P(ThreadPoolTaskTrackerTest,FlushPendingUndelayedTask)650 TEST_P(ThreadPoolTaskTrackerTest, FlushPendingUndelayedTask) {
651 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
652 auto undelayed_sequence =
653 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
654
655 // FlushForTesting() shouldn't return before the undelayed task runs.
656 CallFlushFromAnotherThread();
657 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
658 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
659
660 // FlushForTesting() should return after the undelayed task runs.
661 RunAndPopNextTask(std::move(undelayed_sequence));
662 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
663 }
664
TEST_P(ThreadPoolTaskTrackerTest,MultipleFlushes)665 TEST_P(ThreadPoolTaskTrackerTest, MultipleFlushes) {
666 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
667 auto undelayed_sequence =
668 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
669
670 // Multiple flushes should all unwind after the task runs.
671 CallFlushFromAnotherThread();
672 CallFlushFromAnotherThread();
673 CallFlushFromAnotherThread();
674 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
675 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
676
677 RunAndPopNextTask(std::move(undelayed_sequence));
678 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
679 }
680
TEST_P(ThreadPoolTaskTrackerTest,FlushAsyncForTestingPendingUndelayedTask)681 TEST_P(ThreadPoolTaskTrackerTest, FlushAsyncForTestingPendingUndelayedTask) {
682 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
683 auto undelayed_sequence =
684 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
685
686 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
687 TestWaitableEvent event;
688 tracker_.FlushAsyncForTesting(
689 BindOnce(&TestWaitableEvent::Signal, Unretained(&event)));
690 EXPECT_FALSE(event.IsSignaled());
691
692 // FlushAsyncForTesting() should callback after the undelayed task runs.
693 RunAndPopNextTask(std::move(undelayed_sequence));
694 event.Wait();
695 }
696
TEST_P(ThreadPoolTaskTrackerTest,MultipleFlushAsyncForTesting)697 TEST_P(ThreadPoolTaskTrackerTest, MultipleFlushAsyncForTesting) {
698 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
699 auto undelayed_sequence =
700 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
701
702 TestWaitableEvent three_callbacks_ran;
703 auto on_flush_done = BarrierClosure(
704 3,
705 BindOnce(&TestWaitableEvent::Signal, Unretained(&three_callbacks_ran)));
706 tracker_.FlushAsyncForTesting(on_flush_done);
707 tracker_.FlushAsyncForTesting(on_flush_done);
708 tracker_.FlushAsyncForTesting(on_flush_done);
709 EXPECT_FALSE(three_callbacks_ran.IsSignaled());
710
711 // FlushAsyncForTesting() should callback after the undelayed task runs.
712 RunAndPopNextTask(std::move(undelayed_sequence));
713 three_callbacks_ran.Wait();
714 }
715
TEST_P(ThreadPoolTaskTrackerTest,PostTaskDuringFlush)716 TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlush) {
717 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
718 auto undelayed_sequence =
719 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
720
721 // FlushForTesting() shouldn't return before the undelayed task runs.
722 CallFlushFromAnotherThread();
723 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
724 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
725
726 // Simulate posting another undelayed task.
727 Task other_undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(),
728 TimeDelta());
729 auto other_undelayed_sequence = WillPostTaskAndQueueTaskSource(
730 std::move(other_undelayed_task), {GetParam()});
731
732 // Run the first undelayed task.
733 RunAndPopNextTask(std::move(undelayed_sequence));
734
735 // FlushForTesting() shouldn't return before the second undelayed task runs.
736 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
737 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
738
739 // FlushForTesting() should return after the second undelayed task runs.
740 RunAndPopNextTask(std::move(other_undelayed_sequence));
741 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
742 }
743
TEST_P(ThreadPoolTaskTrackerTest,PostTaskDuringFlushAsyncForTesting)744 TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) {
745 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
746 auto undelayed_sequence =
747 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
748
749 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
750 TestWaitableEvent event;
751 tracker_.FlushAsyncForTesting(
752 BindOnce(&TestWaitableEvent::Signal, Unretained(&event)));
753 EXPECT_FALSE(event.IsSignaled());
754
755 // Simulate posting another undelayed task.
756 Task other_undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(),
757 TimeDelta());
758 auto other_undelayed_sequence = WillPostTaskAndQueueTaskSource(
759 std::move(other_undelayed_task), {GetParam()});
760
761 // Run the first undelayed task.
762 RunAndPopNextTask(std::move(undelayed_sequence));
763
764 // FlushAsyncForTesting() shouldn't callback before the second undelayed task
765 // runs.
766 EXPECT_FALSE(event.IsSignaled());
767
768 // FlushAsyncForTesting() should callback after the second undelayed task
769 // runs.
770 RunAndPopNextTask(std::move(other_undelayed_sequence));
771 event.Wait();
772 }
773
TEST_P(ThreadPoolTaskTrackerTest,RunDelayedTaskDuringFlush)774 TEST_P(ThreadPoolTaskTrackerTest, RunDelayedTaskDuringFlush) {
775 // Simulate posting a delayed and an undelayed task.
776 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
777 auto delayed_sequence =
778 WillPostTaskAndQueueTaskSource(std::move(delayed_task), {GetParam()});
779 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
780 auto undelayed_sequence =
781 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
782
783 // FlushForTesting() shouldn't return before the undelayed task runs.
784 CallFlushFromAnotherThread();
785 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
786 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
787
788 // Run the delayed task.
789 RunAndPopNextTask(std::move(delayed_sequence));
790
791 // FlushForTesting() shouldn't return since there is still a pending undelayed
792 // task.
793 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
794 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
795
796 // Run the undelayed task.
797 RunAndPopNextTask(std::move(undelayed_sequence));
798
799 // FlushForTesting() should now ESreturn.
800 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
801 }
802
TEST_P(ThreadPoolTaskTrackerTest,RunDelayedTaskDuringFlushAsyncForTesting)803 TEST_P(ThreadPoolTaskTrackerTest, RunDelayedTaskDuringFlushAsyncForTesting) {
804 // Simulate posting a delayed and an undelayed task.
805 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
806 auto delayed_sequence =
807 WillPostTaskAndQueueTaskSource(std::move(delayed_task), {GetParam()});
808 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
809 auto undelayed_sequence =
810 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
811
812 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
813 TestWaitableEvent event;
814 tracker_.FlushAsyncForTesting(
815 BindOnce(&TestWaitableEvent::Signal, Unretained(&event)));
816 EXPECT_FALSE(event.IsSignaled());
817
818 // Run the delayed task.
819 RunAndPopNextTask(std::move(delayed_sequence));
820
821 // FlushAsyncForTesting() shouldn't callback since there is still a pending
822 // undelayed task.
823 EXPECT_FALSE(event.IsSignaled());
824
825 // Run the undelayed task.
826 RunAndPopNextTask(std::move(undelayed_sequence));
827
828 // FlushAsyncForTesting() should now callback.
829 event.Wait();
830 }
831
TEST_P(ThreadPoolTaskTrackerTest,FlushAfterShutdown)832 TEST_P(ThreadPoolTaskTrackerTest, FlushAfterShutdown) {
833 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
834 return;
835
836 // Simulate posting a task.
837 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
838 tracker_.WillPostTask(&undelayed_task, GetParam());
839
840 // Shutdown() should return immediately since there are no pending
841 // BLOCK_SHUTDOWN tasks.
842 test::ShutdownTaskTracker(&tracker_);
843
844 // FlushForTesting() should return immediately after shutdown, even if an
845 // undelayed task hasn't run.
846 tracker_.FlushForTesting();
847 }
848
TEST_P(ThreadPoolTaskTrackerTest,FlushAfterShutdownAsync)849 TEST_P(ThreadPoolTaskTrackerTest, FlushAfterShutdownAsync) {
850 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
851 return;
852
853 // Simulate posting a task.
854 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
855 tracker_.WillPostTask(&undelayed_task, GetParam());
856
857 // Shutdown() should return immediately since there are no pending
858 // BLOCK_SHUTDOWN tasks.
859 test::ShutdownTaskTracker(&tracker_);
860
861 // FlushForTesting() should callback immediately after shutdown, even if an
862 // undelayed task hasn't run.
863 bool called_back = false;
864 tracker_.FlushAsyncForTesting(
865 BindOnce([](bool* called_back) { *called_back = true; },
866 Unretained(&called_back)));
867 EXPECT_TRUE(called_back);
868 }
869
TEST_P(ThreadPoolTaskTrackerTest,ShutdownDuringFlush)870 TEST_P(ThreadPoolTaskTrackerTest, ShutdownDuringFlush) {
871 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
872 return;
873
874 // Simulate posting a task.
875 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
876 auto undelayed_sequence =
877 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
878
879 // FlushForTesting() shouldn't return before the undelayed task runs or
880 // shutdown completes.
881 CallFlushFromAnotherThread();
882 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
883 VERIFY_ASYNC_FLUSHES_IN_PROGRESS();
884
885 // Shutdown() should return immediately since there are no pending
886 // BLOCK_SHUTDOWN tasks.
887 test::ShutdownTaskTracker(&tracker_);
888
889 // FlushForTesting() should now return, even if an undelayed task hasn't run.
890 WAIT_FOR_ASYNC_FLUSHES_RETURNED();
891 }
892
TEST_P(ThreadPoolTaskTrackerTest,ShutdownDuringFlushAsyncForTesting)893 TEST_P(ThreadPoolTaskTrackerTest, ShutdownDuringFlushAsyncForTesting) {
894 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
895 return;
896
897 // Simulate posting a task.
898 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
899 auto undelayed_sequence =
900 WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()});
901
902 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs or
903 // shutdown completes.
904 TestWaitableEvent event;
905 tracker_.FlushAsyncForTesting(
906 BindOnce(&TestWaitableEvent::Signal, Unretained(&event)));
907 EXPECT_FALSE(event.IsSignaled());
908
909 // Shutdown() should return immediately since there are no pending
910 // BLOCK_SHUTDOWN tasks.
911 test::ShutdownTaskTracker(&tracker_);
912
913 // FlushAsyncForTesting() should now callback, even if an undelayed task
914 // hasn't run.
915 event.Wait();
916 }
917
TEST_P(ThreadPoolTaskTrackerTest,PostTasksDoNotBlockShutdown)918 TEST_P(ThreadPoolTaskTrackerTest, PostTasksDoNotBlockShutdown) {
919 // Simulate posting an undelayed task.
920 Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
921 EXPECT_TRUE(tracker_.WillPostTask(&undelayed_task, GetParam()));
922
923 // Since no sequence was queued, a call to Shutdown() should not hang.
924 test::ShutdownTaskTracker(&tracker_);
925 }
926
927 // Verify that a delayed task does not block shutdown once it's run, regardless
928 // of its shutdown behavior.
TEST_P(ThreadPoolTaskTrackerTest,DelayedRunTasks)929 TEST_P(ThreadPoolTaskTrackerTest, DelayedRunTasks) {
930 // Simulate posting a delayed task.
931 Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), Days(1));
932 auto sequence =
933 WillPostTaskAndQueueTaskSource(std::move(delayed_task), {GetParam()});
934 EXPECT_TRUE(sequence);
935
936 RunAndPopNextTask(std::move(sequence));
937
938 // Since the delayed task doesn't block shutdown, a call to Shutdown() should
939 // not hang.
940 test::ShutdownTaskTracker(&tracker_);
941 }
942
943 INSTANTIATE_TEST_SUITE_P(
944 ContinueOnShutdown,
945 ThreadPoolTaskTrackerTest,
946 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
947 INSTANTIATE_TEST_SUITE_P(
948 SkipOnShutdown,
949 ThreadPoolTaskTrackerTest,
950 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
951 INSTANTIATE_TEST_SUITE_P(
952 BlockShutdown,
953 ThreadPoolTaskTrackerTest,
954 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN));
955
956 namespace {
957
ExpectSequenceToken(SequenceToken sequence_token)958 void ExpectSequenceToken(SequenceToken sequence_token) {
959 EXPECT_EQ(sequence_token, SequenceToken::GetForCurrentThread());
960 }
961
962 } // namespace
963
964 // Verify that SequenceToken::GetForCurrentThread() returns the Sequence's token
965 // when a Task runs.
TEST_F(ThreadPoolTaskTrackerTest,CurrentSequenceToken)966 TEST_F(ThreadPoolTaskTrackerTest, CurrentSequenceToken) {
967 scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(
968 TaskTraits(), nullptr, TaskSourceExecutionMode::kParallel);
969
970 const SequenceToken sequence_token = sequence->token();
971 Task task(FROM_HERE, BindOnce(&ExpectSequenceToken, sequence_token),
972 TimeTicks::Now(), TimeDelta());
973 tracker_.WillPostTask(&task, sequence->shutdown_behavior());
974
975 {
976 Sequence::Transaction sequence_transaction(sequence->BeginTransaction());
977 sequence_transaction.WillPushImmediateTask();
978 sequence_transaction.PushImmediateTask(std::move(task));
979
980 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
981 }
982
983 test::QueueAndRunTaskSource(&tracker_, std::move(sequence));
984 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
985 }
986
TEST_F(ThreadPoolTaskTrackerTest,LoadWillPostAndRunBeforeShutdown)987 TEST_F(ThreadPoolTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) {
988 // Post and run tasks asynchronously.
989 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
990
991 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
992 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
993 &tracker_,
994 MakeRefCounted<Sequence>(
995 TaskTraits{TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, nullptr,
996 TaskSourceExecutionMode::kParallel),
997 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true,
998 CreateTask()));
999 threads.back()->Start();
1000
1001 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1002 &tracker_,
1003 MakeRefCounted<Sequence>(
1004 TaskTraits{TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, nullptr,
1005 TaskSourceExecutionMode::kParallel),
1006 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true,
1007 CreateTask()));
1008 threads.back()->Start();
1009
1010 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1011 &tracker_,
1012 MakeRefCounted<Sequence>(
1013 TaskTraits{TaskShutdownBehavior::BLOCK_SHUTDOWN}, nullptr,
1014 TaskSourceExecutionMode::kParallel),
1015 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true,
1016 CreateTask()));
1017 threads.back()->Start();
1018 }
1019
1020 for (const auto& thread : threads)
1021 thread->Join();
1022
1023 // Expect all tasks to be executed.
1024 EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted());
1025
1026 // Should return immediately because no tasks are blocking shutdown.
1027 test::ShutdownTaskTracker(&tracker_);
1028 }
1029
TEST_F(ThreadPoolTaskTrackerTest,LoadWillPostBeforeShutdownAndRunDuringShutdown)1030 TEST_F(ThreadPoolTaskTrackerTest,
1031 LoadWillPostBeforeShutdownAndRunDuringShutdown) {
1032 constexpr TaskTraits traits_continue_on_shutdown =
1033 TaskTraits(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN);
1034 constexpr TaskTraits traits_skip_on_shutdown =
1035 TaskTraits(TaskShutdownBehavior::SKIP_ON_SHUTDOWN);
1036 constexpr TaskTraits traits_block_shutdown =
1037 TaskTraits(TaskShutdownBehavior::BLOCK_SHUTDOWN);
1038
1039 // Post tasks asynchronously.
1040 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads;
1041 {
1042 std::vector<scoped_refptr<Sequence>> sequences_continue_on_shutdown;
1043 std::vector<scoped_refptr<Sequence>> sequences_skip_on_shutdown;
1044 std::vector<scoped_refptr<Sequence>> sequences_block_shutdown;
1045 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1046 sequences_continue_on_shutdown.push_back(
1047 MakeRefCounted<Sequence>(traits_continue_on_shutdown, nullptr,
1048 TaskSourceExecutionMode::kParallel));
1049 sequences_skip_on_shutdown.push_back(
1050 MakeRefCounted<Sequence>(traits_skip_on_shutdown, nullptr,
1051 TaskSourceExecutionMode::kParallel));
1052 sequences_block_shutdown.push_back(MakeRefCounted<Sequence>(
1053 traits_block_shutdown, nullptr, TaskSourceExecutionMode::kParallel));
1054 }
1055
1056 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1057 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1058 &tracker_, sequences_continue_on_shutdown[i],
1059 ThreadPostingAndRunningTask::Action::WILL_POST, true, CreateTask()));
1060 post_threads.back()->Start();
1061
1062 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1063 &tracker_, sequences_skip_on_shutdown[i],
1064 ThreadPostingAndRunningTask::Action::WILL_POST, true, CreateTask()));
1065 post_threads.back()->Start();
1066
1067 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1068 &tracker_, sequences_block_shutdown[i],
1069 ThreadPostingAndRunningTask::Action::WILL_POST, true, CreateTask()));
1070 post_threads.back()->Start();
1071 }
1072 }
1073
1074 for (const auto& thread : post_threads)
1075 thread->Join();
1076
1077 // Start shutdown and try to complete shutdown asynchronously.
1078 tracker_.StartShutdown();
1079 ExpectAsyncCompleteShutdownBlocks();
1080
1081 // Run tasks asynchronously.
1082 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads;
1083 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1084 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1085 &tracker_, post_threads[i * 3]->TakeTaskSource()));
1086 run_threads.back()->Start();
1087
1088 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1089 &tracker_, post_threads[i * 3 + 1]->TakeTaskSource()));
1090 run_threads.back()->Start();
1091
1092 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1093 &tracker_, post_threads[i * 3 + 2]->TakeTaskSource()));
1094 run_threads.back()->Start();
1095 }
1096
1097 for (const auto& thread : run_threads)
1098 thread->Join();
1099
1100 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
1101
1102 // Expect BLOCK_SHUTDOWN tasks to have been executed.
1103 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
1104 }
1105
TEST_F(ThreadPoolTaskTrackerTest,LoadWillPostAndRunDuringShutdown)1106 TEST_F(ThreadPoolTaskTrackerTest, LoadWillPostAndRunDuringShutdown) {
1107 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
1108 // block shutdown.
1109 auto block_shutdown_sequence = WillPostTaskAndQueueTaskSource(
1110 CreateTask(), {TaskShutdownBehavior::BLOCK_SHUTDOWN});
1111 EXPECT_TRUE(block_shutdown_sequence);
1112
1113 // Start shutdown and try to complete it asynchronously.
1114 tracker_.StartShutdown();
1115 ExpectAsyncCompleteShutdownBlocks();
1116
1117 // Post and run tasks asynchronously.
1118 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
1119
1120 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1121 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1122 &tracker_,
1123 MakeRefCounted<Sequence>(
1124 TaskTraits{TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, nullptr,
1125 TaskSourceExecutionMode::kParallel),
1126 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false,
1127 CreateTask()));
1128 threads.back()->Start();
1129
1130 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1131 &tracker_,
1132 MakeRefCounted<Sequence>(
1133 TaskTraits{TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, nullptr,
1134 TaskSourceExecutionMode::kParallel),
1135 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false,
1136 CreateTask()));
1137 threads.back()->Start();
1138
1139 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1140 &tracker_,
1141 MakeRefCounted<Sequence>(
1142 TaskTraits{TaskShutdownBehavior::BLOCK_SHUTDOWN}, nullptr,
1143 TaskSourceExecutionMode::kParallel),
1144 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true,
1145 CreateTask()));
1146 threads.back()->Start();
1147 }
1148
1149 for (const auto& thread : threads)
1150 thread->Join();
1151
1152 // Expect BLOCK_SHUTDOWN tasks to have been executed.
1153 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
1154
1155 // Shutdown() shouldn't return before |block_shutdown_task| is executed.
1156 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
1157
1158 // Unblock shutdown by running |block_shutdown_task|.
1159 RunAndPopNextTask(std::move(block_shutdown_sequence));
1160 EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted());
1161 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
1162 }
1163
1164 // Verify that RunAndPopNextTask() returns the sequence from which it ran a task
1165 // when it can be rescheduled.
TEST_F(ThreadPoolTaskTrackerTest,RunAndPopNextTaskReturnsSequenceToReschedule)1166 TEST_F(ThreadPoolTaskTrackerTest,
1167 RunAndPopNextTaskReturnsSequenceToReschedule) {
1168 TaskTraits default_traits;
1169 Task task_1(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
1170 EXPECT_TRUE(
1171 tracker_.WillPostTask(&task_1, default_traits.shutdown_behavior()));
1172 Task task_2(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta());
1173 EXPECT_TRUE(
1174 tracker_.WillPostTask(&task_2, default_traits.shutdown_behavior()));
1175
1176 scoped_refptr<Sequence> sequence =
1177 test::CreateSequenceWithTask(std::move(task_1), default_traits);
1178 {
1179 auto transaction = sequence->BeginTransaction();
1180 transaction.WillPushImmediateTask();
1181 transaction.PushImmediateTask(std::move(task_2));
1182 }
1183 EXPECT_EQ(sequence,
1184 test::QueueAndRunTaskSource(&tracker_, sequence).Unregister());
1185 }
1186
1187 namespace {
1188
1189 class WaitAllowedTestThread : public SimpleThread {
1190 public:
WaitAllowedTestThread()1191 WaitAllowedTestThread() : SimpleThread("WaitAllowedTestThread") {}
1192 WaitAllowedTestThread(const WaitAllowedTestThread&) = delete;
1193 WaitAllowedTestThread& operator=(const WaitAllowedTestThread&) = delete;
1194
1195 private:
Run()1196 void Run() override {
1197 auto task_tracker = std::make_unique<TaskTracker>();
1198
1199 // Waiting is allowed by default. Expect TaskTracker to disallow it before
1200 // running a task without the WithBaseSyncPrimitives() trait.
1201 internal::AssertBaseSyncPrimitivesAllowed();
1202 Task task_without_sync_primitives(
1203 FROM_HERE, BindOnce([]() {
1204 EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
1205 }),
1206 TimeTicks::Now(), TimeDelta());
1207 TaskTraits default_traits;
1208 EXPECT_TRUE(task_tracker->WillPostTask(&task_without_sync_primitives,
1209 default_traits.shutdown_behavior()));
1210 auto sequence_without_sync_primitives = test::CreateSequenceWithTask(
1211 std::move(task_without_sync_primitives), default_traits);
1212 test::QueueAndRunTaskSource(task_tracker.get(),
1213 std::move(sequence_without_sync_primitives));
1214
1215 // Expect TaskTracker to keep waiting allowed when running a task with the
1216 // WithBaseSyncPrimitives() trait.
1217 internal::AssertBaseSyncPrimitivesAllowed();
1218 Task task_with_sync_primitives(
1219 FROM_HERE, BindOnce([]() {
1220 // Shouldn't fail.
1221 internal::AssertBaseSyncPrimitivesAllowed();
1222 }),
1223 TimeTicks::Now(), TimeDelta());
1224 TaskTraits traits_with_sync_primitives =
1225 TaskTraits(WithBaseSyncPrimitives());
1226 EXPECT_TRUE(task_tracker->WillPostTask(
1227 &task_with_sync_primitives,
1228 traits_with_sync_primitives.shutdown_behavior()));
1229 auto sequence_with_sync_primitives = test::CreateSequenceWithTask(
1230 std::move(task_with_sync_primitives), traits_with_sync_primitives);
1231 test::QueueAndRunTaskSource(task_tracker.get(),
1232 std::move(sequence_with_sync_primitives));
1233
1234 ScopedAllowBaseSyncPrimitivesForTesting
1235 allow_wait_in_task_tracker_destructor;
1236 task_tracker.reset();
1237 }
1238 };
1239
1240 } // namespace
1241
1242 // Verify that AssertIOAllowed() succeeds only for a WithBaseSyncPrimitives()
1243 // task.
TEST(ThreadPoolTaskTrackerWaitAllowedTest,WaitAllowed)1244 TEST(ThreadPoolTaskTrackerWaitAllowedTest, WaitAllowed) {
1245 // Run the test on the separate thread since it is not possible to reset the
1246 // "wait allowed" bit of a thread without being a friend of
1247 // ThreadRestrictions.
1248 GTEST_FLAG_SET(death_test_style, "threadsafe");
1249 WaitAllowedTestThread wait_allowed_test_thread;
1250 wait_allowed_test_thread.Start();
1251 wait_allowed_test_thread.Join();
1252 }
1253
1254 } // namespace internal
1255 } // namespace base
1256