OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "components/scheduler/child/idle_helper.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "base/callback.h" | |
10 #include "base/macros.h" | |
11 #include "base/memory/ptr_util.h" | |
12 #include "base/run_loop.h" | |
13 #include "base/test/simple_test_tick_clock.h" | |
14 #include "cc/test/ordered_simple_task_runner.h" | |
15 #include "components/scheduler/base/real_time_domain.h" | |
16 #include "components/scheduler/base/task_queue.h" | |
17 #include "components/scheduler/base/task_queue_manager.h" | |
18 #include "components/scheduler/base/test_time_source.h" | |
19 #include "components/scheduler/child/scheduler_helper.h" | |
20 #include "components/scheduler/child/scheduler_tqm_delegate_for_test.h" | |
21 #include "components/scheduler/child/scheduler_tqm_delegate_impl.h" | |
22 #include "testing/gmock/include/gmock/gmock.h" | |
23 #include "testing/gtest/include/gtest/gtest.h" | |
24 | |
25 using testing::_; | |
26 using testing::AnyNumber; | |
27 using testing::AtLeast; | |
28 using testing::Exactly; | |
29 using testing::Invoke; | |
30 using testing::Return; | |
31 | |
32 namespace scheduler { | |
33 | |
34 namespace { | |
35 void AppendToVectorTestTask(std::vector<std::string>* vector, | |
36 std::string value) { | |
37 vector->push_back(value); | |
38 } | |
39 | |
40 void AppendToVectorIdleTestTask(std::vector<std::string>* vector, | |
41 std::string value, | |
42 base::TimeTicks deadline) { | |
43 AppendToVectorTestTask(vector, value); | |
44 } | |
45 | |
46 void NullTask() { | |
47 } | |
48 | |
49 void NullIdleTask(base::TimeTicks deadline) { | |
50 } | |
51 | |
52 void AppendToVectorReentrantTask(base::SingleThreadTaskRunner* task_runner, | |
53 std::vector<int>* vector, | |
54 int* reentrant_count, | |
55 int max_reentrant_count) { | |
56 vector->push_back((*reentrant_count)++); | |
57 if (*reentrant_count < max_reentrant_count) { | |
58 task_runner->PostTask( | |
59 FROM_HERE, | |
60 base::Bind(AppendToVectorReentrantTask, base::Unretained(task_runner), | |
61 vector, reentrant_count, max_reentrant_count)); | |
62 } | |
63 } | |
64 | |
65 void IdleTestTask(int* run_count, | |
66 base::TimeTicks* deadline_out, | |
67 base::TimeTicks deadline) { | |
68 (*run_count)++; | |
69 *deadline_out = deadline; | |
70 } | |
71 | |
72 int max_idle_task_reposts = 2; | |
73 | |
74 void RepostingIdleTestTask(SingleThreadIdleTaskRunner* idle_task_runner, | |
75 int* run_count, | |
76 base::TimeTicks* deadline_out, | |
77 base::TimeTicks deadline) { | |
78 if ((*run_count + 1) < max_idle_task_reposts) { | |
79 idle_task_runner->PostIdleTask( | |
80 FROM_HERE, | |
81 base::Bind(&RepostingIdleTestTask, base::Unretained(idle_task_runner), | |
82 run_count, deadline_out)); | |
83 } | |
84 *deadline_out = deadline; | |
85 (*run_count)++; | |
86 } | |
87 | |
88 void RepostingUpdateClockIdleTestTask( | |
89 SingleThreadIdleTaskRunner* idle_task_runner, | |
90 int* run_count, | |
91 base::SimpleTestTickClock* clock, | |
92 base::TimeDelta advance_time, | |
93 std::vector<base::TimeTicks>* deadlines, | |
94 base::TimeTicks deadline) { | |
95 if ((*run_count + 1) < max_idle_task_reposts) { | |
96 idle_task_runner->PostIdleTask( | |
97 FROM_HERE, base::Bind(&RepostingUpdateClockIdleTestTask, | |
98 base::Unretained(idle_task_runner), run_count, | |
99 clock, advance_time, deadlines)); | |
100 } | |
101 deadlines->push_back(deadline); | |
102 (*run_count)++; | |
103 clock->Advance(advance_time); | |
104 } | |
105 | |
106 void RepeatingTask(base::SingleThreadTaskRunner* task_runner, | |
107 int num_repeats, | |
108 base::TimeDelta delay) { | |
109 if (num_repeats > 1) { | |
110 task_runner->PostDelayedTask( | |
111 FROM_HERE, base::Bind(&RepeatingTask, base::Unretained(task_runner), | |
112 num_repeats - 1, delay), | |
113 delay); | |
114 } | |
115 } | |
116 | |
117 void UpdateClockIdleTestTask(base::SimpleTestTickClock* clock, | |
118 int* run_count, | |
119 base::TimeTicks set_time, | |
120 base::TimeTicks deadline) { | |
121 clock->Advance(set_time - clock->NowTicks()); | |
122 (*run_count)++; | |
123 } | |
124 | |
125 void UpdateClockToDeadlineIdleTestTask(base::SimpleTestTickClock* clock, | |
126 int* run_count, | |
127 base::TimeTicks deadline) { | |
128 UpdateClockIdleTestTask(clock, run_count, deadline, deadline); | |
129 } | |
130 | |
131 void EndIdlePeriodIdleTask(IdleHelper* idle_helper, base::TimeTicks deadline) { | |
132 idle_helper->EndIdlePeriod(); | |
133 } | |
134 | |
135 scoped_refptr<SchedulerTqmDelegate> CreateTaskRunnerDelegate( | |
136 base::MessageLoop* message_loop, | |
137 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner, | |
138 std::unique_ptr<TestTimeSource> test_time_source) { | |
139 if (message_loop) | |
140 return SchedulerTqmDelegateImpl::Create(message_loop, | |
141 std::move(test_time_source)); | |
142 | |
143 return SchedulerTqmDelegateForTest::Create(mock_task_runner, | |
144 std::move(test_time_source)); | |
145 } | |
146 | |
147 }; // namespace | |
148 | |
149 class IdleHelperForTest : public IdleHelper, public IdleHelper::Delegate { | |
150 public: | |
151 explicit IdleHelperForTest( | |
152 SchedulerHelper* scheduler_helper, | |
153 base::TimeDelta required_quiescence_duration_before_long_idle_period) | |
154 : IdleHelper(scheduler_helper, | |
155 this, | |
156 "test.idle", | |
157 TRACE_DISABLED_BY_DEFAULT("test.idle"), | |
158 "TestSchedulerIdlePeriod", | |
159 required_quiescence_duration_before_long_idle_period) {} | |
160 | |
161 ~IdleHelperForTest() override {} | |
162 | |
163 // SchedulerHelperDelegate implementation: | |
164 MOCK_METHOD2(CanEnterLongIdlePeriod, | |
165 bool(base::TimeTicks now, | |
166 base::TimeDelta* next_long_idle_period_delay_out)); | |
167 | |
168 MOCK_METHOD0(IsNotQuiescent, void()); | |
169 MOCK_METHOD0(OnIdlePeriodStarted, void()); | |
170 MOCK_METHOD0(OnIdlePeriodEnded, void()); | |
171 }; | |
172 | |
173 class BaseIdleHelperTest : public testing::Test { | |
174 public: | |
175 BaseIdleHelperTest( | |
176 base::MessageLoop* message_loop, | |
177 base::TimeDelta required_quiescence_duration_before_long_idle_period) | |
178 : clock_(new base::SimpleTestTickClock()), | |
179 mock_task_runner_( | |
180 message_loop | |
181 ? nullptr | |
182 : new cc::OrderedSimpleTaskRunner(clock_.get(), false)), | |
183 message_loop_(message_loop), | |
184 main_task_runner_(CreateTaskRunnerDelegate( | |
185 message_loop, | |
186 mock_task_runner_, | |
187 base::WrapUnique(new TestTimeSource(clock_.get())))), | |
188 scheduler_helper_( | |
189 new SchedulerHelper(main_task_runner_, | |
190 "test.idle", | |
191 TRACE_DISABLED_BY_DEFAULT("test.idle"), | |
192 TRACE_DISABLED_BY_DEFAULT("test.idle.debug"))), | |
193 idle_helper_(new IdleHelperForTest( | |
194 scheduler_helper_.get(), | |
195 required_quiescence_duration_before_long_idle_period)), | |
196 default_task_runner_(scheduler_helper_->DefaultTaskRunner()), | |
197 idle_task_runner_(idle_helper_->IdleTaskRunner()) { | |
198 clock_->Advance(base::TimeDelta::FromMicroseconds(5000)); | |
199 } | |
200 | |
201 ~BaseIdleHelperTest() override {} | |
202 | |
203 void SetUp() override { | |
204 EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber()); | |
205 EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber()); | |
206 EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)) | |
207 .Times(AnyNumber()) | |
208 .WillRepeatedly(Return(true)); | |
209 } | |
210 | |
211 void TearDown() override { | |
212 DCHECK(!mock_task_runner_.get() || !message_loop_.get()); | |
213 if (mock_task_runner_.get()) { | |
214 // Check that all tests stop posting tasks. | |
215 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
216 while (mock_task_runner_->RunUntilIdle()) { | |
217 } | |
218 } else { | |
219 base::RunLoop().RunUntilIdle(); | |
220 } | |
221 } | |
222 | |
223 void RunUntilIdle() { | |
224 // Only one of mock_task_runner_ or message_loop_ should be set. | |
225 DCHECK(!mock_task_runner_.get() || !message_loop_.get()); | |
226 if (mock_task_runner_.get()) | |
227 mock_task_runner_->RunUntilIdle(); | |
228 else | |
229 base::RunLoop().RunUntilIdle(); | |
230 } | |
231 | |
232 template <typename E> | |
233 static void CallForEachEnumValue(E first, | |
234 E last, | |
235 const char* (*function)(E)) { | |
236 for (E val = first; val < last; | |
237 val = static_cast<E>(static_cast<int>(val) + 1)) { | |
238 (*function)(val); | |
239 } | |
240 } | |
241 | |
242 static void CheckAllTaskQueueIdToString() { | |
243 CallForEachEnumValue<IdleHelper::IdlePeriodState>( | |
244 IdleHelper::IdlePeriodState::FIRST_IDLE_PERIOD_STATE, | |
245 IdleHelper::IdlePeriodState::IDLE_PERIOD_STATE_COUNT, | |
246 &IdleHelper::IdlePeriodStateToString); | |
247 } | |
248 | |
249 bool IsInIdlePeriod() const { | |
250 return idle_helper_->IsInIdlePeriod( | |
251 idle_helper_->SchedulerIdlePeriodState()); | |
252 } | |
253 | |
254 protected: | |
255 static base::TimeDelta maximum_idle_period_duration() { | |
256 return base::TimeDelta::FromMilliseconds( | |
257 IdleHelper::kMaximumIdlePeriodMillis); | |
258 } | |
259 | |
260 static base::TimeDelta retry_enable_long_idle_period_delay() { | |
261 return base::TimeDelta::FromMilliseconds( | |
262 IdleHelper::kRetryEnableLongIdlePeriodDelayMillis); | |
263 } | |
264 | |
265 static base::TimeDelta minimum_idle_period_duration() { | |
266 return base::TimeDelta::FromMilliseconds( | |
267 IdleHelper::kMinimumIdlePeriodDurationMillis); | |
268 } | |
269 | |
270 base::TimeTicks CurrentIdleTaskDeadline() { | |
271 return idle_helper_->CurrentIdleTaskDeadline(); | |
272 } | |
273 | |
274 void CheckIdlePeriodStateIs(const char* expected) { | |
275 EXPECT_STREQ(expected, IdleHelper::IdlePeriodStateToString( | |
276 idle_helper_->SchedulerIdlePeriodState())); | |
277 } | |
278 | |
279 std::unique_ptr<base::SimpleTestTickClock> clock_; | |
280 // Only one of mock_task_runner_ or message_loop_ will be set. | |
281 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_; | |
282 std::unique_ptr<base::MessageLoop> message_loop_; | |
283 | |
284 scoped_refptr<SchedulerTqmDelegate> main_task_runner_; | |
285 std::unique_ptr<SchedulerHelper> scheduler_helper_; | |
286 std::unique_ptr<IdleHelperForTest> idle_helper_; | |
287 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; | |
288 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; | |
289 | |
290 DISALLOW_COPY_AND_ASSIGN(BaseIdleHelperTest); | |
291 }; | |
292 | |
293 class IdleHelperTest : public BaseIdleHelperTest { | |
294 public: | |
295 IdleHelperTest() : BaseIdleHelperTest(nullptr, base::TimeDelta()) {} | |
296 | |
297 ~IdleHelperTest() override {} | |
298 | |
299 TaskQueueManager* task_queue_manager() const { | |
300 return scheduler_helper_->GetTaskQueueManagerForTesting(); | |
301 } | |
302 | |
303 private: | |
304 DISALLOW_COPY_AND_ASSIGN(IdleHelperTest); | |
305 }; | |
306 | |
307 TEST_F(IdleHelperTest, TestPostIdleTask) { | |
308 int run_count = 0; | |
309 base::TimeTicks expected_deadline = | |
310 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(2300); | |
311 base::TimeTicks deadline_in_task; | |
312 | |
313 clock_->Advance(base::TimeDelta::FromMilliseconds(100)); | |
314 idle_task_runner_->PostIdleTask( | |
315 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
316 | |
317 RunUntilIdle(); | |
318 EXPECT_EQ(0, run_count); | |
319 | |
320 idle_helper_->StartIdlePeriod( | |
321 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
322 expected_deadline); | |
323 RunUntilIdle(); | |
324 EXPECT_EQ(1, run_count); | |
325 EXPECT_EQ(expected_deadline, deadline_in_task); | |
326 } | |
327 | |
328 TEST_F(IdleHelperTest, TestPostIdleTask_EndIdlePeriod) { | |
329 int run_count = 0; | |
330 base::TimeTicks deadline_in_task; | |
331 | |
332 clock_->Advance(base::TimeDelta::FromMilliseconds(100)); | |
333 idle_task_runner_->PostIdleTask( | |
334 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
335 | |
336 RunUntilIdle(); | |
337 EXPECT_EQ(0, run_count); | |
338 | |
339 idle_helper_->StartIdlePeriod( | |
340 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
341 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
342 idle_helper_->EndIdlePeriod(); | |
343 RunUntilIdle(); | |
344 EXPECT_EQ(0, run_count); | |
345 } | |
346 | |
347 TEST_F(IdleHelperTest, TestRepostingIdleTask) { | |
348 base::TimeTicks actual_deadline; | |
349 int run_count = 0; | |
350 | |
351 max_idle_task_reposts = 2; | |
352 idle_task_runner_->PostIdleTask( | |
353 FROM_HERE, | |
354 base::Bind(&RepostingIdleTestTask, base::RetainedRef(idle_task_runner_), | |
355 &run_count, &actual_deadline)); | |
356 idle_helper_->StartIdlePeriod( | |
357 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
358 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
359 RunUntilIdle(); | |
360 EXPECT_EQ(1, run_count); | |
361 | |
362 // Reposted tasks shouldn't run until next idle period. | |
363 RunUntilIdle(); | |
364 EXPECT_EQ(1, run_count); | |
365 | |
366 idle_helper_->StartIdlePeriod( | |
367 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
368 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
369 RunUntilIdle(); | |
370 EXPECT_EQ(2, run_count); | |
371 } | |
372 | |
373 TEST_F(IdleHelperTest, TestIdleTaskExceedsDeadline) { | |
374 int run_count = 0; | |
375 | |
376 // Post two UpdateClockToDeadlineIdleTestTask tasks. | |
377 idle_task_runner_->PostIdleTask( | |
378 FROM_HERE, | |
379 base::Bind(&UpdateClockToDeadlineIdleTestTask, clock_.get(), &run_count)); | |
380 idle_task_runner_->PostIdleTask( | |
381 FROM_HERE, | |
382 base::Bind(&UpdateClockToDeadlineIdleTestTask, clock_.get(), &run_count)); | |
383 | |
384 idle_helper_->StartIdlePeriod( | |
385 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
386 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
387 RunUntilIdle(); | |
388 // Only the first idle task should execute since it's used up the deadline. | |
389 EXPECT_EQ(1, run_count); | |
390 | |
391 idle_helper_->EndIdlePeriod(); | |
392 idle_helper_->StartIdlePeriod( | |
393 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
394 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
395 RunUntilIdle(); | |
396 // Second task should be run on the next idle period. | |
397 EXPECT_EQ(2, run_count); | |
398 } | |
399 | |
400 TEST_F(IdleHelperTest, TestPostIdleTaskAfterWakeup) { | |
401 base::TimeTicks deadline_in_task; | |
402 int run_count = 0; | |
403 | |
404 idle_task_runner_->PostIdleTaskAfterWakeup( | |
405 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
406 | |
407 idle_helper_->StartIdlePeriod( | |
408 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
409 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
410 RunUntilIdle(); | |
411 // Shouldn't run yet as no other task woke up the scheduler. | |
412 EXPECT_EQ(0, run_count); | |
413 | |
414 // Must start a new idle period before idle task runs. | |
415 idle_task_runner_->PostIdleTaskAfterWakeup( | |
416 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
417 | |
418 idle_helper_->StartIdlePeriod( | |
419 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
420 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
421 RunUntilIdle(); | |
422 // Another after wakeup idle task shouldn't wake the scheduler. | |
423 EXPECT_EQ(0, run_count); | |
424 | |
425 default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask)); | |
426 | |
427 RunUntilIdle(); | |
428 idle_helper_->StartIdlePeriod( | |
429 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
430 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
431 RunUntilIdle(); | |
432 // Execution of default task queue task should trigger execution of idle task. | |
433 EXPECT_EQ(2, run_count); | |
434 } | |
435 | |
436 TEST_F(IdleHelperTest, TestPostIdleTaskAfterWakeupWhileAwake) { | |
437 base::TimeTicks deadline_in_task; | |
438 int run_count = 0; | |
439 | |
440 idle_task_runner_->PostIdleTaskAfterWakeup( | |
441 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
442 default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask)); | |
443 | |
444 RunUntilIdle(); | |
445 // Must start a new idle period before idle task runs. | |
446 idle_helper_->StartIdlePeriod( | |
447 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
448 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
449 RunUntilIdle(); | |
450 // Should run as the scheduler was already awakened by the normal task. | |
451 EXPECT_EQ(1, run_count); | |
452 } | |
453 | |
454 TEST_F(IdleHelperTest, TestPostIdleTaskWakesAfterWakeupIdleTask) { | |
455 base::TimeTicks deadline_in_task; | |
456 int run_count = 0; | |
457 | |
458 idle_task_runner_->PostIdleTaskAfterWakeup( | |
459 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
460 idle_task_runner_->PostIdleTask( | |
461 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
462 | |
463 idle_helper_->StartIdlePeriod( | |
464 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
465 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
466 RunUntilIdle(); | |
467 // Must start a new idle period before after-wakeup idle task runs. | |
468 idle_helper_->StartIdlePeriod( | |
469 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
470 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
471 RunUntilIdle(); | |
472 // Normal idle task should wake up after-wakeup idle task. | |
473 EXPECT_EQ(2, run_count); | |
474 } | |
475 | |
476 class IdleHelperTestWithIdlePeriodObserver : public BaseIdleHelperTest { | |
477 public: | |
478 IdleHelperTestWithIdlePeriodObserver() | |
479 : BaseIdleHelperTest(nullptr, base::TimeDelta()) {} | |
480 | |
481 ~IdleHelperTestWithIdlePeriodObserver() override {} | |
482 | |
483 void SetUp() override { | |
484 // Don't set expectations on IdleHelper::Delegate. | |
485 } | |
486 | |
487 TaskQueueManager* task_queue_manager() const { | |
488 return scheduler_helper_->GetTaskQueueManagerForTesting(); | |
489 } | |
490 | |
491 void ExpectIdlePeriodStartsButNeverEnds() { | |
492 EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(1); | |
493 EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(0); | |
494 } | |
495 | |
496 void ExpectIdlePeriodStartsAndEnds(const testing::Cardinality& cardinality) { | |
497 EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(cardinality); | |
498 EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(cardinality); | |
499 } | |
500 | |
501 private: | |
502 DISALLOW_COPY_AND_ASSIGN(IdleHelperTestWithIdlePeriodObserver); | |
503 }; | |
504 | |
505 TEST_F(IdleHelperTestWithIdlePeriodObserver, TestEnterButNotExitIdlePeriod) { | |
506 ExpectIdlePeriodStartsButNeverEnds(); | |
507 | |
508 idle_helper_->StartIdlePeriod( | |
509 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
510 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
511 } | |
512 | |
513 TEST_F(IdleHelperTestWithIdlePeriodObserver, TestEnterAndExitIdlePeriod) { | |
514 BaseIdleHelperTest* fixture = this; | |
515 ON_CALL(*idle_helper_, OnIdlePeriodStarted()) | |
516 .WillByDefault( | |
517 Invoke([fixture]() { EXPECT_TRUE(fixture->IsInIdlePeriod()); })); | |
518 ON_CALL(*idle_helper_, OnIdlePeriodEnded()) | |
519 .WillByDefault( | |
520 Invoke([fixture]() { EXPECT_FALSE(fixture->IsInIdlePeriod()); })); | |
521 | |
522 ExpectIdlePeriodStartsAndEnds(Exactly(1)); | |
523 | |
524 idle_helper_->StartIdlePeriod( | |
525 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
526 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
527 idle_helper_->EndIdlePeriod(); | |
528 } | |
529 | |
530 class IdleHelperWithMessageLoopTest : public BaseIdleHelperTest { | |
531 public: | |
532 IdleHelperWithMessageLoopTest() | |
533 : BaseIdleHelperTest(new base::MessageLoop(), base::TimeDelta()) {} | |
534 ~IdleHelperWithMessageLoopTest() override {} | |
535 | |
536 void PostFromNestedRunloop(std::vector< | |
537 std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>* tasks) { | |
538 base::MessageLoop::ScopedNestableTaskAllower allow(message_loop_.get()); | |
539 for (std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>& pair : *tasks) { | |
540 if (pair.second) { | |
541 idle_task_runner_->PostIdleTask(FROM_HERE, pair.first); | |
542 } else { | |
543 idle_task_runner_->PostNonNestableIdleTask(FROM_HERE, pair.first); | |
544 } | |
545 } | |
546 idle_helper_->StartIdlePeriod( | |
547 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
548 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
549 base::RunLoop().RunUntilIdle(); | |
550 } | |
551 | |
552 void SetUp() override { | |
553 EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber()); | |
554 EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber()); | |
555 } | |
556 | |
557 private: | |
558 DISALLOW_COPY_AND_ASSIGN(IdleHelperWithMessageLoopTest); | |
559 }; | |
560 | |
561 TEST_F(IdleHelperWithMessageLoopTest, | |
562 NonNestableIdleTaskDoesntExecuteInNestedLoop) { | |
563 std::vector<std::string> order; | |
564 idle_task_runner_->PostIdleTask( | |
565 FROM_HERE, | |
566 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("1"))); | |
567 idle_task_runner_->PostIdleTask( | |
568 FROM_HERE, | |
569 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("2"))); | |
570 | |
571 std::vector<std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>> | |
572 tasks_to_post_from_nested_loop; | |
573 tasks_to_post_from_nested_loop.push_back(std::make_pair( | |
574 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("3")), | |
575 false)); | |
576 tasks_to_post_from_nested_loop.push_back(std::make_pair( | |
577 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("4")), true)); | |
578 tasks_to_post_from_nested_loop.push_back(std::make_pair( | |
579 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("5")), true)); | |
580 | |
581 default_task_runner_->PostTask( | |
582 FROM_HERE, | |
583 base::Bind(&IdleHelperWithMessageLoopTest::PostFromNestedRunloop, | |
584 base::Unretained(this), | |
585 base::Unretained(&tasks_to_post_from_nested_loop))); | |
586 | |
587 idle_helper_->StartIdlePeriod( | |
588 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
589 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
590 RunUntilIdle(); | |
591 // Note we expect task 3 to run last because it's non-nestable. | |
592 EXPECT_THAT(order, testing::ElementsAre(std::string("1"), std::string("2"), | |
593 std::string("4"), std::string("5"), | |
594 std::string("3"))); | |
595 } | |
596 | |
597 TEST_F(IdleHelperTestWithIdlePeriodObserver, TestLongIdlePeriod) { | |
598 base::TimeTicks expected_deadline = | |
599 clock_->NowTicks() + maximum_idle_period_duration(); | |
600 base::TimeTicks deadline_in_task; | |
601 int run_count = 0; | |
602 | |
603 idle_task_runner_->PostIdleTask( | |
604 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
605 | |
606 EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)) | |
607 .Times(1) | |
608 .WillRepeatedly(Return(true)); | |
609 ExpectIdlePeriodStartsButNeverEnds(); | |
610 | |
611 RunUntilIdle(); | |
612 EXPECT_EQ(0, run_count); // Shouldn't run yet as no idle period. | |
613 | |
614 idle_helper_->EnableLongIdlePeriod(); | |
615 RunUntilIdle(); | |
616 EXPECT_EQ(1, run_count); // Should have run in a long idle time. | |
617 EXPECT_EQ(expected_deadline, deadline_in_task); | |
618 } | |
619 | |
620 TEST_F(IdleHelperTest, TestLongIdlePeriodWithPendingDelayedTask) { | |
621 base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(30); | |
622 base::TimeTicks expected_deadline = clock_->NowTicks() + pending_task_delay; | |
623 base::TimeTicks deadline_in_task; | |
624 int run_count = 0; | |
625 | |
626 idle_task_runner_->PostIdleTask( | |
627 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
628 default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask), | |
629 pending_task_delay); | |
630 | |
631 idle_helper_->EnableLongIdlePeriod(); | |
632 RunUntilIdle(); | |
633 EXPECT_EQ(1, run_count); // Should have run in a long idle time. | |
634 EXPECT_EQ(expected_deadline, deadline_in_task); | |
635 } | |
636 | |
637 TEST_F(IdleHelperTest, TestLongIdlePeriodWithLatePendingDelayedTask) { | |
638 base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(10); | |
639 base::TimeTicks deadline_in_task; | |
640 int run_count = 0; | |
641 | |
642 default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask), | |
643 pending_task_delay); | |
644 | |
645 // Advance clock until after delayed task was meant to be run. | |
646 clock_->Advance(base::TimeDelta::FromMilliseconds(20)); | |
647 | |
648 // Post an idle task and then EnableLongIdlePeriod. Since there is a late | |
649 // pending delayed task this shouldn't actually start an idle period. | |
650 idle_task_runner_->PostIdleTask( | |
651 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
652 idle_helper_->EnableLongIdlePeriod(); | |
653 RunUntilIdle(); | |
654 EXPECT_EQ(0, run_count); | |
655 | |
656 // After the delayed task has been run we should trigger an idle period. | |
657 clock_->Advance(maximum_idle_period_duration()); | |
658 RunUntilIdle(); | |
659 EXPECT_EQ(1, run_count); | |
660 } | |
661 | |
662 TEST_F(IdleHelperTestWithIdlePeriodObserver, TestLongIdlePeriodRepeating) { | |
663 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
664 std::vector<base::TimeTicks> actual_deadlines; | |
665 int run_count = 0; | |
666 | |
667 EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)) | |
668 .Times(4) | |
669 .WillRepeatedly(Return(true)); | |
670 ExpectIdlePeriodStartsAndEnds(AtLeast(2)); | |
671 | |
672 max_idle_task_reposts = 3; | |
673 base::TimeTicks clock_before(clock_->NowTicks()); | |
674 base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10)); | |
675 idle_task_runner_->PostIdleTask( | |
676 FROM_HERE, | |
677 base::Bind(&RepostingUpdateClockIdleTestTask, | |
678 base::RetainedRef(idle_task_runner_), &run_count, clock_.get(), | |
679 idle_task_runtime, &actual_deadlines)); | |
680 | |
681 // Check each idle task runs in their own idle period. | |
682 idle_helper_->EnableLongIdlePeriod(); | |
683 RunUntilIdle(); | |
684 EXPECT_EQ(3, run_count); | |
685 EXPECT_THAT( | |
686 actual_deadlines, | |
687 testing::ElementsAre( | |
688 clock_before + maximum_idle_period_duration(), | |
689 clock_before + idle_task_runtime + maximum_idle_period_duration(), | |
690 clock_before + (2 * idle_task_runtime) + | |
691 maximum_idle_period_duration())); | |
692 | |
693 max_idle_task_reposts = 5; | |
694 idle_task_runner_->PostIdleTask( | |
695 FROM_HERE, | |
696 base::Bind(&RepostingUpdateClockIdleTestTask, | |
697 base::RetainedRef(idle_task_runner_), &run_count, clock_.get(), | |
698 idle_task_runtime, &actual_deadlines)); | |
699 idle_task_runner_->PostIdleTask( | |
700 FROM_HERE, | |
701 base::Bind(&EndIdlePeriodIdleTask, base::Unretained(idle_helper_.get()))); | |
702 | |
703 // Ensure that reposting tasks stop after EndIdlePeriod is called. | |
704 RunUntilIdle(); | |
705 EXPECT_EQ(4, run_count); | |
706 } | |
707 | |
708 TEST_F(IdleHelperTest, TestLongIdlePeriodDoesNotWakeScheduler) { | |
709 base::TimeTicks deadline_in_task; | |
710 int run_count = 0; | |
711 | |
712 // Start a long idle period and get the time it should end. | |
713 idle_helper_->EnableLongIdlePeriod(); | |
714 // The scheduler should not run the enable_next_long_idle_period task if | |
715 // there are no idle tasks and no other task woke up the scheduler, thus | |
716 // the idle period deadline shouldn't update at the end of the current long | |
717 // idle period. | |
718 base::TimeTicks idle_period_deadline = CurrentIdleTaskDeadline(); | |
719 clock_->Advance(maximum_idle_period_duration()); | |
720 RunUntilIdle(); | |
721 | |
722 base::TimeTicks new_idle_period_deadline = CurrentIdleTaskDeadline(); | |
723 EXPECT_EQ(idle_period_deadline, new_idle_period_deadline); | |
724 | |
725 // Posting a after-wakeup idle task also shouldn't wake the scheduler or | |
726 // initiate the next long idle period. | |
727 idle_task_runner_->PostIdleTaskAfterWakeup( | |
728 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
729 RunUntilIdle(); | |
730 new_idle_period_deadline = CurrentIdleTaskDeadline(); | |
731 EXPECT_EQ(idle_period_deadline, new_idle_period_deadline); | |
732 EXPECT_EQ(0, run_count); | |
733 | |
734 // Running a normal task should initiate a new long idle period though. | |
735 default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask)); | |
736 RunUntilIdle(); | |
737 new_idle_period_deadline = CurrentIdleTaskDeadline(); | |
738 EXPECT_EQ(idle_period_deadline + maximum_idle_period_duration(), | |
739 new_idle_period_deadline); | |
740 | |
741 EXPECT_EQ(1, run_count); | |
742 } | |
743 | |
744 TEST_F(IdleHelperTestWithIdlePeriodObserver, | |
745 TestLongIdlePeriodWhenNotCanEnterLongIdlePeriod) { | |
746 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(1000); | |
747 base::TimeDelta halfDelay = base::TimeDelta::FromMilliseconds(500); | |
748 base::TimeTicks delayOver = clock_->NowTicks() + delay; | |
749 base::TimeTicks deadline_in_task; | |
750 int run_count = 0; | |
751 | |
752 ON_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)) | |
753 .WillByDefault(Invoke( | |
754 [delay, delayOver](base::TimeTicks now, | |
755 base::TimeDelta* next_long_idle_period_delay_out) { | |
756 if (now >= delayOver) | |
757 return true; | |
758 *next_long_idle_period_delay_out = delay; | |
759 return false; | |
760 })); | |
761 | |
762 EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)).Times(2); | |
763 EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber()); | |
764 | |
765 idle_task_runner_->PostIdleTask( | |
766 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
767 | |
768 // Make sure Idle tasks don't run until the delay has occurred. | |
769 idle_helper_->EnableLongIdlePeriod(); | |
770 RunUntilIdle(); | |
771 EXPECT_EQ(0, run_count); | |
772 | |
773 clock_->Advance(halfDelay); | |
774 RunUntilIdle(); | |
775 EXPECT_EQ(0, run_count); | |
776 | |
777 // Delay is finished, idle task should run. | |
778 clock_->Advance(halfDelay); | |
779 RunUntilIdle(); | |
780 EXPECT_EQ(1, run_count); | |
781 } | |
782 | |
783 TEST_F(IdleHelperTest, TestLongIdlePeriodImmediatelyRestartsIfMaxDeadline) { | |
784 std::vector<base::TimeTicks> actual_deadlines; | |
785 int run_count = 0; | |
786 | |
787 base::TimeTicks clock_before(clock_->NowTicks()); | |
788 base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10)); | |
789 | |
790 // The second idle period should happen immediately after the first the | |
791 // they have max deadlines. | |
792 max_idle_task_reposts = 2; | |
793 idle_task_runner_->PostIdleTask( | |
794 FROM_HERE, | |
795 base::Bind(&RepostingUpdateClockIdleTestTask, | |
796 base::RetainedRef(idle_task_runner_), &run_count, clock_.get(), | |
797 idle_task_runtime, &actual_deadlines)); | |
798 | |
799 idle_helper_->EnableLongIdlePeriod(); | |
800 RunUntilIdle(); | |
801 EXPECT_EQ(2, run_count); | |
802 EXPECT_THAT( | |
803 actual_deadlines, | |
804 testing::ElementsAre( | |
805 clock_before + maximum_idle_period_duration(), | |
806 clock_before + idle_task_runtime + maximum_idle_period_duration())); | |
807 } | |
808 | |
809 TEST_F(IdleHelperTest, TestLongIdlePeriodRestartWaitsIfNotMaxDeadline) { | |
810 base::TimeTicks actual_deadline; | |
811 int run_count = 0; | |
812 | |
813 base::TimeDelta pending_task_delay(base::TimeDelta::FromMilliseconds(20)); | |
814 base::TimeDelta idle_task_duration(base::TimeDelta::FromMilliseconds(10)); | |
815 base::TimeTicks expected_deadline(clock_->NowTicks() + pending_task_delay + | |
816 maximum_idle_period_duration() + | |
817 retry_enable_long_idle_period_delay()); | |
818 | |
819 // Post delayed task to ensure idle period doesn't have a max deadline. | |
820 default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask), | |
821 pending_task_delay); | |
822 | |
823 max_idle_task_reposts = 2; | |
824 idle_task_runner_->PostIdleTask( | |
825 FROM_HERE, | |
826 base::Bind(&RepostingIdleTestTask, base::RetainedRef(idle_task_runner_), | |
827 &run_count, &actual_deadline)); | |
828 idle_helper_->EnableLongIdlePeriod(); | |
829 RunUntilIdle(); | |
830 EXPECT_EQ(1, run_count); | |
831 clock_->Advance(idle_task_duration); | |
832 | |
833 // Next idle period shouldn't happen until the pending task has been run. | |
834 RunUntilIdle(); | |
835 EXPECT_EQ(1, run_count); | |
836 | |
837 // Once the pending task is run the new idle period should start. | |
838 clock_->Advance(pending_task_delay - idle_task_duration); | |
839 | |
840 // Since the idle period tried to start before the pending task ran we have to | |
841 // wait for the idle helper to retry starting the long idle period. | |
842 clock_->Advance(retry_enable_long_idle_period_delay()); | |
843 RunUntilIdle(); | |
844 | |
845 EXPECT_EQ(2, run_count); | |
846 EXPECT_EQ(expected_deadline, actual_deadline); | |
847 } | |
848 | |
849 TEST_F(IdleHelperTest, TestLongIdlePeriodPaused) { | |
850 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
851 std::vector<base::TimeTicks> actual_deadlines; | |
852 int run_count = 0; | |
853 | |
854 // If there are no idle tasks posted we should start in the paused state. | |
855 idle_helper_->EnableLongIdlePeriod(); | |
856 CheckIdlePeriodStateIs("in_long_idle_period_paused"); | |
857 // There shouldn't be any delayed tasks posted by the idle helper when paused. | |
858 base::TimeTicks next_pending_delayed_task; | |
859 EXPECT_FALSE(scheduler_helper_->real_time_domain()->NextScheduledRunTime( | |
860 &next_pending_delayed_task)); | |
861 | |
862 // Posting a task should transition us to the an active state. | |
863 max_idle_task_reposts = 2; | |
864 base::TimeTicks clock_before(clock_->NowTicks()); | |
865 base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10)); | |
866 idle_task_runner_->PostIdleTask( | |
867 FROM_HERE, | |
868 base::Bind(&RepostingUpdateClockIdleTestTask, | |
869 base::RetainedRef(idle_task_runner_), &run_count, clock_.get(), | |
870 idle_task_runtime, &actual_deadlines)); | |
871 RunUntilIdle(); | |
872 EXPECT_EQ(2, run_count); | |
873 EXPECT_THAT( | |
874 actual_deadlines, | |
875 testing::ElementsAre( | |
876 clock_before + maximum_idle_period_duration(), | |
877 clock_before + idle_task_runtime + maximum_idle_period_duration())); | |
878 | |
879 // Once all task have been run we should go back to the paused state. | |
880 CheckIdlePeriodStateIs("in_long_idle_period_paused"); | |
881 EXPECT_FALSE(scheduler_helper_->real_time_domain()->NextScheduledRunTime( | |
882 &next_pending_delayed_task)); | |
883 | |
884 idle_helper_->EndIdlePeriod(); | |
885 CheckIdlePeriodStateIs("not_in_idle_period"); | |
886 } | |
887 | |
888 TEST_F(IdleHelperTest, TestLongIdlePeriodWhenShutdown) { | |
889 base::TimeTicks deadline_in_task; | |
890 int run_count = 0; | |
891 | |
892 idle_task_runner_->PostIdleTask( | |
893 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
894 scheduler_helper_->Shutdown(); | |
895 | |
896 // We shouldn't be able to enter a long idle period when shutdown | |
897 idle_helper_->EnableLongIdlePeriod(); | |
898 RunUntilIdle(); | |
899 CheckIdlePeriodStateIs("not_in_idle_period"); | |
900 EXPECT_EQ(0, run_count); | |
901 } | |
902 | |
903 void TestCanExceedIdleDeadlineIfRequiredTask(IdleHelperForTest* idle_helper, | |
904 bool* can_exceed_idle_deadline_out, | |
905 int* run_count, | |
906 base::TimeTicks deadline) { | |
907 *can_exceed_idle_deadline_out = | |
908 idle_helper->CanExceedIdleDeadlineIfRequired(); | |
909 (*run_count)++; | |
910 } | |
911 | |
912 TEST_F(IdleHelperTest, CanExceedIdleDeadlineIfRequired) { | |
913 int run_count = 0; | |
914 bool can_exceed_idle_deadline = false; | |
915 | |
916 // Should return false if not in an idle period. | |
917 EXPECT_FALSE(idle_helper_->CanExceedIdleDeadlineIfRequired()); | |
918 | |
919 // Should return false for short idle periods. | |
920 idle_task_runner_->PostIdleTask( | |
921 FROM_HERE, | |
922 base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask, idle_helper_.get(), | |
923 &can_exceed_idle_deadline, &run_count)); | |
924 idle_helper_->StartIdlePeriod( | |
925 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
926 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(10)); | |
927 RunUntilIdle(); | |
928 EXPECT_EQ(1, run_count); | |
929 EXPECT_FALSE(can_exceed_idle_deadline); | |
930 | |
931 // Should return false for a long idle period which is shortened due to a | |
932 // pending delayed task. | |
933 default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask), | |
934 base::TimeDelta::FromMilliseconds(10)); | |
935 idle_task_runner_->PostIdleTask( | |
936 FROM_HERE, | |
937 base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask, idle_helper_.get(), | |
938 &can_exceed_idle_deadline, &run_count)); | |
939 idle_helper_->EnableLongIdlePeriod(); | |
940 RunUntilIdle(); | |
941 EXPECT_EQ(2, run_count); | |
942 EXPECT_FALSE(can_exceed_idle_deadline); | |
943 | |
944 // Next long idle period will be for the maximum time, so | |
945 // CanExceedIdleDeadlineIfRequired should return true. | |
946 clock_->Advance(maximum_idle_period_duration()); | |
947 idle_task_runner_->PostIdleTask( | |
948 FROM_HERE, | |
949 base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask, idle_helper_.get(), | |
950 &can_exceed_idle_deadline, &run_count)); | |
951 RunUntilIdle(); | |
952 EXPECT_EQ(3, run_count); | |
953 EXPECT_TRUE(can_exceed_idle_deadline); | |
954 } | |
955 | |
956 class IdleHelperWithQuiescencePeriodTest : public BaseIdleHelperTest { | |
957 public: | |
958 enum { | |
959 kQuiescenceDelayMs = 100, | |
960 kLongIdlePeriodMs = 50, | |
961 }; | |
962 | |
963 IdleHelperWithQuiescencePeriodTest() | |
964 : BaseIdleHelperTest( | |
965 nullptr, | |
966 base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs)) {} | |
967 | |
968 ~IdleHelperWithQuiescencePeriodTest() override {} | |
969 | |
970 void SetUp() override { | |
971 EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber()); | |
972 EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber()); | |
973 EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)) | |
974 .Times(AnyNumber()) | |
975 .WillRepeatedly(Return(true)); | |
976 EXPECT_CALL(*idle_helper_, IsNotQuiescent()).Times(AnyNumber()); | |
977 } | |
978 | |
979 void MakeNonQuiescent() { | |
980 // Run an arbitrary task so we're deemed to be not quiescent. | |
981 default_task_runner_->PostTask(FROM_HERE, base::Bind(NullTask)); | |
982 RunUntilIdle(); | |
983 } | |
984 | |
985 private: | |
986 DISALLOW_COPY_AND_ASSIGN(IdleHelperWithQuiescencePeriodTest); | |
987 }; | |
988 | |
989 class IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver : | |
990 public IdleHelperWithQuiescencePeriodTest { | |
991 public: | |
992 | |
993 IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver() | |
994 : IdleHelperWithQuiescencePeriodTest() {} | |
995 | |
996 ~IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver() override {} | |
997 | |
998 void SetUp() override { | |
999 // Don't set expectations on IdleHelper::Delegate. | |
1000 } | |
1001 | |
1002 private: | |
1003 DISALLOW_COPY_AND_ASSIGN( | |
1004 IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver); | |
1005 }; | |
1006 | |
1007 | |
1008 TEST_F(IdleHelperWithQuiescencePeriodTest, | |
1009 LongIdlePeriodStartsImmediatelyIfQuiescent) { | |
1010 base::TimeTicks actual_deadline; | |
1011 int run_count = 0; | |
1012 max_idle_task_reposts = 1; | |
1013 idle_task_runner_->PostIdleTask( | |
1014 FROM_HERE, | |
1015 base::Bind(&RepostingIdleTestTask, base::RetainedRef(idle_task_runner_), | |
1016 &run_count, &actual_deadline)); | |
1017 | |
1018 idle_helper_->EnableLongIdlePeriod(); | |
1019 RunUntilIdle(); | |
1020 | |
1021 EXPECT_EQ(1, run_count); | |
1022 } | |
1023 | |
1024 TEST_F(IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver, | |
1025 LongIdlePeriodDoesNotStartsImmediatelyIfBusy) { | |
1026 MakeNonQuiescent(); | |
1027 EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(0); | |
1028 EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(0); | |
1029 EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)).Times(0); | |
1030 EXPECT_CALL(*idle_helper_, IsNotQuiescent()).Times(AtLeast(1)); | |
1031 | |
1032 base::TimeTicks actual_deadline; | |
1033 int run_count = 0; | |
1034 max_idle_task_reposts = 1; | |
1035 idle_task_runner_->PostIdleTask( | |
1036 FROM_HERE, | |
1037 base::Bind(&RepostingIdleTestTask, base::RetainedRef(idle_task_runner_), | |
1038 &run_count, &actual_deadline)); | |
1039 | |
1040 idle_helper_->EnableLongIdlePeriod(); | |
1041 RunUntilIdle(); | |
1042 | |
1043 EXPECT_EQ(0, run_count); | |
1044 | |
1045 scheduler_helper_->Shutdown(); | |
1046 } | |
1047 | |
1048 TEST_F(IdleHelperWithQuiescencePeriodTest, | |
1049 LongIdlePeriodStartsAfterQuiescence) { | |
1050 MakeNonQuiescent(); | |
1051 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
1052 | |
1053 // Run a repeating task so we're deemed to be busy for the next 400ms. | |
1054 default_task_runner_->PostTask( | |
1055 FROM_HERE, | |
1056 base::Bind(&RepeatingTask, base::Unretained(default_task_runner_.get()), | |
1057 10, base::TimeDelta::FromMilliseconds(40))); | |
1058 | |
1059 int run_count = 0; | |
1060 // In this scenario EnableLongIdlePeriod deems us not to be quiescent 5x in | |
1061 // a row. | |
1062 base::TimeTicks expected_deadline = | |
1063 clock_->NowTicks() + base::TimeDelta::FromMilliseconds( | |
1064 5 * kQuiescenceDelayMs + kLongIdlePeriodMs); | |
1065 base::TimeTicks deadline_in_task; | |
1066 idle_task_runner_->PostIdleTask( | |
1067 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
1068 | |
1069 idle_helper_->EnableLongIdlePeriod(); | |
1070 RunUntilIdle(); | |
1071 EXPECT_EQ(1, run_count); | |
1072 EXPECT_EQ(expected_deadline, deadline_in_task); | |
1073 } | |
1074 | |
1075 TEST_F(IdleHelperWithQuiescencePeriodTest, | |
1076 QuescienceCheckedForAfterLongIdlePeriodEnds) { | |
1077 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
1078 | |
1079 idle_task_runner_->PostIdleTask(FROM_HERE, base::Bind(&NullIdleTask)); | |
1080 idle_helper_->EnableLongIdlePeriod(); | |
1081 RunUntilIdle(); | |
1082 | |
1083 // Post a normal task to make the scheduler non-quiescent. | |
1084 default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask)); | |
1085 RunUntilIdle(); | |
1086 | |
1087 // Post an idle task. The idle task won't run initially because the system is | |
1088 // not judged to be quiescent, but should be run after the quiescence delay. | |
1089 int run_count = 0; | |
1090 base::TimeTicks deadline_in_task; | |
1091 base::TimeTicks expected_deadline = | |
1092 clock_->NowTicks() + | |
1093 base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs + kLongIdlePeriodMs); | |
1094 idle_task_runner_->PostIdleTask( | |
1095 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
1096 idle_helper_->EnableLongIdlePeriod(); | |
1097 RunUntilIdle(); | |
1098 | |
1099 EXPECT_EQ(1, run_count); | |
1100 EXPECT_EQ(expected_deadline, deadline_in_task); | |
1101 } | |
1102 | |
1103 TEST_F(IdleHelperTest, NoShortIdlePeriodWhenDeadlineTooClose) { | |
1104 int run_count = 0; | |
1105 base::TimeTicks deadline_in_task; | |
1106 | |
1107 idle_task_runner_->PostIdleTask( | |
1108 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
1109 | |
1110 base::TimeDelta half_a_ms(base::TimeDelta::FromMicroseconds(50)); | |
1111 base::TimeTicks less_than_min_deadline( | |
1112 clock_->NowTicks() + minimum_idle_period_duration() - half_a_ms); | |
1113 base::TimeTicks more_than_min_deadline( | |
1114 clock_->NowTicks() + minimum_idle_period_duration() + half_a_ms); | |
1115 | |
1116 idle_helper_->StartIdlePeriod( | |
1117 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
1118 less_than_min_deadline); | |
1119 RunUntilIdle(); | |
1120 EXPECT_EQ(0, run_count); | |
1121 | |
1122 idle_helper_->StartIdlePeriod( | |
1123 IdleHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD, clock_->NowTicks(), | |
1124 more_than_min_deadline); | |
1125 RunUntilIdle(); | |
1126 EXPECT_EQ(1, run_count); | |
1127 } | |
1128 | |
1129 TEST_F(IdleHelperTest, NoLongIdlePeriodWhenDeadlineTooClose) { | |
1130 int run_count = 0; | |
1131 base::TimeTicks deadline_in_task; | |
1132 | |
1133 base::TimeDelta half_a_ms(base::TimeDelta::FromMicroseconds(50)); | |
1134 base::TimeDelta less_than_min_deadline_duration( | |
1135 minimum_idle_period_duration() - half_a_ms); | |
1136 base::TimeDelta more_than_min_deadline_duration( | |
1137 minimum_idle_period_duration() + half_a_ms); | |
1138 | |
1139 idle_task_runner_->PostIdleTask( | |
1140 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task)); | |
1141 default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask), | |
1142 less_than_min_deadline_duration); | |
1143 | |
1144 idle_helper_->EnableLongIdlePeriod(); | |
1145 RunUntilIdle(); | |
1146 EXPECT_EQ(0, run_count); | |
1147 | |
1148 idle_helper_->EndIdlePeriod(); | |
1149 clock_->Advance(maximum_idle_period_duration()); | |
1150 RunUntilIdle(); | |
1151 EXPECT_EQ(0, run_count); | |
1152 | |
1153 default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask), | |
1154 more_than_min_deadline_duration); | |
1155 idle_helper_->EnableLongIdlePeriod(); | |
1156 RunUntilIdle(); | |
1157 EXPECT_EQ(1, run_count); | |
1158 } | |
1159 | |
1160 } // namespace scheduler | |
OLD | NEW |