Home | History | Annotate | Download | only in notifier
      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/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/message_loop.h"
     15 #include "base/stl_util.h"
     16 #include "google/cacheinvalidation/include/invalidation-client.h"
     17 #include "sync/notifier/invalidation_util.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 namespace syncer {
     21 namespace {
     22 
     23 // Fake registration manager that lets you override jitter.
     24 class FakeRegistrationManager : public RegistrationManager {
     25  public:
     26   explicit FakeRegistrationManager(
     27       invalidation::InvalidationClient* invalidation_client)
     28       : RegistrationManager(invalidation_client),
     29         jitter_(0.0) {}
     30 
     31   virtual ~FakeRegistrationManager() {}
     32 
     33   void SetJitter(double jitter) {
     34     jitter_ = jitter;
     35   }
     36 
     37  protected:
     38   virtual double GetJitter() OVERRIDE {
     39     return jitter_;
     40   }
     41 
     42  private:
     43   double jitter_;
     44 
     45   DISALLOW_COPY_AND_ASSIGN(FakeRegistrationManager);
     46 };
     47 
     48 // Fake invalidation client that just stores the currently-registered
     49 // object IDs.
     50 class FakeInvalidationClient : public invalidation::InvalidationClient {
     51  public:
     52   FakeInvalidationClient() {}
     53 
     54   virtual ~FakeInvalidationClient() {}
     55 
     56   void LoseRegistration(const invalidation::ObjectId& oid) {
     57     EXPECT_TRUE(ContainsKey(registered_ids_, oid));
     58     registered_ids_.erase(oid);
     59   }
     60 
     61   void LoseAllRegistrations() {
     62     registered_ids_.clear();
     63   }
     64 
     65   // invalidation::InvalidationClient implementation.
     66 
     67   virtual void Start() OVERRIDE {}
     68   virtual void Stop() OVERRIDE {}
     69   virtual void Acknowledge(const invalidation::AckHandle& handle) OVERRIDE {}
     70 
     71   virtual void Register(const invalidation::ObjectId& oid) OVERRIDE {
     72     EXPECT_FALSE(ContainsKey(registered_ids_, oid));
     73     registered_ids_.insert(oid);
     74   }
     75 
     76   virtual void Register(
     77       const std::vector<invalidation::ObjectId>& oids) OVERRIDE {
     78     // Unused for now.
     79   }
     80 
     81   virtual void Unregister(const invalidation::ObjectId& oid) OVERRIDE {
     82     EXPECT_TRUE(ContainsKey(registered_ids_, oid));
     83     registered_ids_.erase(oid);
     84   }
     85 
     86   virtual void Unregister(
     87       const std::vector<invalidation::ObjectId>& oids) OVERRIDE {
     88     // Unused for now.
     89   }
     90 
     91   const ObjectIdSet& GetRegisteredIdsForTest() const {
     92     return registered_ids_;
     93   }
     94 
     95  private:
     96   ObjectIdSet registered_ids_;
     97 
     98   DISALLOW_COPY_AND_ASSIGN(FakeInvalidationClient);
     99 };
    100 
    101 size_t kObjectIdsCount = 5;
    102 
    103 invalidation::ObjectId GetIdForIndex(size_t index) {
    104   char name[2] = "a";
    105   name[0] += static_cast<char>(index);
    106   return invalidation::ObjectId(1 + index, name);
    107 }
    108 
    109 ObjectIdSet GetSequenceOfIdsStartingAt(size_t start, size_t count) {
    110   ObjectIdSet ids;
    111   for (size_t i = start; i < start + count; ++i)
    112     ids.insert(GetIdForIndex(i));
    113   return ids;
    114 }
    115 
    116 ObjectIdSet GetSequenceOfIds(size_t count) {
    117   return GetSequenceOfIdsStartingAt(0, count);
    118 }
    119 
    120 void ExpectPendingRegistrations(
    121     const ObjectIdSet& expected_pending_ids,
    122     double expected_delay_seconds,
    123     const RegistrationManager::PendingRegistrationMap& pending_registrations) {
    124   ObjectIdSet pending_ids;
    125   for (RegistrationManager::PendingRegistrationMap::const_iterator it =
    126            pending_registrations.begin(); it != pending_registrations.end();
    127        ++it) {
    128     SCOPED_TRACE(ObjectIdToString(it->first));
    129     pending_ids.insert(it->first);
    130     base::TimeDelta offset =
    131         it->second.last_registration_request -
    132         it->second.registration_attempt;
    133     base::TimeDelta expected_delay =
    134         base::TimeDelta::FromSeconds(
    135             static_cast<int64>(expected_delay_seconds)) + offset;
    136     // TODO(akalin): Add base::PrintTo() for base::Time and
    137     // base::TimeDeltas.
    138     EXPECT_EQ(expected_delay, it->second.delay)
    139         << expected_delay.InMicroseconds()
    140         << ", " << it->second.delay.InMicroseconds();
    141     if (it->second.delay <= base::TimeDelta()) {
    142       EXPECT_EQ(base::TimeDelta(), it->second.actual_delay);
    143     } else {
    144       EXPECT_EQ(it->second.actual_delay, it->second.delay);
    145     }
    146   }
    147   EXPECT_EQ(expected_pending_ids, pending_ids);
    148 }
    149 
    150 class RegistrationManagerTest : public testing::Test {
    151  protected:
    152   RegistrationManagerTest()
    153       : fake_registration_manager_(&fake_invalidation_client_) {}
    154 
    155   virtual ~RegistrationManagerTest() {}
    156 
    157   void LoseRegistrations(const ObjectIdSet& oids) {
    158     for (ObjectIdSet::const_iterator it = oids.begin(); it != oids.end();
    159          ++it) {
    160       fake_invalidation_client_.LoseRegistration(*it);
    161       fake_registration_manager_.MarkRegistrationLost(*it);
    162     }
    163   }
    164 
    165   void DisableIds(const ObjectIdSet& oids) {
    166     for (ObjectIdSet::const_iterator it = oids.begin(); it != oids.end();
    167          ++it) {
    168       fake_invalidation_client_.LoseRegistration(*it);
    169       fake_registration_manager_.DisableId(*it);
    170     }
    171   }
    172 
    173   // Used by MarkRegistrationLostBackoff* tests.
    174   void RunBackoffTest(double jitter) {
    175     fake_registration_manager_.SetJitter(jitter);
    176     ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);
    177     fake_registration_manager_.UpdateRegisteredIds(ids);
    178 
    179     // Lose some ids.
    180     ObjectIdSet lost_ids = GetSequenceOfIds(2);
    181     LoseRegistrations(lost_ids);
    182     ExpectPendingRegistrations(
    183         lost_ids, 0.0,
    184         fake_registration_manager_.GetPendingRegistrationsForTest());
    185 
    186     // Trigger another failure to start delaying.
    187     fake_registration_manager_.FirePendingRegistrationsForTest();
    188     LoseRegistrations(lost_ids);
    189 
    190     double scaled_jitter =
    191         jitter * RegistrationManager::kRegistrationDelayMaxJitter;
    192 
    193     double expected_delay =
    194         RegistrationManager::kInitialRegistrationDelaySeconds *
    195         (1.0 + scaled_jitter);
    196     expected_delay = std::floor(expected_delay);
    197     ExpectPendingRegistrations(
    198         lost_ids, expected_delay,
    199         fake_registration_manager_.GetPendingRegistrationsForTest());
    200 
    201     // Trigger another failure.
    202     fake_registration_manager_.FirePendingRegistrationsForTest();
    203     LoseRegistrations(lost_ids);
    204     expected_delay *=
    205         RegistrationManager::kRegistrationDelayExponent + scaled_jitter;
    206     expected_delay = std::floor(expected_delay);
    207     ExpectPendingRegistrations(
    208         lost_ids, expected_delay,
    209         fake_registration_manager_.GetPendingRegistrationsForTest());
    210 
    211     // Trigger enough failures to hit the ceiling.
    212     while (expected_delay < RegistrationManager::kMaxRegistrationDelaySeconds) {
    213       fake_registration_manager_.FirePendingRegistrationsForTest();
    214       LoseRegistrations(lost_ids);
    215       expected_delay *=
    216           RegistrationManager::kRegistrationDelayExponent + scaled_jitter;
    217       expected_delay = std::floor(expected_delay);
    218     }
    219     ExpectPendingRegistrations(
    220         lost_ids,
    221         RegistrationManager::kMaxRegistrationDelaySeconds,
    222         fake_registration_manager_.GetPendingRegistrationsForTest());
    223   }
    224 
    225   FakeInvalidationClient fake_invalidation_client_;
    226   FakeRegistrationManager fake_registration_manager_;
    227 
    228  private:
    229   // Needed by timers in RegistrationManager.
    230   base::MessageLoop message_loop_;
    231 
    232   DISALLOW_COPY_AND_ASSIGN(RegistrationManagerTest);
    233 };
    234 
    235 // Basic test of UpdateRegisteredIds to make sure we properly register
    236 // new IDs and unregister any IDs no longer in the set.
    237 TEST_F(RegistrationManagerTest, UpdateRegisteredIds) {
    238   ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount - 1);
    239 
    240   EXPECT_TRUE(fake_registration_manager_.GetRegisteredIdsForTest().empty());
    241   EXPECT_TRUE(fake_invalidation_client_.GetRegisteredIdsForTest().empty());
    242 
    243   ObjectIdSet expected_unregistered_ids;
    244 
    245   ObjectIdSet unregistered_ids =
    246       fake_registration_manager_.UpdateRegisteredIds(ids);
    247   EXPECT_EQ(expected_unregistered_ids, unregistered_ids);
    248   EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest());
    249   EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest());
    250 
    251   ids.insert(GetIdForIndex(kObjectIdsCount - 1));
    252   ids.erase(GetIdForIndex(kObjectIdsCount - 2));
    253   unregistered_ids = fake_registration_manager_.UpdateRegisteredIds(ids);
    254   expected_unregistered_ids.insert(GetIdForIndex(kObjectIdsCount - 2));
    255   EXPECT_EQ(expected_unregistered_ids, unregistered_ids);
    256   EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest());
    257   EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest());
    258 }
    259 
    260 int GetRoundedBackoff(double retry_interval, double jitter) {
    261   const double kInitialRetryInterval = 3.0;
    262   const double kMinRetryInterval = 2.0;
    263   const double kMaxRetryInterval = 20.0;
    264   const double kBackoffExponent = 2.0;
    265   const double kMaxJitter = 0.5;
    266 
    267   return static_cast<int>(
    268       RegistrationManager::CalculateBackoff(retry_interval,
    269                                             kInitialRetryInterval,
    270                                             kMinRetryInterval,
    271                                             kMaxRetryInterval,
    272                                             kBackoffExponent,
    273                                             jitter,
    274                                             kMaxJitter));
    275 }
    276 
    277 TEST_F(RegistrationManagerTest, CalculateBackoff) {
    278   // Test initial.
    279   EXPECT_EQ(2, GetRoundedBackoff(0.0, -1.0));
    280   EXPECT_EQ(3, GetRoundedBackoff(0.0,  0.0));
    281   EXPECT_EQ(4, GetRoundedBackoff(0.0, +1.0));
    282 
    283   // Test non-initial.
    284   EXPECT_EQ(4, GetRoundedBackoff(3.0, -1.0));
    285   EXPECT_EQ(6, GetRoundedBackoff(3.0,  0.0));
    286   EXPECT_EQ(7, GetRoundedBackoff(3.0, +1.0));
    287 
    288   EXPECT_EQ(7, GetRoundedBackoff(5.0, -1.0));
    289   EXPECT_EQ(10, GetRoundedBackoff(5.0,  0.0));
    290   EXPECT_EQ(12, GetRoundedBackoff(5.0, +1.0));
    291 
    292   // Test ceiling.
    293   EXPECT_EQ(19, GetRoundedBackoff(13.0, -1.0));
    294   EXPECT_EQ(20, GetRoundedBackoff(13.0,  0.0));
    295   EXPECT_EQ(20, GetRoundedBackoff(13.0, +1.0));
    296 }
    297 
    298 // Losing a registration should queue automatic re-registration.
    299 TEST_F(RegistrationManagerTest, MarkRegistrationLost) {
    300   ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);
    301 
    302   fake_registration_manager_.UpdateRegisteredIds(ids);
    303   EXPECT_TRUE(
    304       fake_registration_manager_.GetPendingRegistrationsForTest().empty());
    305 
    306   // Lose some ids.
    307   ObjectIdSet lost_ids = GetSequenceOfIds(3);
    308   ObjectIdSet non_lost_ids = GetSequenceOfIdsStartingAt(3, kObjectIdsCount - 3);
    309   LoseRegistrations(lost_ids);
    310   ExpectPendingRegistrations(
    311       lost_ids, 0.0,
    312       fake_registration_manager_.GetPendingRegistrationsForTest());
    313   EXPECT_EQ(non_lost_ids, fake_registration_manager_.GetRegisteredIdsForTest());
    314   EXPECT_EQ(non_lost_ids, fake_invalidation_client_.GetRegisteredIdsForTest());
    315 
    316   // Pretend we waited long enough to re-register.
    317   fake_registration_manager_.FirePendingRegistrationsForTest();
    318   EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest());
    319   EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest());
    320 }
    321 
    322 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffLow) {
    323   RunBackoffTest(-1.0);
    324 }
    325 
    326 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffMid) {
    327   RunBackoffTest(0.0);
    328 }
    329 
    330 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffHigh) {
    331   RunBackoffTest(+1.0);
    332 }
    333 
    334 // Exponential backoff on lost registrations should be reset to zero if
    335 // UpdateRegisteredIds is called.
    336 TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffReset) {
    337   ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);
    338 
    339   fake_registration_manager_.UpdateRegisteredIds(ids);
    340 
    341   // Lose some ids.
    342   ObjectIdSet lost_ids = GetSequenceOfIds(2);
    343   LoseRegistrations(lost_ids);
    344   ExpectPendingRegistrations(
    345       lost_ids, 0.0,
    346       fake_registration_manager_.GetPendingRegistrationsForTest());
    347 
    348   // Trigger another failure to start delaying.
    349   fake_registration_manager_.FirePendingRegistrationsForTest();
    350   LoseRegistrations(lost_ids);
    351   double expected_delay =
    352       RegistrationManager::kInitialRegistrationDelaySeconds;
    353   ExpectPendingRegistrations(
    354       lost_ids, expected_delay,
    355       fake_registration_manager_.GetPendingRegistrationsForTest());
    356 
    357   // Set ids again.
    358   fake_registration_manager_.UpdateRegisteredIds(ids);
    359   ExpectPendingRegistrations(
    360       ObjectIdSet(),
    361       0.0,
    362       fake_registration_manager_.GetPendingRegistrationsForTest());
    363 }
    364 
    365 TEST_F(RegistrationManagerTest, MarkAllRegistrationsLost) {
    366   ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);
    367 
    368   fake_registration_manager_.UpdateRegisteredIds(ids);
    369 
    370   fake_invalidation_client_.LoseAllRegistrations();
    371   fake_registration_manager_.MarkAllRegistrationsLost();
    372 
    373   EXPECT_TRUE(fake_registration_manager_.GetRegisteredIdsForTest().empty());
    374   EXPECT_TRUE(fake_invalidation_client_.GetRegisteredIdsForTest().empty());
    375 
    376   ExpectPendingRegistrations(
    377       ids, 0.0,
    378       fake_registration_manager_.GetPendingRegistrationsForTest());
    379 
    380   // Trigger another failure to start delaying.
    381   fake_registration_manager_.FirePendingRegistrationsForTest();
    382   fake_invalidation_client_.LoseAllRegistrations();
    383   fake_registration_manager_.MarkAllRegistrationsLost();
    384   double expected_delay =
    385       RegistrationManager::kInitialRegistrationDelaySeconds;
    386   ExpectPendingRegistrations(
    387       ids, expected_delay,
    388       fake_registration_manager_.GetPendingRegistrationsForTest());
    389 
    390   // Pretend we waited long enough to re-register.
    391   fake_registration_manager_.FirePendingRegistrationsForTest();
    392   EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest());
    393   EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest());
    394 }
    395 
    396 // IDs that are disabled should not be re-registered by UpdateRegisteredIds or
    397 // automatic re-registration if that registration is lost.
    398 TEST_F(RegistrationManagerTest, DisableId) {
    399   ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);
    400 
    401   fake_registration_manager_.UpdateRegisteredIds(ids);
    402   EXPECT_TRUE(
    403       fake_registration_manager_.GetPendingRegistrationsForTest().empty());
    404 
    405   // Disable some ids.
    406   ObjectIdSet disabled_ids = GetSequenceOfIds(3);
    407   ObjectIdSet enabled_ids = GetSequenceOfIdsStartingAt(3, kObjectIdsCount - 3);
    408   DisableIds(disabled_ids);
    409   ExpectPendingRegistrations(
    410       ObjectIdSet(),
    411       0.0,
    412       fake_registration_manager_.GetPendingRegistrationsForTest());
    413   EXPECT_EQ(enabled_ids, fake_registration_manager_.GetRegisteredIdsForTest());
    414   EXPECT_EQ(enabled_ids, fake_invalidation_client_.GetRegisteredIdsForTest());
    415 
    416   fake_registration_manager_.UpdateRegisteredIds(ids);
    417   EXPECT_EQ(enabled_ids, fake_registration_manager_.GetRegisteredIdsForTest());
    418 
    419   fake_registration_manager_.MarkRegistrationLost(
    420       *disabled_ids.begin());
    421   ExpectPendingRegistrations(
    422       ObjectIdSet(),
    423       0.0,
    424       fake_registration_manager_.GetPendingRegistrationsForTest());
    425 
    426   fake_registration_manager_.MarkAllRegistrationsLost();
    427   ExpectPendingRegistrations(
    428       enabled_ids, 0.0,
    429       fake_registration_manager_.GetPendingRegistrationsForTest());
    430 }
    431 
    432 }  // namespace
    433 }  // namespace syncer
    434