| 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));
|
| +}
|
|
|