Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / change_list_processor_unittest.cc
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.
4
5 #include "chrome/browser/chromeos/drive/change_list_processor.h"
6
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "base/values.h"
10 #include "chrome/browser/chromeos/drive/drive.pb.h"
11 #include "chrome/browser/chromeos/drive/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"
21
22 namespace drive {
23 namespace internal {
24
25 namespace {
26
27 const int64 kBaseResourceListChangestamp = 123;
28 const char kRootId[] = "fake_root";
29
30 enum FileOrDirectory {
31   FILE,
32   DIRECTORY,
33 };
34
35 struct EntryExpectation {
36   std::string path;
37   std::string id;
38   std::string parent_id;
39   FileOrDirectory type;
40 };
41
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);
46
47   // Add directories to the change list.
48   ResourceEntry directory;
49   directory.mutable_file_info()->set_is_directory(true);
50
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);
55
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");
61
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");
67
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);
72
73   // Add files to the change list.
74   ResourceEntry file;
75
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);
80
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");
86
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("");
91
92   change_lists[0]->set_largest_changestamp(kBaseResourceListChangestamp);
93   return change_lists.Pass();
94 }
95
96 class ChangeListProcessorTest : public testing::Test {
97  protected:
98   virtual void SetUp() OVERRIDE {
99     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
100
101     metadata_storage_.reset(new ResourceMetadataStorage(
102         temp_dir_.path(), base::MessageLoopProxy::current().get()));
103     ASSERT_TRUE(metadata_storage_->Initialize());
104
105     fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter);
106     cache_.reset(new FileCache(metadata_storage_.get(),
107                                temp_dir_.path(),
108                                base::MessageLoopProxy::current().get(),
109                                fake_free_disk_space_getter_.get()));
110     ASSERT_TRUE(cache_->Initialize());
111
112     metadata_.reset(new internal::ResourceMetadata(
113         metadata_storage_.get(), cache_.get(),
114         base::MessageLoopProxy::current()));
115     ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
116   }
117
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);
125
126     ChangeListProcessor processor(metadata_.get());
127     return processor.Apply(about_resource.Pass(),
128                            changes.Pass(),
129                            false /* is_delta_update */);
130   }
131
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);
140
141     ChangeListProcessor processor(metadata_.get());
142     FileError error = processor.Apply(about_resource.Pass(),
143                                       changes.Pass(),
144                                       true /* is_delta_update */);
145     *changed_files = processor.changed_files();
146     return error;
147   }
148
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)
156       entry.reset();
157     return entry.Pass();
158   }
159
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_;
167 };
168
169 }  // namespace
170
171 TEST_F(ChangeListProcessorTest, ApplyFullResourceList) {
172   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
173
174   const EntryExpectation kExpected[] = {
175       // Root files
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},
186       // Deeper
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},
193       // Orphan
194       {"drive/other/Orphan File 1.txt", "1_orphanfile_resource_id",
195            "", FILE},
196   };
197
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());
202
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);
209   }
210
211   int64 changestamp = 0;
212   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp));
213   EXPECT_EQ(kBaseResourceListChangestamp, changestamp);
214 }
215
216 TEST_F(ChangeListProcessorTest, DeltaFileAddedInNewDirectory) {
217   ScopedVector<ChangeList> change_lists;
218   change_lists.push_back(new ChangeList);
219
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);
226
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());
233
234   change_lists[0]->set_largest_changestamp(16730);
235
236   // Apply the changelist and check the effect.
237   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
238
239   FileChange changed_files;
240   EXPECT_EQ(FILE_ERROR_OK,
241             ApplyChangeList(change_lists.Pass(), &changed_files));
242
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"));
249
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")));
255 }
256
257 TEST_F(ChangeListProcessorTest, DeltaDirMovedFromRootToDirectory) {
258   ScopedVector<ChangeList> change_lists;
259   change_lists.push_back(new ChangeList);
260
261   ResourceEntry entry;
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");
268
269   change_lists[0]->set_largest_changestamp(16809);
270
271   // Apply the changelist and check the effect.
272   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
273
274   FileChange changed_files;
275   EXPECT_EQ(FILE_ERROR_OK,
276             ApplyChangeList(change_lists.Pass(), &changed_files));
277
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"));
284
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")));
294 }
295
296 TEST_F(ChangeListProcessorTest, DeltaFileMovedFromDirectoryToRoot) {
297   ScopedVector<ChangeList> change_lists;
298   change_lists.push_back(new ChangeList);
299
300   ResourceEntry entry;
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);
305
306   change_lists[0]->set_largest_changestamp(16815);
307
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));
313
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"));
320
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")));
326 }
327
328 TEST_F(ChangeListProcessorTest, DeltaFileRenamedInDirectory) {
329   ScopedVector<ChangeList> change_lists;
330   change_lists.push_back(new ChangeList);
331
332   ResourceEntry entry;
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");
338
339   change_lists[0]->set_largest_changestamp(16767);
340
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));
346
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"));
354
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")));
360 }
361
362 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileInRoot) {
363   // Create ChangeList to add a file.
364   ScopedVector<ChangeList> change_lists;
365   change_lists.push_back(new ChangeList);
366
367   ResourceEntry entry;
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);
372
373   change_lists[0]->set_largest_changestamp(16683);
374
375   // Apply.
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));
380
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")));
388
389   // Create ChangeList to delete the file.
390   change_lists.push_back(new ChangeList);
391
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);
395
396   change_lists[0]->set_largest_changestamp(16687);
397
398   // Apply.
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")));
407 }
408
409
410 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileFromExistingDirectory) {
411   // Create ChangeList to add a file.
412   ScopedVector<ChangeList> change_lists;
413   change_lists.push_back(new ChangeList);
414
415   ResourceEntry entry;
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");
421
422   change_lists[0]->set_largest_changestamp(16730);
423
424   // Apply.
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"));
433
434   EXPECT_EQ(1U, changed_files.size());
435   EXPECT_TRUE(changed_files.count(
436       base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt")));
437
438   // Create ChangeList to delete the file.
439   change_lists.push_back(new ChangeList);
440
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");
445
446   change_lists[0]->set_largest_changestamp(16770);
447
448   // Apply.
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"));
454
455   EXPECT_EQ(1U, changed_files.size());
456   EXPECT_TRUE(changed_files.count(
457       base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt")));
458 }
459
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);
467
468   ResourceEntry file;
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");
475
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);
483
484   change_lists[0]->set_largest_changestamp(16730);
485
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));
491
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"));
496
497   EXPECT_TRUE(changed_files.empty());
498 }
499
500 TEST_F(ChangeListProcessorTest, RefreshDirectory) {
501   // Prepare metadata.
502   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
503
504   // Create change list.
505   scoped_ptr<ChangeList> change_list(new ChangeList);
506
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);
513
514   // Add "Directory 1" to the map with a new name.
515   ResourceEntry dir1;
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);
521
522   // Update the directory with the map.
523   ResourceEntry root;
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(
529       metadata_.get(),
530       DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
531       change_list.Pass(),
532       &refreshed_entries));
533
534   // "new_file" should be added.
535   ResourceEntry entry;
536   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
537       util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
538
539   // "Directory 1" should be renamed.
540   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
541       util::GetDriveMyDriveRootPath().AppendASCII(dir1.title()), &entry));
542 }
543
544 TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) {
545   // Prepare metadata.
546   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
547
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);
557
558
559   // Update the directory.
560   ResourceEntry root;
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(
566       metadata_.get(),
567       DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
568       change_list.Pass(),
569       &refreshed_entries));
570
571   // "new_file" should not be added.
572   ResourceEntry entry;
573   EXPECT_EQ(FILE_ERROR_NOT_FOUND, metadata_->GetResourceEntryByPath(
574       util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
575 }
576
577 TEST_F(ChangeListProcessorTest, SharedFilesWithNoParentInFeed) {
578   // Prepare metadata.
579   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
580
581   // Create change lists.
582   ScopedVector<ChangeList> change_lists;
583   change_lists.push_back(new ChangeList);
584
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);
592
593   FileChange changed_files;
594   EXPECT_EQ(FILE_ERROR_OK,
595             ApplyChangeList(change_lists.Pass(), &changed_files));
596
597   // "new_file" should be added under drive/other.
598   ResourceEntry entry;
599   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
600       util::GetDriveGrandRootPath().AppendASCII("other/new_file"), &entry));
601 }
602
603 TEST_F(ChangeListProcessorTest, ModificationDate) {
604   // Prepare metadata.
605   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
606
607   // Create change lists with a new file.
608   ScopedVector<ChangeList> change_lists;
609   change_lists.push_back(new ChangeList);
610
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());
616
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);
620
621   // Add the same file locally, but with a different name, a dirty metadata
622   // state, and a newer modification date.
623   ResourceEntry root;
624   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
625       util::GetDriveMyDriveRootPath(), &root));
626
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));
636
637   // Apply the change.
638   FileChange changed_files;
639   EXPECT_EQ(FILE_ERROR_OK,
640             ApplyChangeList(change_lists.Pass(), &changed_files));
641
642   // The change is rejected due to the old modification date.
643   ResourceEntry entry;
644   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryById(local_id, &entry));
645   EXPECT_EQ(new_file_local.title(), entry.title());
646 }
647
648 }  // namespace internal
649 }  // namespace drive