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.
5 #include "content/renderer/scheduler/renderer_scheduler_impl.h"
7 #include "base/callback.h"
8 #include "cc/output/begin_frame_args.h"
9 #include "cc/test/ordered_simple_task_runner.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
15 class RendererSchedulerImplTest
: public testing::Test
{
17 RendererSchedulerImplTest()
18 : clock_(cc::TestNowSource::Create(5000)),
19 mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_
, false)),
20 scheduler_(new RendererSchedulerImpl(mock_task_runner_
)),
21 default_task_runner_(scheduler_
->DefaultTaskRunner()),
22 compositor_task_runner_(scheduler_
->CompositorTaskRunner()),
23 loading_task_runner_(scheduler_
->LoadingTaskRunner()),
24 idle_task_runner_(scheduler_
->IdleTaskRunner()) {
25 scheduler_
->SetTimeSourceForTesting(clock_
);
27 ~RendererSchedulerImplTest() override
{}
29 void RunUntilIdle() { mock_task_runner_
->RunUntilIdle(); }
31 void EnableIdleTasks() {
32 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
33 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
34 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
35 scheduler_
->DidCommitFrameToCompositor();
39 scoped_refptr
<cc::TestNowSource
> clock_
;
40 scoped_refptr
<cc::OrderedSimpleTaskRunner
> mock_task_runner_
;
42 scoped_ptr
<RendererSchedulerImpl
> scheduler_
;
43 scoped_refptr
<base::SingleThreadTaskRunner
> default_task_runner_
;
44 scoped_refptr
<base::SingleThreadTaskRunner
> compositor_task_runner_
;
45 scoped_refptr
<base::SingleThreadTaskRunner
> loading_task_runner_
;
46 scoped_refptr
<SingleThreadIdleTaskRunner
> idle_task_runner_
;
48 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest
);
54 void OrderedTestTask(int value
, int* result
) {
55 *result
= (*result
<< 4) | value
;
58 void UnorderedTestTask(int value
, int* result
) {
62 void AppendToVectorTestTask(std::vector
<std::string
>* vector
,
64 vector
->push_back(value
);
67 void AppendToVectorIdleTestTask(std::vector
<std::string
>* vector
,
69 base::TimeTicks deadline
) {
70 AppendToVectorTestTask(vector
, value
);
73 void AppendToVectorReentrantTask(
74 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
75 std::vector
<int>* vector
,
77 int max_reentrant_count
) {
78 vector
->push_back((*reentrant_count
)++);
79 if (*reentrant_count
< max_reentrant_count
) {
80 task_runner
->PostTask(
81 FROM_HERE
, base::Bind(AppendToVectorReentrantTask
, task_runner
, vector
,
82 reentrant_count
, max_reentrant_count
));
86 void IdleTestTask(bool* task_run
,
87 base::TimeTicks
* deadline_out
,
88 base::TimeTicks deadline
) {
89 EXPECT_FALSE(*task_run
);
90 *deadline_out
= deadline
;
94 void RepostingIdleTestTask(
95 scoped_refptr
<SingleThreadIdleTaskRunner
> idle_task_runner
,
97 base::TimeTicks deadline
) {
98 if (*run_count
== 0) {
99 idle_task_runner
->PostIdleTask(
101 base::Bind(&RepostingIdleTestTask
, idle_task_runner
, run_count
));
106 void UpdateClockToDeadlineIdleTestTask(
107 scoped_refptr
<cc::TestNowSource
> clock
,
108 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
110 base::TimeTicks deadline
) {
111 clock
->SetNow(deadline
);
112 // Due to the way in which OrderedSimpleTestRunner orders tasks and the fact
113 // that we updated the time within a task, the delayed pending task to call
114 // EndIdlePeriod will not happen until after a TaskQueueManager DoWork, so
115 // post a normal task here to ensure it runs before the next idle task.
116 task_runner
->PostTask(FROM_HERE
, base::Bind(NullTask
));
120 void PostingYieldingTestTask(
121 RendererSchedulerImpl
* scheduler
,
122 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
124 bool* should_yield_before
,
125 bool* should_yield_after
) {
126 *should_yield_before
= scheduler
->ShouldYieldForHighPriorityWork();
127 task_runner
->PostTask(FROM_HERE
, base::Bind(NullTask
));
128 if (simulate_input
) {
129 scheduler
->DidReceiveInputEventOnCompositorThread(
130 blink::WebInputEvent::GestureFlingStart
);
132 *should_yield_after
= scheduler
->ShouldYieldForHighPriorityWork();
135 TEST_F(RendererSchedulerImplTest
, TestPostDefaultTask
) {
137 default_task_runner_
->PostTask(FROM_HERE
,
138 base::Bind(OrderedTestTask
, 1, &result
));
139 default_task_runner_
->PostTask(FROM_HERE
,
140 base::Bind(OrderedTestTask
, 2, &result
));
141 default_task_runner_
->PostTask(FROM_HERE
,
142 base::Bind(OrderedTestTask
, 3, &result
));
143 default_task_runner_
->PostTask(FROM_HERE
,
144 base::Bind(OrderedTestTask
, 4, &result
));
146 EXPECT_EQ(0x1234, result
);
149 TEST_F(RendererSchedulerImplTest
, TestPostDefaultAndCompositor
) {
151 default_task_runner_
->PostTask(FROM_HERE
,
152 base::Bind(&UnorderedTestTask
, 1, &result
));
153 compositor_task_runner_
->PostTask(FROM_HERE
,
154 base::Bind(&UnorderedTestTask
, 2, &result
));
156 EXPECT_EQ(3, result
);
159 TEST_F(RendererSchedulerImplTest
, TestRentrantTask
) {
161 std::vector
<int> order
;
162 default_task_runner_
->PostTask(
163 FROM_HERE
, base::Bind(AppendToVectorReentrantTask
, default_task_runner_
,
167 EXPECT_THAT(order
, testing::ElementsAre(0, 1, 2, 3, 4));
170 TEST_F(RendererSchedulerImplTest
, TestPostIdleTask
) {
171 bool task_run
= false;
172 base::TimeTicks expected_deadline
=
173 clock_
->Now() + base::TimeDelta::FromMilliseconds(2300);
174 base::TimeTicks deadline_in_task
;
176 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
177 idle_task_runner_
->PostIdleTask(
178 FROM_HERE
, base::Bind(&IdleTestTask
, &task_run
, &deadline_in_task
));
181 EXPECT_FALSE(task_run
); // Shouldn't run yet as no WillBeginFrame.
183 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
184 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
185 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
187 EXPECT_FALSE(task_run
); // Shouldn't run as no DidCommitFrameToCompositor.
189 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(1200));
190 scheduler_
->DidCommitFrameToCompositor();
192 EXPECT_FALSE(task_run
); // We missed the deadline.
194 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
195 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
196 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
197 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(800));
198 scheduler_
->DidCommitFrameToCompositor();
200 EXPECT_TRUE(task_run
);
201 EXPECT_EQ(expected_deadline
, deadline_in_task
);
204 TEST_F(RendererSchedulerImplTest
, TestRepostingIdleTask
) {
207 idle_task_runner_
->PostIdleTask(
209 base::Bind(&RepostingIdleTestTask
, idle_task_runner_
, &run_count
));
212 EXPECT_EQ(1, run_count
);
214 // Reposted tasks shouldn't run until next idle period.
216 EXPECT_EQ(1, run_count
);
220 EXPECT_EQ(2, run_count
);
223 TEST_F(RendererSchedulerImplTest
, TestIdleTaskExceedsDeadline
) {
224 mock_task_runner_
->SetAutoAdvanceNowToPendingTasks(true);
227 // Post two UpdateClockToDeadlineIdleTestTask tasks.
228 idle_task_runner_
->PostIdleTask(
229 FROM_HERE
, base::Bind(&UpdateClockToDeadlineIdleTestTask
, clock_
,
230 default_task_runner_
, &run_count
));
231 idle_task_runner_
->PostIdleTask(
232 FROM_HERE
, base::Bind(&UpdateClockToDeadlineIdleTestTask
, clock_
,
233 default_task_runner_
, &run_count
));
237 // Only the first idle task should execute since it's used up the deadline.
238 EXPECT_EQ(1, run_count
);
242 // Second task should be run on the next idle period.
243 EXPECT_EQ(2, run_count
);
246 TEST_F(RendererSchedulerImplTest
, TestDelayedEndIdlePeriodCanceled
) {
247 bool task_run
= false;
249 base::TimeTicks deadline_in_task
;
250 idle_task_runner_
->PostIdleTask(
251 FROM_HERE
, base::Bind(&IdleTestTask
, &task_run
, &deadline_in_task
));
253 // Trigger the beginning of an idle period for 1000ms.
254 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
255 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
256 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
257 scheduler_
->DidCommitFrameToCompositor();
259 // End the idle period early (after 500ms), and send a WillBeginFrame which
260 // specifies that the next idle period should end 1000ms from now.
261 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(500));
262 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
263 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
264 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
267 EXPECT_FALSE(task_run
); // Not currently in an idle period.
269 // Trigger the start of the idle period before the task to end the previous
270 // idle period has been triggered.
271 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(400));
272 scheduler_
->DidCommitFrameToCompositor();
274 // Post a task which simulates running until after the previous end idle
275 // period delayed task was scheduled for
276 scheduler_
->DefaultTaskRunner()->PostTask(FROM_HERE
, base::Bind(NullTask
));
277 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(300));
280 EXPECT_TRUE(task_run
); // We should still be in the new idle period.
283 TEST_F(RendererSchedulerImplTest
, TestDefaultPolicy
) {
284 std::vector
<std::string
> order
;
286 loading_task_runner_
->PostTask(
288 base::Bind(&AppendToVectorTestTask
, &order
, std::string("L1")));
289 idle_task_runner_
->PostIdleTask(
291 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
292 default_task_runner_
->PostTask(
294 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
295 compositor_task_runner_
->PostTask(
297 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
298 default_task_runner_
->PostTask(
300 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
301 compositor_task_runner_
->PostTask(
303 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
307 EXPECT_THAT(order
, testing::ElementsAre(
308 std::string("L1"), std::string("D1"), std::string("C1"),
309 std::string("D2"), std::string("C2"), std::string("I1")));
312 TEST_F(RendererSchedulerImplTest
, TestCompositorPolicy
) {
313 std::vector
<std::string
> order
;
315 loading_task_runner_
->PostTask(
317 base::Bind(&AppendToVectorTestTask
, &order
, std::string("L1")));
318 idle_task_runner_
->PostIdleTask(
320 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
321 default_task_runner_
->PostTask(
323 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
324 compositor_task_runner_
->PostTask(
326 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
327 default_task_runner_
->PostTask(
329 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
330 compositor_task_runner_
->PostTask(
332 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
334 scheduler_
->DidReceiveInputEventOnCompositorThread(
335 blink::WebInputEvent::GestureFlingStart
);
338 EXPECT_THAT(order
, testing::ElementsAre(
339 std::string("C1"), std::string("C2"), std::string("D1"),
340 std::string("D2"), std::string("L1"), std::string("I1")));
343 TEST_F(RendererSchedulerImplTest
, TestCompositorPolicy_DidAnimateForInput
) {
344 std::vector
<std::string
> order
;
346 idle_task_runner_
->PostIdleTask(
348 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
349 default_task_runner_
->PostTask(
351 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
352 compositor_task_runner_
->PostTask(
354 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
355 default_task_runner_
->PostTask(
357 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
358 compositor_task_runner_
->PostTask(
360 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
362 scheduler_
->DidAnimateForInputOnCompositorThread();
365 EXPECT_THAT(order
, testing::ElementsAre(std::string("C1"), std::string("C2"),
366 std::string("D1"), std::string("D2"),
370 TEST_F(RendererSchedulerImplTest
,
371 DidReceiveInputEventOnCompositorThread_IgnoresMouseEvents
) {
372 std::vector
<std::string
> order
;
374 idle_task_runner_
->PostIdleTask(
376 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
377 default_task_runner_
->PostTask(
379 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
380 compositor_task_runner_
->PostTask(
382 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
383 default_task_runner_
->PostTask(
385 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
386 compositor_task_runner_
->PostTask(
388 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
390 scheduler_
->DidReceiveInputEventOnCompositorThread(
391 blink::WebInputEvent::MouseMove
);
394 // Note compositor tasks are not prioritized.
395 EXPECT_THAT(order
, testing::ElementsAre(std::string("D1"), std::string("C1"),
396 std::string("D2"), std::string("C2"),
400 TEST_F(RendererSchedulerImplTest
,
401 DidReceiveInputEventOnCompositorThread_IgnoresKeyboardEvents
) {
402 std::vector
<std::string
> order
;
404 idle_task_runner_
->PostIdleTask(
406 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
407 default_task_runner_
->PostTask(
409 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
410 compositor_task_runner_
->PostTask(
412 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
413 default_task_runner_
->PostTask(
415 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
416 compositor_task_runner_
->PostTask(
418 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
420 scheduler_
->DidReceiveInputEventOnCompositorThread(
421 blink::WebInputEvent::KeyDown
);
424 // Note compositor tasks are not prioritized.
425 EXPECT_THAT(order
, testing::ElementsAre(std::string("D1"), std::string("C1"),
426 std::string("D2"), std::string("C2"),
430 TEST_F(RendererSchedulerImplTest
,
431 TestCompositorPolicyDoesNotStarveDefaultTasks
) {
432 std::vector
<std::string
> order
;
434 default_task_runner_
->PostTask(
436 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
437 compositor_task_runner_
->PostTask(
439 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
440 for (int i
= 0; i
< 20; i
++) {
441 compositor_task_runner_
->PostTask(FROM_HERE
, base::Bind(&NullTask
));
443 compositor_task_runner_
->PostTask(
445 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
447 scheduler_
->DidReceiveInputEventOnCompositorThread(
448 blink::WebInputEvent::GestureFlingStart
);
450 // Ensure that the default D1 task gets to run at some point before the final
451 // C2 compositor task.
452 EXPECT_THAT(order
, testing::ElementsAre(std::string("C1"), std::string("D1"),
456 TEST_F(RendererSchedulerImplTest
, TestCompositorPolicyEnds
) {
457 std::vector
<std::string
> order
;
459 default_task_runner_
->PostTask(
461 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
462 compositor_task_runner_
->PostTask(
464 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
465 default_task_runner_
->PostTask(
467 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
468 compositor_task_runner_
->PostTask(
470 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
472 scheduler_
->DidReceiveInputEventOnCompositorThread(
473 blink::WebInputEvent::GestureFlingStart
);
476 testing::ElementsAre(std::string("C1"), std::string("C2"),
477 std::string("D1"), std::string("D2")));
480 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(1000));
482 default_task_runner_
->PostTask(
484 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
485 compositor_task_runner_
->PostTask(
487 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
488 default_task_runner_
->PostTask(
490 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
491 compositor_task_runner_
->PostTask(
493 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
495 // Compositor policy mode should have ended now that the clock has advanced.
498 testing::ElementsAre(std::string("D1"), std::string("C1"),
499 std::string("D2"), std::string("C2")));
502 TEST_F(RendererSchedulerImplTest
, TestShouldYield
) {
503 bool should_yield_before
= false;
504 bool should_yield_after
= false;
506 default_task_runner_
->PostTask(
507 FROM_HERE
, base::Bind(&PostingYieldingTestTask
, scheduler_
.get(),
508 default_task_runner_
, false, &should_yield_before
,
509 &should_yield_after
));
511 // Posting to default runner shouldn't cause yielding.
512 EXPECT_FALSE(should_yield_before
);
513 EXPECT_FALSE(should_yield_after
);
515 default_task_runner_
->PostTask(
516 FROM_HERE
, base::Bind(&PostingYieldingTestTask
, scheduler_
.get(),
517 compositor_task_runner_
, false,
518 &should_yield_before
, &should_yield_after
));
520 // Posting while not in compositor priority shouldn't cause yielding.
521 EXPECT_FALSE(should_yield_before
);
522 EXPECT_FALSE(should_yield_after
);
524 default_task_runner_
->PostTask(
525 FROM_HERE
, base::Bind(&PostingYieldingTestTask
, scheduler_
.get(),
526 compositor_task_runner_
, true, &should_yield_before
,
527 &should_yield_after
));
529 // We should be able to switch to compositor priority mid-task.
530 EXPECT_FALSE(should_yield_before
);
531 EXPECT_TRUE(should_yield_after
);
534 } // namespace content