local_to_remote_syncer_unittest.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Copyright 2013 The Chromium Authors. All rights reserved. 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Use of this source code is governed by a BSD-style license that can be 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// found in the LICENSE file. 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h" 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "base/bind.h" 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "base/callback.h" 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "base/files/scoped_temp_dir.h" 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "base/logging.h" 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "base/run_loop.h" 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/drive/drive_api_util.h" 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/drive/drive_uploader.h" 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/drive/fake_drive_service.h" 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h" 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h" 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/fake_drive_service_helper.h" 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/fake_drive_uploader.h" 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/list_changes_task.h" 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h" 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h" 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h" 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/fake_remote_change_processor.h" 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/sync_file_system_test_util.h" 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "chrome/browser/sync_file_system/syncable_file_system_util.h" 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "content/public/test/test_browser_thread_bundle.h" 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "google_apis/drive/drive_api_parser.h" 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "google_apis/drive/gdata_errorcode.h" 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "testing/gtest/include/gtest/gtest.h" 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "third_party/leveldatabase/src/include/leveldb/env.h" 35 36namespace sync_file_system { 37namespace drive_backend { 38 39namespace { 40 41fileapi::FileSystemURL URL(const GURL& origin, 42 const std::string& path) { 43 return CreateSyncableFileSystemURL( 44 origin, base::FilePath::FromUTF8Unsafe(path)); 45} 46 47} // namespace 48 49class LocalToRemoteSyncerTest : public testing::Test { 50 public: 51 LocalToRemoteSyncerTest() 52 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} 53 virtual ~LocalToRemoteSyncerTest() {} 54 55 virtual void SetUp() OVERRIDE { 56 ASSERT_TRUE(database_dir_.CreateUniqueTempDir()); 57 in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); 58 59 fake_drive_service_.reset(new FakeDriveServiceWrapper); 60 61 drive_uploader_.reset(new FakeDriveUploader(fake_drive_service_.get())); 62 fake_drive_helper_.reset(new FakeDriveServiceHelper( 63 fake_drive_service_.get(), 64 drive_uploader_.get(), 65 kSyncRootFolderTitle)); 66 fake_remote_change_processor_.reset(new FakeRemoteChangeProcessor); 67 68 context_.reset(new SyncEngineContext( 69 fake_drive_service_.get(), 70 drive_uploader_.get(), 71 base::MessageLoopProxy::current(), 72 base::MessageLoopProxy::current(), 73 base::MessageLoopProxy::current())); 74 context_->SetRemoteChangeProcessor(fake_remote_change_processor_.get()); 75 76 RegisterSyncableFileSystem(); 77 78 sync_task_manager_.reset(new SyncTaskManager( 79 base::WeakPtr<SyncTaskManager::Client>(), 80 10 /* maximum_background_task */)); 81 sync_task_manager_->Initialize(SYNC_STATUS_OK); 82 } 83 84 virtual void TearDown() OVERRIDE { 85 sync_task_manager_.reset(); 86 fake_drive_service_.reset(); 87 drive_uploader_.reset(); 88 89 RevokeSyncableFileSystem(); 90 91 fake_remote_change_processor_.reset(); 92 fake_drive_helper_.reset(); 93 context_.reset(); 94 base::RunLoop().RunUntilIdle(); 95 } 96 97 void InitializeMetadataDatabase() { 98 SyncEngineInitializer* initializer = 99 new SyncEngineInitializer(context_.get(), 100 base::MessageLoopProxy::current(), 101 database_dir_.path(), 102 in_memory_env_.get()); 103 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 104 105 sync_task_manager_->ScheduleSyncTask( 106 FROM_HERE, 107 scoped_ptr<SyncTask>(initializer), 108 SyncTaskManager::PRIORITY_MED, 109 base::Bind(&LocalToRemoteSyncerTest::DidInitializeMetadataDatabase, 110 base::Unretained(this), initializer, &status)); 111 112 base::RunLoop().RunUntilIdle(); 113 EXPECT_EQ(SYNC_STATUS_OK, status); 114 } 115 116 void DidInitializeMetadataDatabase(SyncEngineInitializer* initializer, 117 SyncStatusCode* status_out, 118 SyncStatusCode status) { 119 *status_out = status; 120 context_->SetMetadataDatabase(initializer->PassMetadataDatabase()); 121 } 122 123 void RegisterApp(const std::string& app_id, 124 const std::string& app_root_folder_id) { 125 SyncStatusCode status = SYNC_STATUS_FAILED; 126 context_->GetMetadataDatabase()->RegisterApp( 127 app_id, app_root_folder_id, CreateResultReceiver(&status)); 128 base::RunLoop().RunUntilIdle(); 129 EXPECT_EQ(SYNC_STATUS_OK, status); 130 } 131 132 MetadataDatabase* GetMetadataDatabase() { 133 return context_->GetMetadataDatabase(); 134 } 135 136 protected: 137 std::string CreateSyncRoot() { 138 std::string sync_root_folder_id; 139 EXPECT_EQ(google_apis::HTTP_CREATED, 140 fake_drive_helper_->AddOrphanedFolder( 141 kSyncRootFolderTitle, &sync_root_folder_id)); 142 return sync_root_folder_id; 143 } 144 145 std::string CreateRemoteFolder(const std::string& parent_folder_id, 146 const std::string& title) { 147 std::string folder_id; 148 EXPECT_EQ(google_apis::HTTP_CREATED, 149 fake_drive_helper_->AddFolder( 150 parent_folder_id, title, &folder_id)); 151 return folder_id; 152 } 153 154 std::string CreateRemoteFile(const std::string& parent_folder_id, 155 const std::string& title, 156 const std::string& content) { 157 std::string file_id; 158 EXPECT_EQ(google_apis::HTTP_SUCCESS, 159 fake_drive_helper_->AddFile( 160 parent_folder_id, title, content, &file_id)); 161 return file_id; 162 } 163 164 void DeleteResource(const std::string& file_id) { 165 EXPECT_EQ(google_apis::HTTP_NO_CONTENT, 166 fake_drive_helper_->DeleteResource(file_id)); 167 } 168 169 SyncStatusCode RunLocalToRemoteSyncer(FileChange file_change, 170 const fileapi::FileSystemURL& url) { 171 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 172 base::FilePath local_path = base::FilePath::FromUTF8Unsafe("dummy"); 173 scoped_ptr<LocalToRemoteSyncer> syncer(new LocalToRemoteSyncer( 174 context_.get(), 175 SyncFileMetadata(file_change.file_type(), 0, base::Time()), 176 file_change, local_path, url)); 177 syncer->RunExclusive(CreateResultReceiver(&status)); 178 base::RunLoop().RunUntilIdle(); 179 return status; 180 } 181 182 SyncStatusCode ListChanges() { 183 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 184 sync_task_manager_->ScheduleSyncTask( 185 FROM_HERE, 186 scoped_ptr<SyncTask>(new ListChangesTask(context_.get())), 187 SyncTaskManager::PRIORITY_MED, 188 CreateResultReceiver(&status)); 189 base::RunLoop().RunUntilIdle(); 190 return status; 191 } 192 193 SyncStatusCode RunRemoteToLocalSyncer() { 194 SyncStatusCode status = SYNC_STATUS_UNKNOWN; 195 scoped_ptr<RemoteToLocalSyncer> 196 syncer(new RemoteToLocalSyncer(context_.get())); 197 syncer->RunExclusive(CreateResultReceiver(&status)); 198 base::RunLoop().RunUntilIdle(); 199 return status; 200 } 201 202 ScopedVector<google_apis::ResourceEntry> 203 GetResourceEntriesForParentAndTitle(const std::string& parent_folder_id, 204 const std::string& title) { 205 ScopedVector<google_apis::ResourceEntry> entries; 206 EXPECT_EQ(google_apis::HTTP_SUCCESS, 207 fake_drive_helper_->SearchByTitle( 208 parent_folder_id, title, &entries)); 209 return entries.Pass(); 210 } 211 212 std::string GetFileIDForParentAndTitle(const std::string& parent_folder_id, 213 const std::string& title) { 214 ScopedVector<google_apis::ResourceEntry> entries = 215 GetResourceEntriesForParentAndTitle(parent_folder_id, title); 216 if (entries.size() != 1) 217 return std::string(); 218 return entries[0]->resource_id(); 219 } 220 221 void VerifyTitleUniqueness(const std::string& parent_folder_id, 222 const std::string& title, 223 google_apis::DriveEntryKind kind) { 224 ScopedVector<google_apis::ResourceEntry> entries; 225 EXPECT_EQ(google_apis::HTTP_SUCCESS, 226 fake_drive_helper_->SearchByTitle( 227 parent_folder_id, title, &entries)); 228 ASSERT_EQ(1u, entries.size()); 229 EXPECT_EQ(kind, entries[0]->kind()); 230 } 231 232 void VerifyFileDeletion(const std::string& parent_folder_id, 233 const std::string& title) { 234 ScopedVector<google_apis::ResourceEntry> entries; 235 EXPECT_EQ(google_apis::HTTP_SUCCESS, 236 fake_drive_helper_->SearchByTitle( 237 parent_folder_id, title, &entries)); 238 EXPECT_TRUE(entries.empty()); 239 } 240 241 private: 242 content::TestBrowserThreadBundle thread_bundle_; 243 base::ScopedTempDir database_dir_; 244 scoped_ptr<leveldb::Env> in_memory_env_; 245 246 scoped_ptr<FakeDriveServiceWrapper> fake_drive_service_; 247 scoped_ptr<drive::DriveUploaderInterface> drive_uploader_; 248 scoped_ptr<SyncEngineContext> context_; 249 scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_; 250 scoped_ptr<MetadataDatabase> metadata_database_; 251 scoped_ptr<FakeRemoteChangeProcessor> fake_remote_change_processor_; 252 scoped_ptr<SyncTaskManager> sync_task_manager_; 253 254 DISALLOW_COPY_AND_ASSIGN(LocalToRemoteSyncerTest); 255}; 256 257TEST_F(LocalToRemoteSyncerTest, CreateFile) { 258 const GURL kOrigin("chrome-extension://example"); 259 const std::string sync_root = CreateSyncRoot(); 260 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 261 InitializeMetadataDatabase(); 262 RegisterApp(kOrigin.host(), app_root); 263 264 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 265 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 266 SYNC_FILE_TYPE_FILE), 267 URL(kOrigin, "file1"))); 268 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 269 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 270 SYNC_FILE_TYPE_DIRECTORY), 271 URL(kOrigin, "folder"))); 272 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 273 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 274 SYNC_FILE_TYPE_FILE), 275 URL(kOrigin, "folder/file2"))); 276 277 std::string folder_id = GetFileIDForParentAndTitle(app_root, "folder"); 278 ASSERT_FALSE(folder_id.empty()); 279 280 VerifyTitleUniqueness(app_root, "file1", google_apis::ENTRY_KIND_FILE); 281 VerifyTitleUniqueness(app_root, "folder", google_apis::ENTRY_KIND_FOLDER); 282 VerifyTitleUniqueness(folder_id, "file2", google_apis::ENTRY_KIND_FILE); 283} 284 285TEST_F(LocalToRemoteSyncerTest, CreateFileOnMissingPath) { 286 const GURL kOrigin("chrome-extension://example"); 287 const std::string sync_root = CreateSyncRoot(); 288 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 289 InitializeMetadataDatabase(); 290 RegisterApp(kOrigin.host(), app_root); 291 292 // Run the syncer 3 times to create missing folder1 and folder2. 293 EXPECT_EQ(SYNC_STATUS_RETRY, RunLocalToRemoteSyncer( 294 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 295 SYNC_FILE_TYPE_FILE), 296 URL(kOrigin, "folder1/folder2/file"))); 297 EXPECT_EQ(SYNC_STATUS_RETRY, RunLocalToRemoteSyncer( 298 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 299 SYNC_FILE_TYPE_FILE), 300 URL(kOrigin, "folder1/folder2/file"))); 301 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 302 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 303 SYNC_FILE_TYPE_FILE), 304 URL(kOrigin, "folder1/folder2/file"))); 305 306 std::string folder_id1 = GetFileIDForParentAndTitle(app_root, "folder1"); 307 ASSERT_FALSE(folder_id1.empty()); 308 std::string folder_id2 = GetFileIDForParentAndTitle(folder_id1, "folder2"); 309 ASSERT_FALSE(folder_id2.empty()); 310 311 VerifyTitleUniqueness(app_root, "folder1", google_apis::ENTRY_KIND_FOLDER); 312 VerifyTitleUniqueness(folder_id1, "folder2", google_apis::ENTRY_KIND_FOLDER); 313 VerifyTitleUniqueness(folder_id2, "file", google_apis::ENTRY_KIND_FILE); 314} 315 316TEST_F(LocalToRemoteSyncerTest, DeleteFile) { 317 const GURL kOrigin("chrome-extension://example"); 318 const std::string sync_root = CreateSyncRoot(); 319 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 320 InitializeMetadataDatabase(); 321 RegisterApp(kOrigin.host(), app_root); 322 323 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 324 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 325 SYNC_FILE_TYPE_FILE), 326 URL(kOrigin, "file"))); 327 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 328 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 329 SYNC_FILE_TYPE_DIRECTORY), 330 URL(kOrigin, "folder"))); 331 332 VerifyTitleUniqueness(app_root, "file", google_apis::ENTRY_KIND_FILE); 333 VerifyTitleUniqueness(app_root, "folder", google_apis::ENTRY_KIND_FOLDER); 334 335 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 336 FileChange(FileChange::FILE_CHANGE_DELETE, 337 SYNC_FILE_TYPE_FILE), 338 URL(kOrigin, "file"))); 339 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 340 FileChange(FileChange::FILE_CHANGE_DELETE, 341 SYNC_FILE_TYPE_DIRECTORY), 342 URL(kOrigin, "folder"))); 343 344 VerifyFileDeletion(app_root, "file"); 345 VerifyFileDeletion(app_root, "folder"); 346} 347 348TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFileOnFolder) { 349 const GURL kOrigin("chrome-extension://example"); 350 const std::string sync_root = CreateSyncRoot(); 351 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 352 InitializeMetadataDatabase(); 353 RegisterApp(kOrigin.host(), app_root); 354 355 CreateRemoteFolder(app_root, "foo"); 356 EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 357 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 358 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 359 SYNC_FILE_TYPE_FILE), 360 URL(kOrigin, "foo"))); 361 362 // There should exist both file and folder on remote. 363 ScopedVector<google_apis::ResourceEntry> entries = 364 GetResourceEntriesForParentAndTitle(app_root, "foo"); 365 ASSERT_EQ(2u, entries.size()); 366 EXPECT_EQ(google_apis::ENTRY_KIND_FOLDER, entries[0]->kind()); 367 EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[1]->kind()); 368} 369 370TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFolderOnFile) { 371 const GURL kOrigin("chrome-extension://example"); 372 const std::string sync_root = CreateSyncRoot(); 373 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 374 InitializeMetadataDatabase(); 375 RegisterApp(kOrigin.host(), app_root); 376 377 CreateRemoteFile(app_root, "foo", "data"); 378 EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 379 380 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 381 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 382 SYNC_FILE_TYPE_DIRECTORY), 383 URL(kOrigin, "foo"))); 384 385 // There should exist both file and folder on remote. 386 ScopedVector<google_apis::ResourceEntry> entries = 387 GetResourceEntriesForParentAndTitle(app_root, "foo"); 388 ASSERT_EQ(2u, entries.size()); 389 EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[0]->kind()); 390 EXPECT_EQ(google_apis::ENTRY_KIND_FOLDER, entries[1]->kind()); 391} 392 393TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFileOnFile) { 394 const GURL kOrigin("chrome-extension://example"); 395 const std::string sync_root = CreateSyncRoot(); 396 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 397 InitializeMetadataDatabase(); 398 RegisterApp(kOrigin.host(), app_root); 399 400 CreateRemoteFile(app_root, "foo", "data"); 401 EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 402 403 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 404 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 405 SYNC_FILE_TYPE_FILE), 406 URL(kOrigin, "foo"))); 407 408 // There should exist both files on remote. 409 ScopedVector<google_apis::ResourceEntry> entries = 410 GetResourceEntriesForParentAndTitle(app_root, "foo"); 411 ASSERT_EQ(2u, entries.size()); 412 EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[0]->kind()); 413 EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[1]->kind()); 414} 415 416TEST_F(LocalToRemoteSyncerTest, Conflict_UpdateDeleteOnFile) { 417 const GURL kOrigin("chrome-extension://example"); 418 const std::string sync_root = CreateSyncRoot(); 419 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 420 InitializeMetadataDatabase(); 421 RegisterApp(kOrigin.host(), app_root); 422 423 const std::string file_id = CreateRemoteFile(app_root, "foo", "data"); 424 EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 425 426 SyncStatusCode status; 427 do { 428 status = RunRemoteToLocalSyncer(); 429 EXPECT_TRUE(status == SYNC_STATUS_OK || 430 status == SYNC_STATUS_RETRY || 431 status == SYNC_STATUS_NO_CHANGE_TO_SYNC); 432 } while (status != SYNC_STATUS_NO_CHANGE_TO_SYNC); 433 434 DeleteResource(file_id); 435 436 EXPECT_EQ(SYNC_STATUS_FILE_BUSY, RunLocalToRemoteSyncer( 437 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 438 SYNC_FILE_TYPE_FILE), 439 URL(kOrigin, "foo"))); 440 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 441 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 442 SYNC_FILE_TYPE_FILE), 443 URL(kOrigin, "foo"))); 444 445 ScopedVector<google_apis::ResourceEntry> entries = 446 GetResourceEntriesForParentAndTitle(app_root, "foo"); 447 ASSERT_EQ(1u, entries.size()); 448 EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[0]->kind()); 449 EXPECT_TRUE(!entries[0]->deleted()); 450 EXPECT_NE(file_id, entries[0]->resource_id()); 451} 452 453TEST_F(LocalToRemoteSyncerTest, Conflict_CreateDeleteOnFile) { 454 const GURL kOrigin("chrome-extension://example"); 455 const std::string sync_root = CreateSyncRoot(); 456 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 457 InitializeMetadataDatabase(); 458 RegisterApp(kOrigin.host(), app_root); 459 460 const std::string file_id = CreateRemoteFile(app_root, "foo", "data"); 461 EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 462 SyncStatusCode status; 463 do { 464 status = RunRemoteToLocalSyncer(); 465 EXPECT_TRUE(status == SYNC_STATUS_OK || 466 status == SYNC_STATUS_RETRY || 467 status == SYNC_STATUS_NO_CHANGE_TO_SYNC); 468 } while (status != SYNC_STATUS_NO_CHANGE_TO_SYNC); 469 470 DeleteResource(file_id); 471 472 EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 473 474 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 475 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 476 SYNC_FILE_TYPE_FILE), 477 URL(kOrigin, "foo"))); 478 479 ScopedVector<google_apis::ResourceEntry> entries = 480 GetResourceEntriesForParentAndTitle(app_root, "foo"); 481 ASSERT_EQ(1u, entries.size()); 482 EXPECT_EQ(google_apis::ENTRY_KIND_FILE, entries[0]->kind()); 483 EXPECT_TRUE(!entries[0]->deleted()); 484 EXPECT_NE(file_id, entries[0]->resource_id()); 485} 486 487TEST_F(LocalToRemoteSyncerTest, Conflict_CreateFolderOnFolder) { 488 const GURL kOrigin("chrome-extension://example"); 489 const std::string sync_root = CreateSyncRoot(); 490 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 491 InitializeMetadataDatabase(); 492 RegisterApp(kOrigin.host(), app_root); 493 494 const std::string folder_id = CreateRemoteFolder(app_root, "foo"); 495 496 EXPECT_EQ(SYNC_STATUS_OK, RunLocalToRemoteSyncer( 497 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 498 SYNC_FILE_TYPE_DIRECTORY), 499 URL(kOrigin, "foo"))); 500 501 ScopedVector<google_apis::ResourceEntry> entries = 502 GetResourceEntriesForParentAndTitle(app_root, "foo"); 503 ASSERT_EQ(2u, entries.size()); 504 EXPECT_EQ(google_apis::ENTRY_KIND_FOLDER, entries[0]->kind()); 505 EXPECT_EQ(google_apis::ENTRY_KIND_FOLDER, entries[1]->kind()); 506 EXPECT_TRUE(!entries[0]->deleted()); 507 EXPECT_TRUE(!entries[1]->deleted()); 508 EXPECT_TRUE(folder_id == entries[0]->resource_id() || 509 folder_id == entries[1]->resource_id()); 510 511 TrackerIDSet trackers; 512 EXPECT_TRUE(GetMetadataDatabase()->FindTrackersByFileID( 513 folder_id, &trackers)); 514 EXPECT_EQ(1u, trackers.size()); 515 ASSERT_TRUE(trackers.has_active()); 516} 517 518TEST_F(LocalToRemoteSyncerTest, AppRootDeletion) { 519 const GURL kOrigin("chrome-extension://example"); 520 const std::string sync_root = CreateSyncRoot(); 521 const std::string app_root = CreateRemoteFolder(sync_root, kOrigin.host()); 522 InitializeMetadataDatabase(); 523 RegisterApp(kOrigin.host(), app_root); 524 525 DeleteResource(app_root); 526 EXPECT_EQ(SYNC_STATUS_OK, ListChanges()); 527 SyncStatusCode status; 528 do { 529 status = RunRemoteToLocalSyncer(); 530 EXPECT_TRUE(status == SYNC_STATUS_OK || 531 status == SYNC_STATUS_RETRY || 532 status == SYNC_STATUS_NO_CHANGE_TO_SYNC); 533 } while (status != SYNC_STATUS_NO_CHANGE_TO_SYNC); 534 535 EXPECT_EQ(SYNC_STATUS_UNKNOWN_ORIGIN, RunLocalToRemoteSyncer( 536 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, 537 SYNC_FILE_TYPE_DIRECTORY), 538 URL(kOrigin, "foo"))); 539 540 // SyncEngine will re-register the app and resurrect the app root later. 541} 542 543} // namespace drive_backend 544} // namespace sync_file_system 545