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 RendererSchedulerImplForTest
: public RendererSchedulerImpl
{
17 RendererSchedulerImplForTest(
18 scoped_refptr
<cc::OrderedSimpleTaskRunner
> task_runner
,
19 scoped_refptr
<cc::TestNowSource
> clock
)
20 : RendererSchedulerImpl(task_runner
), clock_(clock
) {}
21 ~RendererSchedulerImplForTest() override
{}
24 base::TimeTicks
Now() const override
{ return clock_
->Now(); }
27 scoped_refptr
<cc::TestNowSource
> clock_
;
30 class RendererSchedulerImplTest
: public testing::Test
{
32 RendererSchedulerImplTest()
33 : clock_(cc::TestNowSource::Create(5000)),
34 mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_
, false)),
35 scheduler_(new RendererSchedulerImplForTest(mock_task_runner_
, clock_
)),
36 default_task_runner_(scheduler_
->DefaultTaskRunner()),
37 compositor_task_runner_(scheduler_
->CompositorTaskRunner()),
38 loading_task_runner_(scheduler_
->LoadingTaskRunner()),
39 idle_task_runner_(scheduler_
->IdleTaskRunner()) {}
40 ~RendererSchedulerImplTest() override
{}
42 void RunUntilIdle() { mock_task_runner_
->RunUntilIdle(); }
44 void EnableIdleTasks() {
45 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
46 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
47 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
48 scheduler_
->DidCommitFrameToCompositor();
52 scoped_refptr
<cc::TestNowSource
> clock_
;
53 scoped_refptr
<cc::OrderedSimpleTaskRunner
> mock_task_runner_
;
55 scoped_ptr
<RendererSchedulerImpl
> scheduler_
;
56 scoped_refptr
<base::SingleThreadTaskRunner
> default_task_runner_
;
57 scoped_refptr
<base::SingleThreadTaskRunner
> compositor_task_runner_
;
58 scoped_refptr
<base::SingleThreadTaskRunner
> loading_task_runner_
;
59 scoped_refptr
<SingleThreadIdleTaskRunner
> idle_task_runner_
;
61 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest
);
67 void OrderedTestTask(int value
, int* result
) {
68 *result
= (*result
<< 4) | value
;
71 void UnorderedTestTask(int value
, int* result
) {
75 void AppendToVectorTestTask(std::vector
<std::string
>* vector
,
77 vector
->push_back(value
);
80 void AppendToVectorIdleTestTask(std::vector
<std::string
>* vector
,
82 base::TimeTicks deadline
) {
83 AppendToVectorTestTask(vector
, value
);
86 void AppendToVectorReentrantTask(
87 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
88 std::vector
<int>* vector
,
90 int max_reentrant_count
) {
91 vector
->push_back((*reentrant_count
)++);
92 if (*reentrant_count
< max_reentrant_count
) {
93 task_runner
->PostTask(
94 FROM_HERE
, base::Bind(AppendToVectorReentrantTask
, task_runner
, vector
,
95 reentrant_count
, max_reentrant_count
));
99 void IdleTestTask(bool* task_run
,
100 base::TimeTicks
* deadline_out
,
101 base::TimeTicks deadline
) {
102 EXPECT_FALSE(*task_run
);
103 *deadline_out
= deadline
;
107 void RepostingIdleTestTask(
108 scoped_refptr
<SingleThreadIdleTaskRunner
> idle_task_runner
,
110 base::TimeTicks deadline
) {
111 if (*run_count
== 0) {
112 idle_task_runner
->PostIdleTask(
114 base::Bind(&RepostingIdleTestTask
, idle_task_runner
, run_count
));
119 void UpdateClockToDeadlineIdleTestTask(
120 scoped_refptr
<cc::TestNowSource
> clock
,
121 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
123 base::TimeTicks deadline
) {
124 clock
->SetNow(deadline
);
125 // Due to the way in which OrderedSimpleTestRunner orders tasks and the fact
126 // that we updated the time within a task, the delayed pending task to call
127 // EndIdlePeriod will not happen until after a TaskQueueManager DoWork, so
128 // post a normal task here to ensure it runs before the next idle task.
129 task_runner
->PostTask(FROM_HERE
, base::Bind(NullTask
));
133 void PostingYieldingTestTask(
134 RendererSchedulerImpl
* scheduler
,
135 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
137 bool* should_yield_before
,
138 bool* should_yield_after
) {
139 *should_yield_before
= scheduler
->ShouldYieldForHighPriorityWork();
140 task_runner
->PostTask(FROM_HERE
, base::Bind(NullTask
));
141 if (simulate_input
) {
142 scheduler
->DidReceiveInputEventOnCompositorThread(
143 blink::WebInputEvent::GestureFlingStart
);
145 *should_yield_after
= scheduler
->ShouldYieldForHighPriorityWork();
148 TEST_F(RendererSchedulerImplTest
, TestPostDefaultTask
) {
150 default_task_runner_
->PostTask(FROM_HERE
,
151 base::Bind(OrderedTestTask
, 1, &result
));
152 default_task_runner_
->PostTask(FROM_HERE
,
153 base::Bind(OrderedTestTask
, 2, &result
));
154 default_task_runner_
->PostTask(FROM_HERE
,
155 base::Bind(OrderedTestTask
, 3, &result
));
156 default_task_runner_
->PostTask(FROM_HERE
,
157 base::Bind(OrderedTestTask
, 4, &result
));
159 EXPECT_EQ(0x1234, result
);
162 TEST_F(RendererSchedulerImplTest
, TestPostDefaultAndCompositor
) {
164 default_task_runner_
->PostTask(FROM_HERE
,
165 base::Bind(&UnorderedTestTask
, 1, &result
));
166 compositor_task_runner_
->PostTask(FROM_HERE
,
167 base::Bind(&UnorderedTestTask
, 2, &result
));
169 EXPECT_EQ(3, result
);
172 TEST_F(RendererSchedulerImplTest
, TestRentrantTask
) {
174 std::vector
<int> order
;
175 default_task_runner_
->PostTask(
176 FROM_HERE
, base::Bind(AppendToVectorReentrantTask
, default_task_runner_
,
180 EXPECT_THAT(order
, testing::ElementsAre(0, 1, 2, 3, 4));
183 TEST_F(RendererSchedulerImplTest
, TestPostIdleTask
) {
184 bool task_run
= false;
185 base::TimeTicks expected_deadline
=
186 clock_
->Now() + base::TimeDelta::FromMilliseconds(2300);
187 base::TimeTicks deadline_in_task
;
189 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
190 idle_task_runner_
->PostIdleTask(
191 FROM_HERE
, base::Bind(&IdleTestTask
, &task_run
, &deadline_in_task
));
194 EXPECT_FALSE(task_run
); // Shouldn't run yet as no WillBeginFrame.
196 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
197 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
198 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
200 EXPECT_FALSE(task_run
); // Shouldn't run as no DidCommitFrameToCompositor.
202 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(1200));
203 scheduler_
->DidCommitFrameToCompositor();
205 EXPECT_FALSE(task_run
); // We missed the deadline.
207 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
208 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
209 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
210 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(800));
211 scheduler_
->DidCommitFrameToCompositor();
213 EXPECT_TRUE(task_run
);
214 EXPECT_EQ(expected_deadline
, deadline_in_task
);
217 TEST_F(RendererSchedulerImplTest
, TestRepostingIdleTask
) {
220 idle_task_runner_
->PostIdleTask(
222 base::Bind(&RepostingIdleTestTask
, idle_task_runner_
, &run_count
));
225 EXPECT_EQ(1, run_count
);
227 // Reposted tasks shouldn't run until next idle period.
229 EXPECT_EQ(1, run_count
);
233 EXPECT_EQ(2, run_count
);
236 TEST_F(RendererSchedulerImplTest
, TestIdleTaskExceedsDeadline
) {
237 mock_task_runner_
->SetAutoAdvanceNowToPendingTasks(true);
240 // Post two UpdateClockToDeadlineIdleTestTask tasks.
241 idle_task_runner_
->PostIdleTask(
242 FROM_HERE
, base::Bind(&UpdateClockToDeadlineIdleTestTask
, clock_
,
243 default_task_runner_
, &run_count
));
244 idle_task_runner_
->PostIdleTask(
245 FROM_HERE
, base::Bind(&UpdateClockToDeadlineIdleTestTask
, clock_
,
246 default_task_runner_
, &run_count
));
250 // Only the first idle task should execute since it's used up the deadline.
251 EXPECT_EQ(1, run_count
);
255 // Second task should be run on the next idle period.
256 EXPECT_EQ(2, run_count
);
259 TEST_F(RendererSchedulerImplTest
, TestDelayedEndIdlePeriodCanceled
) {
260 bool task_run
= false;
262 base::TimeTicks deadline_in_task
;
263 idle_task_runner_
->PostIdleTask(
264 FROM_HERE
, base::Bind(&IdleTestTask
, &task_run
, &deadline_in_task
));
266 // Trigger the beginning of an idle period for 1000ms.
267 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
268 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
269 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
270 scheduler_
->DidCommitFrameToCompositor();
272 // End the idle period early (after 500ms), and send a WillBeginFrame which
273 // specifies that the next idle period should end 1000ms from now.
274 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(500));
275 scheduler_
->WillBeginFrame(cc::BeginFrameArgs::Create(
276 BEGINFRAME_FROM_HERE
, clock_
->Now(), base::TimeTicks(),
277 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL
));
280 EXPECT_FALSE(task_run
); // Not currently in an idle period.
282 // Trigger the start of the idle period before the task to end the previous
283 // idle period has been triggered.
284 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(400));
285 scheduler_
->DidCommitFrameToCompositor();
287 // Post a task which simulates running until after the previous end idle
288 // period delayed task was scheduled for
289 scheduler_
->DefaultTaskRunner()->PostTask(FROM_HERE
, base::Bind(NullTask
));
290 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(300));
293 EXPECT_TRUE(task_run
); // We should still be in the new idle period.
296 TEST_F(RendererSchedulerImplTest
, TestDefaultPolicy
) {
297 std::vector
<std::string
> order
;
299 loading_task_runner_
->PostTask(
301 base::Bind(&AppendToVectorTestTask
, &order
, std::string("L1")));
302 idle_task_runner_
->PostIdleTask(
304 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
305 default_task_runner_
->PostTask(
307 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
308 compositor_task_runner_
->PostTask(
310 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
311 default_task_runner_
->PostTask(
313 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
314 compositor_task_runner_
->PostTask(
316 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
320 EXPECT_THAT(order
, testing::ElementsAre(
321 std::string("L1"), std::string("D1"), std::string("C1"),
322 std::string("D2"), std::string("C2"), std::string("I1")));
325 TEST_F(RendererSchedulerImplTest
, TestCompositorPolicy
) {
326 std::vector
<std::string
> order
;
328 loading_task_runner_
->PostTask(
330 base::Bind(&AppendToVectorTestTask
, &order
, std::string("L1")));
331 idle_task_runner_
->PostIdleTask(
333 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
334 default_task_runner_
->PostTask(
336 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
337 compositor_task_runner_
->PostTask(
339 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
340 default_task_runner_
->PostTask(
342 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
343 compositor_task_runner_
->PostTask(
345 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
347 scheduler_
->DidReceiveInputEventOnCompositorThread(
348 blink::WebInputEvent::GestureFlingStart
);
351 EXPECT_THAT(order
, testing::ElementsAre(
352 std::string("C1"), std::string("C2"), std::string("D1"),
353 std::string("D2"), std::string("L1"), std::string("I1")));
356 TEST_F(RendererSchedulerImplTest
, TestCompositorPolicy_DidAnimateForInput
) {
357 std::vector
<std::string
> order
;
359 idle_task_runner_
->PostIdleTask(
361 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
362 default_task_runner_
->PostTask(
364 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
365 compositor_task_runner_
->PostTask(
367 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
368 default_task_runner_
->PostTask(
370 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
371 compositor_task_runner_
->PostTask(
373 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
375 scheduler_
->DidAnimateForInputOnCompositorThread();
378 EXPECT_THAT(order
, testing::ElementsAre(std::string("C1"), std::string("C2"),
379 std::string("D1"), std::string("D2"),
383 TEST_F(RendererSchedulerImplTest
,
384 DidReceiveInputEventOnCompositorThread_IgnoresMouseEvents
) {
385 std::vector
<std::string
> order
;
387 idle_task_runner_
->PostIdleTask(
389 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
390 default_task_runner_
->PostTask(
392 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
393 compositor_task_runner_
->PostTask(
395 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
396 default_task_runner_
->PostTask(
398 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
399 compositor_task_runner_
->PostTask(
401 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
403 scheduler_
->DidReceiveInputEventOnCompositorThread(
404 blink::WebInputEvent::MouseMove
);
407 // Note compositor tasks are not prioritized.
408 EXPECT_THAT(order
, testing::ElementsAre(std::string("D1"), std::string("C1"),
409 std::string("D2"), std::string("C2"),
413 TEST_F(RendererSchedulerImplTest
,
414 DidReceiveInputEventOnCompositorThread_IgnoresKeyboardEvents
) {
415 std::vector
<std::string
> order
;
417 idle_task_runner_
->PostIdleTask(
419 base::Bind(&AppendToVectorIdleTestTask
, &order
, std::string("I1")));
420 default_task_runner_
->PostTask(
422 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
423 compositor_task_runner_
->PostTask(
425 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
426 default_task_runner_
->PostTask(
428 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
429 compositor_task_runner_
->PostTask(
431 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
433 scheduler_
->DidReceiveInputEventOnCompositorThread(
434 blink::WebInputEvent::KeyDown
);
437 // Note compositor tasks are not prioritized.
438 EXPECT_THAT(order
, testing::ElementsAre(std::string("D1"), std::string("C1"),
439 std::string("D2"), std::string("C2"),
443 TEST_F(RendererSchedulerImplTest
,
444 TestCompositorPolicyDoesNotStarveDefaultTasks
) {
445 std::vector
<std::string
> order
;
447 default_task_runner_
->PostTask(
449 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
450 compositor_task_runner_
->PostTask(
452 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
453 for (int i
= 0; i
< 20; i
++) {
454 compositor_task_runner_
->PostTask(FROM_HERE
, base::Bind(&NullTask
));
456 compositor_task_runner_
->PostTask(
458 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
460 scheduler_
->DidReceiveInputEventOnCompositorThread(
461 blink::WebInputEvent::GestureFlingStart
);
463 // Ensure that the default D1 task gets to run at some point before the final
464 // C2 compositor task.
465 EXPECT_THAT(order
, testing::ElementsAre(std::string("C1"), std::string("D1"),
469 TEST_F(RendererSchedulerImplTest
, TestCompositorPolicyEnds
) {
470 std::vector
<std::string
> order
;
472 default_task_runner_
->PostTask(
474 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
475 compositor_task_runner_
->PostTask(
477 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
478 default_task_runner_
->PostTask(
480 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
481 compositor_task_runner_
->PostTask(
483 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
485 scheduler_
->DidReceiveInputEventOnCompositorThread(
486 blink::WebInputEvent::GestureFlingStart
);
489 testing::ElementsAre(std::string("C1"), std::string("C2"),
490 std::string("D1"), std::string("D2")));
493 clock_
->AdvanceNow(base::TimeDelta::FromMilliseconds(1000));
495 default_task_runner_
->PostTask(
497 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D1")));
498 compositor_task_runner_
->PostTask(
500 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C1")));
501 default_task_runner_
->PostTask(
503 base::Bind(&AppendToVectorTestTask
, &order
, std::string("D2")));
504 compositor_task_runner_
->PostTask(
506 base::Bind(&AppendToVectorTestTask
, &order
, std::string("C2")));
508 // Compositor policy mode should have ended now that the clock has advanced.
511 testing::ElementsAre(std::string("D1"), std::string("C1"),
512 std::string("D2"), std::string("C2")));
515 TEST_F(RendererSchedulerImplTest
, TestShouldYield
) {
516 bool should_yield_before
= false;
517 bool should_yield_after
= false;
519 default_task_runner_
->PostTask(
520 FROM_HERE
, base::Bind(&PostingYieldingTestTask
, scheduler_
.get(),
521 default_task_runner_
, false, &should_yield_before
,
522 &should_yield_after
));
524 // Posting to default runner shouldn't cause yielding.
525 EXPECT_FALSE(should_yield_before
);
526 EXPECT_FALSE(should_yield_after
);
528 default_task_runner_
->PostTask(
529 FROM_HERE
, base::Bind(&PostingYieldingTestTask
, scheduler_
.get(),
530 compositor_task_runner_
, false,
531 &should_yield_before
, &should_yield_after
));
533 // Posting while not in compositor priority shouldn't cause yielding.
534 EXPECT_FALSE(should_yield_before
);
535 EXPECT_FALSE(should_yield_after
);
537 default_task_runner_
->PostTask(
538 FROM_HERE
, base::Bind(&PostingYieldingTestTask
, scheduler_
.get(),
539 compositor_task_runner_
, true, &should_yield_before
,
540 &should_yield_after
));
542 // We should be able to switch to compositor priority mid-task.
543 EXPECT_FALSE(should_yield_before
);
544 EXPECT_TRUE(should_yield_after
);
547 } // namespace content