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/idle_helper.h"
7 #include "base/callback.h"
8 #include "base/test/simple_test_tick_clock.h"
9 #include "cc/test/ordered_simple_task_runner.h"
10 #include "components/scheduler/child/nestable_task_runner_for_test.h"
11 #include "components/scheduler/child/scheduler_helper.h"
12 #include "components/scheduler/child/scheduler_message_loop_delegate.h"
13 #include "components/scheduler/child/task_queue_manager.h"
14 #include "components/scheduler/child/test_time_source.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
19 using testing::AnyNumber
;
20 using testing::AtLeast
;
21 using testing::Exactly
;
22 using testing::Invoke
;
23 using testing::Return
;
28 void AppendToVectorTestTask(std::vector
<std::string
>* vector
,
30 vector
->push_back(value
);
33 void AppendToVectorIdleTestTask(std::vector
<std::string
>* vector
,
35 base::TimeTicks deadline
) {
36 AppendToVectorTestTask(vector
, value
);
42 void NullIdleTask(base::TimeTicks deadline
) {
45 void AppendToVectorReentrantTask(base::SingleThreadTaskRunner
* task_runner
,
46 std::vector
<int>* vector
,
48 int max_reentrant_count
) {
49 vector
->push_back((*reentrant_count
)++);
50 if (*reentrant_count
< max_reentrant_count
) {
51 task_runner
->PostTask(
53 base::Bind(AppendToVectorReentrantTask
, base::Unretained(task_runner
),
54 vector
, reentrant_count
, max_reentrant_count
));
58 void IdleTestTask(int* run_count
,
59 base::TimeTicks
* deadline_out
,
60 base::TimeTicks deadline
) {
62 *deadline_out
= deadline
;
65 int max_idle_task_reposts
= 2;
67 void RepostingIdleTestTask(SingleThreadIdleTaskRunner
* idle_task_runner
,
69 base::TimeTicks
* deadline_out
,
70 base::TimeTicks deadline
) {
71 if ((*run_count
+ 1) < max_idle_task_reposts
) {
72 idle_task_runner
->PostIdleTask(
74 base::Bind(&RepostingIdleTestTask
, base::Unretained(idle_task_runner
),
75 run_count
, deadline_out
));
77 *deadline_out
= deadline
;
81 void RepostingUpdateClockIdleTestTask(
82 SingleThreadIdleTaskRunner
* idle_task_runner
,
84 base::SimpleTestTickClock
* clock
,
85 base::TimeDelta advance_time
,
86 std::vector
<base::TimeTicks
>* deadlines
,
87 base::TimeTicks deadline
) {
88 if ((*run_count
+ 1) < max_idle_task_reposts
) {
89 idle_task_runner
->PostIdleTask(
90 FROM_HERE
, base::Bind(&RepostingUpdateClockIdleTestTask
,
91 base::Unretained(idle_task_runner
), run_count
,
92 clock
, advance_time
, deadlines
));
94 deadlines
->push_back(deadline
);
96 clock
->Advance(advance_time
);
99 void RepeatingTask(base::SingleThreadTaskRunner
* task_runner
,
101 base::TimeDelta delay
) {
102 if (num_repeats
> 1) {
103 task_runner
->PostDelayedTask(
104 FROM_HERE
, base::Bind(&RepeatingTask
, base::Unretained(task_runner
),
105 num_repeats
- 1, delay
),
110 void UpdateClockIdleTestTask(base::SimpleTestTickClock
* clock
,
112 base::TimeTicks set_time
,
113 base::TimeTicks deadline
) {
114 clock
->Advance(set_time
- clock
->NowTicks());
118 void UpdateClockToDeadlineIdleTestTask(base::SimpleTestTickClock
* clock
,
120 base::TimeTicks deadline
) {
121 UpdateClockIdleTestTask(clock
, run_count
, deadline
, deadline
);
124 void EndIdlePeriodIdleTask(IdleHelper
* idle_helper
, base::TimeTicks deadline
) {
125 idle_helper
->EndIdlePeriod();
128 scoped_refptr
<NestableSingleThreadTaskRunner
>
129 CreateNestableSingleThreadTaskRunner(
130 base::MessageLoop
* message_loop
,
131 scoped_refptr
<cc::OrderedSimpleTaskRunner
> mock_task_runner
) {
133 return SchedulerMessageLoopDelegate::Create(message_loop
);
135 return NestableTaskRunnerForTest::Create(mock_task_runner
);
140 class IdleHelperForTest
: public IdleHelper
, public IdleHelper::Delegate
{
142 explicit IdleHelperForTest(
143 SchedulerHelper
* scheduler_helper
,
144 base::TimeDelta required_quiescence_duration_before_long_idle_period
)
145 : IdleHelper(scheduler_helper
,
147 SchedulerHelper::TASK_QUEUE_COUNT
,
149 TRACE_DISABLED_BY_DEFAULT("test.idle"),
150 "TestSchedulerIdlePeriod",
151 required_quiescence_duration_before_long_idle_period
) {}
153 ~IdleHelperForTest() override
{}
155 // SchedulerHelperDelegate implementation:
156 MOCK_METHOD2(CanEnterLongIdlePeriod
,
157 bool(base::TimeTicks now
,
158 base::TimeDelta
* next_long_idle_period_delay_out
));
160 MOCK_METHOD0(IsNotQuiescent
, void());
161 MOCK_METHOD0(OnIdlePeriodStarted
, void());
162 MOCK_METHOD0(OnIdlePeriodEnded
, void());
165 class BaseIdleHelperTest
: public testing::Test
{
168 base::MessageLoop
* message_loop
,
169 base::TimeDelta required_quiescence_duration_before_long_idle_period
)
170 : clock_(new base::SimpleTestTickClock()),
174 : new cc::OrderedSimpleTaskRunner(clock_
.get(), false)),
175 message_loop_(message_loop
),
176 nestable_task_runner_(
177 CreateNestableSingleThreadTaskRunner(message_loop
,
180 new SchedulerHelper(nestable_task_runner_
,
182 TRACE_DISABLED_BY_DEFAULT("test.idle"),
183 TRACE_DISABLED_BY_DEFAULT("test.idle.debug"),
184 SchedulerHelper::TASK_QUEUE_COUNT
+ 1)),
185 idle_helper_(new IdleHelperForTest(
186 scheduler_helper_
.get(),
187 required_quiescence_duration_before_long_idle_period
)),
188 default_task_runner_(scheduler_helper_
->DefaultTaskRunner()),
189 idle_task_runner_(idle_helper_
->IdleTaskRunner()) {
190 clock_
->Advance(base::TimeDelta::FromMicroseconds(5000));
191 scheduler_helper_
->SetTimeSourceForTesting(
192 make_scoped_ptr(new TestTimeSource(clock_
.get())));
193 scheduler_helper_
->GetTaskQueueManagerForTesting()->SetTimeSourceForTesting(
194 make_scoped_ptr(new TestTimeSource(clock_
.get())));
197 ~BaseIdleHelperTest() override
{}
199 void SetUp() override
{
200 EXPECT_CALL(*idle_helper_
, OnIdlePeriodStarted()).Times(AnyNumber());
201 EXPECT_CALL(*idle_helper_
, OnIdlePeriodEnded()).Times(AnyNumber());
202 EXPECT_CALL(*idle_helper_
, CanEnterLongIdlePeriod(_
, _
))
204 .WillRepeatedly(Return(true));
207 void TearDown() override
{
208 DCHECK(!mock_task_runner_
.get() || !message_loop_
.get());
209 if (mock_task_runner_
.get()) {
210 // Check that all tests stop posting tasks.
211 mock_task_runner_
->SetAutoAdvanceNowToPendingTasks(true);
212 while (mock_task_runner_
->RunUntilIdle()) {
215 message_loop_
->RunUntilIdle();
219 void RunUntilIdle() {
220 // Only one of mock_task_runner_ or message_loop_ should be set.
221 DCHECK(!mock_task_runner_
.get() || !message_loop_
.get());
222 if (mock_task_runner_
.get())
223 mock_task_runner_
->RunUntilIdle();
225 message_loop_
->RunUntilIdle();
228 template <typename E
>
229 static void CallForEachEnumValue(E first
,
231 const char* (*function
)(E
)) {
232 for (E val
= first
; val
< last
;
233 val
= static_cast<E
>(static_cast<int>(val
) + 1)) {
238 static void CheckAllTaskQueueIdToString() {
239 CallForEachEnumValue
<IdleHelper::IdlePeriodState
>(
240 IdleHelper::IdlePeriodState::FIRST_IDLE_PERIOD_STATE
,
241 IdleHelper::IdlePeriodState::IDLE_PERIOD_STATE_COUNT
,
242 &IdleHelper::IdlePeriodStateToString
);
245 bool IsInIdlePeriod() const {
246 return idle_helper_
->IsInIdlePeriod(
247 idle_helper_
->SchedulerIdlePeriodState());
251 static base::TimeDelta
maximum_idle_period_duration() {
252 return base::TimeDelta::FromMilliseconds(
253 IdleHelper::kMaximumIdlePeriodMillis
);
256 static base::TimeDelta
retry_enable_long_idle_period_delay() {
257 return base::TimeDelta::FromMilliseconds(
258 IdleHelper::kRetryEnableLongIdlePeriodDelayMillis
);
261 static base::TimeDelta
minimum_idle_period_duration() {
262 return base::TimeDelta::FromMilliseconds(
263 IdleHelper::kMinimumIdlePeriodDurationMillis
);
266 base::TimeTicks
CurrentIdleTaskDeadline() {
267 return idle_helper_
->CurrentIdleTaskDeadline();
270 void CheckIdlePeriodStateIs(const char* expected
) {
271 EXPECT_STREQ(expected
, IdleHelper::IdlePeriodStateToString(
272 idle_helper_
->SchedulerIdlePeriodState()));
275 scoped_ptr
<base::SimpleTestTickClock
> clock_
;
276 // Only one of mock_task_runner_ or message_loop_ will be set.
277 scoped_refptr
<cc::OrderedSimpleTaskRunner
> mock_task_runner_
;
278 scoped_ptr
<base::MessageLoop
> message_loop_
;
280 scoped_refptr
<NestableSingleThreadTaskRunner
> nestable_task_runner_
;
281 scoped_ptr
<SchedulerHelper
> scheduler_helper_
;
282 scoped_ptr
<IdleHelperForTest
> idle_helper_
;
283 scoped_refptr
<base::SingleThreadTaskRunner
> default_task_runner_
;
284 scoped_refptr
<SingleThreadIdleTaskRunner
> idle_task_runner_
;
286 DISALLOW_COPY_AND_ASSIGN(BaseIdleHelperTest
);
289 class IdleHelperTest
: public BaseIdleHelperTest
{
291 IdleHelperTest() : BaseIdleHelperTest(nullptr, base::TimeDelta()) {}
293 ~IdleHelperTest() override
{}
295 TaskQueueManager
* task_queue_manager() const {
296 return scheduler_helper_
->GetTaskQueueManagerForTesting();
300 DISALLOW_COPY_AND_ASSIGN(IdleHelperTest
);
303 TEST_F(IdleHelperTest
, TestPostIdleTask
) {
305 base::TimeTicks expected_deadline
=
306 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(2300);
307 base::TimeTicks deadline_in_task
;
309 clock_
->Advance(base::TimeDelta::FromMilliseconds(100));
310 idle_task_runner_
->PostIdleTask(
311 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
314 EXPECT_EQ(0, run_count
);
316 idle_helper_
->StartIdlePeriod(
317 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
320 EXPECT_EQ(1, run_count
);
321 EXPECT_EQ(expected_deadline
, deadline_in_task
);
324 TEST_F(IdleHelperTest
, TestPostIdleTask_EndIdlePeriod
) {
326 base::TimeTicks deadline_in_task
;
328 clock_
->Advance(base::TimeDelta::FromMilliseconds(100));
329 idle_task_runner_
->PostIdleTask(
330 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
333 EXPECT_EQ(0, run_count
);
335 idle_helper_
->StartIdlePeriod(
336 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
337 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
338 idle_helper_
->EndIdlePeriod();
340 EXPECT_EQ(0, run_count
);
343 TEST_F(IdleHelperTest
, TestRepostingIdleTask
) {
344 base::TimeTicks actual_deadline
;
347 max_idle_task_reposts
= 2;
348 idle_task_runner_
->PostIdleTask(
349 FROM_HERE
, base::Bind(&RepostingIdleTestTask
, idle_task_runner_
,
350 &run_count
, &actual_deadline
));
351 idle_helper_
->StartIdlePeriod(
352 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
353 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
355 EXPECT_EQ(1, run_count
);
357 // Reposted tasks shouldn't run until next idle period.
359 EXPECT_EQ(1, run_count
);
361 idle_helper_
->StartIdlePeriod(
362 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
363 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
365 EXPECT_EQ(2, run_count
);
368 TEST_F(IdleHelperTest
, TestIdleTaskExceedsDeadline
) {
371 // Post two UpdateClockToDeadlineIdleTestTask tasks.
372 idle_task_runner_
->PostIdleTask(
374 base::Bind(&UpdateClockToDeadlineIdleTestTask
, clock_
.get(), &run_count
));
375 idle_task_runner_
->PostIdleTask(
377 base::Bind(&UpdateClockToDeadlineIdleTestTask
, clock_
.get(), &run_count
));
379 idle_helper_
->StartIdlePeriod(
380 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
381 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
383 // Only the first idle task should execute since it's used up the deadline.
384 EXPECT_EQ(1, run_count
);
386 idle_helper_
->EndIdlePeriod();
387 idle_helper_
->StartIdlePeriod(
388 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
389 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
391 // Second task should be run on the next idle period.
392 EXPECT_EQ(2, run_count
);
395 TEST_F(IdleHelperTest
, TestPostIdleTaskAfterWakeup
) {
396 base::TimeTicks deadline_in_task
;
399 idle_task_runner_
->PostIdleTaskAfterWakeup(
400 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
402 idle_helper_
->StartIdlePeriod(
403 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
404 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
406 // Shouldn't run yet as no other task woke up the scheduler.
407 EXPECT_EQ(0, run_count
);
409 // Must start a new idle period before idle task runs.
410 idle_task_runner_
->PostIdleTaskAfterWakeup(
411 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
413 idle_helper_
->StartIdlePeriod(
414 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
415 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
417 // Another after wakeup idle task shouldn't wake the scheduler.
418 EXPECT_EQ(0, run_count
);
420 default_task_runner_
->PostTask(FROM_HERE
, base::Bind(&NullTask
));
423 idle_helper_
->StartIdlePeriod(
424 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
425 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
427 // Execution of default task queue task should trigger execution of idle task.
428 EXPECT_EQ(2, run_count
);
431 TEST_F(IdleHelperTest
, TestPostIdleTaskAfterWakeupWhileAwake
) {
432 base::TimeTicks deadline_in_task
;
435 idle_task_runner_
->PostIdleTaskAfterWakeup(
436 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
437 default_task_runner_
->PostTask(FROM_HERE
, base::Bind(&NullTask
));
440 // Must start a new idle period before idle task runs.
441 idle_helper_
->StartIdlePeriod(
442 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
443 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
445 // Should run as the scheduler was already awakened by the normal task.
446 EXPECT_EQ(1, run_count
);
449 TEST_F(IdleHelperTest
, TestPostIdleTaskWakesAfterWakeupIdleTask
) {
450 base::TimeTicks deadline_in_task
;
453 idle_task_runner_
->PostIdleTaskAfterWakeup(
454 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
455 idle_task_runner_
->PostIdleTask(
456 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
458 idle_helper_
->StartIdlePeriod(
459 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
460 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
462 // Must start a new idle period before after-wakeup idle task runs.
463 idle_helper_
->StartIdlePeriod(
464 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
465 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
467 // Normal idle task should wake up after-wakeup idle task.
468 EXPECT_EQ(2, run_count
);
471 class IdleHelperTestWithIdlePeriodObserver
: public BaseIdleHelperTest
{
473 IdleHelperTestWithIdlePeriodObserver()
474 : BaseIdleHelperTest(nullptr, base::TimeDelta()) {}
476 ~IdleHelperTestWithIdlePeriodObserver() override
{}
478 void SetUp() override
{
479 // Don't set expectations on IdleHelper::Delegate.
482 TaskQueueManager
* task_queue_manager() const {
483 return scheduler_helper_
->GetTaskQueueManagerForTesting();
486 void ExpectIdlePeriodStartsButNeverEnds() {
487 EXPECT_CALL(*idle_helper_
, OnIdlePeriodStarted()).Times(1);
488 EXPECT_CALL(*idle_helper_
, OnIdlePeriodEnded()).Times(0);
491 void ExpectIdlePeriodStartsAndEnds(const testing::Cardinality
& cardinality
) {
492 EXPECT_CALL(*idle_helper_
, OnIdlePeriodStarted()).Times(cardinality
);
493 EXPECT_CALL(*idle_helper_
, OnIdlePeriodEnded()).Times(cardinality
);
497 DISALLOW_COPY_AND_ASSIGN(IdleHelperTestWithIdlePeriodObserver
);
500 TEST_F(IdleHelperTestWithIdlePeriodObserver
, TestEnterButNotExitIdlePeriod
) {
501 ExpectIdlePeriodStartsButNeverEnds();
503 idle_helper_
->StartIdlePeriod(
504 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
505 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
508 TEST_F(IdleHelperTestWithIdlePeriodObserver
, TestEnterAndExitIdlePeriod
) {
509 BaseIdleHelperTest
* fixture
= this;
510 ON_CALL(*idle_helper_
, OnIdlePeriodStarted())
512 Invoke([fixture
]() { EXPECT_TRUE(fixture
->IsInIdlePeriod()); }));
513 ON_CALL(*idle_helper_
, OnIdlePeriodEnded())
515 Invoke([fixture
]() { EXPECT_FALSE(fixture
->IsInIdlePeriod()); }));
517 ExpectIdlePeriodStartsAndEnds(Exactly(1));
519 idle_helper_
->StartIdlePeriod(
520 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
521 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
522 idle_helper_
->EndIdlePeriod();
525 class IdleHelperWithMessageLoopTest
: public BaseIdleHelperTest
{
527 IdleHelperWithMessageLoopTest()
528 : BaseIdleHelperTest(new base::MessageLoop(), base::TimeDelta()) {}
529 ~IdleHelperWithMessageLoopTest() override
{}
531 void PostFromNestedRunloop(std::vector
<
532 std::pair
<SingleThreadIdleTaskRunner::IdleTask
, bool>>* tasks
) {
533 base::MessageLoop::ScopedNestableTaskAllower
allow(message_loop_
.get());
534 for (std::pair
<SingleThreadIdleTaskRunner::IdleTask
, bool>& pair
: *tasks
) {
536 idle_task_runner_
->PostIdleTask(FROM_HERE
, pair
.first
);
538 idle_task_runner_
->PostNonNestableIdleTask(FROM_HERE
, pair
.first
);
541 idle_helper_
->StartIdlePeriod(
542 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
543 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
544 message_loop_
->RunUntilIdle();
547 void SetUp() override
{
548 EXPECT_CALL(*idle_helper_
, OnIdlePeriodStarted()).Times(AnyNumber());
549 EXPECT_CALL(*idle_helper_
, OnIdlePeriodEnded()).Times(AnyNumber());
553 DISALLOW_COPY_AND_ASSIGN(IdleHelperWithMessageLoopTest
);
556 TEST_F(IdleHelperWithMessageLoopTest
,
557 NonNestableIdleTaskDoesntExecuteInNestedLoop
) {
558 std::vector
<std::string
> order
;
559 idle_task_runner_
->PostIdleTask(
561 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("1")));
562 idle_task_runner_
->PostIdleTask(
564 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("2")));
566 std::vector
<std::pair
<SingleThreadIdleTaskRunner::IdleTask
, bool>>
567 tasks_to_post_from_nested_loop
;
568 tasks_to_post_from_nested_loop
.push_back(std::make_pair(
569 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("3")),
571 tasks_to_post_from_nested_loop
.push_back(std::make_pair(
572 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("4")), true));
573 tasks_to_post_from_nested_loop
.push_back(std::make_pair(
574 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("5")), true));
576 default_task_runner_
->PostTask(
578 base::Bind(&IdleHelperWithMessageLoopTest::PostFromNestedRunloop
,
579 base::Unretained(this),
580 base::Unretained(&tasks_to_post_from_nested_loop
)));
582 idle_helper_
->StartIdlePeriod(
583 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
584 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
586 // Note we expect task 3 to run last because it's non-nestable.
587 EXPECT_THAT(order
, testing::ElementsAre(std::string("1"), std::string("2"),
588 std::string("4"), std::string("5"),
592 TEST_F(IdleHelperTestWithIdlePeriodObserver
, TestLongIdlePeriod
) {
593 base::TimeTicks expected_deadline
=
594 clock_
->NowTicks() + maximum_idle_period_duration();
595 base::TimeTicks deadline_in_task
;
598 idle_task_runner_
->PostIdleTask(
599 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
601 EXPECT_CALL(*idle_helper_
, CanEnterLongIdlePeriod(_
, _
))
603 .WillRepeatedly(Return(true));
604 ExpectIdlePeriodStartsButNeverEnds();
607 EXPECT_EQ(0, run_count
); // Shouldn't run yet as no idle period.
609 idle_helper_
->EnableLongIdlePeriod();
611 EXPECT_EQ(1, run_count
); // Should have run in a long idle time.
612 EXPECT_EQ(expected_deadline
, deadline_in_task
);
615 TEST_F(IdleHelperTest
, TestLongIdlePeriodWithPendingDelayedTask
) {
616 base::TimeDelta pending_task_delay
= base::TimeDelta::FromMilliseconds(30);
617 base::TimeTicks expected_deadline
= clock_
->NowTicks() + pending_task_delay
;
618 base::TimeTicks deadline_in_task
;
621 idle_task_runner_
->PostIdleTask(
622 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
623 default_task_runner_
->PostDelayedTask(FROM_HERE
, base::Bind(&NullTask
),
626 idle_helper_
->EnableLongIdlePeriod();
628 EXPECT_EQ(1, run_count
); // Should have run in a long idle time.
629 EXPECT_EQ(expected_deadline
, deadline_in_task
);
632 TEST_F(IdleHelperTest
, TestLongIdlePeriodWithLatePendingDelayedTask
) {
633 base::TimeDelta pending_task_delay
= base::TimeDelta::FromMilliseconds(10);
634 base::TimeTicks deadline_in_task
;
637 default_task_runner_
->PostDelayedTask(FROM_HERE
, base::Bind(&NullTask
),
640 // Advance clock until after delayed task was meant to be run.
641 clock_
->Advance(base::TimeDelta::FromMilliseconds(20));
643 // Post an idle task and then EnableLongIdlePeriod. Since there is a late
644 // pending delayed task this shouldn't actually start an idle period.
645 idle_task_runner_
->PostIdleTask(
646 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
647 idle_helper_
->EnableLongIdlePeriod();
649 EXPECT_EQ(0, run_count
);
651 // After the delayed task has been run we should trigger an idle period.
652 clock_
->Advance(maximum_idle_period_duration());
654 EXPECT_EQ(1, run_count
);
657 TEST_F(IdleHelperTestWithIdlePeriodObserver
, TestLongIdlePeriodRepeating
) {
658 mock_task_runner_
->SetAutoAdvanceNowToPendingTasks(true);
659 std::vector
<base::TimeTicks
> actual_deadlines
;
662 EXPECT_CALL(*idle_helper_
, CanEnterLongIdlePeriod(_
, _
))
664 .WillRepeatedly(Return(true));
665 ExpectIdlePeriodStartsAndEnds(AtLeast(2));
667 max_idle_task_reposts
= 3;
668 base::TimeTicks
clock_before(clock_
->NowTicks());
669 base::TimeDelta
idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
670 idle_task_runner_
->PostIdleTask(
671 FROM_HERE
, base::Bind(&RepostingUpdateClockIdleTestTask
,
672 idle_task_runner_
, &run_count
, clock_
.get(),
673 idle_task_runtime
, &actual_deadlines
));
675 // Check each idle task runs in their own idle period.
676 idle_helper_
->EnableLongIdlePeriod();
678 EXPECT_EQ(3, run_count
);
681 testing::ElementsAre(
682 clock_before
+ maximum_idle_period_duration(),
683 clock_before
+ idle_task_runtime
+ maximum_idle_period_duration(),
684 clock_before
+ (2 * idle_task_runtime
) +
685 maximum_idle_period_duration()));
687 max_idle_task_reposts
= 5;
688 idle_task_runner_
->PostIdleTask(
689 FROM_HERE
, base::Bind(&RepostingUpdateClockIdleTestTask
,
690 idle_task_runner_
, &run_count
, clock_
.get(),
691 idle_task_runtime
, &actual_deadlines
));
692 idle_task_runner_
->PostIdleTask(
694 base::Bind(&EndIdlePeriodIdleTask
, base::Unretained(idle_helper_
.get())));
696 // Ensure that reposting tasks stop after EndIdlePeriod is called.
698 EXPECT_EQ(4, run_count
);
701 TEST_F(IdleHelperTest
, TestLongIdlePeriodDoesNotWakeScheduler
) {
702 base::TimeTicks deadline_in_task
;
705 // Start a long idle period and get the time it should end.
706 idle_helper_
->EnableLongIdlePeriod();
707 // The scheduler should not run the enable_next_long_idle_period task if
708 // there are no idle tasks and no other task woke up the scheduler, thus
709 // the idle period deadline shouldn't update at the end of the current long
711 base::TimeTicks idle_period_deadline
= CurrentIdleTaskDeadline();
712 clock_
->Advance(maximum_idle_period_duration());
715 base::TimeTicks new_idle_period_deadline
= CurrentIdleTaskDeadline();
716 EXPECT_EQ(idle_period_deadline
, new_idle_period_deadline
);
718 // Posting a after-wakeup idle task also shouldn't wake the scheduler or
719 // initiate the next long idle period.
720 idle_task_runner_
->PostIdleTaskAfterWakeup(
721 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
723 new_idle_period_deadline
= CurrentIdleTaskDeadline();
724 EXPECT_EQ(idle_period_deadline
, new_idle_period_deadline
);
725 EXPECT_EQ(0, run_count
);
727 // Running a normal task should initiate a new long idle period though.
728 default_task_runner_
->PostTask(FROM_HERE
, base::Bind(&NullTask
));
730 new_idle_period_deadline
= CurrentIdleTaskDeadline();
731 EXPECT_EQ(idle_period_deadline
+ maximum_idle_period_duration(),
732 new_idle_period_deadline
);
734 EXPECT_EQ(1, run_count
);
737 TEST_F(IdleHelperTestWithIdlePeriodObserver
,
738 TestLongIdlePeriodWhenNotCanEnterLongIdlePeriod
) {
739 base::TimeDelta delay
= base::TimeDelta::FromMilliseconds(1000);
740 base::TimeDelta halfDelay
= base::TimeDelta::FromMilliseconds(500);
741 base::TimeTicks delayOver
= clock_
->NowTicks() + delay
;
742 base::TimeTicks deadline_in_task
;
745 ON_CALL(*idle_helper_
, CanEnterLongIdlePeriod(_
, _
))
746 .WillByDefault(Invoke(
747 [delay
, delayOver
](base::TimeTicks now
,
748 base::TimeDelta
* next_long_idle_period_delay_out
) {
749 if (now
>= delayOver
)
751 *next_long_idle_period_delay_out
= delay
;
755 EXPECT_CALL(*idle_helper_
, CanEnterLongIdlePeriod(_
, _
)).Times(2);
756 EXPECT_CALL(*idle_helper_
, OnIdlePeriodStarted()).Times(AnyNumber());
758 idle_task_runner_
->PostIdleTask(
759 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
761 // Make sure Idle tasks don't run until the delay has occurred.
762 idle_helper_
->EnableLongIdlePeriod();
764 EXPECT_EQ(0, run_count
);
766 clock_
->Advance(halfDelay
);
768 EXPECT_EQ(0, run_count
);
770 // Delay is finished, idle task should run.
771 clock_
->Advance(halfDelay
);
773 EXPECT_EQ(1, run_count
);
776 TEST_F(IdleHelperTest
, TestLongIdlePeriodImmediatelyRestartsIfMaxDeadline
) {
777 std::vector
<base::TimeTicks
> actual_deadlines
;
780 base::TimeTicks
clock_before(clock_
->NowTicks());
781 base::TimeDelta
idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
783 // The second idle period should happen immediately after the first the
784 // they have max deadlines.
785 max_idle_task_reposts
= 2;
786 idle_task_runner_
->PostIdleTask(
787 FROM_HERE
, base::Bind(&RepostingUpdateClockIdleTestTask
,
788 idle_task_runner_
, &run_count
, clock_
.get(),
789 idle_task_runtime
, &actual_deadlines
));
791 idle_helper_
->EnableLongIdlePeriod();
793 EXPECT_EQ(2, run_count
);
796 testing::ElementsAre(
797 clock_before
+ maximum_idle_period_duration(),
798 clock_before
+ idle_task_runtime
+ maximum_idle_period_duration()));
801 TEST_F(IdleHelperTest
, TestLongIdlePeriodRestartWaitsIfNotMaxDeadline
) {
802 base::TimeTicks actual_deadline
;
805 base::TimeDelta
pending_task_delay(base::TimeDelta::FromMilliseconds(20));
806 base::TimeDelta
idle_task_duration(base::TimeDelta::FromMilliseconds(10));
807 base::TimeTicks
expected_deadline(clock_
->NowTicks() + pending_task_delay
+
808 maximum_idle_period_duration() +
809 retry_enable_long_idle_period_delay());
811 // Post delayed task to ensure idle period doesn't have a max deadline.
812 default_task_runner_
->PostDelayedTask(FROM_HERE
, base::Bind(&NullTask
),
815 max_idle_task_reposts
= 2;
816 idle_task_runner_
->PostIdleTask(
817 FROM_HERE
, base::Bind(&RepostingIdleTestTask
, idle_task_runner_
,
818 &run_count
, &actual_deadline
));
819 idle_helper_
->EnableLongIdlePeriod();
821 EXPECT_EQ(1, run_count
);
822 clock_
->Advance(idle_task_duration
);
824 // Next idle period shouldn't happen until the pending task has been run.
826 EXPECT_EQ(1, run_count
);
828 // Once the pending task is run the new idle period should start.
829 clock_
->Advance(pending_task_delay
- idle_task_duration
);
831 // Since the idle period tried to start before the pending task ran we have to
832 // wait for the idle helper to retry starting the long idle period.
833 clock_
->Advance(retry_enable_long_idle_period_delay());
836 EXPECT_EQ(2, run_count
);
837 EXPECT_EQ(expected_deadline
, actual_deadline
);
840 TEST_F(IdleHelperTest
, TestLongIdlePeriodPaused
) {
841 mock_task_runner_
->SetAutoAdvanceNowToPendingTasks(true);
842 std::vector
<base::TimeTicks
> actual_deadlines
;
845 // If there are no idle tasks posted we should start in the paused state.
846 idle_helper_
->EnableLongIdlePeriod();
847 CheckIdlePeriodStateIs("in_long_idle_period_paused");
848 // There shouldn't be any delayed tasks posted by the idle helper when paused.
849 EXPECT_EQ(base::TimeTicks(),
850 scheduler_helper_
->NextPendingDelayedTaskRunTime());
852 // Posting a task should transition us to the an active state.
853 max_idle_task_reposts
= 2;
854 base::TimeTicks
clock_before(clock_
->NowTicks());
855 base::TimeDelta
idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
856 idle_task_runner_
->PostIdleTask(
857 FROM_HERE
, base::Bind(&RepostingUpdateClockIdleTestTask
,
858 idle_task_runner_
, &run_count
, clock_
.get(),
859 idle_task_runtime
, &actual_deadlines
));
861 EXPECT_EQ(2, run_count
);
864 testing::ElementsAre(
865 clock_before
+ maximum_idle_period_duration(),
866 clock_before
+ idle_task_runtime
+ maximum_idle_period_duration()));
868 // Once all task have been run we should go back to the paused state.
869 CheckIdlePeriodStateIs("in_long_idle_period_paused");
870 EXPECT_EQ(base::TimeTicks(),
871 scheduler_helper_
->NextPendingDelayedTaskRunTime());
873 idle_helper_
->EndIdlePeriod();
874 CheckIdlePeriodStateIs("not_in_idle_period");
877 TEST_F(IdleHelperTest
, TestLongIdlePeriodWhenShutdown
) {
878 base::TimeTicks deadline_in_task
;
881 idle_task_runner_
->PostIdleTask(
882 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
883 scheduler_helper_
->Shutdown();
885 // We shouldn't be able to enter a long idle period when shutdown
886 idle_helper_
->EnableLongIdlePeriod();
888 CheckIdlePeriodStateIs("not_in_idle_period");
889 EXPECT_EQ(0, run_count
);
892 void TestCanExceedIdleDeadlineIfRequiredTask(IdleHelperForTest
* idle_helper
,
893 bool* can_exceed_idle_deadline_out
,
895 base::TimeTicks deadline
) {
896 *can_exceed_idle_deadline_out
=
897 idle_helper
->CanExceedIdleDeadlineIfRequired();
901 TEST_F(IdleHelperTest
, CanExceedIdleDeadlineIfRequired
) {
903 bool can_exceed_idle_deadline
= false;
905 // Should return false if not in an idle period.
906 EXPECT_FALSE(idle_helper_
->CanExceedIdleDeadlineIfRequired());
908 // Should return false for short idle periods.
909 idle_task_runner_
->PostIdleTask(
911 base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask
, idle_helper_
.get(),
912 &can_exceed_idle_deadline
, &run_count
));
913 idle_helper_
->StartIdlePeriod(
914 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
915 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(10));
917 EXPECT_EQ(1, run_count
);
918 EXPECT_FALSE(can_exceed_idle_deadline
);
920 // Should return false for a long idle period which is shortened due to a
921 // pending delayed task.
922 default_task_runner_
->PostDelayedTask(FROM_HERE
, base::Bind(&NullTask
),
923 base::TimeDelta::FromMilliseconds(10));
924 idle_task_runner_
->PostIdleTask(
926 base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask
, idle_helper_
.get(),
927 &can_exceed_idle_deadline
, &run_count
));
928 idle_helper_
->EnableLongIdlePeriod();
930 EXPECT_EQ(2, run_count
);
931 EXPECT_FALSE(can_exceed_idle_deadline
);
933 // Next long idle period will be for the maximum time, so
934 // CanExceedIdleDeadlineIfRequired should return true.
935 clock_
->Advance(maximum_idle_period_duration());
936 idle_task_runner_
->PostIdleTask(
938 base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask
, idle_helper_
.get(),
939 &can_exceed_idle_deadline
, &run_count
));
941 EXPECT_EQ(3, run_count
);
942 EXPECT_TRUE(can_exceed_idle_deadline
);
945 class IdleHelperWithQuiescencePeriodTest
: public BaseIdleHelperTest
{
948 kQuiescenceDelayMs
= 100,
949 kLongIdlePeriodMs
= 50,
952 IdleHelperWithQuiescencePeriodTest()
953 : BaseIdleHelperTest(
955 base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs
)) {}
957 ~IdleHelperWithQuiescencePeriodTest() override
{}
959 void SetUp() override
{
960 EXPECT_CALL(*idle_helper_
, OnIdlePeriodStarted()).Times(AnyNumber());
961 EXPECT_CALL(*idle_helper_
, OnIdlePeriodEnded()).Times(AnyNumber());
962 EXPECT_CALL(*idle_helper_
, CanEnterLongIdlePeriod(_
, _
))
964 .WillRepeatedly(Return(true));
965 EXPECT_CALL(*idle_helper_
, IsNotQuiescent()).Times(AnyNumber());
968 void MakeNonQuiescent() {
969 // Run an arbitrary task so we're deemed to be not quiescent.
970 default_task_runner_
->PostTask(FROM_HERE
, base::Bind(NullTask
));
975 DISALLOW_COPY_AND_ASSIGN(IdleHelperWithQuiescencePeriodTest
);
978 class IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver
:
979 public IdleHelperWithQuiescencePeriodTest
{
982 IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver()
983 : IdleHelperWithQuiescencePeriodTest() {}
985 ~IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver() override
{}
987 void SetUp() override
{
988 // Don't set expectations on IdleHelper::Delegate.
992 DISALLOW_COPY_AND_ASSIGN(
993 IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver
);
997 TEST_F(IdleHelperWithQuiescencePeriodTest
,
998 LongIdlePeriodStartsImmediatelyIfQuiescent
) {
999 base::TimeTicks actual_deadline
;
1001 max_idle_task_reposts
= 1;
1002 idle_task_runner_
->PostIdleTask(
1003 FROM_HERE
, base::Bind(&RepostingIdleTestTask
, idle_task_runner_
,
1004 &run_count
, &actual_deadline
));
1006 idle_helper_
->EnableLongIdlePeriod();
1009 EXPECT_EQ(1, run_count
);
1012 TEST_F(IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver
,
1013 LongIdlePeriodDoesNotStartsImmediatelyIfBusy
) {
1015 EXPECT_CALL(*idle_helper_
, OnIdlePeriodStarted()).Times(0);
1016 EXPECT_CALL(*idle_helper_
, OnIdlePeriodEnded()).Times(0);
1017 EXPECT_CALL(*idle_helper_
, CanEnterLongIdlePeriod(_
, _
)).Times(0);
1018 EXPECT_CALL(*idle_helper_
, IsNotQuiescent()).Times(AtLeast(1));
1020 base::TimeTicks actual_deadline
;
1022 max_idle_task_reposts
= 1;
1023 idle_task_runner_
->PostIdleTask(
1024 FROM_HERE
, base::Bind(&RepostingIdleTestTask
, idle_task_runner_
,
1025 &run_count
, &actual_deadline
));
1027 idle_helper_
->EnableLongIdlePeriod();
1030 EXPECT_EQ(0, run_count
);
1032 scheduler_helper_
->Shutdown();
1035 TEST_F(IdleHelperWithQuiescencePeriodTest
,
1036 LongIdlePeriodStartsAfterQuiescence
) {
1038 mock_task_runner_
->SetAutoAdvanceNowToPendingTasks(true);
1040 // Run a repeating task so we're deemed to be busy for the next 400ms.
1041 default_task_runner_
->PostTask(
1043 base::Bind(&RepeatingTask
, base::Unretained(default_task_runner_
.get()),
1044 10, base::TimeDelta::FromMilliseconds(40)));
1047 // In this scenario EnableLongIdlePeriod deems us not to be quiescent 5x in
1049 base::TimeTicks expected_deadline
=
1050 clock_
->NowTicks() + base::TimeDelta::FromMilliseconds(
1051 5 * kQuiescenceDelayMs
+ kLongIdlePeriodMs
);
1052 base::TimeTicks deadline_in_task
;
1053 idle_task_runner_
->PostIdleTask(
1054 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
1056 idle_helper_
->EnableLongIdlePeriod();
1058 EXPECT_EQ(1, run_count
);
1059 EXPECT_EQ(expected_deadline
, deadline_in_task
);
1062 TEST_F(IdleHelperWithQuiescencePeriodTest
,
1063 QuescienceCheckedForAfterLongIdlePeriodEnds
) {
1064 mock_task_runner_
->SetAutoAdvanceNowToPendingTasks(true);
1066 idle_task_runner_
->PostIdleTask(FROM_HERE
, base::Bind(&NullIdleTask
));
1067 idle_helper_
->EnableLongIdlePeriod();
1070 // Post a normal task to make the scheduler non-quiescent.
1071 default_task_runner_
->PostTask(FROM_HERE
, base::Bind(&NullTask
));
1074 // Post an idle task. The idle task won't run initially because the system is
1075 // not judged to be quiescent, but should be run after the quiescence delay.
1077 base::TimeTicks deadline_in_task
;
1078 base::TimeTicks expected_deadline
=
1079 clock_
->NowTicks() +
1080 base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs
+ kLongIdlePeriodMs
);
1081 idle_task_runner_
->PostIdleTask(
1082 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
1083 idle_helper_
->EnableLongIdlePeriod();
1086 EXPECT_EQ(1, run_count
);
1087 EXPECT_EQ(expected_deadline
, deadline_in_task
);
1090 TEST_F(IdleHelperTest
, NoShortIdlePeriodWhenDeadlineTooClose
) {
1092 base::TimeTicks deadline_in_task
;
1094 idle_task_runner_
->PostIdleTask(
1095 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
1097 base::TimeDelta
half_a_ms(base::TimeDelta::FromMicroseconds(50));
1098 base::TimeTicks
less_than_min_deadline(
1099 clock_
->NowTicks() + minimum_idle_period_duration() - half_a_ms
);
1100 base::TimeTicks
more_than_min_deadline(
1101 clock_
->NowTicks() + minimum_idle_period_duration() + half_a_ms
);
1103 idle_helper_
->StartIdlePeriod(
1104 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
1105 less_than_min_deadline
);
1107 EXPECT_EQ(0, run_count
);
1109 idle_helper_
->StartIdlePeriod(
1110 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD
, clock_
->NowTicks(),
1111 more_than_min_deadline
);
1113 EXPECT_EQ(1, run_count
);
1116 TEST_F(IdleHelperTest
, NoLongIdlePeriodWhenDeadlineTooClose
) {
1118 base::TimeTicks deadline_in_task
;
1120 base::TimeDelta
half_a_ms(base::TimeDelta::FromMicroseconds(50));
1121 base::TimeDelta
less_than_min_deadline_duration(
1122 minimum_idle_period_duration() - half_a_ms
);
1123 base::TimeDelta
more_than_min_deadline_duration(
1124 minimum_idle_period_duration() + half_a_ms
);
1126 idle_task_runner_
->PostIdleTask(
1127 FROM_HERE
, base::Bind(&IdleTestTask
, &run_count
, &deadline_in_task
));
1128 default_task_runner_
->PostDelayedTask(FROM_HERE
, base::Bind(&NullTask
),
1129 less_than_min_deadline_duration
);
1131 idle_helper_
->EnableLongIdlePeriod();
1133 EXPECT_EQ(0, run_count
);
1135 idle_helper_
->EndIdlePeriod();
1136 clock_
->Advance(maximum_idle_period_duration());
1138 EXPECT_EQ(0, run_count
);
1140 default_task_runner_
->PostDelayedTask(FROM_HERE
, base::Bind(&NullTask
),
1141 more_than_min_deadline_duration
);
1142 idle_helper_
->EnableLongIdlePeriod();
1144 EXPECT_EQ(1, run_count
);
1147 } // namespace scheduler