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