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