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