single_client_backup_rollback_test.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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. 4 5#include "base/command_line.h" 6#include "base/message_loop/message_loop.h" 7#include "base/prefs/pref_service.h" 8#include "base/run_loop.h" 9#include "chrome/browser/profiles/profile.h" 10#include "chrome/browser/sync/profile_sync_service.h" 11#include "chrome/browser/sync/test/integration/bookmarks_helper.h" 12#include "chrome/browser/sync/test/integration/preferences_helper.h" 13#include "chrome/browser/sync/test/integration/sync_integration_test_util.h" 14#include "chrome/browser/sync/test/integration/sync_test.h" 15#include "chrome/common/chrome_switches.h" 16#include "chrome/common/pref_names.h" 17#include "components/bookmarks/browser/bookmark_model.h" 18#include "sync/internal_api/public/util/sync_db_util.h" 19#include "sync/test/fake_server/fake_server_verifier.h" 20#include "sync/util/time.h" 21 22using bookmarks_helper::AddFolder; 23using bookmarks_helper::AddURL; 24using bookmarks_helper::GetOtherNode; 25using bookmarks_helper::ModelMatchesVerifier; 26using bookmarks_helper::Move; 27using bookmarks_helper::Remove; 28using sync_integration_test_util::AwaitCommitActivityCompletion; 29 30namespace { 31const char kUrl1[] = "http://www.google.com"; 32const char kUrl2[] = "http://map.google.com"; 33const char kUrl3[] = "http://plus.google.com"; 34} // anonymous namespace 35 36class SingleClientBackupRollbackTest : public SyncTest { 37 public: 38 SingleClientBackupRollbackTest() : SyncTest(SINGLE_CLIENT) {} 39 virtual ~SingleClientBackupRollbackTest() {} 40 41 void DisableBackup() { 42 CommandLine::ForCurrentProcess()->AppendSwitch( 43 switches::kSyncDisableBackup); 44 } 45 46 void DisableRollback() { 47 CommandLine::ForCurrentProcess()->AppendSwitch( 48 switches::kSyncDisableRollback); 49 } 50 51 base::Time GetBackupDbLastModified() { 52 base::RunLoop run_loop; 53 54 base::Time backup_time; 55 syncer::CheckSyncDbLastModifiedTime( 56 GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup")), 57 base::MessageLoopProxy::current(), 58 base::Bind(&SingleClientBackupRollbackTest::CheckDbCallback, 59 base::Unretained(this), &backup_time)); 60 base::MessageLoopProxy::current()->PostTask( 61 FROM_HERE, run_loop.QuitClosure()); 62 run_loop.Run(); 63 return backup_time; 64 } 65 66 private: 67 void CheckDbCallback(base::Time* time_out, base::Time time_in) { 68 *time_out = syncer::ProtoTimeToTime(syncer::TimeToProtoTime(time_in)); 69 } 70 71 DISALLOW_COPY_AND_ASSIGN(SingleClientBackupRollbackTest); 72}; 73 74class BackupModeChecker { 75 public: 76 explicit BackupModeChecker(ProfileSyncService* service, 77 base::TimeDelta timeout) 78 : pss_(service), 79 timeout_(timeout) {} 80 81 bool Wait() { 82 expiration_ = base::TimeTicks::Now() + timeout_; 83 base::MessageLoop::current()->PostDelayedTask( 84 FROM_HERE, 85 base::Bind(&BackupModeChecker::PeriodicCheck, base::Unretained(this)), 86 base::TimeDelta::FromSeconds(1)); 87 base::MessageLoop::current()->Run(); 88 return IsBackupComplete(); 89 } 90 91 private: 92 void PeriodicCheck() { 93 if (IsBackupComplete() || base::TimeTicks::Now() > expiration_) { 94 base::MessageLoop::current()->Quit(); 95 } else { 96 base::MessageLoop::current()->PostDelayedTask( 97 FROM_HERE, 98 base::Bind(&BackupModeChecker::PeriodicCheck, base::Unretained(this)), 99 base::TimeDelta::FromSeconds(1)); 100 } 101 } 102 103 bool IsBackupComplete() { 104 return pss_->backend_mode() == ProfileSyncService::BACKUP && 105 pss_->ShouldPushChanges(); 106 } 107 108 ProfileSyncService* pss_; 109 base::TimeDelta timeout_; 110 base::TimeTicks expiration_; 111}; 112 113#if defined(ENABLE_PRE_SYNC_BACKUP) 114#define MAYBE_TestBackupDisabled TestBackupDisabled 115#else 116#define MAYBE_TestBackupDisabled DISABLED_TestBackupDisabled 117#endif 118IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 119 MAYBE_TestBackupDisabled) { 120 DisableBackup(); 121 122 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 123 124 BackupModeChecker checker(GetSyncService(0), 125 base::TimeDelta::FromSeconds(15)); 126 ASSERT_FALSE(checker.Wait()); 127 128 ASSERT_EQ(ProfileSyncService::IDLE, GetSyncService(0)->backend_mode()); 129} 130 131#if defined(ENABLE_PRE_SYNC_BACKUP) 132#define MAYBE_TestBackupOnly TestBackupOnly 133#else 134#define MAYBE_TestBackupOnly DISABLED_TestBackupOnly 135#endif 136IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 137 MAYBE_TestBackupOnly) { 138 DisableRollback(); 139 140 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 141 142 // Starting state: 143 // other_node 144 // -> http://mail.google.com "url0" 145 // -> http://www.nhl.com "url1" 146 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0", 147 GURL("http://mail.google.com"))); 148 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1", 149 GURL("http://www.nhl.com"))); 150 151 BackupModeChecker checker(GetSyncService(0), 152 base::TimeDelta::FromSeconds(15)); 153 ASSERT_TRUE(checker.Wait()); 154 155 // Setup sync, wait for its completion, and make sure changes were synced. 156 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 157 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 158 ASSERT_TRUE(ModelMatchesVerifier(0)); 159 160 // Made bookmark changes while sync is on. 161 Remove(0, GetOtherNode(0), 1); 162 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url2", 163 GURL("http://www.yahoo.com"))); 164 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 165 ASSERT_TRUE(ModelMatchesVerifier(0)); 166 167 // Let server to return rollback command on next sync request. 168 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK); 169 170 // Make another change to trigger downloading of rollback command. 171 Remove(0, GetOtherNode(0), 0); 172 173 // Wait for sync to switch to backup mode. 174 ASSERT_TRUE(checker.Wait()); 175 176 // With rollback disabled, bookmarks in backup DB should not be restored. 177 // Only bookmark added during sync is present. 178 ASSERT_EQ(1, GetOtherNode(0)->child_count()); 179 ASSERT_EQ(GURL("http://www.yahoo.com"), 180 GetOtherNode(0)->GetChild(0)->url()); 181} 182 183#if defined(ENABLE_PRE_SYNC_BACKUP) 184#define MAYBE_TestBackupRollback TestBackupRollback 185#else 186#define MAYBE_TestBackupRollback DISABLED_TestBackupRollback 187#endif 188IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 189 MAYBE_TestBackupRollback) { 190 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 191 192 // Starting state: 193 // other_node 194 // -> top 195 // -> tier1_a 196 // -> http://mail.google.com "tier1_a_url0" 197 // -> tier1_b 198 // -> http://www.nhl.com "tier1_b_url0" 199 const BookmarkNode* top = AddFolder(0, GetOtherNode(0), 0, "top"); 200 const BookmarkNode* tier1_a = AddFolder(0, top, 0, "tier1_a"); 201 const BookmarkNode* tier1_b = AddFolder(0, top, 1, "tier1_b"); 202 ASSERT_TRUE(AddURL(0, tier1_a, 0, "tier1_a_url0", 203 GURL("http://mail.google.com"))); 204 ASSERT_TRUE(AddURL(0, tier1_b, 0, "tier1_b_url0", 205 GURL("http://www.nhl.com"))); 206 207 BackupModeChecker checker(GetSyncService(0), 208 base::TimeDelta::FromSeconds(15)); 209 ASSERT_TRUE(checker.Wait()); 210 211 // Setup sync, wait for its completion, and make sure changes were synced. 212 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 213 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0))); 214 ASSERT_TRUE(ModelMatchesVerifier(0)); 215 216 // Made bookmark changes while sync is on. 217 Move(0, tier1_a->GetChild(0), tier1_b, 1); 218 Remove(0, tier1_b, 0); 219 ASSERT_TRUE(AddFolder(0, tier1_b, 1, "tier2_c")); 220 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0))); 221 ASSERT_TRUE(ModelMatchesVerifier(0)); 222 223 // Verify backup time is set on device info. 224 base::Time backup_time = GetBackupDbLastModified(); 225 ASSERT_FALSE(backup_time.is_null()); 226 ASSERT_EQ(backup_time, GetSyncService(0)->GetDeviceBackupTimeForTesting()); 227 228 // Let server to return rollback command on next sync request. 229 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK); 230 231 // Make another change to trigger downloading of rollback command. 232 Remove(0, tier1_b, 0); 233 234 // Wait for sync to switch to backup mode after finishing rollback. 235 ASSERT_TRUE(checker.Wait()); 236 237 // Verify bookmarks are restored. 238 ASSERT_EQ(1, tier1_a->child_count()); 239 const BookmarkNode* url1 = tier1_a->GetChild(0); 240 ASSERT_EQ(GURL("http://mail.google.com"), url1->url()); 241 242 ASSERT_EQ(1, tier1_b->child_count()); 243 const BookmarkNode* url2 = tier1_b->GetChild(0); 244 ASSERT_EQ(GURL("http://www.nhl.com"), url2->url()); 245} 246 247#if defined(ENABLE_PRE_SYNC_BACKUP) 248#define MAYBE_TestPrefBackupRollback TestPrefBackupRollback 249#else 250#define MAYBE_TestPrefBackupRollback DISABLED_TestPrefBackupRollback 251#endif 252// Verify local preferences are not affected by preferences in backup DB under 253// backup mode. 254IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 255 MAYBE_TestPrefBackupRollback) { 256 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 257 258 preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl1); 259 260 BackupModeChecker checker(GetSyncService(0), 261 base::TimeDelta::FromSeconds(15)); 262 ASSERT_TRUE(checker.Wait()); 263 264 // Shut down backup, then change preference. 265 GetSyncService(0)->StartStopBackupForTesting(); 266 preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl2); 267 268 // Restart backup. Preference shouldn't change after backup starts. 269 GetSyncService(0)->StartStopBackupForTesting(); 270 ASSERT_TRUE(checker.Wait()); 271 ASSERT_EQ(kUrl2, 272 preferences_helper::GetPrefs(0)->GetString(prefs::kHomePage)); 273 274 // Start sync and change preference. 275 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 276 preferences_helper::ChangeStringPref(0, prefs::kHomePage, kUrl3); 277 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 278 ASSERT_TRUE(ModelMatchesVerifier(0)); 279 280 // Let server return rollback command on next sync request. 281 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK); 282 283 // Make another change to trigger downloading of rollback command. 284 preferences_helper::ChangeStringPref(0, prefs::kHomePage, ""); 285 286 // Wait for sync to switch to backup mode after finishing rollback. 287 ASSERT_TRUE(checker.Wait()); 288 289 // Verify preference is restored. 290 ASSERT_EQ(kUrl2, 291 preferences_helper::GetPrefs(0)->GetString(prefs::kHomePage)); 292} 293 294#if defined(ENABLE_PRE_SYNC_BACKUP) 295#define MAYBE_RollbackNoBackup RollbackNoBackup 296#else 297#define MAYBE_RollbackNoBackup DISABLED_RollbackNoBackup 298#endif 299IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 300 MAYBE_RollbackNoBackup) { 301 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 302 303 // Setup sync, wait for its completion, and make sure changes were synced. 304 ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; 305 306 // Starting state: 307 // other_node 308 // -> http://mail.google.com "url0" 309 // -> http://www.nhl.com "url1" 310 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0", 311 GURL("http://mail.google.com"))); 312 ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1", 313 GURL("http://www.nhl.com"))); 314 315 ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); 316 ASSERT_TRUE(ModelMatchesVerifier(0)); 317 318 // Let server to return rollback command on next sync request. 319 GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK); 320 321 // Make another change to trigger downloading of rollback command. 322 Remove(0, GetOtherNode(0), 0); 323 324 // Wait for sync to switch to backup mode after finishing rollback. 325 BackupModeChecker checker(GetSyncService(0), 326 base::TimeDelta::FromSeconds(15)); 327 ASSERT_TRUE(checker.Wait()); 328 329 // Without backup DB, bookmarks added during sync shouldn't be removed. 330 ASSERT_EQ(1, GetOtherNode(0)->child_count()); 331 ASSERT_EQ(GURL("http://www.nhl.com"), 332 GetOtherNode(0)->GetChild(0)->url()); 333} 334 335#if defined(ENABLE_PRE_SYNC_BACKUP) 336#define MAYBE_DontChangeBookmarkOrdering DontChangeBookmarkOrdering 337#else 338#define MAYBE_DontChangeBookmarkOrdering DISABLED_DontChangeBookmarkOrdering 339#endif 340IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest, 341 MAYBE_DontChangeBookmarkOrdering) { 342 ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; 343 344 const BookmarkNode* sub_folder = AddFolder(0, GetOtherNode(0), 0, "test"); 345 ASSERT_TRUE(AddURL(0, sub_folder, 0, "", GURL(kUrl1))); 346 ASSERT_TRUE(AddURL(0, sub_folder, 1, "", GURL(kUrl2))); 347 ASSERT_TRUE(AddURL(0, sub_folder, 2, "", GURL(kUrl3))); 348 349 BackupModeChecker checker(GetSyncService(0), 350 base::TimeDelta::FromSeconds(15)); 351 ASSERT_TRUE(checker.Wait()); 352 353 // Restart backup. 354 GetSyncService(0)->StartStopBackupForTesting(); 355 GetSyncService(0)->StartStopBackupForTesting(); 356 ASSERT_TRUE(checker.Wait()); 357 358 // Verify bookmarks are unchanged. 359 ASSERT_EQ(3, sub_folder->child_count()); 360 ASSERT_EQ(GURL(kUrl1), sub_folder->GetChild(0)->url()); 361 ASSERT_EQ(GURL(kUrl2), sub_folder->GetChild(1)->url()); 362 ASSERT_EQ(GURL(kUrl3), sub_folder->GetChild(2)->url()); 363} 364