1 // Copyright (c) 2010 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 "chrome/browser/sync/notifier/registration_manager.h"
6
7 #include <algorithm>
8 #include <cmath>
9 #include <cstddef>
10 #include <deque>
11 #include <vector>
12
13 #include "base/basictypes.h"
14 #include "base/message_loop.h"
15 #include "chrome/browser/sync/notifier/invalidation_util.h"
16 #include "chrome/browser/sync/syncable/model_type.h"
17 #include "google/cacheinvalidation/invalidation-client.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace sync_notifier {
21 namespace {
22
ObjectIdToModelType(const invalidation::ObjectId & object_id)23 syncable::ModelType ObjectIdToModelType(
24 const invalidation::ObjectId& object_id) {
25 syncable::ModelType model_type = syncable::UNSPECIFIED;
26 EXPECT_TRUE(ObjectIdToRealModelType(object_id, &model_type));
27 return model_type;
28 }
29
30 // Fake registration manager that lets you override jitter.
31 class FakeRegistrationManager : public RegistrationManager {
32 public:
FakeRegistrationManager(invalidation::InvalidationClient * invalidation_client)33 explicit FakeRegistrationManager(
34 invalidation::InvalidationClient* invalidation_client)
35 : RegistrationManager(invalidation_client),
36 jitter_(0.0) {}
37
~FakeRegistrationManager()38 virtual ~FakeRegistrationManager() {}
39
SetJitter(double jitter)40 void SetJitter(double jitter) {
41 jitter_ = jitter;
42 }
43
44 protected:
GetJitter()45 virtual double GetJitter() {
46 return jitter_;
47 }
48
49 private:
50 double jitter_;
51
52 DISALLOW_COPY_AND_ASSIGN(FakeRegistrationManager);
53 };
54
55 // Fake invalidation client that just stores the currently-registered
56 // model types.
57 class FakeInvalidationClient : public invalidation::InvalidationClient {
58 public:
FakeInvalidationClient()59 FakeInvalidationClient() {}
60
~FakeInvalidationClient()61 virtual ~FakeInvalidationClient() {}
62
LoseRegistration(syncable::ModelType model_type)63 void LoseRegistration(syncable::ModelType model_type) {
64 EXPECT_GT(registered_types_.count(model_type), 0u);
65 registered_types_.erase(model_type);
66 }
67
LoseAllRegistrations()68 void LoseAllRegistrations() {
69 registered_types_.clear();
70 }
71
72 // invalidation::InvalidationClient implementation.
73
Start(const std::string & state)74 virtual void Start(const std::string& state) {}
75
Register(const invalidation::ObjectId & oid)76 virtual void Register(const invalidation::ObjectId& oid) {
77 syncable::ModelType model_type = ObjectIdToModelType(oid);
78 EXPECT_EQ(0u, registered_types_.count(model_type));
79 registered_types_.insert(model_type);
80 }
81
Unregister(const invalidation::ObjectId & oid)82 virtual void Unregister(const invalidation::ObjectId& oid) {
83 syncable::ModelType model_type = ObjectIdToModelType(oid);
84 EXPECT_GT(registered_types_.count(model_type), 0u);
85 registered_types_.erase(model_type);
86 }
87
network_endpoint()88 virtual invalidation::NetworkEndpoint* network_endpoint() {
89 ADD_FAILURE();
90 return NULL;
91 }
92
GetRegisteredTypes() const93 const syncable::ModelTypeSet GetRegisteredTypes() const {
94 return registered_types_;
95 }
96
97 private:
98 syncable::ModelTypeSet registered_types_;
99
100 DISALLOW_COPY_AND_ASSIGN(FakeInvalidationClient);
101 };
102
103 const syncable::ModelType kModelTypes[] = {
104 syncable::BOOKMARKS,
105 syncable::PREFERENCES,
106 syncable::THEMES,
107 syncable::AUTOFILL,
108 syncable::EXTENSIONS,
109 };
110 const size_t kModelTypeCount = arraysize(kModelTypes);
111
ExpectPendingRegistrations(const syncable::ModelTypeSet & expected_pending_types,double expected_delay_seconds,const RegistrationManager::PendingRegistrationMap & pending_registrations)112 void ExpectPendingRegistrations(
113 const syncable::ModelTypeSet& expected_pending_types,
114 double expected_delay_seconds,
115 const RegistrationManager::PendingRegistrationMap& pending_registrations) {
116 syncable::ModelTypeSet pending_types;
117 for (RegistrationManager::PendingRegistrationMap::const_iterator it =
118 pending_registrations.begin(); it != pending_registrations.end();
119 ++it) {
120 SCOPED_TRACE(syncable::ModelTypeToString(it->first));
121 pending_types.insert(it->first);
122 base::TimeDelta offset =
123 it->second.last_registration_request -
124 it->second.registration_attempt;
125 base::TimeDelta expected_delay =
126 base::TimeDelta::FromSeconds(
127 static_cast<int64>(expected_delay_seconds)) + offset;
128 // TODO(akalin): Add base::PrintTo() for base::Time and
129 // base::TimeDeltas.
130 EXPECT_EQ(it->second.delay, expected_delay)
131 << it->second.delay.InMicroseconds()
132 << ", " << expected_delay.InMicroseconds();
133 if (it->second.delay <= base::TimeDelta()) {
134 EXPECT_EQ(it->second.actual_delay, base::TimeDelta());
135 } else {
136 EXPECT_EQ(it->second.delay, it->second.actual_delay);
137 }
138 }
139 EXPECT_EQ(expected_pending_types, pending_types);
140 }
141
142 class RegistrationManagerTest : public testing::Test {
143 protected:
RegistrationManagerTest()144 RegistrationManagerTest()
145 : fake_registration_manager_(&fake_invalidation_client_) {}
146
~RegistrationManagerTest()147 virtual ~RegistrationManagerTest() {}
148
LoseRegistrations(const syncable::ModelTypeSet & types)149 void LoseRegistrations(const syncable::ModelTypeSet& types) {
150 for (syncable::ModelTypeSet::const_iterator it = types.begin();
151 it != types.end(); ++it) {
152 fake_invalidation_client_.LoseRegistration(*it);
153 fake_registration_manager_.MarkRegistrationLost(*it);
154 }
155 }
156
157 // Used by MarkRegistrationLostBackoff* tests.
RunBackoffTest(double jitter)158 void RunBackoffTest(double jitter) {
159 fake_registration_manager_.SetJitter(jitter);
160 syncable::ModelTypeSet types(kModelTypes, kModelTypes + kModelTypeCount);
161 fake_registration_manager_.SetRegisteredTypes(types);
162
163 // Lose some types.
164 syncable::ModelTypeSet lost_types(kModelTypes, kModelTypes + 2);
165 LoseRegistrations(lost_types);
166 ExpectPendingRegistrations(
167 lost_types, 0.0,
168 fake_registration_manager_.GetPendingRegistrations());
169
170 // Trigger another failure to start delaying.
171 fake_registration_manager_.FirePendingRegistrationsForTest();
172 LoseRegistrations(lost_types);
173
174 double scaled_jitter =
175 jitter * RegistrationManager::kRegistrationDelayMaxJitter;
176
177 double expected_delay =
178 RegistrationManager::kInitialRegistrationDelaySeconds *
179 (1.0 + scaled_jitter);
180 expected_delay = std::floor(expected_delay);
181 ExpectPendingRegistrations(
182 lost_types, expected_delay,
183 fake_registration_manager_.GetPendingRegistrations());
184
185 // Trigger another failure.
186 fake_registration_manager_.FirePendingRegistrationsForTest();
187 LoseRegistrations(lost_types);
188 expected_delay *=
189 RegistrationManager::kRegistrationDelayExponent + scaled_jitter;
190 expected_delay = std::floor(expected_delay);
191 ExpectPendingRegistrations(
192 lost_types, expected_delay,
193 fake_registration_manager_.GetPendingRegistrations());
194
195 // Trigger enough failures to hit the ceiling.
196 while (expected_delay < RegistrationManager::kMaxRegistrationDelaySeconds) {
197 fake_registration_manager_.FirePendingRegistrationsForTest();
198 LoseRegistrations(lost_types);
199 expected_delay *=
200 RegistrationManager::kRegistrationDelayExponent + scaled_jitter;
201 expected_delay = std::floor(expected_delay);
202 }
203 ExpectPendingRegistrations(
204 lost_types,
205 RegistrationManager::kMaxRegistrationDelaySeconds,
206 fake_registration_manager_.GetPendingRegistrations());
207 }
208
209 FakeInvalidationClient fake_invalidation_client_;
210 FakeRegistrationManager fake_registration_manager_;
211
212 private:
213 // Needed by timers in RegistrationManager.
214 MessageLoop message_loop_;
215
216 DISALLOW_COPY_AND_ASSIGN(RegistrationManagerTest);
217 };
218
TEST_F(RegistrationManagerTest,SetRegisteredTypes)219 TEST_F(RegistrationManagerTest, SetRegisteredTypes) {
220 syncable::ModelTypeSet no_types;
221 syncable::ModelTypeSet types(kModelTypes, kModelTypes + kModelTypeCount);
222
223 EXPECT_EQ(no_types, fake_registration_manager_.GetRegisteredTypes());
224 EXPECT_EQ(no_types, fake_invalidation_client_.GetRegisteredTypes());
225
226 fake_registration_manager_.SetRegisteredTypes(types);
227 EXPECT_EQ(types, fake_registration_manager_.GetRegisteredTypes());
228 EXPECT_EQ(types, fake_invalidation_client_.GetRegisteredTypes());
229
230 types.insert(syncable::APPS);
231 types.erase(syncable::BOOKMARKS);
232 fake_registration_manager_.SetRegisteredTypes(types);
233 EXPECT_EQ(types, fake_registration_manager_.GetRegisteredTypes());
234 EXPECT_EQ(types, fake_invalidation_client_.GetRegisteredTypes());
235 }
236
GetRoundedBackoff(double retry_interval,double jitter)237 int GetRoundedBackoff(double retry_interval, double jitter) {
238 const double kInitialRetryInterval = 3.0;
239 const double kMinRetryInterval = 2.0;
240 const double kMaxRetryInterval = 20.0;
241 const double kBackoffExponent = 2.0;
242 const double kMaxJitter = 0.5;
243
244 return static_cast<int>(
245 RegistrationManager::CalculateBackoff(retry_interval,
246 kInitialRetryInterval,
247 kMinRetryInterval,
248 kMaxRetryInterval,
249 kBackoffExponent,
250 jitter,
251 kMaxJitter));
252 }
253
TEST_F(RegistrationManagerTest,CalculateBackoff)254 TEST_F(RegistrationManagerTest, CalculateBackoff) {
255 // Test initial.
256 EXPECT_EQ(2, GetRoundedBackoff(0.0, -1.0));
257 EXPECT_EQ(3, GetRoundedBackoff(0.0, 0.0));
258 EXPECT_EQ(4, GetRoundedBackoff(0.0, +1.0));
259
260 // Test non-initial.
261 EXPECT_EQ(4, GetRoundedBackoff(3.0, -1.0));
262 EXPECT_EQ(6, GetRoundedBackoff(3.0, 0.0));
263 EXPECT_EQ(7, GetRoundedBackoff(3.0, +1.0));
264
265 EXPECT_EQ(7, GetRoundedBackoff(5.0, -1.0));
266 EXPECT_EQ(10, GetRoundedBackoff(5.0, 0.0));
267 EXPECT_EQ(12, GetRoundedBackoff(5.0, +1.0));
268
269 // Test ceiling.
270 EXPECT_EQ(19, GetRoundedBackoff(13.0, -1.0));
271 EXPECT_EQ(20, GetRoundedBackoff(13.0, 0.0));
272 EXPECT_EQ(20, GetRoundedBackoff(13.0, +1.0));
273 }
274
TEST_F(RegistrationManagerTest,MarkRegistrationLost)275 TEST_F(RegistrationManagerTest, MarkRegistrationLost) {
276 syncable::ModelTypeSet types(kModelTypes, kModelTypes + kModelTypeCount);
277
278 fake_registration_manager_.SetRegisteredTypes(types);
279 EXPECT_TRUE(fake_registration_manager_.GetPendingRegistrations().empty());
280
281 // Lose some types.
282 syncable::ModelTypeSet lost_types(
283 kModelTypes, kModelTypes + 3);
284 syncable::ModelTypeSet non_lost_types(
285 kModelTypes + 3, kModelTypes + kModelTypeCount);
286 LoseRegistrations(lost_types);
287 ExpectPendingRegistrations(
288 lost_types, 0.0,
289 fake_registration_manager_.GetPendingRegistrations());
290 EXPECT_EQ(non_lost_types, fake_registration_manager_.GetRegisteredTypes());
291 EXPECT_EQ(non_lost_types, fake_invalidation_client_.GetRegisteredTypes());
292
293 // Pretend we waited long enough to re-register.
294 fake_registration_manager_.FirePendingRegistrationsForTest();
295 EXPECT_EQ(types, fake_registration_manager_.GetRegisteredTypes());
296 EXPECT_EQ(types, fake_invalidation_client_.GetRegisteredTypes());
297 }
298
TEST_F(RegistrationManagerTest,MarkRegistrationLostBackoffLow)299 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffLow) {
300 RunBackoffTest(-1.0);
301 }
302
TEST_F(RegistrationManagerTest,MarkRegistrationLostBackoffMid)303 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffMid) {
304 RunBackoffTest(0.0);
305 }
306
TEST_F(RegistrationManagerTest,MarkRegistrationLostBackoffHigh)307 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffHigh) {
308 RunBackoffTest(+1.0);
309 }
310
TEST_F(RegistrationManagerTest,MarkRegistrationLostBackoffReset)311 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffReset) {
312 syncable::ModelTypeSet types(kModelTypes, kModelTypes + kModelTypeCount);
313
314 fake_registration_manager_.SetRegisteredTypes(types);
315
316 // Lose some types.
317 syncable::ModelTypeSet lost_types(kModelTypes, kModelTypes + 2);
318 LoseRegistrations(lost_types);
319 ExpectPendingRegistrations(
320 lost_types, 0.0,
321 fake_registration_manager_.GetPendingRegistrations());
322
323 // Trigger another failure to start delaying.
324 fake_registration_manager_.FirePendingRegistrationsForTest();
325 LoseRegistrations(lost_types);
326 double expected_delay =
327 RegistrationManager::kInitialRegistrationDelaySeconds;
328 ExpectPendingRegistrations(
329 lost_types, expected_delay,
330 fake_registration_manager_.GetPendingRegistrations());
331
332 // Set types again.
333 fake_registration_manager_.SetRegisteredTypes(types);
334 ExpectPendingRegistrations(
335 syncable::ModelTypeSet(), 0.0,
336 fake_registration_manager_.GetPendingRegistrations());
337 }
338
TEST_F(RegistrationManagerTest,MarkAllRegistrationsLost)339 TEST_F(RegistrationManagerTest, MarkAllRegistrationsLost) {
340 syncable::ModelTypeSet types(kModelTypes, kModelTypes + kModelTypeCount);
341
342 fake_registration_manager_.SetRegisteredTypes(types);
343
344 fake_invalidation_client_.LoseAllRegistrations();
345 fake_registration_manager_.MarkAllRegistrationsLost();
346
347 syncable::ModelTypeSet expected_types;
348 EXPECT_EQ(expected_types, fake_registration_manager_.GetRegisteredTypes());
349 EXPECT_EQ(expected_types, fake_invalidation_client_.GetRegisteredTypes());
350
351 ExpectPendingRegistrations(
352 types, 0.0,
353 fake_registration_manager_.GetPendingRegistrations());
354
355 // Trigger another failure to start delaying.
356 fake_registration_manager_.FirePendingRegistrationsForTest();
357 fake_invalidation_client_.LoseAllRegistrations();
358 fake_registration_manager_.MarkAllRegistrationsLost();
359 double expected_delay =
360 RegistrationManager::kInitialRegistrationDelaySeconds;
361 ExpectPendingRegistrations(
362 types, expected_delay,
363 fake_registration_manager_.GetPendingRegistrations());
364
365 // Pretend we waited long enough to re-register.
366 fake_registration_manager_.FirePendingRegistrationsForTest();
367 EXPECT_EQ(types, fake_registration_manager_.GetRegisteredTypes());
368 EXPECT_EQ(types, fake_invalidation_client_.GetRegisteredTypes());
369 }
370
371 } // namespace
372 } // namespace notifier
373