Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / backend_migrator_unittest.cc
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 "chrome/browser/sync/backend_migrator.h"
6
7 #include "base/message_loop/message_loop.h"
8 #include "base/tracked_objects.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/sync/profile_sync_service_mock.h"
11 #include "components/sync_driver/data_type_manager_mock.h"
12 #include "sync/internal_api/public/base/model_type_test_util.h"
13 #include "sync/internal_api/public/test/test_user_share.h"
14 #include "sync/internal_api/public/write_transaction.h"
15 #include "sync/protocol/sync.pb.h"
16 #include "sync/syncable/directory.h"  // TODO(tim): Remove. Bug 131130.
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 using ::testing::_;
21 using ::testing::Eq;
22 using ::testing::Mock;
23 using ::testing::NiceMock;
24 using ::testing::Return;
25
26 namespace browser_sync {
27
28 using syncer::sessions::SyncSessionSnapshot;
29
30 class SyncBackendMigratorTest : public testing::Test {
31  public:
32   SyncBackendMigratorTest() : service_(&profile_) { }
33   virtual ~SyncBackendMigratorTest() { }
34
35   virtual void SetUp() {
36     test_user_share_.SetUp();
37     Mock::VerifyAndClear(manager());
38     Mock::VerifyAndClear(&service_);
39     preferred_types_.Put(syncer::BOOKMARKS);
40     preferred_types_.Put(syncer::PREFERENCES);
41     preferred_types_.Put(syncer::AUTOFILL);
42
43     ON_CALL(service_, GetPreferredDataTypes()).
44         WillByDefault(Return(preferred_types_));
45
46     migrator_.reset(
47         new BackendMigrator(
48             "Profile0", test_user_share_.user_share(), service(), manager(),
49             base::Closure()));
50     SetUnsyncedTypes(syncer::ModelTypeSet());
51   }
52
53   virtual void TearDown() {
54     migrator_.reset();
55     test_user_share_.TearDown();
56   }
57
58   // Marks all types in |unsynced_types| as unsynced  and all other
59   // types as synced.
60   void SetUnsyncedTypes(syncer::ModelTypeSet unsynced_types) {
61     syncer::WriteTransaction trans(FROM_HERE,
62                                      test_user_share_.user_share());
63     for (int i = syncer::FIRST_REAL_MODEL_TYPE;
64          i < syncer::MODEL_TYPE_COUNT; ++i) {
65       syncer::ModelType type = syncer::ModelTypeFromInt(i);
66       sync_pb::DataTypeProgressMarker progress_marker;
67       if (!unsynced_types.Has(type)) {
68         progress_marker.set_token("dummy");
69       }
70       trans.GetDirectory()->SetDownloadProgress(type, progress_marker);
71     }
72   }
73
74   void SendConfigureDone(DataTypeManager::ConfigureStatus status,
75                          syncer::ModelTypeSet requested_types) {
76     if (status == DataTypeManager::OK) {
77       DataTypeManager::ConfigureResult result(status, requested_types);
78       migrator_->OnConfigureDone(result);
79     } else {
80       std::map<syncer::ModelType, syncer::SyncError> errors;
81       DataTypeManager::ConfigureResult result(
82           status,
83           requested_types,
84           errors,
85           syncer::ModelTypeSet(),
86           syncer::ModelTypeSet());
87       migrator_->OnConfigureDone(result);
88     }
89     message_loop_.RunUntilIdle();
90   }
91
92   ProfileSyncService* service() { return &service_; }
93   DataTypeManagerMock* manager() { return &manager_; }
94   syncer::ModelTypeSet preferred_types() { return preferred_types_; }
95   BackendMigrator* migrator() { return migrator_.get(); }
96   void RemovePreferredType(syncer::ModelType type) {
97     preferred_types_.Remove(type);
98     Mock::VerifyAndClear(&service_);
99     ON_CALL(service_, GetPreferredDataTypes()).
100         WillByDefault(Return(preferred_types_));
101   }
102
103  private:
104   scoped_ptr<SyncSessionSnapshot> snap_;
105   base::MessageLoop message_loop_;
106   syncer::ModelTypeSet preferred_types_;
107   TestingProfile profile_;
108   NiceMock<ProfileSyncServiceMock> service_;
109   NiceMock<DataTypeManagerMock> manager_;
110   syncer::TestUserShare test_user_share_;
111   scoped_ptr<BackendMigrator> migrator_;
112 };
113
114 class MockMigrationObserver : public MigrationObserver {
115  public:
116   virtual ~MockMigrationObserver() {}
117
118   MOCK_METHOD0(OnMigrationStateChange, void());
119 };
120
121 // Test that in the normal case a migration does transition through each state
122 // and wind up back in IDLE.
123 TEST_F(SyncBackendMigratorTest, Sanity) {
124   MockMigrationObserver migration_observer;
125   migrator()->AddMigrationObserver(&migration_observer);
126   EXPECT_CALL(migration_observer, OnMigrationStateChange()).Times(4);
127
128   syncer::ModelTypeSet to_migrate, difference;
129   to_migrate.Put(syncer::PREFERENCES);
130   difference.Put(syncer::AUTOFILL);
131   difference.Put(syncer::BOOKMARKS);
132
133   EXPECT_CALL(*manager(), state())
134       .WillOnce(Return(DataTypeManager::CONFIGURED));
135   EXPECT_CALL(
136       *manager(),
137       PurgeForMigration(_, syncer::CONFIGURE_REASON_MIGRATION)).Times(1);
138   EXPECT_CALL(
139       *manager(),
140       Configure(_, syncer::CONFIGURE_REASON_MIGRATION)).Times(1);
141
142   migrator()->MigrateTypes(to_migrate);
143   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
144
145   SetUnsyncedTypes(to_migrate);
146   SendConfigureDone(DataTypeManager::OK, difference);
147   EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
148
149   SetUnsyncedTypes(syncer::ModelTypeSet());
150   SendConfigureDone(DataTypeManager::OK, preferred_types());
151   EXPECT_EQ(BackendMigrator::IDLE, migrator()->state());
152
153   migrator()->RemoveMigrationObserver(&migration_observer);
154 }
155
156 // Test that in the normal case with Nigori a migration transitions through
157 // each state and wind up back in IDLE.
158 TEST_F(SyncBackendMigratorTest, MigrateNigori) {
159   syncer::ModelTypeSet to_migrate, difference;
160   to_migrate.Put(syncer::NIGORI);
161   difference.Put(syncer::AUTOFILL);
162   difference.Put(syncer::BOOKMARKS);
163
164   EXPECT_CALL(*manager(), state())
165       .WillOnce(Return(DataTypeManager::CONFIGURED));
166
167   EXPECT_CALL(*manager(), PurgeForMigration(_,
168       syncer::CONFIGURE_REASON_MIGRATION));
169
170   migrator()->MigrateTypes(to_migrate);
171   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
172
173   SetUnsyncedTypes(to_migrate);
174   SendConfigureDone(DataTypeManager::OK, difference);
175   EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
176
177   SetUnsyncedTypes(syncer::ModelTypeSet());
178   SendConfigureDone(DataTypeManager::OK, preferred_types());
179   EXPECT_EQ(BackendMigrator::IDLE, migrator()->state());
180 }
181
182
183 // Test that the migrator waits for the data type manager to be idle before
184 // starting a migration.
185 TEST_F(SyncBackendMigratorTest, WaitToStart) {
186   syncer::ModelTypeSet to_migrate;
187   to_migrate.Put(syncer::PREFERENCES);
188
189   EXPECT_CALL(*manager(), state())
190       .WillOnce(Return(DataTypeManager::CONFIGURING));
191   EXPECT_CALL(*manager(), Configure(_, _)).Times(0);
192   migrator()->MigrateTypes(to_migrate);
193   EXPECT_EQ(BackendMigrator::WAITING_TO_START, migrator()->state());
194
195   Mock::VerifyAndClearExpectations(manager());
196   EXPECT_CALL(*manager(), state())
197       .WillOnce(Return(DataTypeManager::CONFIGURED));
198   EXPECT_CALL(*manager(),
199               PurgeForMigration(_, syncer::CONFIGURE_REASON_MIGRATION));
200   SetUnsyncedTypes(syncer::ModelTypeSet());
201   SendConfigureDone(DataTypeManager::OK, syncer::ModelTypeSet());
202
203   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
204 }
205
206 // Test that the migrator can cope with a migration request while a migration
207 // is in progress.
208 TEST_F(SyncBackendMigratorTest, RestartMigration) {
209   syncer::ModelTypeSet to_migrate1, to_migrate2, to_migrate_union, bookmarks;
210   to_migrate1.Put(syncer::PREFERENCES);
211   to_migrate2.Put(syncer::AUTOFILL);
212   to_migrate_union.Put(syncer::PREFERENCES);
213   to_migrate_union.Put(syncer::AUTOFILL);
214   bookmarks.Put(syncer::BOOKMARKS);
215
216   EXPECT_CALL(*manager(), state())
217       .WillOnce(Return(DataTypeManager::CONFIGURED));
218   EXPECT_CALL(
219       *manager(),
220       PurgeForMigration(_, syncer::CONFIGURE_REASON_MIGRATION)).Times(2);
221   migrator()->MigrateTypes(to_migrate1);
222
223   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
224   migrator()->MigrateTypes(to_migrate2);
225
226   const syncer::ModelTypeSet difference1 =
227       Difference(preferred_types(), to_migrate1);
228
229   Mock::VerifyAndClearExpectations(manager());
230   EXPECT_CALL(
231       *manager(),
232       PurgeForMigration(_, syncer::CONFIGURE_REASON_MIGRATION)).Times(1);
233   EXPECT_CALL(*manager(), Configure(_, syncer::CONFIGURE_REASON_MIGRATION))
234       .Times(1);
235   SetUnsyncedTypes(to_migrate1);
236   SendConfigureDone(DataTypeManager::OK, difference1);
237   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
238
239   SetUnsyncedTypes(to_migrate_union);
240   SendConfigureDone(DataTypeManager::OK, bookmarks);
241   EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
242 }
243
244 // Test that an external invocation of Configure(...) during a migration results
245 // in a migration reattempt.
246 TEST_F(SyncBackendMigratorTest, InterruptedWhileDisablingTypes) {
247   syncer::ModelTypeSet to_migrate;
248   syncer::ModelTypeSet difference;
249   to_migrate.Put(syncer::PREFERENCES);
250   difference.Put(syncer::AUTOFILL);
251   difference.Put(syncer::BOOKMARKS);
252
253   EXPECT_CALL(*manager(), state())
254       .WillOnce(Return(DataTypeManager::CONFIGURED));
255   EXPECT_CALL(*manager(), PurgeForMigration(HasModelTypes(to_migrate),
256       syncer::CONFIGURE_REASON_MIGRATION));
257   migrator()->MigrateTypes(to_migrate);
258   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
259
260   Mock::VerifyAndClearExpectations(manager());
261   EXPECT_CALL(*manager(), PurgeForMigration(HasModelTypes(to_migrate),
262       syncer::CONFIGURE_REASON_MIGRATION));
263   SetUnsyncedTypes(syncer::ModelTypeSet());
264   SendConfigureDone(DataTypeManager::OK, preferred_types());
265
266   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
267 }
268
269 // Test that spurious OnConfigureDone events don't confuse the
270 // migrator while it's waiting for disabled types to have been purged
271 // from the sync db.
272 TEST_F(SyncBackendMigratorTest, WaitingForPurge) {
273   syncer::ModelTypeSet to_migrate, difference;
274   to_migrate.Put(syncer::PREFERENCES);
275   to_migrate.Put(syncer::AUTOFILL);
276   difference.Put(syncer::BOOKMARKS);
277
278   EXPECT_CALL(*manager(), state())
279       .WillOnce(Return(DataTypeManager::CONFIGURED));
280   EXPECT_CALL(
281       *manager(),
282       PurgeForMigration(_, syncer::CONFIGURE_REASON_MIGRATION)).Times(1);
283   EXPECT_CALL(
284       *manager(),
285       Configure(_, syncer::CONFIGURE_REASON_MIGRATION)).Times(1);
286
287   migrator()->MigrateTypes(to_migrate);
288   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
289
290   SendConfigureDone(DataTypeManager::OK, difference);
291   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
292
293   syncer::ModelTypeSet prefs;
294   prefs.Put(syncer::PREFERENCES);
295   SetUnsyncedTypes(prefs);
296   SendConfigureDone(DataTypeManager::OK, difference);
297   EXPECT_EQ(BackendMigrator::DISABLING_TYPES, migrator()->state());
298
299   SetUnsyncedTypes(to_migrate);
300   SendConfigureDone(DataTypeManager::OK, difference);
301   EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
302 }
303
304 TEST_F(SyncBackendMigratorTest, MigratedTypeDisabledByUserDuringMigration) {
305   syncer::ModelTypeSet to_migrate;
306   to_migrate.Put(syncer::PREFERENCES);
307
308   EXPECT_CALL(*manager(), state())
309       .WillOnce(Return(DataTypeManager::CONFIGURED));
310   EXPECT_CALL(
311       *manager(),
312       PurgeForMigration(_, syncer::CONFIGURE_REASON_MIGRATION)).Times(1);
313   EXPECT_CALL(
314       *manager(),
315       Configure(_, syncer::CONFIGURE_REASON_MIGRATION)).Times(1);
316   migrator()->MigrateTypes(to_migrate);
317
318   RemovePreferredType(syncer::PREFERENCES);
319   SetUnsyncedTypes(to_migrate);
320   SendConfigureDone(DataTypeManager::OK, preferred_types());
321   EXPECT_EQ(BackendMigrator::REENABLING_TYPES, migrator()->state());
322   SetUnsyncedTypes(syncer::ModelTypeSet());
323   SendConfigureDone(DataTypeManager::OK, preferred_types());
324   EXPECT_EQ(BackendMigrator::IDLE, migrator()->state());
325 }
326
327 TEST_F(SyncBackendMigratorTest, ConfigureFailure) {
328   syncer::ModelTypeSet to_migrate;
329   to_migrate.Put(syncer::PREFERENCES);
330
331   EXPECT_CALL(*manager(), state())
332       .WillOnce(Return(DataTypeManager::CONFIGURED));
333   EXPECT_CALL(
334       *manager(),
335       PurgeForMigration(_, syncer::CONFIGURE_REASON_MIGRATION)).Times(1);
336   migrator()->MigrateTypes(to_migrate);
337   SetUnsyncedTypes(syncer::ModelTypeSet());
338   SendConfigureDone(DataTypeManager::ABORTED, syncer::ModelTypeSet());
339   EXPECT_EQ(BackendMigrator::IDLE, migrator()->state());
340 }
341
342 };  // namespace browser_sync