Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: sync/notifier/ack_tracker_unittest.cc

Issue 56113003: Implement new invalidations ack tracking system (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Modify drive TODO comment + rebase Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sync/notifier/ack_tracker.cc ('k') | sync/notifier/fake_invalidation_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "sync/notifier/ack_tracker.h"
6
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"
15
16 namespace syncer {
17
18 namespace {
19
20 class FakeTickClock : public base::TickClock {
21 public:
22 FakeTickClock() {}
23
24 virtual ~FakeTickClock() {}
25
26 void LeapForward(int seconds) {
27 ASSERT_GT(seconds, 0);
28 fake_now_ticks_ += base::TimeDelta::FromSeconds(seconds);
29 }
30
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);
35 }
36
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();
42 }
43 return fake_now_ticks;
44 }
45
46 private:
47 base::TimeTicks fake_now_ticks_;
48 base::TimeDelta delayed_leap_;
49 };
50
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) {
56 }
57
58 protected:
59 virtual base::TimeTicks ImplGetTimeNow() const OVERRIDE {
60 return tick_clock_->NowTicks();
61 }
62
63 private:
64 base::TickClock* const tick_clock_;
65 };
66
67 class MockDelegate : public AckTracker::Delegate {
68 public:
69 MOCK_METHOD1(OnTimeout, void(const ObjectIdSet&));
70 };
71
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));
77 }
78
79 } // namespace
80
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_));
89 }
90
91 protected:
92 bool TriggerTimeoutNow() {
93 return ack_tracker_.TriggerTimeoutAtForTest(fake_tick_clock_.NowTicks());
94 }
95
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();
101 }
102
103 FakeTickClock fake_tick_clock_;
104 ::testing::StrictMock<MockDelegate> delegate_;
105 AckTracker ack_tracker_;
106
107 const invalidation::ObjectId kIdOne;
108 const invalidation::ObjectId kIdTwo;
109
110 // AckTracker uses base::Timer internally, which depends on the existence of a
111 // MessageLoop.
112 base::MessageLoop message_loop_;
113 };
114
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);
125
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());
133
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());
139
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());
145
146 ack_tracker_.Track(ids_all);
147 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
148 ack_tracker_.Ack(ids_all);
149 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
150 }
151
152 TEST_F(AckTrackerTest, DoubleTrack) {
153 ObjectIdSet ids;
154 ids.insert(kIdOne);
155
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());
162 }
163
164 TEST_F(AckTrackerTest, UntrackedAck) {
165 ObjectIdSet ids;
166 ids.insert(kIdOne);
167
168 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
169 ack_tracker_.Ack(ids);
170 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
171 }
172
173 TEST_F(AckTrackerTest, Clear) {
174 ObjectIdSet ids;
175 ids.insert(kIdOne);
176 ids.insert(kIdOne);
177
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());
183 }
184
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);
190
191 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
192 ack_tracker_.Track(ids);
193 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
194
195 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
196 fake_tick_clock_.LeapForward(60);
197 EXPECT_CALL(delegate_, OnTimeout(ids));
198 EXPECT_TRUE(TriggerTimeoutNow());
199
200 EXPECT_EQ(base::TimeDelta::FromSeconds(120), GetTimerDelay());
201 fake_tick_clock_.LeapForward(120);
202 EXPECT_CALL(delegate_, OnTimeout(ids));
203 EXPECT_TRUE(TriggerTimeoutNow());
204
205 EXPECT_EQ(base::TimeDelta::FromSeconds(240), GetTimerDelay());
206 fake_tick_clock_.LeapForward(240);
207 EXPECT_CALL(delegate_, OnTimeout(ids));
208 EXPECT_TRUE(TriggerTimeoutNow());
209
210 EXPECT_EQ(base::TimeDelta::FromSeconds(480), GetTimerDelay());
211 fake_tick_clock_.LeapForward(480);
212 EXPECT_CALL(delegate_, OnTimeout(ids));
213 EXPECT_TRUE(TriggerTimeoutNow());
214
215 EXPECT_EQ(base::TimeDelta::FromSeconds(600), GetTimerDelay());
216 fake_tick_clock_.LeapForward(600);
217 EXPECT_CALL(delegate_, OnTimeout(ids));
218 EXPECT_TRUE(TriggerTimeoutNow());
219
220 EXPECT_EQ(base::TimeDelta::FromSeconds(600), GetTimerDelay());
221 fake_tick_clock_.LeapForward(600);
222 EXPECT_CALL(delegate_, OnTimeout(ids));
223 EXPECT_TRUE(TriggerTimeoutNow());
224
225 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
226 ack_tracker_.Ack(ids);
227 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
228
229 // The backoff time should be reset after an Ack/Track cycle.
230 ack_tracker_.Track(ids);
231 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
232
233 EXPECT_EQ(base::TimeDelta::FromSeconds(60), GetTimerDelay());
234 fake_tick_clock_.LeapForward(60);
235 EXPECT_CALL(delegate_, OnTimeout(ids));
236 EXPECT_TRUE(TriggerTimeoutNow());
237
238 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
239 ack_tracker_.Ack(ids);
240 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
241 }
242
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);
250
251 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
252 ack_tracker_.Track(ids_one);
253 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
254
255 fake_tick_clock_.LeapForward(30);
256 ack_tracker_.Track(ids_two);
257 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
258
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());
263
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());
268
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());
273
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());
278
279 ack_tracker_.Ack(ids_one);
280 ack_tracker_.Ack(ids_two);
281 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
282 }
283
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);
291
292 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
293 ack_tracker_.Track(ids_one);
294 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
295
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());
300
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());
307
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());
314
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());
320
321 ack_tracker_.Ack(ids_one);
322 ack_tracker_.Ack(ids_two);
323 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
324 }
325
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);
332
333 fake_tick_clock_.DelayedLeapForward(90);
334 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
335 ack_tracker_.Track(ids);
336 EXPECT_FALSE(ack_tracker_.IsQueueEmptyForTest());
337
338 EXPECT_EQ(base::TimeDelta::FromSeconds(0), GetTimerDelay());
339 EXPECT_CALL(delegate_, OnTimeout(ids));
340 message_loop_.RunUntilIdle();
341
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());
347
348 ack_tracker_.Ack(ids);
349 EXPECT_TRUE(ack_tracker_.IsQueueEmptyForTest());
350 }
351
352 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/notifier/ack_tracker.cc ('k') | sync/notifier/fake_invalidation_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698