Roll src/third_party/WebKit 605a979:06cb9e9 (svn 202556:202558)
[chromium-blink-merge.git] / components / scheduler / child / worker_scheduler_impl_unittest.cc
blob9b17b157669d8e698f8229658f770e12c2b9e352
1 // Copyright 2015 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.
5 #include "components/scheduler/child/worker_scheduler_impl.h"
7 #include "base/callback.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/test/simple_test_tick_clock.h"
10 #include "cc/test/ordered_simple_task_runner.h"
11 #include "components/scheduler/child/scheduler_task_runner_delegate_for_test.h"
12 #include "components/scheduler/child/test_time_source.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using testing::ElementsAreArray;
18 namespace scheduler {
20 namespace {
21 void NopTask() {
24 int TimeTicksToIntMs(const base::TimeTicks& time) {
25 return static_cast<int>((time - base::TimeTicks()).InMilliseconds());
28 void RecordTimelineTask(std::vector<std::string>* timeline,
29 base::SimpleTestTickClock* clock) {
30 timeline->push_back(base::StringPrintf("run RecordTimelineTask @ %d",
31 TimeTicksToIntMs(clock->NowTicks())));
34 void AppendToVectorTestTask(std::vector<std::string>* vector,
35 std::string value) {
36 vector->push_back(value);
39 void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
40 std::string value,
41 base::TimeTicks deadline) {
42 AppendToVectorTestTask(vector, value);
45 void TimelineIdleTestTask(std::vector<std::string>* timeline,
46 base::TimeTicks deadline) {
47 timeline->push_back(base::StringPrintf("run TimelineIdleTestTask deadline %d",
48 TimeTicksToIntMs(deadline)));
51 }; // namespace
53 class WorkerSchedulerImplForTest : public WorkerSchedulerImpl {
54 public:
55 WorkerSchedulerImplForTest(
56 scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner,
57 base::SimpleTestTickClock* clock_)
58 : WorkerSchedulerImpl(main_task_runner),
59 clock_(clock_),
60 timeline_(nullptr) {}
62 void RecordTimelineEvents(std::vector<std::string>* timeline) {
63 timeline_ = timeline;
66 private:
67 bool CanEnterLongIdlePeriod(
68 base::TimeTicks now,
69 base::TimeDelta* next_long_idle_period_delay_out) override {
70 if (timeline_) {
71 timeline_->push_back(base::StringPrintf("CanEnterLongIdlePeriod @ %d",
72 TimeTicksToIntMs(now)));
74 return WorkerSchedulerImpl::CanEnterLongIdlePeriod(
75 now, next_long_idle_period_delay_out);
78 void IsNotQuiescent() override {
79 if (timeline_) {
80 timeline_->push_back(base::StringPrintf(
81 "IsNotQuiescent @ %d", TimeTicksToIntMs(clock_->NowTicks())));
83 WorkerSchedulerImpl::IsNotQuiescent();
86 base::SimpleTestTickClock* clock_; // NOT OWNED
87 std::vector<std::string>* timeline_; // NOT OWNED
90 class WorkerSchedulerImplTest : public testing::Test {
91 public:
92 WorkerSchedulerImplTest()
93 : clock_(new base::SimpleTestTickClock()),
94 mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_.get(), true)),
95 main_task_runner_(
96 SchedulerTaskRunnerDelegateForTest::Create(mock_task_runner_)),
97 scheduler_(
98 new WorkerSchedulerImplForTest(main_task_runner_, clock_.get())),
99 timeline_(nullptr) {
100 clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
101 scheduler_->GetSchedulerHelperForTesting()->SetTimeSourceForTesting(
102 make_scoped_ptr(new TestTimeSource(clock_.get())));
103 scheduler_->GetSchedulerHelperForTesting()
104 ->GetTaskQueueManagerForTesting()
105 ->SetTimeSourceForTesting(
106 make_scoped_ptr(new TestTimeSource(clock_.get())));
109 ~WorkerSchedulerImplTest() override {}
111 void TearDown() override {
112 // Check that all tests stop posting tasks.
113 while (mock_task_runner_->RunUntilIdle()) {
117 void Init() {
118 scheduler_->Init();
119 default_task_runner_ = scheduler_->DefaultTaskRunner();
120 idle_task_runner_ = scheduler_->IdleTaskRunner();
121 timeline_ = nullptr;
124 void RecordTimelineEvents(std::vector<std::string>* timeline) {
125 timeline_ = timeline;
126 scheduler_->RecordTimelineEvents(timeline);
129 void RunUntilIdle() {
130 if (timeline_) {
131 timeline_->push_back(base::StringPrintf(
132 "RunUntilIdle begin @ %d", TimeTicksToIntMs(clock_->NowTicks())));
134 mock_task_runner_->RunUntilIdle();
135 if (timeline_) {
136 timeline_->push_back(base::StringPrintf(
137 "RunUntilIdle end @ %d", TimeTicksToIntMs(clock_->NowTicks())));
141 // Helper for posting several tasks of specific types. |task_descriptor| is a
142 // string with space delimited task identifiers. The first letter of each
143 // task identifier specifies the task type:
144 // - 'D': Default task
145 // - 'I': Idle task
146 void PostTestTasks(std::vector<std::string>* run_order,
147 const std::string& task_descriptor) {
148 std::istringstream stream(task_descriptor);
149 while (!stream.eof()) {
150 std::string task;
151 stream >> task;
152 switch (task[0]) {
153 case 'D':
154 default_task_runner_->PostTask(
155 FROM_HERE, base::Bind(&AppendToVectorTestTask, run_order, task));
156 break;
157 case 'I':
158 idle_task_runner_->PostIdleTask(
159 FROM_HERE,
160 base::Bind(&AppendToVectorIdleTestTask, run_order, task));
161 break;
162 default:
163 NOTREACHED();
168 static base::TimeDelta maximum_idle_period_duration() {
169 return base::TimeDelta::FromMilliseconds(
170 IdleHelper::kMaximumIdlePeriodMillis);
173 protected:
174 scoped_ptr<base::SimpleTestTickClock> clock_;
175 // Only one of mock_task_runner_ or message_loop_ will be set.
176 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
178 scoped_refptr<SchedulerTaskRunnerDelegate> main_task_runner_;
179 scoped_ptr<WorkerSchedulerImplForTest> scheduler_;
180 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
181 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
182 std::vector<std::string>* timeline_; // NOT OWNED
184 DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerImplTest);
187 TEST_F(WorkerSchedulerImplTest, TestPostDefaultTask) {
188 Init();
190 std::vector<std::string> run_order;
191 PostTestTasks(&run_order, "D1 D2 D3 D4");
193 RunUntilIdle();
194 EXPECT_THAT(run_order,
195 testing::ElementsAre(std::string("D1"), std::string("D2"),
196 std::string("D3"), std::string("D4")));
199 TEST_F(WorkerSchedulerImplTest, TestPostIdleTask) {
200 Init();
202 std::vector<std::string> run_order;
203 PostTestTasks(&run_order, "I1");
205 RunUntilIdle();
206 EXPECT_THAT(run_order, testing::ElementsAre(std::string("I1")));
209 TEST_F(WorkerSchedulerImplTest, TestPostDefaultAndIdleTasks) {
210 Init();
212 std::vector<std::string> run_order;
213 PostTestTasks(&run_order, "I1 D2 D3 D4");
215 RunUntilIdle();
216 EXPECT_THAT(run_order,
217 testing::ElementsAre(std::string("D2"), std::string("D3"),
218 std::string("D4"), std::string("I1")));
221 TEST_F(WorkerSchedulerImplTest, TestPostDefaultDelayedAndIdleTasks) {
222 Init();
224 std::vector<std::string> run_order;
225 PostTestTasks(&run_order, "I1 D2 D3 D4");
227 default_task_runner_->PostDelayedTask(
228 FROM_HERE, base::Bind(&AppendToVectorTestTask, &run_order, "DELAYED"),
229 base::TimeDelta::FromMilliseconds(1000));
231 RunUntilIdle();
232 EXPECT_THAT(run_order,
233 testing::ElementsAre(std::string("D2"), std::string("D3"),
234 std::string("D4"), std::string("I1"),
235 std::string("DELAYED")));
238 TEST_F(WorkerSchedulerImplTest, TestIdleTaskWhenIsNotQuiescent) {
239 std::vector<std::string> timeline;
240 RecordTimelineEvents(&timeline);
241 Init();
243 timeline.push_back("Post default task");
244 // Post a delayed task timed to occur mid way during the long idle period.
245 default_task_runner_->PostTask(
246 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
247 base::Unretained(clock_.get())));
248 RunUntilIdle();
250 timeline.push_back("Post idle task");
251 idle_task_runner_->PostIdleTask(FROM_HERE,
252 base::Bind(&TimelineIdleTestTask, &timeline));
254 RunUntilIdle();
256 std::string expected_timeline[] = {"CanEnterLongIdlePeriod @ 5",
257 "Post default task",
258 "run RecordTimelineTask @ 5",
259 "Post idle task",
260 "IsNotQuiescent @ 5",
261 "CanEnterLongIdlePeriod @ 305",
262 "run TimelineIdleTestTask deadline 355"};
264 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
267 TEST_F(WorkerSchedulerImplTest, TestIdleDeadlineWithPendingDelayedTask) {
268 std::vector<std::string> timeline;
269 RecordTimelineEvents(&timeline);
270 Init();
272 timeline.push_back("Post delayed and idle tasks");
273 // Post a delayed task timed to occur mid way during the long idle period.
274 default_task_runner_->PostDelayedTask(
275 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
276 base::Unretained(clock_.get())),
277 base::TimeDelta::FromMilliseconds(20));
278 idle_task_runner_->PostIdleTask(FROM_HERE,
279 base::Bind(&TimelineIdleTestTask, &timeline));
281 RunUntilIdle();
283 std::string expected_timeline[] = {
284 "CanEnterLongIdlePeriod @ 5",
285 "Post delayed and idle tasks",
286 "CanEnterLongIdlePeriod @ 5",
287 "run TimelineIdleTestTask deadline 25", // Note the short 20ms deadline.
288 "run RecordTimelineTask @ 25"};
290 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
293 TEST_F(WorkerSchedulerImplTest,
294 TestIdleDeadlineWithPendingDelayedTaskFarInTheFuture) {
295 std::vector<std::string> timeline;
296 RecordTimelineEvents(&timeline);
297 Init();
299 timeline.push_back("Post delayed and idle tasks");
300 // Post a delayed task timed to occur well after the long idle period.
301 default_task_runner_->PostDelayedTask(
302 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
303 base::Unretained(clock_.get())),
304 base::TimeDelta::FromMilliseconds(500));
305 idle_task_runner_->PostIdleTask(FROM_HERE,
306 base::Bind(&TimelineIdleTestTask, &timeline));
308 RunUntilIdle();
310 std::string expected_timeline[] = {
311 "CanEnterLongIdlePeriod @ 5",
312 "Post delayed and idle tasks",
313 "CanEnterLongIdlePeriod @ 5",
314 "run TimelineIdleTestTask deadline 55", // Note the full 50ms deadline.
315 "run RecordTimelineTask @ 505"};
317 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
320 TEST_F(WorkerSchedulerImplTest, TestPostIdleTaskAfterRunningUntilIdle) {
321 Init();
323 default_task_runner_->PostDelayedTask(
324 FROM_HERE, base::Bind(&NopTask), base::TimeDelta::FromMilliseconds(1000));
325 RunUntilIdle();
327 std::vector<std::string> run_order;
328 PostTestTasks(&run_order, "I1 I2 D3");
330 RunUntilIdle();
331 EXPECT_THAT(run_order,
332 testing::ElementsAre(std::string("D3"), std::string("I1"),
333 std::string("I2")));
336 TEST_F(WorkerSchedulerImplTest, TestLongIdlePeriodTimeline) {
337 Init();
339 std::vector<std::string> timeline;
340 RecordTimelineEvents(&timeline);
342 // The scheduler should not run the initiate_next_long_idle_period task if
343 // there are no idle tasks and no other task woke up the scheduler, thus
344 // the idle period deadline shouldn't update at the end of the current long
345 // idle period.
346 base::TimeTicks idle_period_deadline =
347 scheduler_->CurrentIdleTaskDeadlineForTesting();
348 clock_->Advance(maximum_idle_period_duration());
349 RunUntilIdle();
351 base::TimeTicks new_idle_period_deadline =
352 scheduler_->CurrentIdleTaskDeadlineForTesting();
353 EXPECT_EQ(idle_period_deadline, new_idle_period_deadline);
355 // Posting a after-wakeup idle task also shouldn't wake the scheduler or
356 // initiate the next long idle period.
357 timeline.push_back("PostIdleTaskAfterWakeup");
358 idle_task_runner_->PostIdleTaskAfterWakeup(
359 FROM_HERE, base::Bind(&TimelineIdleTestTask, &timeline));
360 RunUntilIdle();
361 new_idle_period_deadline = scheduler_->CurrentIdleTaskDeadlineForTesting();
363 // Running a normal task should initiate a new long idle period after waiting
364 // 300ms for quiescence.
365 timeline.push_back("Post RecordTimelineTask");
366 default_task_runner_->PostTask(
367 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
368 base::Unretained(clock_.get())));
369 RunUntilIdle();
371 std::string expected_timeline[] = {
372 "RunUntilIdle begin @ 55",
373 "RunUntilIdle end @ 55",
374 "PostIdleTaskAfterWakeup",
375 "RunUntilIdle begin @ 55", // NOTE idle task doesn't run till later.
376 "RunUntilIdle end @ 55",
377 "Post RecordTimelineTask",
378 "RunUntilIdle begin @ 55",
379 "run RecordTimelineTask @ 55",
380 "IsNotQuiescent @ 55", // NOTE we have to wait for quiescence.
381 "CanEnterLongIdlePeriod @ 355",
382 "run TimelineIdleTestTask deadline 405",
383 "RunUntilIdle end @ 355"};
385 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
388 } // namespace scheduler