• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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