| OLD | NEW | 
 | (Empty) | 
|    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/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" |  | 
|   22  |  | 
|   23 namespace drive { |  | 
|   24 namespace internal { |  | 
|   25  |  | 
|   26 namespace { |  | 
|   27  |  | 
|   28 const int64 kBaseResourceListChangestamp = 123; |  | 
|   29 const char kRootId[] = "fake_root"; |  | 
|   30  |  | 
|   31 enum FileOrDirectory { |  | 
|   32   FILE, |  | 
|   33   DIRECTORY, |  | 
|   34 }; |  | 
|   35  |  | 
|   36 struct EntryExpectation { |  | 
|   37   std::string path; |  | 
|   38   std::string id; |  | 
|   39   std::string parent_id; |  | 
|   40   FileOrDirectory type; |  | 
|   41 }; |  | 
|   42  |  | 
|   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); |  | 
|   47  |  | 
|   48   // Add directories to the change list. |  | 
|   49   ResourceEntry directory; |  | 
|   50   directory.mutable_file_info()->set_is_directory(true); |  | 
|   51  |  | 
|   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); |  | 
|   56  |  | 
|   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"); |  | 
|   62  |  | 
|   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"); |  | 
|   68  |  | 
|   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); |  | 
|   73  |  | 
|   74   // Add files to the change list. |  | 
|   75   ResourceEntry file; |  | 
|   76  |  | 
|   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); |  | 
|   81  |  | 
|   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"); |  | 
|   90  |  | 
|   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(""); |  | 
|   95  |  | 
|   96   change_lists[0]->set_largest_changestamp(kBaseResourceListChangestamp); |  | 
|   97   return change_lists.Pass(); |  | 
|   98 } |  | 
|   99  |  | 
|  100 class ChangeListProcessorTest : public testing::Test { |  | 
|  101  protected: |  | 
|  102   void SetUp() override { |  | 
|  103     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |  | 
|  104  |  | 
|  105     metadata_storage_.reset(new ResourceMetadataStorage( |  | 
|  106         temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get())); |  | 
|  107     ASSERT_TRUE(metadata_storage_->Initialize()); |  | 
|  108  |  | 
|  109     fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter); |  | 
|  110     cache_.reset(new FileCache(metadata_storage_.get(), |  | 
|  111                                temp_dir_.path(), |  | 
|  112                                base::ThreadTaskRunnerHandle::Get().get(), |  | 
|  113                                fake_free_disk_space_getter_.get())); |  | 
|  114     ASSERT_TRUE(cache_->Initialize()); |  | 
|  115  |  | 
|  116     metadata_.reset(new internal::ResourceMetadata( |  | 
|  117         metadata_storage_.get(), cache_.get(), |  | 
|  118         base::ThreadTaskRunnerHandle::Get())); |  | 
|  119     ASSERT_EQ(FILE_ERROR_OK, metadata_->Initialize()); |  | 
|  120   } |  | 
|  121  |  | 
|  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); |  | 
|  129  |  | 
|  130     ChangeListProcessor processor(metadata_.get(), nullptr); |  | 
|  131     return processor.Apply(about_resource.Pass(), |  | 
|  132                            changes.Pass(), |  | 
|  133                            false /* is_delta_update */); |  | 
|  134   } |  | 
|  135  |  | 
|  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); |  | 
|  144  |  | 
|  145     ChangeListProcessor processor(metadata_.get(), nullptr); |  | 
|  146     FileError error = processor.Apply(about_resource.Pass(), |  | 
|  147                                       changes.Pass(), |  | 
|  148                                       true /* is_delta_update */); |  | 
|  149     *changed_files = processor.changed_files(); |  | 
|  150     return error; |  | 
|  151   } |  | 
|  152  |  | 
|  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) |  | 
|  160       entry.reset(); |  | 
|  161     return entry.Pass(); |  | 
|  162   } |  | 
|  163  |  | 
|  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_; |  | 
|  171 }; |  | 
|  172  |  | 
|  173 }  // namespace |  | 
|  174  |  | 
|  175 TEST_F(ChangeListProcessorTest, ApplyFullResourceList) { |  | 
|  176   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); |  | 
|  177  |  | 
|  178   const EntryExpectation kExpected[] = { |  | 
|  179       // Root files |  | 
|  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}, |  | 
|  190       // Deeper |  | 
|  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}, |  | 
|  197       // Orphan |  | 
|  198       {"drive/other/Orphan File 1.txt", "1_orphanfile_resource_id", |  | 
|  199            "", FILE}, |  | 
|  200   }; |  | 
|  201  |  | 
|  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()); |  | 
|  206  |  | 
|  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); |  | 
|  213   } |  | 
|  214  |  | 
|  215   int64 changestamp = 0; |  | 
|  216   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetLargestChangestamp(&changestamp)); |  | 
|  217   EXPECT_EQ(kBaseResourceListChangestamp, changestamp); |  | 
|  218 } |  | 
|  219  |  | 
|  220 TEST_F(ChangeListProcessorTest, DeltaFileAddedInNewDirectory) { |  | 
|  221   ScopedVector<ChangeList> change_lists; |  | 
|  222   change_lists.push_back(new ChangeList); |  | 
|  223  |  | 
|  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); |  | 
|  230  |  | 
|  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()); |  | 
|  237  |  | 
|  238   change_lists[0]->set_largest_changestamp(16730); |  | 
|  239  |  | 
|  240   // Apply the changelist and check the effect. |  | 
|  241   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); |  | 
|  242  |  | 
|  243   FileChange changed_files; |  | 
|  244   EXPECT_EQ(FILE_ERROR_OK, |  | 
|  245             ApplyChangeList(change_lists.Pass(), &changed_files)); |  | 
|  246  |  | 
|  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")); |  | 
|  253  |  | 
|  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"))); |  | 
|  259 } |  | 
|  260  |  | 
|  261 TEST_F(ChangeListProcessorTest, DeltaDirMovedFromRootToDirectory) { |  | 
|  262   ScopedVector<ChangeList> change_lists; |  | 
|  263   change_lists.push_back(new ChangeList); |  | 
|  264  |  | 
|  265   ResourceEntry entry; |  | 
|  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"); |  | 
|  272  |  | 
|  273   change_lists[0]->set_largest_changestamp(16809); |  | 
|  274  |  | 
|  275   // Apply the changelist and check the effect. |  | 
|  276   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); |  | 
|  277  |  | 
|  278   FileChange changed_files; |  | 
|  279   EXPECT_EQ(FILE_ERROR_OK, |  | 
|  280             ApplyChangeList(change_lists.Pass(), &changed_files)); |  | 
|  281  |  | 
|  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")); |  | 
|  288  |  | 
|  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"))); |  | 
|  298 } |  | 
|  299  |  | 
|  300 TEST_F(ChangeListProcessorTest, DeltaFileMovedFromDirectoryToRoot) { |  | 
|  301   ScopedVector<ChangeList> change_lists; |  | 
|  302   change_lists.push_back(new ChangeList); |  | 
|  303  |  | 
|  304   ResourceEntry entry; |  | 
|  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); |  | 
|  309  |  | 
|  310   change_lists[0]->set_largest_changestamp(16815); |  | 
|  311  |  | 
|  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)); |  | 
|  317  |  | 
|  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")); |  | 
|  324  |  | 
|  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"))); |  | 
|  330 } |  | 
|  331  |  | 
|  332 TEST_F(ChangeListProcessorTest, DeltaFileRenamedInDirectory) { |  | 
|  333   ScopedVector<ChangeList> change_lists; |  | 
|  334   change_lists.push_back(new ChangeList); |  | 
|  335  |  | 
|  336   ResourceEntry entry; |  | 
|  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"); |  | 
|  342  |  | 
|  343   change_lists[0]->set_largest_changestamp(16767); |  | 
|  344  |  | 
|  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"))); |  | 
|  355  |  | 
|  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); |  | 
|  364  |  | 
|  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()); |  | 
|  369 } |  | 
|  370  |  | 
|  371 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileInRoot) { |  | 
|  372   // Create ChangeList to add a file. |  | 
|  373   ScopedVector<ChangeList> change_lists; |  | 
|  374   change_lists.push_back(new ChangeList); |  | 
|  375  |  | 
|  376   ResourceEntry entry; |  | 
|  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); |  | 
|  381  |  | 
|  382   change_lists[0]->set_largest_changestamp(16683); |  | 
|  383  |  | 
|  384   // Apply. |  | 
|  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)); |  | 
|  389  |  | 
|  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"))); |  | 
|  397  |  | 
|  398   // Create ChangeList to delete the file. |  | 
|  399   change_lists.push_back(new ChangeList); |  | 
|  400  |  | 
|  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); |  | 
|  404  |  | 
|  405   change_lists[0]->set_largest_changestamp(16687); |  | 
|  406  |  | 
|  407   // Apply. |  | 
|  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"))); |  | 
|  416 } |  | 
|  417  |  | 
|  418  |  | 
|  419 TEST_F(ChangeListProcessorTest, DeltaAddAndDeleteFileFromExistingDirectory) { |  | 
|  420   // Create ChangeList to add a file. |  | 
|  421   ScopedVector<ChangeList> change_lists; |  | 
|  422   change_lists.push_back(new ChangeList); |  | 
|  423  |  | 
|  424   ResourceEntry entry; |  | 
|  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"); |  | 
|  430  |  | 
|  431   change_lists[0]->set_largest_changestamp(16730); |  | 
|  432  |  | 
|  433   // Apply. |  | 
|  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")); |  | 
|  442  |  | 
|  443   EXPECT_EQ(1U, changed_files.size()); |  | 
|  444   EXPECT_TRUE(changed_files.count( |  | 
|  445       base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt"))); |  | 
|  446  |  | 
|  447   // Create ChangeList to delete the file. |  | 
|  448   change_lists.push_back(new ChangeList); |  | 
|  449  |  | 
|  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"); |  | 
|  454  |  | 
|  455   change_lists[0]->set_largest_changestamp(16770); |  | 
|  456  |  | 
|  457   // Apply. |  | 
|  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")); |  | 
|  463  |  | 
|  464   EXPECT_EQ(1U, changed_files.size()); |  | 
|  465   EXPECT_TRUE(changed_files.count( |  | 
|  466       base::FilePath::FromUTF8Unsafe("drive/root/Directory 1/Added file.txt"))); |  | 
|  467 } |  | 
|  468  |  | 
|  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); |  | 
|  476  |  | 
|  477   ResourceEntry file; |  | 
|  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"); |  | 
|  484  |  | 
|  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); |  | 
|  492  |  | 
|  493   change_lists[0]->set_largest_changestamp(16730); |  | 
|  494  |  | 
|  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)); |  | 
|  500  |  | 
|  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")); |  | 
|  505  |  | 
|  506   EXPECT_TRUE(changed_files.empty()); |  | 
|  507 } |  | 
|  508  |  | 
|  509 TEST_F(ChangeListProcessorTest, RefreshDirectory) { |  | 
|  510   // Prepare metadata. |  | 
|  511   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); |  | 
|  512  |  | 
|  513   // Create change list. |  | 
|  514   scoped_ptr<ChangeList> change_list(new ChangeList); |  | 
|  515  |  | 
|  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); |  | 
|  522  |  | 
|  523   // Add "Directory 1" to the map with a new name. |  | 
|  524   ResourceEntry dir1; |  | 
|  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); |  | 
|  530  |  | 
|  531   // Update the directory with the map. |  | 
|  532   ResourceEntry root; |  | 
|  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( |  | 
|  538       metadata_.get(), |  | 
|  539       DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp), |  | 
|  540       change_list.Pass(), |  | 
|  541       &refreshed_entries)); |  | 
|  542  |  | 
|  543   // "new_file" should be added. |  | 
|  544   ResourceEntry entry; |  | 
|  545   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( |  | 
|  546       util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry)); |  | 
|  547  |  | 
|  548   // "Directory 1" should be renamed. |  | 
|  549   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( |  | 
|  550       util::GetDriveMyDriveRootPath().AppendASCII(dir1.title()), &entry)); |  | 
|  551 } |  | 
|  552  |  | 
|  553 TEST_F(ChangeListProcessorTest, RefreshDirectory_WrongParentId) { |  | 
|  554   // Prepare metadata. |  | 
|  555   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); |  | 
|  556  |  | 
|  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); |  | 
|  566  |  | 
|  567  |  | 
|  568   // Update the directory. |  | 
|  569   ResourceEntry root; |  | 
|  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( |  | 
|  575       metadata_.get(), |  | 
|  576       DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp), |  | 
|  577       change_list.Pass(), |  | 
|  578       &refreshed_entries)); |  | 
|  579  |  | 
|  580   // "new_file" should not be added. |  | 
|  581   ResourceEntry entry; |  | 
|  582   EXPECT_EQ(FILE_ERROR_NOT_FOUND, metadata_->GetResourceEntryByPath( |  | 
|  583       util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry)); |  | 
|  584 } |  | 
|  585  |  | 
|  586 TEST_F(ChangeListProcessorTest, SharedFilesWithNoParentInFeed) { |  | 
|  587   // Prepare metadata. |  | 
|  588   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); |  | 
|  589  |  | 
|  590   // Create change lists. |  | 
|  591   ScopedVector<ChangeList> change_lists; |  | 
|  592   change_lists.push_back(new ChangeList); |  | 
|  593  |  | 
|  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); |  | 
|  601  |  | 
|  602   FileChange changed_files; |  | 
|  603   EXPECT_EQ(FILE_ERROR_OK, |  | 
|  604             ApplyChangeList(change_lists.Pass(), &changed_files)); |  | 
|  605  |  | 
|  606   // "new_file" should be added under drive/other. |  | 
|  607   ResourceEntry entry; |  | 
|  608   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( |  | 
|  609       util::GetDriveGrandRootPath().AppendASCII("other/new_file"), &entry)); |  | 
|  610 } |  | 
|  611  |  | 
|  612 TEST_F(ChangeListProcessorTest, ModificationDate) { |  | 
|  613   // Prepare metadata. |  | 
|  614   EXPECT_EQ(FILE_ERROR_OK, ApplyFullResourceList(CreateBaseChangeList())); |  | 
|  615  |  | 
|  616   // Create change lists with a new file. |  | 
|  617   ScopedVector<ChangeList> change_lists; |  | 
|  618   change_lists.push_back(new ChangeList); |  | 
|  619  |  | 
|  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()); |  | 
|  625  |  | 
|  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); |  | 
|  629  |  | 
|  630   // Add the same file locally, but with a different name, a dirty metadata |  | 
|  631   // state, and a newer modification date. |  | 
|  632   ResourceEntry root; |  | 
|  633   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath( |  | 
|  634       util::GetDriveMyDriveRootPath(), &root)); |  | 
|  635  |  | 
|  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)); |  | 
|  645  |  | 
|  646   // Apply the change. |  | 
|  647   FileChange changed_files; |  | 
|  648   EXPECT_EQ(FILE_ERROR_OK, |  | 
|  649             ApplyChangeList(change_lists.Pass(), &changed_files)); |  | 
|  650  |  | 
|  651   // The change is rejected due to the old modification date. |  | 
|  652   ResourceEntry entry; |  | 
|  653   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryById(local_id, &entry)); |  | 
|  654   EXPECT_EQ(new_file_local.title(), entry.title()); |  | 
|  655 } |  | 
|  656  |  | 
|  657 }  // namespace internal |  | 
|  658 }  // namespace drive |  | 
| OLD | NEW |