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.
4
5 #include "cc/scheduler/delay_based_time_source.h"
6
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"
11
12 namespace cc {
13 namespace {
14
Interval()15 base::TimeDelta Interval() {
16 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond /
17 60);
18 }
19
TEST(DelayBasedTimeSourceTest,TaskPostedAndTickCalled)20 TEST(DelayBasedTimeSourceTest, TaskPostedAndTickCalled) {
21 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
22 new base::TestSimpleTaskRunner;
23 FakeTimeSourceClient client;
24 scoped_refptr<FakeDelayBasedTimeSource> timer =
25 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
26 timer->SetClient(&client);
27
28 timer->SetActive(true);
29 EXPECT_TRUE(timer->Active());
30 EXPECT_TRUE(task_runner->HasPendingTask());
31
32 timer->SetNow(timer->Now() + base::TimeDelta::FromMilliseconds(16));
33 task_runner->RunPendingTasks();
34 EXPECT_TRUE(timer->Active());
35 EXPECT_TRUE(client.TickCalled());
36 }
37
TEST(DelayBasedTimeSource,TickNotCalledWithTaskPosted)38 TEST(DelayBasedTimeSource, TickNotCalledWithTaskPosted) {
39 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
40 new base::TestSimpleTaskRunner;
41 FakeTimeSourceClient client;
42 scoped_refptr<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());
50 }
51
TEST(DelayBasedTimeSource,StartTwiceEnqueuesOneTask)52 TEST(DelayBasedTimeSource, StartTwiceEnqueuesOneTask) {
53 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
54 new base::TestSimpleTaskRunner;
55 FakeTimeSourceClient client;
56 scoped_refptr<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());
64 }
65
TEST(DelayBasedTimeSource,StartWhenRunningDoesntTick)66 TEST(DelayBasedTimeSource, StartWhenRunningDoesntTick) {
67 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
68 new base::TestSimpleTaskRunner;
69 FakeTimeSourceClient client;
70 scoped_refptr<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());
79 }
80
81 // At 60Hz, when the tick returns at exactly the requested next time, make sure
82 // a 16ms next delay is posted.
TEST(DelayBasedTimeSource,NextDelaySaneWhenExactlyOnRequestedTime)83 TEST(DelayBasedTimeSource, NextDelaySaneWhenExactlyOnRequestedTime) {
84 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
85 new base::TestSimpleTaskRunner;
86 FakeTimeSourceClient client;
87 scoped_refptr<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();
93
94 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
95
96 timer->SetNow(timer->Now() + Interval());
97 task_runner->RunPendingTasks();
98
99 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
100 }
101
102 // At 60Hz, when the tick returns at slightly after the requested next time,
103 // make sure a 16ms next delay is posted.
TEST(DelayBasedTimeSource,NextDelaySaneWhenSlightlyAfterRequestedTime)104 TEST(DelayBasedTimeSource, NextDelaySaneWhenSlightlyAfterRequestedTime) {
105 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
106 new base::TestSimpleTaskRunner;
107 FakeTimeSourceClient client;
108 scoped_refptr<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();
114
115 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
116
117 timer->SetNow(timer->Now() + Interval() +
118 base::TimeDelta::FromMicroseconds(1));
119 task_runner->RunPendingTasks();
120
121 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
122 }
123
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.
TEST(DelayBasedTimeSource,NextDelaySaneWhenExactlyTwiceAfterRequestedTime)126 TEST(DelayBasedTimeSource, NextDelaySaneWhenExactlyTwiceAfterRequestedTime) {
127 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
128 new base::TestSimpleTaskRunner;
129 FakeTimeSourceClient client;
130 scoped_refptr<FakeDelayBasedTimeSource> timer =
131 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
132 timer->SetClient(&client);
133 timer->SetActive(true);
134 // Run the first tick.
135 task_runner->RunPendingTasks();
136
137 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
138
139 timer->SetNow(timer->Now() + 2 * Interval());
140 task_runner->RunPendingTasks();
141
142 EXPECT_EQ(0, task_runner->NextPendingTaskDelay().InMilliseconds());
143 }
144
145 // At 60Hz, when the tick returns at 2*interval and a bit after the requested
146 // next time, make sure a 16ms next delay is posted.
TEST(DelayBasedTimeSource,NextDelaySaneWhenSlightlyAfterTwiceRequestedTime)147 TEST(DelayBasedTimeSource, NextDelaySaneWhenSlightlyAfterTwiceRequestedTime) {
148 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
149 new base::TestSimpleTaskRunner;
150 FakeTimeSourceClient client;
151 scoped_refptr<FakeDelayBasedTimeSource> timer =
152 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
153 timer->SetClient(&client);
154 timer->SetActive(true);
155 // Run the first tick.
156 task_runner->RunPendingTasks();
157
158 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
159
160 timer->SetNow(timer->Now() + 2 * Interval() +
161 base::TimeDelta::FromMicroseconds(1));
162 task_runner->RunPendingTasks();
163
164 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
165 }
166
167 // At 60Hz, when the tick returns halfway to the next frame time, make sure
168 // a correct next delay value is posted.
TEST(DelayBasedTimeSource,NextDelaySaneWhenHalfAfterRequestedTime)169 TEST(DelayBasedTimeSource, NextDelaySaneWhenHalfAfterRequestedTime) {
170 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
171 new base::TestSimpleTaskRunner;
172 FakeTimeSourceClient client;
173 scoped_refptr<FakeDelayBasedTimeSource> timer =
174 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
175 timer->SetClient(&client);
176 timer->SetActive(true);
177 // Run the first tick.
178 task_runner->RunPendingTasks();
179
180 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
181
182 timer->SetNow(timer->Now() + Interval() +
183 base::TimeDelta::FromMilliseconds(8));
184 task_runner->RunPendingTasks();
185
186 EXPECT_EQ(8, task_runner->NextPendingTaskDelay().InMilliseconds());
187 }
188
189 // If the timebase and interval are updated with a jittery source, we want to
190 // make sure we do not double tick.
TEST(DelayBasedTimeSource,SaneHandlingOfJitteryTimebase)191 TEST(DelayBasedTimeSource, SaneHandlingOfJitteryTimebase) {
192 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
193 new base::TestSimpleTaskRunner;
194 FakeTimeSourceClient client;
195 scoped_refptr<FakeDelayBasedTimeSource> timer =
196 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
197 timer->SetClient(&client);
198 timer->SetActive(true);
199 // Run the first tick.
200 task_runner->RunPendingTasks();
201
202 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
203
204 // Jitter timebase ~1ms late
205 timer->SetNow(timer->Now() + Interval());
206 timer->SetTimebaseAndInterval(
207 timer->Now() + base::TimeDelta::FromMilliseconds(1), Interval());
208 task_runner->RunPendingTasks();
209
210 // Without double tick prevention, NextPendingTaskDelay would be 1.
211 EXPECT_EQ(17, task_runner->NextPendingTaskDelay().InMilliseconds());
212
213 // Jitter timebase ~1ms early
214 timer->SetNow(timer->Now() + Interval());
215 timer->SetTimebaseAndInterval(
216 timer->Now() - base::TimeDelta::FromMilliseconds(1), Interval());
217 task_runner->RunPendingTasks();
218
219 EXPECT_EQ(15, task_runner->NextPendingTaskDelay().InMilliseconds());
220 }
221
TEST(DelayBasedTimeSource,HandlesSignificantTimebaseChangesImmediately)222 TEST(DelayBasedTimeSource, HandlesSignificantTimebaseChangesImmediately) {
223 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
224 new base::TestSimpleTaskRunner;
225 FakeTimeSourceClient client;
226 scoped_refptr<FakeDelayBasedTimeSource> timer =
227 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
228 timer->SetClient(&client);
229 timer->SetActive(true);
230 // Run the first tick.
231 task_runner->RunPendingTasks();
232
233 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
234
235 // Tick, then shift timebase by +7ms.
236 timer->SetNow(timer->Now() + Interval());
237 task_runner->RunPendingTasks();
238
239 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
240
241 client.Reset();
242 task_runner->ClearPendingTasks();
243 task_runner->RunPendingTasks();
244 base::TimeDelta jitter = base::TimeDelta::FromMilliseconds(7) +
245 base::TimeDelta::FromMicroseconds(1);
246 timer->SetTimebaseAndInterval(timer->Now() + jitter, Interval());
247
248 EXPECT_FALSE(client.TickCalled()); // Make sure pending tasks were canceled.
249 EXPECT_EQ(16 + 7, task_runner->NextPendingTaskDelay().InMilliseconds());
250
251 // Tick, then shift timebase by -7ms.
252 timer->SetNow(timer->Now() + Interval() + jitter);
253 task_runner->RunPendingTasks();
254
255 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
256
257 client.Reset();
258 task_runner->ClearPendingTasks();
259 task_runner->RunPendingTasks();
260 timer->SetTimebaseAndInterval(base::TimeTicks() + Interval(), Interval());
261
262 EXPECT_FALSE(client.TickCalled()); // Make sure pending tasks were canceled.
263 EXPECT_EQ(16 - 7, task_runner->NextPendingTaskDelay().InMilliseconds());
264 }
265
TEST(DelayBasedTimeSource,HanldlesSignificantIntervalChangesImmediately)266 TEST(DelayBasedTimeSource, HanldlesSignificantIntervalChangesImmediately) {
267 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
268 new base::TestSimpleTaskRunner;
269 FakeTimeSourceClient client;
270 scoped_refptr<FakeDelayBasedTimeSource> timer =
271 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
272 timer->SetClient(&client);
273 timer->SetActive(true);
274 // Run the first tick.
275 task_runner->RunPendingTasks();
276
277 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
278
279 // Tick, then double the interval.
280 timer->SetNow(timer->Now() + Interval());
281 task_runner->RunPendingTasks();
282
283 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
284
285 client.Reset();
286 task_runner->ClearPendingTasks();
287 task_runner->RunPendingTasks();
288 timer->SetTimebaseAndInterval(base::TimeTicks() + Interval(), Interval() * 2);
289
290 EXPECT_FALSE(client.TickCalled()); // Make sure pending tasks were canceled.
291 EXPECT_EQ(33, task_runner->NextPendingTaskDelay().InMilliseconds());
292
293 // Tick, then halve the interval.
294 timer->SetNow(timer->Now() + Interval() * 2);
295 task_runner->RunPendingTasks();
296
297 EXPECT_EQ(33, task_runner->NextPendingTaskDelay().InMilliseconds());
298
299 client.Reset();
300 task_runner->ClearPendingTasks();
301 task_runner->RunPendingTasks();
302 timer->SetTimebaseAndInterval(base::TimeTicks() + Interval() * 3, Interval());
303
304 EXPECT_FALSE(client.TickCalled()); // Make sure pending tasks were canceled.
305 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
306 }
307
TEST(DelayBasedTimeSource,JitteryRuntimeWithFutureTimebases)308 TEST(DelayBasedTimeSource, JitteryRuntimeWithFutureTimebases) {
309 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
310 new base::TestSimpleTaskRunner;
311 FakeTimeSourceClient client;
312 scoped_refptr<FakeDelayBasedTimeSource> timer =
313 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
314 timer->SetClient(&client);
315 timer->SetActive(true);
316
317 // Run the first tick.
318 task_runner->RunPendingTasks();
319 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
320
321 base::TimeTicks future_timebase = timer->Now() + Interval() * 10;
322
323 // 1ms jitter
324 base::TimeDelta jitter1 = base::TimeDelta::FromMilliseconds(1);
325
326 // Tick with +1ms of jitter
327 future_timebase += Interval();
328 timer->SetTimebaseAndInterval(future_timebase, Interval());
329 timer->SetNow(timer->Now() + Interval() + jitter1);
330 task_runner->RunPendingTasks();
331 EXPECT_EQ(15, task_runner->NextPendingTaskDelay().InMilliseconds());
332
333 // Tick with 0ms of jitter
334 future_timebase += Interval();
335 timer->SetTimebaseAndInterval(future_timebase, Interval());
336 timer->SetNow(timer->Now() + Interval() - jitter1);
337 task_runner->RunPendingTasks();
338 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
339
340 // Tick with -1ms of jitter
341 future_timebase += Interval();
342 timer->SetTimebaseAndInterval(future_timebase, Interval());
343 timer->SetNow(timer->Now() + Interval() - jitter1);
344 task_runner->RunPendingTasks();
345 EXPECT_EQ(17, task_runner->NextPendingTaskDelay().InMilliseconds());
346
347 // Tick with 0ms of jitter
348 future_timebase += Interval();
349 timer->SetTimebaseAndInterval(future_timebase, Interval());
350 timer->SetNow(timer->Now() + Interval() + jitter1);
351 task_runner->RunPendingTasks();
352 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
353
354 // 8 ms jitter
355 base::TimeDelta jitter8 = base::TimeDelta::FromMilliseconds(8);
356
357 // Tick with +8ms of jitter
358 future_timebase += Interval();
359 timer->SetTimebaseAndInterval(future_timebase, Interval());
360 timer->SetNow(timer->Now() + Interval() + jitter8);
361 task_runner->RunPendingTasks();
362 EXPECT_EQ(8, task_runner->NextPendingTaskDelay().InMilliseconds());
363
364 // Tick with 0ms of jitter
365 future_timebase += Interval();
366 timer->SetTimebaseAndInterval(future_timebase, Interval());
367 timer->SetNow(timer->Now() + Interval() - jitter8);
368 task_runner->RunPendingTasks();
369 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
370
371 // Tick with -8ms of jitter
372 future_timebase += Interval();
373 timer->SetTimebaseAndInterval(future_timebase, Interval());
374 timer->SetNow(timer->Now() + Interval() - jitter8);
375 task_runner->RunPendingTasks();
376 EXPECT_EQ(24, task_runner->NextPendingTaskDelay().InMilliseconds());
377
378 // Tick with 0ms of jitter
379 future_timebase += Interval();
380 timer->SetTimebaseAndInterval(future_timebase, Interval());
381 timer->SetNow(timer->Now() + Interval() + jitter8);
382 task_runner->RunPendingTasks();
383 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
384
385 // 15 ms jitter
386 base::TimeDelta jitter15 = base::TimeDelta::FromMilliseconds(15);
387
388 // Tick with +15ms jitter
389 future_timebase += Interval();
390 timer->SetTimebaseAndInterval(future_timebase, Interval());
391 timer->SetNow(timer->Now() + Interval() + jitter15);
392 task_runner->RunPendingTasks();
393 EXPECT_EQ(1, task_runner->NextPendingTaskDelay().InMilliseconds());
394
395 // Tick with 0ms of jitter
396 future_timebase += Interval();
397 timer->SetTimebaseAndInterval(future_timebase, Interval());
398 timer->SetNow(timer->Now() + Interval() - jitter15);
399 task_runner->RunPendingTasks();
400 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
401
402 // Tick with -15ms of jitter
403 future_timebase += Interval();
404 timer->SetTimebaseAndInterval(future_timebase, Interval());
405 timer->SetNow(timer->Now() + Interval() - jitter15);
406 task_runner->RunPendingTasks();
407 EXPECT_EQ(31, task_runner->NextPendingTaskDelay().InMilliseconds());
408
409 // Tick with 0ms of jitter
410 future_timebase += Interval();
411 timer->SetTimebaseAndInterval(future_timebase, Interval());
412 timer->SetNow(timer->Now() + Interval() + jitter15);
413 task_runner->RunPendingTasks();
414 EXPECT_EQ(16, task_runner->NextPendingTaskDelay().InMilliseconds());
415 }
416
TEST(DelayBasedTimeSourceTest,AchievesTargetRateWithNoNoise)417 TEST(DelayBasedTimeSourceTest, AchievesTargetRateWithNoNoise) {
418 int num_iterations = 10;
419
420 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
421 new base::TestSimpleTaskRunner;
422 FakeTimeSourceClient client;
423 scoped_refptr<FakeDelayBasedTimeSource> timer =
424 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
425 timer->SetClient(&client);
426 timer->SetActive(true);
427
428 double total_frame_time = 0.0;
429 for (int i = 0; i < num_iterations; ++i) {
430 int64 delay_ms = task_runner->NextPendingTaskDelay().InMilliseconds();
431
432 // accumulate the "delay"
433 total_frame_time += delay_ms / 1000.0;
434
435 // Run the callback exactly when asked
436 timer->SetNow(timer->Now() + base::TimeDelta::FromMilliseconds(delay_ms));
437 task_runner->RunPendingTasks();
438 }
439 double average_interval =
440 total_frame_time / static_cast<double>(num_iterations);
441 EXPECT_NEAR(1.0 / 60.0, average_interval, 0.1);
442 }
443
TEST(DelayBasedTimeSource,TestDeactivateWhilePending)444 TEST(DelayBasedTimeSource, TestDeactivateWhilePending) {
445 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
446 new base::TestSimpleTaskRunner;
447 FakeTimeSourceClient client;
448 scoped_refptr<FakeDelayBasedTimeSource> timer =
449 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
450 timer->SetClient(&client);
451 timer->SetActive(true); // Should post a task.
452 timer->SetActive(false);
453 timer = NULL;
454 // Should run the posted task without crashing.
455 EXPECT_TRUE(task_runner->HasPendingTask());
456 task_runner->RunPendingTasks();
457 }
458
TEST(DelayBasedTimeSource,TestDeactivateAndReactivateBeforeNextTickTime)459 TEST(DelayBasedTimeSource, TestDeactivateAndReactivateBeforeNextTickTime) {
460 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
461 new base::TestSimpleTaskRunner;
462 FakeTimeSourceClient client;
463 scoped_refptr<FakeDelayBasedTimeSource> timer =
464 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
465 timer->SetClient(&client);
466
467 // Should run the activate task, and pick up a new timebase.
468 timer->SetActive(true);
469 task_runner->RunPendingTasks();
470
471 // Stop the timer
472 timer->SetActive(false);
473
474 // Task will be pending anyway, run it
475 task_runner->RunPendingTasks();
476
477 // Start the timer again, but before the next tick time the timer previously
478 // planned on using. That same tick time should still be targeted.
479 timer->SetNow(timer->Now() + base::TimeDelta::FromMilliseconds(4));
480 timer->SetActive(true);
481 EXPECT_EQ(12, task_runner->NextPendingTaskDelay().InMilliseconds());
482 }
483
TEST(DelayBasedTimeSource,TestDeactivateAndReactivateAfterNextTickTime)484 TEST(DelayBasedTimeSource, TestDeactivateAndReactivateAfterNextTickTime) {
485 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
486 new base::TestSimpleTaskRunner;
487 FakeTimeSourceClient client;
488 scoped_refptr<FakeDelayBasedTimeSource> timer =
489 FakeDelayBasedTimeSource::Create(Interval(), task_runner.get());
490 timer->SetClient(&client);
491
492 // Should run the activate task, and pick up a new timebase.
493 timer->SetActive(true);
494 task_runner->RunPendingTasks();
495
496 // Stop the timer.
497 timer->SetActive(false);
498
499 // Task will be pending anyway, run it.
500 task_runner->RunPendingTasks();
501
502 // Start the timer again, but before the next tick time the timer previously
503 // planned on using. That same tick time should still be targeted.
504 timer->SetNow(timer->Now() + base::TimeDelta::FromMilliseconds(20));
505 timer->SetActive(true);
506 EXPECT_EQ(13, task_runner->NextPendingTaskDelay().InMilliseconds());
507 }
508
TEST(DelayBasedTimeSource,TestOverflow)509 TEST(DelayBasedTimeSource, TestOverflow) {
510 // int(big_now / interval) < 0, so this causes a crash if the number of
511 // intervals elapsed is attempted to be stored in an int.
512 base::TimeDelta interval = base::TimeDelta::FromInternalValue(4000);
513 base::TimeTicks big_now = base::TimeTicks::FromInternalValue(8635916564000);
514
515 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
516 new base::TestSimpleTaskRunner;
517 FakeTimeSourceClient client;
518 scoped_refptr<FakeDelayBasedTimeSource> timer =
519 FakeDelayBasedTimeSource::Create(interval, task_runner.get());
520 timer->SetClient(&client);
521 timer->SetNow(big_now);
522 timer->SetActive(true);
523 EXPECT_EQ(0, task_runner->NextPendingTaskDelay().InMilliseconds());
524 }
525
526 } // namespace
527 } // namespace cc
528