file_system_unittest.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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/file_system.h" 6 7#include <string> 8#include <vector> 9 10#include "base/bind.h" 11#include "base/file_util.h" 12#include "base/files/file_path.h" 13#include "base/files/scoped_temp_dir.h" 14#include "base/json/json_file_value_serializer.h" 15#include "base/memory/scoped_ptr.h" 16#include "base/message_loop.h" 17#include "base/stringprintf.h" 18#include "base/threading/sequenced_worker_pool.h" 19#include "base/values.h" 20#include "chrome/browser/chromeos/drive/change_list_loader.h" 21#include "chrome/browser/chromeos/drive/drive.pb.h" 22#include "chrome/browser/chromeos/drive/drive_webapps_registry.h" 23#include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h" 24#include "chrome/browser/chromeos/drive/file_system_util.h" 25#include "chrome/browser/chromeos/drive/job_scheduler.h" 26#include "chrome/browser/chromeos/drive/mock_directory_change_observer.h" 27#include "chrome/browser/chromeos/drive/mock_file_cache_observer.h" 28#include "chrome/browser/chromeos/drive/test_util.h" 29#include "chrome/browser/google_apis/drive_api_parser.h" 30#include "chrome/browser/google_apis/fake_drive_service.h" 31#include "chrome/browser/google_apis/test_util.h" 32#include "chrome/test/base/testing_profile.h" 33#include "content/public/browser/browser_thread.h" 34#include "content/public/test/test_browser_thread.h" 35#include "testing/gmock/include/gmock/gmock.h" 36#include "testing/gtest/include/gtest/gtest.h" 37 38using ::testing::AtLeast; 39using ::testing::Eq; 40using ::testing::StrictMock; 41using ::testing::_; 42 43namespace drive { 44namespace { 45 46const int64 kLotsOfSpace = internal::kMinFreeSpace * 10; 47 48struct SearchResultPair { 49 const char* path; 50 const bool is_directory; 51}; 52 53// Callback to FileSystem::Search used in ContentSearch tests. 54// Verifies returned vector of results and next feed url. 55void DriveSearchCallback( 56 MessageLoop* message_loop, 57 const SearchResultPair* expected_results, 58 size_t expected_results_size, 59 const GURL& expected_next_feed, 60 FileError error, 61 const GURL& next_feed, 62 scoped_ptr<std::vector<SearchResultInfo> > results) { 63 ASSERT_TRUE(results); 64 ASSERT_EQ(expected_results_size, results->size()); 65 66 for (size_t i = 0; i < results->size(); i++) { 67 EXPECT_EQ(base::FilePath(expected_results[i].path), 68 results->at(i).path); 69 EXPECT_EQ(expected_results[i].is_directory, 70 results->at(i).entry.file_info().is_directory()); 71 } 72 73 EXPECT_EQ(expected_next_feed, next_feed); 74 75 message_loop->Quit(); 76} 77 78// Counts the number of files (not directories) in |entries|. 79int CountFiles(const ResourceEntryVector& entries) { 80 int num_files = 0; 81 for (size_t i = 0; i < entries.size(); ++i) { 82 if (!entries[i].file_info().is_directory()) 83 ++num_files; 84 } 85 return num_files; 86} 87 88// Counts the number of invocation, and if it increased up to |expected_counter| 89// quits the current message loop. 90void AsyncInitializationCallback( 91 int* counter, int expected_counter, MessageLoop* message_loop, 92 FileError error, scoped_ptr<ResourceEntry> entry) { 93 if (error != FILE_ERROR_OK || !entry) { 94 // If we hit an error case, quit the message loop immediately. 95 // Then the expectation in the test case can find it because the actual 96 // value of |counter| is different from the expected one. 97 message_loop->Quit(); 98 return; 99 } 100 101 (*counter)++; 102 if (*counter >= expected_counter) 103 message_loop->Quit(); 104} 105 106void AppendContent(std::vector<std::string>* buffer, 107 google_apis::GDataErrorCode error, 108 scoped_ptr<std::string> content) { 109 DCHECK_EQ(error, google_apis::HTTP_SUCCESS); 110 buffer->push_back(*content); 111} 112 113} // namespace 114 115class DriveFileSystemTest : public testing::Test { 116 protected: 117 DriveFileSystemTest() 118 : ui_thread_(content::BrowserThread::UI, &message_loop_), 119 // |root_feed_changestamp_| should be set to the largest changestamp in 120 // about resource feed. But we fake it by some non-zero positive 121 // increasing value. See |LoadFeed()|. 122 root_feed_changestamp_(1) { 123 } 124 125 virtual void SetUp() OVERRIDE { 126 profile_.reset(new TestingProfile); 127 128 // The fake object will be manually deleted in TearDown(). 129 fake_drive_service_.reset(new google_apis::FakeDriveService); 130 fake_drive_service_->LoadResourceListForWapi( 131 "chromeos/gdata/root_feed.json"); 132 fake_drive_service_->LoadAccountMetadataForWapi( 133 "chromeos/gdata/account_metadata.json"); 134 fake_drive_service_->LoadAppListForDriveApi("chromeos/drive/applist.json"); 135 136 fake_free_disk_space_getter_.reset(new FakeFreeDiskSpaceGetter); 137 138 scheduler_.reset(new JobScheduler(profile_.get(), 139 fake_drive_service_.get())); 140 141 scoped_refptr<base::SequencedWorkerPool> pool = 142 content::BrowserThread::GetBlockingPool(); 143 blocking_task_runner_ = 144 pool->GetSequencedTaskRunner(pool->GetSequenceToken()); 145 146 cache_.reset(new internal::FileCache(util::GetCacheRootPath(profile_.get()), 147 blocking_task_runner_, 148 fake_free_disk_space_getter_.get())); 149 150 drive_webapps_registry_.reset(new DriveWebAppsRegistry); 151 152 mock_cache_observer_.reset(new StrictMock<MockCacheObserver>); 153 cache_->AddObserver(mock_cache_observer_.get()); 154 155 mock_directory_observer_.reset(new StrictMock<MockDirectoryChangeObserver>); 156 157 cache_->RequestInitializeForTesting(); 158 google_apis::test_util::RunBlockingPoolTask(); 159 160 SetUpResourceMetadataAndFileSystem(); 161 } 162 163 void SetUpResourceMetadataAndFileSystem() { 164 resource_metadata_.reset(new internal::ResourceMetadata( 165 cache_->GetCacheDirectoryPath(internal::FileCache::CACHE_TYPE_META), 166 blocking_task_runner_)); 167 168 file_system_.reset(new FileSystem(profile_.get(), 169 cache_.get(), 170 fake_drive_service_.get(), 171 scheduler_.get(), 172 drive_webapps_registry_.get(), 173 resource_metadata_.get(), 174 blocking_task_runner_)); 175 file_system_->AddObserver(mock_directory_observer_.get()); 176 file_system_->Initialize(); 177 178 FileError error = FILE_ERROR_FAILED; 179 resource_metadata_->Initialize( 180 google_apis::test_util::CreateCopyResultCallback(&error)); 181 google_apis::test_util::RunBlockingPoolTask(); 182 ASSERT_EQ(FILE_ERROR_OK, error); 183 } 184 185 virtual void TearDown() OVERRIDE { 186 ASSERT_TRUE(file_system_); 187 file_system_.reset(); 188 scheduler_.reset(); 189 fake_drive_service_.reset(); 190 cache_.reset(); 191 profile_.reset(NULL); 192 } 193 194 // Loads test json file as root ("/drive") element. 195 bool LoadRootFeedDocument() { 196 FileError error = FILE_ERROR_FAILED; 197 file_system_->change_list_loader()->LoadIfNeeded( 198 DirectoryFetchInfo(), 199 google_apis::test_util::CreateCopyResultCallback(&error)); 200 google_apis::test_util::RunBlockingPoolTask(); 201 return error == FILE_ERROR_OK; 202 } 203 204 bool LoadChangeFeed(const std::string& filename) { 205 if (!test_util::LoadChangeFeed(filename, 206 file_system_->change_list_loader(), 207 true, // is_delta_feed 208 fake_drive_service_->GetRootResourceId(), 209 root_feed_changestamp_)) { 210 return false; 211 } 212 root_feed_changestamp_++; 213 return true; 214 } 215 216 FileError AddDirectory(const base::FilePath& directory_path) { 217 FileError error = FILE_ERROR_FAILED; 218 file_system_->CreateDirectory( 219 directory_path, 220 false, // is_exclusive 221 false, // is_recursive 222 google_apis::test_util::CreateCopyResultCallback(&error)); 223 google_apis::test_util::RunBlockingPoolTask(); 224 return error; 225 } 226 227 bool RemoveEntry(const base::FilePath& file_path) { 228 FileError error = FILE_ERROR_FAILED; 229 file_system_->Remove( 230 file_path, false, 231 google_apis::test_util::CreateCopyResultCallback(&error)); 232 google_apis::test_util::RunBlockingPoolTask(); 233 return error == FILE_ERROR_OK; 234 } 235 236 // Gets resource entry by path synchronously. 237 scoped_ptr<ResourceEntry> GetResourceEntryByPathSync( 238 const base::FilePath& file_path) { 239 FileError error = FILE_ERROR_FAILED; 240 scoped_ptr<ResourceEntry> entry; 241 file_system_->GetResourceEntryByPath( 242 file_path, 243 google_apis::test_util::CreateCopyResultCallback(&error, &entry)); 244 google_apis::test_util::RunBlockingPoolTask(); 245 246 return entry.Pass(); 247 } 248 249 // Gets directory info by path synchronously. 250 scoped_ptr<ResourceEntryVector> ReadDirectoryByPathSync( 251 const base::FilePath& file_path) { 252 FileError error = FILE_ERROR_FAILED; 253 bool unused_hide_hosted_documents; 254 scoped_ptr<ResourceEntryVector> entries; 255 file_system_->ReadDirectoryByPath( 256 file_path, 257 google_apis::test_util::CreateCopyResultCallback( 258 &error, &unused_hide_hosted_documents, &entries)); 259 google_apis::test_util::RunBlockingPoolTask(); 260 261 return entries.Pass(); 262 } 263 264 // Returns true if an entry exists at |file_path|. 265 bool EntryExists(const base::FilePath& file_path) { 266 return GetResourceEntryByPathSync(file_path); 267 } 268 269 // Gets the resource ID of |file_path|. Returns an empty string if not found. 270 std::string GetResourceIdByPath(const base::FilePath& file_path) { 271 scoped_ptr<ResourceEntry> entry = 272 GetResourceEntryByPathSync(file_path); 273 if (entry) 274 return entry->resource_id(); 275 else 276 return ""; 277 } 278 279 // Helper function to call GetCacheEntry from origin thread. 280 bool GetCacheEntryFromOriginThread(const std::string& resource_id, 281 const std::string& md5, 282 FileCacheEntry* cache_entry) { 283 bool result = false; 284 cache_->GetCacheEntryOnUIThread( 285 resource_id, md5, 286 google_apis::test_util::CreateCopyResultCallback(&result, cache_entry)); 287 google_apis::test_util::RunBlockingPoolTask(); 288 return result; 289 } 290 291 // Returns true if the cache entry exists for the given resource ID and MD5. 292 bool CacheEntryExists(const std::string& resource_id, 293 const std::string& md5) { 294 FileCacheEntry cache_entry; 295 return GetCacheEntryFromOriginThread(resource_id, md5, &cache_entry); 296 } 297 298 // Flag for specifying the timestamp of the test filesystem cache. 299 enum SetUpTestFileSystemParam { 300 USE_OLD_TIMESTAMP, 301 USE_SERVER_TIMESTAMP, 302 }; 303 304 // Sets up a filesystem with directories: drive/root, drive/root/Dir1, 305 // drive/root/Dir1/SubDir2 and files drive/root/File1, drive/root/Dir1/File2, 306 // drive/root/Dir1/SubDir2/File3. If |use_up_to_date_timestamp| is true, sets 307 // the changestamp to 654321, equal to that of "account_metadata.json" test 308 // data, indicating the cache is holding the latest file system info. 309 bool SetUpTestFileSystem(SetUpTestFileSystemParam param) { 310 // Destroy the existing resource metadata to close DB. 311 resource_metadata_.reset(); 312 313 const std::string root_resource_id = 314 fake_drive_service_->GetRootResourceId(); 315 scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests> 316 resource_metadata(new internal::ResourceMetadata( 317 cache_->GetCacheDirectoryPath(internal::FileCache::CACHE_TYPE_META), 318 blocking_task_runner_)); 319 320 FileError error = FILE_ERROR_FAILED; 321 resource_metadata->Initialize( 322 google_apis::test_util::CreateCopyResultCallback(&error)); 323 google_apis::test_util::RunBlockingPoolTask(); 324 if (error != FILE_ERROR_OK) 325 return false; 326 327 resource_metadata->SetLargestChangestampOnUIThread( 328 param == USE_SERVER_TIMESTAMP ? 654321 : 1, 329 google_apis::test_util::CreateCopyResultCallback(&error)); 330 google_apis::test_util::RunBlockingPoolTask(); 331 if (error != FILE_ERROR_OK) 332 return false; 333 334 // drive/root is already prepared by ResourceMetadata. 335 base::FilePath file_path; 336 337 // drive/root 338 resource_metadata->AddEntryOnUIThread( 339 util::CreateMyDriveRootEntry(root_resource_id), 340 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 341 google_apis::test_util::RunBlockingPoolTask(); 342 if (error != FILE_ERROR_OK) 343 return false; 344 345 // drive/root/File1 346 ResourceEntry file1; 347 file1.set_title("File1"); 348 file1.set_resource_id("resource_id:File1"); 349 file1.set_parent_resource_id(root_resource_id); 350 file1.mutable_file_specific_info()->set_file_md5("md5"); 351 file1.mutable_file_info()->set_is_directory(false); 352 file1.mutable_file_info()->set_size(1048576); 353 resource_metadata->AddEntryOnUIThread( 354 file1, 355 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 356 google_apis::test_util::RunBlockingPoolTask(); 357 if (error != FILE_ERROR_OK) 358 return false; 359 360 // drive/root/Dir1 361 ResourceEntry dir1; 362 dir1.set_title("Dir1"); 363 dir1.set_resource_id("resource_id:Dir1"); 364 dir1.set_parent_resource_id(root_resource_id); 365 dir1.mutable_file_info()->set_is_directory(true); 366 resource_metadata->AddEntryOnUIThread( 367 dir1, 368 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 369 google_apis::test_util::RunBlockingPoolTask(); 370 if (error != FILE_ERROR_OK) 371 return false; 372 373 // drive/root/Dir1/File2 374 ResourceEntry file2; 375 file2.set_title("File2"); 376 file2.set_resource_id("resource_id:File2"); 377 file2.set_parent_resource_id(dir1.resource_id()); 378 file2.mutable_file_specific_info()->set_file_md5("md5"); 379 file2.mutable_file_info()->set_is_directory(false); 380 file2.mutable_file_info()->set_size(555); 381 resource_metadata->AddEntryOnUIThread( 382 file2, 383 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 384 google_apis::test_util::RunBlockingPoolTask(); 385 if (error != FILE_ERROR_OK) 386 return false; 387 388 // drive/root/Dir1/SubDir2 389 ResourceEntry dir2; 390 dir2.set_title("SubDir2"); 391 dir2.set_resource_id("resource_id:SubDir2"); 392 dir2.set_parent_resource_id(dir1.resource_id()); 393 dir2.mutable_file_info()->set_is_directory(true); 394 resource_metadata->AddEntryOnUIThread( 395 dir2, 396 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 397 google_apis::test_util::RunBlockingPoolTask(); 398 if (error != FILE_ERROR_OK) 399 return false; 400 401 // drive/root/Dir1/SubDir2/File3 402 ResourceEntry file3; 403 file3.set_title("File3"); 404 file3.set_resource_id("resource_id:File3"); 405 file3.set_parent_resource_id(dir2.resource_id()); 406 file3.mutable_file_specific_info()->set_file_md5("md5"); 407 file3.mutable_file_info()->set_is_directory(false); 408 file3.mutable_file_info()->set_size(12345); 409 resource_metadata->AddEntryOnUIThread( 410 file3, 411 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 412 google_apis::test_util::RunBlockingPoolTask(); 413 if (error != FILE_ERROR_OK) 414 return false; 415 416 // Recreate resource metadata. 417 SetUpResourceMetadataAndFileSystem(); 418 419 return true; 420 } 421 422 // Verifies that |file_path| is a valid JSON file for the hosted document 423 // associated with |entry| (i.e. |url| and |resource_id| match). 424 void VerifyHostedDocumentJSONFile(const ResourceEntry& entry, 425 const base::FilePath& file_path) { 426 std::string error; 427 JSONFileValueSerializer serializer(file_path); 428 scoped_ptr<Value> value(serializer.Deserialize(NULL, &error)); 429 ASSERT_TRUE(value) << "Parse error " << file_path.value() << ": " << error; 430 DictionaryValue* dict_value = NULL; 431 ASSERT_TRUE(value->GetAsDictionary(&dict_value)); 432 433 std::string alternate_url, resource_id; 434 EXPECT_TRUE(dict_value->GetString("url", &alternate_url)); 435 EXPECT_TRUE(dict_value->GetString("resource_id", &resource_id)); 436 437 EXPECT_EQ(entry.file_specific_info().alternate_url(), alternate_url); 438 EXPECT_EQ(entry.resource_id(), resource_id); 439 } 440 441 MessageLoopForUI message_loop_; 442 content::TestBrowserThread ui_thread_; 443 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; 444 scoped_ptr<TestingProfile> profile_; 445 446 scoped_ptr<internal::FileCache, test_util::DestroyHelperForTests> cache_; 447 scoped_ptr<FileSystem> file_system_; 448 scoped_ptr<google_apis::FakeDriveService> fake_drive_service_; 449 scoped_ptr<JobScheduler> scheduler_; 450 scoped_ptr<DriveWebAppsRegistry> drive_webapps_registry_; 451 scoped_ptr<internal::ResourceMetadata, test_util::DestroyHelperForTests> 452 resource_metadata_; 453 scoped_ptr<FakeFreeDiskSpaceGetter> fake_free_disk_space_getter_; 454 scoped_ptr<StrictMock<MockCacheObserver> > mock_cache_observer_; 455 scoped_ptr<StrictMock<MockDirectoryChangeObserver> > mock_directory_observer_; 456 457 int root_feed_changestamp_; 458}; 459 460TEST_F(DriveFileSystemTest, DuplicatedAsyncInitialization) { 461 // "Fast fetch" will fire an OnirectoryChanged event. 462 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 463 Eq(base::FilePath(FILE_PATH_LITERAL("drive"))))).Times(1); 464 465 int counter = 0; 466 const GetResourceEntryCallback& callback = base::Bind( 467 &AsyncInitializationCallback, &counter, 2, &message_loop_); 468 469 file_system_->GetResourceEntryByPath( 470 base::FilePath(FILE_PATH_LITERAL("drive/root")), callback); 471 file_system_->GetResourceEntryByPath( 472 base::FilePath(FILE_PATH_LITERAL("drive/root")), callback); 473 message_loop_.Run(); // Wait to get our result 474 EXPECT_EQ(2, counter); 475 476 // Although GetResourceEntryByPath() was called twice, the resource list 477 // should only be loaded once. In the past, there was a bug that caused 478 // it to be loaded twice. 479 EXPECT_EQ(1, fake_drive_service_->resource_list_load_count()); 480 // See the comment in GetMyDriveRoot test case why this is 2. 481 EXPECT_EQ(2, fake_drive_service_->about_resource_load_count()); 482} 483 484TEST_F(DriveFileSystemTest, GetGrandRootEntry) { 485 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive")); 486 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath); 487 ASSERT_TRUE(entry); 488 EXPECT_EQ(util::kDriveGrandRootSpecialResourceId, entry->resource_id()); 489 490 // Getting the grand root entry should not cause the resource load to happen. 491 EXPECT_EQ(0, fake_drive_service_->about_resource_load_count()); 492 EXPECT_EQ(0, fake_drive_service_->resource_list_load_count()); 493} 494 495TEST_F(DriveFileSystemTest, GetOtherDirEntry) { 496 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/other")); 497 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath); 498 ASSERT_TRUE(entry); 499 EXPECT_EQ(util::kDriveOtherDirSpecialResourceId, entry->resource_id()); 500 501 // Getting the "other" directory entry should not cause the resource load to 502 // happen. 503 EXPECT_EQ(0, fake_drive_service_->about_resource_load_count()); 504 EXPECT_EQ(0, fake_drive_service_->resource_list_load_count()); 505} 506 507TEST_F(DriveFileSystemTest, GetMyDriveRoot) { 508 // "Fast fetch" will fire an OnirectoryChanged event. 509 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 510 Eq(base::FilePath(FILE_PATH_LITERAL("drive"))))).Times(1); 511 512 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root")); 513 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath); 514 ASSERT_TRUE(entry); 515 EXPECT_EQ(fake_drive_service_->GetRootResourceId(), entry->resource_id()); 516 517 // Absence of "drive/root" in the local metadata triggers the "fast fetch" 518 // of "drive" directory. Fetch of "drive" grand root directory has a special 519 // implementation. Instead of normal GetResourceListInDirectory(), it is 520 // emulated by calling GetAboutResource() so that the resource_id of 521 // "drive/root" is listed. 522 // Together with the normal GetAboutResource() call to retrieve the largest 523 // changestamp, the method is called twice. 524 EXPECT_EQ(2, fake_drive_service_->about_resource_load_count()); 525 526 // After "fast fetch" is done, full resource list is fetched. 527 EXPECT_EQ(1, fake_drive_service_->resource_list_load_count()); 528} 529 530TEST_F(DriveFileSystemTest, GetExistingFile) { 531 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/File 1.txt")); 532 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath); 533 ASSERT_TRUE(entry); 534 EXPECT_EQ("file:2_file_resource_id", entry->resource_id()); 535 536 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count()); 537 EXPECT_EQ(1, fake_drive_service_->resource_list_load_count()); 538} 539 540TEST_F(DriveFileSystemTest, GetExistingDocument) { 541 const base::FilePath kFilePath( 542 FILE_PATH_LITERAL("drive/root/Document 1 excludeDir-test.gdoc")); 543 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath); 544 ASSERT_TRUE(entry); 545 EXPECT_EQ("document:5_document_resource_id", entry->resource_id()); 546} 547 548TEST_F(DriveFileSystemTest, GetNonExistingFile) { 549 const base::FilePath kFilePath( 550 FILE_PATH_LITERAL("drive/root/nonexisting.file")); 551 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath); 552 EXPECT_FALSE(entry); 553} 554 555TEST_F(DriveFileSystemTest, GetEncodedFileNames) { 556 const base::FilePath kFilePath1( 557 FILE_PATH_LITERAL("drive/root/Slash / in file 1.txt")); 558 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath1); 559 ASSERT_FALSE(entry); 560 561 const base::FilePath kFilePath2 = base::FilePath::FromUTF8Unsafe( 562 "drive/root/Slash \xE2\x88\x95 in file 1.txt"); 563 entry = GetResourceEntryByPathSync(kFilePath2); 564 ASSERT_TRUE(entry); 565 EXPECT_EQ("file:slash_file_resource_id", entry->resource_id()); 566 567 const base::FilePath kFilePath3 = base::FilePath::FromUTF8Unsafe( 568 "drive/root/Slash \xE2\x88\x95 in directory/Slash SubDir File.txt"); 569 entry = GetResourceEntryByPathSync(kFilePath3); 570 ASSERT_TRUE(entry); 571 EXPECT_EQ("file:slash_subdir_file", entry->resource_id()); 572} 573 574TEST_F(DriveFileSystemTest, GetDuplicateNames) { 575 const base::FilePath kFilePath1( 576 FILE_PATH_LITERAL("drive/root/Duplicate Name.txt")); 577 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath1); 578 ASSERT_TRUE(entry); 579 const std::string resource_id1 = entry->resource_id(); 580 581 const base::FilePath kFilePath2( 582 FILE_PATH_LITERAL("drive/root/Duplicate Name (2).txt")); 583 entry = GetResourceEntryByPathSync(kFilePath2); 584 ASSERT_TRUE(entry); 585 const std::string resource_id2 = entry->resource_id(); 586 587 // The entries are de-duped non-deterministically, so we shouldn't rely on the 588 // names matching specific resource ids. 589 const std::string file3_resource_id = "file:3_file_resource_id"; 590 const std::string file4_resource_id = "file:4_file_resource_id"; 591 EXPECT_TRUE(file3_resource_id == resource_id1 || 592 file3_resource_id == resource_id2); 593 EXPECT_TRUE(file4_resource_id == resource_id1 || 594 file4_resource_id == resource_id2); 595} 596 597TEST_F(DriveFileSystemTest, GetExistingDirectory) { 598 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/Directory 1")); 599 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath); 600 ASSERT_TRUE(entry); 601 ASSERT_EQ("folder:1_folder_resource_id", entry->resource_id()); 602 603 // The changestamp should be propagated to the directory. 604 EXPECT_EQ(fake_drive_service_->largest_changestamp(), 605 entry->directory_specific_info().changestamp()); 606} 607 608TEST_F(DriveFileSystemTest, GetInSubSubdir) { 609 const base::FilePath kFilePath( 610 FILE_PATH_LITERAL("drive/root/Directory 1/Sub Directory Folder/" 611 "Sub Sub Directory Folder")); 612 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath); 613 ASSERT_TRUE(entry); 614 ASSERT_EQ("folder:sub_sub_directory_folder_id", entry->resource_id()); 615} 616 617TEST_F(DriveFileSystemTest, GetOrphanFile) { 618 const base::FilePath kFilePath( 619 FILE_PATH_LITERAL("drive/other/Orphan File 1.txt")); 620 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync(kFilePath); 621 ASSERT_TRUE(entry); 622 EXPECT_EQ("file:1_orphanfile_resource_id", entry->resource_id()); 623} 624 625TEST_F(DriveFileSystemTest, ReadDirectoryByPath_Root) { 626 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 627 Eq(base::FilePath(FILE_PATH_LITERAL("drive"))))).Times(1); 628 629 // ReadDirectoryByPath() should kick off the resource list loading. 630 scoped_ptr<ResourceEntryVector> entries( 631 ReadDirectoryByPathSync(base::FilePath::FromUTF8Unsafe("drive"))); 632 // The root directory should be read correctly. 633 ASSERT_TRUE(entries); 634 ASSERT_EQ(2U, entries->size()); 635 636 // The found two directories should be /drive/root and /drive/other. 637 bool found_other = false; 638 bool found_my_drive = false; 639 for (size_t i = 0; i < entries->size(); ++i) { 640 const base::FilePath title = 641 base::FilePath::FromUTF8Unsafe((*entries)[i].title()); 642 if (title == base::FilePath(util::kDriveOtherDirName)) { 643 found_other = true; 644 } else if (title == base::FilePath(util::kDriveMyDriveRootDirName)) { 645 found_my_drive = true; 646 } 647 } 648 649 EXPECT_TRUE(found_other); 650 EXPECT_TRUE(found_my_drive); 651} 652 653TEST_F(DriveFileSystemTest, ReadDirectoryByPath_NonRootDirectory) { 654 // ReadDirectoryByPath() should kick off the resource list loading. 655 scoped_ptr<ResourceEntryVector> entries( 656 ReadDirectoryByPathSync( 657 base::FilePath::FromUTF8Unsafe("drive/root/Directory 1"))); 658 // The non root directory should also be read correctly. 659 // There was a bug (crbug.com/181487), which broke this behavior. 660 // Make sure this is fixed. 661 ASSERT_TRUE(entries); 662 EXPECT_EQ(3U, entries->size()); 663} 664 665TEST_F(DriveFileSystemTest, ChangeFeed_AddAndDeleteFileInRoot) { 666 ASSERT_TRUE(LoadRootFeedDocument()); 667 668 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 669 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(2); 670 671 ASSERT_TRUE(LoadChangeFeed("chromeos/gdata/delta_file_added_in_root.json")); 672 EXPECT_TRUE(EntryExists( 673 base::FilePath(FILE_PATH_LITERAL("drive/root/Added file.gdoc")))); 674 675 ASSERT_TRUE(LoadChangeFeed("chromeos/gdata/delta_file_deleted_in_root.json")); 676 EXPECT_FALSE(EntryExists( 677 base::FilePath(FILE_PATH_LITERAL("drive/root/Added file.gdoc")))); 678} 679 680TEST_F(DriveFileSystemTest, ChangeFeed_AddAndDeleteFileFromExistingDirectory) { 681 ASSERT_TRUE(LoadRootFeedDocument()); 682 683 EXPECT_TRUE( 684 EntryExists(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1")))); 685 686 // Add file to an existing directory. 687 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 688 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 689 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 690 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 691 .Times(1); 692 ASSERT_TRUE( 693 LoadChangeFeed("chromeos/gdata/delta_file_added_in_directory.json")); 694 EXPECT_TRUE(EntryExists(base::FilePath( 695 FILE_PATH_LITERAL("drive/root/Directory 1/Added file.gdoc")))); 696 697 // Remove that file from the directory. 698 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 699 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 700 .Times(1); 701 ASSERT_TRUE( 702 LoadChangeFeed("chromeos/gdata/delta_file_deleted_in_directory.json")); 703 EXPECT_TRUE( 704 EntryExists(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1")))); 705 EXPECT_FALSE(EntryExists(base::FilePath( 706 FILE_PATH_LITERAL("drive/root/Directory 1/Added file.gdoc")))); 707} 708 709TEST_F(DriveFileSystemTest, ChangeFeed_AddFileToNewDirectory) { 710 ASSERT_TRUE(LoadRootFeedDocument()); 711 // Add file to a new directory. 712 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 713 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 714 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 715 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/New Directory"))))) 716 .Times(1); 717 718 ASSERT_TRUE( 719 LoadChangeFeed("chromeos/gdata/delta_file_added_in_new_directory.json")); 720 721 EXPECT_TRUE( 722 EntryExists(base::FilePath( 723 FILE_PATH_LITERAL("drive/root/New Directory")))); 724 EXPECT_TRUE(EntryExists(base::FilePath( 725 FILE_PATH_LITERAL("drive/root/New Directory/File in new dir.gdoc")))); 726} 727 728TEST_F(DriveFileSystemTest, ChangeFeed_AddFileToNewButDeletedDirectory) { 729 ASSERT_TRUE(LoadRootFeedDocument()); 730 731 // This feed contains the following updates: 732 // 1) A new PDF file is added to a new directory 733 // 2) but the new directory is marked "deleted" (i.e. moved to Trash) 734 // Hence, the PDF file should be just ignored. 735 ASSERT_TRUE(LoadChangeFeed( 736 "chromeos/gdata/delta_file_added_in_new_but_deleted_directory.json")); 737} 738 739TEST_F(DriveFileSystemTest, ChangeFeed_DirectoryMovedFromRootToDirectory) { 740 ASSERT_TRUE(LoadRootFeedDocument()); 741 742 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 743 "drive/root/Directory 2 excludeDir-test")))); 744 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 745 "drive/root/Directory 1")))); 746 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 747 "drive/root/Directory 1/SubDirectory File 1.txt")))); 748 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 749 "drive/root/Directory 1/Sub Directory Folder")))); 750 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 751 "drive/root/Directory 1/Sub Directory Folder/" 752 "Sub Sub Directory Folder")))); 753 754 // This will move "Directory 1" from "drive/root/" to 755 // "drive/root/Directory 2/". 756 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 757 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 758 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 759 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 760 .Times(1); 761 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 762 Eq(base::FilePath(FILE_PATH_LITERAL( 763 "drive/root/Directory 2 excludeDir-test"))))).Times(1); 764 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 765 Eq(base::FilePath(FILE_PATH_LITERAL( 766 "drive/root/Directory 2 excludeDir-test/Directory 1"))))).Times(1); 767 ASSERT_TRUE(LoadChangeFeed( 768 "chromeos/gdata/delta_dir_moved_from_root_to_directory.json")); 769 770 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 771 "drive/root/Directory 2 excludeDir-test")))); 772 EXPECT_FALSE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 773 "drive/root/Directory 1")))); 774 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 775 "drive/root/Directory 2 excludeDir-test/Directory 1")))); 776 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 777 "drive/root/Directory 2 excludeDir-test/Directory 1/" 778 "SubDirectory File 1.txt")))); 779 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 780 "drive/root/Directory 2 excludeDir-test/Directory 1/" 781 "Sub Directory Folder")))); 782 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 783 "drive/root/Directory 2 excludeDir-test/Directory 1/Sub Directory Folder/" 784 "Sub Sub Directory Folder")))); 785} 786 787TEST_F(DriveFileSystemTest, ChangeFeed_FileMovedFromDirectoryToRoot) { 788 ASSERT_TRUE(LoadRootFeedDocument()); 789 790 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 791 "drive/root/Directory 1")))); 792 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 793 "drive/root/Directory 1/Sub Directory Folder")))); 794 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 795 "drive/root/Directory 1/Sub Directory Folder/" 796 "Sub Sub Directory Folder")))); 797 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 798 "drive/root/Directory 1/SubDirectory File 1.txt")))); 799 800 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 801 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 802 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 803 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 804 .Times(1); 805 ASSERT_TRUE(LoadChangeFeed( 806 "chromeos/gdata/delta_file_moved_from_directory_to_root.json")); 807 808 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 809 "drive/root/Directory 1")))); 810 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 811 "drive/root/Directory 1/Sub Directory Folder")))); 812 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 813 "drive/root/Directory 1/Sub Directory Folder/" 814 "Sub Sub Directory Folder")))); 815 EXPECT_FALSE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 816 "drive/root/Directory 1/SubDirectory File 1.txt")))); 817 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 818 "drive/root/SubDirectory File 1.txt")))); 819} 820 821TEST_F(DriveFileSystemTest, ChangeFeed_FileRenamedInDirectory) { 822 ASSERT_TRUE(LoadRootFeedDocument()); 823 824 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 825 "drive/root/Directory 1")))); 826 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 827 "drive/root/Directory 1/SubDirectory File 1.txt")))); 828 829 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 830 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 831 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 832 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 833 .Times(1); 834 ASSERT_TRUE(LoadChangeFeed( 835 "chromeos/gdata/delta_file_renamed_in_directory.json")); 836 837 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 838 "drive/root/Directory 1")))); 839 EXPECT_FALSE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 840 "drive/root/Directory 1/SubDirectory File 1.txt")))); 841 EXPECT_TRUE(EntryExists(base::FilePath(FILE_PATH_LITERAL( 842 "drive/root/Directory 1/New SubDirectory File 1.txt")))); 843} 844 845TEST_F(DriveFileSystemTest, CachedFeedLoadingThenServerFeedLoading) { 846 ASSERT_TRUE(SetUpTestFileSystem(USE_SERVER_TIMESTAMP)); 847 848 // Kicks loading of cached file system and query for server update. 849 EXPECT_TRUE(ReadDirectoryByPathSync(util::GetDriveMyDriveRootPath())); 850 851 // SetUpTestFileSystem and "account_metadata.json" have the same changestamp, 852 // so no request for new feeds (i.e., call to GetResourceList) should happen. 853 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count()); 854 EXPECT_EQ(0, fake_drive_service_->resource_list_load_count()); 855 856 // Since the file system has verified that it holds the latest snapshot, 857 // it should change its state to "loaded", which admits periodic refresh. 858 // To test it, call CheckForUpdates and verify it does try to check updates. 859 file_system_->CheckForUpdates(); 860 google_apis::test_util::RunBlockingPoolTask(); 861 EXPECT_EQ(2, fake_drive_service_->about_resource_load_count()); 862} 863 864TEST_F(DriveFileSystemTest, OfflineCachedFeedLoading) { 865 ASSERT_TRUE(SetUpTestFileSystem(USE_OLD_TIMESTAMP)); 866 867 // Make GetResourceList fail for simulating offline situation. This will leave 868 // the file system "loaded from cache, but not synced with server" state. 869 fake_drive_service_->set_offline(true); 870 871 // Kicks loading of cached file system and query for server update. 872 EXPECT_TRUE(ReadDirectoryByPathSync(util::GetDriveMyDriveRootPath())); 873 // Loading of about resource should not happen as it's offline. 874 EXPECT_EQ(0, fake_drive_service_->about_resource_load_count()); 875 876 // Tests that cached data can be loaded even if the server is not reachable. 877 EXPECT_TRUE(EntryExists(base::FilePath( 878 FILE_PATH_LITERAL("drive/root/File1")))); 879 EXPECT_TRUE(EntryExists(base::FilePath( 880 FILE_PATH_LITERAL("drive/root/Dir1")))); 881 EXPECT_TRUE( 882 EntryExists(base::FilePath(FILE_PATH_LITERAL("drive/root/Dir1/File2")))); 883 EXPECT_TRUE(EntryExists(base::FilePath( 884 FILE_PATH_LITERAL("drive/root/Dir1/SubDir2")))); 885 EXPECT_TRUE(EntryExists( 886 base::FilePath(FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3")))); 887 888 // Since the file system has at least succeeded to load cached snapshot, 889 // the file system should be able to start periodic refresh. 890 // To test it, call CheckForUpdates and verify it does try to check 891 // updates, which will cause directory changes. 892 fake_drive_service_->set_offline(false); 893 894 file_system_->CheckForUpdates(); 895 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(_)) 896 .Times(AtLeast(1)); 897 898 google_apis::test_util::RunBlockingPoolTask(); 899 EXPECT_EQ(1, fake_drive_service_->about_resource_load_count()); 900 EXPECT_EQ(1, fake_drive_service_->change_list_load_count()); 901} 902 903TEST_F(DriveFileSystemTest, ReadDirectoryWhileRefreshing) { 904 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(_)) 905 .Times(AtLeast(1)); 906 907 // Enter the "refreshing" state so the fast fetch will be performed. 908 ASSERT_TRUE(SetUpTestFileSystem(USE_OLD_TIMESTAMP)); 909 file_system_->CheckForUpdates(); 910 911 // The list of resources in "drive/root/Dir1" should be fetched. 912 EXPECT_TRUE(ReadDirectoryByPathSync(base::FilePath( 913 FILE_PATH_LITERAL("drive/root/Dir1")))); 914 EXPECT_EQ(1, fake_drive_service_->directory_load_count()); 915} 916 917TEST_F(DriveFileSystemTest, GetResourceEntryExistingWhileRefreshing) { 918 // Enter the "refreshing" state. 919 ASSERT_TRUE(SetUpTestFileSystem(USE_OLD_TIMESTAMP)); 920 file_system_->CheckForUpdates(); 921 922 // If an entry is already found in local metadata, no directory fetch happens. 923 EXPECT_TRUE(GetResourceEntryByPathSync(base::FilePath( 924 FILE_PATH_LITERAL("drive/root/Dir1/File2")))); 925 EXPECT_EQ(0, fake_drive_service_->directory_load_count()); 926} 927 928TEST_F(DriveFileSystemTest, GetResourceEntryNonExistentWhileRefreshing) { 929 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(_)) 930 .Times(AtLeast(1)); 931 932 // Enter the "refreshing" state so the fast fetch will be performed. 933 ASSERT_TRUE(SetUpTestFileSystem(USE_OLD_TIMESTAMP)); 934 file_system_->CheckForUpdates(); 935 936 // If an entry is not found, parent directory's resource list is fetched. 937 EXPECT_FALSE(GetResourceEntryByPathSync(base::FilePath( 938 FILE_PATH_LITERAL("drive/root/Dir1/NonExistentFile")))); 939 EXPECT_EQ(1, fake_drive_service_->directory_load_count()); 940} 941 942TEST_F(DriveFileSystemTest, TransferFileFromLocalToRemote_RegularFile) { 943 fake_free_disk_space_getter_->set_fake_free_disk_space(kLotsOfSpace); 944 945 ASSERT_TRUE(LoadRootFeedDocument()); 946 947 // We'll add a file to the Drive root directory. 948 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 949 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 950 951 // Prepare a local file. 952 base::ScopedTempDir temp_dir; 953 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 954 const base::FilePath local_src_file_path = 955 temp_dir.path().AppendASCII("local.txt"); 956 ASSERT_TRUE( 957 google_apis::test_util::WriteStringToFile(local_src_file_path, "hello")); 958 959 // Confirm that the remote file does not exist. 960 const base::FilePath remote_dest_file_path( 961 FILE_PATH_LITERAL("drive/root/remote.txt")); 962 EXPECT_FALSE(EntryExists(remote_dest_file_path)); 963 964 // What TransferFileFromLocalToRemote does is to store the local file in 965 // the Drive file cache, and mark it as dirty+committed. Here we test that 966 // the "cache committed" event is indeed fired as a result of this test case. 967 // 968 // In the production environment, SyncClient listens this event and uploads 969 // the file to the remote server in background. This part should be tested in 970 // sync_client_unittest.cc 971 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(_)).Times(1); 972 973 // Transfer the local file to Drive. 974 FileError error = FILE_ERROR_FAILED; 975 file_system_->TransferFileFromLocalToRemote( 976 local_src_file_path, 977 remote_dest_file_path, 978 google_apis::test_util::CreateCopyResultCallback(&error)); 979 google_apis::test_util::RunBlockingPoolTask(); 980 981 EXPECT_EQ(FILE_ERROR_OK, error); 982 983 // Now the remote file should exist. 984 EXPECT_TRUE(EntryExists(remote_dest_file_path)); 985} 986 987TEST_F(DriveFileSystemTest, TransferFileFromLocalToRemote_HostedDocument) { 988 ASSERT_TRUE(LoadRootFeedDocument()); 989 990 // Prepare a local file, which is a json file of a hosted document, which 991 // matches "Document 1" in root_feed.json. 992 base::ScopedTempDir temp_dir; 993 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 994 const base::FilePath local_src_file_path = 995 temp_dir.path().AppendASCII("local.gdoc"); 996 const std::string kEditUrl = 997 "https://3_document_self_link/document:5_document_resource_id"; 998 const std::string kResourceId = "document:5_document_resource_id"; 999 ASSERT_TRUE(google_apis::test_util::WriteStringToFile( 1000 local_src_file_path, 1001 base::StringPrintf("{\"url\": \"%s\", \"resource_id\": \"%s\"}", 1002 kEditUrl.c_str(), kResourceId.c_str()))); 1003 1004 // Confirm that the remote file does not exist. 1005 const base::FilePath remote_dest_file_path(FILE_PATH_LITERAL( 1006 "drive/root/Directory 1/Document 1 excludeDir-test.gdoc")); 1007 EXPECT_FALSE(EntryExists(remote_dest_file_path)); 1008 1009 // We'll add a file to the Drive root and then move to "Directory 1". 1010 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1011 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1012 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1013 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 1014 .Times(1); 1015 1016 // Transfer the local file to Drive. 1017 FileError error = FILE_ERROR_FAILED; 1018 file_system_->TransferFileFromLocalToRemote( 1019 local_src_file_path, 1020 remote_dest_file_path, 1021 google_apis::test_util::CreateCopyResultCallback(&error)); 1022 google_apis::test_util::RunBlockingPoolTask(); 1023 1024 EXPECT_EQ(FILE_ERROR_OK, error); 1025 1026 // Now the remote file should exist. 1027 EXPECT_TRUE(EntryExists(remote_dest_file_path)); 1028} 1029 1030TEST_F(DriveFileSystemTest, TransferFileFromRemoteToLocal_RegularFile) { 1031 ASSERT_TRUE(LoadRootFeedDocument()); 1032 1033 // The transfered file is cached and the change of "offline available" 1034 // attribute is notified. 1035 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1036 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1037 1038 base::ScopedTempDir temp_dir; 1039 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 1040 base::FilePath local_dest_file_path = 1041 temp_dir.path().AppendASCII("local_copy.txt"); 1042 1043 base::FilePath remote_src_file_path( 1044 FILE_PATH_LITERAL("drive/root/File 1.txt")); 1045 scoped_ptr<ResourceEntry> file = GetResourceEntryByPathSync( 1046 remote_src_file_path); 1047 const int64 file_size = file->file_info().size(); 1048 1049 // Pretend we have enough space. 1050 fake_free_disk_space_getter_->set_fake_free_disk_space( 1051 file_size + internal::kMinFreeSpace); 1052 1053 FileError error = FILE_ERROR_FAILED; 1054 file_system_->TransferFileFromRemoteToLocal( 1055 remote_src_file_path, 1056 local_dest_file_path, 1057 google_apis::test_util::CreateCopyResultCallback(&error)); 1058 google_apis::test_util::RunBlockingPoolTask(); 1059 1060 EXPECT_EQ(FILE_ERROR_OK, error); 1061 1062 // The content is "x"s of the file size. 1063 base::FilePath cache_file_path; 1064 cache_->GetFileOnUIThread(file->resource_id(), 1065 file->file_specific_info().file_md5(), 1066 google_apis::test_util::CreateCopyResultCallback( 1067 &error, &cache_file_path)); 1068 google_apis::test_util::RunBlockingPoolTask(); 1069 EXPECT_EQ(FILE_ERROR_OK, error); 1070 1071 const std::string kExpectedContent = "xxxxxxxxxx"; 1072 std::string cache_file_data; 1073 EXPECT_TRUE(file_util::ReadFileToString(cache_file_path, &cache_file_data)); 1074 EXPECT_EQ(kExpectedContent, cache_file_data); 1075 1076 std::string local_dest_file_data; 1077 EXPECT_TRUE(file_util::ReadFileToString(local_dest_file_path, 1078 &local_dest_file_data)); 1079 EXPECT_EQ(kExpectedContent, local_dest_file_data); 1080} 1081 1082TEST_F(DriveFileSystemTest, TransferFileFromRemoteToLocal_HostedDocument) { 1083 ASSERT_TRUE(LoadRootFeedDocument()); 1084 1085 base::ScopedTempDir temp_dir; 1086 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 1087 base::FilePath local_dest_file_path = 1088 temp_dir.path().AppendASCII("local_copy.txt"); 1089 base::FilePath remote_src_file_path( 1090 FILE_PATH_LITERAL("drive/root/Document 1 excludeDir-test.gdoc")); 1091 FileError error = FILE_ERROR_FAILED; 1092 file_system_->TransferFileFromRemoteToLocal( 1093 remote_src_file_path, 1094 local_dest_file_path, 1095 google_apis::test_util::CreateCopyResultCallback(&error)); 1096 google_apis::test_util::RunBlockingPoolTask(); 1097 1098 EXPECT_EQ(FILE_ERROR_OK, error); 1099 1100 scoped_ptr<ResourceEntry> entry = GetResourceEntryByPathSync( 1101 remote_src_file_path); 1102 ASSERT_TRUE(entry); 1103 VerifyHostedDocumentJSONFile(*entry, local_dest_file_path); 1104} 1105 1106TEST_F(DriveFileSystemTest, CopyNotExistingFile) { 1107 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/Dummy file.txt")); 1108 base::FilePath dest_file_path(FILE_PATH_LITERAL("drive/root/Test.log")); 1109 1110 ASSERT_TRUE(LoadRootFeedDocument()); 1111 1112 EXPECT_FALSE(EntryExists(src_file_path)); 1113 1114 FileError error = FILE_ERROR_OK; 1115 file_system_->Copy( 1116 src_file_path, 1117 dest_file_path, 1118 google_apis::test_util::CreateCopyResultCallback(&error)); 1119 google_apis::test_util::RunBlockingPoolTask(); 1120 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error); 1121 1122 EXPECT_FALSE(EntryExists(src_file_path)); 1123 EXPECT_FALSE(EntryExists(dest_file_path)); 1124} 1125 1126TEST_F(DriveFileSystemTest, CopyFileToNonExistingDirectory) { 1127 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1128 base::FilePath dest_parent_path(FILE_PATH_LITERAL("drive/root/Dummy")); 1129 base::FilePath dest_file_path(FILE_PATH_LITERAL("drive/root/Dummy/Test.log")); 1130 1131 ASSERT_TRUE(LoadRootFeedDocument()); 1132 1133 ASSERT_TRUE(EntryExists(src_file_path)); 1134 scoped_ptr<ResourceEntry> src_entry = GetResourceEntryByPathSync( 1135 src_file_path); 1136 ASSERT_TRUE(src_entry); 1137 std::string src_file_path_resource_id = src_entry->resource_id(); 1138 1139 EXPECT_FALSE(EntryExists(dest_parent_path)); 1140 1141 FileError error = FILE_ERROR_OK; 1142 file_system_->Move( 1143 src_file_path, 1144 dest_file_path, 1145 google_apis::test_util::CreateCopyResultCallback(&error)); 1146 google_apis::test_util::RunBlockingPoolTask(); 1147 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error); 1148 1149 EXPECT_TRUE(EntryExists(src_file_path)); 1150 EXPECT_FALSE(EntryExists(dest_parent_path)); 1151 EXPECT_FALSE(EntryExists(dest_file_path)); 1152} 1153 1154// Test the case where the parent of |dest_file_path| is an existing file, 1155// not a directory. 1156TEST_F(DriveFileSystemTest, CopyFileToInvalidPath) { 1157 base::FilePath src_file_path(FILE_PATH_LITERAL( 1158 "drive/root/Document 1 excludeDir-test.gdoc")); 1159 base::FilePath dest_parent_path( 1160 FILE_PATH_LITERAL("drive/root/Duplicate Name.txt")); 1161 base::FilePath dest_file_path(FILE_PATH_LITERAL( 1162 "drive/root/Duplicate Name.txt/Document 1 excludeDir-test.gdoc")); 1163 1164 ASSERT_TRUE(LoadRootFeedDocument()); 1165 1166 ASSERT_TRUE(EntryExists(src_file_path)); 1167 scoped_ptr<ResourceEntry> src_entry = GetResourceEntryByPathSync( 1168 src_file_path); 1169 ASSERT_TRUE(src_entry); 1170 std::string src_file_resource_id = src_entry->resource_id(); 1171 1172 ASSERT_TRUE(EntryExists(dest_parent_path)); 1173 scoped_ptr<ResourceEntry> dest_entry = GetResourceEntryByPathSync( 1174 dest_parent_path); 1175 ASSERT_TRUE(dest_entry); 1176 1177 FileError error = FILE_ERROR_OK; 1178 file_system_->Copy( 1179 src_file_path, 1180 dest_file_path, 1181 google_apis::test_util::CreateCopyResultCallback(&error)); 1182 google_apis::test_util::RunBlockingPoolTask(); 1183 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error); 1184 1185 EXPECT_TRUE(EntryExists(src_file_path)); 1186 EXPECT_TRUE(EntryExists(src_file_path)); 1187 EXPECT_TRUE(EntryExists(dest_parent_path)); 1188 1189 EXPECT_FALSE(EntryExists(dest_file_path)); 1190} 1191 1192TEST_F(DriveFileSystemTest, RenameFile) { 1193 const base::FilePath src_file_path( 1194 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt")); 1195 const base::FilePath src_parent_path( 1196 FILE_PATH_LITERAL("drive/root/Directory 1")); 1197 const base::FilePath dest_file_path( 1198 FILE_PATH_LITERAL("drive/root/Directory 1/Test.log")); 1199 1200 ASSERT_TRUE(LoadRootFeedDocument()); 1201 1202 ASSERT_TRUE(EntryExists(src_file_path)); 1203 scoped_ptr<ResourceEntry> src_entry = GetResourceEntryByPathSync( 1204 src_file_path); 1205 ASSERT_TRUE(src_entry); 1206 std::string src_file_resource_id = 1207 src_entry->resource_id(); 1208 1209 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1210 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 1211 .Times(1); 1212 1213 FileError error = FILE_ERROR_FAILED; 1214 file_system_->Move( 1215 src_file_path, 1216 dest_file_path, 1217 google_apis::test_util::CreateCopyResultCallback(&error)); 1218 google_apis::test_util::RunBlockingPoolTask(); 1219 EXPECT_EQ(FILE_ERROR_OK, error); 1220 1221 EXPECT_FALSE(EntryExists(src_file_path)); 1222 EXPECT_TRUE(EntryExists(dest_file_path)); 1223 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path)); 1224} 1225 1226TEST_F(DriveFileSystemTest, MoveFileFromRootToSubDirectory) { 1227 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1228 base::FilePath dest_parent_path(FILE_PATH_LITERAL("drive/root/Directory 1")); 1229 base::FilePath dest_file_path( 1230 FILE_PATH_LITERAL("drive/root/Directory 1/Test.log")); 1231 1232 ASSERT_TRUE(LoadRootFeedDocument()); 1233 1234 ASSERT_TRUE(EntryExists(src_file_path)); 1235 scoped_ptr<ResourceEntry> src_entry = GetResourceEntryByPathSync( 1236 src_file_path); 1237 ASSERT_TRUE(src_entry); 1238 std::string src_file_resource_id = src_entry->resource_id(); 1239 1240 ASSERT_TRUE(EntryExists(dest_parent_path)); 1241 scoped_ptr<ResourceEntry> dest_parent_proto = GetResourceEntryByPathSync( 1242 dest_parent_path); 1243 ASSERT_TRUE(dest_parent_proto); 1244 ASSERT_TRUE(dest_parent_proto->file_info().is_directory()); 1245 1246 // Expect notification for both source and destination directories. 1247 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1248 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1249 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1250 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 1251 .Times(1); 1252 1253 FileError error = FILE_ERROR_FAILED; 1254 file_system_->Move( 1255 src_file_path, 1256 dest_file_path, 1257 google_apis::test_util::CreateCopyResultCallback(&error)); 1258 google_apis::test_util::RunBlockingPoolTask(); 1259 EXPECT_EQ(FILE_ERROR_OK, error); 1260 1261 EXPECT_FALSE(EntryExists(src_file_path)); 1262 EXPECT_TRUE(EntryExists(dest_file_path)); 1263 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path)); 1264} 1265 1266TEST_F(DriveFileSystemTest, MoveFileFromSubDirectoryToRoot) { 1267 base::FilePath src_parent_path(FILE_PATH_LITERAL("drive/root/Directory 1")); 1268 base::FilePath src_file_path( 1269 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt")); 1270 base::FilePath dest_file_path(FILE_PATH_LITERAL("drive/root/Test.log")); 1271 1272 ASSERT_TRUE(LoadRootFeedDocument()); 1273 1274 ASSERT_TRUE(EntryExists(src_file_path)); 1275 scoped_ptr<ResourceEntry> src_entry = GetResourceEntryByPathSync( 1276 src_file_path); 1277 ASSERT_TRUE(src_entry); 1278 std::string src_file_resource_id = src_entry->resource_id(); 1279 1280 ASSERT_TRUE(EntryExists(src_parent_path)); 1281 scoped_ptr<ResourceEntry> src_parent_proto = GetResourceEntryByPathSync( 1282 src_parent_path); 1283 ASSERT_TRUE(src_parent_proto); 1284 ASSERT_TRUE(src_parent_proto->file_info().is_directory()); 1285 1286 // Expect notification for both source and destination directories. 1287 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1288 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1289 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1290 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 1291 .Times(1); 1292 1293 FileError error = FILE_ERROR_FAILED; 1294 file_system_->Move( 1295 src_file_path, 1296 dest_file_path, 1297 google_apis::test_util::CreateCopyResultCallback(&error)); 1298 google_apis::test_util::RunBlockingPoolTask(); 1299 EXPECT_EQ(FILE_ERROR_OK, error); 1300 1301 EXPECT_FALSE(EntryExists(src_file_path)); 1302 ASSERT_TRUE(EntryExists(dest_file_path)); 1303 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path)); 1304} 1305 1306TEST_F(DriveFileSystemTest, MoveFileBetweenSubDirectories) { 1307 base::FilePath src_parent_path(FILE_PATH_LITERAL("drive/root/Directory 1")); 1308 base::FilePath src_file_path( 1309 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt")); 1310 base::FilePath dest_parent_path(FILE_PATH_LITERAL("drive/root/New Folder 1")); 1311 base::FilePath dest_file_path( 1312 FILE_PATH_LITERAL("drive/root/New Folder 1/Test.log")); 1313 base::FilePath interim_file_path(FILE_PATH_LITERAL("drive/root/Test.log")); 1314 1315 ASSERT_TRUE(LoadRootFeedDocument()); 1316 1317 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1318 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1319 1320 EXPECT_EQ(FILE_ERROR_OK, AddDirectory(dest_parent_path)); 1321 1322 ASSERT_TRUE(EntryExists(src_file_path)); 1323 scoped_ptr<ResourceEntry> src_entry = GetResourceEntryByPathSync( 1324 src_file_path); 1325 ASSERT_TRUE(src_entry); 1326 std::string src_file_resource_id = src_entry->resource_id(); 1327 1328 ASSERT_TRUE(EntryExists(src_parent_path)); 1329 scoped_ptr<ResourceEntry> src_parent_proto = GetResourceEntryByPathSync( 1330 src_parent_path); 1331 ASSERT_TRUE(src_parent_proto); 1332 ASSERT_TRUE(src_parent_proto->file_info().is_directory()); 1333 1334 ASSERT_TRUE(EntryExists(dest_parent_path)); 1335 scoped_ptr<ResourceEntry> dest_parent_proto = GetResourceEntryByPathSync( 1336 dest_parent_path); 1337 ASSERT_TRUE(dest_parent_proto); 1338 ASSERT_TRUE(dest_parent_proto->file_info().is_directory()); 1339 1340 EXPECT_FALSE(EntryExists(interim_file_path)); 1341 1342 // Expect notification for both source and destination directories. 1343 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1344 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/Directory 1"))))) 1345 .Times(1); 1346 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1347 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/New Folder 1"))))) 1348 .Times(1); 1349 1350 FileError error = FILE_ERROR_FAILED; 1351 file_system_->Move( 1352 src_file_path, 1353 dest_file_path, 1354 google_apis::test_util::CreateCopyResultCallback(&error)); 1355 google_apis::test_util::RunBlockingPoolTask(); 1356 EXPECT_EQ(FILE_ERROR_OK, error); 1357 1358 EXPECT_FALSE(EntryExists(src_file_path)); 1359 EXPECT_FALSE(EntryExists(interim_file_path)); 1360 1361 EXPECT_FALSE(EntryExists(src_file_path)); 1362 EXPECT_TRUE(EntryExists(dest_file_path)); 1363 EXPECT_EQ(src_file_resource_id, GetResourceIdByPath(dest_file_path)); 1364} 1365 1366TEST_F(DriveFileSystemTest, MoveNotExistingFile) { 1367 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/Dummy file.txt")); 1368 base::FilePath dest_file_path(FILE_PATH_LITERAL("drive/root/Test.log")); 1369 1370 ASSERT_TRUE(LoadRootFeedDocument()); 1371 1372 EXPECT_FALSE(EntryExists(src_file_path)); 1373 1374 FileError error = FILE_ERROR_OK; 1375 file_system_->Move( 1376 src_file_path, 1377 dest_file_path, 1378 google_apis::test_util::CreateCopyResultCallback(&error)); 1379 google_apis::test_util::RunBlockingPoolTask(); 1380 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error); 1381 1382 EXPECT_FALSE(EntryExists(src_file_path)); 1383 EXPECT_FALSE(EntryExists(dest_file_path)); 1384} 1385 1386TEST_F(DriveFileSystemTest, MoveFileToNonExistingDirectory) { 1387 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1388 base::FilePath dest_parent_path(FILE_PATH_LITERAL("drive/root/Dummy")); 1389 base::FilePath dest_file_path(FILE_PATH_LITERAL("drive/root/Dummy/Test.log")); 1390 1391 ASSERT_TRUE(LoadRootFeedDocument()); 1392 1393 ASSERT_TRUE(EntryExists(src_file_path)); 1394 scoped_ptr<ResourceEntry> src_entry = GetResourceEntryByPathSync( 1395 src_file_path); 1396 ASSERT_TRUE(src_entry); 1397 std::string src_file_resource_id = src_entry->resource_id(); 1398 1399 EXPECT_FALSE(EntryExists(dest_parent_path)); 1400 1401 FileError error = FILE_ERROR_OK; 1402 file_system_->Move( 1403 src_file_path, 1404 dest_file_path, 1405 google_apis::test_util::CreateCopyResultCallback(&error)); 1406 google_apis::test_util::RunBlockingPoolTask(); 1407 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error); 1408 1409 EXPECT_FALSE(EntryExists(dest_parent_path)); 1410 EXPECT_FALSE(EntryExists(dest_file_path)); 1411} 1412 1413// Test the case where the parent of |dest_file_path| is a existing file, 1414// not a directory. 1415TEST_F(DriveFileSystemTest, MoveFileToInvalidPath) { 1416 base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1417 base::FilePath dest_parent_path( 1418 FILE_PATH_LITERAL("drive/root/Duplicate Name.txt")); 1419 base::FilePath dest_file_path(FILE_PATH_LITERAL( 1420 "drive/root/Duplicate Name.txt/Test.log")); 1421 1422 ASSERT_TRUE(LoadRootFeedDocument()); 1423 1424 ASSERT_TRUE(EntryExists(src_file_path)); 1425 scoped_ptr<ResourceEntry> src_entry = GetResourceEntryByPathSync( 1426 src_file_path); 1427 ASSERT_TRUE(src_entry); 1428 std::string src_file_resource_id = src_entry->resource_id(); 1429 1430 ASSERT_TRUE(EntryExists(dest_parent_path)); 1431 scoped_ptr<ResourceEntry> dest_parent_proto = GetResourceEntryByPathSync( 1432 dest_parent_path); 1433 ASSERT_TRUE(dest_parent_proto); 1434 1435 FileError error = FILE_ERROR_OK; 1436 file_system_->Move( 1437 src_file_path, 1438 dest_file_path, 1439 google_apis::test_util::CreateCopyResultCallback(&error)); 1440 google_apis::test_util::RunBlockingPoolTask(); 1441 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error); 1442 1443 EXPECT_TRUE(EntryExists(src_file_path)); 1444 EXPECT_TRUE(EntryExists(dest_parent_path)); 1445 EXPECT_FALSE(EntryExists(dest_file_path)); 1446} 1447 1448TEST_F(DriveFileSystemTest, RemoveEntries) { 1449 ASSERT_TRUE(LoadRootFeedDocument()); 1450 1451 base::FilePath nonexisting_file( 1452 FILE_PATH_LITERAL("drive/root/Dummy file.txt")); 1453 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1454 base::FilePath dir_in_root(FILE_PATH_LITERAL("drive/root/Directory 1")); 1455 base::FilePath file_in_subdir( 1456 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt")); 1457 1458 ASSERT_TRUE(EntryExists(file_in_root)); 1459 scoped_ptr<ResourceEntry> file_in_root_proto = GetResourceEntryByPathSync( 1460 file_in_root); 1461 ASSERT_TRUE(file_in_root_proto); 1462 1463 ASSERT_TRUE(EntryExists(dir_in_root)); 1464 scoped_ptr<ResourceEntry> dir_in_root_proto = GetResourceEntryByPathSync( 1465 dir_in_root); 1466 ASSERT_TRUE(dir_in_root_proto); 1467 ASSERT_TRUE(dir_in_root_proto->file_info().is_directory()); 1468 1469 ASSERT_TRUE(EntryExists(file_in_subdir)); 1470 scoped_ptr<ResourceEntry> file_in_subdir_proto = GetResourceEntryByPathSync( 1471 file_in_subdir); 1472 ASSERT_TRUE(file_in_subdir_proto); 1473 1474 // Once for file in root and once for file... 1475 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1476 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(2); 1477 1478 // Remove first file in root. 1479 EXPECT_TRUE(RemoveEntry(file_in_root)); 1480 EXPECT_FALSE(EntryExists(file_in_root)); 1481 EXPECT_TRUE(EntryExists(dir_in_root)); 1482 EXPECT_TRUE(EntryExists(file_in_subdir)); 1483 1484 // Remove directory. 1485 EXPECT_TRUE(RemoveEntry(dir_in_root)); 1486 EXPECT_FALSE(EntryExists(file_in_root)); 1487 EXPECT_FALSE(EntryExists(dir_in_root)); 1488 EXPECT_FALSE(EntryExists(file_in_subdir)); 1489 1490 // Try removing file in already removed subdirectory. 1491 EXPECT_FALSE(RemoveEntry(file_in_subdir)); 1492 1493 // Try removing non-existing file. 1494 EXPECT_FALSE(RemoveEntry(nonexisting_file)); 1495 1496 // Try removing root file element. 1497 EXPECT_FALSE(RemoveEntry(base::FilePath(FILE_PATH_LITERAL("drive/root")))); 1498 1499 // Need this to ensure OnDirectoryChanged() is run. 1500 google_apis::test_util::RunBlockingPoolTask(); 1501} 1502 1503TEST_F(DriveFileSystemTest, CreateDirectory) { 1504 ASSERT_TRUE(LoadRootFeedDocument()); 1505 1506 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1507 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1508 1509 // Create directory in root. 1510 base::FilePath dir_path(FILE_PATH_LITERAL("drive/root/New Folder 1")); 1511 EXPECT_FALSE(EntryExists(dir_path)); 1512 EXPECT_EQ(FILE_ERROR_OK, AddDirectory(dir_path)); 1513 EXPECT_TRUE(EntryExists(dir_path)); 1514 1515 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1516 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root/New Folder 1"))))) 1517 .Times(1); 1518 1519 // Create directory in a sub directory. 1520 base::FilePath subdir_path( 1521 FILE_PATH_LITERAL("drive/root/New Folder 1/New Folder 2")); 1522 EXPECT_FALSE(EntryExists(subdir_path)); 1523 EXPECT_EQ(FILE_ERROR_OK, AddDirectory(subdir_path)); 1524 EXPECT_TRUE(EntryExists(subdir_path)); 1525} 1526 1527TEST_F(DriveFileSystemTest, CreateDirectoryByImplicitLoad) { 1528 // Intentionally *not* calling LoadRootFeedDocument(), for testing that 1529 // CreateDirectory ensures feed loading before it runs. 1530 1531 base::FilePath existing_directory( 1532 FILE_PATH_LITERAL("drive/root/Directory 1")); 1533 FileError error = FILE_ERROR_FAILED; 1534 file_system_->CreateDirectory( 1535 existing_directory, 1536 true, // is_exclusive 1537 false, // is_recursive 1538 google_apis::test_util::CreateCopyResultCallback(&error)); 1539 google_apis::test_util::RunBlockingPoolTask(); 1540 1541 // It should fail because is_exclusive is set to true. 1542 EXPECT_EQ(FILE_ERROR_EXISTS, error); 1543} 1544 1545TEST_F(DriveFileSystemTest, PinAndUnpin) { 1546 ASSERT_TRUE(LoadRootFeedDocument()); 1547 1548 base::FilePath file_path(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1549 1550 // Get the file info. 1551 scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(file_path)); 1552 ASSERT_TRUE(entry); 1553 1554 // Pin the file. 1555 FileError error = FILE_ERROR_FAILED; 1556 EXPECT_CALL(*mock_cache_observer_, 1557 OnCachePinned(entry->resource_id(), 1558 entry->file_specific_info().file_md5())).Times(1); 1559 file_system_->Pin(file_path, 1560 google_apis::test_util::CreateCopyResultCallback(&error)); 1561 google_apis::test_util::RunBlockingPoolTask(); 1562 EXPECT_EQ(FILE_ERROR_OK, error); 1563 1564 // Unpin the file. 1565 error = FILE_ERROR_FAILED; 1566 EXPECT_CALL(*mock_cache_observer_, 1567 OnCacheUnpinned(entry->resource_id(), 1568 entry->file_specific_info().file_md5())).Times(1); 1569 file_system_->Unpin(file_path, 1570 google_apis::test_util::CreateCopyResultCallback(&error)); 1571 google_apis::test_util::RunBlockingPoolTask(); 1572 EXPECT_EQ(FILE_ERROR_OK, error); 1573} 1574 1575TEST_F(DriveFileSystemTest, GetFileByPath_FromGData_EnoughSpace) { 1576 ASSERT_TRUE(LoadRootFeedDocument()); 1577 1578 // The transfered file is cached and the change of "offline available" 1579 // attribute is notified. 1580 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1581 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1582 1583 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1584 scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(file_in_root)); 1585 const int64 file_size = entry->file_info().size(); 1586 1587 // Pretend we have enough space. 1588 fake_free_disk_space_getter_->set_fake_free_disk_space( 1589 file_size + internal::kMinFreeSpace); 1590 1591 FileError error = FILE_ERROR_FAILED; 1592 base::FilePath file_path; 1593 entry.reset(); 1594 file_system_->GetFileByPath(file_in_root, 1595 google_apis::test_util::CreateCopyResultCallback( 1596 &error, &file_path, &entry)); 1597 google_apis::test_util::RunBlockingPoolTask(); 1598 1599 EXPECT_EQ(FILE_ERROR_OK, error); 1600 ASSERT_TRUE(entry); 1601 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 1602 1603 // Verify that readable permission is set. 1604 int permission = 0; 1605 EXPECT_TRUE(file_util::GetPosixFilePermissions(file_path, &permission)); 1606 EXPECT_EQ(file_util::FILE_PERMISSION_READ_BY_USER | 1607 file_util::FILE_PERMISSION_WRITE_BY_USER | 1608 file_util::FILE_PERMISSION_READ_BY_GROUP | 1609 file_util::FILE_PERMISSION_READ_BY_OTHERS, permission); 1610} 1611 1612TEST_F(DriveFileSystemTest, GetFileByPath_FromGData_NoSpaceAtAll) { 1613 ASSERT_TRUE(LoadRootFeedDocument()); 1614 1615 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1616 1617 // Pretend we have no space at all. 1618 fake_free_disk_space_getter_->set_fake_free_disk_space(0); 1619 1620 FileError error = FILE_ERROR_OK; 1621 base::FilePath file_path; 1622 scoped_ptr<ResourceEntry> entry; 1623 file_system_->GetFileByPath(file_in_root, 1624 google_apis::test_util::CreateCopyResultCallback( 1625 &error, &file_path, &entry)); 1626 google_apis::test_util::RunBlockingPoolTask(); 1627 1628 EXPECT_EQ(FILE_ERROR_NO_SPACE, error); 1629} 1630 1631TEST_F(DriveFileSystemTest, GetFileByPath_FromGData_NoEnoughSpaceButCanFreeUp) { 1632 ASSERT_TRUE(LoadRootFeedDocument()); 1633 1634 // The transfered file is cached and the change of "offline available" 1635 // attribute is notified. 1636 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1637 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1638 1639 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1640 scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(file_in_root)); 1641 const int64 file_size = entry->file_info().size(); 1642 1643 // Pretend we have no space first (checked before downloading a file), 1644 // but then start reporting we have space. This is to emulate that 1645 // the disk space was freed up by removing temporary files. 1646 fake_free_disk_space_getter_->set_fake_free_disk_space( 1647 file_size + internal::kMinFreeSpace); 1648 fake_free_disk_space_getter_->set_fake_free_disk_space(0); 1649 fake_free_disk_space_getter_->set_fake_free_disk_space( 1650 file_size + internal::kMinFreeSpace); 1651 fake_free_disk_space_getter_->set_fake_free_disk_space( 1652 file_size + internal::kMinFreeSpace); 1653 1654 // Store something of the file size in the temporary cache directory. 1655 const std::string content(file_size, 'x'); 1656 base::ScopedTempDir temp_dir; 1657 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 1658 const base::FilePath tmp_file = 1659 temp_dir.path().AppendASCII("something.txt"); 1660 ASSERT_TRUE(google_apis::test_util::WriteStringToFile(tmp_file, content)); 1661 1662 FileError error = FILE_ERROR_FAILED; 1663 cache_->StoreOnUIThread( 1664 "<resource_id>", "<md5>", tmp_file, 1665 internal::FileCache::FILE_OPERATION_COPY, 1666 google_apis::test_util::CreateCopyResultCallback(&error)); 1667 google_apis::test_util::RunBlockingPoolTask(); 1668 EXPECT_EQ(FILE_ERROR_OK, error); 1669 ASSERT_TRUE(CacheEntryExists("<resource_id>", "<md5>")); 1670 1671 base::FilePath file_path; 1672 entry.reset(); 1673 file_system_->GetFileByPath(file_in_root, 1674 google_apis::test_util::CreateCopyResultCallback( 1675 &error, &file_path, &entry)); 1676 google_apis::test_util::RunBlockingPoolTask(); 1677 1678 EXPECT_EQ(FILE_ERROR_OK, error); 1679 ASSERT_TRUE(entry); 1680 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 1681 1682 // The cache entry should be removed in order to free up space. 1683 ASSERT_FALSE(CacheEntryExists("<resource_id>", "<md5>")); 1684} 1685 1686TEST_F(DriveFileSystemTest, GetFileByPath_FromGData_EnoughSpaceButBecomeFull) { 1687 ASSERT_TRUE(LoadRootFeedDocument()); 1688 1689 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1690 scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(file_in_root)); 1691 const int64 file_size = entry->file_info().size(); 1692 1693 // Pretend we have enough space first (checked before downloading a file), 1694 // but then start reporting we have not enough space. This is to emulate that 1695 // the disk space becomes full after the file is downloaded for some reason 1696 // (ex. the actual file was larger than the expected size). 1697 fake_free_disk_space_getter_->set_fake_free_disk_space( 1698 file_size + internal::kMinFreeSpace); 1699 fake_free_disk_space_getter_->set_fake_free_disk_space( 1700 internal::kMinFreeSpace - 1); 1701 fake_free_disk_space_getter_->set_fake_free_disk_space( 1702 internal::kMinFreeSpace - 1); 1703 1704 FileError error = FILE_ERROR_OK; 1705 base::FilePath file_path; 1706 entry.reset(); 1707 file_system_->GetFileByPath(file_in_root, 1708 google_apis::test_util::CreateCopyResultCallback( 1709 &error, &file_path, &entry)); 1710 google_apis::test_util::RunBlockingPoolTask(); 1711 1712 EXPECT_EQ(FILE_ERROR_NO_SPACE, error); 1713} 1714 1715TEST_F(DriveFileSystemTest, GetFileByPath_FromCache) { 1716 fake_free_disk_space_getter_->set_fake_free_disk_space(kLotsOfSpace); 1717 1718 ASSERT_TRUE(LoadRootFeedDocument()); 1719 1720 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1721 scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(file_in_root)); 1722 1723 // Store something as cached version of this file. 1724 FileError error = FILE_ERROR_OK; 1725 cache_->StoreOnUIThread( 1726 entry->resource_id(), 1727 entry->file_specific_info().file_md5(), 1728 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 1729 internal::FileCache::FILE_OPERATION_COPY, 1730 google_apis::test_util::CreateCopyResultCallback(&error)); 1731 google_apis::test_util::RunBlockingPoolTask(); 1732 EXPECT_EQ(FILE_ERROR_OK, error); 1733 1734 base::FilePath file_path; 1735 entry.reset(); 1736 file_system_->GetFileByPath(file_in_root, 1737 google_apis::test_util::CreateCopyResultCallback( 1738 &error, &file_path, &entry)); 1739 google_apis::test_util::RunBlockingPoolTask(); 1740 1741 EXPECT_EQ(FILE_ERROR_OK, error); 1742 ASSERT_TRUE(entry); 1743 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 1744} 1745 1746TEST_F(DriveFileSystemTest, GetFileByPath_HostedDocument) { 1747 ASSERT_TRUE(LoadRootFeedDocument()); 1748 1749 base::FilePath file_in_root(FILE_PATH_LITERAL( 1750 "drive/root/Document 1 excludeDir-test.gdoc")); 1751 scoped_ptr<ResourceEntry> src_entry = 1752 GetResourceEntryByPathSync(file_in_root); 1753 ASSERT_TRUE(src_entry); 1754 1755 FileError error = FILE_ERROR_FAILED; 1756 base::FilePath file_path; 1757 scoped_ptr<ResourceEntry> entry; 1758 file_system_->GetFileByPath(file_in_root, 1759 google_apis::test_util::CreateCopyResultCallback( 1760 &error, &file_path, &entry)); 1761 google_apis::test_util::RunBlockingPoolTask(); 1762 1763 EXPECT_EQ(FILE_ERROR_OK, error); 1764 ASSERT_TRUE(entry); 1765 EXPECT_TRUE(entry->file_specific_info().is_hosted_document()); 1766 EXPECT_FALSE(file_path.empty()); 1767 1768 ASSERT_TRUE(src_entry); 1769 VerifyHostedDocumentJSONFile(*src_entry, file_path); 1770} 1771 1772TEST_F(DriveFileSystemTest, GetFileByResourceId) { 1773 fake_free_disk_space_getter_->set_fake_free_disk_space(kLotsOfSpace); 1774 1775 // The transfered file is cached and the change of "offline available" 1776 // attribute is notified. 1777 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1778 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1779 1780 ASSERT_TRUE(LoadRootFeedDocument()); 1781 1782 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1783 scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(file_in_root)); 1784 std::string resource_id = entry->resource_id(); 1785 1786 FileError error = FILE_ERROR_OK; 1787 base::FilePath file_path; 1788 entry.reset(); 1789 file_system_->GetFileByResourceId( 1790 resource_id, 1791 DriveClientContext(USER_INITIATED), 1792 google_apis::test_util::CreateCopyResultCallback( 1793 &error, &file_path, &entry), 1794 google_apis::GetContentCallback()); 1795 google_apis::test_util::RunBlockingPoolTask(); 1796 1797 EXPECT_EQ(FILE_ERROR_OK, error); 1798 ASSERT_TRUE(entry); 1799 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 1800} 1801 1802TEST_F(DriveFileSystemTest, GetFileContentByPath) { 1803 fake_free_disk_space_getter_->set_fake_free_disk_space(kLotsOfSpace); 1804 1805 // The transfered file is cached and the change of "offline available" 1806 // attribute is notified. 1807 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 1808 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 1809 1810 ASSERT_TRUE(LoadRootFeedDocument()); 1811 1812 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1813 1814 { 1815 FileError initialized_error = FILE_ERROR_FAILED; 1816 scoped_ptr<ResourceEntry> entry; 1817 base::FilePath local_path; 1818 base::Closure cancel_download; 1819 1820 std::vector<std::string> content_buffer; 1821 1822 FileError completion_error = FILE_ERROR_FAILED; 1823 1824 file_system_->GetFileContentByPath( 1825 file_in_root, 1826 google_apis::test_util::CreateCopyResultCallback( 1827 &initialized_error, &entry, &local_path, &cancel_download), 1828 base::Bind(&AppendContent, &content_buffer), 1829 google_apis::test_util::CreateCopyResultCallback(&completion_error)); 1830 google_apis::test_util::RunBlockingPoolTask(); 1831 1832 // For the first time, file is downloaded from the remote server. 1833 // In this case, |local_path| is empty while |cancel_download| is not. 1834 EXPECT_EQ(FILE_ERROR_OK, initialized_error); 1835 ASSERT_TRUE(entry); 1836 ASSERT_TRUE(local_path.empty()); 1837 EXPECT_TRUE(!cancel_download.is_null()); 1838 // Content is available through the second callback arguemnt. 1839 size_t content_size = 0; 1840 for (size_t i = 0; i < content_buffer.size(); ++i) { 1841 content_size += content_buffer[i].size(); 1842 } 1843 EXPECT_EQ(static_cast<size_t>(entry->file_info().size()), 1844 content_size); 1845 EXPECT_EQ(FILE_ERROR_OK, completion_error); 1846 } 1847 1848 { 1849 FileError initialized_error = FILE_ERROR_FAILED; 1850 scoped_ptr<ResourceEntry> entry; 1851 base::FilePath local_path; 1852 base::Closure cancel_download; 1853 1854 std::vector<std::string> content_buffer; 1855 1856 FileError completion_error = FILE_ERROR_FAILED; 1857 1858 file_system_->GetFileContentByPath( 1859 file_in_root, 1860 google_apis::test_util::CreateCopyResultCallback( 1861 &initialized_error, &entry, &local_path, &cancel_download), 1862 base::Bind(&AppendContent, &content_buffer), 1863 google_apis::test_util::CreateCopyResultCallback(&completion_error)); 1864 google_apis::test_util::RunBlockingPoolTask(); 1865 1866 // Try second download. In this case, the file should be cached, so 1867 // |local_path| should not be empty while |cancel_download| is empty. 1868 EXPECT_EQ(FILE_ERROR_OK, initialized_error); 1869 ASSERT_TRUE(entry); 1870 ASSERT_TRUE(!local_path.empty()); 1871 EXPECT_TRUE(cancel_download.is_null()); 1872 // The content is available from the cache file. 1873 EXPECT_TRUE(content_buffer.empty()); 1874 int64 local_file_size = 0; 1875 file_util::GetFileSize(local_path, &local_file_size); 1876 EXPECT_EQ(entry->file_info().size(), local_file_size); 1877 EXPECT_EQ(FILE_ERROR_OK, completion_error); 1878 } 1879} 1880 1881TEST_F(DriveFileSystemTest, GetFileByResourceId_FromCache) { 1882 fake_free_disk_space_getter_->set_fake_free_disk_space(kLotsOfSpace); 1883 1884 ASSERT_TRUE(LoadRootFeedDocument()); 1885 1886 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1887 scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(file_in_root)); 1888 1889 // Store something as cached version of this file. 1890 FileError error = FILE_ERROR_FAILED; 1891 cache_->StoreOnUIThread( 1892 entry->resource_id(), 1893 entry->file_specific_info().file_md5(), 1894 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 1895 internal::FileCache::FILE_OPERATION_COPY, 1896 google_apis::test_util::CreateCopyResultCallback(&error)); 1897 google_apis::test_util::RunBlockingPoolTask(); 1898 EXPECT_EQ(FILE_ERROR_OK, error); 1899 1900 // The file is obtained from the cache. 1901 // Hence the downloading should work even if the drive service is offline. 1902 fake_drive_service_->set_offline(true); 1903 1904 std::string resource_id = entry->resource_id(); 1905 base::FilePath file_path; 1906 entry.reset(); 1907 file_system_->GetFileByResourceId( 1908 resource_id, 1909 DriveClientContext(USER_INITIATED), 1910 google_apis::test_util::CreateCopyResultCallback( 1911 &error, &file_path, &entry), 1912 google_apis::GetContentCallback()); 1913 google_apis::test_util::RunBlockingPoolTask(); 1914 1915 EXPECT_EQ(FILE_ERROR_OK, error); 1916 ASSERT_TRUE(entry); 1917 EXPECT_FALSE(entry->file_specific_info().is_hosted_document()); 1918} 1919 1920TEST_F(DriveFileSystemTest, UpdateFileByResourceId_PersistentFile) { 1921 fake_free_disk_space_getter_->set_fake_free_disk_space(kLotsOfSpace); 1922 1923 ASSERT_TRUE(LoadRootFeedDocument()); 1924 1925 // This is a file defined in root_feed.json. 1926 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/File 1.txt")); 1927 const std::string kResourceId("file:2_file_resource_id"); 1928 const std::string kMd5("3b4382ebefec6e743578c76bbd0575ce"); 1929 1930 // Pin the file so it'll be store in "persistent" directory. 1931 EXPECT_CALL(*mock_cache_observer_, OnCachePinned(kResourceId, kMd5)).Times(1); 1932 FileError error = FILE_ERROR_OK; 1933 cache_->PinOnUIThread( 1934 kResourceId, kMd5, 1935 google_apis::test_util::CreateCopyResultCallback(&error)); 1936 google_apis::test_util::RunBlockingPoolTask(); 1937 EXPECT_EQ(FILE_ERROR_OK, error); 1938 1939 // First store a file to cache. 1940 cache_->StoreOnUIThread( 1941 kResourceId, 1942 kMd5, 1943 // Anything works. 1944 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 1945 internal::FileCache::FILE_OPERATION_COPY, 1946 google_apis::test_util::CreateCopyResultCallback(&error)); 1947 google_apis::test_util::RunBlockingPoolTask(); 1948 EXPECT_EQ(FILE_ERROR_OK, error); 1949 1950 // Add the dirty bit. 1951 cache_->MarkDirtyOnUIThread( 1952 kResourceId, kMd5, 1953 google_apis::test_util::CreateCopyResultCallback(&error)); 1954 google_apis::test_util::RunBlockingPoolTask(); 1955 EXPECT_EQ(FILE_ERROR_OK, error); 1956 1957 // Commit the dirty bit. 1958 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(kResourceId)).Times(1); 1959 cache_->CommitDirtyOnUIThread( 1960 kResourceId, kMd5, 1961 google_apis::test_util::CreateCopyResultCallback(&error)); 1962 google_apis::test_util::RunBlockingPoolTask(); 1963 EXPECT_EQ(FILE_ERROR_OK, error); 1964 1965 // We'll notify the directory change to the observer upon completion. 1966 EXPECT_CALL(*mock_directory_observer_, 1967 OnDirectoryChanged(Eq(util::GetDriveMyDriveRootPath()))) 1968 .Times(1); 1969 1970 // Check the number of files in the root directory. We'll compare the 1971 // number after updating a file. 1972 scoped_ptr<ResourceEntryVector> root_directory_entries( 1973 ReadDirectoryByPathSync(base::FilePath::FromUTF8Unsafe("drive/root"))); 1974 ASSERT_TRUE(root_directory_entries); 1975 const int num_files_in_root = CountFiles(*root_directory_entries); 1976 1977 // The callback will be called upon completion of 1978 // UpdateFileByResourceId(). 1979 file_system_->UpdateFileByResourceId( 1980 kResourceId, 1981 DriveClientContext(USER_INITIATED), 1982 google_apis::test_util::CreateCopyResultCallback(&error)); 1983 google_apis::test_util::RunBlockingPoolTask(); 1984 EXPECT_EQ(FILE_ERROR_OK, error); 1985 1986 // Make sure that the number of files did not change (i.e. we updated an 1987 // existing file, rather than adding a new file. The number of files 1988 // increases if we don't handle the file update right). 1989 EXPECT_EQ(num_files_in_root, CountFiles(*root_directory_entries)); 1990} 1991 1992TEST_F(DriveFileSystemTest, UpdateFileByResourceId_NonexistentFile) { 1993 ASSERT_TRUE(LoadRootFeedDocument()); 1994 1995 // This is nonexistent in root_feed.json. 1996 const base::FilePath kFilePath( 1997 FILE_PATH_LITERAL("drive/root/Nonexistent.txt")); 1998 const std::string kResourceId("file:nonexistent_resource_id"); 1999 const std::string kMd5("nonexistent_md5"); 2000 2001 // The callback will be called upon completion of 2002 // UpdateFileByResourceId(). 2003 FileError error = FILE_ERROR_OK; 2004 file_system_->UpdateFileByResourceId( 2005 kResourceId, 2006 DriveClientContext(USER_INITIATED), 2007 google_apis::test_util::CreateCopyResultCallback(&error)); 2008 google_apis::test_util::RunBlockingPoolTask(); 2009 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error); 2010} 2011 2012TEST_F(DriveFileSystemTest, ContentSearch) { 2013 ASSERT_TRUE(LoadRootFeedDocument()); 2014 2015 const SearchResultPair kExpectedResults[] = { 2016 { "drive/root/Directory 1/Sub Directory Folder/Sub Sub Directory Folder", 2017 true }, 2018 { "drive/root/Directory 1/Sub Directory Folder", true }, 2019 { "drive/root/Directory 1/SubDirectory File 1.txt", false }, 2020 { "drive/root/Directory 1", true }, 2021 { "drive/root/Directory 2 excludeDir-test", true }, 2022 }; 2023 2024 SearchCallback callback = base::Bind( 2025 &DriveSearchCallback, 2026 &message_loop_, 2027 kExpectedResults, ARRAYSIZE_UNSAFE(kExpectedResults), 2028 GURL()); 2029 2030 file_system_->Search("Directory", GURL(), callback); 2031 message_loop_.Run(); // Wait to get our result. 2032} 2033 2034TEST_F(DriveFileSystemTest, ContentSearchWithNewEntry) { 2035 ASSERT_TRUE(LoadRootFeedDocument()); 2036 2037 // Create a new directory in the drive service. 2038 google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 2039 scoped_ptr<google_apis::ResourceEntry> resource_entry; 2040 fake_drive_service_->AddNewDirectory( 2041 fake_drive_service_->GetRootResourceId(), // Add to the root directory. 2042 "New Directory 1!", 2043 google_apis::test_util::CreateCopyResultCallback( 2044 &error, &resource_entry)); 2045 message_loop_.RunUntilIdle(); 2046 2047 // As the result of the first Search(), only entries in the current file 2048 // system snapshot are expected to be returned (i.e. "New Directory 1!" 2049 // shouldn't be included in the search result even though it matches 2050 // "Directory 1". 2051 const SearchResultPair kExpectedResults[] = { 2052 { "drive/root/Directory 1", true } 2053 }; 2054 2055 // At the same time, unknown entry should trigger delta feed request. 2056 // This will cause notification to directory observers (e.g., File Browser) 2057 // so that they can request search again. 2058 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged(_)) 2059 .Times(AtLeast(1)); 2060 2061 SearchCallback callback = base::Bind( 2062 &DriveSearchCallback, 2063 &message_loop_, 2064 kExpectedResults, ARRAYSIZE_UNSAFE(kExpectedResults), 2065 GURL()); 2066 2067 file_system_->Search("\"Directory 1\"", GURL(), callback); 2068 // Make sure all the delayed tasks to complete. 2069 // message_loop_.Run() can return before the delta feed processing finishes. 2070 google_apis::test_util::RunBlockingPoolTask(); 2071} 2072 2073TEST_F(DriveFileSystemTest, ContentSearchEmptyResult) { 2074 ASSERT_TRUE(LoadRootFeedDocument()); 2075 2076 const SearchResultPair* expected_results = NULL; 2077 2078 SearchCallback callback = base::Bind( 2079 &DriveSearchCallback, 2080 &message_loop_, 2081 expected_results, 2082 0u, 2083 GURL()); 2084 2085 file_system_->Search("\"no-match query\"", GURL(), callback); 2086 message_loop_.Run(); // Wait to get our result. 2087} 2088 2089TEST_F(DriveFileSystemTest, GetAvailableSpace) { 2090 FileError error = FILE_ERROR_OK; 2091 int64 bytes_total; 2092 int64 bytes_used; 2093 file_system_->GetAvailableSpace( 2094 google_apis::test_util::CreateCopyResultCallback( 2095 &error, &bytes_total, &bytes_used)); 2096 google_apis::test_util::RunBlockingPoolTask(); 2097 EXPECT_EQ(GG_LONGLONG(6789012345), bytes_used); 2098 EXPECT_EQ(GG_LONGLONG(9876543210), bytes_total); 2099} 2100 2101TEST_F(DriveFileSystemTest, RefreshDirectory) { 2102 ASSERT_TRUE(LoadRootFeedDocument()); 2103 2104 // We'll notify the directory change to the observer. 2105 EXPECT_CALL(*mock_directory_observer_, 2106 OnDirectoryChanged(Eq(util::GetDriveMyDriveRootPath()))).Times(1); 2107 2108 FileError error = FILE_ERROR_FAILED; 2109 file_system_->RefreshDirectory( 2110 util::GetDriveMyDriveRootPath(), 2111 google_apis::test_util::CreateCopyResultCallback(&error)); 2112 google_apis::test_util::RunBlockingPoolTask(); 2113 EXPECT_EQ(FILE_ERROR_OK, error); 2114} 2115 2116TEST_F(DriveFileSystemTest, OpenAndCloseFile) { 2117 ASSERT_TRUE(LoadRootFeedDocument()); 2118 2119 // The transfered file is cached and the change of "offline available" 2120 // attribute is notified. 2121 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 2122 Eq(base::FilePath(FILE_PATH_LITERAL("drive/root"))))).Times(1); 2123 2124 const base::FilePath kFileInRoot(FILE_PATH_LITERAL("drive/root/File 1.txt")); 2125 scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(kFileInRoot)); 2126 const int64 file_size = entry->file_info().size(); 2127 const std::string& file_resource_id = 2128 entry->resource_id(); 2129 const std::string& file_md5 = entry->file_specific_info().file_md5(); 2130 2131 // A dirty file is created on close. 2132 EXPECT_CALL(*mock_cache_observer_, OnCacheCommitted(file_resource_id)) 2133 .Times(1); 2134 2135 // Pretend we have enough space. 2136 fake_free_disk_space_getter_->set_fake_free_disk_space( 2137 file_size + internal::kMinFreeSpace); 2138 2139 // Open kFileInRoot ("drive/root/File 1.txt"). 2140 FileError error = FILE_ERROR_FAILED; 2141 base::FilePath file_path; 2142 file_system_->OpenFile( 2143 kFileInRoot, 2144 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 2145 google_apis::test_util::RunBlockingPoolTask(); 2146 const base::FilePath opened_file_path = file_path; 2147 2148 // Verify that the file was properly opened. 2149 EXPECT_EQ(FILE_ERROR_OK, error); 2150 2151 // Try to open the already opened file. 2152 file_system_->OpenFile( 2153 kFileInRoot, 2154 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 2155 google_apis::test_util::RunBlockingPoolTask(); 2156 2157 // It must fail. 2158 EXPECT_EQ(FILE_ERROR_IN_USE, error); 2159 2160 // Verify that the file contents match the expected contents. 2161 // The content is "x"s of the file size. 2162 const std::string kExpectedContent = "xxxxxxxxxx"; 2163 std::string cache_file_data; 2164 EXPECT_TRUE(file_util::ReadFileToString(opened_file_path, &cache_file_data)); 2165 EXPECT_EQ(kExpectedContent, cache_file_data); 2166 2167 FileCacheEntry cache_entry; 2168 EXPECT_TRUE(GetCacheEntryFromOriginThread(file_resource_id, file_md5, 2169 &cache_entry)); 2170 EXPECT_TRUE(cache_entry.is_present()); 2171 EXPECT_TRUE(cache_entry.is_dirty()); 2172 EXPECT_TRUE(cache_entry.is_persistent()); 2173 2174 base::FilePath cache_file_path; 2175 cache_->GetFileOnUIThread(file_resource_id, file_md5, 2176 google_apis::test_util::CreateCopyResultCallback( 2177 &error, &cache_file_path)); 2178 google_apis::test_util::RunBlockingPoolTask(); 2179 EXPECT_EQ(FILE_ERROR_OK, error); 2180 EXPECT_EQ(cache_file_path, opened_file_path); 2181 2182 // Close kFileInRoot ("drive/root/File 1.txt"). 2183 file_system_->CloseFile( 2184 kFileInRoot, 2185 google_apis::test_util::CreateCopyResultCallback(&error)); 2186 google_apis::test_util::RunBlockingPoolTask(); 2187 2188 // Verify that the file was properly closed. 2189 EXPECT_EQ(FILE_ERROR_OK, error); 2190 2191 // Verify that the cache state was changed as expected. 2192 EXPECT_TRUE(GetCacheEntryFromOriginThread(file_resource_id, file_md5, 2193 &cache_entry)); 2194 EXPECT_TRUE(cache_entry.is_present()); 2195 EXPECT_TRUE(cache_entry.is_dirty()); 2196 EXPECT_TRUE(cache_entry.is_persistent()); 2197 2198 // Try to close the same file twice. 2199 file_system_->CloseFile( 2200 kFileInRoot, 2201 google_apis::test_util::CreateCopyResultCallback(&error)); 2202 google_apis::test_util::RunBlockingPoolTask(); 2203 2204 // It must fail. 2205 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error); 2206} 2207 2208// TODO(satorux): Testing if WebAppsRegistry is loaded here is awkward. We 2209// should move this to change_list_loader_unittest.cc. crbug.com/161703 2210TEST_F(DriveFileSystemTest, WebAppsRegistryIsLoaded) { 2211 ASSERT_TRUE(SetUpTestFileSystem(USE_SERVER_TIMESTAMP)); 2212 2213 // No apps should be found as the webapps registry is empty. 2214 ScopedVector<DriveWebAppInfo> apps; 2215 drive_webapps_registry_->GetWebAppsForFile( 2216 base::FilePath::FromUTF8Unsafe("foo.exe"), 2217 "" /* mime_type */, 2218 &apps); 2219 EXPECT_TRUE(apps.empty()); 2220 2221 // Kicks loading of cached file system and query for server update. This 2222 // will cause GetAboutResource() to be called, to check the server-side 2223 // changestamp, and the webapps registry will be loaded at the same time. 2224 EXPECT_TRUE(ReadDirectoryByPathSync(util::GetDriveMyDriveRootPath())); 2225 2226 // An app for foo.exe should now be found, as the registry was loaded. 2227 drive_webapps_registry_->GetWebAppsForFile( 2228 base::FilePath(FILE_PATH_LITERAL("foo.exe")), 2229 "" /* mime_type */, 2230 &apps); 2231 EXPECT_EQ(1U, apps.size()); 2232} 2233 2234TEST_F(DriveFileSystemTest, MarkCacheFileAsMountedAndUnmounted) { 2235 fake_free_disk_space_getter_->set_fake_free_disk_space(kLotsOfSpace); 2236 ASSERT_TRUE(LoadRootFeedDocument()); 2237 2238 base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt")); 2239 scoped_ptr<ResourceEntry> entry(GetResourceEntryByPathSync(file_in_root)); 2240 ASSERT_TRUE(entry); 2241 2242 // Write to cache. 2243 FileError error = FILE_ERROR_FAILED; 2244 cache_->StoreOnUIThread( 2245 entry->resource_id(), 2246 entry->file_specific_info().file_md5(), 2247 google_apis::test_util::GetTestFilePath("chromeos/gdata/root_feed.json"), 2248 internal::FileCache::FILE_OPERATION_COPY, 2249 google_apis::test_util::CreateCopyResultCallback(&error)); 2250 google_apis::test_util::RunBlockingPoolTask(); 2251 ASSERT_EQ(FILE_ERROR_OK, error); 2252 2253 // Test for mounting. 2254 base::FilePath file_path; 2255 file_system_->MarkCacheFileAsMounted( 2256 file_in_root, 2257 google_apis::test_util::CreateCopyResultCallback(&error, &file_path)); 2258 google_apis::test_util::RunBlockingPoolTask(); 2259 EXPECT_EQ(FILE_ERROR_OK, error); 2260 2261 bool success = false; 2262 FileCacheEntry cache_entry; 2263 cache_->GetCacheEntryOnUIThread( 2264 entry->resource_id(), 2265 entry->file_specific_info().file_md5(), 2266 google_apis::test_util::CreateCopyResultCallback(&success, &cache_entry)); 2267 google_apis::test_util::RunBlockingPoolTask(); 2268 2269 EXPECT_TRUE(success); 2270 EXPECT_TRUE(cache_entry.is_mounted()); 2271 2272 // Test for unmounting. 2273 error = FILE_ERROR_FAILED; 2274 file_system_->MarkCacheFileAsUnmounted( 2275 file_path, 2276 google_apis::test_util::CreateCopyResultCallback(&error)); 2277 google_apis::test_util::RunBlockingPoolTask(); 2278 2279 EXPECT_EQ(FILE_ERROR_OK, error); 2280 2281 success = false; 2282 cache_->GetCacheEntryOnUIThread( 2283 entry->resource_id(), 2284 entry->file_specific_info().file_md5(), 2285 google_apis::test_util::CreateCopyResultCallback(&success, &cache_entry)); 2286 google_apis::test_util::RunBlockingPoolTask(); 2287 2288 EXPECT_TRUE(success); 2289 EXPECT_FALSE(cache_entry.is_mounted()); 2290} 2291 2292// TODO(kinaba): crbug.com/237066 2293// Create and move to file_system/create create_file_operation_unittest.cc. 2294TEST_F(DriveFileSystemTest, CreateFile) { 2295 fake_free_disk_space_getter_->set_fake_free_disk_space(kLotsOfSpace); 2296 ASSERT_TRUE(LoadRootFeedDocument()); 2297 2298 const base::FilePath kExistingFile( 2299 FILE_PATH_LITERAL("drive/root/File 1.txt")); 2300 const base::FilePath kExistingDirectory( 2301 FILE_PATH_LITERAL("drive/root/Directory 1")); 2302 const base::FilePath kNonExistingFile( 2303 FILE_PATH_LITERAL("drive/root/Directory 1/not exist.png")); 2304 const base::FilePath kFileInNonExistingDirectory( 2305 FILE_PATH_LITERAL("drive/root/not exist/not exist.png")); 2306 2307 EXPECT_CALL(*mock_directory_observer_, OnDirectoryChanged( 2308 Eq(kNonExistingFile.DirName()))).Times(1); 2309 2310 // Create fails if is_exclusive = true and a file exists. 2311 FileError error = FILE_ERROR_FAILED; 2312 file_system_->CreateFile( 2313 kExistingFile, 2314 true /* is_exclusive */, 2315 google_apis::test_util::CreateCopyResultCallback(&error)); 2316 google_apis::test_util::RunBlockingPoolTask(); 2317 EXPECT_EQ(FILE_ERROR_EXISTS, error); 2318 2319 // Create succeeds if is_exclusive = false and a file exists. 2320 file_system_->CreateFile( 2321 kExistingFile, 2322 false /* is_exclusive */, 2323 google_apis::test_util::CreateCopyResultCallback(&error)); 2324 google_apis::test_util::RunBlockingPoolTask(); 2325 EXPECT_EQ(FILE_ERROR_OK, error); 2326 2327 // Create fails if a directory existed even when is_exclusive = false. 2328 file_system_->CreateFile( 2329 kExistingDirectory, 2330 false /* is_exclusive */, 2331 google_apis::test_util::CreateCopyResultCallback(&error)); 2332 google_apis::test_util::RunBlockingPoolTask(); 2333 EXPECT_EQ(FILE_ERROR_EXISTS, error); 2334 2335 // Create succeeds if no entry exists. 2336 file_system_->CreateFile( 2337 kNonExistingFile, 2338 true /* is_exclusive */, 2339 google_apis::test_util::CreateCopyResultCallback(&error)); 2340 google_apis::test_util::RunBlockingPoolTask(); 2341 EXPECT_EQ(FILE_ERROR_OK, error); 2342 2343 // Create fails if the parent directory does not exist. 2344 file_system_->CreateFile( 2345 kFileInNonExistingDirectory, false, 2346 google_apis::test_util::CreateCopyResultCallback(&error)); 2347 google_apis::test_util::RunBlockingPoolTask(); 2348 EXPECT_EQ(FILE_ERROR_NOT_A_DIRECTORY, error); 2349} 2350 2351} // namespace drive 2352