Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / change_list_processor_unittest.cc
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.
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/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"
19
20 namespace drive {
21 namespace internal {
22
23 namespace {
24
25 const int64 kBaseResourceListChangestamp = 123;
26 const char kRootId[] = "fake_root";
27
28 enum FileOrDirectory {
29   FILE,
30   DIRECTORY,
31 };
32
33 struct EntryExpectation {
34   std::string path;
35   std::string id;
36   std::string parent_id;
37   FileOrDirectory type;
38 };
39
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);
44
45   // Add directories to the change list.
46   ResourceEntry directory;
47   directory.mutable_file_info()->set_is_directory(true);
48
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);
53
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");
59
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");
65
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);
70
71   // Add files to the change list.
72   ResourceEntry file;
73
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);
78
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");
84
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("");
89
90   change_lists[0]->set_largest_changestamp(kBaseResourceListChangestamp);
91   return change_lists.Pass();
92 }
93
94 class ChangeListProcessorTest : public testing::Test {
95  protected:
96   virtual void SetUp() OVERRIDE {
97     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
98
99     metadata_storage_.reset(new ResourceMetadataStorage(
100         temp_dir_.path(), base::MessageLoopProxy::current().get()));
101     ASSERT_TRUE(metadata_storage_->Initialize());
102
103     metadata_.reset(new internal::ResourceMetadata(
104         metadata_storage_.get(), base::MessageLoopProxy::current()));
105     ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize());
106   }
107
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);
115
116     ChangeListProcessor processor(metadata_.get());
117     return processor.Apply(about_resource.Pass(),
118                            changes.Pass(),
119                            false /* is_delta_update */);
120   }
121
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);
130
131     ChangeListProcessor processor(metadata_.get());
132     FileError error = processor.Apply(about_resource.Pass(),
133                                       changes.Pass(),
134                                       true /* is_delta_update */);
135     *changed_dirs = processor.changed_dirs();
136     return error;
137   }
138
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)
146       entry.reset();
147     return entry.Pass();
148   }
149
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_;
155 };
156
157 }  // namespace
158
159 TEST_F(ChangeListProcessorTest, ApplyFullResourceList) {
160   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
161
162   const EntryExpectation kExpected[] = {
163       // Root files
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},
174       // Deeper
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},
181       // Orphan
182       {"drive/other/Orphan File 1.txt", "file:1_orphanfile_resource_id",
183            "", FILE},
184   };
185
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());
190
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);
197   }
198
199   EXPECT_EQ(kBaseResourceListChangestamp, metadata_->GetLargestChangestamp());
200 }
201
202 TEST_F(ChangeListProcessorTest, DeltaFileAddedInNewDirectory) {
203   ScopedVector<ChangeList> change_lists;
204   change_lists.push_back(new ChangeList);
205
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);
212
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());
219
220   change_lists[0]->set_largest_changestamp(16730);
221
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));
226
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"));
231
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")));
237 }
238
239 TEST_F(ChangeListProcessorTest, DeltaDirMovedFromRootToDirectory) {
240   ScopedVector<ChangeList> change_lists;
241   change_lists.push_back(new ChangeList);
242
243   ResourceEntry entry;
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");
250
251   change_lists[0]->set_largest_changestamp(16809);
252
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));
257
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"));
262
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")));
274 }
275
276 TEST_F(ChangeListProcessorTest, DeltaFileMovedFromDirectoryToRoot) {
277   ScopedVector<ChangeList> change_lists;
278   change_lists.push_back(new ChangeList);
279
280   ResourceEntry entry;
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);
285
286   change_lists[0]->set_largest_changestamp(16815);
287
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));
292
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"));
297
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")));
303 }
304
305 TEST_F(ChangeListProcessorTest, DeltaFileRenamedInDirectory) {
306   ScopedVector<ChangeList> change_lists;
307   change_lists.push_back(new ChangeList);
308
309   ResourceEntry entry;
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");
315
316   change_lists[0]->set_largest_changestamp(16767);
317
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));
322
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"));
328
329   EXPECT_EQ(1U, changed_dirs.size());
330   EXPECT_TRUE(changed_dirs.count(
331       base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
332 }
333
334 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileInRoot) {
335   // Create ChangeList to add a file.
336   ScopedVector<ChangeList> change_lists;
337   change_lists.push_back(new ChangeList);
338
339   ResourceEntry entry;
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);
344
345   change_lists[0]->set_largest_changestamp(16683);
346
347   // Apply.
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")));
356
357   // Create ChangeList to delete the file.
358   change_lists.push_back(new ChangeList);
359
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);
363
364   change_lists[0]->set_largest_changestamp(16687);
365
366   // Apply.
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")));
373 }
374
375
376 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileFromExistingDirectory) {
377   // Create ChangeList to add a file.
378   ScopedVector<ChangeList> change_lists;
379   change_lists.push_back(new ChangeList);
380
381   ResourceEntry entry;
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");
387
388   change_lists[0]->set_largest_changestamp(16730);
389
390   // Apply.
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"));
396
397   EXPECT_EQ(1U, changed_dirs.size());
398   EXPECT_TRUE(changed_dirs.count(
399       base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
400
401   // Create ChangeList to delete the file.
402   change_lists.push_back(new ChangeList);
403
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");
408
409   change_lists[0]->set_largest_changestamp(16770);
410
411   // Apply.
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"));
415
416   EXPECT_EQ(1U, changed_dirs.size());
417   EXPECT_TRUE(changed_dirs.count(
418       base::FilePath::FromUTF8Unsafe("drive/root/Directory 1")));
419 }
420
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);
428
429   ResourceEntry file;
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");
436
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);
444
445   change_lists[0]->set_largest_changestamp(16730);
446
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));
451
452   EXPECT_EQ(16730, metadata_->GetLargestChangestamp());
453   EXPECT_FALSE(GetResourceEntry("drive/root/New Directory/new_pdf_file.pdf"));
454
455   EXPECT_TRUE(changed_dirs.empty());
456 }
457
458 TEST_F(ChangeListProcessorTest, RefreshDirectory) {
459   // Prepare metadata.
460   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
461
462   // Create change list.
463   scoped_ptr<ChangeList> change_list(new ChangeList);
464
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);
471
472   // Add "Directory 1" to the map with a new name.
473   ResourceEntry dir1;
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);
479
480   // Update the directory with the map.
481   ResourceEntry root;
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(
487       metadata_.get(),
488       DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
489       change_list.Pass(),
490       &refreshed_entries));
491
492   // "new_file" should be added.
493   ResourceEntry entry;
494   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
495       util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
496
497   // "Directory 1" should be renamed.
498   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
499       util::GetDriveMyDriveRootPath().AppendASCII(dir1.title()), &entry));
500 }
501
502 TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) {
503   // Prepare metadata.
504   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
505
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);
515
516
517   // Update the directory.
518   ResourceEntry root;
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(
524       metadata_.get(),
525       DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
526       change_list.Pass(),
527       &refreshed_entries));
528
529   // "new_file" should not be added.
530   ResourceEntry entry;
531   EXPECT_EQ(FILE_ERROR_NOT_FOUND, metadata_->GetResourceEntryByPath(
532       util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
533 }
534
535 TEST_F(ChangeListProcessorTest, SharedFilesWithNoParentInFeed) {
536   // Prepare metadata.
537   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
538
539   // Create change lists.
540   ScopedVector<ChangeList> change_lists;
541   change_lists.push_back(new ChangeList);
542
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);
550
551   std::set<base::FilePath> changed_dirs;
552   EXPECT_EQ(FILE_ERROR_OK, ApplyChangeList(change_lists.Pass(), &changed_dirs));
553
554   // "new_file" should be added under drive/other.
555   ResourceEntry entry;
556   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
557       util::GetDriveGrandRootPath().AppendASCII("other/new_file"), &entry));
558 }
559
560 TEST_F(ChangeListProcessorTest, ModificationDate) {
561   // Prepare metadata.
562   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList()));
563
564   // Create change lists with a new file.
565   ScopedVector<ChangeList> change_lists;
566   change_lists.push_back(new ChangeList);
567
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());
573
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);
577
578   // Add the same file locally, but with a different name, a dirty metadata
579   // state, and a newer modification date.
580   ResourceEntry root;
581   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
582       util::GetDriveMyDriveRootPath(), &root));
583
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));
593
594   // Apply the change.
595   std::set<base::FilePath> changed_dirs;
596   EXPECT_EQ(FILE_ERROR_OK, ApplyChangeList(change_lists.Pass(), &changed_dirs));
597
598   // The change is rejected due to the old modification date.
599   ResourceEntry entry;
600   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryById(local_id, &entry));
601   EXPECT_EQ(new_file_local.title(), entry.title());
602 }
603
604 }  // namespace internal
605 }  // namespace drive