1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/task_scheduler/task_tracker.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "base/bind.h"
14 #include "base/bind_helpers.h"
15 #include "base/callback.h"
16 #include "base/logging.h"
17 #include "base/macros.h"
18 #include "base/memory/ptr_util.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/metrics/histogram_base.h"
21 #include "base/metrics/histogram_samples.h"
22 #include "base/metrics/statistics_recorder.h"
23 #include "base/sequence_token.h"
24 #include "base/sequenced_task_runner.h"
25 #include "base/single_thread_task_runner.h"
26 #include "base/synchronization/atomic_flag.h"
27 #include "base/synchronization/waitable_event.h"
28 #include "base/task_scheduler/scheduler_lock.h"
29 #include "base/task_scheduler/task.h"
30 #include "base/task_scheduler/task_traits.h"
31 #include "base/task_scheduler/test_utils.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/threading/platform_thread.h"
37 #include "base/threading/sequenced_task_runner_handle.h"
38 #include "base/threading/simple_thread.h"
39 #include "base/threading/thread_restrictions.h"
40 #include "base/threading/thread_task_runner_handle.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 class MockCanScheduleSequenceObserver : public CanScheduleSequenceObserver {
52 public:
OnCanScheduleSequence(scoped_refptr<Sequence> sequence)53 void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override {
54 MockOnCanScheduleSequence(sequence.get());
55 }
56
57 MOCK_METHOD1(MockOnCanScheduleSequence, void(Sequence*));
58 };
59
60 // Invokes a closure asynchronously.
61 class CallbackThread : public SimpleThread {
62 public:
CallbackThread(const Closure & closure)63 explicit CallbackThread(const Closure& closure)
64 : SimpleThread("CallbackThread"), closure_(closure) {}
65
66 // Returns true once the callback returns.
has_returned()67 bool has_returned() { return has_returned_.IsSet(); }
68
69 private:
Run()70 void Run() override {
71 closure_.Run();
72 has_returned_.Set();
73 }
74
75 const Closure closure_;
76 AtomicFlag has_returned_;
77
78 DISALLOW_COPY_AND_ASSIGN(CallbackThread);
79 };
80
81 class ThreadPostingAndRunningTask : public SimpleThread {
82 public:
83 enum class Action {
84 WILL_POST,
85 RUN,
86 WILL_POST_AND_RUN,
87 };
88
ThreadPostingAndRunningTask(TaskTracker * tracker,Task * task,Action action,bool expect_post_succeeds)89 ThreadPostingAndRunningTask(TaskTracker* tracker,
90 Task* task,
91 Action action,
92 bool expect_post_succeeds)
93 : SimpleThread("ThreadPostingAndRunningTask"),
94 tracker_(tracker),
95 owned_task_(FROM_HERE, OnceClosure(), TaskTraits(), TimeDelta()),
96 task_(task),
97 action_(action),
98 expect_post_succeeds_(expect_post_succeeds) {
99 EXPECT_TRUE(task_);
100
101 // Ownership of the Task is required to run it.
102 EXPECT_NE(Action::RUN, action_);
103 EXPECT_NE(Action::WILL_POST_AND_RUN, action_);
104 }
105
ThreadPostingAndRunningTask(TaskTracker * tracker,Task task,Action action,bool expect_post_succeeds)106 ThreadPostingAndRunningTask(TaskTracker* tracker,
107 Task task,
108 Action action,
109 bool expect_post_succeeds)
110 : SimpleThread("ThreadPostingAndRunningTask"),
111 tracker_(tracker),
112 owned_task_(std::move(task)),
113 task_(&owned_task_),
114 action_(action),
115 expect_post_succeeds_(expect_post_succeeds) {
116 EXPECT_TRUE(owned_task_.task);
117 }
118
119 private:
Run()120 void Run() override {
121 bool post_succeeded = true;
122 if (action_ == Action::WILL_POST || action_ == Action::WILL_POST_AND_RUN) {
123 post_succeeded = tracker_->WillPostTask(task_);
124 EXPECT_EQ(expect_post_succeeds_, post_succeeded);
125 }
126 if (post_succeeded &&
127 (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) {
128 EXPECT_TRUE(owned_task_.task);
129
130 testing::StrictMock<MockCanScheduleSequenceObserver>
131 never_notified_observer;
132 auto sequence = tracker_->WillScheduleSequence(
133 test::CreateSequenceWithTask(std::move(owned_task_)),
134 &never_notified_observer);
135 ASSERT_TRUE(sequence);
136 // Expect RunAndPopNextTask to return nullptr since |sequence| is empty
137 // after popping a task from it.
138 EXPECT_FALSE(tracker_->RunAndPopNextTask(std::move(sequence),
139 &never_notified_observer));
140 }
141 }
142
143 TaskTracker* const tracker_;
144 Task owned_task_;
145 Task* task_;
146 const Action action_;
147 const bool expect_post_succeeds_;
148
149 DISALLOW_COPY_AND_ASSIGN(ThreadPostingAndRunningTask);
150 };
151
152 class ScopedSetSingletonAllowed {
153 public:
ScopedSetSingletonAllowed(bool singleton_allowed)154 ScopedSetSingletonAllowed(bool singleton_allowed)
155 : previous_value_(
156 ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {}
~ScopedSetSingletonAllowed()157 ~ScopedSetSingletonAllowed() {
158 ThreadRestrictions::SetSingletonAllowed(previous_value_);
159 }
160
161 private:
162 const bool previous_value_;
163 };
164
165 class TaskSchedulerTaskTrackerTest
166 : public testing::TestWithParam<TaskShutdownBehavior> {
167 protected:
168 TaskSchedulerTaskTrackerTest() = default;
169
170 // Creates a task with |shutdown_behavior|.
CreateTask(TaskShutdownBehavior shutdown_behavior)171 Task CreateTask(TaskShutdownBehavior shutdown_behavior) {
172 return Task(
173 FROM_HERE,
174 Bind(&TaskSchedulerTaskTrackerTest::RunTaskCallback, Unretained(this)),
175 TaskTraits(shutdown_behavior), TimeDelta());
176 }
177
DispatchAndRunTaskWithTracker(Task task)178 void DispatchAndRunTaskWithTracker(Task task) {
179 auto sequence = tracker_.WillScheduleSequence(
180 test::CreateSequenceWithTask(std::move(task)),
181 &never_notified_observer_);
182 ASSERT_TRUE(sequence);
183 tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_);
184 }
185
186 // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown()
187 // method has been entered on the new thread, but it hasn't necessarily
188 // returned.
CallShutdownAsync()189 void CallShutdownAsync() {
190 ASSERT_FALSE(thread_calling_shutdown_);
191 thread_calling_shutdown_.reset(new CallbackThread(
192 Bind(&TaskTracker::Shutdown, Unretained(&tracker_))));
193 thread_calling_shutdown_->Start();
194 while (!tracker_.HasShutdownStarted())
195 PlatformThread::YieldCurrentThread();
196 }
197
WaitForAsyncIsShutdownComplete()198 void WaitForAsyncIsShutdownComplete() {
199 ASSERT_TRUE(thread_calling_shutdown_);
200 thread_calling_shutdown_->Join();
201 EXPECT_TRUE(thread_calling_shutdown_->has_returned());
202 EXPECT_TRUE(tracker_.IsShutdownComplete());
203 }
204
VerifyAsyncShutdownInProgress()205 void VerifyAsyncShutdownInProgress() {
206 ASSERT_TRUE(thread_calling_shutdown_);
207 EXPECT_FALSE(thread_calling_shutdown_->has_returned());
208 EXPECT_TRUE(tracker_.HasShutdownStarted());
209 EXPECT_FALSE(tracker_.IsShutdownComplete());
210 }
211
212 // Calls tracker_->FlushForTesting() on a new thread.
CallFlushFromAnotherThread()213 void CallFlushFromAnotherThread() {
214 ASSERT_FALSE(thread_calling_flush_);
215 thread_calling_flush_.reset(new CallbackThread(
216 Bind(&TaskTracker::FlushForTesting, Unretained(&tracker_))));
217 thread_calling_flush_->Start();
218 }
219
WaitForAsyncFlushReturned()220 void WaitForAsyncFlushReturned() {
221 ASSERT_TRUE(thread_calling_flush_);
222 thread_calling_flush_->Join();
223 EXPECT_TRUE(thread_calling_flush_->has_returned());
224 }
225
VerifyAsyncFlushInProgress()226 void VerifyAsyncFlushInProgress() {
227 ASSERT_TRUE(thread_calling_flush_);
228 EXPECT_FALSE(thread_calling_flush_->has_returned());
229 }
230
NumTasksExecuted()231 size_t NumTasksExecuted() {
232 AutoSchedulerLock auto_lock(lock_);
233 return num_tasks_executed_;
234 }
235
236 TaskTracker tracker_ = {"Test"};
237 testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer_;
238
239 private:
RunTaskCallback()240 void RunTaskCallback() {
241 AutoSchedulerLock auto_lock(lock_);
242 ++num_tasks_executed_;
243 }
244
245 std::unique_ptr<CallbackThread> thread_calling_shutdown_;
246 std::unique_ptr<CallbackThread> thread_calling_flush_;
247
248 // Synchronizes accesses to |num_tasks_executed_|.
249 SchedulerLock lock_;
250
251 size_t num_tasks_executed_ = 0;
252
253 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest);
254 };
255
256 #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \
257 do { \
258 SCOPED_TRACE(""); \
259 WaitForAsyncIsShutdownComplete(); \
260 } while (false)
261
262 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \
263 do { \
264 SCOPED_TRACE(""); \
265 VerifyAsyncShutdownInProgress(); \
266 } while (false)
267
268 #define WAIT_FOR_ASYNC_FLUSH_RETURNED() \
269 do { \
270 SCOPED_TRACE(""); \
271 WaitForAsyncFlushReturned(); \
272 } while (false)
273
274 #define VERIFY_ASYNC_FLUSH_IN_PROGRESS() \
275 do { \
276 SCOPED_TRACE(""); \
277 VerifyAsyncFlushInProgress(); \
278 } while (false)
279
280 } // namespace
281
TEST_P(TaskSchedulerTaskTrackerTest,WillPostAndRunBeforeShutdown)282 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) {
283 Task task(CreateTask(GetParam()));
284
285 // Inform |task_tracker_| that |task| will be posted.
286 EXPECT_TRUE(tracker_.WillPostTask(&task));
287
288 // Run the task.
289 EXPECT_EQ(0U, NumTasksExecuted());
290
291 DispatchAndRunTaskWithTracker(std::move(task));
292 EXPECT_EQ(1U, NumTasksExecuted());
293
294 // Shutdown() shouldn't block.
295 tracker_.Shutdown();
296 }
297
TEST_P(TaskSchedulerTaskTrackerTest,WillPostAndRunLongTaskBeforeShutdown)298 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) {
299 // Create a task that signals |task_running| and blocks until |task_barrier|
300 // is signaled.
301 WaitableEvent task_running(WaitableEvent::ResetPolicy::AUTOMATIC,
302 WaitableEvent::InitialState::NOT_SIGNALED);
303 WaitableEvent task_barrier(WaitableEvent::ResetPolicy::AUTOMATIC,
304 WaitableEvent::InitialState::NOT_SIGNALED);
305 Task blocked_task(
306 FROM_HERE,
307 Bind(
308 [](WaitableEvent* task_running, WaitableEvent* task_barrier) {
309 task_running->Signal();
310 task_barrier->Wait();
311 },
312 Unretained(&task_running), Unretained(&task_barrier)),
313 TaskTraits(WithBaseSyncPrimitives(), GetParam()), TimeDelta());
314
315 // Inform |task_tracker_| that |blocked_task| will be posted.
316 EXPECT_TRUE(tracker_.WillPostTask(&blocked_task));
317
318 // Create a thread to run the task. Wait until the task starts running.
319 ThreadPostingAndRunningTask thread_running_task(
320 &tracker_, std::move(blocked_task),
321 ThreadPostingAndRunningTask::Action::RUN, false);
322 thread_running_task.Start();
323 task_running.Wait();
324
325 // Initiate shutdown after the task has started to run.
326 CallShutdownAsync();
327
328 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) {
329 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress.
330 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
331 } else {
332 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress.
333 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
334 }
335
336 // Unblock the task.
337 task_barrier.Signal();
338 thread_running_task.Join();
339
340 // Shutdown should now complete for a non CONTINUE_ON_SHUTDOWN task.
341 if (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
342 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
343 }
344
TEST_P(TaskSchedulerTaskTrackerTest,WillPostBeforeShutdownRunDuringShutdown)345 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) {
346 // Inform |task_tracker_| that a task will be posted.
347 Task task(CreateTask(GetParam()));
348 EXPECT_TRUE(tracker_.WillPostTask(&task));
349
350 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
351 // block shutdown.
352 Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
353 EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task));
354
355 // Call Shutdown() asynchronously.
356 CallShutdownAsync();
357 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
358
359 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it
360 // should be discarded.
361 EXPECT_EQ(0U, NumTasksExecuted());
362 const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN;
363
364 DispatchAndRunTaskWithTracker(std::move(task));
365 EXPECT_EQ(should_run ? 1U : 0U, NumTasksExecuted());
366 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
367
368 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task.
369 DispatchAndRunTaskWithTracker(std::move(block_shutdown_task));
370 EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted());
371 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
372 }
373
TEST_P(TaskSchedulerTaskTrackerTest,WillPostBeforeShutdownRunAfterShutdown)374 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) {
375 // Inform |task_tracker_| that a task will be posted.
376 Task task(CreateTask(GetParam()));
377 EXPECT_TRUE(tracker_.WillPostTask(&task));
378
379 // Call Shutdown() asynchronously.
380 CallShutdownAsync();
381 EXPECT_EQ(0U, NumTasksExecuted());
382
383 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
384 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
385
386 // Run the task to unblock shutdown.
387 DispatchAndRunTaskWithTracker(std::move(task));
388 EXPECT_EQ(1U, NumTasksExecuted());
389 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
390
391 // It is not possible to test running a BLOCK_SHUTDOWN task posted before
392 // shutdown after shutdown because Shutdown() won't return if there are
393 // pending BLOCK_SHUTDOWN tasks.
394 } else {
395 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
396
397 // The task shouldn't be allowed to run after shutdown.
398 DispatchAndRunTaskWithTracker(std::move(task));
399 EXPECT_EQ(0U, NumTasksExecuted());
400 }
401 }
402
TEST_P(TaskSchedulerTaskTrackerTest,WillPostAndRunDuringShutdown)403 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) {
404 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
405 // block shutdown.
406 Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
407 EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task));
408
409 // Call Shutdown() asynchronously.
410 CallShutdownAsync();
411 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
412
413 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
414 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted.
415 Task task(CreateTask(GetParam()));
416 EXPECT_TRUE(tracker_.WillPostTask(&task));
417
418 // Run the BLOCK_SHUTDOWN task.
419 EXPECT_EQ(0U, NumTasksExecuted());
420 DispatchAndRunTaskWithTracker(std::move(task));
421 EXPECT_EQ(1U, NumTasksExecuted());
422 } else {
423 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task.
424 Task task(CreateTask(GetParam()));
425 EXPECT_FALSE(tracker_.WillPostTask(&task));
426
427 // Don't try to run the task, because it wasn't allowed to be posted.
428 }
429
430 // Unblock shutdown by running |block_shutdown_task|.
431 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
432 DispatchAndRunTaskWithTracker(std::move(block_shutdown_task));
433 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U,
434 NumTasksExecuted());
435 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
436 }
437
TEST_P(TaskSchedulerTaskTrackerTest,WillPostAfterShutdown)438 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) {
439 tracker_.Shutdown();
440
441 Task task(CreateTask(GetParam()));
442
443 // |task_tracker_| shouldn't allow a task to be posted after shutdown.
444 EXPECT_FALSE(tracker_.WillPostTask(&task));
445 }
446
447 // Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can
448 // AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't.
TEST_P(TaskSchedulerTaskTrackerTest,SingletonAllowed)449 TEST_P(TaskSchedulerTaskTrackerTest, SingletonAllowed) {
450 const bool can_use_singletons =
451 (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN);
452
453 Task task(FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed),
454 TaskTraits(GetParam()), TimeDelta());
455 EXPECT_TRUE(tracker_.WillPostTask(&task));
456
457 // Set the singleton allowed bit to the opposite of what it is expected to be
458 // when |tracker| runs |task| to verify that |tracker| actually sets the
459 // correct value.
460 ScopedSetSingletonAllowed scoped_singleton_allowed(!can_use_singletons);
461
462 // Running the task should fail iff the task isn't allowed to use singletons.
463 if (can_use_singletons) {
464 DispatchAndRunTaskWithTracker(std::move(task));
465 } else {
466 EXPECT_DCHECK_DEATH({ DispatchAndRunTaskWithTracker(std::move(task)); });
467 }
468 }
469
470 // Verify that AssertIOAllowed() succeeds only for a MayBlock() task.
TEST_P(TaskSchedulerTaskTrackerTest,IOAllowed)471 TEST_P(TaskSchedulerTaskTrackerTest, IOAllowed) {
472 // Unset the IO allowed bit. Expect TaskTracker to set it before running a
473 // task with the MayBlock() trait.
474 ThreadRestrictions::SetIOAllowed(false);
475 Task task_with_may_block(FROM_HERE, Bind([]() {
476 // Shouldn't fail.
477 AssertBlockingAllowed();
478 }),
479 TaskTraits(MayBlock(), GetParam()), TimeDelta());
480 EXPECT_TRUE(tracker_.WillPostTask(&task_with_may_block));
481 DispatchAndRunTaskWithTracker(std::move(task_with_may_block));
482
483 // Set the IO allowed bit. Expect TaskTracker to unset it before running a
484 // task without the MayBlock() trait.
485 ThreadRestrictions::SetIOAllowed(true);
486 Task task_without_may_block(
487 FROM_HERE,
488 Bind([]() { EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); }); }),
489 TaskTraits(GetParam()), TimeDelta());
490 EXPECT_TRUE(tracker_.WillPostTask(&task_without_may_block));
491 DispatchAndRunTaskWithTracker(std::move(task_without_may_block));
492 }
493
RunTaskRunnerHandleVerificationTask(TaskTracker * tracker,Task verify_task)494 static void RunTaskRunnerHandleVerificationTask(TaskTracker* tracker,
495 Task verify_task) {
496 // Pretend |verify_task| is posted to respect TaskTracker's contract.
497 EXPECT_TRUE(tracker->WillPostTask(&verify_task));
498
499 // Confirm that the test conditions are right (no TaskRunnerHandles set
500 // already).
501 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
502 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
503
504 testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
505 auto sequence = tracker->WillScheduleSequence(
506 test::CreateSequenceWithTask(std::move(verify_task)),
507 &never_notified_observer);
508 ASSERT_TRUE(sequence);
509 tracker->RunAndPopNextTask(std::move(sequence), &never_notified_observer);
510
511 // TaskRunnerHandle state is reset outside of task's scope.
512 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
513 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
514 }
515
VerifyNoTaskRunnerHandle()516 static void VerifyNoTaskRunnerHandle() {
517 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
518 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
519 }
520
TEST_P(TaskSchedulerTaskTrackerTest,TaskRunnerHandleIsNotSetOnParallel)521 TEST_P(TaskSchedulerTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) {
522 // Create a task that will verify that TaskRunnerHandles are not set in its
523 // scope per no TaskRunner ref being set to it.
524 Task verify_task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle),
525 TaskTraits(GetParam()), TimeDelta());
526
527 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task));
528 }
529
VerifySequencedTaskRunnerHandle(const SequencedTaskRunner * expected_task_runner)530 static void VerifySequencedTaskRunnerHandle(
531 const SequencedTaskRunner* expected_task_runner) {
532 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
533 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
534 EXPECT_EQ(expected_task_runner, SequencedTaskRunnerHandle::Get());
535 }
536
TEST_P(TaskSchedulerTaskTrackerTest,SequencedTaskRunnerHandleIsSetOnSequenced)537 TEST_P(TaskSchedulerTaskTrackerTest,
538 SequencedTaskRunnerHandleIsSetOnSequenced) {
539 scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner);
540
541 // Create a task that will verify that SequencedTaskRunnerHandle is properly
542 // set to |test_task_runner| in its scope per |sequenced_task_runner_ref|
543 // being set to it.
544 Task verify_task(FROM_HERE,
545 BindOnce(&VerifySequencedTaskRunnerHandle,
546 Unretained(test_task_runner.get())),
547 TaskTraits(GetParam()), TimeDelta());
548 verify_task.sequenced_task_runner_ref = test_task_runner;
549
550 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task));
551 }
552
VerifyThreadTaskRunnerHandle(const SingleThreadTaskRunner * expected_task_runner)553 static void VerifyThreadTaskRunnerHandle(
554 const SingleThreadTaskRunner* expected_task_runner) {
555 EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
556 // SequencedTaskRunnerHandle inherits ThreadTaskRunnerHandle for thread.
557 EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
558 EXPECT_EQ(expected_task_runner, ThreadTaskRunnerHandle::Get());
559 }
560
TEST_P(TaskSchedulerTaskTrackerTest,ThreadTaskRunnerHandleIsSetOnSingleThreaded)561 TEST_P(TaskSchedulerTaskTrackerTest,
562 ThreadTaskRunnerHandleIsSetOnSingleThreaded) {
563 scoped_refptr<SingleThreadTaskRunner> test_task_runner(
564 new TestSimpleTaskRunner);
565
566 // Create a task that will verify that ThreadTaskRunnerHandle is properly set
567 // to |test_task_runner| in its scope per |single_thread_task_runner_ref|
568 // being set on it.
569 Task verify_task(FROM_HERE,
570 BindOnce(&VerifyThreadTaskRunnerHandle,
571 Unretained(test_task_runner.get())),
572 TaskTraits(GetParam()), TimeDelta());
573 verify_task.single_thread_task_runner_ref = test_task_runner;
574
575 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task));
576 }
577
TEST_P(TaskSchedulerTaskTrackerTest,FlushPendingDelayedTask)578 TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingDelayedTask) {
579 Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
580 TimeDelta::FromDays(1));
581 tracker_.WillPostTask(&delayed_task);
582 // FlushForTesting() should return even if the delayed task didn't run.
583 tracker_.FlushForTesting();
584 }
585
TEST_P(TaskSchedulerTaskTrackerTest,FlushAsyncForTestingPendingDelayedTask)586 TEST_P(TaskSchedulerTaskTrackerTest, FlushAsyncForTestingPendingDelayedTask) {
587 Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
588 TimeDelta::FromDays(1));
589 tracker_.WillPostTask(&delayed_task);
590 // FlushAsyncForTesting() should callback even if the delayed task didn't run.
591 bool called_back = false;
592 tracker_.FlushAsyncForTesting(
593 BindOnce([](bool* called_back) { *called_back = true; },
594 Unretained(&called_back)));
595 EXPECT_TRUE(called_back);
596 }
597
TEST_P(TaskSchedulerTaskTrackerTest,FlushPendingUndelayedTask)598 TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingUndelayedTask) {
599 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
600 TimeDelta());
601 tracker_.WillPostTask(&undelayed_task);
602
603 // FlushForTesting() shouldn't return before the undelayed task runs.
604 CallFlushFromAnotherThread();
605 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
606 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
607
608 // FlushForTesting() should return after the undelayed task runs.
609 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
610 WAIT_FOR_ASYNC_FLUSH_RETURNED();
611 }
612
TEST_P(TaskSchedulerTaskTrackerTest,FlushAsyncForTestingPendingUndelayedTask)613 TEST_P(TaskSchedulerTaskTrackerTest, FlushAsyncForTestingPendingUndelayedTask) {
614 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
615 TimeDelta());
616 tracker_.WillPostTask(&undelayed_task);
617
618 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
619 WaitableEvent event;
620 tracker_.FlushAsyncForTesting(
621 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
622 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
623 EXPECT_FALSE(event.IsSignaled());
624
625 // FlushAsyncForTesting() should callback after the undelayed task runs.
626 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
627 event.Wait();
628 }
629
TEST_P(TaskSchedulerTaskTrackerTest,PostTaskDuringFlush)630 TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlush) {
631 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
632 TimeDelta());
633 tracker_.WillPostTask(&undelayed_task);
634
635 // FlushForTesting() shouldn't return before the undelayed task runs.
636 CallFlushFromAnotherThread();
637 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
638 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
639
640 // Simulate posting another undelayed task.
641 Task other_undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
642 TimeDelta());
643 tracker_.WillPostTask(&other_undelayed_task);
644
645 // Run the first undelayed task.
646 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
647
648 // FlushForTesting() shouldn't return before the second undelayed task runs.
649 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
650 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
651
652 // FlushForTesting() should return after the second undelayed task runs.
653 DispatchAndRunTaskWithTracker(std::move(other_undelayed_task));
654 WAIT_FOR_ASYNC_FLUSH_RETURNED();
655 }
656
TEST_P(TaskSchedulerTaskTrackerTest,PostTaskDuringFlushAsyncForTesting)657 TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) {
658 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
659 TimeDelta());
660 tracker_.WillPostTask(&undelayed_task);
661
662 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
663 WaitableEvent event;
664 tracker_.FlushAsyncForTesting(
665 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
666 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
667 EXPECT_FALSE(event.IsSignaled());
668
669 // Simulate posting another undelayed task.
670 Task other_undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
671 TimeDelta());
672 tracker_.WillPostTask(&other_undelayed_task);
673
674 // Run the first undelayed task.
675 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
676
677 // FlushAsyncForTesting() shouldn't callback before the second undelayed task
678 // runs.
679 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
680 EXPECT_FALSE(event.IsSignaled());
681
682 // FlushAsyncForTesting() should callback after the second undelayed task
683 // runs.
684 DispatchAndRunTaskWithTracker(std::move(other_undelayed_task));
685 event.Wait();
686 }
687
TEST_P(TaskSchedulerTaskTrackerTest,RunDelayedTaskDuringFlush)688 TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlush) {
689 // Simulate posting a delayed and an undelayed task.
690 Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
691 TimeDelta::FromDays(1));
692 tracker_.WillPostTask(&delayed_task);
693 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
694 TimeDelta());
695 tracker_.WillPostTask(&undelayed_task);
696
697 // FlushForTesting() shouldn't return before the undelayed task runs.
698 CallFlushFromAnotherThread();
699 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
700 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
701
702 // Run the delayed task.
703 DispatchAndRunTaskWithTracker(std::move(delayed_task));
704
705 // FlushForTesting() shouldn't return since there is still a pending undelayed
706 // task.
707 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
708 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
709
710 // Run the undelayed task.
711 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
712
713 // FlushForTesting() should now return.
714 WAIT_FOR_ASYNC_FLUSH_RETURNED();
715 }
716
TEST_P(TaskSchedulerTaskTrackerTest,RunDelayedTaskDuringFlushAsyncForTesting)717 TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlushAsyncForTesting) {
718 // Simulate posting a delayed and an undelayed task.
719 Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
720 TimeDelta::FromDays(1));
721 tracker_.WillPostTask(&delayed_task);
722 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
723 TimeDelta());
724 tracker_.WillPostTask(&undelayed_task);
725
726 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
727 WaitableEvent event;
728 tracker_.FlushAsyncForTesting(
729 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
730 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
731 EXPECT_FALSE(event.IsSignaled());
732
733 // Run the delayed task.
734 DispatchAndRunTaskWithTracker(std::move(delayed_task));
735
736 // FlushAsyncForTesting() shouldn't callback since there is still a pending
737 // undelayed task.
738 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
739 EXPECT_FALSE(event.IsSignaled());
740
741 // Run the undelayed task.
742 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
743
744 // FlushAsyncForTesting() should now callback.
745 event.Wait();
746 }
747
TEST_P(TaskSchedulerTaskTrackerTest,FlushAfterShutdown)748 TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdown) {
749 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
750 return;
751
752 // Simulate posting a task.
753 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
754 TimeDelta());
755 tracker_.WillPostTask(&undelayed_task);
756
757 // Shutdown() should return immediately since there are no pending
758 // BLOCK_SHUTDOWN tasks.
759 tracker_.Shutdown();
760
761 // FlushForTesting() should return immediately after shutdown, even if an
762 // undelayed task hasn't run.
763 tracker_.FlushForTesting();
764 }
765
TEST_P(TaskSchedulerTaskTrackerTest,FlushAfterShutdownAsync)766 TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdownAsync) {
767 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
768 return;
769
770 // Simulate posting a task.
771 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
772 TimeDelta());
773 tracker_.WillPostTask(&undelayed_task);
774
775 // Shutdown() should return immediately since there are no pending
776 // BLOCK_SHUTDOWN tasks.
777 tracker_.Shutdown();
778
779 // FlushForTesting() should callback immediately after shutdown, even if an
780 // undelayed task hasn't run.
781 bool called_back = false;
782 tracker_.FlushAsyncForTesting(
783 BindOnce([](bool* called_back) { *called_back = true; },
784 Unretained(&called_back)));
785 EXPECT_TRUE(called_back);
786 }
787
TEST_P(TaskSchedulerTaskTrackerTest,ShutdownDuringFlush)788 TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlush) {
789 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
790 return;
791
792 // Simulate posting a task.
793 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
794 TimeDelta());
795 tracker_.WillPostTask(&undelayed_task);
796
797 // FlushForTesting() shouldn't return before the undelayed task runs or
798 // shutdown completes.
799 CallFlushFromAnotherThread();
800 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
801 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
802
803 // Shutdown() should return immediately since there are no pending
804 // BLOCK_SHUTDOWN tasks.
805 tracker_.Shutdown();
806
807 // FlushForTesting() should now return, even if an undelayed task hasn't run.
808 WAIT_FOR_ASYNC_FLUSH_RETURNED();
809 }
810
TEST_P(TaskSchedulerTaskTrackerTest,ShutdownDuringFlushAsyncForTesting)811 TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlushAsyncForTesting) {
812 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
813 return;
814
815 // Simulate posting a task.
816 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
817 TimeDelta());
818 tracker_.WillPostTask(&undelayed_task);
819
820 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs or
821 // shutdown completes.
822 WaitableEvent event;
823 tracker_.FlushAsyncForTesting(
824 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
825 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
826 EXPECT_FALSE(event.IsSignaled());
827
828 // Shutdown() should return immediately since there are no pending
829 // BLOCK_SHUTDOWN tasks.
830 tracker_.Shutdown();
831
832 // FlushAsyncForTesting() should now callback, even if an undelayed task
833 // hasn't run.
834 event.Wait();
835 }
836
TEST_P(TaskSchedulerTaskTrackerTest,DoublePendingFlushAsyncForTestingFails)837 TEST_P(TaskSchedulerTaskTrackerTest, DoublePendingFlushAsyncForTestingFails) {
838 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
839 TimeDelta());
840 tracker_.WillPostTask(&undelayed_task);
841
842 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
843 bool called_back = false;
844 tracker_.FlushAsyncForTesting(
845 BindOnce([](bool* called_back) { *called_back = true; },
846 Unretained(&called_back)));
847 EXPECT_FALSE(called_back);
848 EXPECT_DCHECK_DEATH({ tracker_.FlushAsyncForTesting(BindOnce([]() {})); });
849 }
850
851 INSTANTIATE_TEST_CASE_P(
852 ContinueOnShutdown,
853 TaskSchedulerTaskTrackerTest,
854 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
855 INSTANTIATE_TEST_CASE_P(
856 SkipOnShutdown,
857 TaskSchedulerTaskTrackerTest,
858 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
859 INSTANTIATE_TEST_CASE_P(
860 BlockShutdown,
861 TaskSchedulerTaskTrackerTest,
862 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN));
863
864 namespace {
865
ExpectSequenceToken(SequenceToken sequence_token)866 void ExpectSequenceToken(SequenceToken sequence_token) {
867 EXPECT_EQ(sequence_token, SequenceToken::GetForCurrentThread());
868 }
869
870 } // namespace
871
872 // Verify that SequenceToken::GetForCurrentThread() returns the Sequence's token
873 // when a Task runs.
TEST_F(TaskSchedulerTaskTrackerTest,CurrentSequenceToken)874 TEST_F(TaskSchedulerTaskTrackerTest, CurrentSequenceToken) {
875 scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
876
877 const SequenceToken sequence_token = sequence->token();
878 Task task(FROM_HERE, Bind(&ExpectSequenceToken, sequence_token), TaskTraits(),
879 TimeDelta());
880 tracker_.WillPostTask(&task);
881
882 sequence->PushTask(std::move(task));
883
884 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
885 sequence = tracker_.WillScheduleSequence(std::move(sequence),
886 &never_notified_observer_);
887 ASSERT_TRUE(sequence);
888 tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_);
889 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
890 }
891
TEST_F(TaskSchedulerTaskTrackerTest,LoadWillPostAndRunBeforeShutdown)892 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) {
893 // Post and run tasks asynchronously.
894 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
895
896 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
897 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
898 &tracker_, CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
899 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
900 threads.back()->Start();
901
902 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
903 &tracker_, CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN),
904 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
905 threads.back()->Start();
906
907 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
908 &tracker_, CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN),
909 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
910 threads.back()->Start();
911 }
912
913 for (const auto& thread : threads)
914 thread->Join();
915
916 // Expect all tasks to be executed.
917 EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted());
918
919 // Should return immediately because no tasks are blocking shutdown.
920 tracker_.Shutdown();
921 }
922
TEST_F(TaskSchedulerTaskTrackerTest,LoadWillPostBeforeShutdownAndRunDuringShutdown)923 TEST_F(TaskSchedulerTaskTrackerTest,
924 LoadWillPostBeforeShutdownAndRunDuringShutdown) {
925 // Post tasks asynchronously.
926 std::vector<Task> tasks_continue_on_shutdown;
927 std::vector<Task> tasks_skip_on_shutdown;
928 std::vector<Task> tasks_block_shutdown;
929 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
930 tasks_continue_on_shutdown.push_back(
931 CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
932 tasks_skip_on_shutdown.push_back(
933 CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
934 tasks_block_shutdown.push_back(
935 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
936 }
937
938 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads;
939 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
940 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
941 &tracker_, &tasks_continue_on_shutdown[i],
942 ThreadPostingAndRunningTask::Action::WILL_POST, true));
943 post_threads.back()->Start();
944
945 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
946 &tracker_, &tasks_skip_on_shutdown[i],
947 ThreadPostingAndRunningTask::Action::WILL_POST, true));
948 post_threads.back()->Start();
949
950 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
951 &tracker_, &tasks_block_shutdown[i],
952 ThreadPostingAndRunningTask::Action::WILL_POST, true));
953 post_threads.back()->Start();
954 }
955
956 for (const auto& thread : post_threads)
957 thread->Join();
958
959 // Call Shutdown() asynchronously.
960 CallShutdownAsync();
961
962 // Run tasks asynchronously.
963 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads;
964 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
965 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
966 &tracker_, std::move(tasks_continue_on_shutdown[i]),
967 ThreadPostingAndRunningTask::Action::RUN, false));
968 run_threads.back()->Start();
969
970 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
971 &tracker_, std::move(tasks_skip_on_shutdown[i]),
972 ThreadPostingAndRunningTask::Action::RUN, false));
973 run_threads.back()->Start();
974
975 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
976 &tracker_, std::move(tasks_block_shutdown[i]),
977 ThreadPostingAndRunningTask::Action::RUN, false));
978 run_threads.back()->Start();
979 }
980
981 for (const auto& thread : run_threads)
982 thread->Join();
983
984 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
985
986 // Expect BLOCK_SHUTDOWN tasks to have been executed.
987 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
988 }
989
TEST_F(TaskSchedulerTaskTrackerTest,LoadWillPostAndRunDuringShutdown)990 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) {
991 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
992 // block shutdown.
993 Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
994 EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task));
995
996 // Call Shutdown() asynchronously.
997 CallShutdownAsync();
998
999 // Post and run tasks asynchronously.
1000 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
1001
1002 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
1003 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1004 &tracker_, CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
1005 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false));
1006 threads.back()->Start();
1007
1008 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1009 &tracker_, CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN),
1010 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false));
1011 threads.back()->Start();
1012
1013 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
1014 &tracker_, CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN),
1015 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
1016 threads.back()->Start();
1017 }
1018
1019 for (const auto& thread : threads)
1020 thread->Join();
1021
1022 // Expect BLOCK_SHUTDOWN tasks to have been executed.
1023 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
1024
1025 // Shutdown() shouldn't return before |block_shutdown_task| is executed.
1026 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
1027
1028 // Unblock shutdown by running |block_shutdown_task|.
1029 DispatchAndRunTaskWithTracker(std::move(block_shutdown_task));
1030 EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted());
1031 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
1032 }
1033
1034 // Verify that RunAndPopNextTask() returns the sequence from which it ran a task
1035 // when it can be rescheduled.
TEST_F(TaskSchedulerTaskTrackerTest,RunAndPopNextTaskReturnsSequenceToReschedule)1036 TEST_F(TaskSchedulerTaskTrackerTest,
1037 RunAndPopNextTaskReturnsSequenceToReschedule) {
1038 Task task_1(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta());
1039 EXPECT_TRUE(tracker_.WillPostTask(&task_1));
1040 Task task_2(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta());
1041 EXPECT_TRUE(tracker_.WillPostTask(&task_2));
1042
1043 scoped_refptr<Sequence> sequence =
1044 test::CreateSequenceWithTask(std::move(task_1));
1045 sequence->PushTask(std::move(task_2));
1046 EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr));
1047
1048 EXPECT_EQ(sequence, tracker_.RunAndPopNextTask(sequence, nullptr));
1049 }
1050
1051 // Verify that WillScheduleSequence() returns nullptr when it receives a
1052 // background sequence and the maximum number of background sequences that can
1053 // be scheduled concurrently is reached. Verify that an observer is notified
1054 // when a background sequence can be scheduled (i.e. when one of the previously
1055 // scheduled background sequences has run).
TEST_F(TaskSchedulerTaskTrackerTest,WillScheduleBackgroundSequenceWithMaxBackgroundSequences)1056 TEST_F(TaskSchedulerTaskTrackerTest,
1057 WillScheduleBackgroundSequenceWithMaxBackgroundSequences) {
1058 constexpr int kMaxNumScheduledBackgroundSequences = 2;
1059 TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences);
1060
1061 // Simulate posting |kMaxNumScheduledBackgroundSequences| background tasks
1062 // and scheduling the associated sequences. This should succeed.
1063 std::vector<scoped_refptr<Sequence>> scheduled_sequences;
1064 testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
1065 for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
1066 Task task(FROM_HERE, DoNothing(), TaskTraits(TaskPriority::BACKGROUND),
1067 TimeDelta());
1068 EXPECT_TRUE(tracker.WillPostTask(&task));
1069 scoped_refptr<Sequence> sequence =
1070 test::CreateSequenceWithTask(std::move(task));
1071 EXPECT_EQ(sequence,
1072 tracker.WillScheduleSequence(sequence, &never_notified_observer));
1073 scheduled_sequences.push_back(std::move(sequence));
1074 }
1075
1076 // Simulate posting extra background tasks and scheduling the associated
1077 // sequences. This should fail because the maximum number of background
1078 // sequences that can be scheduled concurrently is already reached.
1079 std::vector<std::unique_ptr<bool>> extra_tasks_did_run;
1080 std::vector<
1081 std::unique_ptr<testing::StrictMock<MockCanScheduleSequenceObserver>>>
1082 extra_observers;
1083 std::vector<scoped_refptr<Sequence>> extra_sequences;
1084 for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
1085 extra_tasks_did_run.push_back(std::make_unique<bool>());
1086 Task extra_task(
1087 FROM_HERE,
1088 BindOnce([](bool* extra_task_did_run) { *extra_task_did_run = true; },
1089 Unretained(extra_tasks_did_run.back().get())),
1090 TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
1091 EXPECT_TRUE(tracker.WillPostTask(&extra_task));
1092 extra_sequences.push_back(
1093 test::CreateSequenceWithTask(std::move(extra_task)));
1094 extra_observers.push_back(
1095 std::make_unique<
1096 testing::StrictMock<MockCanScheduleSequenceObserver>>());
1097 EXPECT_EQ(nullptr,
1098 tracker.WillScheduleSequence(extra_sequences.back(),
1099 extra_observers.back().get()));
1100 }
1101
1102 // Run the sequences scheduled at the beginning of the test. Expect an
1103 // observer from |extra_observer| to be notified every time a task finishes to
1104 // run.
1105 for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
1106 EXPECT_CALL(*extra_observers[i].get(),
1107 MockOnCanScheduleSequence(extra_sequences[i].get()));
1108 EXPECT_FALSE(tracker.RunAndPopNextTask(scheduled_sequences[i],
1109 &never_notified_observer));
1110 testing::Mock::VerifyAndClear(extra_observers[i].get());
1111 }
1112
1113 // Run the extra sequences.
1114 for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
1115 EXPECT_FALSE(*extra_tasks_did_run[i]);
1116 EXPECT_FALSE(tracker.RunAndPopNextTask(extra_sequences[i],
1117 &never_notified_observer));
1118 EXPECT_TRUE(*extra_tasks_did_run[i]);
1119 }
1120 }
1121
1122 namespace {
1123
SetBool(bool * arg)1124 void SetBool(bool* arg) {
1125 ASSERT_TRUE(arg);
1126 EXPECT_FALSE(*arg);
1127 *arg = true;
1128 }
1129
1130 } // namespace
1131
1132 // Verify that RunAndPopNextTask() doesn't reschedule the background sequence it
1133 // was assigned if there is a preempted background sequence with an earlier
1134 // sequence time (compared to the next task in the sequence assigned to
1135 // RunAndPopNextTask()).
TEST_F(TaskSchedulerTaskTrackerTest,RunNextBackgroundTaskWithEarlierPendingBackgroundTask)1136 TEST_F(TaskSchedulerTaskTrackerTest,
1137 RunNextBackgroundTaskWithEarlierPendingBackgroundTask) {
1138 constexpr int kMaxNumScheduledBackgroundSequences = 1;
1139 TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences);
1140 testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
1141
1142 // Simulate posting a background task and scheduling the associated sequence.
1143 // This should succeed.
1144 bool task_a_1_did_run = false;
1145 Task task_a_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_1_did_run)),
1146 TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
1147 EXPECT_TRUE(tracker.WillPostTask(&task_a_1));
1148 scoped_refptr<Sequence> sequence_a =
1149 test::CreateSequenceWithTask(std::move(task_a_1));
1150 EXPECT_EQ(sequence_a,
1151 tracker.WillScheduleSequence(sequence_a, &never_notified_observer));
1152
1153 // Simulate posting an extra background task and scheduling the associated
1154 // sequence. This should fail because the maximum number of background
1155 // sequences that can be scheduled concurrently is already reached.
1156 bool task_b_1_did_run = false;
1157 Task task_b_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_b_1_did_run)),
1158 TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
1159 EXPECT_TRUE(tracker.WillPostTask(&task_b_1));
1160 scoped_refptr<Sequence> sequence_b =
1161 test::CreateSequenceWithTask(std::move(task_b_1));
1162 testing::StrictMock<MockCanScheduleSequenceObserver> task_b_1_observer;
1163 EXPECT_FALSE(tracker.WillScheduleSequence(sequence_b, &task_b_1_observer));
1164
1165 // Wait to be sure that the sequence time of |task_a_2| is after the sequenced
1166 // time of |task_b_1|.
1167 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
1168
1169 // Post an extra background task in |sequence_a|.
1170 bool task_a_2_did_run = false;
1171 Task task_a_2(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_2_did_run)),
1172 TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
1173 EXPECT_TRUE(tracker.WillPostTask(&task_a_2));
1174 sequence_a->PushTask(std::move(task_a_2));
1175
1176 // Run the first task in |sequence_a|. RunAndPopNextTask() should return
1177 // nullptr since |sequence_a| can't be rescheduled immediately.
1178 // |task_b_1_observer| should be notified that |sequence_b| can be scheduled.
1179 testing::StrictMock<MockCanScheduleSequenceObserver> task_a_2_observer;
1180 EXPECT_CALL(task_b_1_observer, MockOnCanScheduleSequence(sequence_b.get()));
1181 EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &task_a_2_observer));
1182 testing::Mock::VerifyAndClear(&task_b_1_observer);
1183 EXPECT_TRUE(task_a_1_did_run);
1184
1185 // Run the first task in |sequence_b|. RunAndPopNextTask() should return
1186 // nullptr since |sequence_b| is empty after popping a task from it.
1187 // |task_a_2_observer| should be notified that |sequence_a| can be
1188 // scheduled.
1189 EXPECT_CALL(task_a_2_observer, MockOnCanScheduleSequence(sequence_a.get()));
1190 EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_b, &never_notified_observer));
1191 testing::Mock::VerifyAndClear(&task_a_2_observer);
1192 EXPECT_TRUE(task_b_1_did_run);
1193
1194 // Run the first task in |sequence_a|. RunAndPopNextTask() should return
1195 // nullptr since |sequence_b| is empty after popping a task from it. No
1196 // observer should be notified.
1197 EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &never_notified_observer));
1198 EXPECT_TRUE(task_a_2_did_run);
1199 }
1200
1201 // Verify that preempted background sequences are scheduled when shutdown
1202 // starts.
TEST_F(TaskSchedulerTaskTrackerTest,SchedulePreemptedBackgroundSequencesOnShutdown)1203 TEST_F(TaskSchedulerTaskTrackerTest,
1204 SchedulePreemptedBackgroundSequencesOnShutdown) {
1205 constexpr int kMaxNumScheduledBackgroundSequences = 0;
1206 TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences);
1207 testing::StrictMock<MockCanScheduleSequenceObserver> observer;
1208
1209 // Simulate scheduling sequences. TaskTracker should prevent this.
1210 std::vector<scoped_refptr<Sequence>> preempted_sequences;
1211 for (int i = 0; i < 3; ++i) {
1212 Task task(FROM_HERE, DoNothing(),
1213 TaskTraits(TaskPriority::BACKGROUND,
1214 TaskShutdownBehavior::BLOCK_SHUTDOWN),
1215 TimeDelta());
1216 EXPECT_TRUE(tracker.WillPostTask(&task));
1217 scoped_refptr<Sequence> sequence =
1218 test::CreateSequenceWithTask(std::move(task));
1219 EXPECT_FALSE(tracker.WillScheduleSequence(sequence, &observer));
1220 preempted_sequences.push_back(std::move(sequence));
1221
1222 // Wait to be sure that tasks have different |sequenced_time|.
1223 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
1224 }
1225
1226 // Perform shutdown. Expect |preempted_sequences| to be scheduled in posting
1227 // order.
1228 {
1229 testing::InSequence in_sequence;
1230 for (auto& preempted_sequence : preempted_sequences) {
1231 EXPECT_CALL(observer, MockOnCanScheduleSequence(preempted_sequence.get()))
1232 .WillOnce(testing::Invoke([&tracker](Sequence* sequence) {
1233 // Run the task to unblock shutdown.
1234 tracker.RunAndPopNextTask(sequence, nullptr);
1235 }));
1236 }
1237 tracker.Shutdown();
1238 }
1239 }
1240
1241 namespace {
1242
1243 class WaitAllowedTestThread : public SimpleThread {
1244 public:
WaitAllowedTestThread()1245 WaitAllowedTestThread() : SimpleThread("WaitAllowedTestThread") {}
1246
1247 private:
Run()1248 void Run() override {
1249 auto task_tracker = std::make_unique<TaskTracker>("Test");
1250
1251 // Waiting is allowed by default. Expect TaskTracker to disallow it before
1252 // running a task without the WithBaseSyncPrimitives() trait.
1253 internal::AssertBaseSyncPrimitivesAllowed();
1254 Task task_without_sync_primitives(
1255 FROM_HERE, Bind([]() {
1256 EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
1257 }),
1258 TaskTraits(), TimeDelta());
1259 EXPECT_TRUE(task_tracker->WillPostTask(&task_without_sync_primitives));
1260 testing::StrictMock<MockCanScheduleSequenceObserver>
1261 never_notified_observer;
1262 auto sequence_without_sync_primitives = task_tracker->WillScheduleSequence(
1263 test::CreateSequenceWithTask(std::move(task_without_sync_primitives)),
1264 &never_notified_observer);
1265 ASSERT_TRUE(sequence_without_sync_primitives);
1266 task_tracker->RunAndPopNextTask(std::move(sequence_without_sync_primitives),
1267 &never_notified_observer);
1268
1269 // Disallow waiting. Expect TaskTracker to allow it before running a task
1270 // with the WithBaseSyncPrimitives() trait.
1271 ThreadRestrictions::DisallowWaiting();
1272 Task task_with_sync_primitives(
1273 FROM_HERE, Bind([]() {
1274 // Shouldn't fail.
1275 internal::AssertBaseSyncPrimitivesAllowed();
1276 }),
1277 TaskTraits(WithBaseSyncPrimitives()), TimeDelta());
1278 EXPECT_TRUE(task_tracker->WillPostTask(&task_with_sync_primitives));
1279 auto sequence_with_sync_primitives = task_tracker->WillScheduleSequence(
1280 test::CreateSequenceWithTask(std::move(task_with_sync_primitives)),
1281 &never_notified_observer);
1282 ASSERT_TRUE(sequence_with_sync_primitives);
1283 task_tracker->RunAndPopNextTask(std::move(sequence_with_sync_primitives),
1284 &never_notified_observer);
1285
1286 ScopedAllowBaseSyncPrimitivesForTesting
1287 allow_wait_in_task_tracker_destructor;
1288 task_tracker.reset();
1289 }
1290
1291 DISALLOW_COPY_AND_ASSIGN(WaitAllowedTestThread);
1292 };
1293
1294 } // namespace
1295
1296 // Verify that AssertIOAllowed() succeeds only for a WithBaseSyncPrimitives()
1297 // task.
TEST(TaskSchedulerTaskTrackerWaitAllowedTest,WaitAllowed)1298 TEST(TaskSchedulerTaskTrackerWaitAllowedTest, WaitAllowed) {
1299 // Run the test on the separate thread since it is not possible to reset the
1300 // "wait allowed" bit of a thread without being a friend of
1301 // ThreadRestrictions.
1302 testing::GTEST_FLAG(death_test_style) = "threadsafe";
1303 WaitAllowedTestThread wait_allowed_test_thread;
1304 wait_allowed_test_thread.Start();
1305 wait_allowed_test_thread.Join();
1306 }
1307
1308 // Verify that TaskScheduler.TaskLatency.* histograms are correctly recorded
1309 // when a task runs.
TEST(TaskSchedulerTaskTrackerHistogramTest,TaskLatency)1310 TEST(TaskSchedulerTaskTrackerHistogramTest, TaskLatency) {
1311 auto statistics_recorder = StatisticsRecorder::CreateTemporaryForTesting();
1312
1313 TaskTracker tracker("Test");
1314 testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
1315
1316 struct {
1317 const TaskTraits traits;
1318 const char* const expected_histogram;
1319 } static constexpr kTests[] = {
1320 {{TaskPriority::BACKGROUND},
1321 "TaskScheduler.TaskLatencyMicroseconds.Test."
1322 "BackgroundTaskPriority"},
1323 {{MayBlock(), TaskPriority::BACKGROUND},
1324 "TaskScheduler.TaskLatencyMicroseconds.Test."
1325 "BackgroundTaskPriority_MayBlock"},
1326 {{WithBaseSyncPrimitives(), TaskPriority::BACKGROUND},
1327 "TaskScheduler.TaskLatencyMicroseconds.Test."
1328 "BackgroundTaskPriority_MayBlock"},
1329 {{TaskPriority::USER_VISIBLE},
1330 "TaskScheduler.TaskLatencyMicroseconds.Test."
1331 "UserVisibleTaskPriority"},
1332 {{MayBlock(), TaskPriority::USER_VISIBLE},
1333 "TaskScheduler.TaskLatencyMicroseconds.Test."
1334 "UserVisibleTaskPriority_MayBlock"},
1335 {{WithBaseSyncPrimitives(), TaskPriority::USER_VISIBLE},
1336 "TaskScheduler.TaskLatencyMicroseconds.Test."
1337 "UserVisibleTaskPriority_MayBlock"},
1338 {{TaskPriority::USER_BLOCKING},
1339 "TaskScheduler.TaskLatencyMicroseconds.Test."
1340 "UserBlockingTaskPriority"},
1341 {{MayBlock(), TaskPriority::USER_BLOCKING},
1342 "TaskScheduler.TaskLatencyMicroseconds.Test."
1343 "UserBlockingTaskPriority_MayBlock"},
1344 {{WithBaseSyncPrimitives(), TaskPriority::USER_BLOCKING},
1345 "TaskScheduler.TaskLatencyMicroseconds.Test."
1346 "UserBlockingTaskPriority_MayBlock"}};
1347
1348 for (const auto& test : kTests) {
1349 Task task(FROM_HERE, DoNothing(), test.traits, TimeDelta());
1350 ASSERT_TRUE(tracker.WillPostTask(&task));
1351
1352 HistogramTester tester;
1353
1354 auto sequence = tracker.WillScheduleSequence(
1355 test::CreateSequenceWithTask(std::move(task)),
1356 &never_notified_observer);
1357 ASSERT_TRUE(sequence);
1358 tracker.RunAndPopNextTask(std::move(sequence), &never_notified_observer);
1359 tester.ExpectTotalCount(test.expected_histogram, 1);
1360 }
1361 }
1362
1363 } // namespace internal
1364 } // namespace base
1365