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 Property
* const property
= file
.mutable_new_properties()->Add();
84 property
->set_key("hello");
85 property
->set_value("world");
86 change_lists
[0]->mutable_entries()->push_back(file
);
87 change_lists
[0]->mutable_parent_resource_ids()->push_back(
88 "1_folder_resource_id");
90 file
.set_title("Orphan File 1.txt");
91 file
.set_resource_id("1_orphanfile_resource_id");
92 change_lists
[0]->mutable_entries()->push_back(file
);
93 change_lists
[0]->mutable_parent_resource_ids()->push_back("");
95 change_lists
[0]->set_largest_changestamp(kBaseResourceListChangestamp
);
96 return change_lists
.Pass();
99 class ChangeListProcessorTest
: public testing::Test
{
101 void SetUp() override
{
102 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
104 metadata_storage_
.reset(new ResourceMetadataStorage(
105 temp_dir_
.path(), base::MessageLoopProxy::current().get()));
106 ASSERT_TRUE(metadata_storage_
->Initialize());
108 fake_free_disk_space_getter_
.reset(new FakeFreeDiskSpaceGetter
);
109 cache_
.reset(new FileCache(metadata_storage_
.get(),
111 base::MessageLoopProxy::current().get(),
112 fake_free_disk_space_getter_
.get()));
113 ASSERT_TRUE(cache_
->Initialize());
115 metadata_
.reset(new internal::ResourceMetadata(
116 metadata_storage_
.get(), cache_
.get(),
117 base::MessageLoopProxy::current()));
118 ASSERT_EQ(FILE_ERROR_OK
, metadata_
->Initialize());
121 // Applies the |changes| to |metadata_| as a full resource list of changestamp
122 // |kBaseResourceListChangestamp|.
123 FileError
ApplyFullResourceList(ScopedVector
<ChangeList
> changes
) {
124 scoped_ptr
<google_apis::AboutResource
> about_resource(
125 new google_apis::AboutResource
);
126 about_resource
->set_largest_change_id(kBaseResourceListChangestamp
);
127 about_resource
->set_root_folder_id(kRootId
);
129 ChangeListProcessor
processor(metadata_
.get());
130 return processor
.Apply(about_resource
.Pass(),
132 false /* is_delta_update */);
135 // Applies the |changes| to |metadata_| as a delta update. Delta changelists
136 // should contain their changestamp in themselves.
137 FileError
ApplyChangeList(ScopedVector
<ChangeList
> changes
,
138 FileChange
* changed_files
) {
139 scoped_ptr
<google_apis::AboutResource
> about_resource(
140 new google_apis::AboutResource
);
141 about_resource
->set_largest_change_id(kBaseResourceListChangestamp
);
142 about_resource
->set_root_folder_id(kRootId
);
144 ChangeListProcessor
processor(metadata_
.get());
145 FileError error
= processor
.Apply(about_resource
.Pass(),
147 true /* is_delta_update */);
148 *changed_files
= processor
.changed_files();
152 // Gets the resource entry for the path from |metadata_| synchronously.
153 // Returns null if the entry does not exist.
154 scoped_ptr
<ResourceEntry
> GetResourceEntry(const std::string
& path
) {
155 scoped_ptr
<ResourceEntry
> entry(new ResourceEntry
);
156 FileError error
= metadata_
->GetResourceEntryByPath(
157 base::FilePath::FromUTF8Unsafe(path
), entry
.get());
158 if (error
!= FILE_ERROR_OK
)
163 content::TestBrowserThreadBundle thread_bundle_
;
164 base::ScopedTempDir temp_dir_
;
165 scoped_ptr
<ResourceMetadataStorage
,
166 test_util::DestroyHelperForTests
> metadata_storage_
;
167 scoped_ptr
<FakeFreeDiskSpaceGetter
> fake_free_disk_space_getter_
;
168 scoped_ptr
<FileCache
, test_util::DestroyHelperForTests
> cache_
;
169 scoped_ptr
<ResourceMetadata
, test_util::DestroyHelperForTests
> metadata_
;
174 TEST_F(ChangeListProcessorTest
, ApplyFullResourceList
) {
175 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
177 const EntryExpectation kExpected
[] = {
179 {"drive/root", kRootId
, "", DIRECTORY
},
180 {"drive/root/File 1.txt",
181 "2_file_resource_id", kRootId
, FILE},
182 // Subdirectory files
183 {"drive/root/Directory 1",
184 "1_folder_resource_id", kRootId
, DIRECTORY
},
185 {"drive/root/Directory 1/SubDirectory File 1.txt",
186 "subdirectory_file_1_id", "1_folder_resource_id", FILE},
187 {"drive/root/Directory 2 excludeDir-test",
188 "sub_dir_folder_2_self_link", kRootId
, DIRECTORY
},
190 {"drive/root/Directory 1/Sub Directory Folder",
191 "sub_dir_folder_resource_id",
192 "1_folder_resource_id", DIRECTORY
},
193 {"drive/root/Directory 1/Sub Directory Folder/Sub Sub Directory Folder",
194 "sub_sub_directory_folder_id",
195 "sub_dir_folder_resource_id", DIRECTORY
},
197 {"drive/other/Orphan File 1.txt", "1_orphanfile_resource_id",
201 for (size_t i
= 0; i
< arraysize(kExpected
); ++i
) {
202 scoped_ptr
<ResourceEntry
> entry
= GetResourceEntry(kExpected
[i
].path
);
203 ASSERT_TRUE(entry
) << "for path: " << kExpected
[i
].path
;
204 EXPECT_EQ(kExpected
[i
].id
, entry
->resource_id());
206 ResourceEntry parent_entry
;
207 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryById(
208 entry
->parent_local_id(), &parent_entry
));
209 EXPECT_EQ(kExpected
[i
].parent_id
, parent_entry
.resource_id());
210 EXPECT_EQ(kExpected
[i
].type
,
211 entry
->file_info().is_directory() ? DIRECTORY
: FILE);
214 int64 changestamp
= 0;
215 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
216 EXPECT_EQ(kBaseResourceListChangestamp
, changestamp
);
219 TEST_F(ChangeListProcessorTest
, DeltaFileAddedInNewDirectory
) {
220 ScopedVector
<ChangeList
> change_lists
;
221 change_lists
.push_back(new ChangeList
);
223 ResourceEntry new_folder
;
224 new_folder
.set_resource_id("new_folder_resource_id");
225 new_folder
.set_title("New Directory");
226 new_folder
.mutable_file_info()->set_is_directory(true);
227 change_lists
[0]->mutable_entries()->push_back(new_folder
);
228 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
230 ResourceEntry new_file
;
231 new_file
.set_resource_id("file_added_in_new_dir_id");
232 new_file
.set_title("File in new dir.txt");
233 change_lists
[0]->mutable_entries()->push_back(new_file
);
234 change_lists
[0]->mutable_parent_resource_ids()->push_back(
235 new_folder
.resource_id());
237 change_lists
[0]->set_largest_changestamp(16730);
239 // Apply the changelist and check the effect.
240 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
242 FileChange changed_files
;
243 EXPECT_EQ(FILE_ERROR_OK
,
244 ApplyChangeList(change_lists
.Pass(), &changed_files
));
246 int64 changestamp
= 0;
247 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
248 EXPECT_EQ(16730, changestamp
);
249 EXPECT_TRUE(GetResourceEntry("drive/root/New Directory"));
250 EXPECT_TRUE(GetResourceEntry(
251 "drive/root/New Directory/File in new dir.txt"));
253 EXPECT_EQ(2U, changed_files
.size());
254 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
255 "drive/root/New Directory/File in new dir.txt")));
256 EXPECT_TRUE(changed_files
.count(
257 base::FilePath::FromUTF8Unsafe("drive/root/New Directory")));
260 TEST_F(ChangeListProcessorTest
, DeltaDirMovedFromRootToDirectory
) {
261 ScopedVector
<ChangeList
> change_lists
;
262 change_lists
.push_back(new ChangeList
);
265 entry
.set_resource_id("1_folder_resource_id");
266 entry
.set_title("Directory 1");
267 entry
.mutable_file_info()->set_is_directory(true);
268 change_lists
[0]->mutable_entries()->push_back(entry
);
269 change_lists
[0]->mutable_parent_resource_ids()->push_back(
270 "sub_dir_folder_2_self_link");
272 change_lists
[0]->set_largest_changestamp(16809);
274 // Apply the changelist and check the effect.
275 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
277 FileChange changed_files
;
278 EXPECT_EQ(FILE_ERROR_OK
,
279 ApplyChangeList(change_lists
.Pass(), &changed_files
));
281 int64 changestamp
= 0;
282 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
283 EXPECT_EQ(16809, changestamp
);
284 EXPECT_FALSE(GetResourceEntry("drive/root/Directory 1"));
285 EXPECT_TRUE(GetResourceEntry(
286 "drive/root/Directory 2 excludeDir-test/Directory 1"));
288 EXPECT_EQ(2U, changed_files
.size());
289 EXPECT_TRUE(changed_files
.CountDirectory(
290 base::FilePath::FromUTF8Unsafe("drive/root")));
291 EXPECT_TRUE(changed_files
.count(
292 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
293 EXPECT_TRUE(changed_files
.CountDirectory(base::FilePath::FromUTF8Unsafe(
294 "drive/root/Directory 2 excludeDir-test")));
295 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
296 "drive/root/Directory 2 excludeDir-test/Directory 1")));
299 TEST_F(ChangeListProcessorTest
, DeltaFileMovedFromDirectoryToRoot
) {
300 ScopedVector
<ChangeList
> change_lists
;
301 change_lists
.push_back(new ChangeList
);
304 entry
.set_resource_id("subdirectory_file_1_id");
305 entry
.set_title("SubDirectory File 1.txt");
306 change_lists
[0]->mutable_entries()->push_back(entry
);
307 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
309 change_lists
[0]->set_largest_changestamp(16815);
311 // Apply the changelist and check the effect.
312 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
313 FileChange changed_files
;
314 EXPECT_EQ(FILE_ERROR_OK
,
315 ApplyChangeList(change_lists
.Pass(), &changed_files
));
317 int64 changestamp
= 0;
318 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
319 EXPECT_EQ(16815, changestamp
);
320 EXPECT_FALSE(GetResourceEntry(
321 "drive/root/Directory 1/SubDirectory File 1.txt"));
322 EXPECT_TRUE(GetResourceEntry("drive/root/SubDirectory File 1.txt"));
324 EXPECT_EQ(2U, changed_files
.size());
325 EXPECT_TRUE(changed_files
.count(
326 base::FilePath::FromUTF8Unsafe("drive/root/SubDirectory File 1.txt")));
327 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
328 "drive/root/Directory 1/SubDirectory File 1.txt")));
331 TEST_F(ChangeListProcessorTest
, DeltaFileRenamedInDirectory
) {
332 ScopedVector
<ChangeList
> change_lists
;
333 change_lists
.push_back(new ChangeList
);
336 entry
.set_resource_id("subdirectory_file_1_id");
337 entry
.set_title("New SubDirectory File 1.txt");
338 change_lists
[0]->mutable_entries()->push_back(entry
);
339 change_lists
[0]->mutable_parent_resource_ids()->push_back(
340 "1_folder_resource_id");
342 change_lists
[0]->set_largest_changestamp(16767);
344 // Apply the changelist and check the effect.
345 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
346 FileChange changed_files
;
347 EXPECT_EQ(FILE_ERROR_OK
,
348 ApplyChangeList(change_lists
.Pass(), &changed_files
));
349 EXPECT_EQ(2U, changed_files
.size());
350 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
351 "drive/root/Directory 1/SubDirectory File 1.txt")));
352 EXPECT_TRUE(changed_files
.count(base::FilePath::FromUTF8Unsafe(
353 "drive/root/Directory 1/New SubDirectory File 1.txt")));
355 int64 changestamp
= 0;
356 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
357 EXPECT_EQ(16767, changestamp
);
358 EXPECT_FALSE(GetResourceEntry(
359 "drive/root/Directory 1/SubDirectory File 1.txt"));
360 scoped_ptr
<ResourceEntry
> new_entry(
361 GetResourceEntry("drive/root/Directory 1/New SubDirectory File 1.txt"));
362 ASSERT_TRUE(new_entry
);
364 // Keep the to-be-synced properties.
365 ASSERT_EQ(1, new_entry
->mutable_new_properties()->size());
366 const Property
& new_property
= new_entry
->new_properties().Get(0);
367 EXPECT_EQ("hello", new_property
.key());
370 TEST_F(ChangeListProcessorTest
, DeltaAddAndDeleteFileInRoot
) {
371 // Create ChangeList to add a file.
372 ScopedVector
<ChangeList
> change_lists
;
373 change_lists
.push_back(new ChangeList
);
376 entry
.set_resource_id("added_in_root_id");
377 entry
.set_title("Added file.txt");
378 change_lists
[0]->mutable_entries()->push_back(entry
);
379 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
381 change_lists
[0]->set_largest_changestamp(16683);
384 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
385 FileChange changed_files
;
386 EXPECT_EQ(FILE_ERROR_OK
,
387 ApplyChangeList(change_lists
.Pass(), &changed_files
));
389 int64 changestamp
= 0;
390 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
391 EXPECT_EQ(16683, changestamp
);
392 EXPECT_TRUE(GetResourceEntry("drive/root/Added file.txt"));
393 EXPECT_EQ(1U, changed_files
.size());
394 EXPECT_TRUE(changed_files
.count(
395 base::FilePath::FromUTF8Unsafe("drive/root/Added file.txt")));
397 // Create ChangeList to delete the file.
398 change_lists
.push_back(new ChangeList
);
400 entry
.set_deleted(true);
401 change_lists
[0]->mutable_entries()->push_back(entry
);
402 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
404 change_lists
[0]->set_largest_changestamp(16687);
407 EXPECT_EQ(FILE_ERROR_OK
,
408 ApplyChangeList(change_lists
.Pass(), &changed_files
));
409 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
410 EXPECT_EQ(16687, changestamp
);
411 EXPECT_FALSE(GetResourceEntry("drive/root/Added file.txt"));
412 EXPECT_EQ(1U, changed_files
.size());
413 EXPECT_TRUE(changed_files
.count(
414 base::FilePath::FromUTF8Unsafe("drive/root/Added file.txt")));
418 TEST_F(ChangeListProcessorTest
, DeltaAddAndDeleteFileFromExistingDirectory
) {
419 // Create ChangeList to add a file.
420 ScopedVector
<ChangeList
> change_lists
;
421 change_lists
.push_back(new ChangeList
);
424 entry
.set_resource_id("added_in_root_id");
425 entry
.set_title("Added file.txt");
426 change_lists
[0]->mutable_entries()->push_back(entry
);
427 change_lists
[0]->mutable_parent_resource_ids()->push_back(
428 "1_folder_resource_id");
430 change_lists
[0]->set_largest_changestamp(16730);
433 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
434 FileChange changed_files
;
435 EXPECT_EQ(FILE_ERROR_OK
,
436 ApplyChangeList(change_lists
.Pass(), &changed_files
));
437 int64 changestamp
= 0;
438 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
439 EXPECT_EQ(16730, changestamp
);
440 EXPECT_TRUE(GetResourceEntry("drive/root/Directory 1/Added file.txt"));
442 EXPECT_EQ(1U, changed_files
.size());
443 EXPECT_TRUE(changed_files
.count(
444 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt")));
446 // Create ChangeList to delete the file.
447 change_lists
.push_back(new ChangeList
);
449 entry
.set_deleted(true);
450 change_lists
[0]->mutable_entries()->push_back(entry
);
451 change_lists
[0]->mutable_parent_resource_ids()->push_back(
452 "1_folder_resource_id");
454 change_lists
[0]->set_largest_changestamp(16770);
457 EXPECT_EQ(FILE_ERROR_OK
,
458 ApplyChangeList(change_lists
.Pass(), &changed_files
));
459 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
460 EXPECT_EQ(16770, changestamp
);
461 EXPECT_FALSE(GetResourceEntry("drive/root/Directory 1/Added file.txt"));
463 EXPECT_EQ(1U, changed_files
.size());
464 EXPECT_TRUE(changed_files
.count(
465 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt")));
468 TEST_F(ChangeListProcessorTest
, DeltaAddFileToNewButDeletedDirectory
) {
469 // Create a change which contains the following updates:
470 // 1) A new PDF file is added to a new directory
471 // 2) but the new directory is marked "deleted" (i.e. moved to Trash)
472 // Hence, the PDF file should be just ignored.
473 ScopedVector
<ChangeList
> change_lists
;
474 change_lists
.push_back(new ChangeList
);
477 file
.set_resource_id("file_added_in_deleted_id");
478 file
.set_title("new_pdf_file.pdf");
479 file
.set_deleted(true);
480 change_lists
[0]->mutable_entries()->push_back(file
);
481 change_lists
[0]->mutable_parent_resource_ids()->push_back(
482 "new_folder_resource_id");
484 ResourceEntry directory
;
485 directory
.set_resource_id("new_folder_resource_id");
486 directory
.set_title("New Directory");
487 directory
.mutable_file_info()->set_is_directory(true);
488 directory
.set_deleted(true);
489 change_lists
[0]->mutable_entries()->push_back(directory
);
490 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
492 change_lists
[0]->set_largest_changestamp(16730);
494 // Apply the changelist and check the effect.
495 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
496 FileChange changed_files
;
497 EXPECT_EQ(FILE_ERROR_OK
,
498 ApplyChangeList(change_lists
.Pass(), &changed_files
));
500 int64 changestamp
= 0;
501 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetLargestChangestamp(&changestamp
));
502 EXPECT_EQ(16730, changestamp
);
503 EXPECT_FALSE(GetResourceEntry("drive/root/New Directory/new_pdf_file.pdf"));
505 EXPECT_TRUE(changed_files
.empty());
508 TEST_F(ChangeListProcessorTest
, RefreshDirectory
) {
510 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
512 // Create change list.
513 scoped_ptr
<ChangeList
> change_list(new ChangeList
);
515 // Add a new file to the change list.
516 ResourceEntry new_file
;
517 new_file
.set_title("new_file");
518 new_file
.set_resource_id("new_file_id");
519 change_list
->mutable_entries()->push_back(new_file
);
520 change_list
->mutable_parent_resource_ids()->push_back(kRootId
);
522 // Add "Directory 1" to the map with a new name.
524 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
525 util::GetDriveMyDriveRootPath().AppendASCII("Directory 1"), &dir1
));
526 dir1
.set_title(dir1
.title() + " (renamed)");
527 change_list
->mutable_entries()->push_back(dir1
);
528 change_list
->mutable_parent_resource_ids()->push_back(kRootId
);
530 // Update the directory with the map.
532 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
533 util::GetDriveMyDriveRootPath(), &root
));
534 const int64 kNewChangestamp
= 12345;
535 ResourceEntryVector refreshed_entries
;
536 EXPECT_EQ(FILE_ERROR_OK
, ChangeListProcessor::RefreshDirectory(
538 DirectoryFetchInfo(root
.local_id(), kRootId
, kNewChangestamp
),
540 &refreshed_entries
));
542 // "new_file" should be added.
544 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
545 util::GetDriveMyDriveRootPath().AppendASCII(new_file
.title()), &entry
));
547 // "Directory 1" should be renamed.
548 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
549 util::GetDriveMyDriveRootPath().AppendASCII(dir1
.title()), &entry
));
552 TEST_F(ChangeListProcessorTest
, RefreshDirectory_WrongParentId
) {
554 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
556 // Create change list and add a new file to it.
557 scoped_ptr
<ChangeList
> change_list(new ChangeList
);
558 ResourceEntry new_file
;
559 new_file
.set_title("new_file");
560 new_file
.set_resource_id("new_file_id");
561 // This entry should not be added because the parent ID does not match.
562 change_list
->mutable_parent_resource_ids()->push_back(
563 "some-random-resource-id");
564 change_list
->mutable_entries()->push_back(new_file
);
567 // Update the directory.
569 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
570 util::GetDriveMyDriveRootPath(), &root
));
571 const int64 kNewChangestamp
= 12345;
572 ResourceEntryVector refreshed_entries
;
573 EXPECT_EQ(FILE_ERROR_OK
, ChangeListProcessor::RefreshDirectory(
575 DirectoryFetchInfo(root
.local_id(), kRootId
, kNewChangestamp
),
577 &refreshed_entries
));
579 // "new_file" should not be added.
581 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, metadata_
->GetResourceEntryByPath(
582 util::GetDriveMyDriveRootPath().AppendASCII(new_file
.title()), &entry
));
585 TEST_F(ChangeListProcessorTest
, SharedFilesWithNoParentInFeed
) {
587 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
589 // Create change lists.
590 ScopedVector
<ChangeList
> change_lists
;
591 change_lists
.push_back(new ChangeList
);
593 // Add a new file with non-existing parent resource id to the change lists.
594 ResourceEntry new_file
;
595 new_file
.set_title("new_file");
596 new_file
.set_resource_id("new_file_id");
597 change_lists
[0]->mutable_entries()->push_back(new_file
);
598 change_lists
[0]->mutable_parent_resource_ids()->push_back("nonexisting");
599 change_lists
[0]->set_largest_changestamp(kBaseResourceListChangestamp
+ 1);
601 FileChange changed_files
;
602 EXPECT_EQ(FILE_ERROR_OK
,
603 ApplyChangeList(change_lists
.Pass(), &changed_files
));
605 // "new_file" should be added under drive/other.
607 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
608 util::GetDriveGrandRootPath().AppendASCII("other/new_file"), &entry
));
611 TEST_F(ChangeListProcessorTest
, ModificationDate
) {
613 EXPECT_EQ(FILE_ERROR_OK
, ApplyFullResourceList(CreateBaseChangeList()));
615 // Create change lists with a new file.
616 ScopedVector
<ChangeList
> change_lists
;
617 change_lists
.push_back(new ChangeList
);
619 const base::Time now
= base::Time::Now();
620 ResourceEntry new_file_remote
;
621 new_file_remote
.set_title("new_file_remote");
622 new_file_remote
.set_resource_id("new_file_id");
623 new_file_remote
.set_modification_date(now
.ToInternalValue());
625 change_lists
[0]->mutable_entries()->push_back(new_file_remote
);
626 change_lists
[0]->mutable_parent_resource_ids()->push_back(kRootId
);
627 change_lists
[0]->set_largest_changestamp(kBaseResourceListChangestamp
+ 1);
629 // Add the same file locally, but with a different name, a dirty metadata
630 // state, and a newer modification date.
632 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryByPath(
633 util::GetDriveMyDriveRootPath(), &root
));
635 ResourceEntry new_file_local
;
636 new_file_local
.set_resource_id(new_file_remote
.resource_id());
637 new_file_local
.set_parent_local_id(root
.local_id());
638 new_file_local
.set_title("new_file_local");
639 new_file_local
.set_metadata_edit_state(ResourceEntry::DIRTY
);
640 new_file_local
.set_modification_date(
641 (now
+ base::TimeDelta::FromSeconds(1)).ToInternalValue());
642 std::string local_id
;
643 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->AddEntry(new_file_local
, &local_id
));
646 FileChange changed_files
;
647 EXPECT_EQ(FILE_ERROR_OK
,
648 ApplyChangeList(change_lists
.Pass(), &changed_files
));
650 // The change is rejected due to the old modification date.
652 EXPECT_EQ(FILE_ERROR_OK
, metadata_
->GetResourceEntryById(local_id
, &entry
));
653 EXPECT_EQ(new_file_local
.title(), entry
.title());
656 } // namespace internal