1 // Copyright 2014 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/command_line.h"
6 #include "base/file_util.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/run_loop.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/sync/profile_sync_service.h"
12 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
13 #include "chrome/browser/sync/test/integration/preferences_helper.h"
14 #include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
15 #include "chrome/browser/sync/test/integration/sync_test.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/common/pref_names.h"
18 #include "components/bookmarks/browser/bookmark_model.h"
19 #include "sync/internal_api/public/util/sync_db_util.h"
20 #include "sync/test/fake_server/fake_server_verifier.h"
21 #include "sync/util/time.h"
23 using bookmarks_helper::AddFolder;
24 using bookmarks_helper::AddURL;
25 using bookmarks_helper::GetOtherNode;
26 using bookmarks_helper::ModelMatchesVerifier;
27 using bookmarks_helper::Move;
28 using bookmarks_helper::Remove;
29 using sync_integration_test_util::AwaitCommitActivityCompletion;
32 const char kUrl1[] = "http://www.google.com";
33 const char kUrl2[] = "http://map.google.com";
34 const char kUrl3[] = "http://plus.google.com";
35 } // anonymous namespace
37 class SingleClientBackupRollbackTest : public SyncTest {
39 SingleClientBackupRollbackTest() : SyncTest(SINGLE_CLIENT) {}
40 virtual ~SingleClientBackupRollbackTest() {}
42 void DisableBackup() {
43 CommandLine::ForCurrentProcess()->AppendSwitch(
44 switches::kSyncDisableBackup);
47 void DisableRollback() {
48 CommandLine::ForCurrentProcess()->AppendSwitch(
49 switches::kSyncDisableRollback);
52 base::Time GetBackupDbLastModified() {
53 base::RunLoop run_loop;
55 base::Time backup_time;
56 syncer::CheckSyncDbLastModifiedTime(
57 GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup")),
58 base::MessageLoopProxy::current(),
59 base::Bind(&SingleClientBackupRollbackTest::CheckDbCallback,
60 base::Unretained(this), &backup_time));
61 base::MessageLoopProxy::current()->PostTask(
62 FROM_HERE, run_loop.QuitClosure());
68 void CheckDbCallback(base::Time* time_out, base::Time time_in) {
69 *time_out = syncer::ProtoTimeToTime(syncer::TimeToProtoTime(time_in));
72 DISALLOW_COPY_AND_ASSIGN(SingleClientBackupRollbackTest);
75 class SyncBackendStoppedChecker {
77 explicit SyncBackendStoppedChecker(ProfileSyncService* service,
78 base::TimeDelta timeout)
83 expiration_ = base::TimeTicks::Now() + timeout_;
84 base::MessageLoop::current()->PostDelayedTask(
86 base::Bind(&SyncBackendStoppedChecker::PeriodicCheck,
87 base::Unretained(this)),
88 base::TimeDelta::FromSeconds(1));
89 base::MessageLoop::current()->Run();
90 return ProfileSyncService::IDLE == pss_->backend_mode();
94 void PeriodicCheck() {
95 if (ProfileSyncService::IDLE == pss_->backend_mode() ||
96 base::TimeTicks::Now() > expiration_) {
97 base::MessageLoop::current()->Quit();
99 base::MessageLoop::current()->PostDelayedTask(
101 base::Bind(&SyncBackendStoppedChecker::PeriodicCheck,
102 base::Unretained(this)),
103 base::TimeDelta::FromSeconds(1));
107 ProfileSyncService* pss_;
108 base::TimeDelta timeout_;
109 base::TimeTicks expiration_;
112 #if defined(ENABLE_PRE_SYNC_BACKUP)
113 #define MAYBE_TestBackup TestBackup
115 #define MAYBE_TestBackup DISABLED_TestBackup
117 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
119 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
121 // Setup sync, wait for its completion, and make sure changes were synced.
122 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
123 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
124 ASSERT_TRUE(ModelMatchesVerifier(0));
126 // Verify backup DB is created and backup time is set on device info.
127 base::Time backup_time = GetBackupDbLastModified();
128 ASSERT_FALSE(backup_time.is_null());
129 ASSERT_EQ(backup_time, GetSyncService(0)->GetDeviceBackupTimeForTesting());
132 #if defined(ENABLE_PRE_SYNC_BACKUP)
133 #define MAYBE_TestBackupDisabled TestBackupDisabled
135 #define MAYBE_TestBackupDisabled DISABLED_TestBackupDisabled
137 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
138 MAYBE_TestBackupDisabled) {
141 // Setup sync, wait for its completion, and make sure changes were synced.
142 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
143 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
144 ASSERT_TRUE(ModelMatchesVerifier(0));
146 // Verify backup DB is not created and backup time is not set on device info.
147 ASSERT_FALSE(base::PathExists(
148 GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup"))));
149 ASSERT_TRUE(GetSyncService(0)->GetDeviceBackupTimeForTesting().is_null());
152 #if defined(ENABLE_PRE_SYNC_BACKUP)
153 #define MAYBE_TestRollback TestRollback
155 #define MAYBE_TestRollback DISABLED_TestRollback
157 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
158 MAYBE_TestRollback) {
159 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
165 // -> http://mail.google.com "tier1_a_url0"
167 // -> http://www.nhl.com "tier1_b_url0"
168 const BookmarkNode* top = AddFolder(0, GetOtherNode(0), 0, "top");
169 const BookmarkNode* tier1_a = AddFolder(0, top, 0, "tier1_a");
170 const BookmarkNode* tier1_b = AddFolder(0, top, 1, "tier1_b");
171 ASSERT_TRUE(AddURL(0, tier1_a, 0, "tier1_a_url0",
172 GURL("http://mail.google.com")));
173 ASSERT_TRUE(AddURL(0, tier1_b, 0, "tier1_b_url0",
174 GURL("http://www.nhl.com")));
176 // Setup sync, wait for its completion, and make sure changes were synced.
177 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
178 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
179 ASSERT_TRUE(ModelMatchesVerifier(0));
181 // Made bookmark changes while sync is on.
182 Move(0, tier1_a->GetChild(0), tier1_b, 1);
183 Remove(0, tier1_b, 0);
184 ASSERT_TRUE(AddFolder(0, tier1_b, 1, "tier2_c"));
185 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
186 ASSERT_TRUE(ModelMatchesVerifier(0));
188 // Let server to return rollback command on next sync request.
189 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
191 // Make another change to trigger downloading of rollback command.
192 Remove(0, tier1_b, 0);
194 // Wait for rollback to finish and sync backend is completely shut down.
195 SyncBackendStoppedChecker checker(GetSyncService(0),
196 base::TimeDelta::FromSeconds(5));
197 ASSERT_TRUE(checker.Wait());
199 // Verify bookmarks are restored.
200 ASSERT_EQ(1, tier1_a->child_count());
201 const BookmarkNode* url1 = tier1_a->GetChild(0);
202 ASSERT_EQ(GURL("http://mail.google.com"), url1->url());
204 ASSERT_EQ(1, tier1_b->child_count());
205 const BookmarkNode* url2 = tier1_b->GetChild(0);
206 ASSERT_EQ(GURL("http://www.nhl.com"), url2->url());
208 // Backup DB should be deleted after rollback is done.
209 ASSERT_FALSE(base::PathExists(
210 GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup"))));
213 #if defined(ENABLE_PRE_SYNC_BACKUP)
214 #define MAYBE_TestRollbackDisabled TestRollbackDisabled
216 #define MAYBE_TestRollbackDisabled DISABLED_TestRollbackDisabled
218 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
219 MAYBE_TestRollbackDisabled) {
222 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
226 // -> http://mail.google.com "url0"
227 // -> http://www.nhl.com "url1"
228 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
229 GURL("http://mail.google.com")));
230 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
231 GURL("http://www.nhl.com")));
233 // Setup sync, wait for its completion, and make sure changes were synced.
234 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
235 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
236 ASSERT_TRUE(ModelMatchesVerifier(0));
238 // Made bookmark changes while sync is on.
239 Remove(0, GetOtherNode(0), 1);
240 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url2",
241 GURL("http://www.yahoo.com")));
242 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
243 ASSERT_TRUE(ModelMatchesVerifier(0));
245 // Let server to return rollback command on next sync request.
246 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
248 // Make another change to trigger downloading of rollback command.
249 Remove(0, GetOtherNode(0), 0);
251 // Wait for rollback to finish and sync backend is completely shut down.
252 SyncBackendStoppedChecker checker(GetSyncService(0),
253 base::TimeDelta::FromSeconds(5));
254 ASSERT_TRUE(checker.Wait());
256 // With rollback disabled, bookmarks in backup DB should not be restored.
257 // Only bookmark added during sync is present.
258 ASSERT_EQ(1, GetOtherNode(0)->child_count());
259 ASSERT_EQ(GURL("http://www.yahoo.com"),
260 GetOtherNode(0)->GetChild(0)->url());
262 // Backup DB should be deleted after.
263 ASSERT_FALSE(base::PathExists(
264 GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup"))));
267 #if defined(ENABLE_PRE_SYNC_BACKUP)
268 #define MAYBE_TestSyncDisabled TestSyncDisabled
270 #define MAYBE_TestSyncDisabled DISABLED_TestSyncDisabled
272 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
273 MAYBE_TestSyncDisabled) {
274 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
278 // -> http://mail.google.com "url0"
279 // -> http://www.nhl.com "url1"
280 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
281 GURL("http://mail.google.com")));
282 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
283 GURL("http://www.nhl.com")));
285 // Setup sync, wait for its completion, and make sure changes were synced.
286 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
287 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
288 ASSERT_TRUE(ModelMatchesVerifier(0));
290 // Made bookmark changes while sync is on.
291 Remove(0, GetOtherNode(0), 1);
292 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url2",
293 GURL("http://www.yahoo.com")));
294 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
295 ASSERT_TRUE(ModelMatchesVerifier(0));
297 // Let server to return birthday error on next sync request.
298 GetFakeServer()->TriggerError(sync_pb::SyncEnums::NOT_MY_BIRTHDAY);
300 // Make another change to trigger downloading of rollback command.
301 Remove(0, GetOtherNode(0), 0);
303 // Wait for rollback to finish and sync backend is completely shut down.
304 SyncBackendStoppedChecker checker(GetSyncService(0),
305 base::TimeDelta::FromSeconds(5));
306 ASSERT_TRUE(checker.Wait());
308 // Shouldn't restore bookmarks with sign-out only.
309 ASSERT_EQ(1, GetOtherNode(0)->child_count());
310 ASSERT_EQ(GURL("http://www.yahoo.com"),
311 GetOtherNode(0)->GetChild(0)->url());
313 // Backup DB should be deleted after.
314 ASSERT_FALSE(base::PathExists(
315 GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup"))));
318 #if defined(ENABLE_PRE_SYNC_BACKUP)
319 #define MAYBE_RollbackNoBackup RollbackNoBackup
321 #define MAYBE_RollbackNoBackup DISABLED_RollbackNoBackup
323 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
324 MAYBE_RollbackNoBackup) {
325 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
329 // -> http://mail.google.com "url0"
330 // -> http://www.nhl.com "url1"
331 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
332 GURL("http://mail.google.com")));
334 // Setup sync, wait for its completion, and make sure changes were synced.
335 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
336 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
337 ASSERT_TRUE(ModelMatchesVerifier(0));
339 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
340 GURL("http://www.nhl.com")));
344 GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup")),
347 // Let server to return rollback command on next sync request.
348 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
350 // Make another change to trigger downloading of rollback command.
351 Remove(0, GetOtherNode(0), 0);
353 // Wait for backend to completely shut down.
354 SyncBackendStoppedChecker checker(GetSyncService(0),
355 base::TimeDelta::FromSeconds(15));
356 ASSERT_TRUE(checker.Wait());
358 // Without backup DB, bookmarks remain at the state when sync stops.
359 ASSERT_EQ(1, GetOtherNode(0)->child_count());
360 ASSERT_EQ(GURL("http://www.nhl.com"),
361 GetOtherNode(0)->GetChild(0)->url());
364 #if defined(ENABLE_PRE_SYNC_BACKUP)
365 #define MAYBE_DontChangeBookmarkOrdering DontChangeBookmarkOrdering
367 #define MAYBE_DontChangeBookmarkOrdering DISABLED_DontChangeBookmarkOrdering
369 IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
370 MAYBE_DontChangeBookmarkOrdering) {
371 ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
373 const BookmarkNode* sub_folder = AddFolder(0, GetOtherNode(0), 0, "test");
374 ASSERT_TRUE(AddURL(0, sub_folder, 0, "", GURL(kUrl1)));
375 ASSERT_TRUE(AddURL(0, sub_folder, 1, "", GURL(kUrl2)));
376 ASSERT_TRUE(AddURL(0, sub_folder, 2, "", GURL(kUrl3)));
378 // Setup sync, wait for its completion, and make sure changes were synced.
379 ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
380 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
381 ASSERT_TRUE(ModelMatchesVerifier(0));
383 // Made bookmark changes while sync is on.
384 Remove(0, sub_folder, 0);
385 Remove(0, sub_folder, 0);
386 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
387 ASSERT_TRUE(ModelMatchesVerifier(0));
389 // Let server to return rollback command on next sync request.
390 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK);
392 // Make another change to trigger downloading of rollback command.
393 Remove(0, sub_folder, 0);
395 // Wait for rollback to finish and sync backend is completely shut down.
396 SyncBackendStoppedChecker checker(GetSyncService(0),
397 base::TimeDelta::FromSeconds(5));
398 ASSERT_TRUE(checker.Wait());
400 // Verify bookmarks are unchanged.
401 ASSERT_EQ(3, sub_folder->child_count());
402 ASSERT_EQ(GURL(kUrl1), sub_folder->GetChild(0)->url());
403 ASSERT_EQ(GURL(kUrl2), sub_folder->GetChild(1)->url());
404 ASSERT_EQ(GURL(kUrl3), sub_folder->GetChild(2)->url());