Get foreground tab on Android
[chromium-blink-merge.git] / sync / notifier / ack_tracker_unittest.cc
blobc1a677351e28540c83a55e7253ef38c38269e3d8
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/compiler_specific.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/time/tick_clock.h"
11 #include "google/cacheinvalidation/include/types.h"
12 #include "google/cacheinvalidation/types.pb.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace syncer {
18 namespace {
20 class FakeTickClock : public base::TickClock {
21 public:
22 FakeTickClock() {}
24 virtual ~FakeTickClock() {}
26 void LeapForward(int seconds) {
27 ASSERT_GT(seconds, 0);
28 fake_now_ticks_ += base::TimeDelta::FromSeconds(seconds);
31 // After the next call to Now(), immediately leap forward by |seconds|.
32 void DelayedLeapForward(int seconds) {
33 ASSERT_GT(seconds, 0);
34 delayed_leap_ = base::TimeDelta::FromSeconds(seconds);
37 virtual base::TimeTicks NowTicks() OVERRIDE {
38 base::TimeTicks fake_now_ticks = fake_now_ticks_;
39 if (delayed_leap_ > base::TimeDelta()) {
40 fake_now_ticks_ += delayed_leap_;
41 delayed_leap_ = base::TimeDelta();
43 return fake_now_ticks;
46 private:
47 base::TimeTicks fake_now_ticks_;
48 base::TimeDelta delayed_leap_;
51 class FakeBackoffEntry : public net::BackoffEntry {
52 public:
53 FakeBackoffEntry(const Policy* const policy, base::TickClock* tick_clock)
54 : BackoffEntry(policy),
55 tick_clock_(tick_clock) {
58 protected:
59 virtual base::TimeTicks ImplGetTimeNow() const OVERRIDE {
60 return tick_clock_->NowTicks();
63 private:
64 base::TickClock* const tick_clock_;
67 class MockDelegate : public AckTracker::Delegate {
68 public:
69 MOCK_METHOD1(OnTimeout, void(const ObjectIdSet&));
72 scoped_ptr<net::BackoffEntry> CreateMockEntry(
73 base::TickClock* tick_clock,
74 const net::BackoffEntry::Policy* const policy) {
75 return scoped_ptr<net::BackoffEntry>(new FakeBackoffEntry(
76 policy, tick_clock));
79 } // namespace
81 class AckTrackerTest : public testing::Test {
82 public:
83 AckTrackerTest()
84 : ack_tracker_(&fake_tick_clock_, &delegate_),
85 kIdOne(ipc::invalidation::ObjectSource::TEST, "one"),
86 kIdTwo(ipc::invalidation::ObjectSource::TEST, "two") {
87 ack_tracker_.SetCreateBackoffEntryCallbackForTest(
88 base::Bind(&CreateMockEntry, &fake_tick_clock_));
91 protected:
92 bool TriggerTimeoutNow() {
93 return ack_tracker_.TriggerTimeoutAtForTest(fake_tick_clock_.NowTicks());
96 base::TimeDelta GetTimerDelay() const {
97 const base::Timer& timer = ack_tracker_.GetTimerForTest();
98 if (!timer.IsRunning())
99 ADD_FAILURE() << "Timer is not running!";
100 return timer.GetCurrentDelay();
103 FakeTickClock fake_tick_clock_;
104 ::testing::StrictMock<MockDelegate> delegate_;
105 AckTracker ack_tracker_;
107 const invalidation::ObjectId kIdOne;
108 const invalidation::ObjectId kIdTwo;
110 // AckTracker uses base::Timer internally, which depends on the existence of a
111 // MessageLoop.
112 base::MessageLoop message_loop_;
115 // Tests that various combinations of Track()/Ack() behave as
116 // expected.
117 TEST_F(AckTrackerTest, TrackAndAck) {
118 ObjectIdSet ids_one;
119 ids_one.insert(kIdOne);
120 ObjectIdSet ids_two;
121 ids_two.insert(kIdTwo);
122 ObjectIdSet ids_all;
123 ids_all.insert(kIdOne);
124 ids_all.insert(kIdTwo);
126 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
127 ack_tracker_.Track(ids_one);
128 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
129 ack_tracker_.Track(ids_two);
130 ack_tracker_.Ack(ids_one);
131 ack_tracker_.Ack(ids_two);
132 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
134 ack_tracker_.Track(ids_all);
135 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
136 ack_tracker_.Ack(ids_one);
137 ack_tracker_.Ack(ids_two);
138 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
140 ack_tracker_.Track(ids_one);
141 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
142 ack_tracker_.Track(ids_two);
143 ack_tracker_.Ack(ids_all);
144 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
146 ack_tracker_.Track(ids_all);
147 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
148 ack_tracker_.Ack(ids_all);
149 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
152 TEST_F(AckTrackerTest, DoubleTrack) {
153 ObjectIdSet ids;
154 ids.insert(kIdOne);
156 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
157 ack_tracker_.Track(ids);
158 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
159 ack_tracker_.Track(ids);
160 ack_tracker_.Ack(ids);
161 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
164 TEST_F(AckTrackerTest, UntrackedAck) {
165 ObjectIdSet ids;
166 ids.insert(kIdOne);
168 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
169 ack_tracker_.Ack(ids);
170 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
173 TEST_F(AckTrackerTest, Clear) {
174 ObjectIdSet ids;
175 ids.insert(kIdOne);
176 ids.insert(kIdOne);
178 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
179 ack_tracker_.Track(ids);
180 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
181 ack_tracker_.Clear();
182 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
185 // Test that timeout behavior for one object ID. The timeout should increase
186 // exponentially until it hits the cap.
187 TEST_F(AckTrackerTest, SimpleTimeout) {
188 ObjectIdSet ids;
189 ids.insert(kIdOne);
191 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
192 ack_tracker_.Track(ids);
193 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
195 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
196 fake_tick_clock_.LeapForward(60);
197 EXPECT_CALL(delegate_, OnTimeout(ids));
198 EXPECT_TRUE(TriggerTimeoutNow());
200 EXPECT_EQ(base::TimeDelta::FromSeconds(120), GetTimerDelay());
201 fake_tick_clock_.LeapForward(120);
202 EXPECT_CALL(delegate_, OnTimeout(ids));
203 EXPECT_TRUE(TriggerTimeoutNow());
205 EXPECT_EQ(base::TimeDelta::FromSeconds(240), GetTimerDelay());
206 fake_tick_clock_.LeapForward(240);
207 EXPECT_CALL(delegate_, OnTimeout(ids));
208 EXPECT_TRUE(TriggerTimeoutNow());
210 EXPECT_EQ(base::TimeDelta::FromSeconds(480), GetTimerDelay());
211 fake_tick_clock_.LeapForward(480);
212 EXPECT_CALL(delegate_, OnTimeout(ids));
213 EXPECT_TRUE(TriggerTimeoutNow());
215 EXPECT_EQ(base::TimeDelta::FromSeconds(600), GetTimerDelay());
216 fake_tick_clock_.LeapForward(600);
217 EXPECT_CALL(delegate_, OnTimeout(ids));
218 EXPECT_TRUE(TriggerTimeoutNow());
220 EXPECT_EQ(base::TimeDelta::FromSeconds(600), GetTimerDelay());
221 fake_tick_clock_.LeapForward(600);
222 EXPECT_CALL(delegate_, OnTimeout(ids));
223 EXPECT_TRUE(TriggerTimeoutNow());
225 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
226 ack_tracker_.Ack(ids);
227 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
229 // The backoff time should be reset after an Ack/Track cycle.
230 ack_tracker_.Track(ids);
231 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
233 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
234 fake_tick_clock_.LeapForward(60);
235 EXPECT_CALL(delegate_, OnTimeout(ids));
236 EXPECT_TRUE(TriggerTimeoutNow());
238 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
239 ack_tracker_.Ack(ids);
240 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
243 // Tests that a sequence of Track() calls that results in interleaving
244 // timeouts occurs as expected.
245 TEST_F(AckTrackerTest, InterleavedTimeout) {
246 ObjectIdSet ids_one;
247 ids_one.insert(kIdOne);
248 ObjectIdSet ids_two;
249 ids_two.insert(kIdTwo);
251 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
252 ack_tracker_.Track(ids_one);
253 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
255 fake_tick_clock_.LeapForward(30);
256 ack_tracker_.Track(ids_two);
257 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
259 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
260 fake_tick_clock_.LeapForward(30);
261 EXPECT_CALL(delegate_, OnTimeout(ids_one));
262 EXPECT_TRUE(TriggerTimeoutNow());
264 EXPECT_EQ(base::TimeDelta::FromSeconds(30), GetTimerDelay());
265 fake_tick_clock_.LeapForward(30);
266 EXPECT_CALL(delegate_, OnTimeout(ids_two));
267 EXPECT_TRUE(TriggerTimeoutNow());
269 EXPECT_EQ(base::TimeDelta::FromSeconds(90), GetTimerDelay());
270 fake_tick_clock_.LeapForward(90);
271 EXPECT_CALL(delegate_, OnTimeout(ids_one));
272 EXPECT_TRUE(TriggerTimeoutNow());
274 EXPECT_EQ(base::TimeDelta::FromSeconds(30), GetTimerDelay());
275 fake_tick_clock_.LeapForward(30);
276 EXPECT_CALL(delegate_, OnTimeout(ids_two));
277 EXPECT_TRUE(TriggerTimeoutNow());
279 ack_tracker_.Ack(ids_one);
280 ack_tracker_.Ack(ids_two);
281 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
284 // Tests that registering a new object ID properly shortens the timeout when
285 // needed.
286 TEST_F(AckTrackerTest, ShortenTimeout) {
287 ObjectIdSet ids_one;
288 ids_one.insert(kIdOne);
289 ObjectIdSet ids_two;
290 ids_two.insert(kIdTwo);
292 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
293 ack_tracker_.Track(ids_one);
294 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
296 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
297 fake_tick_clock_.LeapForward(60);
298 EXPECT_CALL(delegate_, OnTimeout(ids_one));
299 EXPECT_TRUE(TriggerTimeoutNow());
301 // Without this next register, the next timeout should occur in 120 seconds
302 // from the last timeout event.
303 EXPECT_EQ(base::TimeDelta::FromSeconds(120), GetTimerDelay());
304 fake_tick_clock_.LeapForward(30);
305 ack_tracker_.Track(ids_two);
306 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
308 // Now that we've registered another entry though, we should receive a timeout
309 // in 60 seconds.
310 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
311 fake_tick_clock_.LeapForward(60);
312 EXPECT_CALL(delegate_, OnTimeout(ids_two));
313 EXPECT_TRUE(TriggerTimeoutNow());
315 // Verify that the original timeout for kIdOne still occurs as expected.
316 EXPECT_EQ(base::TimeDelta::FromSeconds(30), GetTimerDelay());
317 fake_tick_clock_.LeapForward(30);
318 EXPECT_CALL(delegate_, OnTimeout(ids_one));
319 EXPECT_TRUE(TriggerTimeoutNow());
321 ack_tracker_.Ack(ids_one);
322 ack_tracker_.Ack(ids_two);
323 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
326 // Tests that a delay between inserting a new object ID registration and start
327 // the timer that is greater than the initial timeout period (60 seconds) does
328 // not break things. This could happen on a heavily loaded system, for instance.
329 TEST_F(AckTrackerTest, ImmediateTimeout) {
330 ObjectIdSet ids;
331 ids.insert(kIdOne);
333 fake_tick_clock_.DelayedLeapForward(90);
334 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
335 ack_tracker_.Track(ids);
336 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
338 EXPECT_EQ(base::TimeDelta::FromSeconds(0), GetTimerDelay());
339 EXPECT_CALL(delegate_, OnTimeout(ids));
340 message_loop_.RunUntilIdle();
342 // The next timeout should still be scheduled normally.
343 EXPECT_EQ(base::TimeDelta::FromSeconds(120), GetTimerDelay());
344 fake_tick_clock_.LeapForward(120);
345 EXPECT_CALL(delegate_, OnTimeout(ids));
346 EXPECT_TRUE(TriggerTimeoutNow());
348 ack_tracker_.Ack(ids);
349 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
352 } // namespace syncer