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
;
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
) {
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
,
44 vector
->push_back(value
);
47 void AppendToVectorIdleTestTask(std::vector
<std::string
>* vector
,
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
)));
61 class WorkerSchedulerImplForTest
: public WorkerSchedulerImpl
{
63 WorkerSchedulerImplForTest(
64 scoped_refptr
<NestableSingleThreadTaskRunner
> main_task_runner
,
65 scoped_refptr
<cc::TestNowSource
> clock_
)
66 : WorkerSchedulerImpl(main_task_runner
),
70 void RecordTimelineEvents(std::vector
<std::string
>* timeline
) {
75 bool CanEnterLongIdlePeriod(
77 base::TimeDelta
* next_long_idle_period_delay_out
) override
{
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
{
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
{
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_
)),
106 new WorkerSchedulerImplForTest(nestable_task_runner_
, clock_
)),
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()) {
125 default_task_runner_
= scheduler_
->DefaultTaskRunner();
126 idle_task_runner_
= scheduler_
->IdleTaskRunner();
130 void RecordTimelineEvents(std::vector
<std::string
>* timeline
) {
131 timeline_
= timeline
;
132 scheduler_
->RecordTimelineEvents(timeline
);
135 void RunUntilIdle() {
137 timeline_
->push_back(base::StringPrintf("RunUntilIdle begin @ %d",
138 TimeTicksToIntMs(clock_
->Now())));
140 mock_task_runner_
->RunUntilIdle();
142 timeline_
->push_back(base::StringPrintf("RunUntilIdle end @ %d",
143 TimeTicksToIntMs(clock_
->Now())));
147 void InitAndPostDelayedWakeupTask() {
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
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()) {
171 default_task_runner_
->PostTask(
172 FROM_HERE
, base::Bind(&AppendToVectorTestTask
, run_order
, task
));
175 idle_task_runner_
->PostIdleTask(
177 base::Bind(&AppendToVectorIdleTestTask
, run_order
, task
));
185 static base::TimeDelta
maximum_idle_period_duration() {
186 return base::TimeDelta::FromMilliseconds(
187 SchedulerHelper::kMaximumIdlePeriodMillis
);
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");
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");
223 EXPECT_THAT(run_order
, testing::ElementsAre(std::string("I1")));
226 TEST_F(WorkerSchedulerImplTest
, TestPostIdleTask_NoWakeup
) {
228 std::vector
<std::string
> run_order
;
229 PostTestTasks(&run_order
, "I1");
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");
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();
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");
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));
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
));
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
));
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));
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");
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));
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");
368 EXPECT_THAT(run_order
,
369 testing::ElementsAre(std::string("D3"), std::string("I1"),
373 TEST_F(WorkerSchedulerImplTest
, TestLongIdlePeriodTimeline
) {
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
383 base::TimeTicks idle_period_deadline
=
384 scheduler_
->CurrentIdleTaskDeadlineForTesting();
385 clock_
->AdvanceNow(maximum_idle_period_duration());
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
));
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())));
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