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 // Supervised user data types 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
);
101 preferred_data_types
.Remove(syncer::SUPERVISED_USER_WHITELISTS
);
103 // Autofill wallet will be unready during this test, so we should not
104 // request that it be migrated.
105 preferred_data_types
.Remove(syncer::AUTOFILL_WALLET_DATA
);
106 preferred_data_types
.Remove(syncer::AUTOFILL_WALLET_METADATA
);
108 // Make sure all clients have the same preferred data types.
109 for (int i
= 1; i
< num_clients(); ++i
) {
110 const syncer::ModelTypeSet other_preferred_data_types
=
111 GetSyncService((i
))->GetPreferredDataTypes();
112 EXPECT_TRUE(preferred_data_types
.Equals(other_preferred_data_types
));
114 return preferred_data_types
;
117 // Returns a MigrationList with every enabled data type in its own
119 MigrationList
GetPreferredDataTypesList() {
120 MigrationList migration_list
;
121 const syncer::ModelTypeSet preferred_data_types
=
122 GetPreferredDataTypes();
123 for (syncer::ModelTypeSet::Iterator it
=
124 preferred_data_types
.First(); it
.Good(); it
.Inc()) {
125 migration_list
.push_back(MakeSet(it
.Get()));
127 return migration_list
;
130 // Trigger a migration for the given types with the given method.
131 void TriggerMigration(syncer::ModelTypeSet model_types
,
132 TriggerMethod trigger_method
) {
133 switch (trigger_method
) {
135 // Unlike MODIFY_BOOKMARK, MODIFY_PREF doesn't cause a
136 // notification to happen (since model association on a
137 // boolean pref clobbers the local value), so it doesn't work
138 // for anything but single-client tests.
139 ASSERT_EQ(1, num_clients());
140 ASSERT_TRUE(BooleanPrefMatches(prefs::kShowHomeButton
));
141 ChangeBooleanPref(0, prefs::kShowHomeButton
);
143 case MODIFY_BOOKMARK
:
144 ASSERT_TRUE(AddURL(0, IndexedURLTitle(0), GURL(IndexedURL(0))));
146 case TRIGGER_NOTIFICATION
:
147 TriggerNotification(model_types
);
154 // Block until all clients have completed migration for the given
156 void AwaitMigration(syncer::ModelTypeSet migrate_types
) {
157 for (int i
= 0; i
< num_clients(); ++i
) {
158 MigrationWaiter
waiter(migrate_types
, migration_watchers_
[i
]);
160 ASSERT_FALSE(waiter
.TimedOut());
164 // Makes sure migration works with the given migration list and
166 void RunMigrationTest(const MigrationList
& migration_list
,
167 TriggerMethod trigger_method
) {
168 // If we have only one client, turn off notifications to avoid the
169 // possibility of spurious sync cycles.
170 bool do_test_without_notifications
=
171 (trigger_method
!= TRIGGER_NOTIFICATION
&& num_clients() == 1);
173 if (do_test_without_notifications
) {
174 DisableNotifications();
177 // Make sure migration hasn't been triggered prematurely.
178 for (int i
= 0; i
< num_clients(); ++i
) {
179 ASSERT_TRUE(migration_watchers_
[i
]->GetMigratedTypes().Empty());
182 // Phase 1: Trigger the migrations on the server.
183 for (MigrationList::const_iterator it
= migration_list
.begin();
184 it
!= migration_list
.end(); ++it
) {
185 TriggerMigrationDoneError(*it
);
188 // Phase 2: Trigger each migration individually and wait for it to
189 // complete. (Multiple migrations may be handled by each
190 // migration cycle, but there's no guarantee of that, so we have
191 // to trigger each migration individually.)
192 for (MigrationList::const_iterator it
= migration_list
.begin();
193 it
!= migration_list
.end(); ++it
) {
194 TriggerMigration(*it
, trigger_method
);
198 // Phase 3: Wait for all clients to catch up.
200 // AwaitQuiescence() will not succeed when notifications are disabled. We
201 // can safely avoid calling it because we know that, in the single client
202 // case, there is no one else to wait for.
204 // TODO(rlarocque, 97780): Remove the if condition when the test harness
205 // supports calling AwaitQuiescence() when notifications are disabled.
206 if (!do_test_without_notifications
) {
210 // TODO(rlarocque): It should be possible to re-enable notifications
211 // here, but doing so makes some windows tests flaky.
215 // Used to keep track of the migration progress for each sync client.
216 ScopedVector
<MigrationWatcher
> migration_watchers_
;
218 DISALLOW_COPY_AND_ASSIGN(MigrationTest
);
221 class MigrationSingleClientTest
: public MigrationTest
{
223 MigrationSingleClientTest() : MigrationTest(SINGLE_CLIENT_LEGACY
) {}
224 ~MigrationSingleClientTest() override
{}
226 void RunSingleClientMigrationTest(const MigrationList
& migration_list
,
227 TriggerMethod trigger_method
) {
228 ASSERT_TRUE(SetupSync());
229 RunMigrationTest(migration_list
, trigger_method
);
233 DISALLOW_COPY_AND_ASSIGN(MigrationSingleClientTest
);
236 // The simplest possible migration tests -- a single data type.
238 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
, PrefsOnlyModifyPref
) {
239 RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES
), MODIFY_PREF
);
242 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
, PrefsOnlyModifyBookmark
) {
243 RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES
),
247 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
,
248 PrefsOnlyTriggerNotification
) {
249 RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES
),
250 TRIGGER_NOTIFICATION
);
253 // Nigori is handled specially, so we test that separately.
255 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
, NigoriOnly
) {
256 RunSingleClientMigrationTest(MakeList(syncer::PREFERENCES
),
257 TRIGGER_NOTIFICATION
);
260 // A little more complicated -- two data types.
262 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
, BookmarksPrefsIndividually
) {
263 RunSingleClientMigrationTest(
264 MakeList(syncer::BOOKMARKS
, syncer::PREFERENCES
),
268 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
, BookmarksPrefsBoth
) {
269 RunSingleClientMigrationTest(
270 MakeList(MakeSet(syncer::BOOKMARKS
, syncer::PREFERENCES
)),
274 // Two data types with one being nigori.
276 // See crbug.com/124480.
277 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
,
278 DISABLED_PrefsNigoriIndividiaully
) {
279 RunSingleClientMigrationTest(
280 MakeList(syncer::PREFERENCES
, syncer::NIGORI
),
281 TRIGGER_NOTIFICATION
);
284 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
, PrefsNigoriBoth
) {
285 RunSingleClientMigrationTest(
286 MakeList(MakeSet(syncer::PREFERENCES
, syncer::NIGORI
)),
290 // The whole shebang -- all data types.
291 // http://crbug.com/403778
292 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
,
293 DISABLED_AllTypesIndividually
) {
294 ASSERT_TRUE(SetupClients());
295 RunSingleClientMigrationTest(GetPreferredDataTypesList(), MODIFY_BOOKMARK
);
298 // http://crbug.com/403778
299 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
,
300 DISABLED_AllTypesIndividuallyTriggerNotification
) {
301 ASSERT_TRUE(SetupClients());
302 RunSingleClientMigrationTest(GetPreferredDataTypesList(),
303 TRIGGER_NOTIFICATION
);
306 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
, AllTypesAtOnce
) {
307 ASSERT_TRUE(SetupClients());
308 RunSingleClientMigrationTest(MakeList(GetPreferredDataTypes()),
312 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
,
313 AllTypesAtOnceTriggerNotification
) {
314 ASSERT_TRUE(SetupClients());
315 RunSingleClientMigrationTest(MakeList(GetPreferredDataTypes()),
316 TRIGGER_NOTIFICATION
);
319 // All data types plus nigori.
321 // See crbug.com/124480.
322 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
,
323 DISABLED_AllTypesWithNigoriIndividually
) {
324 ASSERT_TRUE(SetupClients());
325 MigrationList migration_list
= GetPreferredDataTypesList();
326 migration_list
.push_front(MakeSet(syncer::NIGORI
));
327 RunSingleClientMigrationTest(migration_list
, MODIFY_BOOKMARK
);
330 IN_PROC_BROWSER_TEST_F(MigrationSingleClientTest
, AllTypesWithNigoriAtOnce
) {
331 ASSERT_TRUE(SetupClients());
332 syncer::ModelTypeSet all_types
= GetPreferredDataTypes();
333 all_types
.Put(syncer::NIGORI
);
334 RunSingleClientMigrationTest(MakeList(all_types
), MODIFY_PREF
);
337 class MigrationTwoClientTest
: public MigrationTest
{
339 MigrationTwoClientTest() : MigrationTest(TWO_CLIENT_LEGACY
) {}
340 ~MigrationTwoClientTest() override
{}
342 // Helper function that verifies that preferences sync still works.
343 void VerifyPrefSync() {
344 ASSERT_TRUE(BooleanPrefMatches(prefs::kShowHomeButton
));
345 ChangeBooleanPref(0, prefs::kShowHomeButton
);
346 ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
347 ASSERT_TRUE(BooleanPrefMatches(prefs::kShowHomeButton
));
350 void RunTwoClientMigrationTest(const MigrationList
& migration_list
,
351 TriggerMethod trigger_method
) {
352 ASSERT_TRUE(SetupSync());
354 // Make sure pref sync works before running the migration test.
357 RunMigrationTest(migration_list
, trigger_method
);
359 // Make sure pref sync still works after running the migration
365 DISALLOW_COPY_AND_ASSIGN(MigrationTwoClientTest
);
368 // Easiest possible test of migration errors: triggers a server
369 // migration on one datatype, then modifies some other datatype.
370 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest
, MigratePrefsThenModifyBookmark
) {
371 RunTwoClientMigrationTest(MakeList(syncer::PREFERENCES
),
375 // Triggers a server migration on two datatypes, then makes a local
376 // modification to one of them.
377 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest
,
378 MigratePrefsAndBookmarksThenModifyBookmark
) {
379 RunTwoClientMigrationTest(
380 MakeList(syncer::PREFERENCES
, syncer::BOOKMARKS
),
384 // Migrate every datatype in sequence; the catch being that the server
385 // will only tell the client about the migrations one at a time.
386 // TODO(rsimha): This test takes longer than 60 seconds, and will cause tree
387 // redness due to sharding.
388 // Re-enable this test after syncer::kInitialBackoffShortRetrySeconds is reduced
390 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest
,
391 DISABLED_MigrationHellWithoutNigori
) {
392 ASSERT_TRUE(SetupClients());
393 MigrationList migration_list
= GetPreferredDataTypesList();
394 // Let the first nudge be a datatype that's neither prefs nor
396 migration_list
.push_front(MakeSet(syncer::THEMES
));
397 RunTwoClientMigrationTest(migration_list
, MODIFY_BOOKMARK
);
400 // See crbug.com/124480.
401 IN_PROC_BROWSER_TEST_F(MigrationTwoClientTest
,
402 DISABLED_MigrationHellWithNigori
) {
403 ASSERT_TRUE(SetupClients());
404 MigrationList migration_list
= GetPreferredDataTypesList();
405 // Let the first nudge be a datatype that's neither prefs nor
407 migration_list
.push_front(MakeSet(syncer::THEMES
));
408 // Pop off one so that we don't migrate all data types; the syncer
409 // freaks out if we do that (see http://crbug.com/94882).
410 ASSERT_GE(migration_list
.size(), 2u);
411 ASSERT_FALSE(migration_list
.back().Equals(MakeSet(syncer::NIGORI
)));
412 migration_list
.back() = MakeSet(syncer::NIGORI
);
413 RunTwoClientMigrationTest(migration_list
, MODIFY_BOOKMARK
);
416 class MigrationReconfigureTest
: public MigrationTwoClientTest
{
418 MigrationReconfigureTest() {}
420 void SetUpCommandLine(base::CommandLine
* cl
) override
{
422 // Do not add optional datatypes.
425 ~MigrationReconfigureTest() override
{}
428 DISALLOW_COPY_AND_ASSIGN(MigrationReconfigureTest
);