1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "webkit/browser/fileapi/file_system_operation_impl.h" 6 7 #include "base/bind.h" 8 #include "base/file_util.h" 9 #include "base/files/scoped_temp_dir.h" 10 #include "base/logging.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/run_loop.h" 14 #include "base/strings/stringprintf.h" 15 #include "content/browser/fileapi/mock_file_change_observer.h" 16 #include "content/browser/quota/mock_quota_manager.h" 17 #include "content/browser/quota/mock_quota_manager_proxy.h" 18 #include "content/public/test/async_file_test_helper.h" 19 #include "content/public/test/sandbox_file_system_test_helper.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 #include "url/gurl.h" 22 #include "webkit/browser/fileapi/file_system_context.h" 23 #include "webkit/browser/fileapi/file_system_file_util.h" 24 #include "webkit/browser/fileapi/file_system_operation_context.h" 25 #include "webkit/browser/fileapi/file_system_operation_runner.h" 26 #include "webkit/browser/fileapi/sandbox_file_system_backend.h" 27 #include "webkit/browser/quota/quota_manager.h" 28 #include "webkit/browser/quota/quota_manager_proxy.h" 29 #include "webkit/common/blob/shareable_file_reference.h" 30 #include "webkit/common/fileapi/file_system_util.h" 31 32 using content::AsyncFileTestHelper; 33 using fileapi::FileSystemOperation; 34 using fileapi::FileSystemOperationContext; 35 using fileapi::FileSystemOperationRunner; 36 using fileapi::FileSystemURL; 37 using quota::QuotaManager; 38 using quota::QuotaManagerProxy; 39 using webkit_blob::ShareableFileReference; 40 41 namespace content { 42 43 namespace { 44 45 const int kFileOperationStatusNotSet = 1; 46 47 void AssertFileErrorEq(const tracked_objects::Location& from_here, 48 base::File::Error expected, 49 base::File::Error actual) { 50 ASSERT_EQ(expected, actual) << from_here.ToString(); 51 } 52 53 } // namespace 54 55 // Test class for FileSystemOperationImpl. 56 class FileSystemOperationImplTest 57 : public testing::Test { 58 public: 59 FileSystemOperationImplTest() 60 : status_(kFileOperationStatusNotSet), 61 weak_factory_(this) {} 62 63 protected: 64 virtual void SetUp() OVERRIDE { 65 EXPECT_TRUE(base_.CreateUniqueTempDir()); 66 change_observers_ = fileapi::MockFileChangeObserver::CreateList( 67 &change_observer_); 68 69 base::FilePath base_dir = base_.path().AppendASCII("filesystem"); 70 quota_manager_ = 71 new MockQuotaManager(false /* is_incognito */, 72 base_dir, 73 base::MessageLoopProxy::current().get(), 74 base::MessageLoopProxy::current().get(), 75 NULL /* special storage policy */); 76 quota_manager_proxy_ = new MockQuotaManagerProxy( 77 quota_manager(), base::MessageLoopProxy::current().get()); 78 sandbox_file_system_.SetUp(base_dir, quota_manager_proxy_.get()); 79 sandbox_file_system_.AddFileChangeObserver(&change_observer_); 80 } 81 82 virtual void TearDown() OVERRIDE { 83 // Let the client go away before dropping a ref of the quota manager proxy. 84 quota_manager_proxy()->SimulateQuotaManagerDestroyed(); 85 quota_manager_ = NULL; 86 quota_manager_proxy_ = NULL; 87 sandbox_file_system_.TearDown(); 88 } 89 90 FileSystemOperationRunner* operation_runner() { 91 return sandbox_file_system_.operation_runner(); 92 } 93 94 int status() const { return status_; } 95 const base::File::Info& info() const { return info_; } 96 const base::FilePath& path() const { return path_; } 97 const std::vector<fileapi::DirectoryEntry>& entries() const { 98 return entries_; 99 } 100 101 const ShareableFileReference* shareable_file_ref() const { 102 return shareable_file_ref_.get(); 103 } 104 105 MockQuotaManager* quota_manager() { 106 return static_cast<MockQuotaManager*>(quota_manager_.get()); 107 } 108 109 MockQuotaManagerProxy* quota_manager_proxy() { 110 return static_cast<MockQuotaManagerProxy*>( 111 quota_manager_proxy_.get()); 112 } 113 114 fileapi::FileSystemFileUtil* file_util() { 115 return sandbox_file_system_.file_util(); 116 } 117 118 fileapi::MockFileChangeObserver* change_observer() { 119 return &change_observer_; 120 } 121 122 scoped_ptr<FileSystemOperationContext> NewContext() { 123 FileSystemOperationContext* context = 124 sandbox_file_system_.NewOperationContext(); 125 // Grant enough quota for all test cases. 126 context->set_allowed_bytes_growth(1000000); 127 return make_scoped_ptr(context); 128 } 129 130 FileSystemURL URLForPath(const std::string& path) const { 131 return sandbox_file_system_.CreateURLFromUTF8(path); 132 } 133 134 base::FilePath PlatformPath(const std::string& path) { 135 return sandbox_file_system_.GetLocalPath( 136 base::FilePath::FromUTF8Unsafe(path)); 137 } 138 139 bool FileExists(const std::string& path) { 140 return AsyncFileTestHelper::FileExists( 141 sandbox_file_system_.file_system_context(), URLForPath(path), 142 AsyncFileTestHelper::kDontCheckSize); 143 } 144 145 bool DirectoryExists(const std::string& path) { 146 return AsyncFileTestHelper::DirectoryExists( 147 sandbox_file_system_.file_system_context(), URLForPath(path)); 148 } 149 150 FileSystemURL CreateFile(const std::string& path) { 151 FileSystemURL url = URLForPath(path); 152 bool created = false; 153 EXPECT_EQ(base::File::FILE_OK, 154 file_util()->EnsureFileExists(NewContext().get(), 155 url, &created)); 156 EXPECT_TRUE(created); 157 return url; 158 } 159 160 FileSystemURL CreateDirectory(const std::string& path) { 161 FileSystemURL url = URLForPath(path); 162 EXPECT_EQ(base::File::FILE_OK, 163 file_util()->CreateDirectory(NewContext().get(), url, 164 false /* exclusive */, true)); 165 return url; 166 } 167 168 int64 GetFileSize(const std::string& path) { 169 base::File::Info info; 170 EXPECT_TRUE(base::GetFileInfo(PlatformPath(path), &info)); 171 return info.size; 172 } 173 174 // Callbacks for recording test results. 175 FileSystemOperation::StatusCallback RecordStatusCallback() { 176 return base::Bind(&FileSystemOperationImplTest::DidFinish, 177 weak_factory_.GetWeakPtr()); 178 } 179 180 FileSystemOperation::ReadDirectoryCallback 181 RecordReadDirectoryCallback() { 182 return base::Bind(&FileSystemOperationImplTest::DidReadDirectory, 183 weak_factory_.GetWeakPtr()); 184 } 185 186 FileSystemOperation::GetMetadataCallback RecordMetadataCallback() { 187 return base::Bind(&FileSystemOperationImplTest::DidGetMetadata, 188 weak_factory_.GetWeakPtr()); 189 } 190 191 FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback() { 192 return base::Bind(&FileSystemOperationImplTest::DidCreateSnapshotFile, 193 weak_factory_.GetWeakPtr()); 194 } 195 196 void DidFinish(base::File::Error status) { 197 status_ = status; 198 } 199 200 void DidReadDirectory( 201 base::File::Error status, 202 const std::vector<fileapi::DirectoryEntry>& entries, 203 bool /* has_more */) { 204 entries_ = entries; 205 status_ = status; 206 } 207 208 void DidGetMetadata(base::File::Error status, 209 const base::File::Info& info) { 210 info_ = info; 211 status_ = status; 212 } 213 214 void DidCreateSnapshotFile( 215 base::File::Error status, 216 const base::File::Info& info, 217 const base::FilePath& platform_path, 218 const scoped_refptr<ShareableFileReference>& shareable_file_ref) { 219 info_ = info; 220 path_ = platform_path; 221 status_ = status; 222 shareable_file_ref_ = shareable_file_ref; 223 } 224 225 int64 GetDataSizeOnDisk() { 226 return sandbox_file_system_.ComputeCurrentOriginUsage() - 227 sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage(); 228 } 229 230 void GetUsageAndQuota(int64* usage, int64* quota) { 231 quota::QuotaStatusCode status = 232 AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(), 233 sandbox_file_system_.origin(), 234 sandbox_file_system_.type(), 235 usage, 236 quota); 237 base::RunLoop().RunUntilIdle(); 238 ASSERT_EQ(quota::kQuotaStatusOk, status); 239 } 240 241 int64 ComputePathCost(const FileSystemURL& url) { 242 int64 base_usage; 243 GetUsageAndQuota(&base_usage, NULL); 244 245 AsyncFileTestHelper::CreateFile( 246 sandbox_file_system_.file_system_context(), url); 247 operation_runner()->Remove(url, false /* recursive */, 248 base::Bind(&AssertFileErrorEq, FROM_HERE, 249 base::File::FILE_OK)); 250 base::RunLoop().RunUntilIdle(); 251 change_observer()->ResetCount(); 252 253 int64 total_usage; 254 GetUsageAndQuota(&total_usage, NULL); 255 return total_usage - base_usage; 256 } 257 258 void GrantQuotaForCurrentUsage() { 259 int64 usage; 260 GetUsageAndQuota(&usage, NULL); 261 quota_manager()->SetQuota(sandbox_file_system_.origin(), 262 sandbox_file_system_.storage_type(), 263 usage); 264 } 265 266 int64 GetUsage() { 267 int64 usage = 0; 268 GetUsageAndQuota(&usage, NULL); 269 return usage; 270 } 271 272 void AddQuota(int64 quota_delta) { 273 int64 quota; 274 GetUsageAndQuota(NULL, "a); 275 quota_manager()->SetQuota(sandbox_file_system_.origin(), 276 sandbox_file_system_.storage_type(), 277 quota + quota_delta); 278 } 279 280 private: 281 base::MessageLoop message_loop_; 282 scoped_refptr<QuotaManager> quota_manager_; 283 scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; 284 285 // Common temp base for nondestructive uses. 286 base::ScopedTempDir base_; 287 288 SandboxFileSystemTestHelper sandbox_file_system_; 289 290 // For post-operation status. 291 int status_; 292 base::File::Info info_; 293 base::FilePath path_; 294 std::vector<fileapi::DirectoryEntry> entries_; 295 scoped_refptr<ShareableFileReference> shareable_file_ref_; 296 297 fileapi::MockFileChangeObserver change_observer_; 298 fileapi::ChangeObserverList change_observers_; 299 300 base::WeakPtrFactory<FileSystemOperationImplTest> weak_factory_; 301 302 DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplTest); 303 }; 304 305 TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDoesntExist) { 306 change_observer()->ResetCount(); 307 operation_runner()->Move(URLForPath("a"), URLForPath("b"), 308 FileSystemOperation::OPTION_NONE, 309 RecordStatusCallback()); 310 base::RunLoop().RunUntilIdle(); 311 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 312 EXPECT_TRUE(change_observer()->HasNoChange()); 313 } 314 315 TEST_F(FileSystemOperationImplTest, TestMoveFailureContainsPath) { 316 FileSystemURL src_dir(CreateDirectory("src")); 317 FileSystemURL dest_dir(CreateDirectory("src/dest")); 318 319 operation_runner()->Move(src_dir, dest_dir, 320 FileSystemOperation::OPTION_NONE, 321 RecordStatusCallback()); 322 base::RunLoop().RunUntilIdle(); 323 EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status()); 324 EXPECT_TRUE(change_observer()->HasNoChange()); 325 } 326 327 TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDirExistsDestFile) { 328 // Src exists and is dir. Dest is a file. 329 FileSystemURL src_dir(CreateDirectory("src")); 330 FileSystemURL dest_dir(CreateDirectory("dest")); 331 FileSystemURL dest_file(CreateFile("dest/file")); 332 333 operation_runner()->Move(src_dir, dest_file, 334 FileSystemOperation::OPTION_NONE, 335 RecordStatusCallback()); 336 base::RunLoop().RunUntilIdle(); 337 EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status()); 338 EXPECT_TRUE(change_observer()->HasNoChange()); 339 } 340 341 TEST_F(FileSystemOperationImplTest, 342 TestMoveFailureSrcFileExistsDestNonEmptyDir) { 343 // Src exists and is a directory. Dest is a non-empty directory. 344 FileSystemURL src_dir(CreateDirectory("src")); 345 FileSystemURL dest_dir(CreateDirectory("dest")); 346 FileSystemURL dest_file(CreateFile("dest/file")); 347 348 operation_runner()->Move(src_dir, dest_dir, 349 FileSystemOperation::OPTION_NONE, 350 RecordStatusCallback()); 351 base::RunLoop().RunUntilIdle(); 352 EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, status()); 353 EXPECT_TRUE(change_observer()->HasNoChange()); 354 } 355 356 TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcFileExistsDestDir) { 357 // Src exists and is a file. Dest is a directory. 358 FileSystemURL src_dir(CreateDirectory("src")); 359 FileSystemURL src_file(CreateFile("src/file")); 360 FileSystemURL dest_dir(CreateDirectory("dest")); 361 362 operation_runner()->Move(src_file, dest_dir, 363 FileSystemOperation::OPTION_NONE, 364 RecordStatusCallback()); 365 base::RunLoop().RunUntilIdle(); 366 EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status()); 367 EXPECT_TRUE(change_observer()->HasNoChange()); 368 } 369 370 TEST_F(FileSystemOperationImplTest, TestMoveFailureDestParentDoesntExist) { 371 // Dest. parent path does not exist. 372 FileSystemURL src_dir(CreateDirectory("src")); 373 operation_runner()->Move(src_dir, URLForPath("nonexistent/deset"), 374 FileSystemOperation::OPTION_NONE, 375 RecordStatusCallback()); 376 base::RunLoop().RunUntilIdle(); 377 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 378 EXPECT_TRUE(change_observer()->HasNoChange()); 379 } 380 381 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndOverwrite) { 382 FileSystemURL src_file(CreateFile("src")); 383 FileSystemURL dest_file(CreateFile("dest")); 384 385 operation_runner()->Move(src_file, dest_file, 386 FileSystemOperation::OPTION_NONE, 387 RecordStatusCallback()); 388 base::RunLoop().RunUntilIdle(); 389 EXPECT_EQ(base::File::FILE_OK, status()); 390 EXPECT_TRUE(FileExists("dest")); 391 392 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); 393 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); 394 EXPECT_TRUE(change_observer()->HasNoChange()); 395 396 EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count()); 397 } 398 399 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndNew) { 400 FileSystemURL src_file(CreateFile("src")); 401 402 operation_runner()->Move(src_file, URLForPath("new"), 403 FileSystemOperation::OPTION_NONE, 404 RecordStatusCallback()); 405 base::RunLoop().RunUntilIdle(); 406 EXPECT_EQ(base::File::FILE_OK, status()); 407 EXPECT_TRUE(FileExists("new")); 408 409 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count()); 410 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); 411 EXPECT_TRUE(change_observer()->HasNoChange()); 412 } 413 414 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndOverwrite) { 415 FileSystemURL src_dir(CreateDirectory("src")); 416 FileSystemURL dest_dir(CreateDirectory("dest")); 417 418 operation_runner()->Move(src_dir, dest_dir, 419 FileSystemOperation::OPTION_NONE, 420 RecordStatusCallback()); 421 base::RunLoop().RunUntilIdle(); 422 EXPECT_EQ(base::File::FILE_OK, status()); 423 EXPECT_FALSE(DirectoryExists("src")); 424 425 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 426 EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count()); 427 EXPECT_TRUE(change_observer()->HasNoChange()); 428 429 // Make sure we've overwritten but not moved the source under the |dest_dir|. 430 EXPECT_TRUE(DirectoryExists("dest")); 431 EXPECT_FALSE(DirectoryExists("dest/src")); 432 } 433 434 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndNew) { 435 FileSystemURL src_dir(CreateDirectory("src")); 436 FileSystemURL dest_dir(CreateDirectory("dest")); 437 438 operation_runner()->Move(src_dir, URLForPath("dest/new"), 439 FileSystemOperation::OPTION_NONE, 440 RecordStatusCallback()); 441 base::RunLoop().RunUntilIdle(); 442 EXPECT_EQ(base::File::FILE_OK, status()); 443 EXPECT_FALSE(DirectoryExists("src")); 444 EXPECT_TRUE(DirectoryExists("dest/new")); 445 446 EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); 447 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 448 EXPECT_TRUE(change_observer()->HasNoChange()); 449 } 450 451 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirRecursive) { 452 FileSystemURL src_dir(CreateDirectory("src")); 453 CreateDirectory("src/dir"); 454 CreateFile("src/dir/sub"); 455 456 FileSystemURL dest_dir(CreateDirectory("dest")); 457 458 operation_runner()->Move(src_dir, dest_dir, 459 FileSystemOperation::OPTION_NONE, 460 RecordStatusCallback()); 461 base::RunLoop().RunUntilIdle(); 462 EXPECT_EQ(base::File::FILE_OK, status()); 463 EXPECT_TRUE(DirectoryExists("dest/dir")); 464 EXPECT_TRUE(FileExists("dest/dir/sub")); 465 466 EXPECT_EQ(3, change_observer()->get_and_reset_remove_directory_count()); 467 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); 468 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); 469 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count()); 470 EXPECT_TRUE(change_observer()->HasNoChange()); 471 } 472 473 TEST_F(FileSystemOperationImplTest, TestMoveSuccessSamePath) { 474 FileSystemURL src_dir(CreateDirectory("src")); 475 CreateDirectory("src/dir"); 476 CreateFile("src/dir/sub"); 477 478 operation_runner()->Move(src_dir, src_dir, 479 FileSystemOperation::OPTION_NONE, 480 RecordStatusCallback()); 481 base::RunLoop().RunUntilIdle(); 482 EXPECT_EQ(base::File::FILE_OK, status()); 483 EXPECT_TRUE(DirectoryExists("src/dir")); 484 EXPECT_TRUE(FileExists("src/dir/sub")); 485 486 EXPECT_EQ(0, change_observer()->get_and_reset_remove_directory_count()); 487 EXPECT_EQ(0, change_observer()->get_and_reset_create_directory_count()); 488 EXPECT_EQ(0, change_observer()->get_and_reset_remove_file_count()); 489 EXPECT_EQ(0, change_observer()->get_and_reset_create_file_from_count()); 490 EXPECT_TRUE(change_observer()->HasNoChange()); 491 } 492 493 TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDoesntExist) { 494 operation_runner()->Copy(URLForPath("a"), URLForPath("b"), 495 FileSystemOperation::OPTION_NONE, 496 FileSystemOperationRunner::CopyProgressCallback(), 497 RecordStatusCallback()); 498 base::RunLoop().RunUntilIdle(); 499 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 500 EXPECT_TRUE(change_observer()->HasNoChange()); 501 } 502 503 TEST_F(FileSystemOperationImplTest, TestCopyFailureContainsPath) { 504 FileSystemURL src_dir(CreateDirectory("src")); 505 FileSystemURL dest_dir(CreateDirectory("src/dir")); 506 507 operation_runner()->Copy(src_dir, dest_dir, 508 FileSystemOperation::OPTION_NONE, 509 FileSystemOperationRunner::CopyProgressCallback(), 510 RecordStatusCallback()); 511 base::RunLoop().RunUntilIdle(); 512 EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status()); 513 EXPECT_TRUE(change_observer()->HasNoChange()); 514 } 515 516 TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDirExistsDestFile) { 517 // Src exists and is dir. Dest is a file. 518 FileSystemURL src_dir(CreateDirectory("src")); 519 FileSystemURL dest_dir(CreateDirectory("dest")); 520 FileSystemURL dest_file(CreateFile("dest/file")); 521 522 operation_runner()->Copy(src_dir, dest_file, 523 FileSystemOperation::OPTION_NONE, 524 FileSystemOperationRunner::CopyProgressCallback(), 525 RecordStatusCallback()); 526 base::RunLoop().RunUntilIdle(); 527 EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status()); 528 EXPECT_TRUE(change_observer()->HasNoChange()); 529 } 530 531 TEST_F(FileSystemOperationImplTest, 532 TestCopyFailureSrcFileExistsDestNonEmptyDir) { 533 // Src exists and is a directory. Dest is a non-empty directory. 534 FileSystemURL src_dir(CreateDirectory("src")); 535 FileSystemURL dest_dir(CreateDirectory("dest")); 536 FileSystemURL dest_file(CreateFile("dest/file")); 537 538 operation_runner()->Copy(src_dir, dest_dir, 539 FileSystemOperation::OPTION_NONE, 540 FileSystemOperationRunner::CopyProgressCallback(), 541 RecordStatusCallback()); 542 base::RunLoop().RunUntilIdle(); 543 EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, status()); 544 EXPECT_TRUE(change_observer()->HasNoChange()); 545 } 546 547 TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcFileExistsDestDir) { 548 // Src exists and is a file. Dest is a directory. 549 FileSystemURL src_file(CreateFile("src")); 550 FileSystemURL dest_dir(CreateDirectory("dest")); 551 552 operation_runner()->Copy(src_file, dest_dir, 553 FileSystemOperation::OPTION_NONE, 554 FileSystemOperationRunner::CopyProgressCallback(), 555 RecordStatusCallback()); 556 base::RunLoop().RunUntilIdle(); 557 EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status()); 558 EXPECT_TRUE(change_observer()->HasNoChange()); 559 } 560 561 TEST_F(FileSystemOperationImplTest, TestCopyFailureDestParentDoesntExist) { 562 // Dest. parent path does not exist. 563 FileSystemURL src_dir(CreateDirectory("src")); 564 565 operation_runner()->Copy(src_dir, URLForPath("nonexistent/dest"), 566 FileSystemOperation::OPTION_NONE, 567 FileSystemOperationRunner::CopyProgressCallback(), 568 RecordStatusCallback()); 569 base::RunLoop().RunUntilIdle(); 570 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 571 EXPECT_TRUE(change_observer()->HasNoChange()); 572 } 573 574 TEST_F(FileSystemOperationImplTest, TestCopyFailureByQuota) { 575 FileSystemURL src_dir(CreateDirectory("src")); 576 FileSystemURL src_file(CreateFile("src/file")); 577 FileSystemURL dest_dir(CreateDirectory("dest")); 578 operation_runner()->Truncate(src_file, 6, RecordStatusCallback()); 579 base::RunLoop().RunUntilIdle(); 580 EXPECT_EQ(base::File::FILE_OK, status()); 581 EXPECT_EQ(6, GetFileSize("src/file")); 582 583 FileSystemURL dest_file(URLForPath("dest/file")); 584 int64 dest_path_cost = ComputePathCost(dest_file); 585 GrantQuotaForCurrentUsage(); 586 AddQuota(6 + dest_path_cost - 1); 587 588 operation_runner()->Copy(src_file, dest_file, 589 FileSystemOperation::OPTION_NONE, 590 FileSystemOperationRunner::CopyProgressCallback(), 591 RecordStatusCallback()); 592 base::RunLoop().RunUntilIdle(); 593 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status()); 594 EXPECT_FALSE(FileExists("dest/file")); 595 } 596 597 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndOverwrite) { 598 FileSystemURL src_file(CreateFile("src")); 599 FileSystemURL dest_file(CreateFile("dest")); 600 601 operation_runner()->Copy(src_file, dest_file, 602 FileSystemOperation::OPTION_NONE, 603 FileSystemOperationRunner::CopyProgressCallback(), 604 RecordStatusCallback()); 605 base::RunLoop().RunUntilIdle(); 606 EXPECT_EQ(base::File::FILE_OK, status()); 607 EXPECT_TRUE(FileExists("dest")); 608 EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count()); 609 610 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); 611 EXPECT_TRUE(change_observer()->HasNoChange()); 612 } 613 614 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndNew) { 615 FileSystemURL src_file(CreateFile("src")); 616 617 operation_runner()->Copy(src_file, URLForPath("new"), 618 FileSystemOperation::OPTION_NONE, 619 FileSystemOperationRunner::CopyProgressCallback(), 620 RecordStatusCallback()); 621 base::RunLoop().RunUntilIdle(); 622 EXPECT_EQ(base::File::FILE_OK, status()); 623 EXPECT_TRUE(FileExists("new")); 624 EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count()); 625 626 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count()); 627 EXPECT_TRUE(change_observer()->HasNoChange()); 628 } 629 630 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndOverwrite) { 631 FileSystemURL src_dir(CreateDirectory("src")); 632 FileSystemURL dest_dir(CreateDirectory("dest")); 633 634 operation_runner()->Copy(src_dir, dest_dir, 635 FileSystemOperation::OPTION_NONE, 636 FileSystemOperationRunner::CopyProgressCallback(), 637 RecordStatusCallback()); 638 base::RunLoop().RunUntilIdle(); 639 EXPECT_EQ(base::File::FILE_OK, status()); 640 641 // Make sure we've overwritten but not copied the source under the |dest_dir|. 642 EXPECT_TRUE(DirectoryExists("dest")); 643 EXPECT_FALSE(DirectoryExists("dest/src")); 644 EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 3); 645 646 EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); 647 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 648 EXPECT_TRUE(change_observer()->HasNoChange()); 649 } 650 651 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndNew) { 652 FileSystemURL src_dir(CreateDirectory("src")); 653 FileSystemURL dest_dir_new(URLForPath("dest")); 654 655 operation_runner()->Copy(src_dir, dest_dir_new, 656 FileSystemOperation::OPTION_NONE, 657 FileSystemOperationRunner::CopyProgressCallback(), 658 RecordStatusCallback()); 659 base::RunLoop().RunUntilIdle(); 660 EXPECT_EQ(base::File::FILE_OK, status()); 661 EXPECT_TRUE(DirectoryExists("dest")); 662 EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 2); 663 664 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 665 EXPECT_TRUE(change_observer()->HasNoChange()); 666 } 667 668 TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirRecursive) { 669 FileSystemURL src_dir(CreateDirectory("src")); 670 CreateDirectory("src/dir"); 671 CreateFile("src/dir/sub"); 672 673 FileSystemURL dest_dir(CreateDirectory("dest")); 674 675 operation_runner()->Copy(src_dir, dest_dir, 676 FileSystemOperation::OPTION_NONE, 677 FileSystemOperationRunner::CopyProgressCallback(), 678 RecordStatusCallback()); 679 base::RunLoop().RunUntilIdle(); 680 681 EXPECT_EQ(base::File::FILE_OK, status()); 682 EXPECT_TRUE(DirectoryExists("dest/dir")); 683 EXPECT_TRUE(FileExists("dest/dir/sub")); 684 685 // For recursive copy we may record multiple read access. 686 EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 1); 687 688 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); 689 EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); 690 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count()); 691 EXPECT_TRUE(change_observer()->HasNoChange()); 692 } 693 694 TEST_F(FileSystemOperationImplTest, TestCopySuccessSamePath) { 695 FileSystemURL src_dir(CreateDirectory("src")); 696 CreateDirectory("src/dir"); 697 CreateFile("src/dir/sub"); 698 699 operation_runner()->Copy(src_dir, src_dir, 700 FileSystemOperation::OPTION_NONE, 701 FileSystemOperationRunner::CopyProgressCallback(), 702 RecordStatusCallback()); 703 base::RunLoop().RunUntilIdle(); 704 705 EXPECT_EQ(base::File::FILE_OK, status()); 706 EXPECT_TRUE(DirectoryExists("src/dir")); 707 EXPECT_TRUE(FileExists("src/dir/sub")); 708 709 EXPECT_EQ(0, change_observer()->get_and_reset_create_directory_count()); 710 EXPECT_EQ(0, change_observer()->get_and_reset_remove_file_count()); 711 EXPECT_EQ(0, change_observer()->get_and_reset_create_file_from_count()); 712 EXPECT_TRUE(change_observer()->HasNoChange()); 713 } 714 715 TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) { 716 base::FilePath src_local_disk_file_path; 717 base::CreateTemporaryFile(&src_local_disk_file_path); 718 const char test_data[] = "foo"; 719 int data_size = ARRAYSIZE_UNSAFE(test_data); 720 base::WriteFile(src_local_disk_file_path, test_data, data_size); 721 722 FileSystemURL dest_dir(CreateDirectory("dest")); 723 724 int64 before_usage; 725 GetUsageAndQuota(&before_usage, NULL); 726 727 // Check that the file copied and corresponding usage increased. 728 operation_runner()->CopyInForeignFile(src_local_disk_file_path, 729 URLForPath("dest/file"), 730 RecordStatusCallback()); 731 base::RunLoop().RunUntilIdle(); 732 733 EXPECT_EQ(1, change_observer()->create_file_count()); 734 EXPECT_EQ(base::File::FILE_OK, status()); 735 EXPECT_TRUE(FileExists("dest/file")); 736 int64 after_usage; 737 GetUsageAndQuota(&after_usage, NULL); 738 EXPECT_GT(after_usage, before_usage); 739 740 // Compare contents of src and copied file. 741 char buffer[100]; 742 EXPECT_EQ(data_size, base::ReadFile(PlatformPath("dest/file"), 743 buffer, data_size)); 744 for (int i = 0; i < data_size; ++i) 745 EXPECT_EQ(test_data[i], buffer[i]); 746 } 747 748 TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileFailureByQuota) { 749 base::FilePath src_local_disk_file_path; 750 base::CreateTemporaryFile(&src_local_disk_file_path); 751 const char test_data[] = "foo"; 752 base::WriteFile(src_local_disk_file_path, test_data, 753 ARRAYSIZE_UNSAFE(test_data)); 754 755 FileSystemURL dest_dir(CreateDirectory("dest")); 756 757 GrantQuotaForCurrentUsage(); 758 operation_runner()->CopyInForeignFile(src_local_disk_file_path, 759 URLForPath("dest/file"), 760 RecordStatusCallback()); 761 base::RunLoop().RunUntilIdle(); 762 763 EXPECT_FALSE(FileExists("dest/file")); 764 EXPECT_EQ(0, change_observer()->create_file_count()); 765 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status()); 766 } 767 768 TEST_F(FileSystemOperationImplTest, TestCreateFileFailure) { 769 // Already existing file and exclusive true. 770 FileSystemURL file(CreateFile("file")); 771 operation_runner()->CreateFile(file, true, RecordStatusCallback()); 772 base::RunLoop().RunUntilIdle(); 773 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, status()); 774 EXPECT_TRUE(change_observer()->HasNoChange()); 775 } 776 777 TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileExists) { 778 // Already existing file and exclusive false. 779 FileSystemURL file(CreateFile("file")); 780 operation_runner()->CreateFile(file, false, RecordStatusCallback()); 781 base::RunLoop().RunUntilIdle(); 782 EXPECT_EQ(base::File::FILE_OK, status()); 783 EXPECT_TRUE(FileExists("file")); 784 785 // The file was already there; did nothing. 786 EXPECT_TRUE(change_observer()->HasNoChange()); 787 } 788 789 TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessExclusive) { 790 // File doesn't exist but exclusive is true. 791 operation_runner()->CreateFile(URLForPath("new"), true, 792 RecordStatusCallback()); 793 base::RunLoop().RunUntilIdle(); 794 EXPECT_EQ(base::File::FILE_OK, status()); 795 EXPECT_TRUE(FileExists("new")); 796 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 797 } 798 799 TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileDoesntExist) { 800 // Non existing file. 801 operation_runner()->CreateFile(URLForPath("nonexistent"), false, 802 RecordStatusCallback()); 803 base::RunLoop().RunUntilIdle(); 804 EXPECT_EQ(base::File::FILE_OK, status()); 805 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 806 } 807 808 TEST_F(FileSystemOperationImplTest, 809 TestCreateDirFailureDestParentDoesntExist) { 810 // Dest. parent path does not exist. 811 operation_runner()->CreateDirectory( 812 URLForPath("nonexistent/dir"), false, false, 813 RecordStatusCallback()); 814 base::RunLoop().RunUntilIdle(); 815 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 816 EXPECT_TRUE(change_observer()->HasNoChange()); 817 } 818 819 TEST_F(FileSystemOperationImplTest, TestCreateDirFailureDirExists) { 820 // Exclusive and dir existing at path. 821 FileSystemURL dir(CreateDirectory("dir")); 822 operation_runner()->CreateDirectory(dir, true, false, 823 RecordStatusCallback()); 824 base::RunLoop().RunUntilIdle(); 825 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, status()); 826 EXPECT_TRUE(change_observer()->HasNoChange()); 827 } 828 829 TEST_F(FileSystemOperationImplTest, TestCreateDirFailureFileExists) { 830 // Exclusive true and file existing at path. 831 FileSystemURL file(CreateFile("file")); 832 operation_runner()->CreateDirectory(file, true, false, 833 RecordStatusCallback()); 834 base::RunLoop().RunUntilIdle(); 835 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, status()); 836 EXPECT_TRUE(change_observer()->HasNoChange()); 837 } 838 839 TEST_F(FileSystemOperationImplTest, TestCreateDirSuccess) { 840 // Dir exists and exclusive is false. 841 FileSystemURL dir(CreateDirectory("dir")); 842 operation_runner()->CreateDirectory(dir, false, false, 843 RecordStatusCallback()); 844 base::RunLoop().RunUntilIdle(); 845 EXPECT_EQ(base::File::FILE_OK, status()); 846 EXPECT_TRUE(change_observer()->HasNoChange()); 847 848 // Dir doesn't exist. 849 operation_runner()->CreateDirectory(URLForPath("new"), false, false, 850 RecordStatusCallback()); 851 base::RunLoop().RunUntilIdle(); 852 EXPECT_EQ(base::File::FILE_OK, status()); 853 EXPECT_TRUE(DirectoryExists("new")); 854 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 855 } 856 857 TEST_F(FileSystemOperationImplTest, TestCreateDirSuccessExclusive) { 858 // Dir doesn't exist. 859 operation_runner()->CreateDirectory(URLForPath("new"), true, false, 860 RecordStatusCallback()); 861 base::RunLoop().RunUntilIdle(); 862 EXPECT_EQ(base::File::FILE_OK, status()); 863 EXPECT_TRUE(DirectoryExists("new")); 864 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 865 EXPECT_TRUE(change_observer()->HasNoChange()); 866 } 867 868 TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataFailure) { 869 operation_runner()->GetMetadata(URLForPath("nonexistent"), 870 RecordMetadataCallback()); 871 base::RunLoop().RunUntilIdle(); 872 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 873 874 operation_runner()->FileExists(URLForPath("nonexistent"), 875 RecordStatusCallback()); 876 base::RunLoop().RunUntilIdle(); 877 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 878 879 operation_runner()->DirectoryExists(URLForPath("nonexistent"), 880 RecordStatusCallback()); 881 base::RunLoop().RunUntilIdle(); 882 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 883 EXPECT_TRUE(change_observer()->HasNoChange()); 884 } 885 886 TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataSuccess) { 887 FileSystemURL dir(CreateDirectory("dir")); 888 FileSystemURL file(CreateFile("dir/file")); 889 int read_access = 0; 890 891 operation_runner()->DirectoryExists(dir, RecordStatusCallback()); 892 base::RunLoop().RunUntilIdle(); 893 EXPECT_EQ(base::File::FILE_OK, status()); 894 ++read_access; 895 896 operation_runner()->GetMetadata(dir, RecordMetadataCallback()); 897 base::RunLoop().RunUntilIdle(); 898 EXPECT_EQ(base::File::FILE_OK, status()); 899 EXPECT_TRUE(info().is_directory); 900 ++read_access; 901 902 operation_runner()->FileExists(file, RecordStatusCallback()); 903 base::RunLoop().RunUntilIdle(); 904 EXPECT_EQ(base::File::FILE_OK, status()); 905 ++read_access; 906 907 operation_runner()->GetMetadata(file, RecordMetadataCallback()); 908 base::RunLoop().RunUntilIdle(); 909 EXPECT_EQ(base::File::FILE_OK, status()); 910 EXPECT_FALSE(info().is_directory); 911 ++read_access; 912 913 EXPECT_EQ(read_access, 914 quota_manager_proxy()->notify_storage_accessed_count()); 915 EXPECT_TRUE(change_observer()->HasNoChange()); 916 } 917 918 TEST_F(FileSystemOperationImplTest, TestTypeMismatchErrors) { 919 FileSystemURL dir(CreateDirectory("dir")); 920 operation_runner()->FileExists(dir, RecordStatusCallback()); 921 base::RunLoop().RunUntilIdle(); 922 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE, status()); 923 924 FileSystemURL file(CreateFile("file")); 925 operation_runner()->DirectoryExists(file, RecordStatusCallback()); 926 base::RunLoop().RunUntilIdle(); 927 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, status()); 928 } 929 930 TEST_F(FileSystemOperationImplTest, TestReadDirFailure) { 931 // Path doesn't exist 932 operation_runner()->ReadDirectory(URLForPath("nonexistent"), 933 RecordReadDirectoryCallback()); 934 base::RunLoop().RunUntilIdle(); 935 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 936 937 // File exists. 938 FileSystemURL file(CreateFile("file")); 939 operation_runner()->ReadDirectory(file, RecordReadDirectoryCallback()); 940 base::RunLoop().RunUntilIdle(); 941 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, status()); 942 EXPECT_TRUE(change_observer()->HasNoChange()); 943 } 944 945 TEST_F(FileSystemOperationImplTest, TestReadDirSuccess) { 946 // parent_dir 947 // | | 948 // child_dir child_file 949 // Verify reading parent_dir. 950 FileSystemURL parent_dir(CreateDirectory("dir")); 951 FileSystemURL child_dir(CreateDirectory("dir/child_dir")); 952 FileSystemURL child_file(CreateFile("dir/child_file")); 953 954 operation_runner()->ReadDirectory(parent_dir, RecordReadDirectoryCallback()); 955 base::RunLoop().RunUntilIdle(); 956 EXPECT_EQ(base::File::FILE_OK, status()); 957 EXPECT_EQ(2u, entries().size()); 958 959 for (size_t i = 0; i < entries().size(); ++i) { 960 if (entries()[i].is_directory) 961 EXPECT_EQ(FILE_PATH_LITERAL("child_dir"), entries()[i].name); 962 else 963 EXPECT_EQ(FILE_PATH_LITERAL("child_file"), entries()[i].name); 964 } 965 EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count()); 966 EXPECT_TRUE(change_observer()->HasNoChange()); 967 } 968 969 TEST_F(FileSystemOperationImplTest, TestRemoveFailure) { 970 // Path doesn't exist. 971 operation_runner()->Remove(URLForPath("nonexistent"), false /* recursive */, 972 RecordStatusCallback()); 973 base::RunLoop().RunUntilIdle(); 974 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status()); 975 976 // It's an error to try to remove a non-empty directory if recursive flag 977 // is false. 978 // parent_dir 979 // | | 980 // child_dir child_file 981 // Verify deleting parent_dir. 982 FileSystemURL parent_dir(CreateDirectory("dir")); 983 FileSystemURL child_dir(CreateDirectory("dir/child_dir")); 984 FileSystemURL child_file(CreateFile("dir/child_file")); 985 986 operation_runner()->Remove(parent_dir, false /* recursive */, 987 RecordStatusCallback()); 988 base::RunLoop().RunUntilIdle(); 989 EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, status()); 990 EXPECT_TRUE(change_observer()->HasNoChange()); 991 } 992 993 TEST_F(FileSystemOperationImplTest, TestRemoveSuccess) { 994 FileSystemURL empty_dir(CreateDirectory("empty_dir")); 995 EXPECT_TRUE(DirectoryExists("empty_dir")); 996 operation_runner()->Remove(empty_dir, false /* recursive */, 997 RecordStatusCallback()); 998 base::RunLoop().RunUntilIdle(); 999 EXPECT_EQ(base::File::FILE_OK, status()); 1000 EXPECT_FALSE(DirectoryExists("empty_dir")); 1001 1002 EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); 1003 EXPECT_TRUE(change_observer()->HasNoChange()); 1004 } 1005 1006 TEST_F(FileSystemOperationImplTest, TestRemoveSuccessRecursive) { 1007 // Removing a non-empty directory with recursive flag == true should be ok. 1008 // parent_dir 1009 // | | 1010 // child_dir child_files 1011 // | 1012 // child_files 1013 // 1014 // Verify deleting parent_dir. 1015 FileSystemURL parent_dir(CreateDirectory("dir")); 1016 for (int i = 0; i < 8; ++i) 1017 CreateFile(base::StringPrintf("dir/file-%d", i)); 1018 FileSystemURL child_dir(CreateDirectory("dir/child_dir")); 1019 for (int i = 0; i < 8; ++i) 1020 CreateFile(base::StringPrintf("dir/child_dir/file-%d", i)); 1021 1022 operation_runner()->Remove(parent_dir, true /* recursive */, 1023 RecordStatusCallback()); 1024 base::RunLoop().RunUntilIdle(); 1025 EXPECT_EQ(base::File::FILE_OK, status()); 1026 EXPECT_FALSE(DirectoryExists("parent_dir")); 1027 1028 EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count()); 1029 EXPECT_EQ(16, change_observer()->get_and_reset_remove_file_count()); 1030 EXPECT_TRUE(change_observer()->HasNoChange()); 1031 } 1032 1033 TEST_F(FileSystemOperationImplTest, TestTruncate) { 1034 FileSystemURL file(CreateFile("file")); 1035 base::FilePath platform_path = PlatformPath("file"); 1036 1037 char test_data[] = "test data"; 1038 int data_size = static_cast<int>(sizeof(test_data)); 1039 EXPECT_EQ(data_size, 1040 base::WriteFile(platform_path, test_data, data_size)); 1041 1042 // Check that its length is the size of the data written. 1043 operation_runner()->GetMetadata(file, RecordMetadataCallback()); 1044 base::RunLoop().RunUntilIdle(); 1045 EXPECT_EQ(base::File::FILE_OK, status()); 1046 EXPECT_FALSE(info().is_directory); 1047 EXPECT_EQ(data_size, info().size); 1048 1049 // Extend the file by truncating it. 1050 int length = 17; 1051 operation_runner()->Truncate(file, length, RecordStatusCallback()); 1052 base::RunLoop().RunUntilIdle(); 1053 EXPECT_EQ(base::File::FILE_OK, status()); 1054 1055 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); 1056 EXPECT_TRUE(change_observer()->HasNoChange()); 1057 1058 // Check that its length is now 17 and that it's all zeroes after the test 1059 // data. 1060 EXPECT_EQ(length, GetFileSize("file")); 1061 char data[100]; 1062 EXPECT_EQ(length, base::ReadFile(platform_path, data, length)); 1063 for (int i = 0; i < length; ++i) { 1064 if (i < static_cast<int>(sizeof(test_data))) 1065 EXPECT_EQ(test_data[i], data[i]); 1066 else 1067 EXPECT_EQ(0, data[i]); 1068 } 1069 1070 // Shorten the file by truncating it. 1071 length = 3; 1072 operation_runner()->Truncate(file, length, RecordStatusCallback()); 1073 base::RunLoop().RunUntilIdle(); 1074 EXPECT_EQ(base::File::FILE_OK, status()); 1075 1076 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); 1077 EXPECT_TRUE(change_observer()->HasNoChange()); 1078 1079 // Check that its length is now 3 and that it contains only bits of test data. 1080 EXPECT_EQ(length, GetFileSize("file")); 1081 EXPECT_EQ(length, base::ReadFile(platform_path, data, length)); 1082 for (int i = 0; i < length; ++i) 1083 EXPECT_EQ(test_data[i], data[i]); 1084 1085 // Truncate is not a 'read' access. (Here expected access count is 1 1086 // since we made 1 read access for GetMetadata.) 1087 EXPECT_EQ(1, quota_manager_proxy()->notify_storage_accessed_count()); 1088 } 1089 1090 TEST_F(FileSystemOperationImplTest, TestTruncateFailureByQuota) { 1091 FileSystemURL dir(CreateDirectory("dir")); 1092 FileSystemURL file(CreateFile("dir/file")); 1093 1094 GrantQuotaForCurrentUsage(); 1095 AddQuota(10); 1096 1097 operation_runner()->Truncate(file, 10, RecordStatusCallback()); 1098 base::RunLoop().RunUntilIdle(); 1099 EXPECT_EQ(base::File::FILE_OK, status()); 1100 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); 1101 EXPECT_TRUE(change_observer()->HasNoChange()); 1102 1103 EXPECT_EQ(10, GetFileSize("dir/file")); 1104 1105 operation_runner()->Truncate(file, 11, RecordStatusCallback()); 1106 base::RunLoop().RunUntilIdle(); 1107 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status()); 1108 EXPECT_TRUE(change_observer()->HasNoChange()); 1109 1110 EXPECT_EQ(10, GetFileSize("dir/file")); 1111 } 1112 1113 TEST_F(FileSystemOperationImplTest, TestTouchFile) { 1114 FileSystemURL file(CreateFile("file")); 1115 base::FilePath platform_path = PlatformPath("file"); 1116 1117 base::File::Info info; 1118 EXPECT_TRUE(base::GetFileInfo(platform_path, &info)); 1119 EXPECT_FALSE(info.is_directory); 1120 EXPECT_EQ(0, info.size); 1121 const base::Time last_modified = info.last_modified; 1122 const base::Time last_accessed = info.last_accessed; 1123 1124 const base::Time new_modified_time = base::Time::UnixEpoch(); 1125 const base::Time new_accessed_time = new_modified_time + 1126 base::TimeDelta::FromHours(77); 1127 ASSERT_NE(last_modified, new_modified_time); 1128 ASSERT_NE(last_accessed, new_accessed_time); 1129 1130 operation_runner()->TouchFile(file, new_accessed_time, new_modified_time, 1131 RecordStatusCallback()); 1132 base::RunLoop().RunUntilIdle(); 1133 EXPECT_EQ(base::File::FILE_OK, status()); 1134 EXPECT_TRUE(change_observer()->HasNoChange()); 1135 1136 EXPECT_TRUE(base::GetFileInfo(platform_path, &info)); 1137 // We compare as time_t here to lower our resolution, to avoid false 1138 // negatives caused by conversion to the local filesystem's native 1139 // representation and back. 1140 EXPECT_EQ(new_modified_time.ToTimeT(), info.last_modified.ToTimeT()); 1141 EXPECT_EQ(new_accessed_time.ToTimeT(), info.last_accessed.ToTimeT()); 1142 } 1143 1144 TEST_F(FileSystemOperationImplTest, TestCreateSnapshotFile) { 1145 FileSystemURL dir(CreateDirectory("dir")); 1146 1147 // Create a file for the testing. 1148 operation_runner()->DirectoryExists(dir, RecordStatusCallback()); 1149 FileSystemURL file(CreateFile("dir/file")); 1150 operation_runner()->FileExists(file, RecordStatusCallback()); 1151 base::RunLoop().RunUntilIdle(); 1152 EXPECT_EQ(base::File::FILE_OK, status()); 1153 1154 // See if we can get a 'snapshot' file info for the file. 1155 // Since FileSystemOperationImpl assumes the file exists in the local 1156 // directory it should just returns the same metadata and platform_path 1157 // as the file itself. 1158 operation_runner()->CreateSnapshotFile(file, RecordSnapshotFileCallback()); 1159 base::RunLoop().RunUntilIdle(); 1160 EXPECT_EQ(base::File::FILE_OK, status()); 1161 EXPECT_FALSE(info().is_directory); 1162 EXPECT_EQ(PlatformPath("dir/file"), path()); 1163 EXPECT_TRUE(change_observer()->HasNoChange()); 1164 1165 // The FileSystemOpration implementation does not create a 1166 // shareable file reference. 1167 EXPECT_EQ(NULL, shareable_file_ref()); 1168 } 1169 1170 TEST_F(FileSystemOperationImplTest, 1171 TestMoveSuccessSrcDirRecursiveWithQuota) { 1172 FileSystemURL src(CreateDirectory("src")); 1173 int src_path_cost = GetUsage(); 1174 1175 FileSystemURL dest(CreateDirectory("dest")); 1176 FileSystemURL child_file1(CreateFile("src/file1")); 1177 FileSystemURL child_file2(CreateFile("src/file2")); 1178 FileSystemURL child_dir(CreateDirectory("src/dir")); 1179 FileSystemURL grandchild_file1(CreateFile("src/dir/file1")); 1180 FileSystemURL grandchild_file2(CreateFile("src/dir/file2")); 1181 1182 int total_path_cost = GetUsage(); 1183 EXPECT_EQ(0, GetDataSizeOnDisk()); 1184 1185 operation_runner()->Truncate( 1186 child_file1, 5000, 1187 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1188 operation_runner()->Truncate( 1189 child_file2, 400, 1190 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1191 operation_runner()->Truncate( 1192 grandchild_file1, 30, 1193 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1194 operation_runner()->Truncate( 1195 grandchild_file2, 2, 1196 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1197 base::RunLoop().RunUntilIdle(); 1198 1199 const int64 all_file_size = 5000 + 400 + 30 + 2; 1200 EXPECT_EQ(all_file_size, GetDataSizeOnDisk()); 1201 EXPECT_EQ(all_file_size + total_path_cost, GetUsage()); 1202 1203 operation_runner()->Move( 1204 src, dest, FileSystemOperation::OPTION_NONE, 1205 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1206 base::RunLoop().RunUntilIdle(); 1207 1208 EXPECT_FALSE(DirectoryExists("src/dir")); 1209 EXPECT_FALSE(FileExists("src/dir/file2")); 1210 EXPECT_TRUE(DirectoryExists("dest/dir")); 1211 EXPECT_TRUE(FileExists("dest/dir/file2")); 1212 1213 EXPECT_EQ(all_file_size, GetDataSizeOnDisk()); 1214 EXPECT_EQ(all_file_size + total_path_cost - src_path_cost, 1215 GetUsage()); 1216 } 1217 1218 TEST_F(FileSystemOperationImplTest, 1219 TestCopySuccessSrcDirRecursiveWithQuota) { 1220 FileSystemURL src(CreateDirectory("src")); 1221 FileSystemURL dest1(CreateDirectory("dest1")); 1222 FileSystemURL dest2(CreateDirectory("dest2")); 1223 1224 int64 usage = GetUsage(); 1225 FileSystemURL child_file1(CreateFile("src/file1")); 1226 FileSystemURL child_file2(CreateFile("src/file2")); 1227 FileSystemURL child_dir(CreateDirectory("src/dir")); 1228 int64 child_path_cost = GetUsage() - usage; 1229 usage += child_path_cost; 1230 1231 FileSystemURL grandchild_file1(CreateFile("src/dir/file1")); 1232 FileSystemURL grandchild_file2(CreateFile("src/dir/file2")); 1233 int64 total_path_cost = GetUsage(); 1234 int64 grandchild_path_cost = total_path_cost - usage; 1235 1236 EXPECT_EQ(0, GetDataSizeOnDisk()); 1237 1238 operation_runner()->Truncate( 1239 child_file1, 8000, 1240 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1241 operation_runner()->Truncate( 1242 child_file2, 700, 1243 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1244 operation_runner()->Truncate( 1245 grandchild_file1, 60, 1246 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1247 operation_runner()->Truncate( 1248 grandchild_file2, 5, 1249 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1250 base::RunLoop().RunUntilIdle(); 1251 1252 const int64 child_file_size = 8000 + 700; 1253 const int64 grandchild_file_size = 60 + 5; 1254 const int64 all_file_size = child_file_size + grandchild_file_size; 1255 int64 expected_usage = all_file_size + total_path_cost; 1256 1257 usage = GetUsage(); 1258 EXPECT_EQ(all_file_size, GetDataSizeOnDisk()); 1259 EXPECT_EQ(expected_usage, usage); 1260 1261 // Copy src to dest1. 1262 operation_runner()->Copy( 1263 src, dest1, FileSystemOperation::OPTION_NONE, 1264 FileSystemOperationRunner::CopyProgressCallback(), 1265 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1266 base::RunLoop().RunUntilIdle(); 1267 1268 expected_usage += all_file_size + child_path_cost + grandchild_path_cost; 1269 EXPECT_TRUE(DirectoryExists("src/dir")); 1270 EXPECT_TRUE(FileExists("src/dir/file2")); 1271 EXPECT_TRUE(DirectoryExists("dest1/dir")); 1272 EXPECT_TRUE(FileExists("dest1/dir/file2")); 1273 1274 EXPECT_EQ(2 * all_file_size, GetDataSizeOnDisk()); 1275 EXPECT_EQ(expected_usage, GetUsage()); 1276 1277 // Copy src/dir to dest2. 1278 operation_runner()->Copy( 1279 child_dir, dest2, FileSystemOperation::OPTION_NONE, 1280 FileSystemOperationRunner::CopyProgressCallback(), 1281 base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK)); 1282 base::RunLoop().RunUntilIdle(); 1283 1284 expected_usage += grandchild_file_size + grandchild_path_cost; 1285 usage = GetUsage(); 1286 EXPECT_EQ(2 * child_file_size + 3 * grandchild_file_size, 1287 GetDataSizeOnDisk()); 1288 EXPECT_EQ(expected_usage, usage); 1289 } 1290 1291 } // namespace content 1292