Roll src/third_party/WebKit afc1431:5a99872 (svn 194212:194220)
[chromium-blink-merge.git] / content / child / scheduler / worker_scheduler_impl_unittest.cc
blobedeaa369bfe698b372f0802dd9ffb44d1c57040f
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 "content/child/scheduler/worker_scheduler_impl.h"
7 #include "base/callback.h"
8 #include "base/strings/stringprintf.h"
9 #include "cc/test/ordered_simple_task_runner.h"
10 #include "cc/test/test_now_source.h"
11 #include "content/child/scheduler/nestable_task_runner_for_test.h"
12 #include "content/child/scheduler/scheduler_message_loop_delegate.h"
13 #include "content/test/test_time_source.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 using testing::ElementsAreArray;
19 namespace content {
21 namespace {
22 void NopTask() {
25 int TimeTicksToIntMs(const base::TimeTicks& time) {
26 return static_cast<int>((time - base::TimeTicks()).InMilliseconds());
29 void WakeUpTask(std::vector<std::string>* timeline, cc::TestNowSource* clock) {
30 if (timeline) {
31 timeline->push_back(base::StringPrintf(
32 "run WakeUpTask @ %d", TimeTicksToIntMs(clock->Now())));
36 void RecordTimelineTask(std::vector<std::string>* timeline,
37 cc::TestNowSource* clock) {
38 timeline->push_back(base::StringPrintf(
39 "run RecordTimelineTask @ %d", TimeTicksToIntMs(clock->Now())));
42 void AppendToVectorTestTask(std::vector<std::string>* vector,
43 std::string value) {
44 vector->push_back(value);
47 void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
48 std::string value,
49 base::TimeTicks deadline) {
50 AppendToVectorTestTask(vector, value);
53 void TimelineIdleTestTask(std::vector<std::string>* timeline,
54 base::TimeTicks deadline) {
55 timeline->push_back(base::StringPrintf("run TimelineIdleTestTask deadline %d",
56 TimeTicksToIntMs(deadline)));
59 }; // namespace
61 class WorkerSchedulerImplForTest : public WorkerSchedulerImpl {
62 public:
63 WorkerSchedulerImplForTest(
64 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner,
65 scoped_refptr<cc::TestNowSource> clock_)
66 : WorkerSchedulerImpl(main_task_runner),
67 clock_(clock_),
68 timeline_(nullptr) {}
70 void RecordTimelineEvents(std::vector<std::string>* timeline) {
71 timeline_ = timeline;
74 private:
75 bool CanEnterLongIdlePeriod(
76 base::TimeTicks now,
77 base::TimeDelta* next_long_idle_period_delay_out) override {
78 if (timeline_) {
79 timeline_->push_back(base::StringPrintf("CanEnterLongIdlePeriod @ %d",
80 TimeTicksToIntMs(now)));
82 return WorkerSchedulerImpl::CanEnterLongIdlePeriod(
83 now, next_long_idle_period_delay_out);
86 void IsNotQuiescent() override {
87 if (timeline_) {
88 timeline_->push_back(base::StringPrintf("IsNotQuiescent @ %d",
89 TimeTicksToIntMs(clock_->Now())));
91 WorkerSchedulerImpl::IsNotQuiescent();
94 scoped_refptr<cc::TestNowSource> clock_;
95 std::vector<std::string>* timeline_; // NOT OWNED
98 class WorkerSchedulerImplTest : public testing::Test {
99 public:
100 WorkerSchedulerImplTest()
101 : clock_(cc::TestNowSource::Create(5000)),
102 mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_, true)),
103 nestable_task_runner_(
104 NestableTaskRunnerForTest::Create(mock_task_runner_)),
105 scheduler_(
106 new WorkerSchedulerImplForTest(nestable_task_runner_, clock_)),
107 timeline_(nullptr) {
108 scheduler_->GetSchedulerHelperForTesting()->SetTimeSourceForTesting(
109 make_scoped_ptr(new TestTimeSource(clock_)));
110 scheduler_->GetSchedulerHelperForTesting()
111 ->GetTaskQueueManagerForTesting()
112 ->SetTimeSourceForTesting(make_scoped_ptr(new TestTimeSource(clock_)));
115 ~WorkerSchedulerImplTest() override {}
117 void TearDown() override {
118 // Check that all tests stop posting tasks.
119 while (mock_task_runner_->RunUntilIdle()) {
123 void Init() {
124 scheduler_->Init();
125 default_task_runner_ = scheduler_->DefaultTaskRunner();
126 idle_task_runner_ = scheduler_->IdleTaskRunner();
127 timeline_ = nullptr;
130 void RecordTimelineEvents(std::vector<std::string>* timeline) {
131 timeline_ = timeline;
132 scheduler_->RecordTimelineEvents(timeline);
135 void RunUntilIdle() {
136 if (timeline_) {
137 timeline_->push_back(base::StringPrintf("RunUntilIdle begin @ %d",
138 TimeTicksToIntMs(clock_->Now())));
140 mock_task_runner_->RunUntilIdle();
141 if (timeline_) {
142 timeline_->push_back(base::StringPrintf("RunUntilIdle end @ %d",
143 TimeTicksToIntMs(clock_->Now())));
147 void InitAndPostDelayedWakeupTask() {
148 Init();
149 // WorkerSchedulerImpl::Init causes a delayed task to be posted on the
150 // after wakeup control runner. We need a task to wake the system up
151 // AFTER the delay for this has expired.
152 default_task_runner_->PostDelayedTask(
153 FROM_HERE, base::Bind(&WakeUpTask, base::Unretained(timeline_),
154 base::Unretained(clock_.get())),
155 base::TimeDelta::FromMilliseconds(100));
158 // Helper for posting several tasks of specific types. |task_descriptor| is a
159 // string with space delimited task identifiers. The first letter of each
160 // task identifier specifies the task type:
161 // - 'D': Default task
162 // - 'I': Idle task
163 void PostTestTasks(std::vector<std::string>* run_order,
164 const std::string& task_descriptor) {
165 std::istringstream stream(task_descriptor);
166 while (!stream.eof()) {
167 std::string task;
168 stream >> task;
169 switch (task[0]) {
170 case 'D':
171 default_task_runner_->PostTask(
172 FROM_HERE, base::Bind(&AppendToVectorTestTask, run_order, task));
173 break;
174 case 'I':
175 idle_task_runner_->PostIdleTask(
176 FROM_HERE,
177 base::Bind(&AppendToVectorIdleTestTask, run_order, task));
178 break;
179 default:
180 NOTREACHED();
185 static base::TimeDelta maximum_idle_period_duration() {
186 return base::TimeDelta::FromMilliseconds(
187 SchedulerHelper::kMaximumIdlePeriodMillis);
190 protected:
191 scoped_refptr<cc::TestNowSource> clock_;
192 // Only one of mock_task_runner_ or message_loop_ will be set.
193 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
195 scoped_refptr<NestableSingleThreadTaskRunner> nestable_task_runner_;
196 scoped_ptr<WorkerSchedulerImplForTest> scheduler_;
197 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
198 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
199 std::vector<std::string>* timeline_; // NOT OWNED
201 DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerImplTest);
204 TEST_F(WorkerSchedulerImplTest, TestPostDefaultTask) {
205 InitAndPostDelayedWakeupTask();
207 std::vector<std::string> run_order;
208 PostTestTasks(&run_order, "D1 D2 D3 D4");
210 RunUntilIdle();
211 EXPECT_THAT(run_order,
212 testing::ElementsAre(std::string("D1"), std::string("D2"),
213 std::string("D3"), std::string("D4")));
216 TEST_F(WorkerSchedulerImplTest, TestPostIdleTask) {
217 InitAndPostDelayedWakeupTask();
219 std::vector<std::string> run_order;
220 PostTestTasks(&run_order, "I1");
222 RunUntilIdle();
223 EXPECT_THAT(run_order, testing::ElementsAre(std::string("I1")));
226 TEST_F(WorkerSchedulerImplTest, TestPostIdleTask_NoWakeup) {
227 Init();
228 std::vector<std::string> run_order;
229 PostTestTasks(&run_order, "I1");
231 RunUntilIdle();
232 EXPECT_TRUE(run_order.empty());
235 TEST_F(WorkerSchedulerImplTest, TestPostDefaultAndIdleTasks) {
236 InitAndPostDelayedWakeupTask();
238 std::vector<std::string> run_order;
239 PostTestTasks(&run_order, "I1 D2 D3 D4");
241 RunUntilIdle();
242 EXPECT_THAT(run_order,
243 testing::ElementsAre(std::string("D2"), std::string("D3"),
244 std::string("D4"), std::string("I1")));
247 TEST_F(WorkerSchedulerImplTest, TestPostIdleTaskWithWakeupNeeded_NoWakeup) {
248 InitAndPostDelayedWakeupTask();
250 RunUntilIdle();
251 // The delayed call to EnableLongIdlePeriod happened and it posted a call to
252 // EnableLongIdlePeriod on the after wakeup control queue.
254 std::vector<std::string> run_order;
255 PostTestTasks(&run_order, "I1");
257 RunUntilIdle();
258 EXPECT_TRUE(run_order.empty());
261 TEST_F(WorkerSchedulerImplTest, TestPostDefaultDelayedAndIdleTasks) {
262 InitAndPostDelayedWakeupTask();
264 std::vector<std::string> run_order;
265 PostTestTasks(&run_order, "I1 D2 D3 D4");
267 default_task_runner_->PostDelayedTask(
268 FROM_HERE, base::Bind(&AppendToVectorTestTask, &run_order, "DELAYED"),
269 base::TimeDelta::FromMilliseconds(1000));
271 RunUntilIdle();
272 EXPECT_THAT(run_order,
273 testing::ElementsAre(std::string("D2"), std::string("D3"),
274 std::string("D4"), std::string("I1"),
275 std::string("DELAYED")));
278 TEST_F(WorkerSchedulerImplTest, TestIdleDeadlineWithPendingDelayedTask) {
279 std::vector<std::string> timeline;
280 RecordTimelineEvents(&timeline);
281 InitAndPostDelayedWakeupTask();
283 timeline.push_back("Post delayed and idle tasks");
284 // Post a delayed task timed to occur mid way during the long idle period.
285 default_task_runner_->PostDelayedTask(
286 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
287 base::Unretained(clock_.get())),
288 base::TimeDelta::FromMilliseconds(420));
289 idle_task_runner_->PostIdleTask(FROM_HERE,
290 base::Bind(&TimelineIdleTestTask, &timeline));
292 RunUntilIdle();
294 std::string expected_timeline[] = {
295 "CanEnterLongIdlePeriod @ 5",
296 "Post delayed and idle tasks",
297 "IsNotQuiescent @ 105",
298 "CanEnterLongIdlePeriod @ 405",
299 "run TimelineIdleTestTask deadline 425", // Note the short 20ms deadline.
300 "CanEnterLongIdlePeriod @ 425",
301 "run RecordTimelineTask @ 425"};
303 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
306 TEST_F(WorkerSchedulerImplTest,
307 TestIdleDeadlineWithPendingDelayedTaskFarInTheFuture) {
308 std::vector<std::string> timeline;
309 RecordTimelineEvents(&timeline);
310 InitAndPostDelayedWakeupTask();
312 timeline.push_back("Post delayed and idle tasks");
313 // Post a delayed task timed to occur well after the long idle period.
314 default_task_runner_->PostDelayedTask(
315 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
316 base::Unretained(clock_.get())),
317 base::TimeDelta::FromMilliseconds(1000));
318 idle_task_runner_->PostIdleTask(FROM_HERE,
319 base::Bind(&TimelineIdleTestTask, &timeline));
321 RunUntilIdle();
323 std::string expected_timeline[] = {
324 "CanEnterLongIdlePeriod @ 5",
325 "Post delayed and idle tasks",
326 "IsNotQuiescent @ 105",
327 "CanEnterLongIdlePeriod @ 405",
328 "run TimelineIdleTestTask deadline 455", // Note the full 50ms deadline.
329 "CanEnterLongIdlePeriod @ 455",
330 "run RecordTimelineTask @ 1005"};
332 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
335 TEST_F(WorkerSchedulerImplTest,
336 TestPostIdleTaskAfterRunningUntilIdle_NoWakeUp) {
337 InitAndPostDelayedWakeupTask();
339 default_task_runner_->PostDelayedTask(
340 FROM_HERE, base::Bind(&NopTask), base::TimeDelta::FromMilliseconds(1000));
341 RunUntilIdle();
343 // The delayed call to EnableLongIdlePeriod happened and it posted a call to
344 // EnableLongIdlePeriod on the after wakeup control queue. Without an other
345 // non-idle task posted, the idle tasks won't run.
346 std::vector<std::string> run_order;
347 PostTestTasks(&run_order, "I1 I2");
349 RunUntilIdle();
350 EXPECT_TRUE(run_order.empty());
353 TEST_F(WorkerSchedulerImplTest,
354 TestPostIdleTaskAfterRunningUntilIdle_WithWakeUp) {
355 InitAndPostDelayedWakeupTask();
357 default_task_runner_->PostDelayedTask(
358 FROM_HERE, base::Bind(&NopTask), base::TimeDelta::FromMilliseconds(1000));
359 RunUntilIdle();
360 // The delayed call to EnableLongIdlePeriod happened and it posted a call to
361 // EnableLongIdlePeriod on the after wakeup control queue. Without an other
362 // non-idle task posted, the idle tasks won't run.
364 std::vector<std::string> run_order;
365 PostTestTasks(&run_order, "I1 I2 D3");
367 RunUntilIdle();
368 EXPECT_THAT(run_order,
369 testing::ElementsAre(std::string("D3"), std::string("I1"),
370 std::string("I2")));
373 TEST_F(WorkerSchedulerImplTest, TestLongIdlePeriodTimeline) {
374 Init();
376 std::vector<std::string> timeline;
377 RecordTimelineEvents(&timeline);
379 // The scheduler should not run the initiate_next_long_idle_period task if
380 // there are no idle tasks and no other task woke up the scheduler, thus
381 // the idle period deadline shouldn't update at the end of the current long
382 // idle period.
383 base::TimeTicks idle_period_deadline =
384 scheduler_->CurrentIdleTaskDeadlineForTesting();
385 clock_->AdvanceNow(maximum_idle_period_duration());
386 RunUntilIdle();
388 base::TimeTicks new_idle_period_deadline =
389 scheduler_->CurrentIdleTaskDeadlineForTesting();
390 EXPECT_EQ(idle_period_deadline, new_idle_period_deadline);
392 // Posting a after-wakeup idle task also shouldn't wake the scheduler or
393 // initiate the next long idle period.
394 timeline.push_back("PostIdleTaskAfterWakeup");
395 idle_task_runner_->PostIdleTaskAfterWakeup(
396 FROM_HERE, base::Bind(&TimelineIdleTestTask, &timeline));
397 RunUntilIdle();
398 new_idle_period_deadline = scheduler_->CurrentIdleTaskDeadlineForTesting();
400 // Running a normal task should initiate a new long idle period after waiting
401 // 300ms for quiescence.
402 timeline.push_back("Post RecordTimelineTask");
403 default_task_runner_->PostTask(
404 FROM_HERE, base::Bind(&RecordTimelineTask, base::Unretained(&timeline),
405 base::Unretained(clock_.get())));
406 RunUntilIdle();
408 std::string expected_timeline[] = {
409 "RunUntilIdle begin @ 55",
410 "RunUntilIdle end @ 55",
411 "PostIdleTaskAfterWakeup",
412 "RunUntilIdle begin @ 55", // NOTE idle task doesn't run till later.
413 "RunUntilIdle end @ 55",
414 "Post RecordTimelineTask",
415 "RunUntilIdle begin @ 55",
416 "run RecordTimelineTask @ 55",
417 "IsNotQuiescent @ 55", // NOTE we have to wait for quiescence.
418 "CanEnterLongIdlePeriod @ 355",
419 "run TimelineIdleTestTask deadline 405",
420 "CanEnterLongIdlePeriod @ 405",
421 "RunUntilIdle end @ 455"};
423 EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
426 } // namespace content