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/single_thread_task_runner.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "base/values.h"
11 #include "components/drive/drive.pb.h"
12 #include "components/drive/drive_test_util.h"
13 #include "components/drive/fake_free_disk_space_getter.h"
14 #include "components/drive/file_cache.h"
15 #include "components/drive/file_change.h"
16 #include "components/drive/file_system_core_util.h"
17 #include "components/drive/resource_metadata.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "google_apis/drive/drive_api_parser.h"
20 #include "google_apis/drive/test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
28 const int64 kBaseResourceListChangestamp
= 123;
29 const char kRootId
[] = "fake_root";
31 enum FileOrDirectory
{
36 struct EntryExpectation
{
39 std::string parent_id
;
43 // Returns a basic change list which contains some files and directories.
44 ScopedVector
<ChangeList
> CreateBaseChangeList() {
45 ScopedVector
<ChangeList
> change_lists
;
46 change_lists
.push_back(new ChangeList
);
48 // Add directories to the change list.
49 ResourceEntry directory
;
50 directory
.mutable_file_info()->set_is_directory(true);
52 directory
.set_title("Directory 1");
53 directory
.set_resource_id("1_folder_resource_id");
54 change_lists
[0]->mutable_entries()->push_back(directory
);
55 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
57 directory
.set_title("Sub Directory Folder");
58 directory
.set_resource_id("sub_dir_folder_resource_id");
59 change_lists
[0]->mutable_entries()->push_back(directory
);
60 change_lists
[0]->mutable_parent_resource_ids()->push_back(
61 "1_folder_resource_id");
63 directory
.set_title("Sub Sub Directory Folder");
64 directory
.set_resource_id("sub_sub_directory_folder_id");
65 change_lists
[0]->mutable_entries()->push_back(directory
);
66 change_lists
[0]->mutable_parent_resource_ids()->push_back(
67 "sub_dir_folder_resource_id");
69 directory
.set_title("Directory 2 excludeDir-test");
70 directory
.set_resource_id("sub_dir_folder_2_self_link");
71 change_lists
[0]->mutable_entries()->push_back(directory
);
72 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
74 // Add files to the change list.
77 file
.set_title("File 1.txt");
78 file
.set_resource_id("2_file_resource_id");
79 change_lists
[0]->mutable_entries()->push_back(file
);
80 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
82 file
.set_title("SubDirectory File 1.txt");
83 file
.set_resource_id("subdirectory_file_1_id");
84 Property
* const property
= file
.mutable_new_properties()->Add();
85 property
->set_key("hello");
86 property
->set_value("world");
87 change_lists
[0]->mutable_entries()->push_back(file
);
88 change_lists
[0]->mutable_parent_resource_ids()->push_back(
89 "1_folder_resource_id");
91 file
.set_title("Orphan File 1.txt");
92 file
.set_resource_id("1_orphanfile_resource_id");
93 change_lists
[0]->mutable_entries()->push_back(file
);
94 change_lists
[0]->mutable_parent_resource_ids()->push_back("");
96 change_lists
[0]->set_largest_changestamp(kBaseResourceListChangestamp
);
97 return change_lists
.Pass();
100 class ChangeListProcessorTest
: public testing::Test
{
102 void SetUp() override
{
103 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
105 metadata_storage_
.reset(new ResourceMetadataStorage(
106 temp_dir_
.path(), base::ThreadTaskRunnerHandle::Get().get()));
107 ASSERT_TRUE(metadata_storage_
->Initialize());
109 fake_free_disk_space_getter_
.reset(new FakeFreeDiskSpaceGetter
);
110 cache_
.reset(new FileCache(metadata_storage_
.get(),
112 base::ThreadTaskRunnerHandle::Get().get(),
113 fake_free_disk_space_getter_
.get()));
114 ASSERT_TRUE(cache_
->Initialize());
116 metadata_
.reset(new internal::ResourceMetadata(
117 metadata_storage_
.get(), cache_
.get(),
118 base::ThreadTaskRunnerHandle::Get()));
119 ASSERT_EQ(FILE_ERROR_OK
, metadata_
->Initialize());
122 // Applies the |changes| to |metadata_| as a full resource list of changestamp
123 // |kBaseResourceListChangestamp|.
124 FileError
ApplyFullResourceList(ScopedVector
<ChangeList
> changes
) {
125 scoped_ptr
<google_apis::AboutResource
> about_resource(
126 new google_apis::AboutResource
);
127 about_resource
->set_largest_change_id(kBaseResourceListChangestamp
);
128 about_resource
->set_root_folder_id(kRootId
);
130 ChangeListProcessor
processor(metadata_
.get(), nullptr);
131 return processor
.Apply(about_resource
.Pass(),
133 false /* is_delta_update */);
136 // Applies the |changes| to |metadata_| as a delta update. Delta changelists
137 // should contain their changestamp in themselves.
138 FileError
ApplyChangeList(ScopedVector
<ChangeList
> changes
,
139 FileChange
* changed_files
) {
140 scoped_ptr
<google_apis::AboutResource
> about_resource(
141 new google_apis::AboutResource
);
142 about_resource
->set_largest_change_id(kBaseResourceListChangestamp
);
143 about_resource
->set_root_folder_id(kRootId
);
145 ChangeListProcessor
processor(metadata_
.get(), nullptr);
146 FileError error
= processor
.Apply(about_resource
.Pass(),
148 true /* is_delta_update */);
149 *changed_files
= processor
.changed_files();
153 // Gets the resource entry for the path from |metadata_| synchronously.
154 // Returns null if the entry does not exist.
155 scoped_ptr
<ResourceEntry
> GetResourceEntry(const std::string
& path
) {
156 scoped_ptr
<ResourceEntry
> entry(new ResourceEntry
);
157 FileError error
= metadata_
->GetResourceEntryByPath(
158 base::FilePath::FromUTF8Unsafe(path
), entry
.get());
159 if (error
!= FILE_ERROR_OK
)
164 content::TestBrowserThreadBundle thread_bundle_
;
165 base::ScopedTempDir temp_dir_
;
166 scoped_ptr
<ResourceMetadataStorage
,
167 test_util::DestroyHelperForTests
> metadata_storage_
;
168 scoped_ptr
<FakeFreeDiskSpaceGetter
> fake_free_disk_space_getter_
;
169 scoped_ptr
<FileCache
, test_util::DestroyHelperForTests
> cache_
;
170 scoped_ptr
<ResourceMetadata
, test_util::DestroyHelperForTests
> metadata_
;
175 TEST_F(ChangeListProcessorTest
, ApplyFullResourceList
) {
176 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
178 const EntryExpectation kExpected
[] = {
180 {"drive/root", kRootId
, "", DIRECTORY
},
181 {"drive/root/File 1.txt",
182 "2_file_resource_id", kRootId
, FILE},
183 // Subdirectory files
184 {"drive/root/Directory 1",
185 "1_folder_resource_id", kRootId
, DIRECTORY
},
186 {"drive/root/Directory 1/SubDirectory File 1.txt",
187 "subdirectory_file_1_id", "1_folder_resource_id", FILE},
188 {"drive/root/Directory 2 excludeDir-test",
189 "sub_dir_folder_2_self_link", kRootId
, DIRECTORY
},
191 {"drive/root/Directory 1/Sub Directory Folder",
192 "sub_dir_folder_resource_id",
193 "1_folder_resource_id", DIRECTORY
},
194 {"drive/root/Directory 1/Sub Directory Folder/Sub Sub Directory Folder",
195 "sub_sub_directory_folder_id",
196 "sub_dir_folder_resource_id", DIRECTORY
},
198 {"drive/other/Orphan File 1.txt", "1_orphanfile_resource_id",
202 for (size_t i
= 0; i
< arraysize(kExpected
); ++i
) {
203 scoped_ptr
<ResourceEntry
> entry
= GetResourceEntry(kExpected
[i
].path
);
204 ASSERT_TRUE(entry
) << "for path: " << kExpected
[i
].path
;
205 EXPECT_EQ(kExpected
[i
].id
, entry
->resource_id());
207 ResourceEntry parent_entry
;
208 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryById(
209 entry
->parent_local_id(), &parent_entry
));
210 EXPECT_EQ(kExpected
[i
].parent_id
, parent_entry
.resource_id());
211 EXPECT_EQ(kExpected
[i
].type
,
212 entry
->file_info().is_directory() ? DIRECTORY
: FILE);
215 int64 changestamp
= 0;
216 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
217 EXPECT_EQ(kBaseResourceListChangestamp
, changestamp
);
220 TEST_F(ChangeListProcessorTest
, DeltaFileAddedInNewDirectory
) {
221 ScopedVector
<ChangeList
> change_lists
;
222 change_lists
.push_back(new ChangeList
);
224 ResourceEntry new_folder
;
225 new_folder
.set_resource_id("new_folder_resource_id");
226 new_folder
.set_title("New Directory");
227 new_folder
.mutable_file_info()->set_is_directory(true);
228 change_lists
[0]->mutable_entries()->push_back(new_folder
);
229 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
231 ResourceEntry new_file
;
232 new_file
.set_resource_id("file_added_in_new_dir_id");
233 new_file
.set_title("File in new dir.txt");
234 change_lists
[0]->mutable_entries()->push_back(new_file
);
235 change_lists
[0]->mutable_parent_resource_ids()->push_back(
236 new_folder
.resource_id());
238 change_lists
[0]->set_largest_changestamp(16730);
240 // Apply the changelist and check the effect.
241 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
243 FileChange changed_files
;
244 EXPECT_EQ(FILE_ERROR_OK
,
245 ApplyChangeList(change_lists
.Pass(), &changed_files
));
247 int64 changestamp
= 0;
248 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
249 EXPECT_EQ(16730, changestamp
);
250 EXPECT_TRUE(GetResourceEntry("drive/root/New Directory"));
251 EXPECT_TRUE(GetResourceEntry(
252 "drive/root/New Directory/File in new dir.txt"));
254 EXPECT_EQ(2U, changed_files
.size());
255 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
256 "drive/root/New Directory/File in new dir.txt")));
257 EXPECT_TRUE(changed_files
.count(
258 base::FilePath::FromUTF8Unsafe("drive/root/New Directory")));
261 TEST_F(ChangeListProcessorTest
, DeltaDirMovedFromRootToDirectory
) {
262 ScopedVector
<ChangeList
> change_lists
;
263 change_lists
.push_back(new ChangeList
);
266 entry
.set_resource_id("1_folder_resource_id");
267 entry
.set_title("Directory 1");
268 entry
.mutable_file_info()->set_is_directory(true);
269 change_lists
[0]->mutable_entries()->push_back(entry
);
270 change_lists
[0]->mutable_parent_resource_ids()->push_back(
271 "sub_dir_folder_2_self_link");
273 change_lists
[0]->set_largest_changestamp(16809);
275 // Apply the changelist and check the effect.
276 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
278 FileChange changed_files
;
279 EXPECT_EQ(FILE_ERROR_OK
,
280 ApplyChangeList(change_lists
.Pass(), &changed_files
));
282 int64 changestamp
= 0;
283 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
284 EXPECT_EQ(16809, changestamp
);
285 EXPECT_FALSE(GetResourceEntry("drive/root/Directory 1"));
286 EXPECT_TRUE(GetResourceEntry(
287 "drive/root/Directory 2 excludeDir-test/Directory 1"));
289 EXPECT_EQ(2U, changed_files
.size());
290 EXPECT_TRUE(changed_files
.CountDirectory(
291 base::FilePath::FromUTF8Unsafe("drive/root")));
292 EXPECT_TRUE(changed_files
.count(
293 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
294 EXPECT_TRUE(changed_files
.CountDirectory(base::FilePath::FromUTF8Unsafe(
295 "drive/root/Directory 2 excludeDir-test")));
296 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
297 "drive/root/Directory 2 excludeDir-test/Directory 1")));
300 TEST_F(ChangeListProcessorTest
, DeltaFileMovedFromDirectoryToRoot
) {
301 ScopedVector
<ChangeList
> change_lists
;
302 change_lists
.push_back(new ChangeList
);
305 entry
.set_resource_id("subdirectory_file_1_id");
306 entry
.set_title("SubDirectory File 1.txt");
307 change_lists
[0]->mutable_entries()->push_back(entry
);
308 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
310 change_lists
[0]->set_largest_changestamp(16815);
312 // Apply the changelist and check the effect.
313 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
314 FileChange changed_files
;
315 EXPECT_EQ(FILE_ERROR_OK
,
316 ApplyChangeList(change_lists
.Pass(), &changed_files
));
318 int64 changestamp
= 0;
319 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
320 EXPECT_EQ(16815, changestamp
);
321 EXPECT_FALSE(GetResourceEntry(
322 "drive/root/Directory 1/SubDirectory File 1.txt"));
323 EXPECT_TRUE(GetResourceEntry("drive/root/SubDirectory File 1.txt"));
325 EXPECT_EQ(2U, changed_files
.size());
326 EXPECT_TRUE(changed_files
.count(
327 base::FilePath::FromUTF8Unsafe("drive/root/SubDirectory File 1.txt")));
328 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
329 "drive/root/Directory 1/SubDirectory File 1.txt")));
332 TEST_F(ChangeListProcessorTest
, DeltaFileRenamedInDirectory
) {
333 ScopedVector
<ChangeList
> change_lists
;
334 change_lists
.push_back(new ChangeList
);
337 entry
.set_resource_id("subdirectory_file_1_id");
338 entry
.set_title("New SubDirectory File 1.txt");
339 change_lists
[0]->mutable_entries()->push_back(entry
);
340 change_lists
[0]->mutable_parent_resource_ids()->push_back(
341 "1_folder_resource_id");
343 change_lists
[0]->set_largest_changestamp(16767);
345 // Apply the changelist and check the effect.
346 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
347 FileChange changed_files
;
348 EXPECT_EQ(FILE_ERROR_OK
,
349 ApplyChangeList(change_lists
.Pass(), &changed_files
));
350 EXPECT_EQ(2U, changed_files
.size());
351 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
352 "drive/root/Directory 1/SubDirectory File 1.txt")));
353 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
354 "drive/root/Directory 1/New SubDirectory File 1.txt")));
356 int64 changestamp
= 0;
357 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
358 EXPECT_EQ(16767, changestamp
);
359 EXPECT_FALSE(GetResourceEntry(
360 "drive/root/Directory 1/SubDirectory File 1.txt"));
361 scoped_ptr
<ResourceEntry
> new_entry(
362 GetResourceEntry("drive/root/Directory 1/New SubDirectory File 1.txt"));
363 ASSERT_TRUE(new_entry
);
365 // Keep the to-be-synced properties.
366 ASSERT_EQ(1, new_entry
->mutable_new_properties()->size());
367 const Property
& new_property
= new_entry
->new_properties().Get(0);
368 EXPECT_EQ("hello", new_property
.key());
371 TEST_F(ChangeListProcessorTest
, DeltaAddAndDeleteFileInRoot
) {
372 // Create ChangeList to add a file.
373 ScopedVector
<ChangeList
> change_lists
;
374 change_lists
.push_back(new ChangeList
);
377 entry
.set_resource_id("added_in_root_id");
378 entry
.set_title("Added file.txt");
379 change_lists
[0]->mutable_entries()->push_back(entry
);
380 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
382 change_lists
[0]->set_largest_changestamp(16683);
385 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
386 FileChange changed_files
;
387 EXPECT_EQ(FILE_ERROR_OK
,
388 ApplyChangeList(change_lists
.Pass(), &changed_files
));
390 int64 changestamp
= 0;
391 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
392 EXPECT_EQ(16683, changestamp
);
393 EXPECT_TRUE(GetResourceEntry("drive/root/Added file.txt"));
394 EXPECT_EQ(1U, changed_files
.size());
395 EXPECT_TRUE(changed_files
.count(
396 base::FilePath::FromUTF8Unsafe("drive/root/Added file.txt")));
398 // Create ChangeList to delete the file.
399 change_lists
.push_back(new ChangeList
);
401 entry
.set_deleted(true);
402 change_lists
[0]->mutable_entries()->push_back(entry
);
403 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
405 change_lists
[0]->set_largest_changestamp(16687);
408 EXPECT_EQ(FILE_ERROR_OK
,
409 ApplyChangeList(change_lists
.Pass(), &changed_files
));
410 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
411 EXPECT_EQ(16687, changestamp
);
412 EXPECT_FALSE(GetResourceEntry("drive/root/Added file.txt"));
413 EXPECT_EQ(1U, changed_files
.size());
414 EXPECT_TRUE(changed_files
.count(
415 base::FilePath::FromUTF8Unsafe("drive/root/Added file.txt")));
419 TEST_F(ChangeListProcessorTest
, DeltaAddAndDeleteFileFromExistingDirectory
) {
420 // Create ChangeList to add a file.
421 ScopedVector
<ChangeList
> change_lists
;
422 change_lists
.push_back(new ChangeList
);
425 entry
.set_resource_id("added_in_root_id");
426 entry
.set_title("Added file.txt");
427 change_lists
[0]->mutable_entries()->push_back(entry
);
428 change_lists
[0]->mutable_parent_resource_ids()->push_back(
429 "1_folder_resource_id");
431 change_lists
[0]->set_largest_changestamp(16730);
434 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
435 FileChange changed_files
;
436 EXPECT_EQ(FILE_ERROR_OK
,
437 ApplyChangeList(change_lists
.Pass(), &changed_files
));
438 int64 changestamp
= 0;
439 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
440 EXPECT_EQ(16730, changestamp
);
441 EXPECT_TRUE(GetResourceEntry("drive/root/Directory 1/Added file.txt"));
443 EXPECT_EQ(1U, changed_files
.size());
444 EXPECT_TRUE(changed_files
.count(
445 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt")));
447 // Create ChangeList to delete the file.
448 change_lists
.push_back(new ChangeList
);
450 entry
.set_deleted(true);
451 change_lists
[0]->mutable_entries()->push_back(entry
);
452 change_lists
[0]->mutable_parent_resource_ids()->push_back(
453 "1_folder_resource_id");
455 change_lists
[0]->set_largest_changestamp(16770);
458 EXPECT_EQ(FILE_ERROR_OK
,
459 ApplyChangeList(change_lists
.Pass(), &changed_files
));
460 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
461 EXPECT_EQ(16770, changestamp
);
462 EXPECT_FALSE(GetResourceEntry("drive/root/Directory 1/Added file.txt"));
464 EXPECT_EQ(1U, changed_files
.size());
465 EXPECT_TRUE(changed_files
.count(
466 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt")));
469 TEST_F(ChangeListProcessorTest
, DeltaAddFileToNewButDeletedDirectory
) {
470 // Create a change which contains the following updates:
471 // 1) A new PDF file is added to a new directory
472 // 2) but the new directory is marked "deleted" (i.e. moved to Trash)
473 // Hence, the PDF file should be just ignored.
474 ScopedVector
<ChangeList
> change_lists
;
475 change_lists
.push_back(new ChangeList
);
478 file
.set_resource_id("file_added_in_deleted_id");
479 file
.set_title("new_pdf_file.pdf");
480 file
.set_deleted(true);
481 change_lists
[0]->mutable_entries()->push_back(file
);
482 change_lists
[0]->mutable_parent_resource_ids()->push_back(
483 "new_folder_resource_id");
485 ResourceEntry directory
;
486 directory
.set_resource_id("new_folder_resource_id");
487 directory
.set_title("New Directory");
488 directory
.mutable_file_info()->set_is_directory(true);
489 directory
.set_deleted(true);
490 change_lists
[0]->mutable_entries()->push_back(directory
);
491 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
493 change_lists
[0]->set_largest_changestamp(16730);
495 // Apply the changelist and check the effect.
496 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
497 FileChange changed_files
;
498 EXPECT_EQ(FILE_ERROR_OK
,
499 ApplyChangeList(change_lists
.Pass(), &changed_files
));
501 int64 changestamp
= 0;
502 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
503 EXPECT_EQ(16730, changestamp
);
504 EXPECT_FALSE(GetResourceEntry("drive/root/New Directory/new_pdf_file.pdf"));
506 EXPECT_TRUE(changed_files
.empty());
509 TEST_F(ChangeListProcessorTest
, RefreshDirectory
) {
511 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
513 // Create change list.
514 scoped_ptr
<ChangeList
> change_list(new ChangeList
);
516 // Add a new file to the change list.
517 ResourceEntry new_file
;
518 new_file
.set_title("new_file");
519 new_file
.set_resource_id("new_file_id");
520 change_list
->mutable_entries()->push_back(new_file
);
521 change_list
->mutable_parent_resource_ids()->push_back(kRootId
);
523 // Add "Directory 1" to the map with a new name.
525 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
526 util::GetDriveMyDriveRootPath().AppendASCII("Directory 1"), &dir1
));
527 dir1
.set_title(dir1
.title() + " (renamed)");
528 change_list
->mutable_entries()->push_back(dir1
);
529 change_list
->mutable_parent_resource_ids()->push_back(kRootId
);
531 // Update the directory with the map.
533 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
534 util::GetDriveMyDriveRootPath(), &root
));
535 const int64 kNewChangestamp
= 12345;
536 ResourceEntryVector refreshed_entries
;
537 EXPECT_EQ(FILE_ERROR_OK
, ChangeListProcessor::RefreshDirectory(
539 DirectoryFetchInfo(root
.local_id(), kRootId
, kNewChangestamp
),
541 &refreshed_entries
));
543 // "new_file" should be added.
545 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
546 util::GetDriveMyDriveRootPath().AppendASCII(new_file
.title()), &entry
));
548 // "Directory 1" should be renamed.
549 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
550 util::GetDriveMyDriveRootPath().AppendASCII(dir1
.title()), &entry
));
553 TEST_F(ChangeListProcessorTest
, RefreshDirectory_WrongParentId
) {
555 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
557 // Create change list and add a new file to it.
558 scoped_ptr
<ChangeList
> change_list(new ChangeList
);
559 ResourceEntry new_file
;
560 new_file
.set_title("new_file");
561 new_file
.set_resource_id("new_file_id");
562 // This entry should not be added because the parent ID does not match.
563 change_list
->mutable_parent_resource_ids()->push_back(
564 "some-random-resource-id");
565 change_list
->mutable_entries()->push_back(new_file
);
568 // Update the directory.
570 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
571 util::GetDriveMyDriveRootPath(), &root
));
572 const int64 kNewChangestamp
= 12345;
573 ResourceEntryVector refreshed_entries
;
574 EXPECT_EQ(FILE_ERROR_OK
, ChangeListProcessor::RefreshDirectory(
576 DirectoryFetchInfo(root
.local_id(), kRootId
, kNewChangestamp
),
578 &refreshed_entries
));
580 // "new_file" should not be added.
582 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, metadata_
->GetResourceEntryByPath(
583 util::GetDriveMyDriveRootPath().AppendASCII(new_file
.title()), &entry
));
586 TEST_F(ChangeListProcessorTest
, SharedFilesWithNoParentInFeed
) {
588 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
590 // Create change lists.
591 ScopedVector
<ChangeList
> change_lists
;
592 change_lists
.push_back(new ChangeList
);
594 // Add a new file with non-existing parent resource id to the change lists.
595 ResourceEntry new_file
;
596 new_file
.set_title("new_file");
597 new_file
.set_resource_id("new_file_id");
598 change_lists
[0]->mutable_entries()->push_back(new_file
);
599 change_lists
[0]->mutable_parent_resource_ids()->push_back("nonexisting");
600 change_lists
[0]->set_largest_changestamp(kBaseResourceListChangestamp
+ 1);
602 FileChange changed_files
;
603 EXPECT_EQ(FILE_ERROR_OK
,
604 ApplyChangeList(change_lists
.Pass(), &changed_files
));
606 // "new_file" should be added under drive/other.
608 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
609 util::GetDriveGrandRootPath().AppendASCII("other/new_file"), &entry
));
612 TEST_F(ChangeListProcessorTest
, ModificationDate
) {
614 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
616 // Create change lists with a new file.
617 ScopedVector
<ChangeList
> change_lists
;
618 change_lists
.push_back(new ChangeList
);
620 const base::Time now
= base::Time::Now();
621 ResourceEntry new_file_remote
;
622 new_file_remote
.set_title("new_file_remote");
623 new_file_remote
.set_resource_id("new_file_id");
624 new_file_remote
.set_modification_date(now
.ToInternalValue());
626 change_lists
[0]->mutable_entries()->push_back(new_file_remote
);
627 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
628 change_lists
[0]->set_largest_changestamp(kBaseResourceListChangestamp
+ 1);
630 // Add the same file locally, but with a different name, a dirty metadata
631 // state, and a newer modification date.
633 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
634 util::GetDriveMyDriveRootPath(), &root
));
636 ResourceEntry new_file_local
;
637 new_file_local
.set_resource_id(new_file_remote
.resource_id());
638 new_file_local
.set_parent_local_id(root
.local_id());
639 new_file_local
.set_title("new_file_local");
640 new_file_local
.set_metadata_edit_state(ResourceEntry::DIRTY
);
641 new_file_local
.set_modification_date(
642 (now
+ base::TimeDelta::FromSeconds(1)).ToInternalValue());
643 std::string local_id
;
644 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->AddEntry(new_file_local
, &local_id
));
647 FileChange changed_files
;
648 EXPECT_EQ(FILE_ERROR_OK
,
649 ApplyChangeList(change_lists
.Pass(), &changed_files
));
651 // The change is rejected due to the old modification date.
653 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryById(local_id
, &entry
));
654 EXPECT_EQ(new_file_local
.title(), entry
.title());
657 } // namespace internal