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

Side by Side Diff: content/renderer/scheduler/renderer_scheduler_impl_unittest.cc

Issue 664963002: content: Add RendererScheduler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Daniel and Jared's comments and move renderer_scheduler ownership to render_thread_impl Created 6 years, 1 month 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/renderer/scheduler/renderer_scheduler_impl.h"
6
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"
12
13 namespace content {
14
15 class RendererSchedulerImplForTest : public RendererSchedulerImpl {
16 public:
17 RendererSchedulerImplForTest(
18 scoped_refptr<cc::OrderedSimpleTaskRunner> task_runner,
19 scoped_refptr<cc::TestNowSource> clock)
20 : RendererSchedulerImpl(task_runner), clock_(clock) {}
21 ~RendererSchedulerImplForTest() override {}
22
23 protected:
24 base::TimeTicks Now() const override { return clock_->Now(); }
25
26 private:
27 scoped_refptr<cc::TestNowSource> clock_;
28 };
29
30 class RendererSchedulerImplTest : public testing::Test {
31 public:
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 idle_task_runner_(scheduler_->IdleTaskRunner()) {}
39 ~RendererSchedulerImplTest() override {}
40
41 void RunUntilIdle() { mock_task_runner_->RunUntilIdle(); }
42
43 void EnableIdleTasks() {
44 scheduler_->WillBeginFrame(
45 cc::BeginFrameArgs::Create(clock_->Now(),
46 base::TimeTicks(),
47 base::TimeDelta::FromMilliseconds(1000)));
48 scheduler_->DidCommitFrameToCompositor();
49 }
50
51 protected:
52 scoped_refptr<cc::TestNowSource> clock_;
53 scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
54
55 scoped_ptr<RendererSchedulerImpl> scheduler_;
56 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
57 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
58 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
59
60 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest);
61 };
62
63 void NullTask() {
64 }
65
66 void OrderedTestTask(int value, int* result) {
67 *result = (*result << 4) | value;
68 }
69
70 void UnorderedTestTask(int value, int* result) {
71 *result += value;
72 }
73
74 void AppendToVectorTestTask(std::vector<std::string>* vector,
75 std::string value) {
76 vector->push_back(value);
77 }
78
79 void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
80 std::string value,
81 base::TimeTicks deadline) {
82 AppendToVectorTestTask(vector, value);
83 }
84
85 void AppendToVectorReentrantTask(
86 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
87 std::vector<int>* vector,
88 int* reentrant_count,
89 int max_reentrant_count) {
90 vector->push_back((*reentrant_count)++);
91 if (*reentrant_count < max_reentrant_count) {
92 task_runner->PostTask(FROM_HERE,
93 base::Bind(AppendToVectorReentrantTask,
94 task_runner,
95 vector,
96 reentrant_count,
97 max_reentrant_count));
98 }
99 }
100
101 void IdleTestTask(bool* task_run,
102 base::TimeTicks* deadline_out,
103 base::TimeTicks deadline) {
104 EXPECT_FALSE(*task_run);
105 *deadline_out = deadline;
106 *task_run = true;
107 }
108
109 void RepostingIdleTestTask(
110 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner,
111 int* run_count,
112 base::TimeTicks deadline) {
113 if (*run_count == 0) {
114 idle_task_runner->PostIdleTask(
115 FROM_HERE,
116 base::Bind(&RepostingIdleTestTask, idle_task_runner, run_count));
117 }
118 (*run_count)++;
119 }
120
121 void UpdateClockToDeadlineIdleTestTask(
122 scoped_refptr<cc::TestNowSource> clock,
123 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
124 int* run_count,
125 base::TimeTicks deadline) {
126 clock->SetNow(deadline);
127 // Due to the way in which OrderedSimpleTestRunner orders tasks and the fact
128 // that we updated the time within a task, the delayed pending task to call
129 // EndIdlePeriod will not happen until after a TaskQueueManager DoWork, so
130 // post a normal task here to ensure it runs before the next idle task.
131 task_runner->PostTask(FROM_HERE, base::Bind(NullTask));
132 (*run_count)++;
133 }
134
135 void PostingYieldingTestTask(
136 RendererSchedulerImpl* scheduler,
137 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
138 bool simulate_input,
139 bool* should_yield_before,
140 bool* should_yield_after) {
141 *should_yield_before = scheduler->ShouldYieldForHighPriorityWork();
142 task_runner->PostTask(FROM_HERE, base::Bind(NullTask));
143 if (simulate_input) {
144 scheduler->DidReceiveInputEvent();
145 }
146 *should_yield_after = scheduler->ShouldYieldForHighPriorityWork();
147 }
148
149 TEST_F(RendererSchedulerImplTest, TestPostDefaultTask) {
150 int result = 0;
151 default_task_runner_->PostTask(FROM_HERE,
152 base::Bind(OrderedTestTask, 1, &result));
153 default_task_runner_->PostTask(FROM_HERE,
154 base::Bind(OrderedTestTask, 2, &result));
155 default_task_runner_->PostTask(FROM_HERE,
156 base::Bind(OrderedTestTask, 3, &result));
157 default_task_runner_->PostTask(FROM_HERE,
158 base::Bind(OrderedTestTask, 4, &result));
159 RunUntilIdle();
160 EXPECT_EQ(0x1234, result);
161 }
162
163 TEST_F(RendererSchedulerImplTest, TestPostDefaultAndCompositor) {
164 int result = 0;
165 default_task_runner_->PostTask(FROM_HERE,
166 base::Bind(&UnorderedTestTask, 1, &result));
167 compositor_task_runner_->PostTask(FROM_HERE,
168 base::Bind(&UnorderedTestTask, 2, &result));
169 RunUntilIdle();
170 EXPECT_EQ(3, result);
171 }
172
173 TEST_F(RendererSchedulerImplTest, TestRentrantTask) {
174 int count = 0;
175 std::vector<int> order;
176 default_task_runner_->PostTask(FROM_HERE,
177 base::Bind(AppendToVectorReentrantTask,
178 default_task_runner_,
179 &order,
180 &count,
181 5));
182 RunUntilIdle();
183
184 EXPECT_THAT(order, testing::ElementsAre(0, 1, 2, 3, 4));
185 }
186
187 TEST_F(RendererSchedulerImplTest, TestPostIdleTask) {
188 bool task_run = false;
189 base::TimeTicks expected_deadline =
190 clock_->Now() + base::TimeDelta::FromMilliseconds(2300);
191 base::TimeTicks deadline_in_task;
192
193 clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
194 idle_task_runner_->PostIdleTask(
195 FROM_HERE, base::Bind(&IdleTestTask, &task_run, &deadline_in_task));
196
197 RunUntilIdle();
198 EXPECT_FALSE(task_run); // Shouldn't run yet as no WillBeginFrame.
199
200 scheduler_->WillBeginFrame(
201 cc::BeginFrameArgs::Create(clock_->Now(),
202 base::TimeTicks(),
203 base::TimeDelta::FromMilliseconds(1000)));
204 RunUntilIdle();
205 EXPECT_FALSE(task_run); // Shouldn't run as no DidCommitFrameToCompositor.
206
207 clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(1200));
208 scheduler_->DidCommitFrameToCompositor();
209 RunUntilIdle();
210 EXPECT_FALSE(task_run); // We missed the deadline.
211
212 scheduler_->WillBeginFrame(
213 cc::BeginFrameArgs::Create(clock_->Now(),
214 base::TimeTicks(),
215 base::TimeDelta::FromMilliseconds(1000)));
216 clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(800));
217 scheduler_->DidCommitFrameToCompositor();
218 RunUntilIdle();
219 EXPECT_TRUE(task_run);
220 EXPECT_EQ(expected_deadline, deadline_in_task);
221 }
222
223 TEST_F(RendererSchedulerImplTest, TestRepostingIdleTask) {
224 int run_count = 0;
225
226 idle_task_runner_->PostIdleTask(
227 FROM_HERE,
228 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count));
229 EnableIdleTasks();
230 RunUntilIdle();
231 EXPECT_EQ(1, run_count);
232
233 // Reposted tasks shouldn't run until next idle period.
234 RunUntilIdle();
235 EXPECT_EQ(1, run_count);
236
237 EnableIdleTasks();
238 RunUntilIdle();
239 EXPECT_EQ(2, run_count);
240 }
241
242 TEST_F(RendererSchedulerImplTest, TestIdleTaskExceedsDeadline) {
243 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
244 int run_count = 0;
245
246 // Post two UpdateClockToDeadlineIdleTestTask tasks.
247 idle_task_runner_->PostIdleTask(FROM_HERE,
248 base::Bind(&UpdateClockToDeadlineIdleTestTask,
249 clock_,
250 default_task_runner_,
251 &run_count));
252 idle_task_runner_->PostIdleTask(FROM_HERE,
253 base::Bind(&UpdateClockToDeadlineIdleTestTask,
254 clock_,
255 default_task_runner_,
256 &run_count));
257
258 EnableIdleTasks();
259 RunUntilIdle();
260 // Only the first idle task should execute since it's used up the deadline.
261 EXPECT_EQ(1, run_count);
262
263 EnableIdleTasks();
264 RunUntilIdle();
265 // Second task should be run on the next idle period.
266 EXPECT_EQ(2, run_count);
267 }
268
269 TEST_F(RendererSchedulerImplTest, TestDefaultPolicy) {
270 std::vector<std::string> order;
271
272 idle_task_runner_->PostIdleTask(
273 FROM_HERE,
274 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1")));
275 default_task_runner_->PostTask(
276 FROM_HERE,
277 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
278 compositor_task_runner_->PostTask(
279 FROM_HERE,
280 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
281 default_task_runner_->PostTask(
282 FROM_HERE,
283 base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
284 compositor_task_runner_->PostTask(
285 FROM_HERE,
286 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
287
288 EnableIdleTasks();
289 RunUntilIdle();
290 EXPECT_THAT(order,
291 testing::ElementsAre(std::string("D1"),
292 std::string("C1"),
293 std::string("D2"),
294 std::string("C2"),
295 std::string("I1")));
296 }
297
298 TEST_F(RendererSchedulerImplTest, TestCompositorPolicy) {
299 std::vector<std::string> order;
300
301 idle_task_runner_->PostIdleTask(
302 FROM_HERE,
303 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1")));
304 default_task_runner_->PostTask(
305 FROM_HERE,
306 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
307 compositor_task_runner_->PostTask(
308 FROM_HERE,
309 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
310 default_task_runner_->PostTask(
311 FROM_HERE,
312 base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
313 compositor_task_runner_->PostTask(
314 FROM_HERE,
315 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
316
317 scheduler_->DidReceiveInputEvent();
318 EnableIdleTasks();
319 RunUntilIdle();
320 EXPECT_THAT(order,
321 testing::ElementsAre(std::string("C1"),
322 std::string("C2"),
323 std::string("D1"),
324 std::string("D2"),
325 std::string("I1")));
326 }
327
328 TEST_F(RendererSchedulerImplTest,
329 TestCompositorPolicyDoesNotStarveDefaultTasks) {
330 std::vector<std::string> order;
331
332 default_task_runner_->PostTask(
333 FROM_HERE,
334 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
335 compositor_task_runner_->PostTask(
336 FROM_HERE,
337 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
338 for (int i = 0; i < 20; i++) {
339 compositor_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
340 }
341 compositor_task_runner_->PostTask(
342 FROM_HERE,
343 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
344
345 scheduler_->DidReceiveInputEvent();
346 RunUntilIdle();
347 // Ensure that the default D1 task gets to run at some point before the final
348 // C2 compositor task.
349 EXPECT_THAT(order,
350 testing::ElementsAre(
351 std::string("C1"), std::string("D1"), std::string("C2")));
352 }
353
354 TEST_F(RendererSchedulerImplTest, TestCompositorPolicyEnds) {
355 std::vector<std::string> order;
356
357 default_task_runner_->PostTask(
358 FROM_HERE,
359 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
360 compositor_task_runner_->PostTask(
361 FROM_HERE,
362 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
363 default_task_runner_->PostTask(
364 FROM_HERE,
365 base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
366 compositor_task_runner_->PostTask(
367 FROM_HERE,
368 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
369
370 scheduler_->DidReceiveInputEvent();
371 RunUntilIdle();
372 EXPECT_THAT(order,
373 testing::ElementsAre(std::string("C1"),
374 std::string("C2"),
375 std::string("D1"),
376 std::string("D2")));
377
378 order.clear();
379 clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(1000));
380
381 default_task_runner_->PostTask(
382 FROM_HERE,
383 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
384 compositor_task_runner_->PostTask(
385 FROM_HERE,
386 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
387 default_task_runner_->PostTask(
388 FROM_HERE,
389 base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
390 compositor_task_runner_->PostTask(
391 FROM_HERE,
392 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
393
394 // Compositor policy mode should have ended now that the clock has advanced.
395 RunUntilIdle();
396 EXPECT_THAT(order,
397 testing::ElementsAre(std::string("D1"),
398 std::string("C1"),
399 std::string("D2"),
400 std::string("C2")));
401 }
402
403 TEST_F(RendererSchedulerImplTest, TestShouldYield) {
404 bool should_yield_before = false;
405 bool should_yield_after = false;
406
407 default_task_runner_->PostTask(FROM_HERE,
408 base::Bind(&PostingYieldingTestTask,
409 scheduler_.get(),
410 default_task_runner_,
411 false,
412 &should_yield_before,
413 &should_yield_after));
414 RunUntilIdle();
415 // Posting to default runner shouldn't cause yielding.
416 EXPECT_FALSE(should_yield_before);
417 EXPECT_FALSE(should_yield_after);
418
419 default_task_runner_->PostTask(FROM_HERE,
420 base::Bind(&PostingYieldingTestTask,
421 scheduler_.get(),
422 compositor_task_runner_,
423 false,
424 &should_yield_before,
425 &should_yield_after));
426 RunUntilIdle();
427 // Posting while not in compositor priority shouldn't cause yielding.
428 EXPECT_FALSE(should_yield_before);
429 EXPECT_FALSE(should_yield_after);
430
431 default_task_runner_->PostTask(FROM_HERE,
432 base::Bind(&PostingYieldingTestTask,
433 scheduler_.get(),
434 compositor_task_runner_,
435 true,
436 &should_yield_before,
437 &should_yield_after));
438 RunUntilIdle();
439 // We should be able to switch to compositor priority mid-task.
440 EXPECT_FALSE(should_yield_before);
441 EXPECT_TRUE(should_yield_after);
442 }
443
444 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698