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.
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 "components/translate/core/browser/translate_prefs.h"
19 using bookmarks_helper::AddURL;
20 using bookmarks_helper::IndexedURL;
21 using bookmarks_helper::IndexedURLTitle;
23 using preferences_helper::BooleanPrefMatches;
24 using preferences_helper::ChangeBooleanPref;
28 // Utility functions to make a model type set out of a small number of
31 syncer::ModelTypeSet MakeSet(syncer::ModelType type) {
32 return syncer::ModelTypeSet(type);
35 syncer::ModelTypeSet MakeSet(syncer::ModelType type1,
36 syncer::ModelType type2) {
37 return syncer::ModelTypeSet(type1, type2);
40 // An ordered list of model types sets to migrate. Used by
41 // RunMigrationTest().
42 typedef std::deque<syncer::ModelTypeSet> MigrationList;
44 // Utility functions to make a MigrationList out of a small number of
45 // model types / model type sets.
47 MigrationList MakeList(syncer::ModelTypeSet model_types) {
48 return MigrationList(1, model_types);
51 MigrationList MakeList(syncer::ModelTypeSet model_types1,
52 syncer::ModelTypeSet model_types2) {
53 MigrationList migration_list;
54 migration_list.push_back(model_types1);
55 migration_list.push_back(model_types2);
56 return migration_list;
59 MigrationList MakeList(syncer::ModelType type) {
60 return MakeList(MakeSet(type));
63 MigrationList MakeList(syncer::ModelType type1,
64 syncer::ModelType type2) {
65 return MakeList(MakeSet(type1), MakeSet(type2));
69 class MigrationTest : public SyncTest {
71 explicit MigrationTest(TestType test_type) : SyncTest(test_type) {}
72 ~MigrationTest() override {}
74 enum TriggerMethod { MODIFY_PREF, MODIFY_BOOKMARK, TRIGGER_NOTIFICATION };
76 // Set up sync for all profiles and initialize all MigrationWatchers. This
77 // helps ensure that all migration events are captured, even if they were to
78 // occur before a test calls AwaitMigration for a specific profile.
79 bool SetupSync() override {
80 if (!SyncTest::SetupSync())
83 for (int i = 0; i < num_clients(); ++i) {
84 MigrationWatcher* watcher = new MigrationWatcher(GetClient(i));
85 migration_watchers_.push_back(watcher);
90 syncer::ModelTypeSet GetPreferredDataTypes() {
91 // ProfileSyncService must already have been created before we can call
92 // GetPreferredDataTypes().
93 DCHECK(GetSyncService((0)));
94 syncer::ModelTypeSet preferred_data_types =
95 GetSyncService((0))->GetPreferredDataTypes();
96 preferred_data_types.RemoveAll(syncer::ProxyTypes());
98 // The managed user settings will be "unready" during this test, so we
99 // should not request that they be migrated.
100 preferred_data_types.Remove(syncer::SUPERVISED_USER_SETTINGS);
102 // Make sure all clients have the same preferred data types.
103 for (int i = 1; i < num_clients(); ++i) {
104 const syncer::ModelTypeSet other_preferred_data_types =
105 GetSyncService((i))->GetPreferredDataTypes();
106 EXPECT_TRUE(preferred_data_types.Equals(other_preferred_data_types));
108 return preferred_data_types;
111 // Returns a MigrationList with every enabled data type in its own
113 MigrationList GetPreferredDataTypesList() {
114 MigrationList migration_list;
115 const syncer::ModelTypeSet preferred_data_types =
116 GetPreferredDataTypes();
117 for (syncer::ModelTypeSet::Iterator it =
118 preferred_data_types.First(); it.Good(); it.Inc()) {
119 migration_list.push_back(MakeSet(it.Get()));
121 return migration_list;
124 // Trigger a migration for the given types with the given method.
125 void TriggerMigration(syncer::ModelTypeSet model_types,
126 TriggerMethod trigger_method) {
127 switch (trigger_method) {
129 // Unlike MODIFY_BOOKMARK, MODIFY_PREF doesn't cause a
130 // notification to happen (since model association on a
131 // boolean pref clobbers the local value), so it doesn't work
132 // for anything but single-client tests.
133 ASSERT_EQ(1, num_clients());
134 ASSERT_TRUE(BooleanPrefMatches(prefs::kShowHomeButton));
135 ChangeBooleanPref(0, prefs::kShowHomeButton);
137 case MODIFY_BOOKMARK:
138 ASSERT_TRUE(AddURL(0, IndexedURLTitle(0), GURL(IndexedURL(0))));
140 case TRIGGER_NOTIFICATION:
141 TriggerNotification(model_types);
148 // Block until all clients have completed migration for the given
150 void AwaitMigration(syncer::ModelTypeSet migrate_types) {
151 for (int i = 0; i < num_clients(); ++i) {
152 MigrationWaiter waiter(migrate_types, migration_watchers_[i]);
154 ASSERT_FALSE(waiter.TimedOut());
158 // Makes sure migration works with the given migration list and
160 void RunMigrationTest(const MigrationList& migration_list,
161 TriggerMethod trigger_method) {
162 // If we have only one client, turn off notifications to avoid the
163 // possibility of spurious sync cycles.
164 bool do_test_without_notifications =
165 (trigger_method != TRIGGER_NOTIFICATION && num_clients() == 1);
167 if (do_test_without_notifications) {
168 DisableNotifications();
171 // Make sure migration hasn't been triggered prematurely.
172 for (int i = 0; i < num_clients(); ++i) {
173 ASSERT_TRUE(migration_watchers_[i]->GetMigratedTypes().Empty());
176 // Phase 1: Trigger the migrations on the server.
177 for (MigrationList::const_iterator it = migration_list.begin();
178 it != migration_list.end(); ++it) {
179 TriggerMigrationDoneError(*it);
182 // Phase 2: Trigger each migration individually and wait for it to
183 // complete. (Multiple migrations may be handled by each
184 // migration cycle, but there's no guarantee of that, so we have
185 // to trigger each migration individually.)
186 for (MigrationList::const_iterator it = migration_list.begin();
187 it != migration_list.end(); ++it) {
188 TriggerMigration(*it, trigger_method);
192 // Phase 3: Wait for all clients to catch up.
194 // AwaitQuiescence() will not succeed when notifications are disabled. We
195 // can safely avoid calling it because we know that, in the single client
196 // case, there is no one else to wait for.
198 // TODO(rlarocque, 97780): Remove the if condition when the test harness
199 // supports calling AwaitQuiescence() when notifications are disabled.
200 if (!do_test_without_notifications) {
204 // TODO(rlarocque): It should be possible to re-enable notifications
205 // here, but doing so makes some windows tests flaky.
209 // Used to keep track of the migration progress for each sync client.
210 ScopedVector<MigrationWatcher> migration_watchers_;
212 DISALLOW_COPY_AND_ASSIGN(MigrationTest);
215 class MigrationSingleClientTest : public MigrationTest {
217 MigrationSingleClientTest() : MigrationTest(SINGLE_CLIENT_LEGACY) {}
218 ~MigrationSingleClientTest() override {}
220 void RunSingleClientMigrationTest(const MigrationList& migration_list,
221 TriggerMethod trigger_method) {
222 ASSERT_TRUE(SetupSync());
223 RunMigrationTest(migration_list, trigger_method);
227 DISALLOW_COPY_AND_ASSIGN(MigrationSingleClientTest);
230 // The simplest possible migration tests -- a single data type.
232 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, PrefsOnlyModifyPref) {
233 RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES), MODIFY_PREF);
236 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, PrefsOnlyModifyBookmark) {
237 RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES),
241 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
242 PrefsOnlyTriggerNotification) {
243 RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES),
244 TRIGGER_NOTIFICATION);
247 // Nigori is handled specially, so we test that separately.
249 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, NigoriOnly) {
250 RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES),
251 TRIGGER_NOTIFICATION);
254 // A little more complicated -- two data types.
256 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, BookmarksPrefsIndividually) {
257 RunSingleClientMigrationTest(
258 MakeList(syncer::BOOKMARKS, syncer::PREFERENCES),
262 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, BookmarksPrefsBoth) {
263 RunSingleClientMigrationTest(
264 MakeList(MakeSet(syncer::BOOKMARKS, syncer::PREFERENCES)),
268 // Two data types with one being nigori.
270 // See crbug.com/124480.
271 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
272 DISABLED_PrefsNigoriIndividiaully) {
273 RunSingleClientMigrationTest(
274 MakeList(syncer::PREFERENCES, syncer::NIGORI),
275 TRIGGER_NOTIFICATION);
278 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, PrefsNigoriBoth) {
279 RunSingleClientMigrationTest(
280 MakeList(MakeSet(syncer::PREFERENCES, syncer::NIGORI)),
284 // The whole shebang -- all data types.
285 #if defined(OS_WIN) || defined(OS_MACOSX)
286 // http://crbug.com/403778
287 #define MAYBE_AllTypesIndividually DISABLED_AllTypesIndividually
289 #define MAYBE_AllTypesIndividually AllTypesIndividually
291 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, MAYBE_AllTypesIndividually) {
292 ASSERT_TRUE(SetupClients());
293 RunSingleClientMigrationTest(GetPreferredDataTypesList(), MODIFY_BOOKMARK);
296 #if defined(OS_WIN) || defined(OS_MACOSX)
297 // http://crbug.com/403778
298 #define MAYBE_AllTypesIndividuallyTriggerNotification DISABLED_AllTypesIndividuallyTriggerNotification
300 #define MAYBE_AllTypesIndividuallyTriggerNotification AllTypesIndividuallyTriggerNotification
302 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
303 MAYBE_AllTypesIndividuallyTriggerNotification) {
304 ASSERT_TRUE(SetupClients());
305 RunSingleClientMigrationTest(GetPreferredDataTypesList(),
306 TRIGGER_NOTIFICATION);
309 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, AllTypesAtOnce) {
310 ASSERT_TRUE(SetupClients());
311 RunSingleClientMigrationTest(MakeList(GetPreferredDataTypes()),
315 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
316 AllTypesAtOnceTriggerNotification) {
317 ASSERT_TRUE(SetupClients());
318 RunSingleClientMigrationTest(MakeList(GetPreferredDataTypes()),
319 TRIGGER_NOTIFICATION);
322 // All data types plus nigori.
324 // See crbug.com/124480.
325 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest,
326 DISABLED_AllTypesWithNigoriIndividually) {
327 ASSERT_TRUE(SetupClients());
328 MigrationList migration_list = GetPreferredDataTypesList();
329 migration_list.push_front(MakeSet(syncer::NIGORI));
330 RunSingleClientMigrationTest(migration_list, MODIFY_BOOKMARK);
333 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest, AllTypesWithNigoriAtOnce) {
334 ASSERT_TRUE(SetupClients());
335 syncer::ModelTypeSet all_types = GetPreferredDataTypes();
336 all_types.Put(syncer::NIGORI);
337 RunSingleClientMigrationTest(MakeList(all_types), MODIFY_PREF);
340 class MigrationTwoClientTest : public MigrationTest {
342 MigrationTwoClientTest() : MigrationTest(TWO_CLIENT_LEGACY) {}
343 ~MigrationTwoClientTest() override {}
345 // Helper function that verifies that preferences sync still works.
346 void VerifyPrefSync() {
347 ASSERT_TRUE(BooleanPrefMatches(prefs::kShowHomeButton));
348 ChangeBooleanPref(0, prefs::kShowHomeButton);
349 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
350 ASSERT_TRUE(BooleanPrefMatches(prefs::kShowHomeButton));
353 void RunTwoClientMigrationTest(const MigrationList& migration_list,
354 TriggerMethod trigger_method) {
355 ASSERT_TRUE(SetupSync());
357 // Make sure pref sync works before running the migration test.
360 RunMigrationTest(migration_list, trigger_method);
362 // Make sure pref sync still works after running the migration
368 DISALLOW_COPY_AND_ASSIGN(MigrationTwoClientTest);
371 // Easiest possible test of migration errors: triggers a server
372 // migration on one datatype, then modifies some other datatype.
373 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest, MigratePrefsThenModifyBookmark) {
374 RunTwoClientMigrationTest(MakeList(syncer::PREFERENCES),
378 // Triggers a server migration on two datatypes, then makes a local
379 // modification to one of them.
380 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest,
381 MigratePrefsAndBookmarksThenModifyBookmark) {
382 RunTwoClientMigrationTest(
383 MakeList(syncer::PREFERENCES, syncer::BOOKMARKS),
387 // Migrate every datatype in sequence; the catch being that the server
388 // will only tell the client about the migrations one at a time.
389 // TODO(rsimha): This test takes longer than 60 seconds, and will cause tree
390 // redness due to sharding.
391 // Re-enable this test after syncer::kInitialBackoffShortRetrySeconds is reduced
393 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest,
394 DISABLED_MigrationHellWithoutNigori) {
395 ASSERT_TRUE(SetupClients());
396 MigrationList migration_list = GetPreferredDataTypesList();
397 // Let the first nudge be a datatype that's neither prefs nor
399 migration_list.push_front(MakeSet(syncer::THEMES));
400 RunTwoClientMigrationTest(migration_list, MODIFY_BOOKMARK);
403 // See crbug.com/124480.
404 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest,
405 DISABLED_MigrationHellWithNigori) {
406 ASSERT_TRUE(SetupClients());
407 MigrationList migration_list = GetPreferredDataTypesList();
408 // Let the first nudge be a datatype that's neither prefs nor
410 migration_list.push_front(MakeSet(syncer::THEMES));
411 // Pop off one so that we don't migrate all data types; the syncer
412 // freaks out if we do that (see http://crbug.com/94882).
413 ASSERT_GE(migration_list.size(), 2u);
414 ASSERT_FALSE(migration_list.back().Equals(MakeSet(syncer::NIGORI)));
415 migration_list.back() = MakeSet(syncer::NIGORI);
416 RunTwoClientMigrationTest(migration_list, MODIFY_BOOKMARK);
419 class MigrationReconfigureTest : public MigrationTwoClientTest {
421 MigrationReconfigureTest() {}
423 void SetUpCommandLine(base::CommandLine* cl) override {
425 // Do not add optional datatypes.
428 ~MigrationReconfigureTest() override {}
431 DISALLOW_COPY_AND_ASSIGN(MigrationReconfigureTest);