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.
5 #include "chrome/browser/chromeos/drive/change_list_processor.h"
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"
27 const int64 kBaseResourceListChangestamp = 123;
28 const char kRootId[] = "fake_root";
30 enum FileOrDirectory {
35 struct EntryExpectation {
38 std::string parent_id;
42 // Returns a basic change list which contains some files and directories.
43 ScopedVector<ChangeList> CreateBaseChangeList() {
44 ScopedVector<ChangeList> change_lists;
45 change_lists.push_back(new ChangeList);
47 // Add directories to the change list.
48 ResourceEntry directory;
49 directory.mutable_file_info()->set_is_directory(true);
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);
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");
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");
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);
73 // Add files to the change list.
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);
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");
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("");
92 change_lists[0]->set_largest_changestamp(kBaseResourceListChangestamp);
93 return change_lists.Pass();
96 class ChangeListProcessorTest : public testing::Test {
98 virtual void SetUp() OVERRIDE {
99 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
101 metadata_storage_.reset(new ResourceMetadataStorage(
102 temp_dir_.path(), base::MessageLoopProxy::current().get()));
103 ASSERT_TRUE(metadata_storage_->Initialize());
105 fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
106 cache_.reset(new FileCache(metadata_storage_.get(),
108 base::MessageLoopProxy::current().get(),
109 fake_free_disk_space_getter_.get()));
110 ASSERT_TRUE(cache_->Initialize());
112 metadata_.reset(new internal::ResourceMetadata(
113 metadata_storage_.get(), cache_.get(),
114 base::MessageLoopProxy::current()));
115 ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
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);
126 ChangeListProcessor processor(metadata_.get());
127 return processor.Apply(about_resource.Pass(),
129 false /* is_delta_update */);
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);
141 ChangeListProcessor processor(metadata_.get());
142 FileError error = processor.Apply(about_resource.Pass(),
144 true /* is_delta_update */);
145 *changed_files = processor.changed_files();
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)
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_;
171 TEST_F(ChangeListProcessorTest, ApplyFullResourceList) {
172 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
174 const EntryExpectation kExpected[] = {
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},
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},
194 {"drive/other/Orphan File 1.txt", "1_orphanfile_resource_id",
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());
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);
211 int64 changestamp = 0;
212 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp));
213 EXPECT_EQ(kBaseResourceListChangestamp, changestamp);
216 TEST_F(ChangeListProcessorTest, DeltaFileAddedInNewDirectory) {
217 ScopedVector<ChangeList> change_lists;
218 change_lists.push_back(new ChangeList);
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);
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());
234 change_lists[0]->set_largest_changestamp(16730);
236 // Apply the changelist and check the effect.
237 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
239 FileChange changed_files;
240 EXPECT_EQ(FILE_ERROR_OK,
241 ApplyChangeList(change_lists.Pass(), &changed_files));
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"));
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")));
257 TEST_F(ChangeListProcessorTest, DeltaDirMovedFromRootToDirectory) {
258 ScopedVector<ChangeList> change_lists;
259 change_lists.push_back(new ChangeList);
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");
269 change_lists[0]->set_largest_changestamp(16809);
271 // Apply the changelist and check the effect.
272 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
274 FileChange changed_files;
275 EXPECT_EQ(FILE_ERROR_OK,
276 ApplyChangeList(change_lists.Pass(), &changed_files));
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"));
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")));
296 TEST_F(ChangeListProcessorTest, DeltaFileMovedFromDirectoryToRoot) {
297 ScopedVector<ChangeList> change_lists;
298 change_lists.push_back(new ChangeList);
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);
306 change_lists[0]->set_largest_changestamp(16815);
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));
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"));
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")));
328 TEST_F(ChangeListProcessorTest, DeltaFileRenamedInDirectory) {
329 ScopedVector<ChangeList> change_lists;
330 change_lists.push_back(new ChangeList);
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");
339 change_lists[0]->set_largest_changestamp(16767);
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));
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"));
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")));
362 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileInRoot) {
363 // Create ChangeList to add a file.
364 ScopedVector<ChangeList> change_lists;
365 change_lists.push_back(new ChangeList);
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);
373 change_lists[0]->set_largest_changestamp(16683);
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));
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")));
389 // Create ChangeList to delete the file.
390 change_lists.push_back(new ChangeList);
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);
396 change_lists[0]->set_largest_changestamp(16687);
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")));
410 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileFromExistingDirectory) {
411 // Create ChangeList to add a file.
412 ScopedVector<ChangeList> change_lists;
413 change_lists.push_back(new ChangeList);
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");
422 change_lists[0]->set_largest_changestamp(16730);
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"));
434 EXPECT_EQ(1U, changed_files.size());
435 EXPECT_TRUE(changed_files.count(
436 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt")));
438 // Create ChangeList to delete the file.
439 change_lists.push_back(new ChangeList);
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");
446 change_lists[0]->set_largest_changestamp(16770);
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"));
455 EXPECT_EQ(1U, changed_files.size());
456 EXPECT_TRUE(changed_files.count(
457 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt")));
460 TEST_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);
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");
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);
484 change_lists[0]->set_largest_changestamp(16730);
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));
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"));
497 EXPECT_TRUE(changed_files.empty());
500 TEST_F(ChangeListProcessorTest, RefreshDirectory) {
502 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
504 // Create change list.
505 scoped_ptr<ChangeList> change_list(new ChangeList);
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);
514 // Add "Directory 1" to the map with a new name.
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);
522 // Update the directory with the map.
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(
530 DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
532 &refreshed_entries));
534 // "new_file" should be added.
536 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
537 util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
539 // "Directory 1" should be renamed.
540 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
541 util::GetDriveMyDriveRootPath().AppendASCII(dir1.title()), &entry));
544 TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) {
546 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
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);
559 // Update the directory.
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(
567 DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
569 &refreshed_entries));
571 // "new_file" should not be added.
573 EXPECT_EQ(FILE_ERROR_NOT_FOUND, metadata_->GetResourceEntryByPath(
574 util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
577 TEST_F(ChangeListProcessorTest, SharedFilesWithNoParentInFeed) {
579 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
581 // Create change lists.
582 ScopedVector<ChangeList> change_lists;
583 change_lists.push_back(new ChangeList);
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);
593 FileChange changed_files;
594 EXPECT_EQ(FILE_ERROR_OK,
595 ApplyChangeList(change_lists.Pass(), &changed_files));
597 // "new_file" should be added under drive/other.
599 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
600 util::GetDriveGrandRootPath().AppendASCII("other/new_file"), &entry));
603 TEST_F(ChangeListProcessorTest, ModificationDate) {
605 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
607 // Create change lists with a new file.
608 ScopedVector<ChangeList> change_lists;
609 change_lists.push_back(new ChangeList);
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());
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);
621 // Add the same file locally, but with a different name, a dirty metadata
622 // state, and a newer modification date.
624 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
625 util::GetDriveMyDriveRootPath(), &root));
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));
638 FileChange changed_files;
639 EXPECT_EQ(FILE_ERROR_OK,
640 ApplyChangeList(change_lists.Pass(), &changed_files));
642 // The change is rejected due to the old modification date.
644 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryById(local_id, &entry));
645 EXPECT_EQ(new_file_local.title(), entry.title());
648 } // namespace internal