blob: cdc264370e3245f164770a153010d8402d66725c [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"
[email protected]432115822011-07-10 15:52:2710#include "chrome/common/chrome_notification_types.h"
[email protected]dc556252011-04-20 01:59:3511#include "testing/gmock/include/gmock/gmock.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14using ::testing::_;
15using ::testing::Eq;
16using ::testing::Mock;
17using ::testing::NiceMock;
18using ::testing::Return;
19using ::testing::SetArgumentPointee;
20
21namespace browser_sync {
22
23using sessions::ErrorCounters;
24using sessions::SyncerStatus;
25using sessions::SyncSessionSnapshot;
26
27class BackendMigratorTest : public testing::Test {
28 public:
29 BackendMigratorTest() { }
30 virtual ~BackendMigratorTest() { }
31
32 virtual void SetUp() {
33 Mock::VerifyAndClear(manager());
34 Mock::VerifyAndClear(&service_);
35 preferred_types_.insert(syncable::BOOKMARKS);
36 preferred_types_.insert(syncable::PREFERENCES);
37 preferred_types_.insert(syncable::AUTOFILL);
38
39 ON_CALL(service_, GetPreferredDataTypes(_)).
40 WillByDefault(SetArgumentPointee<0>(preferred_types_));
41 }
42
43 void ReturnEmptyProgressMarkersInSnapshot() {
44 ReturnNonEmptyProgressMarkersInSnapshot(syncable::ModelTypeSet());
45 }
46
47 void ReturnNonEmptyProgressMarkersInSnapshot(
48 const syncable::ModelTypeSet& for_types) {
49 std::string download_progress_markers[syncable::MODEL_TYPE_COUNT];
50 for (syncable::ModelTypeSet::const_iterator it = for_types.begin();
51 it != for_types.end(); ++it) {
52 download_progress_markers[*it] = "foobar";
53 }
54
55 snap_.reset(new SyncSessionSnapshot(SyncerStatus(), ErrorCounters(),
56 0, false, syncable::ModelTypeBitSet(), download_progress_markers,
[email protected]0cc700d2011-05-20 03:53:3157 false, false, 0, 0, 0, false, sessions::SyncSourceInfo(), 0));
[email protected]dc556252011-04-20 01:59:3558 EXPECT_CALL(service_, GetLastSessionSnapshot())
59 .WillOnce(Return(snap_.get()));
60 }
61
62 void SendConfigureDone(DataTypeManager::ConfigureResult result,
63 const syncable::ModelTypeSet& types) {
64 DataTypeManager::ConfigureResultWithErrorLocation result_with_location(
65 result, FROM_HERE, types);
66 NotificationService::current()->Notify(
[email protected]432115822011-07-10 15:52:2767 chrome::NOTIFICATION_SYNC_CONFIGURE_DONE,
[email protected]dc556252011-04-20 01:59:3568 Source<DataTypeManager>(&manager_),
69 Details<DataTypeManager::ConfigureResultWithErrorLocation>(
70 &result_with_location));
71 }
72
73 ProfileSyncService* service() { return &service_; }
74 DataTypeManagerMock* manager() { return &manager_; }
75 const syncable::ModelTypeSet& preferred_types() { return preferred_types_; }
76 void RemovePreferredType(syncable::ModelType type) {
77 preferred_types_.erase(type);
78 Mock::VerifyAndClear(&service_);
79 ON_CALL(service_, GetPreferredDataTypes(_)).
80 WillByDefault(SetArgumentPointee<0>(preferred_types_));
81 }
82 private:
83 scoped_ptr<SyncSessionSnapshot> snap_;
84 syncable::ModelTypeSet preferred_types_;
85 NiceMock<ProfileSyncServiceMock> service_;
86 NiceMock<DataTypeManagerMock> manager_;
87};
88
89// Test that in the normal case a migration does transition through each state
90// and wind up back in IDLE.
91TEST_F(BackendMigratorTest, Sanity) {
92 BackendMigrator migrator(service(), manager());
93 syncable::ModelTypeSet to_migrate, difference;
94 to_migrate.insert(syncable::PREFERENCES);
95 difference.insert(syncable::AUTOFILL);
96 difference.insert(syncable::BOOKMARKS);
97
98 EXPECT_CALL(*manager(), state())
99 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55100 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35101
102 migrator.MigrateTypes(to_migrate);
103 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
104
105 SendConfigureDone(DataTypeManager::OK, difference);
106 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
107
108 ReturnEmptyProgressMarkersInSnapshot();
[email protected]b2a3c142011-05-05 03:29:55109 EXPECT_CALL(*manager(), Configure(preferred_types(),
110 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35111 migrator.OnStateChanged();
112 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
113
114 SendConfigureDone(DataTypeManager::OK, preferred_types());
115 EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
116}
117
[email protected]8e8aea772011-06-02 18:43:57118// Test that in the normal case with Nigori a migration transitions through
119// each state and wind up back in IDLE.
120TEST_F(BackendMigratorTest, MigrateNigori) {
121 BackendMigrator migrator(service(), manager());
122 syncable::ModelTypeSet to_migrate, difference;
123 to_migrate.insert(syncable::NIGORI);
124 difference.insert(syncable::AUTOFILL);
125 difference.insert(syncable::BOOKMARKS);
126
127 EXPECT_CALL(*manager(), state())
128 .WillOnce(Return(DataTypeManager::CONFIGURED));
129
130 EXPECT_CALL(*manager(), ConfigureWithoutNigori(_,
131 sync_api::CONFIGURE_REASON_MIGRATION));
132
133 migrator.MigrateTypes(to_migrate);
134 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
135
136 SendConfigureDone(DataTypeManager::OK, difference);
137 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
138
139 ReturnEmptyProgressMarkersInSnapshot();
140 EXPECT_CALL(*manager(), Configure(preferred_types(),
141 sync_api::CONFIGURE_REASON_MIGRATION));
142 migrator.OnStateChanged();
143 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
144
145 SendConfigureDone(DataTypeManager::OK, preferred_types());
146 EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
147}
148
149
[email protected]dc556252011-04-20 01:59:35150// Test that the migrator waits for the data type manager to be idle before
151// starting a migration.
152TEST_F(BackendMigratorTest, WaitToStart) {
153 BackendMigrator migrator(service(), manager());
154 syncable::ModelTypeSet to_migrate;
155 to_migrate.insert(syncable::PREFERENCES);
156
157 EXPECT_CALL(*manager(), state())
158 .WillOnce(Return(DataTypeManager::CONFIGURING));
[email protected]b2a3c142011-05-05 03:29:55159 EXPECT_CALL(*manager(), Configure(_, _)).Times(0);
[email protected]dc556252011-04-20 01:59:35160 migrator.MigrateTypes(to_migrate);
161 EXPECT_EQ(BackendMigrator::WAITING_TO_START, migrator.state());
162
163 Mock::VerifyAndClearExpectations(manager());
164 EXPECT_CALL(*manager(), state())
165 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55166 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35167 SendConfigureDone(DataTypeManager::OK, syncable::ModelTypeSet());
168
169 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
170}
171
172// Test that the migrator can cope with a migration request while a migration
173// is in progress.
174TEST_F(BackendMigratorTest, RestartMigration) {
175 BackendMigrator migrator(service(), manager());
176 syncable::ModelTypeSet to_migrate1, to_migrate2, bookmarks;
177 to_migrate1.insert(syncable::PREFERENCES);
178 to_migrate2.insert(syncable::AUTOFILL);
179 bookmarks.insert(syncable::BOOKMARKS);
180
181 EXPECT_CALL(*manager(), state())
182 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55183 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
184 .Times(1);
[email protected]dc556252011-04-20 01:59:35185 migrator.MigrateTypes(to_migrate1);
186
187 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
188 migrator.MigrateTypes(to_migrate2);
189
190 syncable::ModelTypeSet difference1;
191 std::set_difference(preferred_types().begin(), preferred_types().end(),
192 to_migrate1.begin(), to_migrate1.end(),
193 std::inserter(difference1, difference1.end()));
194
195 Mock::VerifyAndClearExpectations(manager());
196 EXPECT_CALL(*manager(), state())
197 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55198 EXPECT_CALL(*manager(), Configure(bookmarks,
199 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35200 SendConfigureDone(DataTypeManager::OK, difference1);
201 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
202
203 SendConfigureDone(DataTypeManager::OK, bookmarks);
204 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
205}
206
207// Test that an external invocation of Configure(...) during a migration results
208// in a migration reattempt.
209TEST_F(BackendMigratorTest, InterruptedWhileDisablingTypes) {
210 BackendMigrator migrator(service(), manager());
211 syncable::ModelTypeSet to_migrate;
212 syncable::ModelTypeSet difference;
213 to_migrate.insert(syncable::PREFERENCES);
214 difference.insert(syncable::AUTOFILL);
215 difference.insert(syncable::BOOKMARKS);
216
217 EXPECT_CALL(*manager(), state())
218 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55219 EXPECT_CALL(*manager(), Configure(difference,
220 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35221 migrator.MigrateTypes(to_migrate);
222 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
223
224 Mock::VerifyAndClearExpectations(manager());
225 EXPECT_CALL(*manager(), state())
226 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55227 EXPECT_CALL(*manager(), Configure(difference,
228 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35229 SendConfigureDone(DataTypeManager::OK, preferred_types());
230
231 EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator.state());
232}
233
234// Test that spurious OnStateChanged events don't confuse the migrator while
235// it's waiting for disabled types to have been purged from the sync db.
236TEST_F(BackendMigratorTest, WaitingForPurge) {
237 BackendMigrator migrator(service(), manager());
238 syncable::ModelTypeSet to_migrate, difference;
239 to_migrate.insert(syncable::PREFERENCES);
240 to_migrate.insert(syncable::AUTOFILL);
241 difference.insert(syncable::BOOKMARKS);
242
243 EXPECT_CALL(*manager(), state())
244 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55245 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35246 migrator.MigrateTypes(to_migrate);
247 SendConfigureDone(DataTypeManager::OK, difference);
248 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
249
250 ReturnNonEmptyProgressMarkersInSnapshot(to_migrate);
251 migrator.OnStateChanged();
252 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
253
254 syncable::ModelTypeSet prefs;
255 prefs.insert(syncable::PREFERENCES);
256 ReturnNonEmptyProgressMarkersInSnapshot(prefs);
257 migrator.OnStateChanged();
258 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
259
260 syncable::ModelTypeSet bookmarks;
261 bookmarks.insert(syncable::BOOKMARKS);
262 ReturnNonEmptyProgressMarkersInSnapshot(bookmarks);
[email protected]b2a3c142011-05-05 03:29:55263 EXPECT_CALL(*manager(), Configure(preferred_types(),
264 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35265 migrator.OnStateChanged();
266 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
267}
268
269TEST_F(BackendMigratorTest, MigratedTypeDisabledByUserDuringMigration) {
270 BackendMigrator migrator(service(), manager());
271 syncable::ModelTypeSet to_migrate;
272 to_migrate.insert(syncable::PREFERENCES);
273
274 EXPECT_CALL(*manager(), state())
275 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55276 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35277 migrator.MigrateTypes(to_migrate);
278
279 RemovePreferredType(syncable::PREFERENCES);
280 SendConfigureDone(DataTypeManager::OK, preferred_types());
281 EXPECT_EQ(BackendMigrator::WAITING_FOR_PURGE, migrator.state());
282
283 Mock::VerifyAndClearExpectations(manager());
284 ReturnEmptyProgressMarkersInSnapshot();
[email protected]b2a3c142011-05-05 03:29:55285 EXPECT_CALL(*manager(), Configure(preferred_types(),
286 sync_api::CONFIGURE_REASON_MIGRATION));
[email protected]dc556252011-04-20 01:59:35287 migrator.OnStateChanged();
288
289 EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator.state());
290 SendConfigureDone(DataTypeManager::OK, preferred_types());
291 EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
292}
293
294TEST_F(BackendMigratorTest, ConfigureFailure) {
295 BackendMigrator migrator(service(), manager());
296 syncable::ModelTypeSet to_migrate;
297 to_migrate.insert(syncable::PREFERENCES);
298
299 EXPECT_CALL(*manager(), state())
300 .WillOnce(Return(DataTypeManager::CONFIGURED));
[email protected]b2a3c142011-05-05 03:29:55301 EXPECT_CALL(*manager(), Configure(_, sync_api::CONFIGURE_REASON_MIGRATION))
302 .Times(1);
[email protected]dc556252011-04-20 01:59:35303 migrator.MigrateTypes(to_migrate);
304 SendConfigureDone(DataTypeManager::ABORTED, syncable::ModelTypeSet());
305 EXPECT_EQ(BackendMigrator::IDLE, migrator.state());
306}
307
308}; // namespace browser_sync