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
;
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
,
36 vector
->push_back(value
);
39 void AppendToVectorIdleTestTask(std::vector
<std::string
>* vector
,
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
)));
53 class WorkerSchedulerImplForTest
: public WorkerSchedulerImpl
{
55 WorkerSchedulerImplForTest(
56 scoped_refptr
<SchedulerTaskRunnerDelegate
> main_task_runner
,
57 base::SimpleTestTickClock
* clock_
)
58 : WorkerSchedulerImpl(main_task_runner
),
62 void RecordTimelineEvents(std::vector
<std::string
>* timeline
) {
67 bool CanEnterLongIdlePeriod(
69 base::TimeDelta
* next_long_idle_period_delay_out
) override
{
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
{
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
{
92 WorkerSchedulerImplTest()
93 : clock_(new base::SimpleTestTickClock()),
94 mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_
.get(), true)),
96 SchedulerTaskRunnerDelegateForTest::Create(mock_task_runner_
)),
98 new WorkerSchedulerImplForTest(main_task_runner_
, clock_
.get())),
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()) {
119 default_task_runner_
= scheduler_
->DefaultTaskRunner();
120 idle_task_runner_
= scheduler_
->IdleTaskRunner();
124 void RecordTimelineEvents(std::vector
<std::string
>* timeline
) {
125 timeline_
= timeline
;
126 scheduler_
->RecordTimelineEvents(timeline
);
129 void RunUntilIdle() {
131 timeline_
->push_back(base::StringPrintf(
132 "RunUntilIdle begin @ %d", TimeTicksToIntMs(clock_
->NowTicks())));
134 mock_task_runner_
->RunUntilIdle();
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
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()) {
154 default_task_runner_
->PostTask(
155 FROM_HERE
, base::Bind(&AppendToVectorTestTask
, run_order
, task
));
158 idle_task_runner_
->PostIdleTask(
160 base::Bind(&AppendToVectorIdleTestTask
, run_order
, task
));
168 static base::TimeDelta
maximum_idle_period_duration() {
169 return base::TimeDelta::FromMilliseconds(
170 IdleHelper::kMaximumIdlePeriodMillis
);
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
) {
190 std::vector
<std::string
> run_order
;
191 PostTestTasks(&run_order
, "D1 D2 D3 D4");
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
) {
202 std::vector
<std::string
> run_order
;
203 PostTestTasks(&run_order
, "I1");
206 EXPECT_THAT(run_order
, testing::ElementsAre(std::string("I1")));
209 TEST_F(WorkerSchedulerImplTest
, TestPostDefaultAndIdleTasks
) {
212 std::vector
<std::string
> run_order
;
213 PostTestTasks(&run_order
, "I1 D2 D3 D4");
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
) {
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));
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
);
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())));
250 timeline
.push_back("Post idle task");
251 idle_task_runner_
->PostIdleTask(FROM_HERE
,
252 base::Bind(&TimelineIdleTestTask
, &timeline
));
256 std::string expected_timeline
[] = {"CanEnterLongIdlePeriod @ 5",
258 "run RecordTimelineTask @ 5",
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
);
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
));
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
);
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
));
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
) {
323 default_task_runner_
->PostDelayedTask(
324 FROM_HERE
, base::Bind(&NopTask
), base::TimeDelta::FromMilliseconds(1000));
327 std::vector
<std::string
> run_order
;
328 PostTestTasks(&run_order
, "I1 I2 D3");
331 EXPECT_THAT(run_order
,
332 testing::ElementsAre(std::string("D3"), std::string("I1"),
336 TEST_F(WorkerSchedulerImplTest
, TestLongIdlePeriodTimeline
) {
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
346 base::TimeTicks idle_period_deadline
=
347 scheduler_
->CurrentIdleTaskDeadlineForTesting();
348 clock_
->Advance(maximum_idle_period_duration());
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
));
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())));
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