cd5c318c2f0e9c8450ecd1f17dee65eac93c07fe
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync / test / integration / migration_test.cc
1 // Copyright 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 "base/compiler_specific.h"
6 #include "base/memory/scoped_vector.h"
7 #include "base/prefs/scoped_user_pref_update.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/sync/profile_sync_service.h"
10 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
11 #include "chrome/browser/sync/test/integration/migration_waiter.h"
12 #include "chrome/browser/sync/test/integration/migration_watcher.h"
13 #include "chrome/browser/sync/test/integration/preferences_helper.h"
14 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
15 #include "chrome/browser/sync/test/integration/sync_test.h"
16 #include "chrome/common/pref_names.h"
17 #include "chrome/test/base/ui_test_utils.h"
18 #include "components/translate/core/browser/translate_prefs.h"
19
20 using bookmarks_helper::AddURL;
21 using bookmarks_helper::IndexedURL;
22 using bookmarks_helper::IndexedURLTitle;
23
24 using preferences_helper::BooleanPrefMatches;
25 using preferences_helper::ChangeBooleanPref;
26
27 namespace {
28
29 // Utility functions to make a model type set out of a small number of
30 // model types.
31
32 syncer::ModelTypeSet MakeSet(syncer::ModelType type) {
33   return syncer::ModelTypeSet(type);
34 }
35
36 syncer::ModelTypeSet MakeSet(syncer::ModelType type1,
37                              syncer::ModelType type2) {
38   return syncer::ModelTypeSet(type1, type2);
39 }
40
41 // An ordered list of model types sets to migrate.  Used by
42 // RunMigrationTest().
43 typedef std::deque<syncer::ModelTypeSet> MigrationList;
44
45 // Utility functions to make a MigrationList out of a small number of
46 // model types / model type sets.
47
48 MigrationList MakeList(syncer::ModelTypeSet model_types) {
49   return MigrationList(1, model_types);
50 }
51
52 MigrationList MakeList(syncer::ModelTypeSet model_types1,
53                        syncer::ModelTypeSet model_types2) {
54   MigrationList migration_list;
55   migration_list.push_back(model_types1);
56   migration_list.push_back(model_types2);
57   return migration_list;
58 }
59
60 MigrationList MakeList(syncer::ModelType type) {
61   return MakeList(MakeSet(type));
62 }
63
64 MigrationList MakeList(syncer::ModelType type1,
65                        syncer::ModelType type2) {
66   return MakeList(MakeSet(type1), MakeSet(type2));
67 }
68
69
70 class MigrationTest : public SyncTest  {
71  public:
72   explicit MigrationTest(TestType test_type) : SyncTest(test_type) {}
73   virtual ~MigrationTest() {}
74
75   enum TriggerMethod { MODIFY_PREF, MODIFY_BOOKMARK, TRIGGER_NOTIFICATION };
76
77   // Set up sync for all profiles and initialize all MigrationWatchers. This
78   // helps ensure that all migration events are captured, even if they were to
79   // occur before a test calls AwaitMigration for a specific profile.
80   virtual bool SetupSync() OVERRIDE {
81     if (!SyncTest::SetupSync())
82       return false;
83
84     for (int i = 0; i < num_clients(); ++i) {
85       MigrationWatcher* watcher = new MigrationWatcher(GetClient(i));
86       migration_watchers_.push_back(watcher);
87     }
88     return true;
89   }
90
91   syncer::ModelTypeSet GetPreferredDataTypes() {
92     // ProfileSyncService must already have been created before we can call
93     // GetPreferredDataTypes().
94     DCHECK(GetSyncService((0)));
95     syncer::ModelTypeSet preferred_data_types =
96         GetSyncService((0))->GetPreferredDataTypes();
97     preferred_data_types.RemoveAll(syncer::ProxyTypes());
98
99     // The managed user settings will be "unready" during this test, so we
100     // should not request that they be migrated.
101     preferred_data_types.Remove(syncer::SUPERVISED_USER_SETTINGS);
102
103     // Make sure all clients have the same preferred data types.
104     for (int i = 1; i < num_clients(); ++i) {
105       const syncer::ModelTypeSet other_preferred_data_types =
106           GetSyncService((i))->GetPreferredDataTypes();
107       EXPECT_TRUE(preferred_data_types.Equals(other_preferred_data_types));
108     }
109     return preferred_data_types;
110   }
111
112   // Returns a MigrationList with every enabled data type in its own
113   // set.
114   MigrationList GetPreferredDataTypesList() {
115     MigrationList migration_list;
116     const syncer::ModelTypeSet preferred_data_types =
117         GetPreferredDataTypes();
118     for (syncer::ModelTypeSet::Iterator it =
119              preferred_data_types.First(); it.Good(); it.Inc()) {
120       migration_list.push_back(MakeSet(it.Get()));
121     }
122     return migration_list;
123   }
124
125   // Trigger a migration for the given types with the given method.
126   void TriggerMigration(syncer::ModelTypeSet model_types,
127                         TriggerMethod trigger_method) {
128     switch (trigger_method) {
129       case MODIFY_PREF:
130         // Unlike MODIFY_BOOKMARK, MODIFY_PREF doesn't cause a
131         // notification to happen (since model association on a
132         // boolean pref clobbers the local value), so it doesn't work
133         // for anything but single-client tests.
134         ASSERT_EQ(1, num_clients());
135         ASSERT_TRUE(BooleanPrefMatches(prefs::kShowHomeButton));
136         ChangeBooleanPref(0, prefs::kShowHomeButton);
137         break;
138       case MODIFY_BOOKMARK:
139         ASSERT_TRUE(AddURL(0, IndexedURLTitle(0), GURL(IndexedURL(0))));
140         break;
141       case TRIGGER_NOTIFICATION:
142         TriggerNotification(model_types);
143         break;
144       default:
145         ADD_FAILURE();
146     }
147   }
148
149   // Block until all clients have completed migration for the given
150   // types.
151   void AwaitMigration(syncer::ModelTypeSet migrate_types) {
152     for (int i = 0; i < num_clients(); ++i) {
153       MigrationWaiter waiter(migrate_types, migration_watchers_[i]);
154       waiter.Wait();
155       ASSERT_FALSE(waiter.TimedOut());
156     }
157   }
158
159   // Makes sure migration works with the given migration list and
160   // trigger method.
161   void RunMigrationTest(const MigrationList& migration_list,
162                         TriggerMethod trigger_method) {
163     // If we have only one client, turn off notifications to avoid the
164     // possibility of spurious sync cycles.
165     bool do_test_without_notifications =
166         (trigger_method != TRIGGER_NOTIFICATION && num_clients() == 1);
167
168     if (do_test_without_notifications) {
169       DisableNotifications();
170     }
171
172     // Make sure migration hasn't been triggered prematurely.
173     for (int i = 0; i < num_clients(); ++i) {
174       ASSERT_TRUE(migration_watchers_[i]->GetMigratedTypes().Empty());
175     }
176
177     // Phase 1: Trigger the migrations on the server.
178     for (MigrationList::const_iterator it = migration_list.begin();
179          it != migration_list.end(); ++it) {
180       TriggerMigrationDoneError(*it);
181     }
182
183     // Phase 2: Trigger each migration individually and wait for it to
184     // complete.  (Multiple migrations may be handled by each
185     // migration cycle, but there's no guarantee of that, so we have
186     // to trigger each migration individually.)
187     for (MigrationList::const_iterator it = migration_list.begin();
188          it != migration_list.end(); ++it) {
189       TriggerMigration(*it, trigger_method);
190       AwaitMigration(*it);
191     }
192
193     // Phase 3: Wait for all clients to catch up.
194     //
195     // AwaitQuiescence() will not succeed when notifications are disabled.  We
196     // can safely avoid calling it because we know that, in the single client
197     // case, there is no one else to wait for.
198     //
199     // TODO(rlarocque, 97780): Remove the if condition when the test harness
200     // supports calling AwaitQuiescence() when notifications are disabled.
201     if (!do_test_without_notifications) {
202       AwaitQuiescence();
203     }
204
205     // TODO(rlarocque): It should be possible to re-enable notifications
206     // here, but doing so makes some windows tests flaky.
207   }
208
209  private:
210   // Used to keep track of the migration progress for each sync client.
211   ScopedVector<MigrationWatcher> migration_watchers_;
212
213   DISALLOW_COPY_AND_ASSIGN(MigrationTest);
214 };
215
216 class MigrationSingleClientTest : public MigrationTest {
217  public:
218   MigrationSingleClientTest() : MigrationTest(SINGLE_CLIENT_LEGACY) {}
219   virtual ~MigrationSingleClientTest() {}
220
221   void RunSingleClientMigrationTest(const MigrationList& migration_list,
222                                     TriggerMethod trigger_method) {
223     ASSERT_TRUE(SetupSync());
224     RunMigrationTest(migration_list, trigger_method);
225   }
226
227  private:
228   DISALLOW_COPY_AND_ASSIGN(MigrationSingleClientTest);
229 };
230
231 // The simplest possible migration tests -- a single data type.
232
233 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, PrefsOnlyModifyPref) {
234   RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES), MODIFY_PREF);
235 }
236
237 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, PrefsOnlyModifyBookmark) {
238   RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES),
239                                MODIFY_BOOKMARK);
240 }
241
242 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
243                        PrefsOnlyTriggerNotification) {
244   RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES),
245                                TRIGGER_NOTIFICATION);
246 }
247
248 // Nigori is handled specially, so we test that separately.
249
250 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, NigoriOnly) {
251   RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES),
252                                TRIGGER_NOTIFICATION);
253 }
254
255 // A little more complicated -- two data types.
256
257 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, BookmarksPrefsIndividually) {
258   RunSingleClientMigrationTest(
259       MakeList(syncer::BOOKMARKS, syncer::PREFERENCES),
260       MODIFY_PREF);
261 }
262
263 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, BookmarksPrefsBoth) {
264   RunSingleClientMigrationTest(
265       MakeList(MakeSet(syncer::BOOKMARKS, syncer::PREFERENCES)),
266       MODIFY_BOOKMARK);
267 }
268
269 // Two data types with one being nigori.
270
271 // See crbug.com/124480.
272 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
273                        DISABLED_PrefsNigoriIndividiaully) {
274   RunSingleClientMigrationTest(
275       MakeList(syncer::PREFERENCES, syncer::NIGORI),
276       TRIGGER_NOTIFICATION);
277 }
278
279 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, PrefsNigoriBoth) {
280   RunSingleClientMigrationTest(
281       MakeList(MakeSet(syncer::PREFERENCES, syncer::NIGORI)),
282       MODIFY_PREF);
283 }
284
285 // The whole shebang -- all data types.
286 #if defined(OS_WIN)
287 // http://crbug.com/403778
288 #define MAYBE_AllTypesIndividually DISABLED_AllTypesIndividually
289 #else
290 #define MAYBE_AllTypesIndividually AllTypesIndividually
291 #endif
292 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, MAYBE_AllTypesIndividually) {
293   ASSERT_TRUE(SetupClients());
294   RunSingleClientMigrationTest(GetPreferredDataTypesList(), MODIFY_BOOKMARK);
295 }
296
297 #if defined(OS_WIN)
298 // http://crbug.com/403778
299 #define MAYBE_AllTypesIndividuallyTriggerNotification DISABLED_AllTypesIndividuallyTriggerNotification
300 #else
301 #define MAYBE_AllTypesIndividuallyTriggerNotification AllTypesIndividuallyTriggerNotification
302 #endif
303 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
304                        MAYBE_AllTypesIndividuallyTriggerNotification) {
305   ASSERT_TRUE(SetupClients());
306   RunSingleClientMigrationTest(GetPreferredDataTypesList(),
307                                TRIGGER_NOTIFICATION);
308 }
309
310 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, AllTypesAtOnce) {
311   ASSERT_TRUE(SetupClients());
312   RunSingleClientMigrationTest(MakeList(GetPreferredDataTypes()),
313                                MODIFY_PREF);
314 }
315
316 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
317                        AllTypesAtOnceTriggerNotification) {
318   ASSERT_TRUE(SetupClients());
319   RunSingleClientMigrationTest(MakeList(GetPreferredDataTypes()),
320                                TRIGGER_NOTIFICATION);
321 }
322
323 // All data types plus nigori.
324
325 // See crbug.com/124480.
326 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
327                        DISABLED_AllTypesWithNigoriIndividually) {
328   ASSERT_TRUE(SetupClients());
329   MigrationList migration_list = GetPreferredDataTypesList();
330   migration_list.push_front(MakeSet(syncer::NIGORI));
331   RunSingleClientMigrationTest(migration_list, MODIFY_BOOKMARK);
332 }
333
334 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, AllTypesWithNigoriAtOnce) {
335   ASSERT_TRUE(SetupClients());
336   syncer::ModelTypeSet all_types = GetPreferredDataTypes();
337   all_types.Put(syncer::NIGORI);
338   RunSingleClientMigrationTest(MakeList(all_types), MODIFY_PREF);
339 }
340
341 class MigrationTwoClientTest : public MigrationTest {
342  public:
343   MigrationTwoClientTest() : MigrationTest(TWO_CLIENT_LEGACY) {}
344   virtual ~MigrationTwoClientTest() {}
345
346   // Helper function that verifies that preferences sync still works.
347   void VerifyPrefSync() {
348     ASSERT_TRUE(BooleanPrefMatches(prefs::kShowHomeButton));
349     ChangeBooleanPref(0, prefs::kShowHomeButton);
350     ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
351     ASSERT_TRUE(BooleanPrefMatches(prefs::kShowHomeButton));
352   }
353
354   void RunTwoClientMigrationTest(const MigrationList& migration_list,
355                                  TriggerMethod trigger_method) {
356     ASSERT_TRUE(SetupSync());
357
358     // Make sure pref sync works before running the migration test.
359     VerifyPrefSync();
360
361     RunMigrationTest(migration_list, trigger_method);
362
363     // Make sure pref sync still works after running the migration
364     // test.
365     VerifyPrefSync();
366   }
367
368  private:
369   DISALLOW_COPY_AND_ASSIGN(MigrationTwoClientTest);
370 };
371
372 // Easiest possible test of migration errors: triggers a server
373 // migration on one datatype, then modifies some other datatype.
374 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest, MigratePrefsThenModifyBookmark) {
375   RunTwoClientMigrationTest(MakeList(syncer::PREFERENCES),
376                             MODIFY_BOOKMARK);
377 }
378
379 // Triggers a server migration on two datatypes, then makes a local
380 // modification to one of them.
381 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest,
382                        MigratePrefsAndBookmarksThenModifyBookmark) {
383   RunTwoClientMigrationTest(
384       MakeList(syncer::PREFERENCES, syncer::BOOKMARKS),
385       MODIFY_BOOKMARK);
386 }
387
388 // Migrate every datatype in sequence; the catch being that the server
389 // will only tell the client about the migrations one at a time.
390 // TODO(rsimha): This test takes longer than 60 seconds, and will cause tree
391 // redness due to sharding.
392 // Re-enable this test after syncer::kInitialBackoffShortRetrySeconds is reduced
393 // to zero.
394 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest,
395                        DISABLED_MigrationHellWithoutNigori) {
396   ASSERT_TRUE(SetupClients());
397   MigrationList migration_list = GetPreferredDataTypesList();
398   // Let the first nudge be a datatype that's neither prefs nor
399   // bookmarks.
400   migration_list.push_front(MakeSet(syncer::THEMES));
401   RunTwoClientMigrationTest(migration_list, MODIFY_BOOKMARK);
402 }
403
404 // See crbug.com/124480.
405 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest,
406                        DISABLED_MigrationHellWithNigori) {
407   ASSERT_TRUE(SetupClients());
408   MigrationList migration_list = GetPreferredDataTypesList();
409   // Let the first nudge be a datatype that's neither prefs nor
410   // bookmarks.
411   migration_list.push_front(MakeSet(syncer::THEMES));
412   // Pop off one so that we don't migrate all data types; the syncer
413   // freaks out if we do that (see http://crbug.com/94882).
414   ASSERT_GE(migration_list.size(), 2u);
415   ASSERT_FALSE(migration_list.back().Equals(MakeSet(syncer::NIGORI)));
416   migration_list.back() = MakeSet(syncer::NIGORI);
417   RunTwoClientMigrationTest(migration_list, MODIFY_BOOKMARK);
418 }
419
420 class MigrationReconfigureTest : public MigrationTwoClientTest {
421  public:
422   MigrationReconfigureTest() {}
423
424   virtual void SetUpCommandLine(base::CommandLine* cl) OVERRIDE {
425     AddTestSwitches(cl);
426     // Do not add optional datatypes.
427   }
428
429   virtual ~MigrationReconfigureTest() {}
430
431  private:
432   DISALLOW_COPY_AND_ASSIGN(MigrationReconfigureTest);
433 };
434
435 }  // namespace