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

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

Powered by Google App Engine
This is Rietveld 408576698