1// Copyright (c) 2012 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/chromeos/drive/change_list_processor.h" 6 7#include "base/files/scoped_temp_dir.h" 8#include "base/message_loop/message_loop_proxy.h" 9#include "base/values.h" 10#include "chrome/browser/chromeos/drive/drive.pb.h" 11#include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h" 12#include "chrome/browser/chromeos/drive/file_cache.h" 13#include "chrome/browser/chromeos/drive/file_change.h" 14#include "chrome/browser/chromeos/drive/file_system_util.h" 15#include "chrome/browser/chromeos/drive/resource_metadata.h" 16#include "chrome/browser/chromeos/drive/test_util.h" 17#include "content/public/test/test_browser_thread_bundle.h" 18#include "google_apis/drive/drive_api_parser.h" 19#include "google_apis/drive/test_util.h" 20#include "testing/gtest/include/gtest/gtest.h" 21 22namespace drive { 23namespace internal { 24 25namespace { 26 27const int64 kBaseResourceListChangestamp = 123; 28const char kRootId[] = "fake_root"; 29 30enum FileOrDirectory { 31 FILE, 32 DIRECTORY, 33}; 34 35struct EntryExpectation { 36 std::string path; 37 std::string id; 38 std::string parent_id; 39 FileOrDirectory type; 40}; 41 42// Returns a basic change list which contains some files and directories. 43ScopedVector<ChangeList> CreateBaseChangeList() { 44 ScopedVector<ChangeList> change_lists; 45 change_lists.push_back(new ChangeList); 46 47 // Add directories to the change list. 48 ResourceEntry directory; 49 directory.mutable_file_info()->set_is_directory(true); 50 51 directory.set_title("Directory 1"); 52 directory.set_resource_id("1_folder_resource_id"); 53 change_lists[0]->mutable_entries()->push_back(directory); 54 change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); 55 56 directory.set_title("Sub Directory Folder"); 57 directory.set_resource_id("sub_dir_folder_resource_id"); 58 change_lists[0]->mutable_entries()->push_back(directory); 59 change_lists[0]->mutable_parent_resource_ids()->push_back( 60 "1_folder_resource_id"); 61 62 directory.set_title("Sub Sub Directory Folder"); 63 directory.set_resource_id("sub_sub_directory_folder_id"); 64 change_lists[0]->mutable_entries()->push_back(directory); 65 change_lists[0]->mutable_parent_resource_ids()->push_back( 66 "sub_dir_folder_resource_id"); 67 68 directory.set_title("Directory 2 excludeDir-test"); 69 directory.set_resource_id("sub_dir_folder_2_self_link"); 70 change_lists[0]->mutable_entries()->push_back(directory); 71 change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); 72 73 // Add files to the change list. 74 ResourceEntry file; 75 76 file.set_title("File 1.txt"); 77 file.set_resource_id("2_file_resource_id"); 78 change_lists[0]->mutable_entries()->push_back(file); 79 change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); 80 81 file.set_title("SubDirectory File 1.txt"); 82 file.set_resource_id("subdirectory_file_1_id"); 83 change_lists[0]->mutable_entries()->push_back(file); 84 change_lists[0]->mutable_parent_resource_ids()->push_back( 85 "1_folder_resource_id"); 86 87 file.set_title("Orphan File 1.txt"); 88 file.set_resource_id("1_orphanfile_resource_id"); 89 change_lists[0]->mutable_entries()->push_back(file); 90 change_lists[0]->mutable_parent_resource_ids()->push_back(""); 91 92 change_lists[0]->set_largest_changestamp(kBaseResourceListChangestamp); 93 return change_lists.Pass(); 94} 95 96class ChangeListProcessorTest : public testing::Test { 97 protected: 98 virtual void SetUp() OVERRIDE { 99 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 100 101 metadata_storage_.reset(new ResourceMetadataStorage( 102 temp_dir_.path(), base::MessageLoopProxy::current().get())); 103 ASSERT_TRUE(metadata_storage_->Initialize()); 104 105 fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter); 106 cache_.reset(new FileCache(metadata_storage_.get(), 107 temp_dir_.path(), 108 base::MessageLoopProxy::current().get(), 109 fake_free_disk_space_getter_.get())); 110 ASSERT_TRUE(cache_->Initialize()); 111 112 metadata_.reset(new internal::ResourceMetadata( 113 metadata_storage_.get(), cache_.get(), 114 base::MessageLoopProxy::current())); 115 ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize()); 116 } 117 118 // Applies the |changes| to |metadata_| as a full resource list of changestamp 119 // |kBaseResourceListChangestamp|. 120 FileError ApplyFullResourceList(ScopedVector<ChangeList> changes) { 121 scoped_ptr<google_apis::AboutResource> about_resource( 122 new google_apis::AboutResource); 123 about_resource->set_largest_change_id(kBaseResourceListChangestamp); 124 about_resource->set_root_folder_id(kRootId); 125 126 ChangeListProcessor processor(metadata_.get()); 127 return processor.Apply(about_resource.Pass(), 128 changes.Pass(), 129 false /* is_delta_update */); 130 } 131 132 // Applies the |changes| to |metadata_| as a delta update. Delta changelists 133 // should contain their changestamp in themselves. 134 FileError ApplyChangeList(ScopedVector<ChangeList> changes, 135 FileChange* changed_files) { 136 scoped_ptr<google_apis::AboutResource> about_resource( 137 new google_apis::AboutResource); 138 about_resource->set_largest_change_id(kBaseResourceListChangestamp); 139 about_resource->set_root_folder_id(kRootId); 140 141 ChangeListProcessor processor(metadata_.get()); 142 FileError error = processor.Apply(about_resource.Pass(), 143 changes.Pass(), 144 true /* is_delta_update */); 145 *changed_files = processor.changed_files(); 146 return error; 147 } 148 149 // Gets the resource entry for the path from |metadata_| synchronously. 150 // Returns null if the entry does not exist. 151 scoped_ptr<ResourceEntry> GetResourceEntry(const std::string& path) { 152 scoped_ptr<ResourceEntry> entry(new ResourceEntry); 153 FileError error = metadata_->GetResourceEntryByPath( 154 base::FilePath::FromUTF8Unsafe(path), entry.get()); 155 if (error != FILE_ERROR_OK) 156 entry.reset(); 157 return entry.Pass(); 158 } 159 160 content::TestBrowserThreadBundle thread_bundle_; 161 base::ScopedTempDir temp_dir_; 162 scoped_ptr<ResourceMetadataStorage, 163 test_util::DestroyHelperForTests> metadata_storage_; 164 scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_; 165 scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_; 166 scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests> metadata_; 167}; 168 169} // namespace 170 171TEST_F(ChangeListProcessorTest, ApplyFullResourceList) { 172 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 173 174 const EntryExpectation kExpected[] = { 175 // Root files 176 {"drive/root", kRootId, "", DIRECTORY}, 177 {"drive/root/File 1.txt", 178 "2_file_resource_id", kRootId, FILE}, 179 // Subdirectory files 180 {"drive/root/Directory 1", 181 "1_folder_resource_id", kRootId, DIRECTORY}, 182 {"drive/root/Directory 1/SubDirectory File 1.txt", 183 "subdirectory_file_1_id", "1_folder_resource_id", FILE}, 184 {"drive/root/Directory 2 excludeDir-test", 185 "sub_dir_folder_2_self_link", kRootId, DIRECTORY}, 186 // Deeper 187 {"drive/root/Directory 1/Sub Directory Folder", 188 "sub_dir_folder_resource_id", 189 "1_folder_resource_id", DIRECTORY}, 190 {"drive/root/Directory 1/Sub Directory Folder/Sub Sub Directory Folder", 191 "sub_sub_directory_folder_id", 192 "sub_dir_folder_resource_id", DIRECTORY}, 193 // Orphan 194 {"drive/other/Orphan File 1.txt", "1_orphanfile_resource_id", 195 "", FILE}, 196 }; 197 198 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kExpected); ++i) { 199 scoped_ptr<ResourceEntry> entry = GetResourceEntry(kExpected[i].path); 200 ASSERT_TRUE(entry) << "for path: " << kExpected[i].path; 201 EXPECT_EQ(kExpected[i].id, entry->resource_id()); 202 203 ResourceEntry parent_entry; 204 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryById( 205 entry->parent_local_id(), &parent_entry)); 206 EXPECT_EQ(kExpected[i].parent_id, parent_entry.resource_id()); 207 EXPECT_EQ(kExpected[i].type, 208 entry->file_info().is_directory() ? DIRECTORY : FILE); 209 } 210 211 int64 changestamp = 0; 212 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 213 EXPECT_EQ(kBaseResourceListChangestamp, changestamp); 214} 215 216TEST_F(ChangeListProcessorTest, DeltaFileAddedInNewDirectory) { 217 ScopedVector<ChangeList> change_lists; 218 change_lists.push_back(new ChangeList); 219 220 ResourceEntry new_folder; 221 new_folder.set_resource_id("new_folder_resource_id"); 222 new_folder.set_title("New Directory"); 223 new_folder.mutable_file_info()->set_is_directory(true); 224 change_lists[0]->mutable_entries()->push_back(new_folder); 225 change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); 226 227 ResourceEntry new_file; 228 new_file.set_resource_id("file_added_in_new_dir_id"); 229 new_file.set_title("File in new dir.txt"); 230 change_lists[0]->mutable_entries()->push_back(new_file); 231 change_lists[0]->mutable_parent_resource_ids()->push_back( 232 new_folder.resource_id()); 233 234 change_lists[0]->set_largest_changestamp(16730); 235 236 // Apply the changelist and check the effect. 237 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 238 239 FileChange changed_files; 240 EXPECT_EQ(FILE_ERROR_OK, 241 ApplyChangeList(change_lists.Pass(), &changed_files)); 242 243 int64 changestamp = 0; 244 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 245 EXPECT_EQ(16730, changestamp); 246 EXPECT_TRUE(GetResourceEntry("drive/root/New Directory")); 247 EXPECT_TRUE(GetResourceEntry( 248 "drive/root/New Directory/File in new dir.txt")); 249 250 EXPECT_EQ(2U, changed_files.size()); 251 EXPECT_TRUE(changed_files.count(base::FilePath::FromUTF8Unsafe( 252 "drive/root/New Directory/File in new dir.txt"))); 253 EXPECT_TRUE(changed_files.count( 254 base::FilePath::FromUTF8Unsafe("drive/root/New Directory"))); 255} 256 257TEST_F(ChangeListProcessorTest, DeltaDirMovedFromRootToDirectory) { 258 ScopedVector<ChangeList> change_lists; 259 change_lists.push_back(new ChangeList); 260 261 ResourceEntry entry; 262 entry.set_resource_id("1_folder_resource_id"); 263 entry.set_title("Directory 1"); 264 entry.mutable_file_info()->set_is_directory(true); 265 change_lists[0]->mutable_entries()->push_back(entry); 266 change_lists[0]->mutable_parent_resource_ids()->push_back( 267 "sub_dir_folder_2_self_link"); 268 269 change_lists[0]->set_largest_changestamp(16809); 270 271 // Apply the changelist and check the effect. 272 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 273 274 FileChange changed_files; 275 EXPECT_EQ(FILE_ERROR_OK, 276 ApplyChangeList(change_lists.Pass(), &changed_files)); 277 278 int64 changestamp = 0; 279 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 280 EXPECT_EQ(16809, changestamp); 281 EXPECT_FALSE(GetResourceEntry("drive/root/Directory 1")); 282 EXPECT_TRUE(GetResourceEntry( 283 "drive/root/Directory 2 excludeDir-test/Directory 1")); 284 285 EXPECT_EQ(2U, changed_files.size()); 286 EXPECT_TRUE(changed_files.CountDirectory( 287 base::FilePath::FromUTF8Unsafe("drive/root"))); 288 EXPECT_TRUE(changed_files.count( 289 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1"))); 290 EXPECT_TRUE(changed_files.CountDirectory(base::FilePath::FromUTF8Unsafe( 291 "drive/root/Directory 2 excludeDir-test"))); 292 EXPECT_TRUE(changed_files.count(base::FilePath::FromUTF8Unsafe( 293 "drive/root/Directory 2 excludeDir-test/Directory 1"))); 294} 295 296TEST_F(ChangeListProcessorTest, DeltaFileMovedFromDirectoryToRoot) { 297 ScopedVector<ChangeList> change_lists; 298 change_lists.push_back(new ChangeList); 299 300 ResourceEntry entry; 301 entry.set_resource_id("subdirectory_file_1_id"); 302 entry.set_title("SubDirectory File 1.txt"); 303 change_lists[0]->mutable_entries()->push_back(entry); 304 change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); 305 306 change_lists[0]->set_largest_changestamp(16815); 307 308 // Apply the changelist and check the effect. 309 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 310 FileChange changed_files; 311 EXPECT_EQ(FILE_ERROR_OK, 312 ApplyChangeList(change_lists.Pass(), &changed_files)); 313 314 int64 changestamp = 0; 315 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 316 EXPECT_EQ(16815, changestamp); 317 EXPECT_FALSE(GetResourceEntry( 318 "drive/root/Directory 1/SubDirectory File 1.txt")); 319 EXPECT_TRUE(GetResourceEntry("drive/root/SubDirectory File 1.txt")); 320 321 EXPECT_EQ(2U, changed_files.size()); 322 EXPECT_TRUE(changed_files.count( 323 base::FilePath::FromUTF8Unsafe("drive/root/SubDirectory File 1.txt"))); 324 EXPECT_TRUE(changed_files.count(base::FilePath::FromUTF8Unsafe( 325 "drive/root/Directory 1/SubDirectory File 1.txt"))); 326} 327 328TEST_F(ChangeListProcessorTest, DeltaFileRenamedInDirectory) { 329 ScopedVector<ChangeList> change_lists; 330 change_lists.push_back(new ChangeList); 331 332 ResourceEntry entry; 333 entry.set_resource_id("subdirectory_file_1_id"); 334 entry.set_title("New SubDirectory File 1.txt"); 335 change_lists[0]->mutable_entries()->push_back(entry); 336 change_lists[0]->mutable_parent_resource_ids()->push_back( 337 "1_folder_resource_id"); 338 339 change_lists[0]->set_largest_changestamp(16767); 340 341 // Apply the changelist and check the effect. 342 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 343 FileChange changed_files; 344 EXPECT_EQ(FILE_ERROR_OK, 345 ApplyChangeList(change_lists.Pass(), &changed_files)); 346 347 int64 changestamp = 0; 348 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 349 EXPECT_EQ(16767, changestamp); 350 EXPECT_FALSE(GetResourceEntry( 351 "drive/root/Directory 1/SubDirectory File 1.txt")); 352 EXPECT_TRUE(GetResourceEntry( 353 "drive/root/Directory 1/New SubDirectory File 1.txt")); 354 355 EXPECT_EQ(2U, changed_files.size()); 356 EXPECT_TRUE(changed_files.count(base::FilePath::FromUTF8Unsafe( 357 "drive/root/Directory 1/SubDirectory File 1.txt"))); 358 EXPECT_TRUE(changed_files.count(base::FilePath::FromUTF8Unsafe( 359 "drive/root/Directory 1/New SubDirectory File 1.txt"))); 360} 361 362TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileInRoot) { 363 // Create ChangeList to add a file. 364 ScopedVector<ChangeList> change_lists; 365 change_lists.push_back(new ChangeList); 366 367 ResourceEntry entry; 368 entry.set_resource_id("added_in_root_id"); 369 entry.set_title("Added file.txt"); 370 change_lists[0]->mutable_entries()->push_back(entry); 371 change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); 372 373 change_lists[0]->set_largest_changestamp(16683); 374 375 // Apply. 376 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 377 FileChange changed_files; 378 EXPECT_EQ(FILE_ERROR_OK, 379 ApplyChangeList(change_lists.Pass(), &changed_files)); 380 381 int64 changestamp = 0; 382 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 383 EXPECT_EQ(16683, changestamp); 384 EXPECT_TRUE(GetResourceEntry("drive/root/Added file.txt")); 385 EXPECT_EQ(1U, changed_files.size()); 386 EXPECT_TRUE(changed_files.count( 387 base::FilePath::FromUTF8Unsafe("drive/root/Added file.txt"))); 388 389 // Create ChangeList to delete the file. 390 change_lists.push_back(new ChangeList); 391 392 entry.set_deleted(true); 393 change_lists[0]->mutable_entries()->push_back(entry); 394 change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); 395 396 change_lists[0]->set_largest_changestamp(16687); 397 398 // Apply. 399 EXPECT_EQ(FILE_ERROR_OK, 400 ApplyChangeList(change_lists.Pass(), &changed_files)); 401 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 402 EXPECT_EQ(16687, changestamp); 403 EXPECT_FALSE(GetResourceEntry("drive/root/Added file.txt")); 404 EXPECT_EQ(1U, changed_files.size()); 405 EXPECT_TRUE(changed_files.count( 406 base::FilePath::FromUTF8Unsafe("drive/root/Added file.txt"))); 407} 408 409 410TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileFromExistingDirectory) { 411 // Create ChangeList to add a file. 412 ScopedVector<ChangeList> change_lists; 413 change_lists.push_back(new ChangeList); 414 415 ResourceEntry entry; 416 entry.set_resource_id("added_in_root_id"); 417 entry.set_title("Added file.txt"); 418 change_lists[0]->mutable_entries()->push_back(entry); 419 change_lists[0]->mutable_parent_resource_ids()->push_back( 420 "1_folder_resource_id"); 421 422 change_lists[0]->set_largest_changestamp(16730); 423 424 // Apply. 425 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 426 FileChange changed_files; 427 EXPECT_EQ(FILE_ERROR_OK, 428 ApplyChangeList(change_lists.Pass(), &changed_files)); 429 int64 changestamp = 0; 430 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 431 EXPECT_EQ(16730, changestamp); 432 EXPECT_TRUE(GetResourceEntry("drive/root/Directory 1/Added file.txt")); 433 434 EXPECT_EQ(1U, changed_files.size()); 435 EXPECT_TRUE(changed_files.count( 436 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt"))); 437 438 // Create ChangeList to delete the file. 439 change_lists.push_back(new ChangeList); 440 441 entry.set_deleted(true); 442 change_lists[0]->mutable_entries()->push_back(entry); 443 change_lists[0]->mutable_parent_resource_ids()->push_back( 444 "1_folder_resource_id"); 445 446 change_lists[0]->set_largest_changestamp(16770); 447 448 // Apply. 449 EXPECT_EQ(FILE_ERROR_OK, 450 ApplyChangeList(change_lists.Pass(), &changed_files)); 451 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 452 EXPECT_EQ(16770, changestamp); 453 EXPECT_FALSE(GetResourceEntry("drive/root/Directory 1/Added file.txt")); 454 455 EXPECT_EQ(1U, changed_files.size()); 456 EXPECT_TRUE(changed_files.count( 457 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt"))); 458} 459 460TEST_F(ChangeListProcessorTest, DeltaAddFileToNewButDeletedDirectory) { 461 // Create a change which contains the following updates: 462 // 1) A new PDF file is added to a new directory 463 // 2) but the new directory is marked "deleted" (i.e. moved to Trash) 464 // Hence, the PDF file should be just ignored. 465 ScopedVector<ChangeList> change_lists; 466 change_lists.push_back(new ChangeList); 467 468 ResourceEntry file; 469 file.set_resource_id("file_added_in_deleted_id"); 470 file.set_title("new_pdf_file.pdf"); 471 file.set_deleted(true); 472 change_lists[0]->mutable_entries()->push_back(file); 473 change_lists[0]->mutable_parent_resource_ids()->push_back( 474 "new_folder_resource_id"); 475 476 ResourceEntry directory; 477 directory.set_resource_id("new_folder_resource_id"); 478 directory.set_title("New Directory"); 479 directory.mutable_file_info()->set_is_directory(true); 480 directory.set_deleted(true); 481 change_lists[0]->mutable_entries()->push_back(directory); 482 change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); 483 484 change_lists[0]->set_largest_changestamp(16730); 485 486 // Apply the changelist and check the effect. 487 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 488 FileChange changed_files; 489 EXPECT_EQ(FILE_ERROR_OK, 490 ApplyChangeList(change_lists.Pass(), &changed_files)); 491 492 int64 changestamp = 0; 493 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); 494 EXPECT_EQ(16730, changestamp); 495 EXPECT_FALSE(GetResourceEntry("drive/root/New Directory/new_pdf_file.pdf")); 496 497 EXPECT_TRUE(changed_files.empty()); 498} 499 500TEST_F(ChangeListProcessorTest, RefreshDirectory) { 501 // Prepare metadata. 502 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 503 504 // Create change list. 505 scoped_ptr<ChangeList> change_list(new ChangeList); 506 507 // Add a new file to the change list. 508 ResourceEntry new_file; 509 new_file.set_title("new_file"); 510 new_file.set_resource_id("new_file_id"); 511 change_list->mutable_entries()->push_back(new_file); 512 change_list->mutable_parent_resource_ids()->push_back(kRootId); 513 514 // Add "Directory 1" to the map with a new name. 515 ResourceEntry dir1; 516 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( 517 util::GetDriveMyDriveRootPath().AppendASCII("Directory 1"), &dir1)); 518 dir1.set_title(dir1.title() + " (renamed)"); 519 change_list->mutable_entries()->push_back(dir1); 520 change_list->mutable_parent_resource_ids()->push_back(kRootId); 521 522 // Update the directory with the map. 523 ResourceEntry root; 524 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( 525 util::GetDriveMyDriveRootPath(), &root)); 526 const int64 kNewChangestamp = 12345; 527 ResourceEntryVector refreshed_entries; 528 EXPECT_EQ(FILE_ERROR_OK, ChangeListProcessor::RefreshDirectory( 529 metadata_.get(), 530 DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp), 531 change_list.Pass(), 532 &refreshed_entries)); 533 534 // "new_file" should be added. 535 ResourceEntry entry; 536 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( 537 util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry)); 538 539 // "Directory 1" should be renamed. 540 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( 541 util::GetDriveMyDriveRootPath().AppendASCII(dir1.title()), &entry)); 542} 543 544TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) { 545 // Prepare metadata. 546 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 547 548 // Create change list and add a new file to it. 549 scoped_ptr<ChangeList> change_list(new ChangeList); 550 ResourceEntry new_file; 551 new_file.set_title("new_file"); 552 new_file.set_resource_id("new_file_id"); 553 // This entry should not be added because the parent ID does not match. 554 change_list->mutable_parent_resource_ids()->push_back( 555 "some-random-resource-id"); 556 change_list->mutable_entries()->push_back(new_file); 557 558 559 // Update the directory. 560 ResourceEntry root; 561 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( 562 util::GetDriveMyDriveRootPath(), &root)); 563 const int64 kNewChangestamp = 12345; 564 ResourceEntryVector refreshed_entries; 565 EXPECT_EQ(FILE_ERROR_OK, ChangeListProcessor::RefreshDirectory( 566 metadata_.get(), 567 DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp), 568 change_list.Pass(), 569 &refreshed_entries)); 570 571 // "new_file" should not be added. 572 ResourceEntry entry; 573 EXPECT_EQ(FILE_ERROR_NOT_FOUND, metadata_->GetResourceEntryByPath( 574 util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry)); 575} 576 577TEST_F(ChangeListProcessorTest, SharedFilesWithNoParentInFeed) { 578 // Prepare metadata. 579 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 580 581 // Create change lists. 582 ScopedVector<ChangeList> change_lists; 583 change_lists.push_back(new ChangeList); 584 585 // Add a new file with non-existing parent resource id to the change lists. 586 ResourceEntry new_file; 587 new_file.set_title("new_file"); 588 new_file.set_resource_id("new_file_id"); 589 change_lists[0]->mutable_entries()->push_back(new_file); 590 change_lists[0]->mutable_parent_resource_ids()->push_back("nonexisting"); 591 change_lists[0]->set_largest_changestamp(kBaseResourceListChangestamp + 1); 592 593 FileChange changed_files; 594 EXPECT_EQ(FILE_ERROR_OK, 595 ApplyChangeList(change_lists.Pass(), &changed_files)); 596 597 // "new_file" should be added under drive/other. 598 ResourceEntry entry; 599 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( 600 util::GetDriveGrandRootPath().AppendASCII("other/new_file"), &entry)); 601} 602 603TEST_F(ChangeListProcessorTest, ModificationDate) { 604 // Prepare metadata. 605 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); 606 607 // Create change lists with a new file. 608 ScopedVector<ChangeList> change_lists; 609 change_lists.push_back(new ChangeList); 610 611 const base::Time now = base::Time::Now(); 612 ResourceEntry new_file_remote; 613 new_file_remote.set_title("new_file_remote"); 614 new_file_remote.set_resource_id("new_file_id"); 615 new_file_remote.set_modification_date(now.ToInternalValue()); 616 617 change_lists[0]->mutable_entries()->push_back(new_file_remote); 618 change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId); 619 change_lists[0]->set_largest_changestamp(kBaseResourceListChangestamp + 1); 620 621 // Add the same file locally, but with a different name, a dirty metadata 622 // state, and a newer modification date. 623 ResourceEntry root; 624 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( 625 util::GetDriveMyDriveRootPath(), &root)); 626 627 ResourceEntry new_file_local; 628 new_file_local.set_resource_id(new_file_remote.resource_id()); 629 new_file_local.set_parent_local_id(root.local_id()); 630 new_file_local.set_title("new_file_local"); 631 new_file_local.set_metadata_edit_state(ResourceEntry::DIRTY); 632 new_file_local.set_modification_date( 633 (now + base::TimeDelta::FromSeconds(1)).ToInternalValue()); 634 std::string local_id; 635 EXPECT_EQ(FILE_ERROR_OK, metadata_->AddEntry(new_file_local, &local_id)); 636 637 // Apply the change. 638 FileChange changed_files; 639 EXPECT_EQ(FILE_ERROR_OK, 640 ApplyChangeList(change_lists.Pass(), &changed_files)); 641 642 // The change is rejected due to the old modification date. 643 ResourceEntry entry; 644 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryById(local_id, &entry)); 645 EXPECT_EQ(new_file_local.title(), entry.title()); 646} 647 648} // namespace internal 649} // namespace drive 650