| 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/resource_metadata.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <string> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/files/scoped_temp_dir.h" | |
| 12 #include "base/single_thread_task_runner.h" | |
| 13 #include "base/strings/stringprintf.h" | |
| 14 #include "base/thread_task_runner_handle.h" | |
| 15 #include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h" | |
| 16 #include "chrome/browser/chromeos/drive/file_cache.h" | |
| 17 #include "chrome/browser/chromeos/drive/file_system_core_util.h" | |
| 18 #include "components/drive/drive.pb.h" | |
| 19 #include "components/drive/drive_test_util.h" | |
| 20 #include "content/public/test/test_browser_thread_bundle.h" | |
| 21 #include "testing/gtest/include/gtest/gtest.h" | |
| 22 | |
| 23 namespace drive { | |
| 24 namespace internal { | |
| 25 namespace { | |
| 26 | |
| 27 // The changestamp of the resource metadata used in | |
| 28 // ResourceMetadataTest. | |
| 29 const int64 kTestChangestamp = 100; | |
| 30 | |
| 31 // Returns the sorted base names from |entries|. | |
| 32 std::vector<std::string> GetSortedBaseNames( | |
| 33 const ResourceEntryVector& entries) { | |
| 34 std::vector<std::string> base_names; | |
| 35 for (size_t i = 0; i < entries.size(); ++i) | |
| 36 base_names.push_back(entries[i].base_name()); | |
| 37 std::sort(base_names.begin(), base_names.end()); | |
| 38 | |
| 39 return base_names; | |
| 40 } | |
| 41 | |
| 42 // Creates a ResourceEntry for a directory with explicitly set resource_id. | |
| 43 ResourceEntry CreateDirectoryEntryWithResourceId( | |
| 44 const std::string& title, | |
| 45 const std::string& resource_id, | |
| 46 const std::string& parent_local_id) { | |
| 47 ResourceEntry entry; | |
| 48 entry.set_title(title); | |
| 49 entry.set_resource_id(resource_id); | |
| 50 entry.set_parent_local_id(parent_local_id); | |
| 51 entry.mutable_file_info()->set_is_directory(true); | |
| 52 entry.mutable_directory_specific_info()->set_changestamp(kTestChangestamp); | |
| 53 return entry; | |
| 54 } | |
| 55 | |
| 56 // Creates a ResourceEntry for a directory. | |
| 57 ResourceEntry CreateDirectoryEntry(const std::string& title, | |
| 58 const std::string& parent_local_id) { | |
| 59 return CreateDirectoryEntryWithResourceId( | |
| 60 title, "id:" + title, parent_local_id); | |
| 61 } | |
| 62 | |
| 63 // Creates a ResourceEntry for a file with explicitly set resource_id. | |
| 64 ResourceEntry CreateFileEntryWithResourceId( | |
| 65 const std::string& title, | |
| 66 const std::string& resource_id, | |
| 67 const std::string& parent_local_id) { | |
| 68 ResourceEntry entry; | |
| 69 entry.set_title(title); | |
| 70 entry.set_resource_id(resource_id); | |
| 71 entry.set_parent_local_id(parent_local_id); | |
| 72 entry.mutable_file_info()->set_is_directory(false); | |
| 73 entry.mutable_file_info()->set_size(1024); | |
| 74 entry.mutable_file_specific_info()->set_md5("md5:" + title); | |
| 75 return entry; | |
| 76 } | |
| 77 | |
| 78 // Creates a ResourceEntry for a file. | |
| 79 ResourceEntry CreateFileEntry(const std::string& title, | |
| 80 const std::string& parent_local_id) { | |
| 81 return CreateFileEntryWithResourceId(title, "id:" + title, parent_local_id); | |
| 82 } | |
| 83 | |
| 84 // Creates the following files/directories | |
| 85 // drive/root/dir1/ | |
| 86 // drive/root/dir2/ | |
| 87 // drive/root/dir1/dir3/ | |
| 88 // drive/root/dir1/file4 | |
| 89 // drive/root/dir1/file5 | |
| 90 // drive/root/dir2/file6 | |
| 91 // drive/root/dir2/file7 | |
| 92 // drive/root/dir2/file8 | |
| 93 // drive/root/dir1/dir3/file9 | |
| 94 // drive/root/dir1/dir3/file10 | |
| 95 void SetUpEntries(ResourceMetadata* resource_metadata) { | |
| 96 std::string local_id; | |
| 97 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->GetIdByPath( | |
| 98 util::GetDriveMyDriveRootPath(), &local_id)); | |
| 99 const std::string root_local_id = local_id; | |
| 100 | |
| 101 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 102 CreateDirectoryEntry("dir1", root_local_id), &local_id)); | |
| 103 const std::string local_id_dir1 = local_id; | |
| 104 | |
| 105 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 106 CreateDirectoryEntry("dir2", root_local_id), &local_id)); | |
| 107 const std::string local_id_dir2 = local_id; | |
| 108 | |
| 109 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 110 CreateDirectoryEntry("dir3", local_id_dir1), &local_id)); | |
| 111 const std::string local_id_dir3 = local_id; | |
| 112 | |
| 113 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 114 CreateFileEntry("file4", local_id_dir1), &local_id)); | |
| 115 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 116 CreateFileEntry("file5", local_id_dir1), &local_id)); | |
| 117 | |
| 118 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 119 CreateFileEntry("file6", local_id_dir2), &local_id)); | |
| 120 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 121 CreateFileEntry("file7", local_id_dir2), &local_id)); | |
| 122 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 123 CreateFileEntry("file8", local_id_dir2), &local_id)); | |
| 124 | |
| 125 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 126 CreateFileEntry("file9", local_id_dir3), &local_id)); | |
| 127 ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry( | |
| 128 CreateFileEntry("file10", local_id_dir3), &local_id)); | |
| 129 | |
| 130 ASSERT_EQ(FILE_ERROR_OK, | |
| 131 resource_metadata->SetLargestChangestamp(kTestChangestamp)); | |
| 132 } | |
| 133 | |
| 134 } // namespace | |
| 135 | |
| 136 // Tests for methods running on the blocking task runner. | |
| 137 class ResourceMetadataTest : public testing::Test { | |
| 138 protected: | |
| 139 void SetUp() override { | |
| 140 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
| 141 | |
| 142 metadata_storage_.reset(new ResourceMetadataStorage( | |
| 143 temp_dir_.path(), base::ThreadTaskRunnerHandle::Get().get())); | |
| 144 ASSERT_TRUE(metadata_storage_->Initialize()); | |
| 145 | |
| 146 fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter); | |
| 147 cache_.reset(new FileCache(metadata_storage_.get(), | |
| 148 temp_dir_.path(), | |
| 149 base::ThreadTaskRunnerHandle::Get().get(), | |
| 150 fake_free_disk_space_getter_.get())); | |
| 151 ASSERT_TRUE(cache_->Initialize()); | |
| 152 | |
| 153 resource_metadata_.reset(new ResourceMetadata( | |
| 154 metadata_storage_.get(), cache_.get(), | |
| 155 base::ThreadTaskRunnerHandle::Get())); | |
| 156 | |
| 157 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->Initialize()); | |
| 158 | |
| 159 SetUpEntries(resource_metadata_.get()); | |
| 160 } | |
| 161 | |
| 162 base::ScopedTempDir temp_dir_; | |
| 163 content::TestBrowserThreadBundle thread_bundle_; | |
| 164 scoped_ptr<ResourceMetadataStorage, test_util::DestroyHelperForTests> | |
| 165 metadata_storage_; | |
| 166 scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_; | |
| 167 scoped_ptr<FileCache, test_util::DestroyHelperForTests> cache_; | |
| 168 scoped_ptr<ResourceMetadata, test_util::DestroyHelperForTests> | |
| 169 resource_metadata_; | |
| 170 }; | |
| 171 | |
| 172 TEST_F(ResourceMetadataTest, LargestChangestamp) { | |
| 173 const int64 kChangestamp = 123456; | |
| 174 EXPECT_EQ(FILE_ERROR_OK, | |
| 175 resource_metadata_->SetLargestChangestamp(kChangestamp)); | |
| 176 int64 changestamp = 0; | |
| 177 EXPECT_EQ(FILE_ERROR_OK, | |
| 178 resource_metadata_->GetLargestChangestamp(&changestamp)); | |
| 179 EXPECT_EQ(kChangestamp, changestamp); | |
| 180 } | |
| 181 | |
| 182 TEST_F(ResourceMetadataTest, GetResourceEntryByPath) { | |
| 183 // Confirm that an existing file is found. | |
| 184 ResourceEntry entry; | |
| 185 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 186 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry)); | |
| 187 EXPECT_EQ("file4", entry.base_name()); | |
| 188 | |
| 189 // Confirm that a non existing file is not found. | |
| 190 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath( | |
| 191 base::FilePath::FromUTF8Unsafe("drive/root/dir1/non_existing"), &entry)); | |
| 192 | |
| 193 // Confirm that the root is found. | |
| 194 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 195 base::FilePath::FromUTF8Unsafe("drive"), &entry)); | |
| 196 | |
| 197 // Confirm that a non existing file is not found at the root level. | |
| 198 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath( | |
| 199 base::FilePath::FromUTF8Unsafe("non_existing"), &entry)); | |
| 200 | |
| 201 // Confirm that an entry is not found with a wrong root. | |
| 202 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath( | |
| 203 base::FilePath::FromUTF8Unsafe("non_existing/root"), &entry)); | |
| 204 } | |
| 205 | |
| 206 TEST_F(ResourceMetadataTest, ReadDirectoryByPath) { | |
| 207 // Confirm that an existing directory is found. | |
| 208 ResourceEntryVector entries; | |
| 209 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->ReadDirectoryByPath( | |
| 210 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &entries)); | |
| 211 ASSERT_EQ(3U, entries.size()); | |
| 212 // The order is not guaranteed so we should sort the base names. | |
| 213 std::vector<std::string> base_names = GetSortedBaseNames(entries); | |
| 214 EXPECT_EQ("dir3", base_names[0]); | |
| 215 EXPECT_EQ("file4", base_names[1]); | |
| 216 EXPECT_EQ("file5", base_names[2]); | |
| 217 | |
| 218 // Confirm that a non existing directory is not found. | |
| 219 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->ReadDirectoryByPath( | |
| 220 base::FilePath::FromUTF8Unsafe("drive/root/non_existing"), &entries)); | |
| 221 | |
| 222 // Confirm that reading a file results in FILE_ERROR_NOT_A_DIRECTORY. | |
| 223 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, resource_metadata_->ReadDirectoryByPath( | |
| 224 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entries)); | |
| 225 } | |
| 226 | |
| 227 TEST_F(ResourceMetadataTest, RefreshEntry) { | |
| 228 base::FilePath drive_file_path; | |
| 229 ResourceEntry entry; | |
| 230 | |
| 231 // Get file9. | |
| 232 std::string file_id; | |
| 233 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 234 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &file_id)); | |
| 235 EXPECT_EQ(FILE_ERROR_OK, | |
| 236 resource_metadata_->GetResourceEntryById(file_id, &entry)); | |
| 237 EXPECT_EQ("file9", entry.base_name()); | |
| 238 EXPECT_TRUE(!entry.file_info().is_directory()); | |
| 239 EXPECT_EQ("md5:file9", entry.file_specific_info().md5()); | |
| 240 | |
| 241 // Rename it. | |
| 242 ResourceEntry file_entry(entry); | |
| 243 file_entry.set_title("file100"); | |
| 244 EXPECT_EQ(FILE_ERROR_OK, | |
| 245 resource_metadata_->RefreshEntry(file_entry)); | |
| 246 | |
| 247 base::FilePath path; | |
| 248 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetFilePath(file_id, &path)); | |
| 249 EXPECT_EQ("drive/root/dir1/dir3/file100", path.AsUTF8Unsafe()); | |
| 250 entry.Clear(); | |
| 251 EXPECT_EQ(FILE_ERROR_OK, | |
| 252 resource_metadata_->GetResourceEntryById(file_id, &entry)); | |
| 253 EXPECT_EQ("file100", entry.base_name()); | |
| 254 EXPECT_TRUE(!entry.file_info().is_directory()); | |
| 255 EXPECT_EQ("md5:file9", entry.file_specific_info().md5()); | |
| 256 | |
| 257 // Update the file md5. | |
| 258 const std::string updated_md5("md5:updated"); | |
| 259 file_entry = entry; | |
| 260 file_entry.mutable_file_specific_info()->set_md5(updated_md5); | |
| 261 EXPECT_EQ(FILE_ERROR_OK, | |
| 262 resource_metadata_->RefreshEntry(file_entry)); | |
| 263 | |
| 264 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetFilePath(file_id, &path)); | |
| 265 EXPECT_EQ("drive/root/dir1/dir3/file100", path.AsUTF8Unsafe()); | |
| 266 entry.Clear(); | |
| 267 EXPECT_EQ(FILE_ERROR_OK, | |
| 268 resource_metadata_->GetResourceEntryById(file_id, &entry)); | |
| 269 EXPECT_EQ("file100", entry.base_name()); | |
| 270 EXPECT_TRUE(!entry.file_info().is_directory()); | |
| 271 EXPECT_EQ(updated_md5, entry.file_specific_info().md5()); | |
| 272 | |
| 273 // Make sure we get the same thing from GetResourceEntryByPath. | |
| 274 entry.Clear(); | |
| 275 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 276 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file100"), &entry)); | |
| 277 EXPECT_EQ("file100", entry.base_name()); | |
| 278 ASSERT_TRUE(!entry.file_info().is_directory()); | |
| 279 EXPECT_EQ(updated_md5, entry.file_specific_info().md5()); | |
| 280 | |
| 281 // Get dir2. | |
| 282 entry.Clear(); | |
| 283 std::string dir_id; | |
| 284 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 285 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &dir_id)); | |
| 286 EXPECT_EQ(FILE_ERROR_OK, | |
| 287 resource_metadata_->GetResourceEntryById(dir_id, &entry)); | |
| 288 EXPECT_EQ("dir2", entry.base_name()); | |
| 289 ASSERT_TRUE(entry.file_info().is_directory()); | |
| 290 | |
| 291 // Get dir3's ID. | |
| 292 std::string dir3_id; | |
| 293 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 294 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_id)); | |
| 295 | |
| 296 // Change the name to dir100 and change the parent to drive/dir1/dir3. | |
| 297 ResourceEntry dir_entry(entry); | |
| 298 dir_entry.set_title("dir100"); | |
| 299 dir_entry.set_parent_local_id(dir3_id); | |
| 300 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(dir_entry)); | |
| 301 | |
| 302 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetFilePath(dir_id, &path)); | |
| 303 EXPECT_EQ("drive/root/dir1/dir3/dir100", path.AsUTF8Unsafe()); | |
| 304 entry.Clear(); | |
| 305 EXPECT_EQ(FILE_ERROR_OK, | |
| 306 resource_metadata_->GetResourceEntryById(dir_id, &entry)); | |
| 307 EXPECT_EQ("dir100", entry.base_name()); | |
| 308 EXPECT_TRUE(entry.file_info().is_directory()); | |
| 309 EXPECT_EQ("id:dir2", entry.resource_id()); | |
| 310 | |
| 311 // Make sure the children have moved over. Test file6. | |
| 312 entry.Clear(); | |
| 313 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 314 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/dir100/file6"), | |
| 315 &entry)); | |
| 316 EXPECT_EQ("file6", entry.base_name()); | |
| 317 | |
| 318 // Make sure dir2 no longer exists. | |
| 319 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryByPath( | |
| 320 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &entry)); | |
| 321 | |
| 322 // Make sure that directory cannot move under a file. | |
| 323 dir_entry.set_parent_local_id(file_id); | |
| 324 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, | |
| 325 resource_metadata_->RefreshEntry(dir_entry)); | |
| 326 | |
| 327 // Cannot refresh root. | |
| 328 dir_entry.Clear(); | |
| 329 dir_entry.set_local_id(util::kDriveGrandRootLocalId); | |
| 330 dir_entry.set_title("new-root-name"); | |
| 331 dir_entry.set_parent_local_id(dir3_id); | |
| 332 EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, | |
| 333 resource_metadata_->RefreshEntry(dir_entry)); | |
| 334 } | |
| 335 | |
| 336 TEST_F(ResourceMetadataTest, RefreshEntry_ResourceIDCheck) { | |
| 337 // Get an entry with a non-empty resource ID. | |
| 338 ResourceEntry entry; | |
| 339 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 340 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &entry)); | |
| 341 EXPECT_FALSE(entry.resource_id().empty()); | |
| 342 | |
| 343 // Add a new entry with an empty resource ID. | |
| 344 ResourceEntry new_entry; | |
| 345 new_entry.set_parent_local_id(entry.local_id()); | |
| 346 new_entry.set_title("new entry"); | |
| 347 std::string local_id; | |
| 348 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(new_entry, &local_id)); | |
| 349 | |
| 350 // Try to refresh the new entry with a used resource ID. | |
| 351 new_entry.set_local_id(local_id); | |
| 352 new_entry.set_resource_id(entry.resource_id()); | |
| 353 EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, | |
| 354 resource_metadata_->RefreshEntry(new_entry)); | |
| 355 } | |
| 356 | |
| 357 TEST_F(ResourceMetadataTest, RefreshEntry_DoNotOverwriteCacheState) { | |
| 358 ResourceEntry entry; | |
| 359 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 360 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry)); | |
| 361 | |
| 362 // Try to set MD5 with RefreshEntry. | |
| 363 entry.mutable_file_specific_info()->mutable_cache_state()->set_md5("md5"); | |
| 364 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(entry)); | |
| 365 | |
| 366 // Cache state is unchanged. | |
| 367 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 368 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry)); | |
| 369 EXPECT_TRUE(entry.file_specific_info().cache_state().md5().empty()); | |
| 370 | |
| 371 // Pin the file. | |
| 372 EXPECT_EQ(FILE_ERROR_OK, cache_->Pin(entry.local_id())); | |
| 373 | |
| 374 // Try to clear the cache state with RefreshEntry. | |
| 375 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 376 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry)); | |
| 377 entry.mutable_file_specific_info()->clear_cache_state(); | |
| 378 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RefreshEntry(entry)); | |
| 379 | |
| 380 // Cache state is not cleared. | |
| 381 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 382 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &entry)); | |
| 383 EXPECT_TRUE(entry.file_specific_info().cache_state().is_pinned()); | |
| 384 } | |
| 385 | |
| 386 TEST_F(ResourceMetadataTest, GetSubDirectoriesRecursively) { | |
| 387 std::set<base::FilePath> sub_directories; | |
| 388 | |
| 389 // file9: not a directory, so no children. | |
| 390 std::string local_id; | |
| 391 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 392 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), &local_id)); | |
| 393 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetSubDirectoriesRecursively( | |
| 394 local_id, &sub_directories)); | |
| 395 EXPECT_TRUE(sub_directories.empty()); | |
| 396 | |
| 397 // dir2: no child directories. | |
| 398 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 399 base::FilePath::FromUTF8Unsafe("drive/root/dir2"), &local_id)); | |
| 400 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetSubDirectoriesRecursively( | |
| 401 local_id, &sub_directories)); | |
| 402 EXPECT_TRUE(sub_directories.empty()); | |
| 403 const std::string dir2_id = local_id; | |
| 404 | |
| 405 // dir1: dir3 is the only child | |
| 406 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 407 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id)); | |
| 408 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetSubDirectoriesRecursively( | |
| 409 local_id, &sub_directories)); | |
| 410 EXPECT_EQ(1u, sub_directories.size()); | |
| 411 EXPECT_EQ(1u, sub_directories.count( | |
| 412 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"))); | |
| 413 sub_directories.clear(); | |
| 414 | |
| 415 // Add a few more directories to make sure deeper nesting works. | |
| 416 // dir2/dir100 | |
| 417 // dir2/dir101 | |
| 418 // dir2/dir101/dir102 | |
| 419 // dir2/dir101/dir103 | |
| 420 // dir2/dir101/dir104 | |
| 421 // dir2/dir101/dir104/dir105 | |
| 422 // dir2/dir101/dir104/dir105/dir106 | |
| 423 // dir2/dir101/dir104/dir105/dir106/dir107 | |
| 424 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 425 CreateDirectoryEntry("dir100", dir2_id), &local_id)); | |
| 426 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 427 CreateDirectoryEntry("dir101", dir2_id), &local_id)); | |
| 428 const std::string dir101_id = local_id; | |
| 429 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 430 CreateDirectoryEntry("dir102", dir101_id), &local_id)); | |
| 431 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 432 CreateDirectoryEntry("dir103", dir101_id), &local_id)); | |
| 433 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 434 CreateDirectoryEntry("dir104", dir101_id), &local_id)); | |
| 435 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 436 CreateDirectoryEntry("dir105", local_id), &local_id)); | |
| 437 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 438 CreateDirectoryEntry("dir106", local_id), &local_id)); | |
| 439 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 440 CreateDirectoryEntry("dir107", local_id), &local_id)); | |
| 441 | |
| 442 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetSubDirectoriesRecursively( | |
| 443 dir2_id, &sub_directories)); | |
| 444 EXPECT_EQ(8u, sub_directories.size()); | |
| 445 EXPECT_EQ(1u, sub_directories.count(base::FilePath::FromUTF8Unsafe( | |
| 446 "drive/root/dir2/dir101"))); | |
| 447 EXPECT_EQ(1u, sub_directories.count(base::FilePath::FromUTF8Unsafe( | |
| 448 "drive/root/dir2/dir101/dir104"))); | |
| 449 EXPECT_EQ(1u, sub_directories.count(base::FilePath::FromUTF8Unsafe( | |
| 450 "drive/root/dir2/dir101/dir104/dir105/dir106/dir107"))); | |
| 451 } | |
| 452 | |
| 453 TEST_F(ResourceMetadataTest, AddEntry) { | |
| 454 // Add a file to dir3. | |
| 455 std::string local_id; | |
| 456 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 457 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &local_id)); | |
| 458 ResourceEntry file_entry = CreateFileEntry("file100", local_id); | |
| 459 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(file_entry, &local_id)); | |
| 460 base::FilePath path; | |
| 461 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetFilePath(local_id, &path)); | |
| 462 EXPECT_EQ("drive/root/dir1/dir3/file100", path.AsUTF8Unsafe()); | |
| 463 | |
| 464 // Add a directory. | |
| 465 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 466 base::FilePath::FromUTF8Unsafe("drive/root/dir1"), &local_id)); | |
| 467 ResourceEntry dir_entry = CreateDirectoryEntry("dir101", local_id); | |
| 468 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry(dir_entry, &local_id)); | |
| 469 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetFilePath(local_id, &path)); | |
| 470 EXPECT_EQ("drive/root/dir1/dir101", path.AsUTF8Unsafe()); | |
| 471 | |
| 472 // Add to an invalid parent. | |
| 473 ResourceEntry file_entry3 = CreateFileEntry("file103", "id:invalid"); | |
| 474 EXPECT_EQ(FILE_ERROR_NOT_FOUND, | |
| 475 resource_metadata_->AddEntry(file_entry3, &local_id)); | |
| 476 | |
| 477 // Add an existing file. | |
| 478 EXPECT_EQ(FILE_ERROR_EXISTS, | |
| 479 resource_metadata_->AddEntry(file_entry, &local_id)); | |
| 480 } | |
| 481 | |
| 482 TEST_F(ResourceMetadataTest, RemoveEntry) { | |
| 483 // Make sure file9 is found. | |
| 484 std::string file9_local_id; | |
| 485 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 486 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3/file9"), | |
| 487 &file9_local_id)); | |
| 488 ResourceEntry entry; | |
| 489 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 490 file9_local_id, &entry)); | |
| 491 EXPECT_EQ("file9", entry.base_name()); | |
| 492 | |
| 493 // Remove file9. | |
| 494 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RemoveEntry(file9_local_id)); | |
| 495 | |
| 496 // file9 should no longer exist. | |
| 497 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById( | |
| 498 file9_local_id, &entry)); | |
| 499 | |
| 500 // Look for dir3. | |
| 501 std::string dir3_local_id; | |
| 502 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 503 base::FilePath::FromUTF8Unsafe("drive/root/dir1/dir3"), &dir3_local_id)); | |
| 504 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 505 dir3_local_id, &entry)); | |
| 506 EXPECT_EQ("dir3", entry.base_name()); | |
| 507 | |
| 508 // Remove dir3. | |
| 509 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->RemoveEntry(dir3_local_id)); | |
| 510 | |
| 511 // dir3 should no longer exist. | |
| 512 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById( | |
| 513 dir3_local_id, &entry)); | |
| 514 | |
| 515 // Remove unknown local_id using RemoveEntry. | |
| 516 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->RemoveEntry("foo")); | |
| 517 | |
| 518 // Try removing root. This should fail. | |
| 519 EXPECT_EQ(FILE_ERROR_ACCESS_DENIED, resource_metadata_->RemoveEntry( | |
| 520 util::kDriveGrandRootLocalId)); | |
| 521 } | |
| 522 | |
| 523 TEST_F(ResourceMetadataTest, GetResourceEntryById_RootDirectory) { | |
| 524 // Look up the root directory by its ID. | |
| 525 ResourceEntry entry; | |
| 526 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 527 util::kDriveGrandRootLocalId, &entry)); | |
| 528 EXPECT_EQ("drive", entry.base_name()); | |
| 529 } | |
| 530 | |
| 531 TEST_F(ResourceMetadataTest, GetResourceEntryById) { | |
| 532 // Get file4 by path. | |
| 533 std::string local_id; | |
| 534 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 535 base::FilePath::FromUTF8Unsafe("drive/root/dir1/file4"), &local_id)); | |
| 536 | |
| 537 // Confirm that an existing file is found. | |
| 538 ResourceEntry entry; | |
| 539 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 540 local_id, &entry)); | |
| 541 EXPECT_EQ("file4", entry.base_name()); | |
| 542 | |
| 543 // Confirm that a non existing file is not found. | |
| 544 EXPECT_EQ(FILE_ERROR_NOT_FOUND, resource_metadata_->GetResourceEntryById( | |
| 545 "non_existing", &entry)); | |
| 546 } | |
| 547 | |
| 548 TEST_F(ResourceMetadataTest, Iterate) { | |
| 549 scoped_ptr<ResourceMetadata::Iterator> it = resource_metadata_->GetIterator(); | |
| 550 ASSERT_TRUE(it); | |
| 551 | |
| 552 int file_count = 0, directory_count = 0; | |
| 553 for (; !it->IsAtEnd(); it->Advance()) { | |
| 554 if (!it->GetValue().file_info().is_directory()) | |
| 555 ++file_count; | |
| 556 else | |
| 557 ++directory_count; | |
| 558 } | |
| 559 | |
| 560 EXPECT_EQ(7, file_count); | |
| 561 EXPECT_EQ(7, directory_count); | |
| 562 } | |
| 563 | |
| 564 TEST_F(ResourceMetadataTest, DuplicatedNames) { | |
| 565 std::string root_local_id; | |
| 566 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 567 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id)); | |
| 568 | |
| 569 ResourceEntry entry; | |
| 570 | |
| 571 // When multiple entries with the same title are added in a single directory, | |
| 572 // their base_names are de-duped. | |
| 573 // - drive/root/foo | |
| 574 // - drive/root/foo (1) | |
| 575 std::string dir_id_0; | |
| 576 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 577 CreateDirectoryEntryWithResourceId( | |
| 578 "foo", "foo0", root_local_id), &dir_id_0)); | |
| 579 std::string dir_id_1; | |
| 580 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 581 CreateDirectoryEntryWithResourceId( | |
| 582 "foo", "foo1", root_local_id), &dir_id_1)); | |
| 583 | |
| 584 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 585 dir_id_0, &entry)); | |
| 586 EXPECT_EQ("foo", entry.base_name()); | |
| 587 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 588 dir_id_1, &entry)); | |
| 589 EXPECT_EQ("foo (1)", entry.base_name()); | |
| 590 | |
| 591 // - drive/root/foo/bar.txt | |
| 592 // - drive/root/foo/bar (1).txt | |
| 593 // - drive/root/foo/bar (2).txt | |
| 594 // ... | |
| 595 // - drive/root/foo/bar (99).txt | |
| 596 std::vector<std::string> file_ids(100); | |
| 597 for (size_t i = 0; i < file_ids.size(); ++i) { | |
| 598 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 599 CreateFileEntryWithResourceId( | |
| 600 "bar.txt", base::StringPrintf("bar%d", static_cast<int>(i)), | |
| 601 dir_id_0), &file_ids[i])); | |
| 602 } | |
| 603 | |
| 604 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 605 file_ids[0], &entry)); | |
| 606 EXPECT_EQ("bar.txt", entry.base_name()); | |
| 607 for (size_t i = 1; i < file_ids.size(); ++i) { | |
| 608 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 609 file_ids[i], &entry)) << i; | |
| 610 EXPECT_EQ(base::StringPrintf("bar (%d).txt", static_cast<int>(i)), | |
| 611 entry.base_name()); | |
| 612 } | |
| 613 | |
| 614 // Same name but different parent. No renaming. | |
| 615 // - drive/root/foo (1)/bar.txt | |
| 616 std::string file_id_3; | |
| 617 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 618 CreateFileEntryWithResourceId( | |
| 619 "bar.txt", "bar_different_parent", dir_id_1), &file_id_3)); | |
| 620 | |
| 621 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 622 file_id_3, &entry)); | |
| 623 EXPECT_EQ("bar.txt", entry.base_name()); | |
| 624 | |
| 625 // Checks that the entries can be looked up by the de-duped paths. | |
| 626 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 627 base::FilePath::FromUTF8Unsafe("drive/root/foo/bar (2).txt"), &entry)); | |
| 628 EXPECT_EQ("bar2", entry.resource_id()); | |
| 629 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 630 base::FilePath::FromUTF8Unsafe("drive/root/foo (1)/bar.txt"), &entry)); | |
| 631 EXPECT_EQ("bar_different_parent", entry.resource_id()); | |
| 632 } | |
| 633 | |
| 634 TEST_F(ResourceMetadataTest, EncodedNames) { | |
| 635 std::string root_local_id; | |
| 636 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetIdByPath( | |
| 637 base::FilePath::FromUTF8Unsafe("drive/root"), &root_local_id)); | |
| 638 | |
| 639 ResourceEntry entry; | |
| 640 | |
| 641 std::string dir_id; | |
| 642 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 643 CreateDirectoryEntry("\\(^o^)/", root_local_id), &dir_id)); | |
| 644 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 645 dir_id, &entry)); | |
| 646 EXPECT_EQ("\\(^o^)_", entry.base_name()); | |
| 647 | |
| 648 std::string file_id; | |
| 649 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->AddEntry( | |
| 650 CreateFileEntryWithResourceId("Slash /.txt", "myfile", dir_id), | |
| 651 &file_id)); | |
| 652 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryById( | |
| 653 file_id, &entry)); | |
| 654 EXPECT_EQ("Slash _.txt", entry.base_name()); | |
| 655 | |
| 656 ASSERT_EQ(FILE_ERROR_OK, resource_metadata_->GetResourceEntryByPath( | |
| 657 base::FilePath::FromUTF8Unsafe( | |
| 658 "drive/root/\\(^o^)_/Slash _.txt"), | |
| 659 &entry)); | |
| 660 EXPECT_EQ("myfile", entry.resource_id()); | |
| 661 } | |
| 662 | |
| 663 TEST_F(ResourceMetadataTest, Reset) { | |
| 664 // The grand root has "root" which is not empty. | |
| 665 std::vector<ResourceEntry> entries; | |
| 666 ASSERT_EQ(FILE_ERROR_OK, | |
| 667 resource_metadata_->ReadDirectoryByPath( | |
| 668 base::FilePath::FromUTF8Unsafe("drive/root"), &entries)); | |
| 669 ASSERT_FALSE(entries.empty()); | |
| 670 | |
| 671 // Reset. | |
| 672 EXPECT_EQ(FILE_ERROR_OK, resource_metadata_->Reset()); | |
| 673 | |
| 674 // change stamp should be reset. | |
| 675 int64 changestamp = 0; | |
| 676 EXPECT_EQ(FILE_ERROR_OK, | |
| 677 resource_metadata_->GetLargestChangestamp(&changestamp)); | |
| 678 EXPECT_EQ(0, changestamp); | |
| 679 | |
| 680 // root should continue to exist. | |
| 681 ResourceEntry entry; | |
| 682 ASSERT_EQ(FILE_ERROR_OK, | |
| 683 resource_metadata_->GetResourceEntryByPath( | |
| 684 base::FilePath::FromUTF8Unsafe("drive"), &entry)); | |
| 685 EXPECT_EQ("drive", entry.base_name()); | |
| 686 ASSERT_TRUE(entry.file_info().is_directory()); | |
| 687 EXPECT_EQ(util::kDriveGrandRootLocalId, entry.local_id()); | |
| 688 | |
| 689 // There are "other", "trash" and "root" under "drive". | |
| 690 ASSERT_EQ(FILE_ERROR_OK, | |
| 691 resource_metadata_->ReadDirectoryByPath( | |
| 692 base::FilePath::FromUTF8Unsafe("drive"), &entries)); | |
| 693 EXPECT_EQ(3U, entries.size()); | |
| 694 | |
| 695 // The "other" directory should be empty. | |
| 696 ASSERT_EQ(FILE_ERROR_OK, | |
| 697 resource_metadata_->ReadDirectoryByPath( | |
| 698 base::FilePath::FromUTF8Unsafe("drive/other"), &entries)); | |
| 699 EXPECT_TRUE(entries.empty()); | |
| 700 | |
| 701 // The "trash" directory should be empty. | |
| 702 ASSERT_EQ(FILE_ERROR_OK, | |
| 703 resource_metadata_->ReadDirectoryByPath( | |
| 704 base::FilePath::FromUTF8Unsafe("drive/trash"), &entries)); | |
| 705 EXPECT_TRUE(entries.empty()); | |
| 706 } | |
| 707 | |
| 708 } // namespace internal | |
| 709 } // namespace drive | |
| OLD | NEW |