Infobar material design refresh: bg color
[chromium-blink-merge.git] / cc / scheduler / delay_based_time_source_unittest.cc
blob948e0205bbfa15537a7012886652a6a45cab626a
1 // Copyright 2011 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.
5 #include "cc/scheduler/delay_based_time_source.h"
7 #include "base/basictypes.h"
8 #include "base/test/test_simple_task_runner.h"
9 #include "cc/test/scheduler_test_common.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace cc {
13 namespace {
15 base::TimeDelta Interval() {
16 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond /
17 60);
20 TEST(DelayBasedTimeSourceTest, TaskPostedAndTickCalled) {
21 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
22 new base::TestSimpleTaskRunner;
23 FakeDelayBasedTimeSourceClient client;
24 scoped_ptr<FakeDelayBasedTimeSource> timer =
25 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
26 timer->SetClient(&client);
28 timer->SetActive(true);
29 EXPECT_TRUE(timer->Active());
30 EXPECT_TRUE(task_runner->HasPendingTask());
32 timer->SetNow(timer->Now() + base::TimeDelta::FromMilliseconds(16));
33 task_runner->RunPendingTasks();
34 EXPECT_TRUE(timer->Active());
35 EXPECT_TRUE(client.TickCalled());
38 TEST(DelayBasedTimeSourceTest, TickNotCalledWithTaskPosted) {
39 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
40 new base::TestSimpleTaskRunner;
41 FakeDelayBasedTimeSourceClient client;
42 scoped_ptr<FakeDelayBasedTimeSource> timer =
43 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
44 timer->SetClient(&client);
45 timer->SetActive(true);
46 EXPECT_TRUE(task_runner->HasPendingTask());
47 timer->SetActive(false);
48 task_runner->RunPendingTasks();
49 EXPECT_FALSE(client.TickCalled());
52 TEST(DelayBasedTimeSourceTest, StartTwiceEnqueuesOneTask) {
53 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
54 new base::TestSimpleTaskRunner;
55 FakeDelayBasedTimeSourceClient client;
56 scoped_ptr<FakeDelayBasedTimeSource> timer =
57 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
58 timer->SetClient(&client);
59 timer->SetActive(true);
60 EXPECT_TRUE(task_runner->HasPendingTask());
61 task_runner->ClearPendingTasks();
62 timer->SetActive(true);
63 EXPECT_FALSE(task_runner->HasPendingTask());
66 TEST(DelayBasedTimeSourceTest, StartWhenRunningDoesntTick) {
67 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
68 new base::TestSimpleTaskRunner;
69 FakeDelayBasedTimeSourceClient client;
70 scoped_ptr<FakeDelayBasedTimeSource> timer =
71 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
72 timer->SetClient(&client);
73 timer->SetActive(true);
74 EXPECT_TRUE(task_runner->HasPendingTask());
75 task_runner->RunPendingTasks();
76 task_runner->ClearPendingTasks();
77 timer->SetActive(true);
78 EXPECT_FALSE(task_runner->HasPendingTask());
81 // At 60Hz, when the tick returns at exactly the requested next time, make sure
82 // a 16ms next delay is posted.
83 TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenExactlyOnRequestedTime) {
84 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
85 new base::TestSimpleTaskRunner;
86 FakeDelayBasedTimeSourceClient client;
87 scoped_ptr<FakeDelayBasedTimeSource> timer =
88 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
89 timer->SetClient(&client);
90 timer->SetActive(true);
91 // Run the first tick.
92 task_runner->RunPendingTasks();
94 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
96 timer->SetNow(timer->Now() + Interval());
97 task_runner->RunPendingTasks();
99 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
102 // At 60Hz, when the tick returns at slightly after the requested next time,
103 // make sure a 16ms next delay is posted.
104 TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenSlightlyAfterRequestedTime) {
105 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
106 new base::TestSimpleTaskRunner;
107 FakeDelayBasedTimeSourceClient client;
108 scoped_ptr<FakeDelayBasedTimeSource> timer =
109 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
110 timer->SetClient(&client);
111 timer->SetActive(true);
112 // Run the first tick.
113 task_runner->RunPendingTasks();
115 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
117 timer->SetNow(timer->Now() + Interval() +
118 base::TimeDelta::FromMicroseconds(1));
119 task_runner->RunPendingTasks();
121 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
124 // At 60Hz, when the tick returns at exactly 2*interval after the requested next
125 // time, make sure a 0ms next delay is posted.
126 TEST(DelayBasedTimeSourceTest,
127 NextDelaySaneWhenExactlyTwiceAfterRequestedTime) {
128 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
129 new base::TestSimpleTaskRunner;
130 FakeDelayBasedTimeSourceClient client;
131 scoped_ptr<FakeDelayBasedTimeSource> timer =
132 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
133 timer->SetClient(&client);
134 timer->SetActive(true);
135 // Run the first tick.
136 task_runner->RunPendingTasks();
138 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
140 timer->SetNow(timer->Now() + 2 * Interval());
141 task_runner->RunPendingTasks();
143 EXPECT_EQ(0, task_runner->NextPendingTaskDelay().InMilliseconds());
146 // At 60Hz, when the tick returns at 2*interval and a bit after the requested
147 // next time, make sure a 16ms next delay is posted.
148 TEST(DelayBasedTimeSourceTest,
149 NextDelaySaneWhenSlightlyAfterTwiceRequestedTime) {
150 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
151 new base::TestSimpleTaskRunner;
152 FakeDelayBasedTimeSourceClient client;
153 scoped_ptr<FakeDelayBasedTimeSource> timer =
154 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
155 timer->SetClient(&client);
156 timer->SetActive(true);
157 // Run the first tick.
158 task_runner->RunPendingTasks();
160 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
162 timer->SetNow(timer->Now() + 2 * Interval() +
163 base::TimeDelta::FromMicroseconds(1));
164 task_runner->RunPendingTasks();
166 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
169 // At 60Hz, when the tick returns halfway to the next frame time, make sure
170 // a correct next delay value is posted.
171 TEST(DelayBasedTimeSourceTest, NextDelaySaneWhenHalfAfterRequestedTime) {
172 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
173 new base::TestSimpleTaskRunner;
174 FakeDelayBasedTimeSourceClient client;
175 scoped_ptr<FakeDelayBasedTimeSource> timer =
176 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
177 timer->SetClient(&client);
178 timer->SetActive(true);
179 // Run the first tick.
180 task_runner->RunPendingTasks();
182 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
184 timer->SetNow(timer->Now() + Interval() +
185 base::TimeDelta::FromMilliseconds(8));
186 task_runner->RunPendingTasks();
188 EXPECT_EQ(8, task_runner->NextPendingTaskDelay().InMilliseconds());
191 // If the timebase and interval are updated with a jittery source, we want to
192 // make sure we do not double tick.
193 TEST(DelayBasedTimeSourceTest, SaneHandlingOfJitteryTimebase) {
194 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
195 new base::TestSimpleTaskRunner;
196 FakeDelayBasedTimeSourceClient client;
197 scoped_ptr<FakeDelayBasedTimeSource> timer =
198 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
199 timer->SetClient(&client);
200 timer->SetActive(true);
201 // Run the first tick.
202 task_runner->RunPendingTasks();
204 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
206 // Jitter timebase ~1ms late
207 timer->SetNow(timer->Now() + Interval());
208 timer->SetTimebaseAndInterval(
209 timer->Now() + base::TimeDelta::FromMilliseconds(1), Interval());
210 task_runner->RunPendingTasks();
212 // Without double tick prevention, NextPendingTaskDelay would be 1.
213 EXPECT_EQ(17, task_runner->NextPendingTaskDelay().InMilliseconds());
215 // Jitter timebase ~1ms early
216 timer->SetNow(timer->Now() + Interval());
217 timer->SetTimebaseAndInterval(
218 timer->Now() - base::TimeDelta::FromMilliseconds(1), Interval());
219 task_runner->RunPendingTasks();
221 EXPECT_EQ(15, task_runner->NextPendingTaskDelay().InMilliseconds());
224 TEST(DelayBasedTimeSourceTest, HandlesSignificantTimebaseChangesImmediately) {
225 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
226 new base::TestSimpleTaskRunner;
227 FakeDelayBasedTimeSourceClient client;
228 scoped_ptr<FakeDelayBasedTimeSource> timer =
229 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
230 timer->SetClient(&client);
231 timer->SetActive(true);
232 // Run the first tick.
233 task_runner->RunPendingTasks();
235 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
237 // Tick, then shift timebase by +7ms.
238 timer->SetNow(timer->Now() + Interval());
239 task_runner->RunPendingTasks();
241 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
243 client.Reset();
244 task_runner->ClearPendingTasks();
245 task_runner->RunPendingTasks();
246 base::TimeDelta jitter = base::TimeDelta::FromMilliseconds(7) +
247 base::TimeDelta::FromMicroseconds(1);
248 timer->SetTimebaseAndInterval(timer->Now() + jitter, Interval());
250 EXPECT_FALSE(client.TickCalled()); // Make sure pending tasks were canceled.
251 EXPECT_EQ(16 + 7, task_runner->NextPendingTaskDelay().InMilliseconds());
253 // Tick, then shift timebase by -7ms.
254 timer->SetNow(timer->Now() + Interval() + jitter);
255 task_runner->RunPendingTasks();
257 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
259 client.Reset();
260 task_runner->ClearPendingTasks();
261 task_runner->RunPendingTasks();
262 timer->SetTimebaseAndInterval(base::TimeTicks() + Interval(), Interval());
264 EXPECT_FALSE(client.TickCalled()); // Make sure pending tasks were canceled.
265 EXPECT_EQ(16 - 7, task_runner->NextPendingTaskDelay().InMilliseconds());
268 TEST(DelayBasedTimeSourceTest, HanldlesSignificantIntervalChangesImmediately) {
269 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
270 new base::TestSimpleTaskRunner;
271 FakeDelayBasedTimeSourceClient client;
272 scoped_ptr<FakeDelayBasedTimeSource> timer =
273 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
274 timer->SetClient(&client);
275 timer->SetActive(true);
276 // Run the first tick.
277 task_runner->RunPendingTasks();
279 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
281 // Tick, then double the interval.
282 timer->SetNow(timer->Now() + Interval());
283 task_runner->RunPendingTasks();
285 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
287 client.Reset();
288 task_runner->ClearPendingTasks();
289 task_runner->RunPendingTasks();
290 timer->SetTimebaseAndInterval(base::TimeTicks() + Interval(), Interval() * 2);
292 EXPECT_FALSE(client.TickCalled()); // Make sure pending tasks were canceled.
293 EXPECT_EQ(33, task_runner->NextPendingTaskDelay().InMilliseconds());
295 // Tick, then halve the interval.
296 timer->SetNow(timer->Now() + Interval() * 2);
297 task_runner->RunPendingTasks();
299 EXPECT_EQ(33, task_runner->NextPendingTaskDelay().InMilliseconds());
301 client.Reset();
302 task_runner->ClearPendingTasks();
303 task_runner->RunPendingTasks();
304 timer->SetTimebaseAndInterval(base::TimeTicks() + Interval() * 3, Interval());
306 EXPECT_FALSE(client.TickCalled()); // Make sure pending tasks were canceled.
307 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
310 TEST(DelayBasedTimeSourceTest, JitteryRuntimeWithFutureTimebases) {
311 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
312 new base::TestSimpleTaskRunner;
313 FakeDelayBasedTimeSourceClient client;
314 scoped_ptr<FakeDelayBasedTimeSource> timer =
315 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
316 timer->SetClient(&client);
317 timer->SetActive(true);
319 // Run the first tick.
320 task_runner->RunPendingTasks();
321 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
323 base::TimeTicks future_timebase = timer->Now() + Interval() * 10;
325 // 1ms jitter
326 base::TimeDelta jitter1 = base::TimeDelta::FromMilliseconds(1);
328 // Tick with +1ms of jitter
329 future_timebase += Interval();
330 timer->SetTimebaseAndInterval(future_timebase, Interval());
331 timer->SetNow(timer->Now() + Interval() + jitter1);
332 task_runner->RunPendingTasks();
333 EXPECT_EQ(15, task_runner->NextPendingTaskDelay().InMilliseconds());
335 // Tick with 0ms of jitter
336 future_timebase += Interval();
337 timer->SetTimebaseAndInterval(future_timebase, Interval());
338 timer->SetNow(timer->Now() + Interval() - jitter1);
339 task_runner->RunPendingTasks();
340 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
342 // Tick with -1ms of jitter
343 future_timebase += Interval();
344 timer->SetTimebaseAndInterval(future_timebase, Interval());
345 timer->SetNow(timer->Now() + Interval() - jitter1);
346 task_runner->RunPendingTasks();
347 EXPECT_EQ(17, task_runner->NextPendingTaskDelay().InMilliseconds());
349 // Tick with 0ms of jitter
350 future_timebase += Interval();
351 timer->SetTimebaseAndInterval(future_timebase, Interval());
352 timer->SetNow(timer->Now() + Interval() + jitter1);
353 task_runner->RunPendingTasks();
354 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
356 // 8 ms jitter
357 base::TimeDelta jitter8 = base::TimeDelta::FromMilliseconds(8);
359 // Tick with +8ms of jitter
360 future_timebase += Interval();
361 timer->SetTimebaseAndInterval(future_timebase, Interval());
362 timer->SetNow(timer->Now() + Interval() + jitter8);
363 task_runner->RunPendingTasks();
364 EXPECT_EQ(8, task_runner->NextPendingTaskDelay().InMilliseconds());
366 // Tick with 0ms of jitter
367 future_timebase += Interval();
368 timer->SetTimebaseAndInterval(future_timebase, Interval());
369 timer->SetNow(timer->Now() + Interval() - jitter8);
370 task_runner->RunPendingTasks();
371 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
373 // Tick with -8ms of jitter
374 future_timebase += Interval();
375 timer->SetTimebaseAndInterval(future_timebase, Interval());
376 timer->SetNow(timer->Now() + Interval() - jitter8);
377 task_runner->RunPendingTasks();
378 EXPECT_EQ(24, task_runner->NextPendingTaskDelay().InMilliseconds());
380 // Tick with 0ms of jitter
381 future_timebase += Interval();
382 timer->SetTimebaseAndInterval(future_timebase, Interval());
383 timer->SetNow(timer->Now() + Interval() + jitter8);
384 task_runner->RunPendingTasks();
385 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
387 // 15 ms jitter
388 base::TimeDelta jitter15 = base::TimeDelta::FromMilliseconds(15);
390 // Tick with +15ms jitter
391 future_timebase += Interval();
392 timer->SetTimebaseAndInterval(future_timebase, Interval());
393 timer->SetNow(timer->Now() + Interval() + jitter15);
394 task_runner->RunPendingTasks();
395 EXPECT_EQ(1, task_runner->NextPendingTaskDelay().InMilliseconds());
397 // Tick with 0ms of jitter
398 future_timebase += Interval();
399 timer->SetTimebaseAndInterval(future_timebase, Interval());
400 timer->SetNow(timer->Now() + Interval() - jitter15);
401 task_runner->RunPendingTasks();
402 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
404 // Tick with -15ms of jitter
405 future_timebase += Interval();
406 timer->SetTimebaseAndInterval(future_timebase, Interval());
407 timer->SetNow(timer->Now() + Interval() - jitter15);
408 task_runner->RunPendingTasks();
409 EXPECT_EQ(31, task_runner->NextPendingTaskDelay().InMilliseconds());
411 // Tick with 0ms of jitter
412 future_timebase += Interval();
413 timer->SetTimebaseAndInterval(future_timebase, Interval());
414 timer->SetNow(timer->Now() + Interval() + jitter15);
415 task_runner->RunPendingTasks();
416 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
419 TEST(DelayBasedTimeSourceTest, AchievesTargetRateWithNoNoise) {
420 int num_iterations = 10;
422 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
423 new base::TestSimpleTaskRunner;
424 FakeDelayBasedTimeSourceClient client;
425 scoped_ptr<FakeDelayBasedTimeSource> timer =
426 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
427 timer->SetClient(&client);
428 timer->SetActive(true);
430 double total_frame_time = 0.0;
431 for (int i = 0; i < num_iterations; ++i) {
432 int64 delay_ms = task_runner->NextPendingTaskDelay().InMilliseconds();
434 // accumulate the "delay"
435 total_frame_time += delay_ms / 1000.0;
437 // Run the callback exactly when asked
438 timer->SetNow(timer->Now() + base::TimeDelta::FromMilliseconds(delay_ms));
439 task_runner->RunPendingTasks();
441 double average_interval =
442 total_frame_time / static_cast<double>(num_iterations);
443 EXPECT_NEAR(1.0 / 60.0, average_interval, 0.1);
446 TEST(DelayBasedTimeSourceTest, TestDeactivateWhilePending) {
447 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
448 new base::TestSimpleTaskRunner;
449 FakeDelayBasedTimeSourceClient client;
450 scoped_ptr<FakeDelayBasedTimeSource> timer =
451 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
452 timer->SetClient(&client);
453 timer->SetActive(true); // Should post a task.
454 timer->SetActive(false);
455 timer = NULL;
456 // Should run the posted task without crashing.
457 EXPECT_TRUE(task_runner->HasPendingTask());
458 task_runner->RunPendingTasks();
461 TEST(DelayBasedTimeSourceTest, TestDeactivateAndReactivateBeforeNextTickTime) {
462 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
463 new base::TestSimpleTaskRunner;
464 FakeDelayBasedTimeSourceClient client;
465 scoped_ptr<FakeDelayBasedTimeSource> timer =
466 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
467 timer->SetClient(&client);
469 // Should run the activate task, and pick up a new timebase.
470 timer->SetActive(true);
471 task_runner->RunPendingTasks();
473 // Stop the timer
474 timer->SetActive(false);
476 // Task will be pending anyway, run it
477 task_runner->RunPendingTasks();
479 // Start the timer again, but before the next tick time the timer previously
480 // planned on using. That same tick time should still be targeted.
481 timer->SetNow(timer->Now() + base::TimeDelta::FromMilliseconds(4));
482 timer->SetActive(true);
483 EXPECT_EQ(12, task_runner->NextPendingTaskDelay().InMilliseconds());
486 TEST(DelayBasedTimeSourceTest, TestDeactivateAndReactivateAfterNextTickTime) {
487 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
488 new base::TestSimpleTaskRunner;
489 FakeDelayBasedTimeSourceClient client;
490 scoped_ptr<FakeDelayBasedTimeSource> timer =
491 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
492 timer->SetClient(&client);
494 // Should run the activate task, and pick up a new timebase.
495 timer->SetActive(true);
496 task_runner->RunPendingTasks();
498 // Stop the timer.
499 timer->SetActive(false);
501 // Task will be pending anyway, run it.
502 task_runner->RunPendingTasks();
504 // Start the timer again, but before the next tick time the timer previously
505 // planned on using. That same tick time should still be targeted.
506 timer->SetNow(timer->Now() + base::TimeDelta::FromMilliseconds(20));
507 timer->SetActive(true);
508 EXPECT_EQ(13, task_runner->NextPendingTaskDelay().InMilliseconds());
511 TEST(DelayBasedTimeSourceTest, TestReturnValueWhenTimerIsDeActivated) {
512 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
513 new base::TestSimpleTaskRunner;
514 FakeDelayBasedTimeSourceClient client;
515 scoped_ptr<FakeDelayBasedTimeSource> timer =
516 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
517 timer->SetClient(&client);
519 timer->SetActive(true);
520 task_runner->RunPendingTasks();
522 // SetActive should return empty TimeTicks when the timer is deactivated.
523 base::TimeTicks missed_tick_time = timer->SetActive(false);
524 EXPECT_TRUE(missed_tick_time.is_null());
527 } // namespace
528 } // namespace cc