Home | History | Annotate | Download | only in sync
      1 // Copyright (c) 2011 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/backend_migrator.h"
      6 
      7 #include "chrome/browser/sync/glue/data_type_manager_mock.h"
      8 #include "chrome/browser/sync/profile_sync_service_mock.h"
      9 #include "chrome/browser/sync/sessions/session_state.h"
     10 #include "testing/gmock/include/gmock/gmock.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 using ::testing::_;
     14 using ::testing::Eq;
     15 using ::testing::Mock;
     16 using ::testing::NiceMock;
     17 using ::testing::Return;
     18 using ::testing::SetArgumentPointee;
     19 
     20 namespace browser_sync {
     21 
     22 using sessions::ErrorCounters;
     23 using sessions::SyncerStatus;
     24 using sessions::SyncSessionSnapshot;
     25 
     26 class BackendMigratorTest : public testing::Test {
     27  public:
     28   BackendMigratorTest() { }
     29   virtual ~BackendMigratorTest() { }
     30 
     31   virtual void SetUp() {
     32     Mock::VerifyAndClear(manager());
     33     Mock::VerifyAndClear(&service_);
     34     preferred_types_.insert(syncable::BOOKMARKS);
     35     preferred_types_.insert(syncable::PREFERENCES);
     36     preferred_types_.insert(syncable::AUTOFILL);
     37 
     38     ON_CALL(service_, GetPreferredDataTypes(_)).
     39         WillByDefault(SetArgumentPointee<0>(preferred_types_));
     40   }
     41 
     42   void ReturnEmptyProgressMarkersInSnapshot() {
     43     ReturnNonEmptyProgressMarkersInSnapshot(syncable::ModelTypeSet());
     44   }
     45 
     46   void ReturnNonEmptyProgressMarkersInSnapshot(
     47       const syncable::ModelTypeSet& for_types) {
     48     std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
     49     for (syncable::ModelTypeSet::const_iterator it = for_types.begin();
     50          it != for_types.end(); ++it) {
     51       download_progress_markers[*it] = "foobar";
     52     }
     53 
     54     snap_.reset(new SyncSessionSnapshot(SyncerStatus(), ErrorCounters(),
     55         0, false, syncable::ModelTypeBitSet(), download_progress_markers,
     56         false, false, 0, 0, false, sessions::SyncSourceInfo()));
     57     EXPECT_CALL(service_, GetLastSessionSnapshot())
     58         .WillOnce(Return(snap_.get()));
     59   }
     60 
     61   void SendConfigureDone(DataTypeManager::ConfigureResult result,
     62                          const syncable::ModelTypeSet& types) {
     63     DataTypeManager::ConfigureResultWithErrorLocation result_with_location(
     64         result, FROM_HERE, types);
     65     NotificationService::current()->Notify(
     66         NotificationType::SYNC_CONFIGURE_DONE,
     67         Source<DataTypeManager>(&manager_),
     68         Details<DataTypeManager::ConfigureResultWithErrorLocation>(
     69             &result_with_location));
     70   }
     71 
     72   ProfileSyncService* service() { return &service_; }
     73   DataTypeManagerMock* manager() { return &manager_; }
     74   const syncable::ModelTypeSet& preferred_types() { return preferred_types_; }
     75   void RemovePreferredType(syncable::ModelType type) {
     76     preferred_types_.erase(type);
     77     Mock::VerifyAndClear(&service_);
     78     ON_CALL(service_, GetPreferredDataTypes(_)).
     79         WillByDefault(SetArgumentPointee<0>(preferred_types_));
     80   }
     81  private:
     82   scoped_ptr<SyncSessionSnapshot> snap_;
     83   syncable::ModelTypeSet preferred_types_;
     84   NiceMock<ProfileSyncServiceMock> service_;
     85   NiceMock<DataTypeManagerMock> manager_;
     86 };
     87 
     88 // Test that in the normal case a migration does transition through each state
     89 // and wind up back in IDLE.
     90 TEST_F(BackendMigratorTest, Sanity) {
     91   BackendMigrator migrator(service(), manager());
     92   syncable::ModelTypeSet to_migrate, difference;
     93   to_migrate.insert(syncable::PREFERENCES);
     94   difference.insert(syncable::AUTOFILL);
     95   difference.insert(syncable::BOOKMARKS);
     96 
     97   EXPECT_CALL(*manager(), state())
     98       .WillOnce(Return(DataTypeManager::CONFIGURED));
     99   EXPECT_CALL(*manager(), Configure(_));
    100 
    101   migrator.MigrateTypes(to_migrate);
    102   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
    103 
    104   SendConfigureDone(DataTypeManager::OK, difference);
    105   EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
    106 
    107   ReturnEmptyProgressMarkersInSnapshot();
    108   EXPECT_CALL(*manager(), Configure(preferred_types()));
    109   migrator.OnStateChanged();
    110   EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
    111 
    112   SendConfigureDone(DataTypeManager::OK, preferred_types());
    113   EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
    114 }
    115 
    116 // Test that the migrator waits for the data type manager to be idle before
    117 // starting a migration.
    118 TEST_F(BackendMigratorTest, WaitToStart) {
    119   BackendMigrator migrator(service(), manager());
    120   syncable::ModelTypeSet to_migrate;
    121   to_migrate.insert(syncable::PREFERENCES);
    122 
    123   EXPECT_CALL(*manager(), state())
    124       .WillOnce(Return(DataTypeManager::CONFIGURING));
    125   EXPECT_CALL(*manager(), Configure(_)).Times(0);
    126   migrator.MigrateTypes(to_migrate);
    127   EXPECT_EQ(BackendMigrator::WAITING_TO_START, migrator.state());
    128 
    129   Mock::VerifyAndClearExpectations(manager());
    130   EXPECT_CALL(*manager(), state())
    131       .WillOnce(Return(DataTypeManager::CONFIGURED));
    132   EXPECT_CALL(*manager(), Configure(_));
    133   SendConfigureDone(DataTypeManager::OK, syncable::ModelTypeSet());
    134 
    135   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
    136 }
    137 
    138 // Test that the migrator can cope with a migration request while a migration
    139 // is in progress.
    140 TEST_F(BackendMigratorTest, RestartMigration) {
    141   BackendMigrator migrator(service(), manager());
    142   syncable::ModelTypeSet to_migrate1, to_migrate2, bookmarks;
    143   to_migrate1.insert(syncable::PREFERENCES);
    144   to_migrate2.insert(syncable::AUTOFILL);
    145   bookmarks.insert(syncable::BOOKMARKS);
    146 
    147   EXPECT_CALL(*manager(), state())
    148       .WillOnce(Return(DataTypeManager::CONFIGURED));
    149   EXPECT_CALL(*manager(), Configure(_)).Times(1);
    150   migrator.MigrateTypes(to_migrate1);
    151 
    152   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
    153   migrator.MigrateTypes(to_migrate2);
    154 
    155   syncable::ModelTypeSet difference1;
    156   std::set_difference(preferred_types().begin(), preferred_types().end(),
    157                       to_migrate1.begin(), to_migrate1.end(),
    158                       std::inserter(difference1, difference1.end()));
    159 
    160   Mock::VerifyAndClearExpectations(manager());
    161   EXPECT_CALL(*manager(), state())
    162       .WillOnce(Return(DataTypeManager::CONFIGURED));
    163   EXPECT_CALL(*manager(), Configure(bookmarks));
    164   SendConfigureDone(DataTypeManager::OK, difference1);
    165   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
    166 
    167   SendConfigureDone(DataTypeManager::OK, bookmarks);
    168   EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
    169 }
    170 
    171 // Test that an external invocation of Configure(...) during a migration results
    172 // in a migration reattempt.
    173 TEST_F(BackendMigratorTest, InterruptedWhileDisablingTypes) {
    174   BackendMigrator migrator(service(), manager());
    175   syncable::ModelTypeSet to_migrate;
    176   syncable::ModelTypeSet difference;
    177   to_migrate.insert(syncable::PREFERENCES);
    178   difference.insert(syncable::AUTOFILL);
    179   difference.insert(syncable::BOOKMARKS);
    180 
    181   EXPECT_CALL(*manager(), state())
    182       .WillOnce(Return(DataTypeManager::CONFIGURED));
    183   EXPECT_CALL(*manager(), Configure(difference));
    184   migrator.MigrateTypes(to_migrate);
    185   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
    186 
    187   Mock::VerifyAndClearExpectations(manager());
    188   EXPECT_CALL(*manager(), state())
    189       .WillOnce(Return(DataTypeManager::CONFIGURED));
    190   EXPECT_CALL(*manager(), Configure(difference));
    191   SendConfigureDone(DataTypeManager::OK, preferred_types());
    192 
    193   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
    194 }
    195 
    196 // Test that spurious OnStateChanged events don't confuse the migrator while
    197 // it's waiting for disabled types to have been purged from the sync db.
    198 TEST_F(BackendMigratorTest, WaitingForPurge) {
    199   BackendMigrator migrator(service(), manager());
    200   syncable::ModelTypeSet to_migrate, difference;
    201   to_migrate.insert(syncable::PREFERENCES);
    202   to_migrate.insert(syncable::AUTOFILL);
    203   difference.insert(syncable::BOOKMARKS);
    204 
    205   EXPECT_CALL(*manager(), state())
    206       .WillOnce(Return(DataTypeManager::CONFIGURED));
    207   EXPECT_CALL(*manager(), Configure(_));
    208   migrator.MigrateTypes(to_migrate);
    209   SendConfigureDone(DataTypeManager::OK, difference);
    210   EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
    211 
    212   ReturnNonEmptyProgressMarkersInSnapshot(to_migrate);
    213   migrator.OnStateChanged();
    214   EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
    215 
    216   syncable::ModelTypeSet prefs;
    217   prefs.insert(syncable::PREFERENCES);
    218   ReturnNonEmptyProgressMarkersInSnapshot(prefs);
    219   migrator.OnStateChanged();
    220   EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
    221 
    222   syncable::ModelTypeSet bookmarks;
    223   bookmarks.insert(syncable::BOOKMARKS);
    224   ReturnNonEmptyProgressMarkersInSnapshot(bookmarks);
    225   EXPECT_CALL(*manager(), Configure(preferred_types()));
    226   migrator.OnStateChanged();
    227   EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
    228 }
    229 
    230 TEST_F(BackendMigratorTest, MigratedTypeDisabledByUserDuringMigration) {
    231   BackendMigrator migrator(service(), manager());
    232   syncable::ModelTypeSet to_migrate;
    233   to_migrate.insert(syncable::PREFERENCES);
    234 
    235   EXPECT_CALL(*manager(), state())
    236       .WillOnce(Return(DataTypeManager::CONFIGURED));
    237   EXPECT_CALL(*manager(), Configure(_));
    238   migrator.MigrateTypes(to_migrate);
    239 
    240   RemovePreferredType(syncable::PREFERENCES);
    241   SendConfigureDone(DataTypeManager::OK, preferred_types());
    242   EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
    243 
    244   Mock::VerifyAndClearExpectations(manager());
    245   ReturnEmptyProgressMarkersInSnapshot();
    246   EXPECT_CALL(*manager(), Configure(preferred_types()));
    247   migrator.OnStateChanged();
    248 
    249   EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
    250   SendConfigureDone(DataTypeManager::OK, preferred_types());
    251   EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
    252 }
    253 
    254 TEST_F(BackendMigratorTest, ConfigureFailure) {
    255   BackendMigrator migrator(service(), manager());
    256   syncable::ModelTypeSet to_migrate;
    257   to_migrate.insert(syncable::PREFERENCES);
    258 
    259   EXPECT_CALL(*manager(), state())
    260       .WillOnce(Return(DataTypeManager::CONFIGURED));
    261   EXPECT_CALL(*manager(), Configure(_)).Times(1);
    262   migrator.MigrateTypes(to_migrate);
    263   SendConfigureDone(DataTypeManager::ABORTED, syncable::ModelTypeSet());
    264   EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
    265 }
    266 
    267 };  // namespace browser_sync
    268