blob: 293914118986ce0f7b909e57230b2da5398ea853 [file] [log] [blame]
[email protected]dc556252011-04-20 01:59:351// 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
13using ::testing::_;
14using ::testing::Eq;
15using ::testing::Mock;
16using ::testing::NiceMock;
17using ::testing::Return;
18using ::testing::SetArgumentPointee;
19
20namespace browser_sync {
21
22using sessions::ErrorCounters;
23using sessions::SyncerStatus;
24using sessions::SyncSessionSnapshot;
25
26class 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,
[email protected]0cc700d2011-05-20 03:53:3156 false, false, 0, 0, 0, false, sessions::SyncSourceInfo(), 0));
[email protected]dc556252011-04-20 01:59:3557 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.
90TEST_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));
[email protected]b2a3c142011-05-05 03:29:5599 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35100
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();
[email protected]b2a3c142011-05-05 03:29:55108 EXPECT_CALL(*manager(), Configure(preferred_types(),
109 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35110 migrator.OnStateChanged();
111 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
112
113 SendConfigureDone(DataTypeManager::OK, preferred_types());
114 EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
115}
116
[email protected]8e8aea772011-06-02 18:43:57117// Test that in the normal case with Nigori a migration transitions through
118// each state and wind up back in IDLE.
119TEST_F(BackendMigratorTest, MigrateNigori) {
120 BackendMigrator migrator(service(), manager());
121 syncable::ModelTypeSet to_migrate, difference;
122 to_migrate.insert(syncable::NIGORI);
123 difference.insert(syncable::AUTOFILL);
124 difference.insert(syncable::BOOKMARKS);
125
126 EXPECT_CALL(*manager(), state())
127 .WillOnce(Return(DataTypeManager::CONFIGURED));
128
129 EXPECT_CALL(*manager(), ConfigureWithoutNigori(_,
130 sync_api::CONFIGURE_REASON_MIGRATION));
131
132 migrator.MigrateTypes(to_migrate);
133 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
134
135 SendConfigureDone(DataTypeManager::OK, difference);
136 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
137
138 ReturnEmptyProgressMarkersInSnapshot();
139 EXPECT_CALL(*manager(), Configure(preferred_types(),
140 sync_api::CONFIGURE_REASON_MIGRATION));
141 migrator.OnStateChanged();
142 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
143
144 SendConfigureDone(DataTypeManager::OK, preferred_types());
145 EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
146}
147
148
[email protected]dc556252011-04-20 01:59:35149// Test that the migrator waits for the data type manager to be idle before
150// starting a migration.
151TEST_F(BackendMigratorTest, WaitToStart) {
152 BackendMigrator migrator(service(), manager());
153 syncable::ModelTypeSet to_migrate;
154 to_migrate.insert(syncable::PREFERENCES);
155
156 EXPECT_CALL(*manager(), state())
157 .WillOnce(Return(DataTypeManager::CONFIGURING));
[email protected]b2a3c142011-05-05 03:29:55158 EXPECT_CALL(*manager(), Configure(_, _)).Times(0);
[email protected]dc556252011-04-20 01:59:35159 migrator.MigrateTypes(to_migrate);
160 EXPECT_EQ(BackendMigrator::WAITING_TO_START, migrator.state());
161
162 Mock::VerifyAndClearExpectations(manager());
163 EXPECT_CALL(*manager(), state())
164 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55165 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35166 SendConfigureDone(DataTypeManager::OK, syncable::ModelTypeSet());
167
168 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
169}
170
171// Test that the migrator can cope with a migration request while a migration
172// is in progress.
173TEST_F(BackendMigratorTest, RestartMigration) {
174 BackendMigrator migrator(service(), manager());
175 syncable::ModelTypeSet to_migrate1, to_migrate2, bookmarks;
176 to_migrate1.insert(syncable::PREFERENCES);
177 to_migrate2.insert(syncable::AUTOFILL);
178 bookmarks.insert(syncable::BOOKMARKS);
179
180 EXPECT_CALL(*manager(), state())
181 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55182 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
183 .Times(1);
[email protected]dc556252011-04-20 01:59:35184 migrator.MigrateTypes(to_migrate1);
185
186 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
187 migrator.MigrateTypes(to_migrate2);
188
189 syncable::ModelTypeSet difference1;
190 std::set_difference(preferred_types().begin(), preferred_types().end(),
191 to_migrate1.begin(), to_migrate1.end(),
192 std::inserter(difference1, difference1.end()));
193
194 Mock::VerifyAndClearExpectations(manager());
195 EXPECT_CALL(*manager(), state())
196 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55197 EXPECT_CALL(*manager(), Configure(bookmarks,
198 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35199 SendConfigureDone(DataTypeManager::OK, difference1);
200 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
201
202 SendConfigureDone(DataTypeManager::OK, bookmarks);
203 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
204}
205
206// Test that an external invocation of Configure(...) during a migration results
207// in a migration reattempt.
208TEST_F(BackendMigratorTest, InterruptedWhileDisablingTypes) {
209 BackendMigrator migrator(service(), manager());
210 syncable::ModelTypeSet to_migrate;
211 syncable::ModelTypeSet difference;
212 to_migrate.insert(syncable::PREFERENCES);
213 difference.insert(syncable::AUTOFILL);
214 difference.insert(syncable::BOOKMARKS);
215
216 EXPECT_CALL(*manager(), state())
217 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55218 EXPECT_CALL(*manager(), Configure(difference,
219 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35220 migrator.MigrateTypes(to_migrate);
221 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
222
223 Mock::VerifyAndClearExpectations(manager());
224 EXPECT_CALL(*manager(), state())
225 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55226 EXPECT_CALL(*manager(), Configure(difference,
227 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35228 SendConfigureDone(DataTypeManager::OK, preferred_types());
229
230 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
231}
232
233// Test that spurious OnStateChanged events don't confuse the migrator while
234// it's waiting for disabled types to have been purged from the sync db.
235TEST_F(BackendMigratorTest, WaitingForPurge) {
236 BackendMigrator migrator(service(), manager());
237 syncable::ModelTypeSet to_migrate, difference;
238 to_migrate.insert(syncable::PREFERENCES);
239 to_migrate.insert(syncable::AUTOFILL);
240 difference.insert(syncable::BOOKMARKS);
241
242 EXPECT_CALL(*manager(), state())
243 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55244 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35245 migrator.MigrateTypes(to_migrate);
246 SendConfigureDone(DataTypeManager::OK, difference);
247 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
248
249 ReturnNonEmptyProgressMarkersInSnapshot(to_migrate);
250 migrator.OnStateChanged();
251 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
252
253 syncable::ModelTypeSet prefs;
254 prefs.insert(syncable::PREFERENCES);
255 ReturnNonEmptyProgressMarkersInSnapshot(prefs);
256 migrator.OnStateChanged();
257 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
258
259 syncable::ModelTypeSet bookmarks;
260 bookmarks.insert(syncable::BOOKMARKS);
261 ReturnNonEmptyProgressMarkersInSnapshot(bookmarks);
[email protected]b2a3c142011-05-05 03:29:55262 EXPECT_CALL(*manager(), Configure(preferred_types(),
263 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35264 migrator.OnStateChanged();
265 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
266}
267
268TEST_F(BackendMigratorTest, MigratedTypeDisabledByUserDuringMigration) {
269 BackendMigrator migrator(service(), manager());
270 syncable::ModelTypeSet to_migrate;
271 to_migrate.insert(syncable::PREFERENCES);
272
273 EXPECT_CALL(*manager(), state())
274 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55275 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35276 migrator.MigrateTypes(to_migrate);
277
278 RemovePreferredType(syncable::PREFERENCES);
279 SendConfigureDone(DataTypeManager::OK, preferred_types());
280 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
281
282 Mock::VerifyAndClearExpectations(manager());
283 ReturnEmptyProgressMarkersInSnapshot();
[email protected]b2a3c142011-05-05 03:29:55284 EXPECT_CALL(*manager(), Configure(preferred_types(),
285 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35286 migrator.OnStateChanged();
287
288 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
289 SendConfigureDone(DataTypeManager::OK, preferred_types());
290 EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
291}
292
293TEST_F(BackendMigratorTest, ConfigureFailure) {
294 BackendMigrator migrator(service(), manager());
295 syncable::ModelTypeSet to_migrate;
296 to_migrate.insert(syncable::PREFERENCES);
297
298 EXPECT_CALL(*manager(), state())
299 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55300 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
301 .Times(1);
[email protected]dc556252011-04-20 01:59:35302 migrator.MigrateTypes(to_migrate);
303 SendConfigureDone(DataTypeManager::ABORTED, syncable::ModelTypeSet());
304 EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
305}
306
307}; // namespace browser_sync