Index: chrome/browser/sync_file_system/drive_backend/conflict_resolver_unittest.cc |
diff --git a/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer_unittest.cc b/chrome/browser/sync_file_system/drive_backend/conflict_resolver_unittest.cc |
similarity index 52% |
copy from chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer_unittest.cc |
copy to chrome/browser/sync_file_system/drive_backend/conflict_resolver_unittest.cc |
index 962394d00a5686a341ea418f3c3e6fb0c1e9c307..d398fa92df25de4c9df49dfdbf50abb2e0b9794e 100644 |
--- a/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer_unittest.cc |
+++ b/chrome/browser/sync_file_system/drive_backend/conflict_resolver_unittest.cc |
@@ -2,12 +2,11 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h" |
+#include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h" |
#include "base/bind.h" |
#include "base/callback.h" |
#include "base/files/scoped_temp_dir.h" |
-#include "base/logging.h" |
#include "base/run_loop.h" |
#include "chrome/browser/drive/drive_uploader.h" |
#include "chrome/browser/drive/fake_drive_service.h" |
@@ -16,6 +15,7 @@ |
#include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h" |
#include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h" |
#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" |
+#include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h" |
#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" |
#include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h" |
#include "chrome/browser/sync_file_system/drive_backend_v1/fake_drive_service_helper.h" |
@@ -29,22 +29,12 @@ |
namespace sync_file_system { |
namespace drive_backend { |
-namespace { |
- |
-fileapi::FileSystemURL URL(const GURL& origin, |
- const std::string& path) { |
- return CreateSyncableFileSystemURL( |
- origin, base::FilePath::FromUTF8Unsafe(path)); |
-} |
- |
-} // namespace |
- |
-class LocalToRemoteSyncerTest : public testing::Test, |
- public SyncEngineContext { |
+class ConflictResolverTest : public testing::Test, |
+ public SyncEngineContext { |
public: |
- LocalToRemoteSyncerTest() |
+ ConflictResolverTest() |
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} |
- virtual ~LocalToRemoteSyncerTest() {} |
+ virtual ~ConflictResolverTest() {} |
virtual void SetUp() OVERRIDE { |
ASSERT_TRUE(database_dir_.CreateUniqueTempDir()); |
@@ -94,6 +84,14 @@ class LocalToRemoteSyncerTest : public testing::Test, |
EXPECT_EQ(SYNC_STATUS_OK, status); |
} |
+ SyncStatusCode RunRemoteSyncer() { |
+ SyncStatusCode status = SYNC_STATUS_UNKNOWN; |
+ scoped_ptr<RemoteToLocalSyncer> syncer(new RemoteToLocalSyncer(this)); |
+ syncer->Run(CreateResultReceiver(&status)); |
+ base::RunLoop().RunUntilIdle(); |
+ return status; |
+ } |
+ |
virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE { |
return fake_drive_service_.get(); |
} |
@@ -142,17 +140,28 @@ class LocalToRemoteSyncerTest : public testing::Test, |
return file_id; |
} |
- SyncStatusCode RunSyncer(FileChange file_change, |
- const fileapi::FileSystemURL& url) { |
+ SyncStatusCode RunSyncer() { |
SyncStatusCode status = SYNC_STATUS_UNKNOWN; |
- base::FilePath local_path = base::FilePath::FromUTF8Unsafe("dummy"); |
- scoped_ptr<LocalToRemoteSyncer> syncer(new LocalToRemoteSyncer( |
- this, file_change, local_path, url)); |
+ scoped_ptr<RemoteToLocalSyncer> syncer(new RemoteToLocalSyncer(this)); |
syncer->Run(CreateResultReceiver(&status)); |
base::RunLoop().RunUntilIdle(); |
return status; |
} |
+ void RunSyncerUntilIdle() { |
+ SyncStatusCode status = SYNC_STATUS_UNKNOWN; |
+ while (status != SYNC_STATUS_NO_CHANGE_TO_SYNC) |
+ status = RunSyncer(); |
+ } |
+ |
+ SyncStatusCode RunConflictResolver() { |
+ SyncStatusCode status = SYNC_STATUS_UNKNOWN; |
+ ConflictResolver resolver(this); |
+ resolver.Run(CreateResultReceiver(&status)); |
+ base::RunLoop().RunUntilIdle(); |
+ return status; |
+ } |
+ |
SyncStatusCode ListChanges() { |
ListChangesTask list_changes(this); |
SyncStatusCode status = SYNC_STATUS_UNKNOWN; |
@@ -171,35 +180,19 @@ class LocalToRemoteSyncerTest : public testing::Test, |
return entries.Pass(); |
} |
- std::string GetFileIDForParentAndTitle(const std::string& parent_folder_id, |
- const std::string& title) { |
- ScopedVector<google_apis::ResourceEntry> entries = |
- GetResourceEntriesForParentAndTitle(parent_folder_id, title); |
- if (entries.size() != 1) |
- return std::string(); |
- return entries[0]->resource_id(); |
- } |
- |
- void VerifyTitleUniqueness(const std::string& parent_folder_id, |
- const std::string& title, |
- google_apis::DriveEntryKind kind) { |
+ void VerifyConflictResolution(const std::string& parent_folder_id, |
+ const std::string& title, |
+ const std::string& primary_file_id, |
+ google_apis::DriveEntryKind kind) { |
ScopedVector<google_apis::ResourceEntry> entries; |
EXPECT_EQ(google_apis::HTTP_SUCCESS, |
fake_drive_helper_->SearchByTitle( |
parent_folder_id, title, &entries)); |
ASSERT_EQ(1u, entries.size()); |
+ EXPECT_EQ(primary_file_id, entries[0]->resource_id()); |
EXPECT_EQ(kind, entries[0]->kind()); |
} |
- void VerifyFileDeletion(const std::string& parent_folder_id, |
- const std::string& title) { |
- ScopedVector<google_apis::ResourceEntry> entries; |
- EXPECT_EQ(google_apis::HTTP_SUCCESS, |
- fake_drive_helper_->SearchByTitle( |
- parent_folder_id, title, &entries)); |
- EXPECT_TRUE(entries.empty()); |
- } |
- |
private: |
content::TestBrowserThreadBundle thread_bundle_; |
base::ScopedTempDir database_dir_; |
@@ -210,169 +203,99 @@ class LocalToRemoteSyncerTest : public testing::Test, |
scoped_ptr<MetadataDatabase> metadata_database_; |
scoped_ptr<FakeRemoteChangeProcessor> fake_remote_change_processor_; |
- DISALLOW_COPY_AND_ASSIGN(LocalToRemoteSyncerTest); |
+ DISALLOW_COPY_AND_ASSIGN(ConflictResolverTest); |
}; |
-TEST_F(LocalToRemoteSyncerTest, CreateFile) { |
- const GURL kOrigin("chrome-extension://example"); |
- const std::string sync_root = CreateSyncRoot(); |
- const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); |
- InitializeMetadataDatabase(); |
- RegisterApp(kOrigin.host(), app_root); |
- |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_FILE), |
- URL(kOrigin, "file1"))); |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_DIRECTORY), |
- URL(kOrigin, "folder"))); |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_FILE), |
- URL(kOrigin, "folder/file2"))); |
- |
- std::string folder_id = GetFileIDForParentAndTitle(app_root, "folder"); |
- ASSERT_FALSE(folder_id.empty()); |
- |
- VerifyTitleUniqueness(app_root, "file1", google_apis::ENTRY_KIND_FILE); |
- VerifyTitleUniqueness(app_root, "folder", google_apis::ENTRY_KIND_FOLDER); |
- VerifyTitleUniqueness(folder_id, "file2", google_apis::ENTRY_KIND_FILE); |
-} |
- |
-TEST_F(LocalToRemoteSyncerTest, CreateFileOnMissingPath) { |
+TEST_F(ConflictResolverTest, NoFileToBeResolved) { |
const GURL kOrigin("chrome-extension://example"); |
const std::string sync_root = CreateSyncRoot(); |
const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); |
InitializeMetadataDatabase(); |
RegisterApp(kOrigin.host(), app_root); |
+ RunSyncerUntilIdle(); |
- // Run the syncer 3 times to create missing folder1 and folder2. |
- EXPECT_EQ(SYNC_STATUS_RETRY, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_FILE), |
- URL(kOrigin, "folder1/folder2/file"))); |
- EXPECT_EQ(SYNC_STATUS_RETRY, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_FILE), |
- URL(kOrigin, "folder1/folder2/file"))); |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_FILE), |
- URL(kOrigin, "folder1/folder2/file"))); |
- |
- std::string folder_id1 = GetFileIDForParentAndTitle(app_root, "folder1"); |
- ASSERT_FALSE(folder_id1.empty()); |
- std::string folder_id2 = GetFileIDForParentAndTitle(folder_id1, "folder2"); |
- ASSERT_FALSE(folder_id2.empty()); |
- |
- VerifyTitleUniqueness(app_root, "folder1", google_apis::ENTRY_KIND_FOLDER); |
- VerifyTitleUniqueness(folder_id1, "folder2", google_apis::ENTRY_KIND_FOLDER); |
- VerifyTitleUniqueness(folder_id2, "file", google_apis::ENTRY_KIND_FILE); |
+ EXPECT_EQ(SYNC_STATUS_NO_CHANGE_TO_SYNC, RunConflictResolver()); |
} |
-TEST_F(LocalToRemoteSyncerTest, DeleteFile) { |
+TEST_F(ConflictResolverTest, ResolveConflict_Files) { |
const GURL kOrigin("chrome-extension://example"); |
const std::string sync_root = CreateSyncRoot(); |
const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); |
InitializeMetadataDatabase(); |
RegisterApp(kOrigin.host(), app_root); |
+ RunSyncerUntilIdle(); |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_FILE), |
- URL(kOrigin, "file"))); |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_DIRECTORY), |
- URL(kOrigin, "folder"))); |
- |
- VerifyTitleUniqueness(app_root, "file", google_apis::ENTRY_KIND_FILE); |
- VerifyTitleUniqueness(app_root, "folder", google_apis::ENTRY_KIND_FOLDER); |
- |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_DELETE, |
- SYNC_FILE_TYPE_FILE), |
- URL(kOrigin, "file"))); |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_DELETE, |
- SYNC_FILE_TYPE_DIRECTORY), |
- URL(kOrigin, "folder"))); |
- |
- VerifyFileDeletion(app_root, "file"); |
- VerifyFileDeletion(app_root, "folder"); |
-} |
- |
-TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFileOnFolder) { |
- const GURL kOrigin("chrome-extension://example"); |
- const std::string sync_root = CreateSyncRoot(); |
- const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); |
- InitializeMetadataDatabase(); |
- RegisterApp(kOrigin.host(), app_root); |
- |
- CreateRemoteFolder(app_root, "foo"); |
+ const std::string kTitle = "foo"; |
+ const std::string primary = CreateRemoteFile(app_root, kTitle, "data1"); |
+ CreateRemoteFile(app_root, kTitle, "data2"); |
+ CreateRemoteFile(app_root, kTitle, "data3"); |
+ CreateRemoteFile(app_root, kTitle, "data4"); |
EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_FILE), |
- URL(kOrigin, "foo"))); |
+ RunSyncerUntilIdle(); |
- // There should exist both file and folder on remote. |
ScopedVector<google_apis::ResourceEntry> entries = |
- GetResourceEntriesForParentAndTitle(app_root, "foo"); |
- ASSERT_EQ(2u, entries.size()); |
- EXPECT_EQ(google_apis::ENTRY_KIND_FOLDER, entries[0]->kind()); |
- EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[1]->kind()); |
+ GetResourceEntriesForParentAndTitle(app_root, kTitle); |
+ ASSERT_EQ(4u, entries.size()); |
+ |
+ // Only primary file should survive. |
+ EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); |
+ VerifyConflictResolution(app_root, kTitle, primary, |
+ google_apis::ENTRY_KIND_FILE); |
} |
-TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFolderOnFile) { |
+TEST_F(ConflictResolverTest, ResolveConflict_Folders) { |
const GURL kOrigin("chrome-extension://example"); |
const std::string sync_root = CreateSyncRoot(); |
const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); |
InitializeMetadataDatabase(); |
RegisterApp(kOrigin.host(), app_root); |
+ RunSyncerUntilIdle(); |
- CreateRemoteFile(app_root, "foo", "data"); |
+ const std::string kTitle = "foo"; |
+ const std::string primary = CreateRemoteFolder(app_root, kTitle); |
+ CreateRemoteFolder(app_root, kTitle); |
+ CreateRemoteFolder(app_root, kTitle); |
+ CreateRemoteFolder(app_root, kTitle); |
EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); |
+ RunSyncerUntilIdle(); |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_DIRECTORY), |
- URL(kOrigin, "foo"))); |
- |
- // There should exist both file and folder on remote. |
ScopedVector<google_apis::ResourceEntry> entries = |
- GetResourceEntriesForParentAndTitle(app_root, "foo"); |
- ASSERT_EQ(2u, entries.size()); |
- EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[0]->kind()); |
- EXPECT_EQ(google_apis::ENTRY_KIND_FOLDER, entries[1]->kind()); |
+ GetResourceEntriesForParentAndTitle(app_root, kTitle); |
+ ASSERT_EQ(4u, entries.size()); |
+ |
+ // Only primary file should survive. |
+ EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); |
+ VerifyConflictResolution(app_root, kTitle, primary, |
+ google_apis::ENTRY_KIND_FOLDER); |
} |
-TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFileOnFile) { |
+TEST_F(ConflictResolverTest, ResolveConflict_FilesAndFolders) { |
const GURL kOrigin("chrome-extension://example"); |
const std::string sync_root = CreateSyncRoot(); |
const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); |
InitializeMetadataDatabase(); |
RegisterApp(kOrigin.host(), app_root); |
+ RunSyncerUntilIdle(); |
- CreateRemoteFile(app_root, "foo", "data"); |
+ const std::string kTitle = "foo"; |
+ CreateRemoteFile(app_root, kTitle, "data"); |
+ const std::string primary = CreateRemoteFolder(app_root, kTitle); |
+ CreateRemoteFile(app_root, kTitle, "data2"); |
+ CreateRemoteFolder(app_root, kTitle); |
EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); |
+ RunSyncerUntilIdle(); |
- EXPECT_EQ(SYNC_STATUS_OK, RunSyncer( |
- FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
- SYNC_FILE_TYPE_FILE), |
- URL(kOrigin, "foo"))); |
- |
- // There should exist both files on remote. |
ScopedVector<google_apis::ResourceEntry> entries = |
- GetResourceEntriesForParentAndTitle(app_root, "foo"); |
- ASSERT_EQ(2u, entries.size()); |
- EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[0]->kind()); |
- EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[1]->kind()); |
+ GetResourceEntriesForParentAndTitle(app_root, kTitle); |
+ ASSERT_EQ(4u, entries.size()); |
+ |
+ // Only primary file should survive. |
+ EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); |
+ VerifyConflictResolution(app_root, kTitle, primary, |
+ google_apis::ENTRY_KIND_FOLDER); |
} |
-// TODO(nhiroki): Add folder-folder conflict (reusing remote folder) case. |
+// TODO(nhiroki): Add multi-parent resolution cases. |
} // namespace drive_backend |
} // namespace sync_file_system |