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