blob: 1c7598321382368b54b2ee5e932e96180d515bfb [file] [log] [blame]
fdoray7c1740c2016-03-30 02:12:53 +09001// 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
fdoray29a45012016-07-19 22:18:54 +09007#include <stdint.h>
8
dchengcc8e4d82016-04-05 06:25:51 +09009#include <memory>
fdorayd7a33a62016-10-12 21:21:27 +090010#include <utility>
fdoray29a45012016-07-19 22:18:54 +090011#include <vector>
fdoray7c1740c2016-03-30 02:12:53 +090012
13#include "base/bind.h"
Peter Kasting88430fa2018-02-13 15:22:40 +090014#include "base/bind_helpers.h"
fdoraye4ba8a52016-09-27 01:18:58 +090015#include "base/callback.h"
fdoray7c1740c2016-03-30 02:12:53 +090016#include "base/logging.h"
17#include "base/macros.h"
dchengcc8e4d82016-04-05 06:25:51 +090018#include "base/memory/ptr_util.h"
gab2dbf09a2016-05-03 06:17:47 +090019#include "base/memory/ref_counted.h"
fdoray67c55952017-01-07 05:12:23 +090020#include "base/metrics/histogram_base.h"
21#include "base/metrics/histogram_samples.h"
22#include "base/metrics/statistics_recorder.h"
fdoray3917fe22016-07-27 08:48:06 +090023#include "base/sequence_token.h"
gab2dbf09a2016-05-03 06:17:47 +090024#include "base/sequenced_task_runner.h"
25#include "base/single_thread_task_runner.h"
fdoraye4ba8a52016-09-27 01:18:58 +090026#include "base/synchronization/atomic_flag.h"
fdoray7c1740c2016-03-30 02:12:53 +090027#include "base/synchronization/waitable_event.h"
fdoray29a45012016-07-19 22:18:54 +090028#include "base/task_scheduler/scheduler_lock.h"
fdoray7c1740c2016-03-30 02:12:53 +090029#include "base/task_scheduler/task.h"
30#include "base/task_scheduler/task_traits.h"
Jeffrey He5b18cb92017-06-07 00:36:03 +090031#include "base/task_scheduler/test_utils.h"
gabbcf9c762016-08-02 01:39:56 +090032#include "base/test/gtest_util.h"
fdoray67c55952017-01-07 05:12:23 +090033#include "base/test/histogram_tester.h"
gab2dbf09a2016-05-03 06:17:47 +090034#include "base/test/test_simple_task_runner.h"
fdoraye4ba8a52016-09-27 01:18:58 +090035#include "base/test/test_timeouts.h"
fdoray7c1740c2016-03-30 02:12:53 +090036#include "base/threading/platform_thread.h"
gab2dbf09a2016-05-03 06:17:47 +090037#include "base/threading/sequenced_task_runner_handle.h"
fdoray7c1740c2016-03-30 02:12:53 +090038#include "base/threading/simple_thread.h"
fdoray618e30e2016-04-29 06:08:32 +090039#include "base/threading/thread_restrictions.h"
gab8d1e4562016-05-12 04:53:43 +090040#include "base/threading/thread_task_runner_handle.h"
Francois Doraycfa05a82017-10-13 03:10:17 +090041#include "testing/gmock/include/gmock/gmock.h"
fdoray7c1740c2016-03-30 02:12:53 +090042#include "testing/gtest/include/gtest/gtest.h"
43
44namespace base {
45namespace internal {
46
47namespace {
48
mbjorgee8e43982017-04-12 04:51:45 +090049constexpr size_t kLoadTestNumIterations = 75;
fdoray29a45012016-07-19 22:18:54 +090050
Francois Doraycfa05a82017-10-13 03:10:17 +090051class MockCanScheduleSequenceObserver : public CanScheduleSequenceObserver {
52 public:
53 void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override {
54 MockOnCanScheduleSequence(sequence.get());
55 }
56
57 MOCK_METHOD1(MockOnCanScheduleSequence, void(Sequence*));
58};
59
fdoraye4ba8a52016-09-27 01:18:58 +090060// Invokes a closure asynchronously.
61class CallbackThread : public SimpleThread {
fdoray7c1740c2016-03-30 02:12:53 +090062 public:
fdoraye4ba8a52016-09-27 01:18:58 +090063 explicit CallbackThread(const Closure& closure)
64 : SimpleThread("CallbackThread"), closure_(closure) {}
fdoray7c1740c2016-03-30 02:12:53 +090065
fdoraye4ba8a52016-09-27 01:18:58 +090066 // Returns true once the callback returns.
67 bool has_returned() { return has_returned_.IsSet(); }
fdoray7c1740c2016-03-30 02:12:53 +090068
69 private:
70 void Run() override {
fdoraye4ba8a52016-09-27 01:18:58 +090071 closure_.Run();
72 has_returned_.Set();
fdoray7c1740c2016-03-30 02:12:53 +090073 }
74
fdoraye4ba8a52016-09-27 01:18:58 +090075 const Closure closure_;
76 AtomicFlag has_returned_;
fdoray7c1740c2016-03-30 02:12:53 +090077
fdoraye4ba8a52016-09-27 01:18:58 +090078 DISALLOW_COPY_AND_ASSIGN(CallbackThread);
fdoray7c1740c2016-03-30 02:12:53 +090079};
80
fdoray29a45012016-07-19 22:18:54 +090081class ThreadPostingAndRunningTask : public SimpleThread {
fdoray7c1740c2016-03-30 02:12:53 +090082 public:
fdoray29a45012016-07-19 22:18:54 +090083 enum class Action {
84 WILL_POST,
85 RUN,
86 WILL_POST_AND_RUN,
87 };
88
89 ThreadPostingAndRunningTask(TaskTracker* tracker,
fdoray8b1ab5c2016-09-07 06:06:13 +090090 Task* task,
fdoray29a45012016-07-19 22:18:54 +090091 Action action,
92 bool expect_post_succeeds)
93 : SimpleThread("ThreadPostingAndRunningTask"),
94 tracker_(tracker),
Robert Liao6ce6b3c2017-12-18 10:38:07 +090095 owned_task_(FROM_HERE, OnceClosure(), TaskTraits(), TimeDelta()),
fdoray8b1ab5c2016-09-07 06:06:13 +090096 task_(task),
fdoray29a45012016-07-19 22:18:54 +090097 action_(action),
fdorayd7a33a62016-10-12 21:21:27 +090098 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
106 ThreadPostingAndRunningTask(TaskTracker* tracker,
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900107 Task task,
fdorayd7a33a62016-10-12 21:21:27 +0900108 Action action,
109 bool expect_post_succeeds)
110 : SimpleThread("ThreadPostingAndRunningTask"),
111 tracker_(tracker),
fdorayd7a33a62016-10-12 21:21:27 +0900112 owned_task_(std::move(task)),
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900113 task_(&owned_task_),
fdorayd7a33a62016-10-12 21:21:27 +0900114 action_(action),
115 expect_post_succeeds_(expect_post_succeeds) {
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900116 EXPECT_TRUE(owned_task_.task);
fdorayd7a33a62016-10-12 21:21:27 +0900117 }
fdoray7c1740c2016-03-30 02:12:53 +0900118
119 private:
fdoray29a45012016-07-19 22:18:54 +0900120 void Run() override {
121 bool post_succeeded = true;
122 if (action_ == Action::WILL_POST || action_ == Action::WILL_POST_AND_RUN) {
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900123 post_succeeded = tracker_->WillPostTask(*task_);
fdoray29a45012016-07-19 22:18:54 +0900124 EXPECT_EQ(expect_post_succeeds_, post_succeeded);
125 }
126 if (post_succeeded &&
127 (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) {
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900128 EXPECT_TRUE(owned_task_.task);
Jeffrey He5b18cb92017-06-07 00:36:03 +0900129
Francois Doraycfa05a82017-10-13 03:10:17 +0900130 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);
Robert Liao72b27712018-02-17 04:27:45 +0900136 // 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));
fdoray29a45012016-07-19 22:18:54 +0900140 }
141 }
fdoray7c1740c2016-03-30 02:12:53 +0900142
143 TaskTracker* const tracker_;
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900144 Task owned_task_;
145 Task* task_;
fdoray29a45012016-07-19 22:18:54 +0900146 const Action action_;
147 const bool expect_post_succeeds_;
fdoray7c1740c2016-03-30 02:12:53 +0900148
fdoray29a45012016-07-19 22:18:54 +0900149 DISALLOW_COPY_AND_ASSIGN(ThreadPostingAndRunningTask);
fdoray7c1740c2016-03-30 02:12:53 +0900150};
151
fdoray618e30e2016-04-29 06:08:32 +0900152class ScopedSetSingletonAllowed {
153 public:
154 ScopedSetSingletonAllowed(bool singleton_allowed)
155 : previous_value_(
156 ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {}
157 ~ScopedSetSingletonAllowed() {
158 ThreadRestrictions::SetSingletonAllowed(previous_value_);
159 }
160
161 private:
162 const bool previous_value_;
163};
164
fdoray7c1740c2016-03-30 02:12:53 +0900165class TaskSchedulerTaskTrackerTest
166 : public testing::TestWithParam<TaskShutdownBehavior> {
167 protected:
168 TaskSchedulerTaskTrackerTest() = default;
169
170 // Creates a task with |shutdown_behavior|.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900171 Task CreateTask(TaskShutdownBehavior shutdown_behavior) {
172 return Task(
fdoray7c1740c2016-03-30 02:12:53 +0900173 FROM_HERE,
174 Bind(&TaskSchedulerTaskTrackerTest::RunTaskCallback, Unretained(this)),
fdorayb7013402017-05-09 13:18:32 +0900175 TaskTraits(shutdown_behavior), TimeDelta());
fdoray7c1740c2016-03-30 02:12:53 +0900176 }
177
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900178 void DispatchAndRunTaskWithTracker(Task task) {
Francois Doraycfa05a82017-10-13 03:10:17 +0900179 auto sequence = tracker_.WillScheduleSequence(
180 test::CreateSequenceWithTask(std::move(task)),
181 &never_notified_observer_);
182 ASSERT_TRUE(sequence);
Robert Liao72b27712018-02-17 04:27:45 +0900183 tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_);
Francois Doraycfa05a82017-10-13 03:10:17 +0900184 }
185
fdoray7c1740c2016-03-30 02:12:53 +0900186 // 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.
189 void CallShutdownAsync() {
190 ASSERT_FALSE(thread_calling_shutdown_);
fdoraye4ba8a52016-09-27 01:18:58 +0900191 thread_calling_shutdown_.reset(new CallbackThread(
192 Bind(&TaskTracker::Shutdown, Unretained(&tracker_))));
fdoray7c1740c2016-03-30 02:12:53 +0900193 thread_calling_shutdown_->Start();
fdoray3d51d962016-07-22 22:50:53 +0900194 while (!tracker_.HasShutdownStarted())
fdoray7c1740c2016-03-30 02:12:53 +0900195 PlatformThread::YieldCurrentThread();
fdoray7c1740c2016-03-30 02:12:53 +0900196 }
197
fdoray29a45012016-07-19 22:18:54 +0900198 void WaitForAsyncIsShutdownComplete() {
fdoray7c1740c2016-03-30 02:12:53 +0900199 ASSERT_TRUE(thread_calling_shutdown_);
200 thread_calling_shutdown_->Join();
201 EXPECT_TRUE(thread_calling_shutdown_->has_returned());
fdoray29a45012016-07-19 22:18:54 +0900202 EXPECT_TRUE(tracker_.IsShutdownComplete());
fdoray7c1740c2016-03-30 02:12:53 +0900203 }
204
205 void VerifyAsyncShutdownInProgress() {
206 ASSERT_TRUE(thread_calling_shutdown_);
207 EXPECT_FALSE(thread_calling_shutdown_->has_returned());
fdoray3d51d962016-07-22 22:50:53 +0900208 EXPECT_TRUE(tracker_.HasShutdownStarted());
fdoray29a45012016-07-19 22:18:54 +0900209 EXPECT_FALSE(tracker_.IsShutdownComplete());
fdoray7c1740c2016-03-30 02:12:53 +0900210 }
211
Robert Liaoe25acff2018-01-25 07:39:17 +0900212 // Calls tracker_->FlushForTesting() on a new thread.
Robert Liaof9099912018-01-25 07:29:30 +0900213 void CallFlushFromAnotherThread() {
fdoraye4ba8a52016-09-27 01:18:58 +0900214 ASSERT_FALSE(thread_calling_flush_);
Robert Liaoe25acff2018-01-25 07:39:17 +0900215 thread_calling_flush_.reset(new CallbackThread(
216 Bind(&TaskTracker::FlushForTesting, Unretained(&tracker_))));
fdoraye4ba8a52016-09-27 01:18:58 +0900217 thread_calling_flush_->Start();
218 }
219
220 void WaitForAsyncFlushReturned() {
221 ASSERT_TRUE(thread_calling_flush_);
222 thread_calling_flush_->Join();
223 EXPECT_TRUE(thread_calling_flush_->has_returned());
224 }
225
226 void VerifyAsyncFlushInProgress() {
227 ASSERT_TRUE(thread_calling_flush_);
228 EXPECT_FALSE(thread_calling_flush_->has_returned());
229 }
230
fdoray29a45012016-07-19 22:18:54 +0900231 size_t NumTasksExecuted() {
232 AutoSchedulerLock auto_lock(lock_);
233 return num_tasks_executed_;
234 }
235
Gabriel Charette19075392018-01-19 20:00:53 +0900236 TaskTracker tracker_ = {"Test"};
Francois Doraycfa05a82017-10-13 03:10:17 +0900237 testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer_;
fdoray7c1740c2016-03-30 02:12:53 +0900238
239 private:
fdoray29a45012016-07-19 22:18:54 +0900240 void RunTaskCallback() {
241 AutoSchedulerLock auto_lock(lock_);
242 ++num_tasks_executed_;
243 }
fdoray7c1740c2016-03-30 02:12:53 +0900244
fdoraye4ba8a52016-09-27 01:18:58 +0900245 std::unique_ptr<CallbackThread> thread_calling_shutdown_;
246 std::unique_ptr<CallbackThread> thread_calling_flush_;
fdoray7c1740c2016-03-30 02:12:53 +0900247
fdoray29a45012016-07-19 22:18:54 +0900248 // Synchronizes accesses to |num_tasks_executed_|.
249 SchedulerLock lock_;
250
251 size_t num_tasks_executed_ = 0;
252
fdoray7c1740c2016-03-30 02:12:53 +0900253 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest);
254};
255
256#define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \
257 do { \
258 SCOPED_TRACE(""); \
fdoray29a45012016-07-19 22:18:54 +0900259 WaitForAsyncIsShutdownComplete(); \
fdoray7c1740c2016-03-30 02:12:53 +0900260 } while (false)
261
262#define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \
263 do { \
264 SCOPED_TRACE(""); \
265 VerifyAsyncShutdownInProgress(); \
266 } while (false)
267
fdoraye4ba8a52016-09-27 01:18:58 +0900268#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
fdoray7c1740c2016-03-30 02:12:53 +0900280} // namespace
281
fdorayed7729f2016-04-08 23:51:48 +0900282TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) {
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900283 Task task(CreateTask(GetParam()));
fdoray7c1740c2016-03-30 02:12:53 +0900284
fdorayed7729f2016-04-08 23:51:48 +0900285 // Inform |task_tracker_| that |task| will be posted.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900286 EXPECT_TRUE(tracker_.WillPostTask(task));
fdoray7c1740c2016-03-30 02:12:53 +0900287
fdorayed7729f2016-04-08 23:51:48 +0900288 // Run the task.
fdoray29a45012016-07-19 22:18:54 +0900289 EXPECT_EQ(0U, NumTasksExecuted());
Jeffrey He5b18cb92017-06-07 00:36:03 +0900290
Francois Doraycfa05a82017-10-13 03:10:17 +0900291 DispatchAndRunTaskWithTracker(std::move(task));
fdoray29a45012016-07-19 22:18:54 +0900292 EXPECT_EQ(1U, NumTasksExecuted());
fdoray7c1740c2016-03-30 02:12:53 +0900293
294 // Shutdown() shouldn't block.
295 tracker_.Shutdown();
296}
297
fdorayed7729f2016-04-08 23:51:48 +0900298TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) {
fdorayaee83de2017-04-07 21:36:21 +0900299 // 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);
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900305 Task blocked_task(
fdorayaee83de2017-04-07 21:36:21 +0900306 FROM_HERE,
307 Bind(
308 [](WaitableEvent* task_running, WaitableEvent* task_barrier) {
309 task_running->Signal();
310 task_barrier->Wait();
311 },
fdorayb7013402017-05-09 13:18:32 +0900312 Unretained(&task_running), Unretained(&task_barrier)),
313 TaskTraits(WithBaseSyncPrimitives(), GetParam()), TimeDelta());
fdorayed7729f2016-04-08 23:51:48 +0900314
315 // Inform |task_tracker_| that |blocked_task| will be posted.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900316 EXPECT_TRUE(tracker_.WillPostTask(blocked_task));
fdoray7c1740c2016-03-30 02:12:53 +0900317
fdorayaee83de2017-04-07 21:36:21 +0900318 // Create a thread to run the task. Wait until the task starts running.
fdoray29a45012016-07-19 22:18:54 +0900319 ThreadPostingAndRunningTask thread_running_task(
fdorayd7a33a62016-10-12 21:21:27 +0900320 &tracker_, std::move(blocked_task),
321 ThreadPostingAndRunningTask::Action::RUN, false);
fdoray7c1740c2016-03-30 02:12:53 +0900322 thread_running_task.Start();
fdorayaee83de2017-04-07 21:36:21 +0900323 task_running.Wait();
fdoray7c1740c2016-03-30 02:12:53 +0900324
Francois Doray5f643432017-10-12 01:27:12 +0900325 // Initiate shutdown after the task has started to run.
fdoray7c1740c2016-03-30 02:12:53 +0900326 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.
fdorayaee83de2017-04-07 21:36:21 +0900337 task_barrier.Signal();
fdoray7c1740c2016-03-30 02:12:53 +0900338 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
fdorayed7729f2016-04-08 23:51:48 +0900345TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) {
346 // Inform |task_tracker_| that a task will be posted.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900347 Task task(CreateTask(GetParam()));
348 EXPECT_TRUE(tracker_.WillPostTask(task));
fdoray7c1740c2016-03-30 02:12:53 +0900349
fdorayed7729f2016-04-08 23:51:48 +0900350 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
351 // block shutdown.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900352 Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
353 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task));
fdoray7c1740c2016-03-30 02:12:53 +0900354
355 // Call Shutdown() asynchronously.
356 CallShutdownAsync();
357 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
358
fdorayed7729f2016-04-08 23:51:48 +0900359 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it
360 // should be discarded.
fdoray29a45012016-07-19 22:18:54 +0900361 EXPECT_EQ(0U, NumTasksExecuted());
fdoray8b1ab5c2016-09-07 06:06:13 +0900362 const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN;
Jeffrey He5b18cb92017-06-07 00:36:03 +0900363
Francois Doraycfa05a82017-10-13 03:10:17 +0900364 DispatchAndRunTaskWithTracker(std::move(task));
fdoray8b1ab5c2016-09-07 06:06:13 +0900365 EXPECT_EQ(should_run ? 1U : 0U, NumTasksExecuted());
fdoray7c1740c2016-03-30 02:12:53 +0900366 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
367
368 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task.
Francois Doraycfa05a82017-10-13 03:10:17 +0900369 DispatchAndRunTaskWithTracker(std::move(block_shutdown_task));
fdoray8b1ab5c2016-09-07 06:06:13 +0900370 EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted());
fdoray7c1740c2016-03-30 02:12:53 +0900371 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
372}
373
fdorayed7729f2016-04-08 23:51:48 +0900374TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) {
375 // Inform |task_tracker_| that a task will be posted.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900376 Task task(CreateTask(GetParam()));
377 EXPECT_TRUE(tracker_.WillPostTask(task));
fdoray7c1740c2016-03-30 02:12:53 +0900378
379 // Call Shutdown() asynchronously.
380 CallShutdownAsync();
fdoray29a45012016-07-19 22:18:54 +0900381 EXPECT_EQ(0U, NumTasksExecuted());
fdoray7c1740c2016-03-30 02:12:53 +0900382
383 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
384 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
385
386 // Run the task to unblock shutdown.
Francois Doraycfa05a82017-10-13 03:10:17 +0900387 DispatchAndRunTaskWithTracker(std::move(task));
fdoray29a45012016-07-19 22:18:54 +0900388 EXPECT_EQ(1U, NumTasksExecuted());
fdoray7c1740c2016-03-30 02:12:53 +0900389 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.
Francois Doraycfa05a82017-10-13 03:10:17 +0900398 DispatchAndRunTaskWithTracker(std::move(task));
fdoray29a45012016-07-19 22:18:54 +0900399 EXPECT_EQ(0U, NumTasksExecuted());
fdoray7c1740c2016-03-30 02:12:53 +0900400 }
401}
402
fdorayed7729f2016-04-08 23:51:48 +0900403TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) {
404 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
405 // block shutdown.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900406 Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
407 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task));
fdoray7c1740c2016-03-30 02:12:53 +0900408
409 // Call Shutdown() asynchronously.
410 CallShutdownAsync();
411 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
412
413 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
fdorayed7729f2016-04-08 23:51:48 +0900414 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900415 Task task(CreateTask(GetParam()));
416 EXPECT_TRUE(tracker_.WillPostTask(task));
fdoray7c1740c2016-03-30 02:12:53 +0900417
fdorayed7729f2016-04-08 23:51:48 +0900418 // Run the BLOCK_SHUTDOWN task.
fdoray29a45012016-07-19 22:18:54 +0900419 EXPECT_EQ(0U, NumTasksExecuted());
Francois Doraycfa05a82017-10-13 03:10:17 +0900420 DispatchAndRunTaskWithTracker(std::move(task));
fdoray29a45012016-07-19 22:18:54 +0900421 EXPECT_EQ(1U, NumTasksExecuted());
fdoray7c1740c2016-03-30 02:12:53 +0900422 } else {
fdorayed7729f2016-04-08 23:51:48 +0900423 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900424 Task task(CreateTask(GetParam()));
425 EXPECT_FALSE(tracker_.WillPostTask(task));
fdoray7c1740c2016-03-30 02:12:53 +0900426
fdorayed7729f2016-04-08 23:51:48 +0900427 // Don't try to run the task, because it wasn't allowed to be posted.
fdoray7c1740c2016-03-30 02:12:53 +0900428 }
429
fdorayed7729f2016-04-08 23:51:48 +0900430 // Unblock shutdown by running |block_shutdown_task|.
fdoray7c1740c2016-03-30 02:12:53 +0900431 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
Francois Doraycfa05a82017-10-13 03:10:17 +0900432 DispatchAndRunTaskWithTracker(std::move(block_shutdown_task));
fdoray7c1740c2016-03-30 02:12:53 +0900433 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U,
fdoray29a45012016-07-19 22:18:54 +0900434 NumTasksExecuted());
fdoray7c1740c2016-03-30 02:12:53 +0900435 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
436}
437
fdorayed7729f2016-04-08 23:51:48 +0900438TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) {
fdoray7c1740c2016-03-30 02:12:53 +0900439 tracker_.Shutdown();
fdoray7c1740c2016-03-30 02:12:53 +0900440
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900441 Task task(CreateTask(GetParam()));
fdorayed7729f2016-04-08 23:51:48 +0900442
443 // |task_tracker_| shouldn't allow a task to be posted after shutdown.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900444 EXPECT_FALSE(tracker_.WillPostTask(task));
fdoray7c1740c2016-03-30 02:12:53 +0900445}
446
fdoray618e30e2016-04-29 06:08:32 +0900447// Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can
448// AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't.
449TEST_P(TaskSchedulerTaskTrackerTest, SingletonAllowed) {
450 const bool can_use_singletons =
451 (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN);
452
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900453 Task task(FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed),
454 TaskTraits(GetParam()), TimeDelta());
455 EXPECT_TRUE(tracker_.WillPostTask(task));
fdoray618e30e2016-04-29 06:08:32 +0900456
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) {
Francois Doraycfa05a82017-10-13 03:10:17 +0900464 DispatchAndRunTaskWithTracker(std::move(task));
fdoray618e30e2016-04-29 06:08:32 +0900465 } else {
Francois Doraycfa05a82017-10-13 03:10:17 +0900466 EXPECT_DCHECK_DEATH({ DispatchAndRunTaskWithTracker(std::move(task)); });
fdoray618e30e2016-04-29 06:08:32 +0900467 }
468}
469
fdorayf0867732016-12-21 09:26:51 +0900470// Verify that AssertIOAllowed() succeeds only for a MayBlock() task.
fdoray97b2e642016-12-03 00:42:20 +0900471TEST_P(TaskSchedulerTaskTrackerTest, IOAllowed) {
fdoray97b2e642016-12-03 00:42:20 +0900472 // Unset the IO allowed bit. Expect TaskTracker to set it before running a
fdorayf0867732016-12-21 09:26:51 +0900473 // task with the MayBlock() trait.
fdoray97b2e642016-12-03 00:42:20 +0900474 ThreadRestrictions::SetIOAllowed(false);
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900475 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));
Francois Doraycfa05a82017-10-13 03:10:17 +0900481 DispatchAndRunTaskWithTracker(std::move(task_with_may_block));
fdoray97b2e642016-12-03 00:42:20 +0900482
483 // Set the IO allowed bit. Expect TaskTracker to unset it before running a
fdorayf0867732016-12-21 09:26:51 +0900484 // task without the MayBlock() trait.
fdoray97b2e642016-12-03 00:42:20 +0900485 ThreadRestrictions::SetIOAllowed(true);
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900486 Task task_without_may_block(
Francois Dorayed9daa62017-10-20 22:50:37 +0900487 FROM_HERE,
488 Bind([]() { EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); }); }),
fdorayb7013402017-05-09 13:18:32 +0900489 TaskTraits(GetParam()), TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900490 EXPECT_TRUE(tracker_.WillPostTask(task_without_may_block));
Francois Doraycfa05a82017-10-13 03:10:17 +0900491 DispatchAndRunTaskWithTracker(std::move(task_without_may_block));
fdoray97b2e642016-12-03 00:42:20 +0900492}
493
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900494static void RunTaskRunnerHandleVerificationTask(TaskTracker* tracker,
495 Task verify_task) {
gab2dbf09a2016-05-03 06:17:47 +0900496 // Pretend |verify_task| is posted to respect TaskTracker's contract.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900497 EXPECT_TRUE(tracker->WillPostTask(verify_task));
gab2dbf09a2016-05-03 06:17:47 +0900498
499 // Confirm that the test conditions are right (no TaskRunnerHandles set
500 // already).
501 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
502 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
503
Francois Doraycfa05a82017-10-13 03:10:17 +0900504 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);
Robert Liao72b27712018-02-17 04:27:45 +0900509 tracker->RunAndPopNextTask(std::move(sequence), &never_notified_observer);
gab2dbf09a2016-05-03 06:17:47 +0900510
511 // TaskRunnerHandle state is reset outside of task's scope.
512 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
513 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
514}
515
516static void VerifyNoTaskRunnerHandle() {
517 EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
518 EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
519}
520
521TEST_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.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900524 Task verify_task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle),
525 TaskTraits(GetParam()), TimeDelta());
gab2dbf09a2016-05-03 06:17:47 +0900526
fdoray3917fe22016-07-27 08:48:06 +0900527 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task));
gab2dbf09a2016-05-03 06:17:47 +0900528}
529
530static 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
537TEST_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.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900544 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;
gab2dbf09a2016-05-03 06:17:47 +0900549
fdoray3917fe22016-07-27 08:48:06 +0900550 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task));
gab2dbf09a2016-05-03 06:17:47 +0900551}
552
553static 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
561TEST_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.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900569 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;
gab2dbf09a2016-05-03 06:17:47 +0900574
fdoray3917fe22016-07-27 08:48:06 +0900575 RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task));
gab2dbf09a2016-05-03 06:17:47 +0900576}
577
fdoraye4ba8a52016-09-27 01:18:58 +0900578TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingDelayedTask) {
Peter Kasting24efe5e2018-02-24 09:03:01 +0900579 const Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
580 TimeDelta::FromDays(1));
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900581 tracker_.WillPostTask(delayed_task);
Robert Liaoe25acff2018-01-25 07:39:17 +0900582 // FlushForTesting() should return even if the delayed task didn't run.
583 tracker_.FlushForTesting();
fdoraye4ba8a52016-09-27 01:18:58 +0900584}
585
Robert Liaof9099912018-01-25 07:29:30 +0900586TEST_P(TaskSchedulerTaskTrackerTest, FlushAsyncForTestingPendingDelayedTask) {
Peter Kasting24efe5e2018-02-24 09:03:01 +0900587 const Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
588 TimeDelta::FromDays(1));
Robert Liaof9099912018-01-25 07:29:30 +0900589 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
fdoraye4ba8a52016-09-27 01:18:58 +0900598TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingUndelayedTask) {
Peter Kasting24efe5e2018-02-24 09:03:01 +0900599 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900600 TimeDelta());
601 tracker_.WillPostTask(undelayed_task);
fdoraye4ba8a52016-09-27 01:18:58 +0900602
Robert Liaoe25acff2018-01-25 07:39:17 +0900603 // FlushForTesting() shouldn't return before the undelayed task runs.
Robert Liaof9099912018-01-25 07:29:30 +0900604 CallFlushFromAnotherThread();
fdoraye4ba8a52016-09-27 01:18:58 +0900605 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
606 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
607
Robert Liaoe25acff2018-01-25 07:39:17 +0900608 // FlushForTesting() should return after the undelayed task runs.
Francois Doraycfa05a82017-10-13 03:10:17 +0900609 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
fdoraye4ba8a52016-09-27 01:18:58 +0900610 WAIT_FOR_ASYNC_FLUSH_RETURNED();
611}
612
Robert Liaof9099912018-01-25 07:29:30 +0900613TEST_P(TaskSchedulerTaskTrackerTest, FlushAsyncForTestingPendingUndelayedTask) {
Peter Kasting24efe5e2018-02-24 09:03:01 +0900614 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liaof9099912018-01-25 07:29:30 +0900615 TimeDelta());
616 tracker_.WillPostTask(undelayed_task);
617
618 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
619 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
620 WaitableEvent::InitialState::NOT_SIGNALED);
621 tracker_.FlushAsyncForTesting(
622 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
623 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
624 EXPECT_FALSE(event.IsSignaled());
625
626 // FlushAsyncForTesting() should callback after the undelayed task runs.
627 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
628 event.Wait();
629}
630
fdoraye4ba8a52016-09-27 01:18:58 +0900631TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlush) {
Peter Kasting24efe5e2018-02-24 09:03:01 +0900632 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900633 TimeDelta());
634 tracker_.WillPostTask(undelayed_task);
fdoraye4ba8a52016-09-27 01:18:58 +0900635
Robert Liaoe25acff2018-01-25 07:39:17 +0900636 // FlushForTesting() shouldn't return before the undelayed task runs.
Robert Liaof9099912018-01-25 07:29:30 +0900637 CallFlushFromAnotherThread();
fdoraye4ba8a52016-09-27 01:18:58 +0900638 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
639 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
640
641 // Simulate posting another undelayed task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900642 Task other_undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900643 TimeDelta());
644 tracker_.WillPostTask(other_undelayed_task);
fdoraye4ba8a52016-09-27 01:18:58 +0900645
646 // Run the first undelayed task.
Francois Doraycfa05a82017-10-13 03:10:17 +0900647 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
fdoraye4ba8a52016-09-27 01:18:58 +0900648
Robert Liaoe25acff2018-01-25 07:39:17 +0900649 // FlushForTesting() shouldn't return before the second undelayed task runs.
fdoraye4ba8a52016-09-27 01:18:58 +0900650 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
651 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
652
Robert Liaoe25acff2018-01-25 07:39:17 +0900653 // FlushForTesting() should return after the second undelayed task runs.
Francois Doraycfa05a82017-10-13 03:10:17 +0900654 DispatchAndRunTaskWithTracker(std::move(other_undelayed_task));
fdoraye4ba8a52016-09-27 01:18:58 +0900655 WAIT_FOR_ASYNC_FLUSH_RETURNED();
656}
657
Robert Liaof9099912018-01-25 07:29:30 +0900658TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) {
Peter Kasting24efe5e2018-02-24 09:03:01 +0900659 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liaof9099912018-01-25 07:29:30 +0900660 TimeDelta());
661 tracker_.WillPostTask(undelayed_task);
662
663 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
664 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
665 WaitableEvent::InitialState::NOT_SIGNALED);
666 tracker_.FlushAsyncForTesting(
667 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
668 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
669 EXPECT_FALSE(event.IsSignaled());
670
671 // Simulate posting another undelayed task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900672 Task other_undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liaof9099912018-01-25 07:29:30 +0900673 TimeDelta());
674 tracker_.WillPostTask(other_undelayed_task);
675
676 // Run the first undelayed task.
677 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
678
679 // FlushAsyncForTesting() shouldn't callback before the second undelayed task
680 // runs.
681 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
682 EXPECT_FALSE(event.IsSignaled());
683
684 // FlushAsyncForTesting() should callback after the second undelayed task
685 // runs.
686 DispatchAndRunTaskWithTracker(std::move(other_undelayed_task));
687 event.Wait();
688}
689
fdoraye4ba8a52016-09-27 01:18:58 +0900690TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlush) {
691 // Simulate posting a delayed and an undelayed task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900692 Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900693 TimeDelta::FromDays(1));
694 tracker_.WillPostTask(delayed_task);
Peter Kasting24efe5e2018-02-24 09:03:01 +0900695 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900696 TimeDelta());
697 tracker_.WillPostTask(undelayed_task);
fdoraye4ba8a52016-09-27 01:18:58 +0900698
Robert Liaoe25acff2018-01-25 07:39:17 +0900699 // FlushForTesting() shouldn't return before the undelayed task runs.
Robert Liaof9099912018-01-25 07:29:30 +0900700 CallFlushFromAnotherThread();
fdoraye4ba8a52016-09-27 01:18:58 +0900701 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
702 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
703
704 // Run the delayed task.
Francois Doraycfa05a82017-10-13 03:10:17 +0900705 DispatchAndRunTaskWithTracker(std::move(delayed_task));
fdoraye4ba8a52016-09-27 01:18:58 +0900706
Robert Liaoe25acff2018-01-25 07:39:17 +0900707 // FlushForTesting() shouldn't return since there is still a pending undelayed
fdoraye4ba8a52016-09-27 01:18:58 +0900708 // task.
709 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
710 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
711
712 // Run the undelayed task.
Francois Doraycfa05a82017-10-13 03:10:17 +0900713 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
fdoraye4ba8a52016-09-27 01:18:58 +0900714
Robert Liaoe25acff2018-01-25 07:39:17 +0900715 // FlushForTesting() should now return.
fdoraye4ba8a52016-09-27 01:18:58 +0900716 WAIT_FOR_ASYNC_FLUSH_RETURNED();
717}
718
Robert Liaof9099912018-01-25 07:29:30 +0900719TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlushAsyncForTesting) {
720 // Simulate posting a delayed and an undelayed task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900721 Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liaof9099912018-01-25 07:29:30 +0900722 TimeDelta::FromDays(1));
723 tracker_.WillPostTask(delayed_task);
Peter Kasting24efe5e2018-02-24 09:03:01 +0900724 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liaof9099912018-01-25 07:29:30 +0900725 TimeDelta());
726 tracker_.WillPostTask(undelayed_task);
727
728 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
729 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
730 WaitableEvent::InitialState::NOT_SIGNALED);
731 tracker_.FlushAsyncForTesting(
732 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
733 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
734 EXPECT_FALSE(event.IsSignaled());
735
736 // Run the delayed task.
737 DispatchAndRunTaskWithTracker(std::move(delayed_task));
738
739 // FlushAsyncForTesting() shouldn't callback since there is still a pending
740 // undelayed task.
741 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
742 EXPECT_FALSE(event.IsSignaled());
743
744 // Run the undelayed task.
745 DispatchAndRunTaskWithTracker(std::move(undelayed_task));
746
747 // FlushAsyncForTesting() should now callback.
748 event.Wait();
749}
750
fdoraye4ba8a52016-09-27 01:18:58 +0900751TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdown) {
752 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
753 return;
754
755 // Simulate posting a task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900756 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900757 TimeDelta());
758 tracker_.WillPostTask(undelayed_task);
fdoraye4ba8a52016-09-27 01:18:58 +0900759
760 // Shutdown() should return immediately since there are no pending
761 // BLOCK_SHUTDOWN tasks.
762 tracker_.Shutdown();
763
Robert Liaoe25acff2018-01-25 07:39:17 +0900764 // FlushForTesting() should return immediately after shutdown, even if an
fdoraye4ba8a52016-09-27 01:18:58 +0900765 // undelayed task hasn't run.
Robert Liaoe25acff2018-01-25 07:39:17 +0900766 tracker_.FlushForTesting();
fdoraye4ba8a52016-09-27 01:18:58 +0900767}
768
Robert Liaof9099912018-01-25 07:29:30 +0900769TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdownAsync) {
770 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
771 return;
772
773 // Simulate posting a task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900774 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liaof9099912018-01-25 07:29:30 +0900775 TimeDelta());
776 tracker_.WillPostTask(undelayed_task);
777
778 // Shutdown() should return immediately since there are no pending
779 // BLOCK_SHUTDOWN tasks.
780 tracker_.Shutdown();
781
Robert Liaoe25acff2018-01-25 07:39:17 +0900782 // FlushForTesting() should callback immediately after shutdown, even if an
783 // undelayed task hasn't run.
Robert Liaof9099912018-01-25 07:29:30 +0900784 bool called_back = false;
785 tracker_.FlushAsyncForTesting(
786 BindOnce([](bool* called_back) { *called_back = true; },
787 Unretained(&called_back)));
788 EXPECT_TRUE(called_back);
789}
790
fdoraye4ba8a52016-09-27 01:18:58 +0900791TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlush) {
792 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
793 return;
794
795 // Simulate posting a task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900796 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900797 TimeDelta());
798 tracker_.WillPostTask(undelayed_task);
fdoraye4ba8a52016-09-27 01:18:58 +0900799
Robert Liaoe25acff2018-01-25 07:39:17 +0900800 // FlushForTesting() shouldn't return before the undelayed task runs or
fdoraye4ba8a52016-09-27 01:18:58 +0900801 // shutdown completes.
Robert Liaof9099912018-01-25 07:29:30 +0900802 CallFlushFromAnotherThread();
fdoraye4ba8a52016-09-27 01:18:58 +0900803 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
804 VERIFY_ASYNC_FLUSH_IN_PROGRESS();
805
806 // Shutdown() should return immediately since there are no pending
807 // BLOCK_SHUTDOWN tasks.
808 tracker_.Shutdown();
809
Robert Liaoe25acff2018-01-25 07:39:17 +0900810 // FlushForTesting() should now return, even if an undelayed task hasn't run.
fdoraye4ba8a52016-09-27 01:18:58 +0900811 WAIT_FOR_ASYNC_FLUSH_RETURNED();
812}
813
Robert Liaof9099912018-01-25 07:29:30 +0900814TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlushAsyncForTesting) {
815 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
816 return;
817
818 // Simulate posting a task.
Peter Kasting24efe5e2018-02-24 09:03:01 +0900819 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liaof9099912018-01-25 07:29:30 +0900820 TimeDelta());
821 tracker_.WillPostTask(undelayed_task);
822
823 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs or
824 // shutdown completes.
825 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
826 WaitableEvent::InitialState::NOT_SIGNALED);
827 tracker_.FlushAsyncForTesting(
828 BindOnce(&WaitableEvent::Signal, Unretained(&event)));
829 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
830 EXPECT_FALSE(event.IsSignaled());
831
832 // Shutdown() should return immediately since there are no pending
833 // BLOCK_SHUTDOWN tasks.
834 tracker_.Shutdown();
835
836 // FlushAsyncForTesting() should now callback, even if an undelayed task
837 // hasn't run.
838 event.Wait();
839}
840
841TEST_P(TaskSchedulerTaskTrackerTest, DoublePendingFlushAsyncForTestingFails) {
Peter Kasting24efe5e2018-02-24 09:03:01 +0900842 Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
Robert Liaof9099912018-01-25 07:29:30 +0900843 TimeDelta());
844 tracker_.WillPostTask(undelayed_task);
845
846 // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
847 bool called_back = false;
848 tracker_.FlushAsyncForTesting(
849 BindOnce([](bool* called_back) { *called_back = true; },
850 Unretained(&called_back)));
851 EXPECT_FALSE(called_back);
852 EXPECT_DCHECK_DEATH({ tracker_.FlushAsyncForTesting(BindOnce([]() {})); });
853}
854
fdoray7c1740c2016-03-30 02:12:53 +0900855INSTANTIATE_TEST_CASE_P(
856 ContinueOnShutdown,
857 TaskSchedulerTaskTrackerTest,
858 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
859INSTANTIATE_TEST_CASE_P(
860 SkipOnShutdown,
861 TaskSchedulerTaskTrackerTest,
862 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
863INSTANTIATE_TEST_CASE_P(
864 BlockShutdown,
865 TaskSchedulerTaskTrackerTest,
866 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN));
867
fdoray3917fe22016-07-27 08:48:06 +0900868namespace {
869
870void ExpectSequenceToken(SequenceToken sequence_token) {
871 EXPECT_EQ(sequence_token, SequenceToken::GetForCurrentThread());
872}
873
874} // namespace
875
876// Verify that SequenceToken::GetForCurrentThread() returns the Sequence's token
877// when a Task runs.
878TEST_F(TaskSchedulerTaskTrackerTest, CurrentSequenceToken) {
Jeffrey He5b18cb92017-06-07 00:36:03 +0900879 scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
880
881 const SequenceToken sequence_token = sequence->token();
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900882 Task task(FROM_HERE, Bind(&ExpectSequenceToken, sequence_token), TaskTraits(),
883 TimeDelta());
884 tracker_.WillPostTask(task);
fdoray3917fe22016-07-27 08:48:06 +0900885
Jeffrey He5b18cb92017-06-07 00:36:03 +0900886 sequence->PushTask(std::move(task));
887
fdoray3917fe22016-07-27 08:48:06 +0900888 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
Francois Doraycfa05a82017-10-13 03:10:17 +0900889 sequence = tracker_.WillScheduleSequence(std::move(sequence),
890 &never_notified_observer_);
891 ASSERT_TRUE(sequence);
Robert Liao72b27712018-02-17 04:27:45 +0900892 tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_);
fdoray3917fe22016-07-27 08:48:06 +0900893 EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
894}
895
fdoray29a45012016-07-19 22:18:54 +0900896TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) {
897 // Post and run tasks asynchronously.
fdoray29a45012016-07-19 22:18:54 +0900898 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
899
900 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
Jeremy Romancd0c4672017-08-17 08:27:24 +0900901 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
fdorayd7a33a62016-10-12 21:21:27 +0900902 &tracker_, CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
ricead95e71b2016-09-13 13:10:11 +0900903 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
fdoray29a45012016-07-19 22:18:54 +0900904 threads.back()->Start();
905
Jeremy Romancd0c4672017-08-17 08:27:24 +0900906 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
fdorayd7a33a62016-10-12 21:21:27 +0900907 &tracker_, CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN),
ricead95e71b2016-09-13 13:10:11 +0900908 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
fdoray29a45012016-07-19 22:18:54 +0900909 threads.back()->Start();
910
Jeremy Romancd0c4672017-08-17 08:27:24 +0900911 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
fdorayd7a33a62016-10-12 21:21:27 +0900912 &tracker_, CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN),
ricead95e71b2016-09-13 13:10:11 +0900913 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
fdoray29a45012016-07-19 22:18:54 +0900914 threads.back()->Start();
915 }
916
917 for (const auto& thread : threads)
918 thread->Join();
919
920 // Expect all tasks to be executed.
921 EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted());
922
923 // Should return immediately because no tasks are blocking shutdown.
924 tracker_.Shutdown();
925}
926
927TEST_F(TaskSchedulerTaskTrackerTest,
928 LoadWillPostBeforeShutdownAndRunDuringShutdown) {
929 // Post tasks asynchronously.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900930 std::vector<Task> tasks_continue_on_shutdown;
931 std::vector<Task> tasks_skip_on_shutdown;
932 std::vector<Task> tasks_block_shutdown;
fdoray29a45012016-07-19 22:18:54 +0900933 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900934 tasks_continue_on_shutdown.push_back(
935 CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
936 tasks_skip_on_shutdown.push_back(
937 CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
938 tasks_block_shutdown.push_back(
939 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
940 }
941
942 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads;
943 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
Jeremy Romancd0c4672017-08-17 08:27:24 +0900944 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900945 &tracker_, &tasks_continue_on_shutdown[i],
ricead95e71b2016-09-13 13:10:11 +0900946 ThreadPostingAndRunningTask::Action::WILL_POST, true));
fdoray29a45012016-07-19 22:18:54 +0900947 post_threads.back()->Start();
948
Jeremy Romancd0c4672017-08-17 08:27:24 +0900949 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900950 &tracker_, &tasks_skip_on_shutdown[i],
ricead95e71b2016-09-13 13:10:11 +0900951 ThreadPostingAndRunningTask::Action::WILL_POST, true));
fdoray29a45012016-07-19 22:18:54 +0900952 post_threads.back()->Start();
953
Jeremy Romancd0c4672017-08-17 08:27:24 +0900954 post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900955 &tracker_, &tasks_block_shutdown[i],
ricead95e71b2016-09-13 13:10:11 +0900956 ThreadPostingAndRunningTask::Action::WILL_POST, true));
fdoray29a45012016-07-19 22:18:54 +0900957 post_threads.back()->Start();
958 }
959
960 for (const auto& thread : post_threads)
961 thread->Join();
962
963 // Call Shutdown() asynchronously.
964 CallShutdownAsync();
965
966 // Run tasks asynchronously.
967 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads;
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900968 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
Jeremy Romancd0c4672017-08-17 08:27:24 +0900969 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900970 &tracker_, std::move(tasks_continue_on_shutdown[i]),
971 ThreadPostingAndRunningTask::Action::RUN, false));
972 run_threads.back()->Start();
973
974 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
975 &tracker_, std::move(tasks_skip_on_shutdown[i]),
976 ThreadPostingAndRunningTask::Action::RUN, false));
977 run_threads.back()->Start();
978
979 run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
980 &tracker_, std::move(tasks_block_shutdown[i]),
981 ThreadPostingAndRunningTask::Action::RUN, false));
fdoray29a45012016-07-19 22:18:54 +0900982 run_threads.back()->Start();
983 }
984
985 for (const auto& thread : run_threads)
986 thread->Join();
987
988 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
989
990 // Expect BLOCK_SHUTDOWN tasks to have been executed.
991 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
992}
993
994TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) {
995 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
996 // block shutdown.
Robert Liao6ce6b3c2017-12-18 10:38:07 +0900997 Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
998 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task));
fdoray29a45012016-07-19 22:18:54 +0900999
1000 // Call Shutdown() asynchronously.
1001 CallShutdownAsync();
1002
1003 // Post and run tasks asynchronously.
fdoray29a45012016-07-19 22:18:54 +09001004 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
1005
1006 for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
Jeremy Romancd0c4672017-08-17 08:27:24 +09001007 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
fdorayd7a33a62016-10-12 21:21:27 +09001008 &tracker_, CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
ricead95e71b2016-09-13 13:10:11 +09001009 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false));
fdoray29a45012016-07-19 22:18:54 +09001010 threads.back()->Start();
1011
Jeremy Romancd0c4672017-08-17 08:27:24 +09001012 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
fdorayd7a33a62016-10-12 21:21:27 +09001013 &tracker_, CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN),
ricead95e71b2016-09-13 13:10:11 +09001014 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false));
fdoray29a45012016-07-19 22:18:54 +09001015 threads.back()->Start();
1016
Jeremy Romancd0c4672017-08-17 08:27:24 +09001017 threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
fdorayd7a33a62016-10-12 21:21:27 +09001018 &tracker_, CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN),
ricead95e71b2016-09-13 13:10:11 +09001019 ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
fdoray29a45012016-07-19 22:18:54 +09001020 threads.back()->Start();
1021 }
1022
1023 for (const auto& thread : threads)
1024 thread->Join();
1025
1026 // Expect BLOCK_SHUTDOWN tasks to have been executed.
1027 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
1028
1029 // Shutdown() shouldn't return before |block_shutdown_task| is executed.
1030 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
1031
1032 // Unblock shutdown by running |block_shutdown_task|.
Francois Doraycfa05a82017-10-13 03:10:17 +09001033 DispatchAndRunTaskWithTracker(std::move(block_shutdown_task));
fdoray29a45012016-07-19 22:18:54 +09001034 EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted());
1035 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
1036}
1037
Robert Liao72b27712018-02-17 04:27:45 +09001038// Verify that RunAndPopNextTask() returns the sequence from which it ran a task
1039// when it can be rescheduled.
1040TEST_F(TaskSchedulerTaskTrackerTest,
1041 RunAndPopNextTaskReturnsSequenceToReschedule) {
Peter Kasting24efe5e2018-02-24 09:03:01 +09001042 Task task_1(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001043 EXPECT_TRUE(tracker_.WillPostTask(task_1));
Peter Kasting24efe5e2018-02-24 09:03:01 +09001044 Task task_2(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001045 EXPECT_TRUE(tracker_.WillPostTask(task_2));
Francois Doraycfa05a82017-10-13 03:10:17 +09001046
1047 scoped_refptr<Sequence> sequence =
1048 test::CreateSequenceWithTask(std::move(task_1));
1049 sequence->PushTask(std::move(task_2));
1050 EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr));
1051
Robert Liao72b27712018-02-17 04:27:45 +09001052 EXPECT_EQ(sequence, tracker_.RunAndPopNextTask(sequence, nullptr));
Francois Doraycfa05a82017-10-13 03:10:17 +09001053}
1054
1055// Verify that WillScheduleSequence() returns nullptr when it receives a
1056// background sequence and the maximum number of background sequences that can
1057// be scheduled concurrently is reached. Verify that an observer is notified
1058// when a background sequence can be scheduled (i.e. when one of the previously
1059// scheduled background sequences has run).
1060TEST_F(TaskSchedulerTaskTrackerTest,
1061 WillScheduleBackgroundSequenceWithMaxBackgroundSequences) {
Francois Dorayea942372018-02-14 04:27:23 +09001062 constexpr int kMaxNumScheduledBackgroundSequences = 2;
1063 TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences);
Francois Doraycfa05a82017-10-13 03:10:17 +09001064
Francois Dorayea942372018-02-14 04:27:23 +09001065 // Simulate posting |kMaxNumScheduledBackgroundSequences| background tasks
Francois Doraycfa05a82017-10-13 03:10:17 +09001066 // and scheduling the associated sequences. This should succeed.
1067 std::vector<scoped_refptr<Sequence>> scheduled_sequences;
1068 testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
Francois Dorayea942372018-02-14 04:27:23 +09001069 for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
Peter Kasting24efe5e2018-02-24 09:03:01 +09001070 Task task(FROM_HERE, DoNothing(), TaskTraits(TaskPriority::BACKGROUND),
1071 TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001072 EXPECT_TRUE(tracker.WillPostTask(task));
Francois Doraycfa05a82017-10-13 03:10:17 +09001073 scoped_refptr<Sequence> sequence =
1074 test::CreateSequenceWithTask(std::move(task));
1075 EXPECT_EQ(sequence,
1076 tracker.WillScheduleSequence(sequence, &never_notified_observer));
1077 scheduled_sequences.push_back(std::move(sequence));
1078 }
1079
1080 // Simulate posting extra background tasks and scheduling the associated
1081 // sequences. This should fail because the maximum number of background
1082 // sequences that can be scheduled concurrently is already reached.
1083 std::vector<std::unique_ptr<bool>> extra_tasks_did_run;
1084 std::vector<
1085 std::unique_ptr<testing::StrictMock<MockCanScheduleSequenceObserver>>>
1086 extra_observers;
1087 std::vector<scoped_refptr<Sequence>> extra_sequences;
Francois Dorayea942372018-02-14 04:27:23 +09001088 for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
Francois Doraycfa05a82017-10-13 03:10:17 +09001089 extra_tasks_did_run.push_back(std::make_unique<bool>());
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001090 Task extra_task(
Francois Doraycfa05a82017-10-13 03:10:17 +09001091 FROM_HERE,
1092 BindOnce([](bool* extra_task_did_run) { *extra_task_did_run = true; },
1093 Unretained(extra_tasks_did_run.back().get())),
1094 TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001095 EXPECT_TRUE(tracker.WillPostTask(extra_task));
Francois Doraycfa05a82017-10-13 03:10:17 +09001096 extra_sequences.push_back(
1097 test::CreateSequenceWithTask(std::move(extra_task)));
1098 extra_observers.push_back(
1099 std::make_unique<
1100 testing::StrictMock<MockCanScheduleSequenceObserver>>());
1101 EXPECT_EQ(nullptr,
1102 tracker.WillScheduleSequence(extra_sequences.back(),
1103 extra_observers.back().get()));
1104 }
1105
1106 // Run the sequences scheduled at the beginning of the test. Expect an
1107 // observer from |extra_observer| to be notified every time a task finishes to
1108 // run.
Francois Dorayea942372018-02-14 04:27:23 +09001109 for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
Francois Doraycfa05a82017-10-13 03:10:17 +09001110 EXPECT_CALL(*extra_observers[i].get(),
1111 MockOnCanScheduleSequence(extra_sequences[i].get()));
Robert Liao72b27712018-02-17 04:27:45 +09001112 EXPECT_FALSE(tracker.RunAndPopNextTask(scheduled_sequences[i],
1113 &never_notified_observer));
Francois Doraycfa05a82017-10-13 03:10:17 +09001114 testing::Mock::VerifyAndClear(extra_observers[i].get());
1115 }
1116
1117 // Run the extra sequences.
Francois Dorayea942372018-02-14 04:27:23 +09001118 for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
Francois Doraycfa05a82017-10-13 03:10:17 +09001119 EXPECT_FALSE(*extra_tasks_did_run[i]);
Robert Liao72b27712018-02-17 04:27:45 +09001120 EXPECT_FALSE(tracker.RunAndPopNextTask(extra_sequences[i],
1121 &never_notified_observer));
Francois Doraycfa05a82017-10-13 03:10:17 +09001122 EXPECT_TRUE(*extra_tasks_did_run[i]);
1123 }
1124}
1125
1126namespace {
1127
1128void SetBool(bool* arg) {
1129 ASSERT_TRUE(arg);
1130 EXPECT_FALSE(*arg);
1131 *arg = true;
1132}
1133
1134} // namespace
1135
Robert Liao72b27712018-02-17 04:27:45 +09001136// Verify that RunAndPopNextTask() doesn't reschedule the background sequence it
1137// was assigned if there is a preempted background sequence with an earlier
1138// sequence time (compared to the next task in the sequence assigned to
1139// RunAndPopNextTask()).
Francois Doraycfa05a82017-10-13 03:10:17 +09001140TEST_F(TaskSchedulerTaskTrackerTest,
1141 RunNextBackgroundTaskWithEarlierPendingBackgroundTask) {
Francois Dorayea942372018-02-14 04:27:23 +09001142 constexpr int kMaxNumScheduledBackgroundSequences = 1;
1143 TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences);
Francois Doraycfa05a82017-10-13 03:10:17 +09001144 testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
1145
1146 // Simulate posting a background task and scheduling the associated sequence.
1147 // This should succeed.
1148 bool task_a_1_did_run = false;
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001149 Task task_a_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_1_did_run)),
1150 TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
1151 EXPECT_TRUE(tracker.WillPostTask(task_a_1));
Francois Doraycfa05a82017-10-13 03:10:17 +09001152 scoped_refptr<Sequence> sequence_a =
1153 test::CreateSequenceWithTask(std::move(task_a_1));
1154 EXPECT_EQ(sequence_a,
1155 tracker.WillScheduleSequence(sequence_a, &never_notified_observer));
1156
1157 // Simulate posting an extra background task and scheduling the associated
1158 // sequence. This should fail because the maximum number of background
1159 // sequences that can be scheduled concurrently is already reached.
1160 bool task_b_1_did_run = false;
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001161 Task task_b_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_b_1_did_run)),
1162 TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
1163 EXPECT_TRUE(tracker.WillPostTask(task_b_1));
Francois Doraycfa05a82017-10-13 03:10:17 +09001164 scoped_refptr<Sequence> sequence_b =
1165 test::CreateSequenceWithTask(std::move(task_b_1));
1166 testing::StrictMock<MockCanScheduleSequenceObserver> task_b_1_observer;
1167 EXPECT_FALSE(tracker.WillScheduleSequence(sequence_b, &task_b_1_observer));
1168
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001169 // Wait to be sure that the sequence time of |task_a_2| is after the sequenced
1170 // time of |task_b_1|.
1171 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
1172
Francois Doraycfa05a82017-10-13 03:10:17 +09001173 // Post an extra background task in |sequence_a|.
1174 bool task_a_2_did_run = false;
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001175 Task task_a_2(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_2_did_run)),
1176 TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
1177 EXPECT_TRUE(tracker.WillPostTask(task_a_2));
Francois Doraycfa05a82017-10-13 03:10:17 +09001178 sequence_a->PushTask(std::move(task_a_2));
Francois Doraycfa05a82017-10-13 03:10:17 +09001179
Robert Liao72b27712018-02-17 04:27:45 +09001180 // Run the first task in |sequence_a|. RunAndPopNextTask() should return
1181 // nullptr since |sequence_a| can't be rescheduled immediately.
1182 // |task_b_1_observer| should be notified that |sequence_b| can be scheduled.
Francois Doraycfa05a82017-10-13 03:10:17 +09001183 testing::StrictMock<MockCanScheduleSequenceObserver> task_a_2_observer;
1184 EXPECT_CALL(task_b_1_observer, MockOnCanScheduleSequence(sequence_b.get()));
Robert Liao72b27712018-02-17 04:27:45 +09001185 EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &task_a_2_observer));
Francois Doraycfa05a82017-10-13 03:10:17 +09001186 testing::Mock::VerifyAndClear(&task_b_1_observer);
1187 EXPECT_TRUE(task_a_1_did_run);
1188
Robert Liao72b27712018-02-17 04:27:45 +09001189 // Run the first task in |sequence_b|. RunAndPopNextTask() should return
1190 // nullptr since |sequence_b| is empty after popping a task from it.
Francois Doraycfa05a82017-10-13 03:10:17 +09001191 // |task_a_2_observer| should be notified that |sequence_a| can be
1192 // scheduled.
1193 EXPECT_CALL(task_a_2_observer, MockOnCanScheduleSequence(sequence_a.get()));
Robert Liao72b27712018-02-17 04:27:45 +09001194 EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_b, &never_notified_observer));
Francois Doraycfa05a82017-10-13 03:10:17 +09001195 testing::Mock::VerifyAndClear(&task_a_2_observer);
1196 EXPECT_TRUE(task_b_1_did_run);
1197
Robert Liao72b27712018-02-17 04:27:45 +09001198 // Run the first task in |sequence_a|. RunAndPopNextTask() should return
1199 // nullptr since |sequence_b| is empty after popping a task from it. No
1200 // observer should be notified.
1201 EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &never_notified_observer));
Francois Doraycfa05a82017-10-13 03:10:17 +09001202 EXPECT_TRUE(task_a_2_did_run);
1203}
1204
Francois Dorayea942372018-02-14 04:27:23 +09001205// Verify that preempted background sequences are scheduled when shutdown
1206// starts.
1207TEST_F(TaskSchedulerTaskTrackerTest,
1208 SchedulePreemptedBackgroundSequencesOnShutdown) {
1209 constexpr int kMaxNumScheduledBackgroundSequences = 0;
1210 TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences);
1211 testing::StrictMock<MockCanScheduleSequenceObserver> observer;
1212
1213 // Simulate scheduling sequences. TaskTracker should prevent this.
1214 std::vector<scoped_refptr<Sequence>> preempted_sequences;
1215 for (int i = 0; i < 3; ++i) {
Peter Kasting24efe5e2018-02-24 09:03:01 +09001216 Task task(FROM_HERE, DoNothing(),
Francois Dorayea942372018-02-14 04:27:23 +09001217 TaskTraits(TaskPriority::BACKGROUND,
1218 TaskShutdownBehavior::BLOCK_SHUTDOWN),
1219 TimeDelta());
1220 EXPECT_TRUE(tracker.WillPostTask(task));
1221 scoped_refptr<Sequence> sequence =
1222 test::CreateSequenceWithTask(std::move(task));
1223 EXPECT_FALSE(tracker.WillScheduleSequence(sequence, &observer));
1224 preempted_sequences.push_back(std::move(sequence));
1225
1226 // Wait to be sure that tasks have different |sequenced_time|.
1227 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
1228 }
1229
1230 // Perform shutdown. Expect |preempted_sequences| to be scheduled in posting
1231 // order.
1232 {
1233 testing::InSequence in_sequence;
1234 for (auto& preempted_sequence : preempted_sequences) {
1235 EXPECT_CALL(observer, MockOnCanScheduleSequence(preempted_sequence.get()))
1236 .WillOnce(testing::Invoke([&tracker](Sequence* sequence) {
1237 // Run the task to unblock shutdown.
Robert Liao72b27712018-02-17 04:27:45 +09001238 tracker.RunAndPopNextTask(sequence, nullptr);
Francois Dorayea942372018-02-14 04:27:23 +09001239 }));
1240 }
1241 tracker.Shutdown();
1242 }
1243}
1244
fdoray26866e22016-11-30 04:45:01 +09001245namespace {
1246
1247class WaitAllowedTestThread : public SimpleThread {
1248 public:
1249 WaitAllowedTestThread() : SimpleThread("WaitAllowedTestThread") {}
1250
1251 private:
1252 void Run() override {
Gabriel Charette19075392018-01-19 20:00:53 +09001253 TaskTracker tracker("Test");
fdoray26866e22016-11-30 04:45:01 +09001254
1255 // Waiting is allowed by default. Expect TaskTracker to disallow it before
fdoray7fdebb72016-12-24 04:38:59 +09001256 // running a task without the WithBaseSyncPrimitives() trait.
Francois Doray7c3de9f2017-10-07 00:51:57 +09001257 internal::AssertBaseSyncPrimitivesAllowed();
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001258 Task task_without_sync_primitives(
fdoray26866e22016-11-30 04:45:01 +09001259 FROM_HERE, Bind([]() {
Francois Doray7c3de9f2017-10-07 00:51:57 +09001260 EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
fdoray26866e22016-11-30 04:45:01 +09001261 }),
1262 TaskTraits(), TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001263 EXPECT_TRUE(tracker.WillPostTask(task_without_sync_primitives));
Francois Doraycfa05a82017-10-13 03:10:17 +09001264 testing::StrictMock<MockCanScheduleSequenceObserver>
1265 never_notified_observer;
1266 auto sequence_without_sync_primitives = tracker.WillScheduleSequence(
1267 test::CreateSequenceWithTask(std::move(task_without_sync_primitives)),
1268 &never_notified_observer);
1269 ASSERT_TRUE(sequence_without_sync_primitives);
Robert Liao72b27712018-02-17 04:27:45 +09001270 tracker.RunAndPopNextTask(std::move(sequence_without_sync_primitives),
1271 &never_notified_observer);
fdoray26866e22016-11-30 04:45:01 +09001272
1273 // Disallow waiting. Expect TaskTracker to allow it before running a task
fdoray7fdebb72016-12-24 04:38:59 +09001274 // with the WithBaseSyncPrimitives() trait.
fdoray26866e22016-11-30 04:45:01 +09001275 ThreadRestrictions::DisallowWaiting();
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001276 Task task_with_sync_primitives(
Jeremy Romancd0c4672017-08-17 08:27:24 +09001277 FROM_HERE, Bind([]() {
1278 // Shouldn't fail.
Francois Doray7c3de9f2017-10-07 00:51:57 +09001279 internal::AssertBaseSyncPrimitivesAllowed();
Jeremy Romancd0c4672017-08-17 08:27:24 +09001280 }),
1281 TaskTraits(WithBaseSyncPrimitives()), TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001282 EXPECT_TRUE(tracker.WillPostTask(task_with_sync_primitives));
Francois Doraycfa05a82017-10-13 03:10:17 +09001283 auto sequence_with_sync_primitives = tracker.WillScheduleSequence(
1284 test::CreateSequenceWithTask(std::move(task_with_sync_primitives)),
1285 &never_notified_observer);
1286 ASSERT_TRUE(sequence_with_sync_primitives);
Robert Liao72b27712018-02-17 04:27:45 +09001287 tracker.RunAndPopNextTask(std::move(sequence_with_sync_primitives),
1288 &never_notified_observer);
fdoray26866e22016-11-30 04:45:01 +09001289 }
1290
1291 DISALLOW_COPY_AND_ASSIGN(WaitAllowedTestThread);
1292};
1293
1294} // namespace
1295
fdoray7fdebb72016-12-24 04:38:59 +09001296// Verify that AssertIOAllowed() succeeds only for a WithBaseSyncPrimitives()
1297// task.
fdoray26866e22016-11-30 04:45:01 +09001298TEST(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 WaitAllowedTestThread wait_allowed_test_thread;
1303 wait_allowed_test_thread.Start();
1304 wait_allowed_test_thread.Join();
1305}
1306
fdoray67c55952017-01-07 05:12:23 +09001307// Verify that TaskScheduler.TaskLatency.* histograms are correctly recorded
1308// when a task runs.
1309TEST(TaskSchedulerTaskTrackerHistogramTest, TaskLatency) {
1310 auto statistics_recorder = StatisticsRecorder::CreateTemporaryForTesting();
1311
Gabriel Charette19075392018-01-19 20:00:53 +09001312 TaskTracker tracker("Test");
Francois Doraycfa05a82017-10-13 03:10:17 +09001313 testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
fdoray67c55952017-01-07 05:12:23 +09001314
1315 struct {
1316 const TaskTraits traits;
1317 const char* const expected_histogram;
Gabriel Charette4f30e662018-01-19 01:48:59 +09001318 } tests[] = {{{TaskPriority::BACKGROUND},
Gabriel Charette19075392018-01-19 20:00:53 +09001319 "TaskScheduler.TaskLatencyMicroseconds.Test."
Gabriel Charette4f30e662018-01-19 01:48:59 +09001320 "BackgroundTaskPriority"},
1321 {{MayBlock(), TaskPriority::BACKGROUND},
Gabriel Charette19075392018-01-19 20:00:53 +09001322 "TaskScheduler.TaskLatencyMicroseconds.Test."
Gabriel Charette4f30e662018-01-19 01:48:59 +09001323 "BackgroundTaskPriority_MayBlock"},
1324 {{WithBaseSyncPrimitives(), TaskPriority::BACKGROUND},
Gabriel Charette19075392018-01-19 20:00:53 +09001325 "TaskScheduler.TaskLatencyMicroseconds.Test."
Gabriel Charette4f30e662018-01-19 01:48:59 +09001326 "BackgroundTaskPriority_MayBlock"},
1327 {{TaskPriority::USER_VISIBLE},
Gabriel Charette19075392018-01-19 20:00:53 +09001328 "TaskScheduler.TaskLatencyMicroseconds.Test."
Gabriel Charette4f30e662018-01-19 01:48:59 +09001329 "UserVisibleTaskPriority"},
1330 {{MayBlock(), TaskPriority::USER_VISIBLE},
Gabriel Charette19075392018-01-19 20:00:53 +09001331 "TaskScheduler.TaskLatencyMicroseconds.Test."
Gabriel Charette4f30e662018-01-19 01:48:59 +09001332 "UserVisibleTaskPriority_MayBlock"},
1333 {{WithBaseSyncPrimitives(), TaskPriority::USER_VISIBLE},
Gabriel Charette19075392018-01-19 20:00:53 +09001334 "TaskScheduler.TaskLatencyMicroseconds.Test."
Gabriel Charette4f30e662018-01-19 01:48:59 +09001335 "UserVisibleTaskPriority_MayBlock"},
1336 {{TaskPriority::USER_BLOCKING},
Gabriel Charette19075392018-01-19 20:00:53 +09001337 "TaskScheduler.TaskLatencyMicroseconds.Test."
Gabriel Charette4f30e662018-01-19 01:48:59 +09001338 "UserBlockingTaskPriority"},
1339 {{MayBlock(), TaskPriority::USER_BLOCKING},
Gabriel Charette19075392018-01-19 20:00:53 +09001340 "TaskScheduler.TaskLatencyMicroseconds.Test."
Gabriel Charette4f30e662018-01-19 01:48:59 +09001341 "UserBlockingTaskPriority_MayBlock"},
1342 {{WithBaseSyncPrimitives(), TaskPriority::USER_BLOCKING},
Gabriel Charette19075392018-01-19 20:00:53 +09001343 "TaskScheduler.TaskLatencyMicroseconds.Test."
Gabriel Charette4f30e662018-01-19 01:48:59 +09001344 "UserBlockingTaskPriority_MayBlock"}};
fdoray67c55952017-01-07 05:12:23 +09001345
1346 for (const auto& test : tests) {
Peter Kasting24efe5e2018-02-24 09:03:01 +09001347 Task task(FROM_HERE, DoNothing(), test.traits, TimeDelta());
Robert Liao6ce6b3c2017-12-18 10:38:07 +09001348 ASSERT_TRUE(tracker.WillPostTask(task));
fdoray67c55952017-01-07 05:12:23 +09001349
1350 HistogramTester tester;
Jeffrey He5b18cb92017-06-07 00:36:03 +09001351
Francois Doraycfa05a82017-10-13 03:10:17 +09001352 auto sequence = tracker.WillScheduleSequence(
1353 test::CreateSequenceWithTask(std::move(task)),
1354 &never_notified_observer);
1355 ASSERT_TRUE(sequence);
Robert Liao72b27712018-02-17 04:27:45 +09001356 tracker.RunAndPopNextTask(std::move(sequence), &never_notified_observer);
fdoray67c55952017-01-07 05:12:23 +09001357 tester.ExpectTotalCount(test.expected_histogram, 1);
1358 }
1359}
1360
fdoray7c1740c2016-03-30 02:12:53 +09001361} // namespace internal
1362} // namespace base