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