Index: chrome/browser/sync/test/integration/single_client_directory_sync_test.cc |
diff --git a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc |
index 14d9d2a9ec7bd6eb27c411c1e57f36ea609d9a35..85cabd95c7df88e586d92d990bcdd955f1561b9f 100644 |
--- a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc |
+++ b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc |
@@ -4,13 +4,23 @@ |
#include "base/message_loop/message_loop.h" |
#include "base/run_loop.h" |
+#include "base/strings/string_number_conversions.h" |
#include "base/synchronization/waitable_event.h" |
#include "base/time/time.h" |
#include "chrome/browser/sync/profile_sync_service.h" |
+#include "chrome/browser/sync/test/integration/bookmarks_helper.h" |
+#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" |
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h" |
#include "chrome/browser/sync/test/integration/sync_test.h" |
#include "content/public/browser/browser_thread.h" |
+#include "sync/syncable/directory.h" |
+#include "sync/test/directory_backing_store_corruption_testing.h" |
+#include "url/gurl.h" |
using content::BrowserThread; |
+using sync_integration_test_util::AwaitCommitActivityCompletion; |
+using syncer::syncable::corruption_testing::kNumEntriesRequiredForCorruption; |
+using syncer::syncable::corruption_testing::CorruptDatabase; |
class SingleClientDirectorySyncTest : public SyncTest { |
public: |
@@ -32,6 +42,21 @@ bool WaitForExistingTasksOnLoop(base::MessageLoop* loop) { |
return e.TimedWait(base::TimeDelta::FromSeconds(45)); |
} |
+// A status change checker that waits for an unrecoverable sync error to occur. |
+class SyncUnrecoverableErrorChecker : public SingleClientStatusChangeChecker { |
+ public: |
+ explicit SyncUnrecoverableErrorChecker(ProfileSyncService* service) |
+ : SingleClientStatusChangeChecker(service) {} |
+ |
+ bool IsExitConditionSatisfied() override { |
+ return service()->HasUnrecoverableError(); |
+ } |
+ |
+ std::string GetDebugMessage() const override { |
+ return "Sync Unrecoverable Error"; |
+ } |
+}; |
+ |
IN_PROC_BROWSER_TEST_F(SingleClientDirectorySyncTest, |
StopThenDisableDeletesDirectory) { |
ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; |
@@ -51,3 +76,53 @@ IN_PROC_BROWSER_TEST_F(SingleClientDirectorySyncTest, |
ASSERT_FALSE(base::DirectoryExists(directory_path)); |
} |
+ |
+// Verify that when the sync directory's backing store becomes corrupted, we |
+// trigger an unrecoverable error and delete the database. |
+// |
+// If this test fails, see the definition of kNumEntriesRequiredForCorruption |
+// for one possible cause. |
+IN_PROC_BROWSER_TEST_F(SingleClientDirectorySyncTest, |
+ DeleteDirectoryWhenCorrupted) { |
+ ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; |
+ // Sync and wait for syncing to complete. |
+ ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; |
+ ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); |
+ ASSERT_TRUE(bookmarks_helper::ModelMatchesVerifier(0)); |
+ |
+ // Flush the directory to the backing store and wait until the flush |
+ // completes. |
+ ProfileSyncService* sync_service = GetSyncService(0); |
+ sync_service->FlushDirectory(); |
+ base::MessageLoop* sync_loop = sync_service->GetSyncLoopForTest(); |
+ ASSERT_TRUE(WaitForExistingTasksOnLoop(sync_loop)); |
+ |
+ // Now corrupt the database. |
+ const base::FilePath directory_path(sync_service->GetDirectoryPathForTest()); |
+ const base::FilePath sync_db(directory_path.Append( |
+ syncer::syncable::Directory::kSyncDatabaseFilename)); |
+ ASSERT_TRUE(CorruptDatabase(sync_db)); |
+ |
+ // Write a bunch of bookmarks and flush the directory to ensure sync notices |
+ // the corruption. The key here is to force sync to actually write a lot of |
+ // data to its DB so it will see the corruption we introduced above. |
+ const GURL url("https://www.google.com"); |
+ const bookmarks::BookmarkNode* top = bookmarks_helper::AddFolder( |
+ 0, bookmarks_helper::GetOtherNode(0), 0, "top"); |
+ for (int i = 0; i < kNumEntriesRequiredForCorruption; ++i) { |
+ ASSERT_TRUE( |
+ bookmarks_helper::AddURL(0, top, 0, base::Int64ToString(i), url)); |
+ } |
+ sync_service->FlushDirectory(); |
+ |
+ // Wait for an unrecoverable error to occur. |
+ SyncUnrecoverableErrorChecker checker(sync_service); |
+ checker.Wait(); |
+ ASSERT_TRUE(!checker.TimedOut()); |
+ ASSERT_TRUE(sync_service->HasUnrecoverableError()); |
+ |
+ // Wait until the sync loop has processed any existing tasks and see that the |
+ // directory no longer exists. |
+ ASSERT_TRUE(WaitForExistingTasksOnLoop(sync_loop)); |
+ ASSERT_FALSE(base::DirectoryExists(directory_path)); |
+} |