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