Don't consider a Bluetooth adapter present until it has an address.
[chromium-blink-merge.git] / cc / CCDelayBasedTimeSourceTest.cpp
blob5e9f49b1d899321b23b8707f9bd0572881a08ed5
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 "config.h"
7 #include "CCDelayBasedTimeSource.h"
9 #include "CCSchedulerTestCommon.h"
10 #include "CCThread.h"
11 #include <gtest/gtest.h>
12 #include <wtf/RefPtr.h>
14 using namespace WTF;
15 using namespace WebCore;
16 using namespace WebKitTests;
18 namespace {
20 TEST(CCDelayBasedTimeSourceTest, TaskPostedAndTickCalled)
22 FakeCCThread thread;
23 FakeCCTimeSourceClient client;
24 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
25 timer->setClient(&client);
27 timer->setMonotonicTimeNow(0);
28 timer->setActive(true);
29 EXPECT_TRUE(timer->active());
30 EXPECT_TRUE(thread.hasPendingTask());
32 timer->setMonotonicTimeNow(0.016);
33 thread.runPendingTask();
34 EXPECT_TRUE(timer->active());
35 EXPECT_TRUE(client.tickCalled());
38 TEST(CCDelayBasedTimeSource, TickNotCalledWithTaskPosted)
40 FakeCCThread thread;
41 FakeCCTimeSourceClient client;
42 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
43 timer->setClient(&client);
44 timer->setActive(true);
45 EXPECT_TRUE(thread.hasPendingTask());
46 timer->setActive(false);
47 thread.runPendingTask();
48 EXPECT_FALSE(client.tickCalled());
51 TEST(CCDelayBasedTimeSource, StartTwiceEnqueuesOneTask)
53 FakeCCThread thread;
54 FakeCCTimeSourceClient client;
55 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
56 timer->setClient(&client);
57 timer->setActive(true);
58 EXPECT_TRUE(thread.hasPendingTask());
59 thread.reset();
60 timer->setActive(true);
61 EXPECT_FALSE(thread.hasPendingTask());
64 TEST(CCDelayBasedTimeSource, StartWhenRunningDoesntTick)
66 FakeCCThread thread;
67 FakeCCTimeSourceClient client;
68 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
69 timer->setClient(&client);
70 timer->setActive(true);
71 thread.runPendingTask();
72 thread.reset();
73 timer->setActive(true);
74 EXPECT_FALSE(thread.hasPendingTask());
77 // At 60Hz, when the tick returns at exactly the requested next time, make sure
78 // a 16ms next delay is posted.
79 TEST(CCDelayBasedTimeSource, NextDelaySaneWhenExactlyOnRequestedTime)
81 FakeCCThread thread;
82 FakeCCTimeSourceClient client;
83 double interval = 1.0 / 60.0;
84 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
85 timer->setClient(&client);
86 timer->setActive(true);
87 // Run the first task, as that activates the timer and picks up a timebase.
88 thread.runPendingTask();
90 EXPECT_EQ(16, thread.pendingDelayMs());
92 timer->setMonotonicTimeNow(interval);
93 thread.runPendingTask();
95 EXPECT_EQ(16, thread.pendingDelayMs());
98 // At 60Hz, when the tick returns at slightly after the requested next time, make sure
99 // a 16ms next delay is posted.
100 TEST(CCDelayBasedTimeSource, NextDelaySaneWhenSlightlyAfterRequestedTime)
102 FakeCCThread thread;
103 FakeCCTimeSourceClient client;
104 double interval = 1.0 / 60.0;
105 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
106 timer->setClient(&client);
107 timer->setActive(true);
108 // Run the first task, as that activates the timer and picks up a timebase.
109 thread.runPendingTask();
111 EXPECT_EQ(16, thread.pendingDelayMs());
113 timer->setMonotonicTimeNow(interval + 0.0000001);
114 thread.runPendingTask();
116 EXPECT_EQ(16, thread.pendingDelayMs());
119 // At 60Hz, when the tick returns at exactly 2*interval after the requested next time, make sure
120 // a 16ms next delay is posted.
121 TEST(CCDelayBasedTimeSource, NextDelaySaneWhenExactlyTwiceAfterRequestedTime)
123 FakeCCThread thread;
124 FakeCCTimeSourceClient client;
125 double interval = 1.0 / 60.0;
126 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
127 timer->setClient(&client);
128 timer->setActive(true);
129 // Run the first task, as that activates the timer and picks up a timebase.
130 thread.runPendingTask();
132 EXPECT_EQ(16, thread.pendingDelayMs());
134 timer->setMonotonicTimeNow(2*interval);
135 thread.runPendingTask();
137 EXPECT_EQ(16, thread.pendingDelayMs());
140 // At 60Hz, when the tick returns at 2*interval and a bit after the requested next time, make sure
141 // a 16ms next delay is posted.
142 TEST(CCDelayBasedTimeSource, NextDelaySaneWhenSlightlyAfterTwiceRequestedTime)
144 FakeCCThread thread;
145 FakeCCTimeSourceClient client;
146 double interval = 1.0 / 60.0;
147 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
148 timer->setClient(&client);
149 timer->setActive(true);
150 // Run the first task, as that activates the timer and picks up a timebase.
151 thread.runPendingTask();
153 EXPECT_EQ(16, thread.pendingDelayMs());
155 timer->setMonotonicTimeNow(2*interval + 0.0000001);
156 thread.runPendingTask();
158 EXPECT_EQ(16, thread.pendingDelayMs());
161 // At 60Hz, when the tick returns halfway to the next frame time, make sure
162 // a correct next delay value is posted.
163 TEST(CCDelayBasedTimeSource, NextDelaySaneWhenHalfAfterRequestedTime)
165 FakeCCThread thread;
166 FakeCCTimeSourceClient client;
167 double interval = 1.0 / 60.0;
168 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
169 timer->setClient(&client);
170 timer->setActive(true);
171 // Run the first task, as that activates the timer and picks up a timebase.
172 thread.runPendingTask();
174 EXPECT_EQ(16, thread.pendingDelayMs());
176 timer->setMonotonicTimeNow(interval + interval * 0.5);
177 thread.runPendingTask();
179 EXPECT_EQ(8, thread.pendingDelayMs());
182 // If the timebase and interval are updated with a jittery source, we want to
183 // make sure we do not double tick.
184 TEST(CCDelayBasedTimeSource, SaneHandlingOfJitteryTimebase)
186 FakeCCThread thread;
187 FakeCCTimeSourceClient client;
188 double interval = 1.0 / 60.0;
189 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
190 timer->setClient(&client);
191 timer->setActive(true);
192 // Run the first task, as that activates the timer and picks up a timebase.
193 thread.runPendingTask();
195 EXPECT_EQ(16, thread.pendingDelayMs());
197 // Jitter timebase ~1ms late
198 timer->setTimebaseAndInterval(interval + 0.001, interval);
199 timer->setMonotonicTimeNow(interval);
200 thread.runPendingTask();
202 // Without double tick prevention, pendingDelayMs would be 1.
203 EXPECT_EQ(17, thread.pendingDelayMs());
205 // Jitter timebase ~1ms early
206 timer->setTimebaseAndInterval(interval * 2 - 0.001, interval);
207 timer->setMonotonicTimeNow(interval * 2);
208 thread.runPendingTask();
210 EXPECT_EQ(15, thread.pendingDelayMs());
213 TEST(CCDelayBasedTimeSource, HanldlesSignificantTimebaseChangesImmediately)
215 FakeCCThread thread;
216 FakeCCTimeSourceClient client;
217 double interval = 1.0 / 60.0;
218 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
219 timer->setClient(&client);
220 timer->setActive(true);
221 // Run the first task, as that activates the timer and picks up a timebase.
222 thread.runPendingTask();
224 EXPECT_EQ(16, thread.pendingDelayMs());
226 // Tick, then shift timebase by +7ms.
227 timer->setMonotonicTimeNow(interval);
228 thread.runPendingTask();
230 EXPECT_EQ(16, thread.pendingDelayMs());
232 client.reset();
233 thread.runPendingTaskOnOverwrite(true);
234 timer->setTimebaseAndInterval(interval + 0.0070001, interval);
235 thread.runPendingTaskOnOverwrite(false);
237 EXPECT_FALSE(client.tickCalled()); // Make sure pending tasks were canceled.
238 EXPECT_EQ(7, thread.pendingDelayMs());
240 // Tick, then shift timebase by -7ms.
241 timer->setMonotonicTimeNow(interval + 0.0070001);
242 thread.runPendingTask();
244 EXPECT_EQ(16, thread.pendingDelayMs());
246 client.reset();
247 thread.runPendingTaskOnOverwrite(true);
248 timer->setTimebaseAndInterval(interval, interval);
249 thread.runPendingTaskOnOverwrite(false);
251 EXPECT_FALSE(client.tickCalled()); // Make sure pending tasks were canceled.
252 EXPECT_EQ(16-7, thread.pendingDelayMs());
255 TEST(CCDelayBasedTimeSource, HanldlesSignificantIntervalChangesImmediately)
257 FakeCCThread thread;
258 FakeCCTimeSourceClient client;
259 double interval = 1.0 / 60.0;
260 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(interval, &thread);
261 timer->setClient(&client);
262 timer->setActive(true);
263 // Run the first task, as that activates the timer and picks up a timebase.
264 thread.runPendingTask();
266 EXPECT_EQ(16, thread.pendingDelayMs());
268 // Tick, then double the interval.
269 timer->setMonotonicTimeNow(interval);
270 thread.runPendingTask();
272 EXPECT_EQ(16, thread.pendingDelayMs());
274 client.reset();
275 thread.runPendingTaskOnOverwrite(true);
276 timer->setTimebaseAndInterval(interval, interval * 2);
277 thread.runPendingTaskOnOverwrite(false);
279 EXPECT_FALSE(client.tickCalled()); // Make sure pending tasks were canceled.
280 EXPECT_EQ(33, thread.pendingDelayMs());
282 // Tick, then halve the interval.
283 timer->setMonotonicTimeNow(interval * 3);
284 thread.runPendingTask();
286 EXPECT_EQ(33, thread.pendingDelayMs());
288 client.reset();
289 thread.runPendingTaskOnOverwrite(true);
290 timer->setTimebaseAndInterval(interval * 3, interval);
291 thread.runPendingTaskOnOverwrite(false);
293 EXPECT_FALSE(client.tickCalled()); // Make sure pending tasks were canceled.
294 EXPECT_EQ(16, thread.pendingDelayMs());
297 TEST(CCDelayBasedTimeSourceTest, AchievesTargetRateWithNoNoise)
299 int numIterations = 1000;
301 FakeCCThread thread;
302 FakeCCTimeSourceClient client;
303 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
304 timer->setClient(&client);
305 timer->setActive(true);
307 double totalFrameTime = 0;
308 for (int i = 0; i < numIterations; ++i) {
309 long long delayMs = thread.pendingDelayMs();
311 // accumulate the "delay"
312 totalFrameTime += delayMs / 1000.0;
314 // Run the callback exactly when asked
315 double now = timer->monotonicTimeNow() + delayMs / 1000.0;
316 timer->setMonotonicTimeNow(now);
317 thread.runPendingTask();
319 double averageInterval = totalFrameTime / static_cast<double>(numIterations);
320 EXPECT_NEAR(1.0 / 60.0, averageInterval, 0.1);
323 TEST(CCDelayBasedTimeSource, TestDeactivateWhilePending)
325 FakeCCThread thread;
326 FakeCCTimeSourceClient client;
327 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
328 timer->setClient(&client);
329 timer->setActive(true); // Should post a task.
330 timer->setActive(false);
331 timer.clear();
332 thread.runPendingTask(); // Should run the posted task without crashing.
335 TEST(CCDelayBasedTimeSource, TestDeactivateAndReactivateBeforeNextTickTime)
337 FakeCCThread thread;
338 FakeCCTimeSourceClient client;
339 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
340 timer->setClient(&client);
342 // Should run the activate task, and pick up a new timebase.
343 timer->setActive(true);
344 timer->setMonotonicTimeNow(0);
345 thread.runPendingTask();
347 // Stop the timer
348 timer->setActive(false);
350 // Task will be pending anyway, run it
351 thread.runPendingTask();
353 // Start the timer again, but before the next tick time the timer previously
354 // planned on using. That same tick time should still be targeted.
355 timer->setMonotonicTimeNow(0.004);
356 timer->setActive(true);
357 EXPECT_EQ(12, thread.pendingDelayMs());
360 TEST(CCDelayBasedTimeSource, TestDeactivateAndReactivateAfterNextTickTime)
362 FakeCCThread thread;
363 FakeCCTimeSourceClient client;
364 RefPtr<FakeCCDelayBasedTimeSource> timer = FakeCCDelayBasedTimeSource::create(1.0 / 60.0, &thread);
365 timer->setClient(&client);
367 // Should run the activate task, and pick up a new timebase.
368 timer->setActive(true);
369 timer->setMonotonicTimeNow(0);
370 thread.runPendingTask();
372 // Stop the timer
373 timer->setActive(false);
375 // Task will be pending anyway, run it
376 thread.runPendingTask();
378 // Start the timer again, but before the next tick time the timer previously
379 // planned on using. That same tick time should still be targeted.
380 timer->setMonotonicTimeNow(0.02);
381 timer->setActive(true);
382 EXPECT_EQ(13, thread.pendingDelayMs());