xref: /aosp_15_r20/external/libchrome/base/task_scheduler/task_tracker_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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