blob: f15602672ba79d493cbfb313caefdc609816c5e4 [file] [log] [blame]
[email protected]b486b462012-02-11 00:11:421// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]dc556252011-04-20 01:59:352// 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
[email protected]1a425fc2011-09-01 23:11:597#include "base/message_loop.h"
8#include "base/tracked_objects.h"
[email protected]dc556252011-04-20 01:59:359#include "chrome/browser/sync/glue/data_type_manager_mock.h"
[email protected]1a425fc2011-09-01 23:11:5910#include "chrome/browser/sync/internal_api/write_transaction.h"
[email protected]dc556252011-04-20 01:59:3511#include "chrome/browser/sync/profile_sync_service_mock.h"
[email protected]1a425fc2011-09-01 23:11:5912#include "chrome/browser/sync/protocol/sync.pb.h"
[email protected]dc556252011-04-20 01:59:3513#include "chrome/browser/sync/sessions/session_state.h"
[email protected]1a425fc2011-09-01 23:11:5914#include "chrome/browser/sync/syncable/directory_manager.h"
[email protected]71229fa82011-12-10 01:00:5415#include "chrome/browser/sync/syncable/model_type_test_util.h"
[email protected]1695f10f2011-09-02 22:16:3216#include "chrome/browser/sync/test/engine/test_user_share.h"
[email protected]432115822011-07-10 15:52:2717#include "chrome/common/chrome_notification_types.h"
[email protected]dc556252011-04-20 01:59:3518#include "testing/gmock/include/gmock/gmock.h"
19#include "testing/gtest/include/gtest/gtest.h"
20
21using ::testing::_;
22using ::testing::Eq;
23using ::testing::Mock;
24using ::testing::NiceMock;
25using ::testing::Return;
[email protected]dc556252011-04-20 01:59:3526
27namespace browser_sync {
28
29using sessions::ErrorCounters;
30using sessions::SyncerStatus;
31using sessions::SyncSessionSnapshot;
32
[email protected]b486b462012-02-11 00:11:4233class SyncBackendMigratorTest : public testing::Test {
[email protected]dc556252011-04-20 01:59:3534 public:
[email protected]b486b462012-02-11 00:11:4235 SyncBackendMigratorTest() { }
36 virtual ~SyncBackendMigratorTest() { }
[email protected]dc556252011-04-20 01:59:3537
38 virtual void SetUp() {
[email protected]1a425fc2011-09-01 23:11:5939 test_user_share_.SetUp();
[email protected]dc556252011-04-20 01:59:3540 Mock::VerifyAndClear(manager());
41 Mock::VerifyAndClear(&service_);
[email protected]71229fa82011-12-10 01:00:5442 preferred_types_.Put(syncable::BOOKMARKS);
43 preferred_types_.Put(syncable::PREFERENCES);
44 preferred_types_.Put(syncable::AUTOFILL);
[email protected]dc556252011-04-20 01:59:3545
[email protected]71229fa82011-12-10 01:00:5446 ON_CALL(service_, GetPreferredDataTypes()).
47 WillByDefault(Return(preferred_types_));
[email protected]1a425fc2011-09-01 23:11:5948
49 migrator_.reset(
50 new BackendMigrator(
51 "Profile0", test_user_share_.user_share(), service(), manager()));
[email protected]400f521a2011-12-13 01:50:2352 SetUnsyncedTypes(syncable::ModelTypeSet());
[email protected]dc556252011-04-20 01:59:3553 }
54
[email protected]1a425fc2011-09-01 23:11:5955 virtual void TearDown() {
56 migrator_.reset();
57 test_user_share_.TearDown();
[email protected]dc556252011-04-20 01:59:3558 }
59
[email protected]1a425fc2011-09-01 23:11:5960 // Marks all types in |unsynced_types| as unsynced and all other
61 // types as synced.
[email protected]400f521a2011-12-13 01:50:2362 void SetUnsyncedTypes(syncable::ModelTypeSet unsynced_types) {
[email protected]1a425fc2011-09-01 23:11:5963 sync_api::WriteTransaction trans(FROM_HERE,
64 test_user_share_.user_share());
65 for (int i = syncable::FIRST_REAL_MODEL_TYPE;
66 i < syncable::MODEL_TYPE_COUNT; ++i) {
67 syncable::ModelType type = syncable::ModelTypeFromInt(i);
68 sync_pb::DataTypeProgressMarker progress_marker;
[email protected]71229fa82011-12-10 01:00:5469 if (!unsynced_types.Has(type)) {
[email protected]1a425fc2011-09-01 23:11:5970 progress_marker.set_token("dummy");
71 }
72 trans.GetLookup()->SetDownloadProgress(type, progress_marker);
[email protected]dc556252011-04-20 01:59:3573 }
[email protected]dc556252011-04-20 01:59:3574 }
75
[email protected]de7d78c72011-07-26 23:41:5076 void SendConfigureDone(DataTypeManager::ConfigureStatus status,
[email protected]400f521a2011-12-13 01:50:2377 syncable::ModelTypeSet requested_types) {
[email protected]de7d78c72011-07-26 23:41:5078 if (status == DataTypeManager::OK) {
[email protected]1a425fc2011-09-01 23:11:5979 DataTypeManager::ConfigureResult result(status, requested_types);
[email protected]ad50def52011-10-19 23:17:0780 content::NotificationService::current()->Notify(
[email protected]de7d78c72011-07-26 23:41:5081 chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
[email protected]6c2381d2011-10-19 02:52:5382 content::Source<DataTypeManager>(&manager_),
83 content::Details<const DataTypeManager::ConfigureResult>(&result));
[email protected]de7d78c72011-07-26 23:41:5084 } else {
[email protected]631b193f2011-10-06 08:07:4685 std::list<SyncError> errors;
86 DataTypeManager::ConfigureResult result(
87 status,
88 requested_types,
89 errors);
[email protected]ad50def52011-10-19 23:17:0790 content::NotificationService::current()->Notify(
[email protected]631b193f2011-10-06 08:07:4691 chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
[email protected]6c2381d2011-10-19 02:52:5392 content::Source<DataTypeManager>(&manager_),
93 content::Details<const DataTypeManager::ConfigureResult>(&result));
[email protected]de7d78c72011-07-26 23:41:5094 }
[email protected]1a425fc2011-09-01 23:11:5995 message_loop_.RunAllPending();
[email protected]dc556252011-04-20 01:59:3596 }
97
98 ProfileSyncService* service() { return &service_; }
99 DataTypeManagerMock* manager() { return &manager_; }
[email protected]400f521a2011-12-13 01:50:23100 syncable::ModelTypeSet preferred_types() { return preferred_types_; }
[email protected]1a425fc2011-09-01 23:11:59101 BackendMigrator* migrator() { return migrator_.get(); }
[email protected]dc556252011-04-20 01:59:35102 void RemovePreferredType(syncable::ModelType type) {
[email protected]71229fa82011-12-10 01:00:54103 preferred_types_.Remove(type);
[email protected]dc556252011-04-20 01:59:35104 Mock::VerifyAndClear(&service_);
[email protected]71229fa82011-12-10 01:00:54105 ON_CALL(service_, GetPreferredDataTypes()).
106 WillByDefault(Return(preferred_types_));
[email protected]dc556252011-04-20 01:59:35107 }
[email protected]1a425fc2011-09-01 23:11:59108
[email protected]dc556252011-04-20 01:59:35109 private:
110 scoped_ptr<SyncSessionSnapshot> snap_;
[email protected]1a425fc2011-09-01 23:11:59111 MessageLoop message_loop_;
[email protected]400f521a2011-12-13 01:50:23112 syncable::ModelTypeSet preferred_types_;
[email protected]dc556252011-04-20 01:59:35113 NiceMock<ProfileSyncServiceMock> service_;
114 NiceMock<DataTypeManagerMock> manager_;
[email protected]1a425fc2011-09-01 23:11:59115 TestUserShare test_user_share_;
116 scoped_ptr<BackendMigrator> migrator_;
117};
118
119class MockMigrationObserver : public MigrationObserver {
120 public:
121 virtual ~MockMigrationObserver() {}
122
123 MOCK_METHOD0(OnMigrationStateChange, void());
[email protected]dc556252011-04-20 01:59:35124};
125
126// Test that in the normal case a migration does transition through each state
127// and wind up back in IDLE.
[email protected]b486b462012-02-11 00:11:42128TEST_F(SyncBackendMigratorTest, Sanity) {
[email protected]1a425fc2011-09-01 23:11:59129 MockMigrationObserver migration_observer;
130 migrator()->AddMigrationObserver(&migration_observer);
131 EXPECT_CALL(migration_observer, OnMigrationStateChange()).Times(4);
132
[email protected]400f521a2011-12-13 01:50:23133 syncable::ModelTypeSet to_migrate, difference;
[email protected]71229fa82011-12-10 01:00:54134 to_migrate.Put(syncable::PREFERENCES);
135 difference.Put(syncable::AUTOFILL);
136 difference.Put(syncable::BOOKMARKS);
[email protected]dc556252011-04-20 01:59:35137
138 EXPECT_CALL(*manager(), state())
139 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]1a425fc2011-09-01 23:11:59140 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
141 .Times(2);
[email protected]dc556252011-04-20 01:59:35142
[email protected]1a425fc2011-09-01 23:11:59143 migrator()->MigrateTypes(to_migrate);
144 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35145
[email protected]1a425fc2011-09-01 23:11:59146 SetUnsyncedTypes(to_migrate);
[email protected]dc556252011-04-20 01:59:35147 SendConfigureDone(DataTypeManager::OK, difference);
[email protected]1a425fc2011-09-01 23:11:59148 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35149
[email protected]400f521a2011-12-13 01:50:23150 SetUnsyncedTypes(syncable::ModelTypeSet());
[email protected]dc556252011-04-20 01:59:35151 SendConfigureDone(DataTypeManager::OK, preferred_types());
[email protected]1a425fc2011-09-01 23:11:59152 EXPECT_EQ(BackendMigrator::IDLE, migrator()->state());
153
154 migrator()->RemoveMigrationObserver(&migration_observer);
[email protected]dc556252011-04-20 01:59:35155}
156
[email protected]8e8aea772011-06-02 18:43:57157// Test that in the normal case with Nigori a migration transitions through
158// each state and wind up back in IDLE.
[email protected]b486b462012-02-11 00:11:42159TEST_F(SyncBackendMigratorTest, MigrateNigori) {
[email protected]400f521a2011-12-13 01:50:23160 syncable::ModelTypeSet to_migrate, difference;
[email protected]71229fa82011-12-10 01:00:54161 to_migrate.Put(syncable::NIGORI);
162 difference.Put(syncable::AUTOFILL);
163 difference.Put(syncable::BOOKMARKS);
[email protected]8e8aea772011-06-02 18:43:57164
165 EXPECT_CALL(*manager(), state())
166 .WillOnce(Return(DataTypeManager::CONFIGURED));
167
168 EXPECT_CALL(*manager(), ConfigureWithoutNigori(_,
169 sync_api::CONFIGURE_REASON_MIGRATION));
170
[email protected]1a425fc2011-09-01 23:11:59171 migrator()->MigrateTypes(to_migrate);
172 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
[email protected]8e8aea772011-06-02 18:43:57173
[email protected]1a425fc2011-09-01 23:11:59174 SetUnsyncedTypes(to_migrate);
[email protected]8e8aea772011-06-02 18:43:57175 SendConfigureDone(DataTypeManager::OK, difference);
[email protected]1a425fc2011-09-01 23:11:59176 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
[email protected]8e8aea772011-06-02 18:43:57177
[email protected]400f521a2011-12-13 01:50:23178 SetUnsyncedTypes(syncable::ModelTypeSet());
[email protected]8e8aea772011-06-02 18:43:57179 SendConfigureDone(DataTypeManager::OK, preferred_types());
[email protected]1a425fc2011-09-01 23:11:59180 EXPECT_EQ(BackendMigrator::IDLE, migrator()->state());
[email protected]8e8aea772011-06-02 18:43:57181}
182
183
[email protected]dc556252011-04-20 01:59:35184// Test that the migrator waits for the data type manager to be idle before
185// starting a migration.
[email protected]b486b462012-02-11 00:11:42186TEST_F(SyncBackendMigratorTest, WaitToStart) {
[email protected]400f521a2011-12-13 01:50:23187 syncable::ModelTypeSet to_migrate;
[email protected]71229fa82011-12-10 01:00:54188 to_migrate.Put(syncable::PREFERENCES);
[email protected]dc556252011-04-20 01:59:35189
190 EXPECT_CALL(*manager(), state())
191 .WillOnce(Return(DataTypeManager::CONFIGURING));
[email protected]b2a3c142011-05-05 03:29:55192 EXPECT_CALL(*manager(), Configure(_, _)).Times(0);
[email protected]1a425fc2011-09-01 23:11:59193 migrator()->MigrateTypes(to_migrate);
194 EXPECT_EQ(BackendMigrator::WAITING_TO_START, migrator()->state());
[email protected]dc556252011-04-20 01:59:35195
196 Mock::VerifyAndClearExpectations(manager());
197 EXPECT_CALL(*manager(), state())
198 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55199 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]400f521a2011-12-13 01:50:23200 SetUnsyncedTypes(syncable::ModelTypeSet());
201 SendConfigureDone(DataTypeManager::OK, syncable::ModelTypeSet());
[email protected]dc556252011-04-20 01:59:35202
[email protected]1a425fc2011-09-01 23:11:59203 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35204}
205
206// Test that the migrator can cope with a migration request while a migration
207// is in progress.
[email protected]b486b462012-02-11 00:11:42208TEST_F(SyncBackendMigratorTest, RestartMigration) {
[email protected]400f521a2011-12-13 01:50:23209 syncable::ModelTypeSet to_migrate1, to_migrate2, to_migrate_union, bookmarks;
[email protected]71229fa82011-12-10 01:00:54210 to_migrate1.Put(syncable::PREFERENCES);
211 to_migrate2.Put(syncable::AUTOFILL);
212 to_migrate_union.Put(syncable::PREFERENCES);
213 to_migrate_union.Put(syncable::AUTOFILL);
214 bookmarks.Put(syncable::BOOKMARKS);
[email protected]dc556252011-04-20 01:59:35215
216 EXPECT_CALL(*manager(), state())
217 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55218 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
[email protected]1a425fc2011-09-01 23:11:59219 .Times(2);
220 migrator()->MigrateTypes(to_migrate1);
[email protected]dc556252011-04-20 01:59:35221
[email protected]1a425fc2011-09-01 23:11:59222 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
223 migrator()->MigrateTypes(to_migrate2);
[email protected]dc556252011-04-20 01:59:35224
[email protected]400f521a2011-12-13 01:50:23225 const syncable::ModelTypeSet difference1 =
[email protected]71229fa82011-12-10 01:00:54226 Difference(preferred_types(), to_migrate1);
[email protected]dc556252011-04-20 01:59:35227
228 Mock::VerifyAndClearExpectations(manager());
[email protected]1a425fc2011-09-01 23:11:59229 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
230 .Times(2);
231 SetUnsyncedTypes(to_migrate1);
[email protected]dc556252011-04-20 01:59:35232 SendConfigureDone(DataTypeManager::OK, difference1);
[email protected]1a425fc2011-09-01 23:11:59233 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35234
[email protected]1a425fc2011-09-01 23:11:59235 SetUnsyncedTypes(to_migrate_union);
[email protected]dc556252011-04-20 01:59:35236 SendConfigureDone(DataTypeManager::OK, bookmarks);
[email protected]1a425fc2011-09-01 23:11:59237 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35238}
239
240// Test that an external invocation of Configure(...) during a migration results
241// in a migration reattempt.
[email protected]b486b462012-02-11 00:11:42242TEST_F(SyncBackendMigratorTest, InterruptedWhileDisablingTypes) {
[email protected]400f521a2011-12-13 01:50:23243 syncable::ModelTypeSet to_migrate;
244 syncable::ModelTypeSet difference;
[email protected]71229fa82011-12-10 01:00:54245 to_migrate.Put(syncable::PREFERENCES);
246 difference.Put(syncable::AUTOFILL);
247 difference.Put(syncable::BOOKMARKS);
[email protected]dc556252011-04-20 01:59:35248
249 EXPECT_CALL(*manager(), state())
250 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]71229fa82011-12-10 01:00:54251 EXPECT_CALL(*manager(), Configure(HasModelTypes(difference),
[email protected]b2a3c142011-05-05 03:29:55252 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]1a425fc2011-09-01 23:11:59253 migrator()->MigrateTypes(to_migrate);
254 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35255
256 Mock::VerifyAndClearExpectations(manager());
[email protected]71229fa82011-12-10 01:00:54257 EXPECT_CALL(*manager(), Configure(HasModelTypes(difference),
[email protected]b2a3c142011-05-05 03:29:55258 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]400f521a2011-12-13 01:50:23259 SetUnsyncedTypes(syncable::ModelTypeSet());
[email protected]dc556252011-04-20 01:59:35260 SendConfigureDone(DataTypeManager::OK, preferred_types());
261
[email protected]1a425fc2011-09-01 23:11:59262 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35263}
264
[email protected]1a425fc2011-09-01 23:11:59265// Test that spurious OnConfigureDone events don't confuse the
266// migrator while it's waiting for disabled types to have been purged
267// from the sync db.
[email protected]b486b462012-02-11 00:11:42268TEST_F(SyncBackendMigratorTest, WaitingForPurge) {
[email protected]400f521a2011-12-13 01:50:23269 syncable::ModelTypeSet to_migrate, difference;
[email protected]71229fa82011-12-10 01:00:54270 to_migrate.Put(syncable::PREFERENCES);
271 to_migrate.Put(syncable::AUTOFILL);
272 difference.Put(syncable::BOOKMARKS);
[email protected]dc556252011-04-20 01:59:35273
274 EXPECT_CALL(*manager(), state())
275 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]1a425fc2011-09-01 23:11:59276 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
277 .Times(2);
[email protected]dc556252011-04-20 01:59:35278
[email protected]1a425fc2011-09-01 23:11:59279 migrator()->MigrateTypes(to_migrate);
280 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
281
282 SendConfigureDone(DataTypeManager::OK, difference);
283 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35284
[email protected]400f521a2011-12-13 01:50:23285 syncable::ModelTypeSet prefs;
[email protected]71229fa82011-12-10 01:00:54286 prefs.Put(syncable::PREFERENCES);
[email protected]1a425fc2011-09-01 23:11:59287 SetUnsyncedTypes(prefs);
288 SendConfigureDone(DataTypeManager::OK, difference);
289 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35290
[email protected]1a425fc2011-09-01 23:11:59291 SetUnsyncedTypes(to_migrate);
292 SendConfigureDone(DataTypeManager::OK, difference);
293 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
[email protected]dc556252011-04-20 01:59:35294}
295
[email protected]b486b462012-02-11 00:11:42296TEST_F(SyncBackendMigratorTest, MigratedTypeDisabledByUserDuringMigration) {
[email protected]400f521a2011-12-13 01:50:23297 syncable::ModelTypeSet to_migrate;
[email protected]71229fa82011-12-10 01:00:54298 to_migrate.Put(syncable::PREFERENCES);
[email protected]dc556252011-04-20 01:59:35299
300 EXPECT_CALL(*manager(), state())
301 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]1a425fc2011-09-01 23:11:59302 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
303 .Times(2);
304 migrator()->MigrateTypes(to_migrate);
[email protected]dc556252011-04-20 01:59:35305
306 RemovePreferredType(syncable::PREFERENCES);
[email protected]1a425fc2011-09-01 23:11:59307 SetUnsyncedTypes(to_migrate);
[email protected]dc556252011-04-20 01:59:35308 SendConfigureDone(DataTypeManager::OK, preferred_types());
[email protected]1a425fc2011-09-01 23:11:59309 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
[email protected]400f521a2011-12-13 01:50:23310 SetUnsyncedTypes(syncable::ModelTypeSet());
[email protected]dc556252011-04-20 01:59:35311 SendConfigureDone(DataTypeManager::OK, preferred_types());
[email protected]1a425fc2011-09-01 23:11:59312 EXPECT_EQ(BackendMigrator::IDLE, migrator()->state());
[email protected]dc556252011-04-20 01:59:35313}
314
[email protected]b486b462012-02-11 00:11:42315TEST_F(SyncBackendMigratorTest, ConfigureFailure) {
[email protected]400f521a2011-12-13 01:50:23316 syncable::ModelTypeSet to_migrate;
[email protected]71229fa82011-12-10 01:00:54317 to_migrate.Put(syncable::PREFERENCES);
[email protected]dc556252011-04-20 01:59:35318
319 EXPECT_CALL(*manager(), state())
320 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55321 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
322 .Times(1);
[email protected]1a425fc2011-09-01 23:11:59323 migrator()->MigrateTypes(to_migrate);
[email protected]400f521a2011-12-13 01:50:23324 SetUnsyncedTypes(syncable::ModelTypeSet());
325 SendConfigureDone(DataTypeManager::ABORTED, syncable::ModelTypeSet());
[email protected]1a425fc2011-09-01 23:11:59326 EXPECT_EQ(BackendMigrator::IDLE, migrator()->state());
[email protected]dc556252011-04-20 01:59:35327}
328
329}; // namespace browser_sync