| 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 |