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.
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/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"
25 const int64 kBaseResourceListChangestamp = 123;
26 const char kRootId[] = "fake_root";
28 enum FileOrDirectory {
33 struct EntryExpectation {
36 std::string parent_id;
40 // Returns a basic change list which contains some files and directories.
41 ScopedVector<ChangeList> CreateBaseChangeList() {
42 ScopedVector<ChangeList> change_lists;
43 change_lists.push_back(new ChangeList);
45 // Add directories to the change list.
46 ResourceEntry directory;
47 directory.mutable_file_info()->set_is_directory(true);
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);
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");
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");
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);
71 // Add files to the change list.
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);
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");
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("");
90 change_lists[0]->set_largest_changestamp(kBaseResourceListChangestamp);
91 return change_lists.Pass();
94 class ChangeListProcessorTest : public testing::Test {
96 virtual void SetUp() OVERRIDE {
97 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
99 metadata_storage_.reset(new ResourceMetadataStorage(
100 temp_dir_.path(), base::MessageLoopProxy::current().get()));
101 ASSERT_TRUE(metadata_storage_->Initialize());
103 metadata_.reset(new internal::ResourceMetadata(
104 metadata_storage_.get(), base::MessageLoopProxy::current()));
105 ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
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);
116 ChangeListProcessor processor(metadata_.get());
117 return processor.Apply(about_resource.Pass(),
119 false /* is_delta_update */);
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);
131 ChangeListProcessor processor(metadata_.get());
132 FileError error = processor.Apply(about_resource.Pass(),
134 true /* is_delta_update */);
135 *changed_dirs = processor.changed_dirs();
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)
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_;
159 TEST_F(ChangeListProcessorTest, ApplyFullResourceList) {
160 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
162 const EntryExpectation kExpected[] = {
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},
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},
182 {"drive/other/Orphan File 1.txt", "file:1_orphanfile_resource_id",
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());
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);
199 EXPECT_EQ(kBaseResourceListChangestamp, metadata_->GetLargestChangestamp());
202 TEST_F(ChangeListProcessorTest, DeltaFileAddedInNewDirectory) {
203 ScopedVector<ChangeList> change_lists;
204 change_lists.push_back(new ChangeList);
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);
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());
220 change_lists[0]->set_largest_changestamp(16730);
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));
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"));
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")));
239 TEST_F(ChangeListProcessorTest, DeltaDirMovedFromRootToDirectory) {
240 ScopedVector<ChangeList> change_lists;
241 change_lists.push_back(new ChangeList);
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");
251 change_lists[0]->set_largest_changestamp(16809);
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));
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"));
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")));
276 TEST_F(ChangeListProcessorTest, DeltaFileMovedFromDirectoryToRoot) {
277 ScopedVector<ChangeList> change_lists;
278 change_lists.push_back(new ChangeList);
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);
286 change_lists[0]->set_largest_changestamp(16815);
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));
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"));
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")));
305 TEST_F(ChangeListProcessorTest, DeltaFileRenamedInDirectory) {
306 ScopedVector<ChangeList> change_lists;
307 change_lists.push_back(new ChangeList);
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");
316 change_lists[0]->set_largest_changestamp(16767);
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));
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"));
329 EXPECT_EQ(1U, changed_dirs.size());
330 EXPECT_TRUE(changed_dirs.count(
331 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
334 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileInRoot) {
335 // Create ChangeList to add a file.
336 ScopedVector<ChangeList> change_lists;
337 change_lists.push_back(new ChangeList);
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);
345 change_lists[0]->set_largest_changestamp(16683);
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")));
357 // Create ChangeList to delete the file.
358 change_lists.push_back(new ChangeList);
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);
364 change_lists[0]->set_largest_changestamp(16687);
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")));
376 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileFromExistingDirectory) {
377 // Create ChangeList to add a file.
378 ScopedVector<ChangeList> change_lists;
379 change_lists.push_back(new ChangeList);
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");
388 change_lists[0]->set_largest_changestamp(16730);
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"));
397 EXPECT_EQ(1U, changed_dirs.size());
398 EXPECT_TRUE(changed_dirs.count(
399 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
401 // Create ChangeList to delete the file.
402 change_lists.push_back(new ChangeList);
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");
409 change_lists[0]->set_largest_changestamp(16770);
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"));
416 EXPECT_EQ(1U, changed_dirs.size());
417 EXPECT_TRUE(changed_dirs.count(
418 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
421 TEST_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);
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");
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);
445 change_lists[0]->set_largest_changestamp(16730);
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));
452 EXPECT_EQ(16730, metadata_->GetLargestChangestamp());
453 EXPECT_FALSE(GetResourceEntry("drive/root/New Directory/new_pdf_file.pdf"));
455 EXPECT_TRUE(changed_dirs.empty());
458 TEST_F(ChangeListProcessorTest, RefreshDirectory) {
460 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
462 // Create change list.
463 scoped_ptr<ChangeList> change_list(new ChangeList);
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);
472 // Add "Directory 1" to the map with a new name.
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);
480 // Update the directory with the map.
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(
488 DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
490 &refreshed_entries));
492 // "new_file" should be added.
494 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
495 util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
497 // "Directory 1" should be renamed.
498 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
499 util::GetDriveMyDriveRootPath().AppendASCII(dir1.title()), &entry));
502 TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) {
504 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
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);
517 // Update the directory.
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(
525 DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
527 &refreshed_entries));
529 // "new_file" should not be added.
531 EXPECT_EQ(FILE_ERROR_NOT_FOUND, metadata_->GetResourceEntryByPath(
532 util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
535 TEST_F(ChangeListProcessorTest, SharedFilesWithNoParentInFeed) {
537 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
539 // Create change lists.
540 ScopedVector<ChangeList> change_lists;
541 change_lists.push_back(new ChangeList);
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);
551 std::set<base::FilePath> changed_dirs;
552 EXPECT_EQ(FILE_ERROR_OK, ApplyChangeList(change_lists.Pass(), &changed_dirs));
554 // "new_file" should be added under drive/other.
556 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
557 util::GetDriveGrandRootPath().AppendASCII("other/new_file"), &entry));
560 TEST_F(ChangeListProcessorTest, ModificationDate) {
562 EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
564 // Create change lists with a new file.
565 ScopedVector<ChangeList> change_lists;
566 change_lists.push_back(new ChangeList);
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());
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);
578 // Add the same file locally, but with a different name, a dirty metadata
579 // state, and a newer modification date.
581 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
582 util::GetDriveMyDriveRootPath(), &root));
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));
595 std::set<base::FilePath> changed_dirs;
596 EXPECT_EQ(FILE_ERROR_OK, ApplyChangeList(change_lists.Pass(), &changed_dirs));
598 // The change is rejected due to the old modification date.
600 EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryById(local_id, &entry));
601 EXPECT_EQ(new_file_local.title(), entry.title());
604 } // namespace internal