1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/bind.h" 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/callback.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/files/scoped_temp_dir.h" 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/run_loop.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/thread_task_runner_handle.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/drive/drive_uploader.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/drive/fake_drive_service.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/fake_drive_uploader.h" 19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h" 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h" 25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h" 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h" 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/fake_remote_change_processor.h" 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/sync_file_system_test_util.h" 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/syncable_file_system_util.h" 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h" 3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "google_apis/drive/drive_api_parser.h" 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/drive/gdata_errorcode.h" 33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/leveldatabase/src/include/leveldb/env.h" 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace sync_file_system { 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace drive_backend { 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)storage::FileSystemURL URL(const GURL& origin, const std::string& path) { 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CreateSyncableFileSystemURL( 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) origin, base::FilePath::FromUTF8Unsafe(path)); 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass ConflictResolverTest : public testing::Test { 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) typedef FakeRemoteChangeProcessor::URLToFileChangesMap URLToFileChangesMap; 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ConflictResolverTest() 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual ~ConflictResolverTest() {} 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual void SetUp() OVERRIDE { 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(database_dir_.CreateUniqueTempDir()); 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<FakeDriveServiceWrapper> 62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) fake_drive_service(new FakeDriveServiceWrapper); 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<drive::DriveUploaderInterface> 64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) drive_uploader(new FakeDriveUploader(fake_drive_service.get())); 65a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch fake_drive_helper_.reset( 66010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) new FakeDriveServiceHelper(fake_drive_service.get(), 67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) drive_uploader.get(), 68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch kSyncRootFolderTitle)); 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) remote_change_processor_.reset(new FakeRemoteChangeProcessor); 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch context_.reset(new SyncEngineContext( 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) fake_drive_service.PassAs<drive::DriveServiceInterface>(), 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) drive_uploader.Pass(), 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NULL, 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ThreadTaskRunnerHandle::Get(), 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ThreadTaskRunnerHandle::Get())); 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) context_->SetRemoteChangeProcessor(remote_change_processor_.get()); 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RegisterSyncableFileSystem(); 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sync_task_manager_.reset(new SyncTaskManager( 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::WeakPtr<SyncTaskManager::Client>(), 836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 10 /* maximum_background_task */, 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ThreadTaskRunnerHandle::Get())); 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sync_task_manager_->Initialize(SYNC_STATUS_OK); 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual void TearDown() OVERRIDE { 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sync_task_manager_.reset(); 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RevokeSyncableFileSystem(); 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fake_drive_helper_.reset(); 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch context_.reset(); 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void InitializeMetadataDatabase() { 97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncEngineInitializer* initializer = 98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new SyncEngineInitializer(context_.get(), 99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch database_dir_.path(), 100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch in_memory_env_.get()); 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SyncStatusCode status = SYNC_STATUS_UNKNOWN; 102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sync_task_manager_->ScheduleSyncTask( 103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<SyncTask>(initializer), 105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncTaskManager::PRIORITY_MED, 106effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&ConflictResolverTest::DidInitializeMetadataDatabase, 107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Unretained(this), initializer, &status)); 108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, status); 111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void DidInitializeMetadataDatabase(SyncEngineInitializer* initializer, 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncStatusCode* status_out, 115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncStatusCode status) { 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch context_->SetMetadataDatabase(initializer->PassMetadataDatabase()); 117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *status_out = status; 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void RegisterApp(const std::string& app_id, 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& app_root_folder_id) { 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SyncStatusCode status = context_->GetMetadataDatabase()->RegisterApp( 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci app_id, app_root_folder_id); 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, status); 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) protected: 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string CreateSyncRoot() { 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string sync_root_folder_id; 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(google_apis::HTTP_CREATED, 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fake_drive_helper_->AddOrphanedFolder( 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) kSyncRootFolderTitle, &sync_root_folder_id)); 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return sync_root_folder_id; 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string CreateRemoteFolder(const std::string& parent_folder_id, 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& title) { 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string folder_id; 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(google_apis::HTTP_CREATED, 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fake_drive_helper_->AddFolder( 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parent_folder_id, title, &folder_id)); 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return folder_id; 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string CreateRemoteFile(const std::string& parent_folder_id, 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& title, 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& content) { 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string file_id; 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(google_apis::HTTP_SUCCESS, 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fake_drive_helper_->AddFile( 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parent_folder_id, title, content, &file_id)); 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return file_id; 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void CreateLocalFile(const storage::FileSystemURL& url) { 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) remote_change_processor_->UpdateLocalFileMetadata( 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) url, FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SYNC_FILE_TYPE_FILE)); 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) google_apis::GDataErrorCode AddFileToFolder( 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& parent_folder_id, 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& file_id) { 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch context_->GetDriveService()->AddResourceToDirectory( 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parent_folder_id, file_id, 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateResultReceiver(&error)); 168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return error; 170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int CountParents(const std::string& file_id) { 17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<google_apis::FileResource> entry; 174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(google_apis::HTTP_SUCCESS, 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) fake_drive_helper_->GetFileResource(file_id, &entry)); 17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return entry->parents().size(); 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncStatusCode RunRemoteToLocalSyncer() { 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SyncStatusCode status = SYNC_STATUS_UNKNOWN; 181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<RemoteToLocalSyncer> syncer( 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new RemoteToLocalSyncer(context_.get())); 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch syncer->RunPreflight(SyncTaskToken::CreateForTesting( 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateResultReceiver(&status))); 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return status; 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SyncStatusCode RunLocalToRemoteSyncer(const storage::FileSystemURL& url, 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const FileChange& file_change) { 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncStatusCode status = SYNC_STATUS_UNKNOWN; 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath local_path = base::FilePath(FILE_PATH_LITERAL("dummy")); 1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (file_change.IsAddOrUpdate()) 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateTemporaryFileInDir(database_dir_.path(), &local_path); 1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<LocalToRemoteSyncer> syncer(new LocalToRemoteSyncer( 196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch context_.get(), 197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncFileMetadata(file_change.file_type(), 0, base::Time()), 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_change, local_path, url)); 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) syncer->RunPreflight(SyncTaskToken::CreateForTesting( 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CreateResultReceiver(&status))); 2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status == SYNC_STATUS_OK) 203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) remote_change_processor_->ClearLocalChanges(url); 2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return status; 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RunRemoteToLocalSyncerUntilIdle() { 2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const int kRetryLimit = 100; 2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SyncStatusCode status; 2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int retry_count = 0; 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) MetadataDatabase* metadata_database = context_->GetMetadataDatabase(); 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) do { 2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (retry_count++ > kRetryLimit) 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status = RunRemoteToLocalSyncer(); 2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } while (status == SYNC_STATUS_OK || 2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) status == SYNC_STATUS_RETRY || 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci metadata_database->PromoteDemotedTrackers()); 2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_NO_CHANGE_TO_SYNC, status); 220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SyncStatusCode RunConflictResolver() { 223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SyncStatusCode status = SYNC_STATUS_UNKNOWN; 224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ConflictResolver resolver(context_.get()); 22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) resolver.RunPreflight(SyncTaskToken::CreateForTesting( 22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CreateResultReceiver(&status))); 227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return status; 229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SyncStatusCode ListChanges() { 232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SyncStatusCode status = SYNC_STATUS_UNKNOWN; 233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch sync_task_manager_->ScheduleSyncTask( 234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FROM_HERE, 235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<SyncTask>(new ListChangesTask(context_.get())), 236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SyncTaskManager::PRIORITY_MED, 237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateResultReceiver(&status)); 238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::RunLoop().RunUntilIdle(); 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return status; 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ScopedVector<google_apis::ResourceEntry> 243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetResourceEntriesForParentAndTitle(const std::string& parent_folder_id, 244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& title) { 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ScopedVector<google_apis::ResourceEntry> entries; 246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(google_apis::HTTP_SUCCESS, 247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fake_drive_helper_->SearchByTitle( 248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parent_folder_id, title, &entries)); 249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return entries.Pass(); 250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void VerifyConflictResolution( 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& parent_folder_id, 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& title, 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& primary_file_id, 256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch google_apis::ResourceEntry::ResourceEntryKind kind) { 257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ScopedVector<google_apis::ResourceEntry> entries; 258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(google_apis::HTTP_SUCCESS, 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fake_drive_helper_->SearchByTitle( 260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parent_folder_id, title, &entries)); 261a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(1u, entries.size()); 262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(primary_file_id, entries[0]->resource_id()); 263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(kind, entries[0]->kind()); 264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void VerifyLocalChangeConsistency( 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const URLToFileChangesMap& expected_changes) { 268010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) remote_change_processor_->VerifyConsistency(expected_changes); 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private: 272a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) content::TestBrowserThreadBundle thread_bundle_; 273a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::ScopedTempDir database_dir_; 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<leveldb::Env> in_memory_env_; 275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<SyncEngineContext> context_; 277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_; 278010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<FakeRemoteChangeProcessor> remote_change_processor_; 279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<SyncTaskManager> sync_task_manager_; 281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ConflictResolverTest); 283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}; 284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(ConflictResolverTest, NoFileToBeResolved) { 286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL kOrigin("chrome-extension://example"); 287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string sync_root = CreateSyncRoot(); 288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InitializeMetadataDatabase(); 290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RegisterApp(kOrigin.host(), app_root); 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_NO_CONFLICT, RunConflictResolver()); 294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(ConflictResolverTest, ResolveConflict_Files) { 297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL kOrigin("chrome-extension://example"); 298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string sync_root = CreateSyncRoot(); 299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InitializeMetadataDatabase(); 301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RegisterApp(kOrigin.host(), app_root); 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string kTitle = "foo"; 305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string primary = CreateRemoteFile(app_root, kTitle, "data1"); 306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateRemoteFile(app_root, kTitle, "data2"); 307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateRemoteFile(app_root, kTitle, "data3"); 308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateRemoteFile(app_root, kTitle, "data4"); 309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ScopedVector<google_apis::ResourceEntry> entries = 313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetResourceEntriesForParentAndTitle(app_root, kTitle); 314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(4u, entries.size()); 315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Only primary file should survive. 317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); 318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VerifyConflictResolution(app_root, kTitle, primary, 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch google_apis::ResourceEntry::ENTRY_KIND_FILE); 320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(ConflictResolverTest, ResolveConflict_Folders) { 323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL kOrigin("chrome-extension://example"); 324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string sync_root = CreateSyncRoot(); 325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InitializeMetadataDatabase(); 327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RegisterApp(kOrigin.host(), app_root); 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string kTitle = "foo"; 331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string primary = CreateRemoteFolder(app_root, kTitle); 332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateRemoteFolder(app_root, kTitle); 333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateRemoteFolder(app_root, kTitle); 334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateRemoteFolder(app_root, kTitle); 335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ScopedVector<google_apis::ResourceEntry> entries = 339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetResourceEntriesForParentAndTitle(app_root, kTitle); 340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(4u, entries.size()); 341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Only primary file should survive. 343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); 344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VerifyConflictResolution(app_root, kTitle, primary, 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch google_apis::ResourceEntry::ENTRY_KIND_FOLDER); 346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(ConflictResolverTest, ResolveConflict_FilesAndFolders) { 349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL kOrigin("chrome-extension://example"); 350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string sync_root = CreateSyncRoot(); 351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InitializeMetadataDatabase(); 353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RegisterApp(kOrigin.host(), app_root); 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string kTitle = "foo"; 357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateRemoteFile(app_root, kTitle, "data"); 358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string primary = CreateRemoteFolder(app_root, kTitle); 359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateRemoteFile(app_root, kTitle, "data2"); 360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateRemoteFolder(app_root, kTitle); 361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ScopedVector<google_apis::ResourceEntry> entries = 365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetResourceEntriesForParentAndTitle(app_root, kTitle); 366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(4u, entries.size()); 367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Only primary file should survive. 369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); 370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VerifyConflictResolution(app_root, kTitle, primary, 371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch google_apis::ResourceEntry::ENTRY_KIND_FOLDER); 372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ConflictResolverTest, ResolveConflict_RemoteFolderOnLocalFile) { 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GURL kOrigin("chrome-extension://example"); 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string sync_root = CreateSyncRoot(); 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeMetadataDatabase(); 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RegisterApp(kOrigin.host(), app_root); 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string kTitle = "foo"; 38303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) storage::FileSystemURL kURL = URL(kOrigin, kTitle); 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Create a file on local and sync it. 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateLocalFile(kURL); 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunLocalToRemoteSyncer( 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kURL, 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, SYNC_FILE_TYPE_FILE)); 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Create a folder on remote and sync it. 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string primary = CreateRemoteFolder(app_root, kTitle); 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedVector<google_apis::ResourceEntry> entries = 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetResourceEntriesForParentAndTitle(app_root, kTitle); 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(2u, entries.size()); 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Run conflict resolver. Only primary file should survive. 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VerifyConflictResolution(app_root, kTitle, primary, 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch google_apis::ResourceEntry::ENTRY_KIND_FOLDER); 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Continue to run remote-to-local sync. 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Verify that the local side has been synced to the same state 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // (i.e. file deletion and folder creation). 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLToFileChangesMap expected_changes; 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expected_changes[kURL].push_back( 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileChange(FileChange::FILE_CHANGE_DELETE, 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SYNC_FILE_TYPE_UNKNOWN)); 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expected_changes[kURL].push_back( 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SYNC_FILE_TYPE_DIRECTORY)); 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VerifyLocalChangeConsistency(expected_changes); 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ConflictResolverTest, ResolveConflict_RemoteNestedFolderOnLocalFile) { 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GURL kOrigin("chrome-extension://example"); 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string sync_root = CreateSyncRoot(); 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InitializeMetadataDatabase(); 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RegisterApp(kOrigin.host(), app_root); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string kTitle = "foo"; 43003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) storage::FileSystemURL kURL = URL(kOrigin, kTitle); 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Create a file on local and sync it. 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateLocalFile(kURL); 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunLocalToRemoteSyncer( 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kURL, 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, SYNC_FILE_TYPE_FILE)); 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Create a folder and subfolder in it on remote, and sync it. 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string primary = CreateRemoteFolder(app_root, kTitle); 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateRemoteFolder(primary, "nested"); 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedVector<google_apis::ResourceEntry> entries = 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetResourceEntriesForParentAndTitle(app_root, kTitle); 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_EQ(2u, entries.size()); 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Run conflict resolver. Only primary file should survive. 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VerifyConflictResolution(app_root, kTitle, primary, 451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch google_apis::ResourceEntry::ENTRY_KIND_FOLDER); 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Continue to run remote-to-local sync. 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Verify that the local side has been synced to the same state 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // (i.e. file deletion and folders creation). 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) URLToFileChangesMap expected_changes; 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expected_changes[kURL].push_back( 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileChange(FileChange::FILE_CHANGE_DELETE, 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SYNC_FILE_TYPE_UNKNOWN)); 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expected_changes[kURL].push_back( 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SYNC_FILE_TYPE_DIRECTORY)); 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expected_changes[URL(kOrigin, "foo/nested")].push_back( 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SYNC_FILE_TYPE_DIRECTORY)); 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VerifyLocalChangeConsistency(expected_changes); 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(ConflictResolverTest, ResolveMultiParents_File) { 473a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL kOrigin("chrome-extension://example"); 474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string sync_root = CreateSyncRoot(); 475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InitializeMetadataDatabase(); 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RegisterApp(kOrigin.host(), app_root); 4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string primary = CreateRemoteFolder(app_root, "primary"); 481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string file = CreateRemoteFile(primary, "file", "data"); 482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(google_apis::HTTP_SUCCESS, 483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddFileToFolder(CreateRemoteFolder(app_root, "nonprimary1"), file)); 484a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(google_apis::HTTP_SUCCESS, 485a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddFileToFolder(CreateRemoteFolder(app_root, "nonprimary2"), file)); 486a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(google_apis::HTTP_SUCCESS, 487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddFileToFolder(CreateRemoteFolder(app_root, "nonprimary3"), file)); 488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 491a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(4, CountParents(file)); 493a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 494a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); 495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 496a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(1, CountParents(file)); 497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 498a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_F(ConflictResolverTest, ResolveMultiParents_Folder) { 500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const GURL kOrigin("chrome-extension://example"); 501a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string sync_root = CreateSyncRoot(); 502a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 503a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) InitializeMetadataDatabase(); 504a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) RegisterApp(kOrigin.host(), app_root); 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 506a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string primary = CreateRemoteFolder(app_root, "primary"); 508a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string file = CreateRemoteFolder(primary, "folder"); 509a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(google_apis::HTTP_SUCCESS, 510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddFileToFolder(CreateRemoteFolder(app_root, "nonprimary1"), file)); 511a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(google_apis::HTTP_SUCCESS, 512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddFileToFolder(CreateRemoteFolder(app_root, "nonprimary2"), file)); 513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_EQ(google_apis::HTTP_SUCCESS, 514a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddFileToFolder(CreateRemoteFolder(app_root, "nonprimary3"), file)); 515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RunRemoteToLocalSyncerUntilIdle(); 518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 519a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(4, CountParents(file)); 520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(SYNC_STATUS_OK, RunConflictResolver()); 522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(1, CountParents(file)); 524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace drive_backend 527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace sync_file_system 528