Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / content / renderer / scheduler / renderer_scheduler_impl_unittest.cc
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