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 20namespace sync_notifier { 21namespace { 22 23syncable::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. 31class FakeRegistrationManager : public RegistrationManager { 32 public: 33 explicit FakeRegistrationManager( 34 invalidation::InvalidationClient* invalidation_client) 35 : RegistrationManager(invalidation_client), 36 jitter_(0.0) {} 37 38 virtual ~FakeRegistrationManager() {} 39 40 void SetJitter(double jitter) { 41 jitter_ = jitter; 42 } 43 44 protected: 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. 57class FakeInvalidationClient : public invalidation::InvalidationClient { 58 public: 59 FakeInvalidationClient() {} 60 61 virtual ~FakeInvalidationClient() {} 62 63 void LoseRegistration(syncable::ModelType model_type) { 64 EXPECT_GT(registered_types_.count(model_type), 0u); 65 registered_types_.erase(model_type); 66 } 67 68 void LoseAllRegistrations() { 69 registered_types_.clear(); 70 } 71 72 // invalidation::InvalidationClient implementation. 73 74 virtual void Start(const std::string& state) {} 75 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 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 88 virtual invalidation::NetworkEndpoint* network_endpoint() { 89 ADD_FAILURE(); 90 return NULL; 91 } 92 93 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 103const syncable::ModelType kModelTypes[] = { 104 syncable::BOOKMARKS, 105 syncable::PREFERENCES, 106 syncable::THEMES, 107 syncable::AUTOFILL, 108 syncable::EXTENSIONS, 109}; 110const size_t kModelTypeCount = arraysize(kModelTypes); 111 112void 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 142class RegistrationManagerTest : public testing::Test { 143 protected: 144 RegistrationManagerTest() 145 : fake_registration_manager_(&fake_invalidation_client_) {} 146 147 virtual ~RegistrationManagerTest() {} 148 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. 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 219TEST_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 237int 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 254TEST_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 275TEST_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 299TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffLow) { 300 RunBackoffTest(-1.0); 301} 302 303TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffMid) { 304 RunBackoffTest(0.0); 305} 306 307TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffHigh) { 308 RunBackoffTest(+1.0); 309} 310 311TEST_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 339TEST_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