Add tests to verify accelerators properly work on constrained window.
[chromium-blink-merge.git] / sync / notifier / ack_tracker_unittest.cc
blob9a5c80288ae1fc6f0eaaa562d0252fd37b631718
1 // Copyright (c) 2012 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 "sync/notifier/ack_tracker.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/message_loop.h"
9 #include "google/cacheinvalidation/include/types.h"
10 #include "google/cacheinvalidation/types.pb.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 namespace syncer {
16 namespace {
18 typedef AckTracker::NowCallback NowCallback;
20 class MockTimeProvider : public base::RefCountedThreadSafe<MockTimeProvider> {
21 public:
22 MockTimeProvider() : fake_now_(base::TimeTicks::Now()) {}
24 void LeapForward(int seconds) {
25 ASSERT_GT(seconds, 0);
26 fake_now_ += base::TimeDelta::FromSeconds(seconds);
29 // After the next call to Now(), immediately leap forward by |seconds|.
30 void DelayedLeapForward(int seconds) {
31 ASSERT_GT(seconds, 0);
32 delayed_leap_ = base::TimeDelta::FromSeconds(seconds);
35 base::TimeTicks Now() {
36 base::TimeTicks fake_now = fake_now_;
37 if (delayed_leap_ > base::TimeDelta()) {
38 fake_now_ += delayed_leap_;
39 delayed_leap_ = base::TimeDelta();
41 return fake_now;
44 private:
45 friend class base::RefCountedThreadSafe<MockTimeProvider>;
47 ~MockTimeProvider() {}
49 base::TimeTicks fake_now_;
50 base::TimeDelta delayed_leap_;
53 class FakeBackoffEntry : public net::BackoffEntry {
54 public:
55 FakeBackoffEntry(const Policy* const policy, const NowCallback& now_callback)
56 : BackoffEntry(policy),
57 now_callback_(now_callback) {
60 protected:
61 virtual base::TimeTicks ImplGetTimeNow() const OVERRIDE {
62 return now_callback_.Run();
65 private:
66 NowCallback now_callback_;
69 class MockDelegate : public AckTracker::Delegate {
70 public:
71 MOCK_METHOD1(OnTimeout, void(const ObjectIdSet&));
74 scoped_ptr<net::BackoffEntry> CreateMockEntry(
75 const NowCallback& now_callback,
76 const net::BackoffEntry::Policy* const policy) {
77 return scoped_ptr<net::BackoffEntry>(new FakeBackoffEntry(
78 policy, now_callback));
81 } // namespace
83 class AckTrackerTest : public testing::Test {
84 public:
85 AckTrackerTest()
86 : time_provider_(new MockTimeProvider),
87 ack_tracker_(&delegate_),
88 kIdOne(ipc::invalidation::ObjectSource::TEST, "one"),
89 kIdTwo(ipc::invalidation::ObjectSource::TEST, "two") {
90 ack_tracker_.SetNowCallbackForTest(
91 base::Bind(&MockTimeProvider::Now, time_provider_));
92 ack_tracker_.SetCreateBackoffEntryCallbackForTest(
93 base::Bind(&CreateMockEntry,
94 base::Bind(&MockTimeProvider::Now,
95 time_provider_)));
98 protected:
99 bool TriggerTimeoutNow() {
100 return ack_tracker_.TriggerTimeoutAtForTest(time_provider_->Now());
103 base::TimeDelta GetTimerDelay() const {
104 const base::Timer& timer = ack_tracker_.GetTimerForTest();
105 if (!timer.IsRunning())
106 ADD_FAILURE() << "Timer is not running!";
107 return timer.GetCurrentDelay();
110 scoped_refptr<MockTimeProvider> time_provider_;
111 ::testing::StrictMock<MockDelegate> delegate_;
112 AckTracker ack_tracker_;
114 const invalidation::ObjectId kIdOne;
115 const invalidation::ObjectId kIdTwo;
117 // AckTracker uses base::Timer internally, which depends on the existence of a
118 // MessageLoop.
119 MessageLoop message_loop_;
122 // Tests that various combinations of Track()/Ack() behave as
123 // expected.
124 TEST_F(AckTrackerTest, TrackAndAck) {
125 ObjectIdSet ids_one;
126 ids_one.insert(kIdOne);
127 ObjectIdSet ids_two;
128 ids_two.insert(kIdTwo);
129 ObjectIdSet ids_all;
130 ids_all.insert(kIdOne);
131 ids_all.insert(kIdTwo);
133 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
134 ack_tracker_.Track(ids_one);
135 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
136 ack_tracker_.Track(ids_two);
137 ack_tracker_.Ack(ids_one);
138 ack_tracker_.Ack(ids_two);
139 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
141 ack_tracker_.Track(ids_all);
142 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
143 ack_tracker_.Ack(ids_one);
144 ack_tracker_.Ack(ids_two);
145 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
147 ack_tracker_.Track(ids_one);
148 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
149 ack_tracker_.Track(ids_two);
150 ack_tracker_.Ack(ids_all);
151 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
153 ack_tracker_.Track(ids_all);
154 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
155 ack_tracker_.Ack(ids_all);
156 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
159 TEST_F(AckTrackerTest, DoubleTrack) {
160 ObjectIdSet ids;
161 ids.insert(kIdOne);
163 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
164 ack_tracker_.Track(ids);
165 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
166 ack_tracker_.Track(ids);
167 ack_tracker_.Ack(ids);
168 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
171 TEST_F(AckTrackerTest, UntrackedAck) {
172 ObjectIdSet ids;
173 ids.insert(kIdOne);
175 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
176 ack_tracker_.Ack(ids);
177 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
180 TEST_F(AckTrackerTest, Clear) {
181 ObjectIdSet ids;
182 ids.insert(kIdOne);
183 ids.insert(kIdOne);
185 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
186 ack_tracker_.Track(ids);
187 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
188 ack_tracker_.Clear();
189 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
192 // Test that timeout behavior for one object ID. The timeout should increase
193 // exponentially until it hits the cap.
194 TEST_F(AckTrackerTest, SimpleTimeout) {
195 ObjectIdSet ids;
196 ids.insert(kIdOne);
198 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
199 ack_tracker_.Track(ids);
200 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
202 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
203 time_provider_->LeapForward(60);
204 EXPECT_CALL(delegate_, OnTimeout(ids));
205 EXPECT_TRUE(TriggerTimeoutNow());
207 EXPECT_EQ(base::TimeDelta::FromSeconds(120), GetTimerDelay());
208 time_provider_->LeapForward(120);
209 EXPECT_CALL(delegate_, OnTimeout(ids));
210 EXPECT_TRUE(TriggerTimeoutNow());
212 EXPECT_EQ(base::TimeDelta::FromSeconds(240), GetTimerDelay());
213 time_provider_->LeapForward(240);
214 EXPECT_CALL(delegate_, OnTimeout(ids));
215 EXPECT_TRUE(TriggerTimeoutNow());
217 EXPECT_EQ(base::TimeDelta::FromSeconds(480), GetTimerDelay());
218 time_provider_->LeapForward(480);
219 EXPECT_CALL(delegate_, OnTimeout(ids));
220 EXPECT_TRUE(TriggerTimeoutNow());
222 EXPECT_EQ(base::TimeDelta::FromSeconds(600), GetTimerDelay());
223 time_provider_->LeapForward(600);
224 EXPECT_CALL(delegate_, OnTimeout(ids));
225 EXPECT_TRUE(TriggerTimeoutNow());
227 EXPECT_EQ(base::TimeDelta::FromSeconds(600), GetTimerDelay());
228 time_provider_->LeapForward(600);
229 EXPECT_CALL(delegate_, OnTimeout(ids));
230 EXPECT_TRUE(TriggerTimeoutNow());
232 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
233 ack_tracker_.Ack(ids);
234 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
236 // The backoff time should be reset after an Ack/Track cycle.
237 ack_tracker_.Track(ids);
238 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
240 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
241 time_provider_->LeapForward(60);
242 EXPECT_CALL(delegate_, OnTimeout(ids));
243 EXPECT_TRUE(TriggerTimeoutNow());
245 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
246 ack_tracker_.Ack(ids);
247 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
250 // Tests that a sequence of Track() calls that results in interleaving
251 // timeouts occurs as expected.
252 TEST_F(AckTrackerTest, InterleavedTimeout) {
253 ObjectIdSet ids_one;
254 ids_one.insert(kIdOne);
255 ObjectIdSet ids_two;
256 ids_two.insert(kIdTwo);
258 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
259 ack_tracker_.Track(ids_one);
260 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
262 time_provider_->LeapForward(30);
263 ack_tracker_.Track(ids_two);
264 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
266 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
267 time_provider_->LeapForward(30);
268 EXPECT_CALL(delegate_, OnTimeout(ids_one));
269 EXPECT_TRUE(TriggerTimeoutNow());
271 EXPECT_EQ(base::TimeDelta::FromSeconds(30), GetTimerDelay());
272 time_provider_->LeapForward(30);
273 EXPECT_CALL(delegate_, OnTimeout(ids_two));
274 EXPECT_TRUE(TriggerTimeoutNow());
276 EXPECT_EQ(base::TimeDelta::FromSeconds(90), GetTimerDelay());
277 time_provider_->LeapForward(90);
278 EXPECT_CALL(delegate_, OnTimeout(ids_one));
279 EXPECT_TRUE(TriggerTimeoutNow());
281 EXPECT_EQ(base::TimeDelta::FromSeconds(30), GetTimerDelay());
282 time_provider_->LeapForward(30);
283 EXPECT_CALL(delegate_, OnTimeout(ids_two));
284 EXPECT_TRUE(TriggerTimeoutNow());
286 ack_tracker_.Ack(ids_one);
287 ack_tracker_.Ack(ids_two);
288 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
291 // Tests that registering a new object ID properly shortens the timeout when
292 // needed.
293 TEST_F(AckTrackerTest, ShortenTimeout) {
294 ObjectIdSet ids_one;
295 ids_one.insert(kIdOne);
296 ObjectIdSet ids_two;
297 ids_two.insert(kIdTwo);
299 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
300 ack_tracker_.Track(ids_one);
301 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
303 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
304 time_provider_->LeapForward(60);
305 EXPECT_CALL(delegate_, OnTimeout(ids_one));
306 EXPECT_TRUE(TriggerTimeoutNow());
308 // Without this next register, the next timeout should occur in 120 seconds
309 // from the last timeout event.
310 EXPECT_EQ(base::TimeDelta::FromSeconds(120), GetTimerDelay());
311 time_provider_->LeapForward(30);
312 ack_tracker_.Track(ids_two);
313 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
315 // Now that we've registered another entry though, we should receive a timeout
316 // in 60 seconds.
317 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
318 time_provider_->LeapForward(60);
319 EXPECT_CALL(delegate_, OnTimeout(ids_two));
320 EXPECT_TRUE(TriggerTimeoutNow());
322 // Verify that the original timeout for kIdOne still occurs as expected.
323 EXPECT_EQ(base::TimeDelta::FromSeconds(30), GetTimerDelay());
324 time_provider_->LeapForward(30);
325 EXPECT_CALL(delegate_, OnTimeout(ids_one));
326 EXPECT_TRUE(TriggerTimeoutNow());
328 ack_tracker_.Ack(ids_one);
329 ack_tracker_.Ack(ids_two);
330 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
333 // Tests that a delay between inserting a new object ID registration and start
334 // the timer that is greater than the initial timeout period (60 seconds) does
335 // not break things. This could happen on a heavily loaded system, for instance.
336 TEST_F(AckTrackerTest, ImmediateTimeout) {
337 ObjectIdSet ids;
338 ids.insert(kIdOne);
340 time_provider_->DelayedLeapForward(90);
341 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
342 ack_tracker_.Track(ids);
343 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
345 EXPECT_EQ(base::TimeDelta::FromSeconds(0), GetTimerDelay());
346 EXPECT_CALL(delegate_, OnTimeout(ids));
347 message_loop_.RunUntilIdle();
349 // The next timeout should still be scheduled normally.
350 EXPECT_EQ(base::TimeDelta::FromSeconds(120), GetTimerDelay());
351 time_provider_->LeapForward(120);
352 EXPECT_CALL(delegate_, OnTimeout(ids));
353 EXPECT_TRUE(TriggerTimeoutNow());
355 ack_tracker_.Ack(ids);
356 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
359 } // namespace syncer