OLD | NEW |
---|---|
(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.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 { | |
Sami
2014/10/24 10:46:13
I wonder if we could just reuse cc/test/ordered_si
rmcilroy
2014/10/24 14:58:29
I'll look into whether this is possible.
| |
17 public: | |
18 DelaySupportingTestSimpleTaskRunner(base::SimpleTestTickClock* clock) | |
19 : clock_(clock) { } | |
20 | |
21 virtual bool PostDelayedTask( | |
22 const tracked_objects::Location& from_here, | |
23 const base::Closure& task, | |
24 base::TimeDelta delay) override { | |
25 DCHECK(thread_checker_.CalledOnValidThread()); | |
26 pending_tasks_.push_back( | |
27 base::TestPendingTask(from_here, task, clock_->NowTicks(), delay, | |
28 base::TestPendingTask::NESTABLE)); | |
29 return true; | |
30 } | |
31 | |
32 virtual bool PostNonNestableDelayedTask( | |
33 const tracked_objects::Location& from_here, | |
34 const base::Closure& task, | |
35 base::TimeDelta delay) override { | |
36 DCHECK(thread_checker_.CalledOnValidThread()); | |
37 pending_tasks_.push_back( | |
38 base::TestPendingTask(from_here, task, clock_->NowTicks(), delay, | |
39 base::TestPendingTask::NON_NESTABLE)); | |
40 return true; | |
41 } | |
42 | |
43 void RunPendingTasksIfNotDelayed() { | |
44 DCHECK(thread_checker_.CalledOnValidThread()); | |
45 // Swap with a local variable to avoid re-entrancy problems. | |
46 std::deque<base::TestPendingTask> tasks_to_run; | |
47 tasks_to_run.swap(pending_tasks_); | |
48 for (std::deque<base::TestPendingTask>::iterator it = tasks_to_run.begin(); | |
49 it != tasks_to_run.end(); ++it) { | |
50 if (it->GetTimeToRun() <= clock_->NowTicks()) { | |
51 it->task.Run(); | |
52 } else { | |
53 pending_tasks_.push_front(*it); | |
54 } | |
55 } | |
56 } | |
57 | |
58 void RunUntilTasksAreAllDelayed() { | |
59 DCHECK(thread_checker_.CalledOnValidThread()); | |
60 while (!pending_tasks_.empty() && | |
61 pending_tasks_.front().GetTimeToRun() <= clock_->NowTicks()) { | |
62 RunPendingTasksIfNotDelayed(); | |
63 } | |
64 } | |
65 | |
66 protected: | |
67 virtual ~DelaySupportingTestSimpleTaskRunner() { } | |
68 | |
69 private: | |
70 base::SimpleTestTickClock* clock_; | |
71 }; | |
72 | |
73 class RendererSchedulerForTest : public RendererScheduler { | |
74 public: | |
75 RendererSchedulerForTest( | |
76 scoped_refptr<base::TestSimpleTaskRunner> task_runner, | |
77 base::SimpleTestTickClock* clock) | |
78 : RendererScheduler(task_runner), | |
79 clock_(clock) { } | |
80 virtual ~RendererSchedulerForTest() { } | |
81 | |
82 protected: | |
83 virtual base::TimeTicks Now() const override { | |
84 return clock_->NowTicks(); | |
85 } | |
86 | |
87 private: | |
88 base::SimpleTestTickClock* clock_; | |
89 }; | |
90 | |
91 class RendererSchedulerTest : public testing::Test { | |
92 public: | |
93 RendererSchedulerTest() | |
94 : clock_(new base::SimpleTestTickClock()), | |
95 mock_task_runner_(new DelaySupportingTestSimpleTaskRunner(clock_.get())), | |
96 scheduler_(new RendererSchedulerForTest(mock_task_runner_, clock_.get())), | |
97 default_task_runner_(scheduler_->DefaultTaskRunner()), | |
98 compositor_task_runner_(scheduler_->CompositorTaskRunner()), | |
99 idle_task_runner_(scheduler_->IdleTaskRunner()) { } | |
100 virtual ~RendererSchedulerTest() { } | |
101 | |
102 void RunUntilIdle() { | |
103 mock_task_runner_->RunUntilTasksAreAllDelayed(); | |
104 } | |
105 | |
106 void EnableIdleTasks() { | |
107 scheduler_->WillBeginFrame( | |
108 cc::BeginFrameArgs::Create(clock_->NowTicks(), | |
109 base::TimeTicks(), | |
110 base::TimeDelta::FromMilliseconds(1000))); | |
111 clock_->Advance(base::TimeDelta::FromMilliseconds(800)); | |
112 scheduler_->DidCommitFrameToCompositor(); | |
113 } | |
114 | |
115 protected: | |
116 virtual void SetUp() override { | |
117 // Ensure clock is non-zero. | |
118 clock_->Advance(base::TimeDelta::FromMilliseconds(5000)); | |
119 } | |
120 | |
121 scoped_ptr<base::SimpleTestTickClock> clock_; | |
122 scoped_refptr<DelaySupportingTestSimpleTaskRunner> mock_task_runner_; | |
123 | |
124 scoped_ptr<RendererScheduler> scheduler_; | |
125 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; | |
126 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; | |
127 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; | |
128 | |
129 DISALLOW_COPY_AND_ASSIGN(RendererSchedulerTest); | |
130 }; | |
131 | |
132 void OrderedTestTask(int value, int* result) { | |
133 *result = (*result << 4) | value; | |
134 } | |
135 | |
136 void UnorderedTestTask(int value, int* result) { | |
137 *result += value; | |
138 } | |
139 | |
140 void AppendToVectorTestTask( | |
141 std::vector<std::string>* vector, std::string value) { | |
142 vector->push_back(value); | |
143 } | |
144 | |
145 void AppendToVectorIdleTestTask( | |
146 std::vector<std::string>* vector, | |
147 std::string value, | |
148 base::TimeTicks deadline) { | |
149 AppendToVectorTestTask(vector, value); | |
150 } | |
151 | |
152 void IdleTestTask( | |
153 bool* task_run, | |
154 base::TimeTicks expected_deadline, | |
155 base::TimeTicks deadline) { | |
156 EXPECT_FALSE(*task_run); | |
157 EXPECT_EQ(expected_deadline, deadline); | |
158 *task_run = true; | |
159 } | |
160 | |
161 void RepostingIdleTestTask( | |
162 scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner, | |
163 int* run_count, | |
164 base::TimeTicks deadline) { | |
165 if (*run_count == 0) | |
166 idle_task_runner->PostIdleTask(FROM_HERE, | |
167 base::Bind(&RepostingIdleTestTask, idle_task_runner, run_count)); | |
168 (*run_count)++; | |
169 } | |
170 | |
171 TEST_F(RendererSchedulerTest, TestPostDefaultTask) { | |
172 int result = 0; | |
173 default_task_runner_->PostTask(FROM_HERE, | |
174 base::Bind(OrderedTestTask, 1, &result)); | |
175 default_task_runner_->PostTask(FROM_HERE, | |
176 base::Bind(OrderedTestTask, 2, &result)); | |
177 default_task_runner_->PostTask(FROM_HERE, | |
178 base::Bind(OrderedTestTask, 3, &result)); | |
179 default_task_runner_->PostTask(FROM_HERE, | |
180 base::Bind(OrderedTestTask, 4, &result)); | |
181 RunUntilIdle(); | |
182 EXPECT_EQ(0x1234, result); | |
183 } | |
184 | |
185 TEST_F(RendererSchedulerTest, TestPostDefaultAndCompositor) { | |
186 int result = 0; | |
187 default_task_runner_->PostTask(FROM_HERE, | |
188 base::Bind(&UnorderedTestTask, 1, &result)); | |
189 compositor_task_runner_->PostTask(FROM_HERE, | |
190 base::Bind(&UnorderedTestTask, 2, &result)); | |
191 RunUntilIdle(); | |
192 EXPECT_EQ(3, result); | |
193 } | |
194 | |
195 TEST_F(RendererSchedulerTest, TestPostIdleTask) { | |
196 bool task_run = false; | |
197 base::TimeTicks expected_deadline = | |
198 clock_->NowTicks() + base::TimeDelta::FromMilliseconds(2300); | |
199 | |
200 clock_->Advance(base::TimeDelta::FromMilliseconds(100)); | |
201 idle_task_runner_->PostIdleTask(FROM_HERE, | |
202 base::Bind(&IdleTestTask, &task_run, expected_deadline)); | |
203 | |
204 RunUntilIdle(); | |
205 EXPECT_FALSE(task_run); // Shouldn't run yet as no WillBeginFrame. | |
206 | |
207 scheduler_->WillBeginFrame( | |
208 cc::BeginFrameArgs::Create(clock_->NowTicks(), | |
209 base::TimeTicks(), | |
210 base::TimeDelta::FromMilliseconds(1000))); | |
211 RunUntilIdle(); | |
212 EXPECT_FALSE(task_run); // Shouldn't run as no didCommitFrameToCompositor. | |
213 | |
214 clock_->Advance(base::TimeDelta::FromMilliseconds(1200)); | |
215 scheduler_->DidCommitFrameToCompositor(); | |
216 RunUntilIdle(); | |
217 EXPECT_FALSE(task_run); // We missed the deadline. | |
218 | |
219 scheduler_->WillBeginFrame( | |
220 cc::BeginFrameArgs::Create(clock_->NowTicks(), | |
221 base::TimeTicks(), | |
222 base::TimeDelta::FromMilliseconds(1000))); | |
223 clock_->Advance(base::TimeDelta::FromMilliseconds(800)); | |
224 scheduler_->DidCommitFrameToCompositor(); | |
225 RunUntilIdle(); | |
226 EXPECT_TRUE(task_run); | |
227 } | |
228 | |
229 TEST_F(RendererSchedulerTest, TestRepostingIdleTask) { | |
230 int run_count = 0; | |
231 | |
232 idle_task_runner_->PostIdleTask(FROM_HERE, | |
233 base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count)); | |
234 EnableIdleTasks(); | |
235 RunUntilIdle(); | |
236 EXPECT_EQ(1, run_count); | |
237 | |
238 // Reposted tasks shouldn't run until next idle period. | |
239 RunUntilIdle(); | |
240 EXPECT_EQ(1, run_count); | |
241 | |
242 EnableIdleTasks(); | |
243 RunUntilIdle(); | |
244 EXPECT_EQ(2, run_count); | |
245 } | |
246 | |
247 TEST_F(RendererSchedulerTest, TestDefaultPolicy) { | |
248 std::vector<std::string> order; | |
249 | |
250 idle_task_runner_->PostIdleTask(FROM_HERE, | |
251 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1"))); | |
252 default_task_runner_->PostTask(FROM_HERE, | |
253 base::Bind(&AppendToVectorTestTask, &order, std::string("D1"))); | |
254 compositor_task_runner_->PostTask(FROM_HERE, | |
255 base::Bind(&AppendToVectorTestTask, &order, std::string("C1"))); | |
256 default_task_runner_->PostTask(FROM_HERE, | |
257 base::Bind(&AppendToVectorTestTask, &order, std::string("D2"))); | |
258 compositor_task_runner_->PostTask(FROM_HERE, | |
259 base::Bind(&AppendToVectorTestTask, &order, std::string("C2"))); | |
260 | |
261 EnableIdleTasks(); | |
262 RunUntilIdle(); | |
263 EXPECT_THAT(order, testing::ElementsAre( | |
264 std::string("D1"), std::string("C1"), std::string("D2"), | |
265 std::string("C2"), std::string("I1"))); | |
266 } | |
267 | |
268 TEST_F(RendererSchedulerTest, TestCompositorPolicy) { | |
269 std::vector<std::string> order; | |
270 | |
271 idle_task_runner_->PostIdleTask(FROM_HERE, | |
272 base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1"))); | |
273 default_task_runner_->PostTask(FROM_HERE, | |
274 base::Bind(&AppendToVectorTestTask, &order, std::string("D1"))); | |
275 compositor_task_runner_->PostTask(FROM_HERE, | |
276 base::Bind(&AppendToVectorTestTask, &order, std::string("C1"))); | |
277 default_task_runner_->PostTask(FROM_HERE, | |
278 base::Bind(&AppendToVectorTestTask, &order, std::string("D2"))); | |
279 compositor_task_runner_->PostTask(FROM_HERE, | |
280 base::Bind(&AppendToVectorTestTask, &order, std::string("C2"))); | |
281 | |
282 scheduler_->DidReceiveInputEvent(); | |
283 EnableIdleTasks(); | |
284 RunUntilIdle(); | |
285 EXPECT_THAT(order, testing::ElementsAre( | |
286 std::string("C1"), std::string("C2"), std::string("D1"), | |
287 std::string("D2"), std::string("I1"))); | |
288 } | |
289 | |
290 } // namespace content | |
OLD | NEW |