Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: content/child/scheduler/scheduler_helper_unittest.cc

Issue 1058873010: Move blink scheduler implementation into a component (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: updates Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 "content/child/scheduler/scheduler_helper.h"
6
7 #include "base/callback.h"
8 #include "cc/test/ordered_simple_task_runner.h"
9 #include "cc/test/test_now_source.h"
10 #include "content/child/scheduler/nestable_task_runner_for_test.h"
11 #include "content/child/scheduler/scheduler_message_loop_delegate.h"
12 #include "content/child/scheduler/task_queue_manager.h"
13 #include "content/test/test_time_source.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 using testing::_;
18 using testing::AnyNumber;
19 using testing::Invoke;
20 using testing::Return;
21
22 namespace content {
23
24 namespace {
25 void AppendToVectorTestTask(std::vector<std::string>* vector,
26 std::string value) {
27 vector->push_back(value);
28 }
29
30 void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
31 std::string value,
32 base::TimeTicks deadline) {
33 AppendToVectorTestTask(vector, value);
34 }
35
36 void NullTask() {
37 }
38
39 void AppendToVectorReentrantTask(
40 base::SingleThreadTaskRunner* task_runner,
41 std::vector<int>* vector,
42 int* reentrant_count,
43 int max_reentrant_count) {
44 vector->push_back((*reentrant_count)++);
45 if (*reentrant_count < max_reentrant_count) {
46 task_runner->PostTask(
47 FROM_HERE, base::Bind(AppendToVectorReentrantTask,
48 base::Unretained(task_runner), vector,
49 reentrant_count, max_reentrant_count));
50 }
51 }
52
53 void NullIdleTask(base::TimeTicks) {
54 }
55
56 void IdleTestTask(int* run_count,
57 base::TimeTicks* deadline_out,
58 base::TimeTicks deadline) {
59 (*run_count)++;
60 *deadline_out = deadline;
61 }
62
63 int max_idle_task_reposts = 2;
64
65 void RepostingIdleTestTask(
66 SingleThreadIdleTaskRunner* idle_task_runner,
67 int* run_count,
68 base::TimeTicks deadline) {
69 if ((*run_count + 1) < max_idle_task_reposts) {
70 idle_task_runner->PostIdleTask(
71 FROM_HERE,
72 base::Bind(&RepostingIdleTestTask,
73 base::Unretained(idle_task_runner), run_count));
74 }
75 (*run_count)++;
76 }
77
78 void UpdateClockToDeadlineIdleTestTask(
79 scoped_refptr<cc::TestNowSource> clock,
80 base::SingleThreadTaskRunner* task_runner,
81 int* run_count,
82 base::TimeTicks deadline) {
83 clock->SetNow(deadline);
84 // Due to the way in which OrderedSimpleTestRunner orders tasks and the fact
85 // that we updated the time within a task, the delayed pending task to call
86 // EndIdlePeriod will not happen until after a TaskQueueManager DoWork, so
87 // post a normal task here to ensure it runs before the next idle task.
88 task_runner->PostTask(FROM_HERE, base::Bind(NullTask));
89 (*run_count)++;
90 }
91
92 void RepeatingTask(base::SingleThreadTaskRunner* task_runner,
93 int num_repeats,
94 base::TimeDelta delay) {
95 if (num_repeats > 1) {
96 task_runner->PostDelayedTask(
97 FROM_HERE, base::Bind(&RepeatingTask, base::Unretained(task_runner),
98 num_repeats - 1, delay),
99 delay);
100 }
101 }
102
103 scoped_refptr<NestableSingleThreadTaskRunner>
104 CreateNestableSingleThreadTaskRunner(
105 base::MessageLoop* message_loop,
106 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner) {
107 if (message_loop)
108 return SchedulerMessageLoopDelegate::Create(message_loop);
109
110 return NestableTaskRunnerForTest::Create(mock_task_runner);
111 }
112
113 }; // namespace
114
115 class SchedulerHelperForTest : public SchedulerHelper,
116 public SchedulerHelper::SchedulerHelperDelegate {
117 public:
118 explicit SchedulerHelperForTest(
119 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner,
120 base::TimeDelta required_quiescence_duration_before_long_idle_period)
121 : SchedulerHelper(main_task_runner,
122 this,
123 "test.scheduler",
124 TRACE_DISABLED_BY_DEFAULT("test.scheduler"),
125 "TestSchedulerIdlePeriod",
126 TASK_QUEUE_COUNT,
127 required_quiescence_duration_before_long_idle_period) {}
128
129 ~SchedulerHelperForTest() override {}
130
131 // SchedulerHelperDelegate implementation:
132 MOCK_METHOD2(CanEnterLongIdlePeriod,
133 bool(base::TimeTicks now,
134 base::TimeDelta* next_long_idle_period_delay_out));
135
136 MOCK_METHOD0(IsNotQuiescent, void());
137 };
138
139 class BaseSchedulerHelperTest : public testing::Test {
140 public:
141 BaseSchedulerHelperTest(
142 base::MessageLoop* message_loop,
143 base::TimeDelta required_quiescence_duration_before_long_idle_period)
144 : clock_(cc::TestNowSource::Create(5000)),
145 mock_task_runner_(message_loop
146 ? nullptr
147 : new cc::OrderedSimpleTaskRunner(clock_, false)),
148 message_loop_(message_loop),
149 nestable_task_runner_(
150 CreateNestableSingleThreadTaskRunner(message_loop,
151 mock_task_runner_)),
152 scheduler_helper_(new SchedulerHelperForTest(
153 nestable_task_runner_,
154 required_quiescence_duration_before_long_idle_period)),
155 default_task_runner_(scheduler_helper_->DefaultTaskRunner()),
156 idle_task_runner_(scheduler_helper_->IdleTaskRunner()) {
157 scheduler_helper_->SetTimeSourceForTesting(
158 make_scoped_ptr(new TestTimeSource(clock_)));
159 scheduler_helper_->GetTaskQueueManagerForTesting()->SetTimeSourceForTesting(
160 make_scoped_ptr(new TestTimeSource(clock_)));
161 }
162
163 ~BaseSchedulerHelperTest() override {}
164
165 void TearDown() override {
166 DCHECK(!mock_task_runner_.get() || !message_loop_.get());
167 if (mock_task_runner_.get()) {
168 // Check that all tests stop posting tasks.
169 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
170 while (mock_task_runner_->RunUntilIdle()) {
171 }
172 } else {
173 message_loop_->RunUntilIdle();
174 }
175 }
176
177 void RunUntilIdle() {
178 // Only one of mock_task_runner_ or message_loop_ should be set.
179 DCHECK(!mock_task_runner_.get() || !message_loop_.get());
180 if (mock_task_runner_.get())
181 mock_task_runner_->RunUntilIdle();
182 else
183 message_loop_->RunUntilIdle();
184 }
185
186 // Helper for posting several tasks of specific types. |task_descriptor| is a
187 // string with space delimited task identifiers. The first letter of each
188 // task identifier specifies the task type:
189 // - 'D': Default task
190 // - 'I': Idle task
191 void PostTestTasks(std::vector<std::string>* run_order,
192 const std::string& task_descriptor) {
193 std::istringstream stream(task_descriptor);
194 while (!stream.eof()) {
195 std::string task;
196 stream >> task;
197 switch (task[0]) {
198 case 'D':
199 default_task_runner_->PostTask(
200 FROM_HERE, base::Bind(&AppendToVectorTestTask, run_order, task));
201 break;
202 case 'I':
203 idle_task_runner_->PostIdleTask(
204 FROM_HERE,
205 base::Bind(&AppendToVectorIdleTestTask, run_order, task));
206 break;
207 default:
208 NOTREACHED();
209 }
210 }
211 }
212
213 protected:
214 static base::TimeDelta maximum_idle_period_duration() {
215 return base::TimeDelta::FromMilliseconds(
216 SchedulerHelper::kMaximumIdlePeriodMillis);
217 }
218
219 base::TimeTicks CurrentIdleTaskDeadlineForTesting() {
220 base::TimeTicks deadline;
221 scheduler_helper_->CurrentIdleTaskDeadlineCallback(&deadline);
222 return deadline;
223 }
224
225 scoped_refptr<cc::TestNowSource> clock_;
226 // Only one of mock_task_runner_ or message_loop_ will be set.
227 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
228 scoped_ptr<base::MessageLoop> message_loop_;
229
230 scoped_refptr<NestableSingleThreadTaskRunner> nestable_task_runner_;
231 scoped_ptr<SchedulerHelperForTest> scheduler_helper_;
232 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
233 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
234
235 DISALLOW_COPY_AND_ASSIGN(BaseSchedulerHelperTest);
236 };
237
238 class SchedulerHelperTest : public BaseSchedulerHelperTest {
239 public:
240 SchedulerHelperTest() : BaseSchedulerHelperTest(nullptr, base::TimeDelta()) {}
241
242 ~SchedulerHelperTest() override {}
243
244 TaskQueueManager* task_queue_manager() const {
245 return scheduler_helper_->task_queue_manager_.get();
246 }
247
248 private:
249 DISALLOW_COPY_AND_ASSIGN(SchedulerHelperTest);
250 };
251
252 TEST_F(SchedulerHelperTest, TestPostDefaultTask) {
253 std::vector<std::string> run_order;
254 PostTestTasks(&run_order, "D1 D2 D3 D4");
255
256 RunUntilIdle();
257 EXPECT_THAT(run_order,
258 testing::ElementsAre(std::string("D1"), std::string("D2"),
259 std::string("D3"), std::string("D4")));
260 }
261
262 TEST_F(SchedulerHelperTest, TestRentrantTask) {
263 int count = 0;
264 std::vector<int> run_order;
265 default_task_runner_->PostTask(
266 FROM_HERE, base::Bind(AppendToVectorReentrantTask, default_task_runner_,
267 &run_order, &count, 5));
268 RunUntilIdle();
269
270 EXPECT_THAT(run_order, testing::ElementsAre(0, 1, 2, 3, 4));
271 }
272
273 TEST_F(SchedulerHelperTest, TestPostIdleTask) {
274 int run_count = 0;
275 base::TimeTicks expected_deadline =
276 clock_->Now() + base::TimeDelta::FromMilliseconds(2300);
277 base::TimeTicks deadline_in_task;
278
279 clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
280 idle_task_runner_->PostIdleTask(
281 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
282
283 RunUntilIdle();
284 EXPECT_EQ(0, run_count);
285
286 scheduler_helper_->StartIdlePeriod(
287 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
288 clock_->Now(),
289 expected_deadline,
290 true);
291 RunUntilIdle();
292 EXPECT_EQ(1, run_count);
293 EXPECT_EQ(expected_deadline, deadline_in_task);
294 }
295
296 TEST_F(SchedulerHelperTest, TestPostIdleTask_EndIdlePeriod) {
297 int run_count = 0;
298 base::TimeTicks deadline_in_task;
299
300 clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
301 idle_task_runner_->PostIdleTask(
302 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
303
304 RunUntilIdle();
305 EXPECT_EQ(0, run_count);
306
307 scheduler_helper_->StartIdlePeriod(
308 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
309 clock_->Now(),
310 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
311 true);
312 scheduler_helper_->EndIdlePeriod();
313 RunUntilIdle();
314 EXPECT_EQ(0, run_count);
315 }
316
317 TEST_F(SchedulerHelperTest, TestRepostingIdleTask) {
318 int run_count = 0;
319
320 max_idle_task_reposts = 2;
321 idle_task_runner_->PostIdleTask(
322 FROM_HERE,
323 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count));
324 scheduler_helper_->StartIdlePeriod(
325 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
326 clock_->Now(),
327 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
328 true);
329 RunUntilIdle();
330 EXPECT_EQ(1, run_count);
331
332 // Reposted tasks shouldn't run until next idle period.
333 RunUntilIdle();
334 EXPECT_EQ(1, run_count);
335
336 scheduler_helper_->StartIdlePeriod(
337 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
338 clock_->Now(),
339 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
340 true);
341 RunUntilIdle();
342 EXPECT_EQ(2, run_count);
343 }
344
345 TEST_F(SchedulerHelperTest, TestIdleTaskExceedsDeadline) {
346 int run_count = 0;
347
348 // Post two UpdateClockToDeadlineIdleTestTask tasks.
349 idle_task_runner_->PostIdleTask(
350 FROM_HERE, base::Bind(&UpdateClockToDeadlineIdleTestTask, clock_,
351 default_task_runner_, &run_count));
352 idle_task_runner_->PostIdleTask(
353 FROM_HERE, base::Bind(&UpdateClockToDeadlineIdleTestTask, clock_,
354 default_task_runner_, &run_count));
355
356 scheduler_helper_->StartIdlePeriod(
357 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
358 clock_->Now(),
359 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
360 true);
361 RunUntilIdle();
362 // Only the first idle task should execute since it's used up the deadline.
363 EXPECT_EQ(1, run_count);
364
365 scheduler_helper_->EndIdlePeriod();
366 scheduler_helper_->StartIdlePeriod(
367 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
368 clock_->Now(),
369 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
370 true);
371 RunUntilIdle();
372 // Second task should be run on the next idle period.
373 EXPECT_EQ(2, run_count);
374 }
375
376 TEST_F(SchedulerHelperTest, TestPostIdleTaskAfterWakeup) {
377 base::TimeTicks deadline_in_task;
378 int run_count = 0;
379
380 idle_task_runner_->PostIdleTaskAfterWakeup(
381 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
382
383 scheduler_helper_->StartIdlePeriod(
384 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
385 clock_->Now(),
386 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
387 true);
388 RunUntilIdle();
389 // Shouldn't run yet as no other task woke up the scheduler.
390 EXPECT_EQ(0, run_count);
391
392 idle_task_runner_->PostIdleTaskAfterWakeup(
393 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
394
395 scheduler_helper_->StartIdlePeriod(
396 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
397 clock_->Now(),
398 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
399 true);
400 RunUntilIdle();
401 // Another after wakeup idle task shouldn't wake the scheduler.
402 EXPECT_EQ(0, run_count);
403
404 default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
405
406 RunUntilIdle();
407 // Must start a new idle period before idle task runs.
408 scheduler_helper_->StartIdlePeriod(
409 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
410 clock_->Now(),
411 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
412 true);
413 RunUntilIdle();
414 // Execution of default task queue task should trigger execution of idle task.
415 EXPECT_EQ(2, run_count);
416 }
417
418 TEST_F(SchedulerHelperTest, TestPostIdleTaskAfterWakeupWhileAwake) {
419 base::TimeTicks deadline_in_task;
420 int run_count = 0;
421
422 idle_task_runner_->PostIdleTaskAfterWakeup(
423 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
424 default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
425
426 RunUntilIdle();
427 // Must start a new idle period before idle task runs.
428 scheduler_helper_->StartIdlePeriod(
429 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
430 clock_->Now(),
431 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
432 true);
433 RunUntilIdle();
434 // Should run as the scheduler was already awakened by the normal task.
435 EXPECT_EQ(1, run_count);
436 }
437
438 TEST_F(SchedulerHelperTest, TestPostIdleTaskWakesAfterWakeupIdleTask) {
439 base::TimeTicks deadline_in_task;
440 int run_count = 0;
441
442 idle_task_runner_->PostIdleTaskAfterWakeup(
443 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
444 idle_task_runner_->PostIdleTask(
445 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
446
447 scheduler_helper_->StartIdlePeriod(
448 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
449 clock_->Now(),
450 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
451 true);
452 RunUntilIdle();
453 // Must start a new idle period before after-wakeup idle task runs.
454 scheduler_helper_->StartIdlePeriod(
455 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
456 clock_->Now(),
457 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
458 true);
459 RunUntilIdle();
460 // Normal idle task should wake up after-wakeup idle task.
461 EXPECT_EQ(2, run_count);
462 }
463
464 TEST_F(SchedulerHelperTest, TestDelayedEndIdlePeriod) {
465 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
466
467 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
468 .Times(2)
469 .WillRepeatedly(Return(true));
470
471 // We need an idle task posted or EnableLongIdlePeriod will use the
472 // control_task_after_wakeup_runner_ instead of the control_task_runner_.
473 idle_task_runner_->PostIdleTask(FROM_HERE, base::Bind(&NullIdleTask));
474 scheduler_helper_->EnableLongIdlePeriod();
475
476 // Check there is a pending delayed task.
477 EXPECT_GT(task_queue_manager()->NextPendingDelayedTaskRunTime(),
478 base::TimeTicks());
479
480 RunUntilIdle();
481
482 // If the delayed task ran, it will an EnableLongIdlePeriod on the control
483 // task after wake up queue.
484 EXPECT_FALSE(task_queue_manager()->IsQueueEmpty(
485 SchedulerHelper::CONTROL_TASK_AFTER_WAKEUP_QUEUE));
486 }
487
488 TEST_F(SchedulerHelperTest, TestDelayedEndIdlePeriodCanceled) {
489 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
490
491 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
492 .Times(1)
493 .WillRepeatedly(Return(true));
494
495 // We need an idle task posted or EnableLongIdlePeriod will use the
496 // control_task_after_wakeup_runner_ instead of the control_task_runner_.
497 idle_task_runner_->PostIdleTask(FROM_HERE, base::Bind(&NullIdleTask));
498 scheduler_helper_->EnableLongIdlePeriod();
499
500 // Check there is a pending delayed task.
501 EXPECT_GT(task_queue_manager()->NextPendingDelayedTaskRunTime(),
502 base::TimeTicks());
503
504 scheduler_helper_->EndIdlePeriod();
505 RunUntilIdle();
506
507 // If the delayed task didn't run, there will be nothing on the control task
508 // after wake up queue.
509 EXPECT_TRUE(scheduler_helper_->IsQueueEmpty(
510 SchedulerHelper::CONTROL_TASK_AFTER_WAKEUP_QUEUE));
511 }
512
513 class SchedulerHelperWithMessageLoopTest : public BaseSchedulerHelperTest {
514 public:
515 SchedulerHelperWithMessageLoopTest()
516 : BaseSchedulerHelperTest(new base::MessageLoop(), base::TimeDelta()) {}
517 ~SchedulerHelperWithMessageLoopTest() override {}
518
519 void PostFromNestedRunloop(std::vector<
520 std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>* tasks) {
521 base::MessageLoop::ScopedNestableTaskAllower allow(message_loop_.get());
522 for (std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>& pair : *tasks) {
523 if (pair.second) {
524 idle_task_runner_->PostIdleTask(FROM_HERE, pair.first);
525 } else {
526 idle_task_runner_->PostNonNestableIdleTask(FROM_HERE, pair.first);
527 }
528 }
529 scheduler_helper_->StartIdlePeriod(
530 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
531 clock_->Now(),
532 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
533 true);
534 message_loop_->RunUntilIdle();
535 }
536
537 private:
538 DISALLOW_COPY_AND_ASSIGN(SchedulerHelperWithMessageLoopTest);
539 };
540
541 TEST_F(SchedulerHelperWithMessageLoopTest,
542 NonNestableIdleTaskDoesntExecuteInNestedLoop) {
543 std::vector<std::string> order;
544 idle_task_runner_->PostIdleTask(
545 FROM_HERE,
546 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("1")));
547 idle_task_runner_->PostIdleTask(
548 FROM_HERE,
549 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("2")));
550
551 std::vector<std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>
552 tasks_to_post_from_nested_loop;
553 tasks_to_post_from_nested_loop.push_back(std::make_pair(
554 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("3")),
555 false));
556 tasks_to_post_from_nested_loop.push_back(std::make_pair(
557 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("4")), true));
558 tasks_to_post_from_nested_loop.push_back(std::make_pair(
559 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("5")), true));
560
561 default_task_runner_->PostTask(
562 FROM_HERE,
563 base::Bind(&SchedulerHelperWithMessageLoopTest::PostFromNestedRunloop,
564 base::Unretained(this),
565 base::Unretained(&tasks_to_post_from_nested_loop)));
566
567 scheduler_helper_->StartIdlePeriod(
568 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
569 clock_->Now(),
570 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
571 true);
572 RunUntilIdle();
573 // Note we expect task 3 to run last because it's non-nestable.
574 EXPECT_THAT(order, testing::ElementsAre(std::string("1"), std::string("2"),
575 std::string("4"), std::string("5"),
576 std::string("3")));
577 }
578
579 TEST_F(SchedulerHelperTest, TestLongIdlePeriod) {
580 base::TimeTicks expected_deadline =
581 clock_->Now() + maximum_idle_period_duration();
582 base::TimeTicks deadline_in_task;
583 int run_count = 0;
584
585 idle_task_runner_->PostIdleTask(
586 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
587
588 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
589 .Times(2)
590 .WillRepeatedly(Return(true));
591
592 RunUntilIdle();
593 EXPECT_EQ(0, run_count); // Shouldn't run yet as no idle period.
594
595 scheduler_helper_->EnableLongIdlePeriod();
596 RunUntilIdle();
597 EXPECT_EQ(1, run_count); // Should have run in a long idle time.
598 EXPECT_EQ(expected_deadline, deadline_in_task);
599 }
600
601 TEST_F(SchedulerHelperTest, TestLongIdlePeriodWithPendingDelayedTask) {
602 base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(30);
603 base::TimeTicks expected_deadline = clock_->Now() + pending_task_delay;
604 base::TimeTicks deadline_in_task;
605 int run_count = 0;
606
607 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
608 .Times(2)
609 .WillRepeatedly(Return(true));
610
611 idle_task_runner_->PostIdleTask(
612 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
613 default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask),
614 pending_task_delay);
615
616 scheduler_helper_->EnableLongIdlePeriod();
617 RunUntilIdle();
618 EXPECT_EQ(1, run_count); // Should have run in a long idle time.
619 EXPECT_EQ(expected_deadline, deadline_in_task);
620 }
621
622 TEST_F(SchedulerHelperTest, TestLongIdlePeriodWithLatePendingDelayedTask) {
623 base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(10);
624 base::TimeTicks deadline_in_task;
625 int run_count = 0;
626
627 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
628 .Times(3)
629 .WillRepeatedly(Return(true));
630
631 default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask),
632 pending_task_delay);
633
634 // Advance clock until after delayed task was meant to be run.
635 clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(20));
636
637 // Post an idle task and then EnableLongIdlePeriod. Since there is a late
638 // pending delayed task this shouldn't actually start an idle period.
639 idle_task_runner_->PostIdleTask(
640 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
641 scheduler_helper_->EnableLongIdlePeriod();
642 RunUntilIdle();
643 EXPECT_EQ(0, run_count);
644
645 // After the delayed task has been run we should trigger an idle period.
646 clock_->AdvanceNow(maximum_idle_period_duration());
647 RunUntilIdle();
648 EXPECT_EQ(1, run_count);
649 }
650
651 TEST_F(SchedulerHelperTest, TestLongIdlePeriodRepeating) {
652 int run_count = 0;
653
654 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
655 .Times(2)
656 .WillRepeatedly(Return(true));
657
658 max_idle_task_reposts = 3;
659 idle_task_runner_->PostIdleTask(
660 FROM_HERE,
661 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count));
662
663 scheduler_helper_->EnableLongIdlePeriod();
664 RunUntilIdle();
665 EXPECT_EQ(1, run_count); // Should only run once per idle period.
666
667 // Advance time to start of next long idle period and check task reposted task
668 // gets run.
669 clock_->AdvanceNow(maximum_idle_period_duration());
670 RunUntilIdle();
671 EXPECT_EQ(2, run_count);
672
673 // Advance time to start of next long idle period then end the idle period and
674 // check the task doesn't get run.
675 clock_->AdvanceNow(maximum_idle_period_duration());
676 scheduler_helper_->EndIdlePeriod();
677 RunUntilIdle();
678 EXPECT_EQ(2, run_count);
679 }
680
681 TEST_F(SchedulerHelperTest, TestLongIdlePeriodDoesNotWakeScheduler) {
682 base::TimeTicks deadline_in_task;
683 int run_count = 0;
684
685 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
686 .Times(3)
687 .WillRepeatedly(Return(true));
688
689 // Start a long idle period and get the time it should end.
690 scheduler_helper_->EnableLongIdlePeriod();
691 // The scheduler should not run the initiate_next_long_idle_period task if
692 // there are no idle tasks and no other task woke up the scheduler, thus
693 // the idle period deadline shouldn't update at the end of the current long
694 // idle period.
695 base::TimeTicks idle_period_deadline = CurrentIdleTaskDeadlineForTesting();
696 clock_->AdvanceNow(maximum_idle_period_duration());
697 RunUntilIdle();
698
699 base::TimeTicks new_idle_period_deadline =
700 CurrentIdleTaskDeadlineForTesting();
701 EXPECT_EQ(idle_period_deadline, new_idle_period_deadline);
702
703 // Posting a after-wakeup idle task also shouldn't wake the scheduler or
704 // initiate the next long idle period.
705 idle_task_runner_->PostIdleTaskAfterWakeup(
706 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
707 RunUntilIdle();
708 new_idle_period_deadline = CurrentIdleTaskDeadlineForTesting();
709 EXPECT_EQ(idle_period_deadline, new_idle_period_deadline);
710 EXPECT_EQ(0, run_count);
711
712 // Running a normal task should initiate a new long idle period though.
713 default_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
714 RunUntilIdle();
715 new_idle_period_deadline = CurrentIdleTaskDeadlineForTesting();
716 EXPECT_EQ(idle_period_deadline + maximum_idle_period_duration(),
717 new_idle_period_deadline);
718
719 EXPECT_EQ(1, run_count);
720 }
721
722 TEST_F(SchedulerHelperTest, TestLongIdlePeriodWhenNotCanEnterLongIdlePeriod) {
723 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(1000);
724 base::TimeDelta halfDelay = base::TimeDelta::FromMilliseconds(500);
725 base::TimeTicks delayOver = clock_->Now() + delay;
726 base::TimeTicks deadline_in_task;
727 int run_count = 0;
728
729 ON_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
730 .WillByDefault(Invoke([delay, delayOver](
731 base::TimeTicks now,
732 base::TimeDelta* next_long_idle_period_delay_out) {
733 if (now >= delayOver)
734 return true;
735 *next_long_idle_period_delay_out = delay;
736 return false;
737 }));
738
739 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _)).Times(3);
740
741 idle_task_runner_->PostIdleTask(
742 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
743
744 // Make sure Idle tasks don't run until the delay has occured.
745 scheduler_helper_->EnableLongIdlePeriod();
746 RunUntilIdle();
747 EXPECT_EQ(0, run_count);
748
749 clock_->AdvanceNow(halfDelay);
750 RunUntilIdle();
751 EXPECT_EQ(0, run_count);
752
753 // Delay is finished, idle task should run.
754 clock_->AdvanceNow(halfDelay);
755 RunUntilIdle();
756 EXPECT_EQ(1, run_count);
757 }
758
759 void TestCanExceedIdleDeadlineIfRequiredTask(SchedulerHelperForTest* scheduler,
760 bool* can_exceed_idle_deadline_out,
761 int* run_count,
762 base::TimeTicks deadline) {
763 *can_exceed_idle_deadline_out = scheduler->CanExceedIdleDeadlineIfRequired();
764 (*run_count)++;
765 }
766
767 TEST_F(SchedulerHelperTest, CanExceedIdleDeadlineIfRequired) {
768 int run_count = 0;
769 bool can_exceed_idle_deadline = false;
770
771 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
772 .Times(3)
773 .WillRepeatedly(Return(true));
774
775 // Should return false if not in an idle period.
776 EXPECT_FALSE(scheduler_helper_->CanExceedIdleDeadlineIfRequired());
777
778 // Should return false for short idle periods.
779 idle_task_runner_->PostIdleTask(
780 FROM_HERE, base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask,
781 scheduler_helper_.get(), &can_exceed_idle_deadline,
782 &run_count));
783 scheduler_helper_->StartIdlePeriod(
784 SchedulerHelper::IdlePeriodState::IN_SHORT_IDLE_PERIOD,
785 clock_->Now(),
786 clock_->Now() + base::TimeDelta::FromMilliseconds(10),
787 true);
788 RunUntilIdle();
789 EXPECT_EQ(1, run_count);
790 EXPECT_FALSE(can_exceed_idle_deadline);
791
792 // Should return false for a long idle period which is shortened due to a
793 // pending delayed task.
794 default_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(&NullTask),
795 base::TimeDelta::FromMilliseconds(10));
796 idle_task_runner_->PostIdleTask(
797 FROM_HERE, base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask,
798 scheduler_helper_.get(), &can_exceed_idle_deadline,
799 &run_count));
800 scheduler_helper_->EnableLongIdlePeriod();
801 RunUntilIdle();
802 EXPECT_EQ(2, run_count);
803 EXPECT_FALSE(can_exceed_idle_deadline);
804
805 // Next long idle period will be for the maximum time, so
806 // CanExceedIdleDeadlineIfRequired should return true.
807 clock_->AdvanceNow(maximum_idle_period_duration());
808 idle_task_runner_->PostIdleTask(
809 FROM_HERE, base::Bind(&TestCanExceedIdleDeadlineIfRequiredTask,
810 scheduler_helper_.get(), &can_exceed_idle_deadline,
811 &run_count));
812 RunUntilIdle();
813 EXPECT_EQ(3, run_count);
814 EXPECT_TRUE(can_exceed_idle_deadline);
815 }
816
817 TEST_F(SchedulerHelperTest, IsShutdown) {
818 EXPECT_FALSE(scheduler_helper_->IsShutdown());
819
820 scheduler_helper_->Shutdown();
821 EXPECT_TRUE(scheduler_helper_->IsShutdown());
822 }
823
824 class SchedulerHelperWithQuiescencePeriodTest : public BaseSchedulerHelperTest {
825 public:
826 enum {
827 kQuiescenceDelayMs = 100,
828 kLongIdlePeriodMs = 50,
829 };
830
831 SchedulerHelperWithQuiescencePeriodTest()
832 : BaseSchedulerHelperTest(
833 nullptr,
834 base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs)) {}
835
836 ~SchedulerHelperWithQuiescencePeriodTest() override {}
837
838 void MakeNonQuiescent() {
839 // Run an arbitrary task so we're deemed to be not quiescent.
840 default_task_runner_->PostTask(FROM_HERE, base::Bind(NullTask));
841 RunUntilIdle();
842 }
843
844 private:
845 DISALLOW_COPY_AND_ASSIGN(SchedulerHelperWithQuiescencePeriodTest);
846 };
847
848 TEST_F(SchedulerHelperWithQuiescencePeriodTest,
849 LongIdlePeriodStartsImmediatelyIfQuiescent) {
850 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
851 .Times(2)
852 .WillRepeatedly(Return(true));
853
854 int run_count = 0;
855 max_idle_task_reposts = 1;
856 idle_task_runner_->PostIdleTask(
857 FROM_HERE,
858 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count));
859
860 scheduler_helper_->EnableLongIdlePeriod();
861 RunUntilIdle();
862
863 EXPECT_EQ(1, run_count);
864 }
865
866 TEST_F(SchedulerHelperWithQuiescencePeriodTest,
867 LongIdlePeriodDoesNotStartsImmediatelyIfBusy) {
868 MakeNonQuiescent();
869 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _)).Times(0);
870
871 int run_count = 0;
872 max_idle_task_reposts = 1;
873 idle_task_runner_->PostIdleTask(
874 FROM_HERE,
875 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count));
876
877 scheduler_helper_->EnableLongIdlePeriod();
878 RunUntilIdle();
879
880 EXPECT_EQ(0, run_count);
881
882 scheduler_helper_->Shutdown();
883 }
884
885 TEST_F(SchedulerHelperWithQuiescencePeriodTest,
886 LongIdlePeriodStartsAfterQuiescence) {
887 MakeNonQuiescent();
888 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
889 .Times(AnyNumber())
890 .WillRepeatedly(Return(true));
891 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
892
893 // Run a repeating task so we're deemed to be busy for the next 400ms.
894 default_task_runner_->PostTask(
895 FROM_HERE,
896 base::Bind(&RepeatingTask, base::Unretained(default_task_runner_.get()),
897 10, base::TimeDelta::FromMilliseconds(40)));
898
899 int run_count = 0;
900 // In this scenario EnableLongIdlePeriod deems us not to be quiescent 5x in
901 // a row.
902 base::TimeTicks expected_deadline =
903 clock_->Now() + base::TimeDelta::FromMilliseconds(5 * kQuiescenceDelayMs +
904 kLongIdlePeriodMs);
905 base::TimeTicks deadline_in_task;
906 idle_task_runner_->PostIdleTask(
907 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
908
909 scheduler_helper_->EnableLongIdlePeriod();
910 RunUntilIdle();
911 EXPECT_EQ(1, run_count);
912 EXPECT_EQ(expected_deadline, deadline_in_task);
913 }
914
915 TEST_F(SchedulerHelperWithQuiescencePeriodTest,
916 QuescienceCheckedForAfterLongIdlePeriodEnds) {
917 EXPECT_CALL(*scheduler_helper_, CanEnterLongIdlePeriod(_, _))
918 .Times(AnyNumber())
919 .WillRepeatedly(Return(true));
920 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
921
922 idle_task_runner_->PostIdleTask(FROM_HERE, base::Bind(&NullIdleTask));
923 scheduler_helper_->EnableLongIdlePeriod();
924 RunUntilIdle();
925
926 int run_count = 0;
927 base::TimeTicks deadline_in_task;
928 // Post an idle task, it won't run initially because the
929 // EnableLongIdlePeriod task was posted on an after wakeup runner.
930 idle_task_runner_->PostIdleTask(
931 FROM_HERE, base::Bind(&IdleTestTask, &run_count, &deadline_in_task));
932 RunUntilIdle();
933 EXPECT_EQ(0, run_count);
934
935 // Post a normal task to wake the system up. The idle task won't run
936 // immediately because the system isn't judged to be quiescent until the
937 // second time EnableLongIdlePeriod is run.
938 base::TimeTicks expected_deadline =
939 clock_->Now() +
940 base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs + kLongIdlePeriodMs);
941 default_task_runner_->PostTask(FROM_HERE, base::Bind(NullTask));
942 RunUntilIdle();
943
944 EXPECT_EQ(1, run_count);
945 EXPECT_EQ(expected_deadline, deadline_in_task);
946 }
947
948 } // namespace content
OLDNEW
« no previous file with comments | « content/child/scheduler/scheduler_helper.cc ('k') | content/child/scheduler/scheduler_message_loop_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698