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

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: Even moar tests, add a null scheduler and follow review. Created 6 years, 2 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/renderer/scheduler/renderer_scheduler_impl.h"
6
7 #include "base/callback.h"
8 #include "base/test/simple_test_tick_clock.h"
9 #include "base/test/test_simple_task_runner.h"
10 #include "cc/output/begin_frame_args.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace content {
15
16 class DelaySupportingTestSimpleTaskRunner : public base::TestSimpleTaskRunner {
17 public:
18 DelaySupportingTestSimpleTaskRunner(base::SimpleTestTickClock* clock)
19 : clock_(clock) {}
20
21 virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
22 const base::Closure& task,
23 base::TimeDelta delay) override {
24 DCHECK(thread_checker_.CalledOnValidThread());
25 pending_tasks_.push_back(
26 base::TestPendingTask(from_here,
27 task,
28 clock_->NowTicks(),
29 delay,
30 base::TestPendingTask::NESTABLE));
31 return true;
32 }
33
34 virtual bool PostNonNestableDelayedTask(
35 const tracked_objects::Location& from_here,
36 const base::Closure& task,
37 base::TimeDelta delay) override {
38 DCHECK(thread_checker_.CalledOnValidThread());
39 pending_tasks_.push_back(
40 base::TestPendingTask(from_here,
41 task,
42 clock_->NowTicks(),
43 delay,
44 base::TestPendingTask::NON_NESTABLE));
45 return true;
46 }
47
48 bool HaveRunnablePendingTasks() {
49 for (base::TestPendingTask pending_task : pending_tasks_) {
50 if (pending_task.GetTimeToRun() <= clock_->NowTicks()) {
51 return true;
52 }
53 }
54 return false;
55 }
56
57 void RunPendingTasksIfNotDelayed() {
58 DCHECK(thread_checker_.CalledOnValidThread());
59 // Swap with a local variable to avoid re-entrancy problems.
60 std::deque<base::TestPendingTask> tasks_to_run;
61 tasks_to_run.swap(pending_tasks_);
62 for (base::TestPendingTask pending_task : tasks_to_run) {
63 if (pending_task.GetTimeToRun() <= clock_->NowTicks()) {
64 pending_task.task.Run();
65 } else {
66 pending_tasks_.push_front(pending_task);
67 }
68 }
69 }
70
71 void RunUntilTasksAreAllDelayed() {
72 DCHECK(thread_checker_.CalledOnValidThread());
73 while (!pending_tasks_.empty() && HaveRunnablePendingTasks()) {
74 RunPendingTasksIfNotDelayed();
75 }
76 }
77
78 protected:
79 virtual ~DelaySupportingTestSimpleTaskRunner() {}
80
81 private:
82 base::SimpleTestTickClock* clock_;
83 };
84
85 class RendererSchedulerImplForTest : public RendererSchedulerImpl {
86 public:
87 RendererSchedulerImplForTest(
88 scoped_refptr<base::TestSimpleTaskRunner> task_runner,
89 base::SimpleTestTickClock* clock)
90 : RendererSchedulerImpl(task_runner), clock_(clock) {}
91 virtual ~RendererSchedulerImplForTest() {}
92
93 protected:
94 virtual base::TimeTicks Now() const override { return clock_->NowTicks(); }
95
96 private:
97 base::SimpleTestTickClock* clock_;
98 };
99
100 class RendererSchedulerImplTest : public testing::Test {
101 public:
102 RendererSchedulerImplTest()
103 : clock_(new base::SimpleTestTickClock()),
104 mock_task_runner_(
105 new DelaySupportingTestSimpleTaskRunner(clock_.get())),
106 scheduler_(
107 new RendererSchedulerImplForTest(mock_task_runner_, clock_.get())),
108 default_task_runner_(scheduler_->DefaultTaskRunner()),
109 compositor_task_runner_(scheduler_->CompositorTaskRunner()),
110 idle_task_runner_(scheduler_->IdleTaskRunner()) {}
111 virtual ~RendererSchedulerImplTest() {}
112
113 void RunUntilIdle() { mock_task_runner_->RunUntilTasksAreAllDelayed(); }
114
115 void EnableIdleTasks() {
116 scheduler_->WillBeginFrame(
117 cc::BeginFrameArgs::Create(clock_->NowTicks(),
118 base::TimeTicks(),
119 base::TimeDelta::FromMilliseconds(1000)));
120 scheduler_->DidCommitFrameToCompositor();
121 }
122
123 protected:
124 virtual void SetUp() override {
125 // Ensure clock is non-zero.
126 clock_->Advance(base::TimeDelta::FromMilliseconds(5000));
127 }
128
129 scoped_ptr<base::SimpleTestTickClock> clock_;
130 scoped_refptr<DelaySupportingTestSimpleTaskRunner> mock_task_runner_;
131
132 scoped_ptr<RendererSchedulerImpl> scheduler_;
133 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
134 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
135 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
136
137 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest);
138 };
139
140 void NullTask() {
141 }
142
143 void OrderedTestTask(int value, int* result) {
144 *result = (*result << 4) | value;
145 }
146
147 void UnorderedTestTask(int value, int* result) {
148 *result += value;
149 }
150
151 void AppendToVectorTestTask(std::vector<std::string>* vector,
152 std::string value) {
153 vector->push_back(value);
154 }
155
156 void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
157 std::string value,
158 base::TimeTicks deadline) {
159 AppendToVectorTestTask(vector, value);
160 }
161
162 void AppendToVectorReentrantTask(
163 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
164 std::vector<int>* vector,
165 int* reentrant_count,
166 int max_reentrant_count) {
167 vector->push_back((*reentrant_count)++);
168 if (*reentrant_count < max_reentrant_count) {
169 task_runner->PostTask(FROM_HERE,
170 base::Bind(AppendToVectorReentrantTask,
171 task_runner,
172 vector,
173 reentrant_count,
174 max_reentrant_count));
175 }
176 }
177
178 void IdleTestTask(bool* task_run,
179 base::TimeTicks expected_deadline,
180 base::TimeTicks deadline) {
181 EXPECT_FALSE(*task_run);
182 EXPECT_EQ(expected_deadline, deadline);
183 *task_run = true;
184 }
185
186 void RepostingIdleTestTask(
187 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner,
188 int* run_count,
189 base::TimeTicks deadline) {
190 if (*run_count == 0)
191 idle_task_runner->PostIdleTask(
192 FROM_HERE,
193 base::Bind(&RepostingIdleTestTask, idle_task_runner, run_count));
194 (*run_count)++;
195 }
196
197 TEST_F(RendererSchedulerImplTest, TestPostDefaultTask) {
198 int result = 0;
199 default_task_runner_->PostTask(FROM_HERE,
200 base::Bind(OrderedTestTask, 1, &result));
201 default_task_runner_->PostTask(FROM_HERE,
202 base::Bind(OrderedTestTask, 2, &result));
203 default_task_runner_->PostTask(FROM_HERE,
204 base::Bind(OrderedTestTask, 3, &result));
205 default_task_runner_->PostTask(FROM_HERE,
206 base::Bind(OrderedTestTask, 4, &result));
207 RunUntilIdle();
208 EXPECT_EQ(0x1234, result);
209 }
210
211 TEST_F(RendererSchedulerImplTest, TestPostDefaultAndCompositor) {
212 int result = 0;
213 default_task_runner_->PostTask(FROM_HERE,
214 base::Bind(&UnorderedTestTask, 1, &result));
215 compositor_task_runner_->PostTask(FROM_HERE,
216 base::Bind(&UnorderedTestTask, 2, &result));
217 RunUntilIdle();
218 EXPECT_EQ(3, result);
219 }
220
221 TEST_F(RendererSchedulerImplTest, TestRentrantTask) {
222 int count = 0;
223 std::vector<int> order;
224 default_task_runner_->PostTask(FROM_HERE,
225 base::Bind(AppendToVectorReentrantTask,
226 default_task_runner_,
227 &order,
228 &count,
229 5));
230 RunUntilIdle();
231
232 EXPECT_THAT(order, testing::ElementsAre(0, 1, 2, 3, 4));
233 }
234
235 TEST_F(RendererSchedulerImplTest, TestPostIdleTask) {
236 bool task_run = false;
237 base::TimeTicks expected_deadline =
238 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(2300);
239
240 clock_->Advance(base::TimeDelta::FromMilliseconds(100));
241 idle_task_runner_->PostIdleTask(
242 FROM_HERE, base::Bind(&IdleTestTask, &task_run, expected_deadline));
243
244 RunUntilIdle();
245 EXPECT_FALSE(task_run); // Shouldn't run yet as no WillBeginFrame.
246
247 scheduler_->WillBeginFrame(
248 cc::BeginFrameArgs::Create(clock_->NowTicks(),
249 base::TimeTicks(),
250 base::TimeDelta::FromMilliseconds(1000)));
251 RunUntilIdle();
252 EXPECT_FALSE(task_run); // Shouldn't run as no didCommitFrameToCompositor.
253
254 clock_->Advance(base::TimeDelta::FromMilliseconds(1200));
255 scheduler_->DidCommitFrameToCompositor();
256 RunUntilIdle();
257 EXPECT_FALSE(task_run); // We missed the deadline.
258
259 scheduler_->WillBeginFrame(
260 cc::BeginFrameArgs::Create(clock_->NowTicks(),
261 base::TimeTicks(),
262 base::TimeDelta::FromMilliseconds(1000)));
263 clock_->Advance(base::TimeDelta::FromMilliseconds(800));
264 scheduler_->DidCommitFrameToCompositor();
265 RunUntilIdle();
266 EXPECT_TRUE(task_run);
267 }
268
269 TEST_F(RendererSchedulerImplTest, TestRepostingIdleTask) {
270 int run_count = 0;
271
272 idle_task_runner_->PostIdleTask(
273 FROM_HERE,
274 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count));
275 EnableIdleTasks();
276 RunUntilIdle();
277 EXPECT_EQ(1, run_count);
278
279 // Reposted tasks shouldn't run until next idle period.
280 RunUntilIdle();
281 EXPECT_EQ(1, run_count);
282
283 EnableIdleTasks();
284 RunUntilIdle();
285 EXPECT_EQ(2, run_count);
286 }
287
288 TEST_F(RendererSchedulerImplTest, TestDefaultPolicy) {
289 std::vector<std::string> order;
290
291 idle_task_runner_->PostIdleTask(
292 FROM_HERE,
293 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1")));
294 default_task_runner_->PostTask(
295 FROM_HERE,
296 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
297 compositor_task_runner_->PostTask(
298 FROM_HERE,
299 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
300 default_task_runner_->PostTask(
301 FROM_HERE,
302 base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
303 compositor_task_runner_->PostTask(
304 FROM_HERE,
305 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
306
307 EnableIdleTasks();
308 RunUntilIdle();
309 EXPECT_THAT(order,
310 testing::ElementsAre(std::string("D1"),
311 std::string("C1"),
312 std::string("D2"),
313 std::string("C2"),
314 std::string("I1")));
315 }
316
317 TEST_F(RendererSchedulerImplTest, TestCompositorPolicy) {
318 std::vector<std::string> order;
319
320 idle_task_runner_->PostIdleTask(
321 FROM_HERE,
322 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1")));
323 default_task_runner_->PostTask(
324 FROM_HERE,
325 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
326 compositor_task_runner_->PostTask(
327 FROM_HERE,
328 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
329 default_task_runner_->PostTask(
330 FROM_HERE,
331 base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
332 compositor_task_runner_->PostTask(
333 FROM_HERE,
334 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
335
336 scheduler_->DidReceiveInputEvent();
337 EnableIdleTasks();
338 RunUntilIdle();
339 EXPECT_THAT(order,
340 testing::ElementsAre(std::string("C1"),
341 std::string("C2"),
342 std::string("D1"),
343 std::string("D2"),
344 std::string("I1")));
345 }
346
347 TEST_F(RendererSchedulerImplTest,
348 TestCompositorPolicyDoesNotStarveDefaultTasks) {
349 std::vector<std::string> order;
350
351 default_task_runner_->PostTask(
352 FROM_HERE,
353 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
354 compositor_task_runner_->PostTask(
355 FROM_HERE,
356 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
357 for (int i = 0; i < 20; i++) {
358 compositor_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
359 }
360 compositor_task_runner_->PostTask(
361 FROM_HERE,
362 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
363
364 scheduler_->DidReceiveInputEvent();
365 RunUntilIdle();
366 // Ensure that the default D1 task gets to run at some point before the final
367 // C2 compositor task.
368 EXPECT_THAT(order,
369 testing::ElementsAre(
370 std::string("C1"), std::string("D1"), std::string("C2")));
371 }
372
373 TEST_F(RendererSchedulerImplTest, TestCompositorPolicyEnds) {
374 std::vector<std::string> order;
375
376 default_task_runner_->PostTask(
377 FROM_HERE,
378 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
379 compositor_task_runner_->PostTask(
380 FROM_HERE,
381 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
382 default_task_runner_->PostTask(
383 FROM_HERE,
384 base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
385 compositor_task_runner_->PostTask(
386 FROM_HERE,
387 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
388
389 scheduler_->DidReceiveInputEvent();
390 RunUntilIdle();
391 EXPECT_THAT(order,
392 testing::ElementsAre(std::string("C1"),
393 std::string("C2"),
394 std::string("D1"),
395 std::string("D2")));
396
397 order.clear();
398 clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
399
400 default_task_runner_->PostTask(
401 FROM_HERE,
402 base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
403 compositor_task_runner_->PostTask(
404 FROM_HERE,
405 base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
406 default_task_runner_->PostTask(
407 FROM_HERE,
408 base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
409 compositor_task_runner_->PostTask(
410 FROM_HERE,
411 base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
412
413 // Compositor policy mode should have ended now that the clock has advanced.
414 RunUntilIdle();
415 EXPECT_THAT(order,
416 testing::ElementsAre(std::string("D1"),
417 std::string("C1"),
418 std::string("D2"),
419 std::string("C2")));
420 }
421
422 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698