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 <set> 6 #include <string> 7 #include <vector> 8 9 #include "base/bind.h" 10 #include "base/file_util.h" 11 #include "base/files/file.h" 12 #include "base/files/file_path.h" 13 #include "base/files/scoped_temp_dir.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/run_loop.h" 16 #include "content/browser/fileapi/mock_file_change_observer.h" 17 #include "content/public/test/async_file_test_helper.h" 18 #include "content/public/test/mock_special_storage_policy.h" 19 #include "content/public/test/sandbox_file_system_test_helper.h" 20 #include "content/public/test/test_file_system_context.h" 21 #include "content/test/fileapi_test_file_set.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 #include "webkit/browser/fileapi/external_mount_points.h" 24 #include "webkit/browser/fileapi/file_system_backend.h" 25 #include "webkit/browser/fileapi/file_system_context.h" 26 #include "webkit/browser/fileapi/file_system_operation_context.h" 27 #include "webkit/browser/fileapi/file_system_usage_cache.h" 28 #include "webkit/browser/fileapi/obfuscated_file_util.h" 29 #include "webkit/browser/fileapi/sandbox_directory_database.h" 30 #include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h" 31 #include "webkit/browser/fileapi/sandbox_isolated_origin_database.h" 32 #include "webkit/browser/fileapi/sandbox_origin_database.h" 33 #include "webkit/browser/quota/quota_manager.h" 34 #include "webkit/common/database/database_identifier.h" 35 #include "webkit/common/quota/quota_types.h" 36 37 using content::AsyncFileTestHelper; 38 using fileapi::FileSystemContext; 39 using fileapi::FileSystemOperation; 40 using fileapi::FileSystemOperationContext; 41 using fileapi::FileSystemURL; 42 using fileapi::ObfuscatedFileUtil; 43 using fileapi::SandboxDirectoryDatabase; 44 using fileapi::SandboxIsolatedOriginDatabase; 45 using fileapi::kFileSystemTypeTemporary; 46 using fileapi::kFileSystemTypePersistent; 47 48 namespace content { 49 50 namespace { 51 52 bool FileExists(const base::FilePath& path) { 53 return base::PathExists(path) && !base::DirectoryExists(path); 54 } 55 56 int64 GetSize(const base::FilePath& path) { 57 int64 size; 58 EXPECT_TRUE(base::GetFileSize(path, &size)); 59 return size; 60 } 61 62 // After a move, the dest exists and the source doesn't. 63 // After a copy, both source and dest exist. 64 struct CopyMoveTestCaseRecord { 65 bool is_copy_not_move; 66 const char source_path[64]; 67 const char dest_path[64]; 68 bool cause_overwrite; 69 }; 70 71 const CopyMoveTestCaseRecord kCopyMoveTestCases[] = { 72 // This is the combinatoric set of: 73 // rename vs. same-name 74 // different directory vs. same directory 75 // overwrite vs. no-overwrite 76 // copy vs. move 77 // We can never be called with source and destination paths identical, so 78 // those cases are omitted. 79 {true, "dir0/file0", "dir0/file1", false}, 80 {false, "dir0/file0", "dir0/file1", false}, 81 {true, "dir0/file0", "dir0/file1", true}, 82 {false, "dir0/file0", "dir0/file1", true}, 83 84 {true, "dir0/file0", "dir1/file0", false}, 85 {false, "dir0/file0", "dir1/file0", false}, 86 {true, "dir0/file0", "dir1/file0", true}, 87 {false, "dir0/file0", "dir1/file0", true}, 88 {true, "dir0/file0", "dir1/file1", false}, 89 {false, "dir0/file0", "dir1/file1", false}, 90 {true, "dir0/file0", "dir1/file1", true}, 91 {false, "dir0/file0", "dir1/file1", true}, 92 }; 93 94 struct OriginEnumerationTestRecord { 95 std::string origin_url; 96 bool has_temporary; 97 bool has_persistent; 98 }; 99 100 const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = { 101 {"http://example.com", false, true}, 102 {"http://example1.com", true, false}, 103 {"https://example1.com", true, true}, 104 {"file://", false, true}, 105 {"http://example.com:8000", false, true}, 106 }; 107 108 FileSystemURL FileSystemURLAppend( 109 const FileSystemURL& url, const base::FilePath::StringType& child) { 110 return FileSystemURL::CreateForTest( 111 url.origin(), url.mount_type(), url.virtual_path().Append(child)); 112 } 113 114 FileSystemURL FileSystemURLAppendUTF8( 115 const FileSystemURL& url, const std::string& child) { 116 return FileSystemURL::CreateForTest( 117 url.origin(), 118 url.mount_type(), 119 url.virtual_path().Append(base::FilePath::FromUTF8Unsafe(child))); 120 } 121 122 FileSystemURL FileSystemURLDirName(const FileSystemURL& url) { 123 return FileSystemURL::CreateForTest( 124 url.origin(), url.mount_type(), 125 fileapi::VirtualPath::DirName(url.virtual_path())); 126 } 127 128 std::string GetTypeString(fileapi::FileSystemType type) { 129 return fileapi::SandboxFileSystemBackendDelegate::GetTypeString(type); 130 } 131 132 bool HasFileSystemType(ObfuscatedFileUtil::AbstractOriginEnumerator* enumerator, 133 fileapi::FileSystemType type) { 134 return enumerator->HasTypeDirectory(GetTypeString(type)); 135 } 136 137 } // namespace 138 139 // TODO(ericu): The vast majority of this and the other FSFU subclass tests 140 // could theoretically be shared. It would basically be a FSFU interface 141 // compliance test, and only the subclass-specific bits that look into the 142 // implementation would need to be written per-subclass. 143 class ObfuscatedFileUtilTest : public testing::Test { 144 public: 145 ObfuscatedFileUtilTest() 146 : origin_(GURL("http://www.example.com")), 147 type_(fileapi::kFileSystemTypeTemporary), 148 weak_factory_(this), 149 sandbox_file_system_(origin_, type_), 150 quota_status_(quota::kQuotaStatusUnknown), 151 usage_(-1) { 152 } 153 154 virtual void SetUp() { 155 ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); 156 157 storage_policy_ = new MockSpecialStoragePolicy(); 158 159 quota_manager_ = 160 new quota::QuotaManager(false /* is_incognito */, 161 data_dir_.path(), 162 base::MessageLoopProxy::current().get(), 163 base::MessageLoopProxy::current().get(), 164 storage_policy_.get()); 165 166 // Every time we create a new sandbox_file_system helper, 167 // it creates another context, which creates another path manager, 168 // another sandbox_backend, and another OFU. 169 // We need to pass in the context to skip all that. 170 file_system_context_ = CreateFileSystemContextForTesting( 171 quota_manager_->proxy(), 172 data_dir_.path()); 173 174 sandbox_file_system_.SetUp(file_system_context_.get()); 175 176 change_observers_ = fileapi::MockFileChangeObserver::CreateList( 177 &change_observer_); 178 } 179 180 virtual void TearDown() { 181 quota_manager_ = NULL; 182 sandbox_file_system_.TearDown(); 183 } 184 185 scoped_ptr<FileSystemOperationContext> LimitedContext( 186 int64 allowed_bytes_growth) { 187 scoped_ptr<FileSystemOperationContext> context( 188 sandbox_file_system_.NewOperationContext()); 189 context->set_allowed_bytes_growth(allowed_bytes_growth); 190 return context.Pass(); 191 } 192 193 scoped_ptr<FileSystemOperationContext> UnlimitedContext() { 194 return LimitedContext(kint64max); 195 } 196 197 FileSystemOperationContext* NewContext( 198 SandboxFileSystemTestHelper* file_system) { 199 change_observer()->ResetCount(); 200 FileSystemOperationContext* context; 201 if (file_system) 202 context = file_system->NewOperationContext(); 203 else 204 context = sandbox_file_system_.NewOperationContext(); 205 // Setting allowed_bytes_growth big enough for all tests. 206 context->set_allowed_bytes_growth(1024 * 1024); 207 context->set_change_observers(change_observers()); 208 return context; 209 } 210 211 const fileapi::ChangeObserverList& change_observers() const { 212 return change_observers_; 213 } 214 215 fileapi::MockFileChangeObserver* change_observer() { 216 return &change_observer_; 217 } 218 219 // This can only be used after SetUp has run and created file_system_context_ 220 // and obfuscated_file_util_. 221 // Use this for tests which need to run in multiple origins; we need a test 222 // helper per origin. 223 SandboxFileSystemTestHelper* NewFileSystem( 224 const GURL& origin, fileapi::FileSystemType type) { 225 SandboxFileSystemTestHelper* file_system = 226 new SandboxFileSystemTestHelper(origin, type); 227 228 file_system->SetUp(file_system_context_.get()); 229 return file_system; 230 } 231 232 scoped_ptr<ObfuscatedFileUtil> CreateObfuscatedFileUtil( 233 quota::SpecialStoragePolicy* storage_policy) { 234 return scoped_ptr<ObfuscatedFileUtil>( 235 ObfuscatedFileUtil::CreateForTesting( 236 storage_policy, data_dir_path(), NULL, 237 base::MessageLoopProxy::current().get())); 238 } 239 240 ObfuscatedFileUtil* ofu() { 241 return static_cast<ObfuscatedFileUtil*>(sandbox_file_system_.file_util()); 242 } 243 244 const base::FilePath& test_directory() const { 245 return data_dir_.path(); 246 } 247 248 const GURL& origin() const { 249 return origin_; 250 } 251 252 fileapi::FileSystemType type() const { 253 return type_; 254 } 255 256 std::string type_string() const { 257 return GetTypeString(type_); 258 } 259 260 int64 ComputeTotalFileSize() { 261 return sandbox_file_system_.ComputeCurrentOriginUsage() - 262 sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage(); 263 } 264 265 void GetUsageFromQuotaManager() { 266 int64 quota = -1; 267 quota_status_ = 268 AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(), 269 origin(), 270 sandbox_file_system_.type(), 271 &usage_, 272 "a); 273 EXPECT_EQ(quota::kQuotaStatusOk, quota_status_); 274 } 275 276 void RevokeUsageCache() { 277 quota_manager_->ResetUsageTracker(sandbox_file_system_.storage_type()); 278 usage_cache()->Delete(sandbox_file_system_.GetUsageCachePath()); 279 } 280 281 int64 SizeByQuotaUtil() { 282 return sandbox_file_system_.GetCachedOriginUsage(); 283 } 284 285 int64 SizeInUsageFile() { 286 base::RunLoop().RunUntilIdle(); 287 int64 usage = 0; 288 return usage_cache()->GetUsage( 289 sandbox_file_system_.GetUsageCachePath(), &usage) ? usage : -1; 290 } 291 292 bool PathExists(const FileSystemURL& url) { 293 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 294 base::File::Info file_info; 295 base::FilePath platform_path; 296 base::File::Error error = ofu()->GetFileInfo( 297 context.get(), url, &file_info, &platform_path); 298 return error == base::File::FILE_OK; 299 } 300 301 bool DirectoryExists(const FileSystemURL& url) { 302 return AsyncFileTestHelper::DirectoryExists(file_system_context(), url); 303 } 304 305 int64 usage() const { return usage_; } 306 fileapi::FileSystemUsageCache* usage_cache() { 307 return sandbox_file_system_.usage_cache(); 308 } 309 310 FileSystemURL CreateURLFromUTF8(const std::string& path) { 311 return sandbox_file_system_.CreateURLFromUTF8(path); 312 } 313 314 int64 PathCost(const FileSystemURL& url) { 315 return ObfuscatedFileUtil::ComputeFilePathCost(url.path()); 316 } 317 318 FileSystemURL CreateURL(const base::FilePath& path) { 319 return sandbox_file_system_.CreateURL(path); 320 } 321 322 void CheckFileAndCloseHandle(const FileSystemURL& url, base::File file) { 323 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 324 base::FilePath local_path; 325 EXPECT_EQ(base::File::FILE_OK, 326 ofu()->GetLocalFilePath(context.get(), url, &local_path)); 327 328 base::File::Info file_info0; 329 base::FilePath data_path; 330 EXPECT_EQ(base::File::FILE_OK, 331 ofu()->GetFileInfo(context.get(), url, &file_info0, &data_path)); 332 EXPECT_EQ(data_path, local_path); 333 EXPECT_TRUE(FileExists(data_path)); 334 EXPECT_EQ(0, GetSize(data_path)); 335 336 const char data[] = "test data"; 337 const int length = arraysize(data) - 1; 338 339 if (!file.IsValid()) { 340 file.Initialize(data_path, 341 base::File::FLAG_OPEN | base::File::FLAG_WRITE); 342 ASSERT_TRUE(file.IsValid()); 343 EXPECT_FALSE(file.created()); 344 } 345 ASSERT_EQ(length, file.Write(0, data, length)); 346 file.Close(); 347 348 base::File::Info file_info1; 349 EXPECT_EQ(length, GetSize(data_path)); 350 context.reset(NewContext(NULL)); 351 EXPECT_EQ(base::File::FILE_OK, 352 ofu()->GetFileInfo(context.get(), url, &file_info1, &data_path)); 353 EXPECT_EQ(data_path, local_path); 354 355 EXPECT_FALSE(file_info0.is_directory); 356 EXPECT_FALSE(file_info1.is_directory); 357 EXPECT_FALSE(file_info0.is_symbolic_link); 358 EXPECT_FALSE(file_info1.is_symbolic_link); 359 EXPECT_EQ(0, file_info0.size); 360 EXPECT_EQ(length, file_info1.size); 361 EXPECT_LE(file_info0.last_modified, file_info1.last_modified); 362 363 context.reset(NewContext(NULL)); 364 EXPECT_EQ(base::File::FILE_OK, 365 ofu()->Truncate(context.get(), url, length * 2)); 366 EXPECT_EQ(length * 2, GetSize(data_path)); 367 368 context.reset(NewContext(NULL)); 369 EXPECT_EQ(base::File::FILE_OK, 370 ofu()->Truncate(context.get(), url, 0)); 371 EXPECT_EQ(0, GetSize(data_path)); 372 } 373 374 void ValidateTestDirectory( 375 const FileSystemURL& root_url, 376 const std::set<base::FilePath::StringType>& files, 377 const std::set<base::FilePath::StringType>& directories) { 378 scoped_ptr<FileSystemOperationContext> context; 379 std::set<base::FilePath::StringType>::const_iterator iter; 380 for (iter = files.begin(); iter != files.end(); ++iter) { 381 bool created = true; 382 context.reset(NewContext(NULL)); 383 ASSERT_EQ(base::File::FILE_OK, 384 ofu()->EnsureFileExists(context.get(), 385 FileSystemURLAppend(root_url, *iter), 386 &created)); 387 ASSERT_FALSE(created); 388 } 389 for (iter = directories.begin(); iter != directories.end(); ++iter) { 390 context.reset(NewContext(NULL)); 391 EXPECT_TRUE(DirectoryExists( 392 FileSystemURLAppend(root_url, *iter))); 393 } 394 } 395 396 class UsageVerifyHelper { 397 public: 398 UsageVerifyHelper(scoped_ptr<FileSystemOperationContext> context, 399 SandboxFileSystemTestHelper* file_system, 400 int64 expected_usage) 401 : context_(context.Pass()), 402 sandbox_file_system_(file_system), 403 expected_usage_(expected_usage) {} 404 405 ~UsageVerifyHelper() { 406 base::RunLoop().RunUntilIdle(); 407 Check(); 408 } 409 410 FileSystemOperationContext* context() { 411 return context_.get(); 412 } 413 414 private: 415 void Check() { 416 ASSERT_EQ(expected_usage_, 417 sandbox_file_system_->GetCachedOriginUsage()); 418 } 419 420 scoped_ptr<FileSystemOperationContext> context_; 421 SandboxFileSystemTestHelper* sandbox_file_system_; 422 int64 expected_usage_; 423 }; 424 425 scoped_ptr<UsageVerifyHelper> AllowUsageIncrease(int64 requested_growth) { 426 int64 usage = sandbox_file_system_.GetCachedOriginUsage(); 427 return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper( 428 LimitedContext(requested_growth), 429 &sandbox_file_system_, usage + requested_growth)); 430 } 431 432 scoped_ptr<UsageVerifyHelper> DisallowUsageIncrease(int64 requested_growth) { 433 int64 usage = sandbox_file_system_.GetCachedOriginUsage(); 434 return scoped_ptr<UsageVerifyHelper>(new UsageVerifyHelper( 435 LimitedContext(requested_growth - 1), &sandbox_file_system_, usage)); 436 } 437 438 void FillTestDirectory( 439 const FileSystemURL& root_url, 440 std::set<base::FilePath::StringType>* files, 441 std::set<base::FilePath::StringType>* directories) { 442 scoped_ptr<FileSystemOperationContext> context; 443 std::vector<fileapi::DirectoryEntry> entries; 444 EXPECT_EQ(base::File::FILE_OK, 445 AsyncFileTestHelper::ReadDirectory(file_system_context(), 446 root_url, &entries)); 447 EXPECT_EQ(0UL, entries.size()); 448 449 files->clear(); 450 files->insert(FILE_PATH_LITERAL("first")); 451 files->insert(FILE_PATH_LITERAL("second")); 452 files->insert(FILE_PATH_LITERAL("third")); 453 directories->clear(); 454 directories->insert(FILE_PATH_LITERAL("fourth")); 455 directories->insert(FILE_PATH_LITERAL("fifth")); 456 directories->insert(FILE_PATH_LITERAL("sixth")); 457 std::set<base::FilePath::StringType>::iterator iter; 458 for (iter = files->begin(); iter != files->end(); ++iter) { 459 bool created = false; 460 context.reset(NewContext(NULL)); 461 ASSERT_EQ(base::File::FILE_OK, 462 ofu()->EnsureFileExists(context.get(), 463 FileSystemURLAppend(root_url, *iter), 464 &created)); 465 ASSERT_TRUE(created); 466 } 467 for (iter = directories->begin(); iter != directories->end(); ++iter) { 468 bool exclusive = true; 469 bool recursive = false; 470 context.reset(NewContext(NULL)); 471 EXPECT_EQ(base::File::FILE_OK, 472 ofu()->CreateDirectory(context.get(), 473 FileSystemURLAppend(root_url, *iter), 474 exclusive, recursive)); 475 } 476 ValidateTestDirectory(root_url, *files, *directories); 477 } 478 479 void TestReadDirectoryHelper(const FileSystemURL& root_url) { 480 std::set<base::FilePath::StringType> files; 481 std::set<base::FilePath::StringType> directories; 482 FillTestDirectory(root_url, &files, &directories); 483 484 scoped_ptr<FileSystemOperationContext> context; 485 std::vector<fileapi::DirectoryEntry> entries; 486 context.reset(NewContext(NULL)); 487 EXPECT_EQ(base::File::FILE_OK, 488 AsyncFileTestHelper::ReadDirectory( 489 file_system_context(), root_url, &entries)); 490 std::vector<fileapi::DirectoryEntry>::iterator entry_iter; 491 EXPECT_EQ(files.size() + directories.size(), entries.size()); 492 EXPECT_TRUE(change_observer()->HasNoChange()); 493 for (entry_iter = entries.begin(); entry_iter != entries.end(); 494 ++entry_iter) { 495 const fileapi::DirectoryEntry& entry = *entry_iter; 496 std::set<base::FilePath::StringType>::iterator iter = 497 files.find(entry.name); 498 if (iter != files.end()) { 499 EXPECT_FALSE(entry.is_directory); 500 files.erase(iter); 501 continue; 502 } 503 iter = directories.find(entry.name); 504 EXPECT_FALSE(directories.end() == iter); 505 EXPECT_TRUE(entry.is_directory); 506 directories.erase(iter); 507 } 508 } 509 510 void TestTouchHelper(const FileSystemURL& url, bool is_file) { 511 base::Time last_access_time = base::Time::Now(); 512 base::Time last_modified_time = base::Time::Now(); 513 514 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 515 EXPECT_EQ(base::File::FILE_OK, 516 ofu()->Touch(context.get(), url, last_access_time, 517 last_modified_time)); 518 // Currently we fire no change notifications for Touch. 519 EXPECT_TRUE(change_observer()->HasNoChange()); 520 base::FilePath local_path; 521 base::File::Info file_info; 522 context.reset(NewContext(NULL)); 523 EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo( 524 context.get(), url, &file_info, &local_path)); 525 // We compare as time_t here to lower our resolution, to avoid false 526 // negatives caused by conversion to the local filesystem's native 527 // representation and back. 528 EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT()); 529 530 context.reset(NewContext(NULL)); 531 last_modified_time += base::TimeDelta::FromHours(1); 532 last_access_time += base::TimeDelta::FromHours(14); 533 EXPECT_EQ(base::File::FILE_OK, 534 ofu()->Touch(context.get(), url, last_access_time, 535 last_modified_time)); 536 EXPECT_TRUE(change_observer()->HasNoChange()); 537 context.reset(NewContext(NULL)); 538 EXPECT_EQ(base::File::FILE_OK, 539 ofu()->GetFileInfo(context.get(), url, &file_info, &local_path)); 540 EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT()); 541 if (is_file) // Directories in OFU don't support atime. 542 EXPECT_EQ(file_info.last_accessed.ToTimeT(), last_access_time.ToTimeT()); 543 } 544 545 void TestCopyInForeignFileHelper(bool overwrite) { 546 base::ScopedTempDir source_dir; 547 ASSERT_TRUE(source_dir.CreateUniqueTempDir()); 548 base::FilePath root_file_path = source_dir.path(); 549 base::FilePath src_file_path = root_file_path.AppendASCII("file_name"); 550 FileSystemURL dest_url = CreateURLFromUTF8("new file"); 551 int64 src_file_length = 87; 552 553 base::File file(src_file_path, 554 base::File::FLAG_CREATE | base::File::FLAG_WRITE); 555 ASSERT_TRUE(file.IsValid()); 556 EXPECT_TRUE(file.created()); 557 ASSERT_TRUE(file.SetLength(src_file_length)); 558 file.Close(); 559 560 scoped_ptr<FileSystemOperationContext> context; 561 562 if (overwrite) { 563 context.reset(NewContext(NULL)); 564 bool created = false; 565 EXPECT_EQ(base::File::FILE_OK, 566 ofu()->EnsureFileExists(context.get(), dest_url, &created)); 567 EXPECT_TRUE(created); 568 569 // We must have observed one (and only one) create_file_count. 570 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 571 EXPECT_TRUE(change_observer()->HasNoChange()); 572 } 573 574 const int64 path_cost = 575 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()); 576 if (!overwrite) { 577 // Verify that file creation requires sufficient quota for the path. 578 context.reset(NewContext(NULL)); 579 context->set_allowed_bytes_growth(path_cost + src_file_length - 1); 580 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, 581 ofu()->CopyInForeignFile(context.get(), 582 src_file_path, dest_url)); 583 } 584 585 context.reset(NewContext(NULL)); 586 context->set_allowed_bytes_growth(path_cost + src_file_length); 587 EXPECT_EQ(base::File::FILE_OK, 588 ofu()->CopyInForeignFile(context.get(), 589 src_file_path, dest_url)); 590 591 EXPECT_TRUE(PathExists(dest_url)); 592 EXPECT_FALSE(DirectoryExists(dest_url)); 593 594 context.reset(NewContext(NULL)); 595 base::File::Info file_info; 596 base::FilePath data_path; 597 EXPECT_EQ(base::File::FILE_OK, 598 ofu()->GetFileInfo(context.get(), dest_url, &file_info, 599 &data_path)); 600 EXPECT_NE(data_path, src_file_path); 601 EXPECT_TRUE(FileExists(data_path)); 602 EXPECT_EQ(src_file_length, GetSize(data_path)); 603 604 EXPECT_EQ(base::File::FILE_OK, 605 ofu()->DeleteFile(context.get(), dest_url)); 606 } 607 608 void ClearTimestamp(const FileSystemURL& url) { 609 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 610 EXPECT_EQ(base::File::FILE_OK, 611 ofu()->Touch(context.get(), url, base::Time(), base::Time())); 612 EXPECT_EQ(base::Time(), GetModifiedTime(url)); 613 } 614 615 base::Time GetModifiedTime(const FileSystemURL& url) { 616 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 617 base::FilePath data_path; 618 base::File::Info file_info; 619 context.reset(NewContext(NULL)); 620 EXPECT_EQ(base::File::FILE_OK, 621 ofu()->GetFileInfo(context.get(), url, &file_info, &data_path)); 622 EXPECT_TRUE(change_observer()->HasNoChange()); 623 return file_info.last_modified; 624 } 625 626 void TestDirectoryTimestampHelper(const FileSystemURL& base_dir, 627 bool copy, 628 bool overwrite) { 629 scoped_ptr<FileSystemOperationContext> context; 630 const FileSystemURL src_dir_url( 631 FileSystemURLAppendUTF8(base_dir, "foo_dir")); 632 const FileSystemURL dest_dir_url( 633 FileSystemURLAppendUTF8(base_dir, "bar_dir")); 634 635 const FileSystemURL src_file_url( 636 FileSystemURLAppendUTF8(src_dir_url, "hoge")); 637 const FileSystemURL dest_file_url( 638 FileSystemURLAppendUTF8(dest_dir_url, "fuga")); 639 640 context.reset(NewContext(NULL)); 641 EXPECT_EQ(base::File::FILE_OK, 642 ofu()->CreateDirectory(context.get(), src_dir_url, true, true)); 643 context.reset(NewContext(NULL)); 644 EXPECT_EQ(base::File::FILE_OK, 645 ofu()->CreateDirectory(context.get(), dest_dir_url, true, true)); 646 647 bool created = false; 648 context.reset(NewContext(NULL)); 649 EXPECT_EQ(base::File::FILE_OK, 650 ofu()->EnsureFileExists(context.get(), src_file_url, &created)); 651 if (overwrite) { 652 context.reset(NewContext(NULL)); 653 EXPECT_EQ(base::File::FILE_OK, 654 ofu()->EnsureFileExists(context.get(), 655 dest_file_url, &created)); 656 } 657 658 ClearTimestamp(src_dir_url); 659 ClearTimestamp(dest_dir_url); 660 context.reset(NewContext(NULL)); 661 EXPECT_EQ(base::File::FILE_OK, 662 ofu()->CopyOrMoveFile(context.get(), 663 src_file_url, dest_file_url, 664 FileSystemOperation::OPTION_NONE, 665 copy)); 666 if (copy) 667 EXPECT_EQ(base::Time(), GetModifiedTime(src_dir_url)); 668 else 669 EXPECT_NE(base::Time(), GetModifiedTime(src_dir_url)); 670 EXPECT_NE(base::Time(), GetModifiedTime(dest_dir_url)); 671 } 672 673 void MaybeDropDatabasesAliveCaseTestBody() { 674 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(NULL); 675 file_util->InitOriginDatabase(GURL(), true /*create*/); 676 ASSERT_TRUE(file_util->origin_database_ != NULL); 677 678 // Callback to Drop DB is called while ObfuscatedFileUtilTest is 679 // still alive. 680 file_util->db_flush_delay_seconds_ = 0; 681 file_util->MarkUsed(); 682 base::RunLoop().RunUntilIdle(); 683 684 ASSERT_TRUE(file_util->origin_database_ == NULL); 685 } 686 687 void MaybeDropDatabasesAlreadyDeletedCaseTestBody() { 688 // Run message loop after OFU is already deleted to make sure callback 689 // doesn't cause a crash for use after free. 690 { 691 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil(NULL); 692 file_util->InitOriginDatabase(GURL(), true /*create*/); 693 file_util->db_flush_delay_seconds_ = 0; 694 file_util->MarkUsed(); 695 } 696 697 // At this point the callback is still in the message queue but OFU is gone. 698 base::RunLoop().RunUntilIdle(); 699 } 700 701 void DestroyDirectoryDatabase_IsolatedTestBody() { 702 storage_policy_->AddIsolated(origin_); 703 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil( 704 storage_policy_.get()); 705 const FileSystemURL url = FileSystemURL::CreateForTest( 706 origin_, kFileSystemTypePersistent, base::FilePath()); 707 708 // Create DirectoryDatabase for isolated origin. 709 SandboxDirectoryDatabase* db = 710 file_util->GetDirectoryDatabase(url, true /* create */); 711 ASSERT_TRUE(db != NULL); 712 713 // Destory it. 714 ASSERT_TRUE(file_util->DestroyDirectoryDatabase( 715 url.origin(), GetTypeString(url.type()))); 716 ASSERT_TRUE(file_util->directories_.empty()); 717 } 718 719 void GetDirectoryDatabase_IsolatedTestBody() { 720 storage_policy_->AddIsolated(origin_); 721 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil( 722 storage_policy_.get()); 723 const FileSystemURL url = FileSystemURL::CreateForTest( 724 origin_, kFileSystemTypePersistent, base::FilePath()); 725 726 // Create DirectoryDatabase for isolated origin. 727 SandboxDirectoryDatabase* db = 728 file_util->GetDirectoryDatabase(url, true /* create */); 729 ASSERT_TRUE(db != NULL); 730 ASSERT_EQ(1U, file_util->directories_.size()); 731 732 // Remove isolated. 733 storage_policy_->RemoveIsolated(url.origin()); 734 735 // This should still get the same database. 736 SandboxDirectoryDatabase* db2 = 737 file_util->GetDirectoryDatabase(url, false /* create */); 738 ASSERT_EQ(db, db2); 739 } 740 741 void MigrationBackFromIsolatedTestBody() { 742 std::string kFakeDirectoryData("0123456789"); 743 base::FilePath old_directory_db_path; 744 745 // Initialize the directory with one origin using 746 // SandboxIsolatedOriginDatabase. 747 { 748 std::string origin_string = 749 webkit_database::GetIdentifierFromOrigin(origin_); 750 SandboxIsolatedOriginDatabase database_old( 751 origin_string, data_dir_path(), 752 base::FilePath( 753 SandboxIsolatedOriginDatabase::kObsoleteOriginDirectory)); 754 base::FilePath path; 755 EXPECT_TRUE(database_old.GetPathForOrigin(origin_string, &path)); 756 EXPECT_FALSE(path.empty()); 757 758 // Populate the origin directory with some fake data. 759 old_directory_db_path = data_dir_path().Append(path); 760 ASSERT_TRUE(base::CreateDirectory(old_directory_db_path)); 761 EXPECT_EQ(static_cast<int>(kFakeDirectoryData.size()), 762 base::WriteFile(old_directory_db_path.AppendASCII("dummy"), 763 kFakeDirectoryData.data(), 764 kFakeDirectoryData.size())); 765 } 766 767 storage_policy_->AddIsolated(origin_); 768 scoped_ptr<ObfuscatedFileUtil> file_util = CreateObfuscatedFileUtil( 769 storage_policy_.get()); 770 base::File::Error error = base::File::FILE_ERROR_FAILED; 771 base::FilePath origin_directory = file_util->GetDirectoryForOrigin( 772 origin_, true /* create */, &error); 773 EXPECT_EQ(base::File::FILE_OK, error); 774 775 // The database is migrated from the old one. 776 EXPECT_TRUE(base::DirectoryExists(origin_directory)); 777 EXPECT_FALSE(base::DirectoryExists(old_directory_db_path)); 778 779 // Check we see the same contents in the new origin directory. 780 std::string origin_db_data; 781 EXPECT_TRUE(base::PathExists(origin_directory.AppendASCII("dummy"))); 782 EXPECT_TRUE(base::ReadFileToString( 783 origin_directory.AppendASCII("dummy"), &origin_db_data)); 784 EXPECT_EQ(kFakeDirectoryData, origin_db_data); 785 } 786 787 int64 ComputeCurrentUsage() { 788 return sandbox_file_system_.ComputeCurrentOriginUsage() - 789 sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage(); 790 } 791 792 FileSystemContext* file_system_context() { 793 return sandbox_file_system_.file_system_context(); 794 } 795 796 const base::FilePath& data_dir_path() const { 797 return data_dir_.path(); 798 } 799 800 protected: 801 base::ScopedTempDir data_dir_; 802 base::MessageLoop message_loop_; 803 scoped_refptr<MockSpecialStoragePolicy> storage_policy_; 804 scoped_refptr<quota::QuotaManager> quota_manager_; 805 scoped_refptr<FileSystemContext> file_system_context_; 806 GURL origin_; 807 fileapi::FileSystemType type_; 808 base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_; 809 SandboxFileSystemTestHelper sandbox_file_system_; 810 quota::QuotaStatusCode quota_status_; 811 int64 usage_; 812 fileapi::MockFileChangeObserver change_observer_; 813 fileapi::ChangeObserverList change_observers_; 814 815 private: 816 DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest); 817 }; 818 819 TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { 820 FileSystemURL url = CreateURLFromUTF8("fake/file"); 821 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 822 int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE; 823 824 base::File file = ofu()->CreateOrOpen(context.get(), url, file_flags); 825 EXPECT_FALSE(file.IsValid()); 826 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details()); 827 828 context.reset(NewContext(NULL)); 829 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 830 ofu()->DeleteFile(context.get(), url)); 831 832 url = CreateURLFromUTF8("test file"); 833 834 EXPECT_TRUE(change_observer()->HasNoChange()); 835 836 // Verify that file creation requires sufficient quota for the path. 837 context.reset(NewContext(NULL)); 838 context->set_allowed_bytes_growth( 839 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1); 840 file = ofu()->CreateOrOpen(context.get(), url, file_flags); 841 EXPECT_FALSE(file.IsValid()); 842 ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE, file.error_details()); 843 844 context.reset(NewContext(NULL)); 845 context->set_allowed_bytes_growth( 846 ObfuscatedFileUtil::ComputeFilePathCost(url.path())); 847 file = ofu()->CreateOrOpen(context.get(), url, file_flags); 848 EXPECT_TRUE(file.IsValid()); 849 ASSERT_TRUE(file.created()); 850 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 851 852 CheckFileAndCloseHandle(url, file.Pass()); 853 854 context.reset(NewContext(NULL)); 855 base::FilePath local_path; 856 EXPECT_EQ(base::File::FILE_OK, 857 ofu()->GetLocalFilePath(context.get(), url, &local_path)); 858 EXPECT_TRUE(base::PathExists(local_path)); 859 860 // Verify that deleting a file isn't stopped by zero quota, and that it frees 861 // up quote from its path. 862 context.reset(NewContext(NULL)); 863 context->set_allowed_bytes_growth(0); 864 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url)); 865 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); 866 EXPECT_FALSE(base::PathExists(local_path)); 867 EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()), 868 context->allowed_bytes_growth()); 869 870 context.reset(NewContext(NULL)); 871 bool exclusive = true; 872 bool recursive = true; 873 FileSystemURL directory_url = CreateURLFromUTF8( 874 "series/of/directories"); 875 url = FileSystemURLAppendUTF8(directory_url, "file name"); 876 EXPECT_EQ(base::File::FILE_OK, 877 ofu()->CreateDirectory(context.get(), directory_url, exclusive, 878 recursive)); 879 // The oepration created 3 directories recursively. 880 EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count()); 881 882 context.reset(NewContext(NULL)); 883 file = ofu()->CreateOrOpen(context.get(), url, file_flags); 884 ASSERT_TRUE(file.IsValid()); 885 ASSERT_TRUE(file.created()); 886 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 887 888 CheckFileAndCloseHandle(url, file.Pass()); 889 890 context.reset(NewContext(NULL)); 891 EXPECT_EQ(base::File::FILE_OK, 892 ofu()->GetLocalFilePath(context.get(), url, &local_path)); 893 EXPECT_TRUE(base::PathExists(local_path)); 894 895 context.reset(NewContext(NULL)); 896 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url)); 897 EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); 898 EXPECT_FALSE(base::PathExists(local_path)); 899 900 // Make sure we have no unexpected changes. 901 EXPECT_TRUE(change_observer()->HasNoChange()); 902 } 903 904 TEST_F(ObfuscatedFileUtilTest, TestTruncate) { 905 bool created = false; 906 FileSystemURL url = CreateURLFromUTF8("file"); 907 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 908 909 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 910 ofu()->Truncate(context.get(), url, 4)); 911 912 context.reset(NewContext(NULL)); 913 ASSERT_EQ(base::File::FILE_OK, 914 ofu()->EnsureFileExists(context.get(), url, &created)); 915 ASSERT_TRUE(created); 916 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 917 918 context.reset(NewContext(NULL)); 919 base::FilePath local_path; 920 EXPECT_EQ(base::File::FILE_OK, 921 ofu()->GetLocalFilePath(context.get(), url, &local_path)); 922 EXPECT_EQ(0, GetSize(local_path)); 923 924 context.reset(NewContext(NULL)); 925 EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 10)); 926 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); 927 EXPECT_EQ(10, GetSize(local_path)); 928 929 context.reset(NewContext(NULL)); 930 EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 1)); 931 EXPECT_EQ(1, GetSize(local_path)); 932 EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); 933 934 EXPECT_FALSE(DirectoryExists(url)); 935 EXPECT_TRUE(PathExists(url)); 936 937 // Make sure we have no unexpected changes. 938 EXPECT_TRUE(change_observer()->HasNoChange()); 939 } 940 941 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnTruncation) { 942 bool created = false; 943 FileSystemURL url = CreateURLFromUTF8("file"); 944 945 ASSERT_EQ(base::File::FILE_OK, 946 ofu()->EnsureFileExists( 947 AllowUsageIncrease(PathCost(url))->context(), 948 url, &created)); 949 ASSERT_TRUE(created); 950 ASSERT_EQ(0, ComputeTotalFileSize()); 951 952 ASSERT_EQ(base::File::FILE_OK, 953 ofu()->Truncate(AllowUsageIncrease(1020)->context(), url, 1020)); 954 ASSERT_EQ(1020, ComputeTotalFileSize()); 955 956 ASSERT_EQ(base::File::FILE_OK, 957 ofu()->Truncate(AllowUsageIncrease(-1020)->context(), url, 0)); 958 ASSERT_EQ(0, ComputeTotalFileSize()); 959 960 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, 961 ofu()->Truncate(DisallowUsageIncrease(1021)->context(), 962 url, 1021)); 963 ASSERT_EQ(0, ComputeTotalFileSize()); 964 965 EXPECT_EQ(base::File::FILE_OK, 966 ofu()->Truncate(AllowUsageIncrease(1020)->context(), url, 1020)); 967 ASSERT_EQ(1020, ComputeTotalFileSize()); 968 969 EXPECT_EQ(base::File::FILE_OK, 970 ofu()->Truncate(AllowUsageIncrease(0)->context(), url, 1020)); 971 ASSERT_EQ(1020, ComputeTotalFileSize()); 972 973 // quota exceeded 974 { 975 scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(-1); 976 helper->context()->set_allowed_bytes_growth( 977 helper->context()->allowed_bytes_growth() - 1); 978 EXPECT_EQ(base::File::FILE_OK, 979 ofu()->Truncate(helper->context(), url, 1019)); 980 ASSERT_EQ(1019, ComputeTotalFileSize()); 981 } 982 983 // Delete backing file to make following truncation fail. 984 base::FilePath local_path; 985 ASSERT_EQ(base::File::FILE_OK, 986 ofu()->GetLocalFilePath(UnlimitedContext().get(), url, 987 &local_path)); 988 ASSERT_FALSE(local_path.empty()); 989 ASSERT_TRUE(base::DeleteFile(local_path, false)); 990 991 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 992 ofu()->Truncate(LimitedContext(1234).get(), url, 1234)); 993 ASSERT_EQ(0, ComputeTotalFileSize()); 994 } 995 996 TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { 997 FileSystemURL url = CreateURLFromUTF8("fake/file"); 998 bool created = false; 999 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1000 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1001 ofu()->EnsureFileExists(context.get(), url, &created)); 1002 EXPECT_TRUE(change_observer()->HasNoChange()); 1003 1004 // Verify that file creation requires sufficient quota for the path. 1005 context.reset(NewContext(NULL)); 1006 url = CreateURLFromUTF8("test file"); 1007 created = false; 1008 context->set_allowed_bytes_growth( 1009 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1); 1010 ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE, 1011 ofu()->EnsureFileExists(context.get(), url, &created)); 1012 ASSERT_FALSE(created); 1013 EXPECT_TRUE(change_observer()->HasNoChange()); 1014 1015 context.reset(NewContext(NULL)); 1016 context->set_allowed_bytes_growth( 1017 ObfuscatedFileUtil::ComputeFilePathCost(url.path())); 1018 ASSERT_EQ(base::File::FILE_OK, 1019 ofu()->EnsureFileExists(context.get(), url, &created)); 1020 ASSERT_TRUE(created); 1021 EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); 1022 1023 CheckFileAndCloseHandle(url, base::File()); 1024 1025 context.reset(NewContext(NULL)); 1026 ASSERT_EQ(base::File::FILE_OK, 1027 ofu()->EnsureFileExists(context.get(), url, &created)); 1028 ASSERT_FALSE(created); 1029 EXPECT_TRUE(change_observer()->HasNoChange()); 1030 1031 // Also test in a subdirectory. 1032 url = CreateURLFromUTF8("path/to/file.txt"); 1033 context.reset(NewContext(NULL)); 1034 bool exclusive = true; 1035 bool recursive = true; 1036 EXPECT_EQ(base::File::FILE_OK, 1037 ofu()->CreateDirectory(context.get(), FileSystemURLDirName(url), 1038 exclusive, recursive)); 1039 // 2 directories: path/ and path/to. 1040 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); 1041 1042 context.reset(NewContext(NULL)); 1043 ASSERT_EQ(base::File::FILE_OK, 1044 ofu()->EnsureFileExists(context.get(), url, &created)); 1045 ASSERT_TRUE(created); 1046 EXPECT_FALSE(DirectoryExists(url)); 1047 EXPECT_TRUE(PathExists(url)); 1048 EXPECT_TRUE(change_observer()->HasNoChange()); 1049 } 1050 1051 TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { 1052 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1053 1054 bool exclusive = false; 1055 bool recursive = false; 1056 FileSystemURL url = CreateURLFromUTF8("foo/bar"); 1057 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1058 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1059 1060 context.reset(NewContext(NULL)); 1061 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1062 ofu()->DeleteDirectory(context.get(), url)); 1063 1064 FileSystemURL root = CreateURLFromUTF8(std::string()); 1065 EXPECT_FALSE(DirectoryExists(url)); 1066 EXPECT_FALSE(PathExists(url)); 1067 context.reset(NewContext(NULL)); 1068 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root)); 1069 1070 context.reset(NewContext(NULL)); 1071 exclusive = false; 1072 recursive = true; 1073 EXPECT_EQ(base::File::FILE_OK, 1074 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1075 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); 1076 1077 EXPECT_TRUE(DirectoryExists(url)); 1078 EXPECT_TRUE(PathExists(url)); 1079 1080 context.reset(NewContext(NULL)); 1081 EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root)); 1082 EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url))); 1083 1084 context.reset(NewContext(NULL)); 1085 EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), 1086 FileSystemURLDirName(url))); 1087 1088 // Can't remove a non-empty directory. 1089 context.reset(NewContext(NULL)); 1090 EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, 1091 ofu()->DeleteDirectory(context.get(), 1092 FileSystemURLDirName(url))); 1093 EXPECT_TRUE(change_observer()->HasNoChange()); 1094 1095 base::File::Info file_info; 1096 base::FilePath local_path; 1097 EXPECT_EQ(base::File::FILE_OK, 1098 ofu()->GetFileInfo(context.get(), url, &file_info, &local_path)); 1099 EXPECT_TRUE(local_path.empty()); 1100 EXPECT_TRUE(file_info.is_directory); 1101 EXPECT_FALSE(file_info.is_symbolic_link); 1102 1103 // Same create again should succeed, since exclusive is false. 1104 context.reset(NewContext(NULL)); 1105 EXPECT_EQ(base::File::FILE_OK, 1106 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1107 EXPECT_TRUE(change_observer()->HasNoChange()); 1108 1109 exclusive = true; 1110 recursive = true; 1111 context.reset(NewContext(NULL)); 1112 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, 1113 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1114 EXPECT_TRUE(change_observer()->HasNoChange()); 1115 1116 // Verify that deleting a directory isn't stopped by zero quota, and that it 1117 // frees up quota from its path. 1118 context.reset(NewContext(NULL)); 1119 context->set_allowed_bytes_growth(0); 1120 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url)); 1121 EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); 1122 EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()), 1123 context->allowed_bytes_growth()); 1124 1125 url = CreateURLFromUTF8("foo/bop"); 1126 1127 EXPECT_FALSE(DirectoryExists(url)); 1128 EXPECT_FALSE(PathExists(url)); 1129 1130 context.reset(NewContext(NULL)); 1131 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url)); 1132 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1133 ofu()->GetFileInfo(context.get(), url, &file_info, &local_path)); 1134 1135 // Verify that file creation requires sufficient quota for the path. 1136 exclusive = true; 1137 recursive = false; 1138 context.reset(NewContext(NULL)); 1139 context->set_allowed_bytes_growth( 1140 ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1); 1141 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, 1142 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1143 EXPECT_TRUE(change_observer()->HasNoChange()); 1144 1145 context.reset(NewContext(NULL)); 1146 context->set_allowed_bytes_growth( 1147 ObfuscatedFileUtil::ComputeFilePathCost(url.path())); 1148 EXPECT_EQ(base::File::FILE_OK, 1149 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1150 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 1151 1152 EXPECT_TRUE(DirectoryExists(url)); 1153 EXPECT_TRUE(PathExists(url)); 1154 1155 exclusive = true; 1156 recursive = false; 1157 context.reset(NewContext(NULL)); 1158 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, 1159 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1160 EXPECT_TRUE(change_observer()->HasNoChange()); 1161 1162 exclusive = true; 1163 recursive = false; 1164 url = CreateURLFromUTF8("foo"); 1165 context.reset(NewContext(NULL)); 1166 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, 1167 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1168 EXPECT_TRUE(change_observer()->HasNoChange()); 1169 1170 url = CreateURLFromUTF8("blah"); 1171 1172 EXPECT_FALSE(DirectoryExists(url)); 1173 EXPECT_FALSE(PathExists(url)); 1174 1175 exclusive = true; 1176 recursive = false; 1177 context.reset(NewContext(NULL)); 1178 EXPECT_EQ(base::File::FILE_OK, 1179 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1180 EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); 1181 1182 EXPECT_TRUE(DirectoryExists(url)); 1183 EXPECT_TRUE(PathExists(url)); 1184 1185 exclusive = true; 1186 recursive = false; 1187 context.reset(NewContext(NULL)); 1188 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, 1189 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1190 EXPECT_TRUE(change_observer()->HasNoChange()); 1191 } 1192 1193 TEST_F(ObfuscatedFileUtilTest, TestReadDirectory) { 1194 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1195 bool exclusive = true; 1196 bool recursive = true; 1197 FileSystemURL url = CreateURLFromUTF8("directory/to/use"); 1198 EXPECT_EQ(base::File::FILE_OK, 1199 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1200 TestReadDirectoryHelper(url); 1201 } 1202 1203 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithSlash) { 1204 TestReadDirectoryHelper(CreateURLFromUTF8(std::string())); 1205 } 1206 1207 TEST_F(ObfuscatedFileUtilTest, TestReadRootWithEmptyString) { 1208 TestReadDirectoryHelper(CreateURLFromUTF8("/")); 1209 } 1210 1211 TEST_F(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) { 1212 FileSystemURL url = CreateURLFromUTF8("file"); 1213 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1214 1215 bool created = false; 1216 ASSERT_EQ(base::File::FILE_OK, 1217 ofu()->EnsureFileExists(context.get(), url, &created)); 1218 ASSERT_TRUE(created); 1219 1220 std::vector<fileapi::DirectoryEntry> entries; 1221 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, 1222 AsyncFileTestHelper::ReadDirectory(file_system_context(), url, 1223 &entries)); 1224 1225 EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url)); 1226 } 1227 1228 TEST_F(ObfuscatedFileUtilTest, TestTouch) { 1229 FileSystemURL url = CreateURLFromUTF8("file"); 1230 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1231 1232 base::Time last_access_time = base::Time::Now(); 1233 base::Time last_modified_time = base::Time::Now(); 1234 1235 // It's not there yet. 1236 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1237 ofu()->Touch(context.get(), url, last_access_time, 1238 last_modified_time)); 1239 1240 // OK, now create it. 1241 context.reset(NewContext(NULL)); 1242 bool created = false; 1243 ASSERT_EQ(base::File::FILE_OK, 1244 ofu()->EnsureFileExists(context.get(), url, &created)); 1245 ASSERT_TRUE(created); 1246 TestTouchHelper(url, true); 1247 1248 // Now test a directory: 1249 context.reset(NewContext(NULL)); 1250 bool exclusive = true; 1251 bool recursive = false; 1252 url = CreateURLFromUTF8("dir"); 1253 ASSERT_EQ(base::File::FILE_OK, 1254 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1255 TestTouchHelper(url, false); 1256 } 1257 1258 TEST_F(ObfuscatedFileUtilTest, TestPathQuotas) { 1259 FileSystemURL url = CreateURLFromUTF8("fake/file"); 1260 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1261 1262 url = CreateURLFromUTF8("file name"); 1263 context->set_allowed_bytes_growth(5); 1264 bool created = false; 1265 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, 1266 ofu()->EnsureFileExists(context.get(), url, &created)); 1267 EXPECT_FALSE(created); 1268 context->set_allowed_bytes_growth(1024); 1269 EXPECT_EQ(base::File::FILE_OK, 1270 ofu()->EnsureFileExists(context.get(), url, &created)); 1271 EXPECT_TRUE(created); 1272 int64 path_cost = ObfuscatedFileUtil::ComputeFilePathCost(url.path()); 1273 EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth()); 1274 1275 context->set_allowed_bytes_growth(1024); 1276 bool exclusive = true; 1277 bool recursive = true; 1278 url = CreateURLFromUTF8("directory/to/use"); 1279 std::vector<base::FilePath::StringType> components; 1280 url.path().GetComponents(&components); 1281 path_cost = 0; 1282 typedef std::vector<base::FilePath::StringType>::iterator iterator; 1283 for (iterator iter = components.begin(); 1284 iter != components.end(); ++iter) { 1285 path_cost += ObfuscatedFileUtil::ComputeFilePathCost( 1286 base::FilePath(*iter)); 1287 } 1288 context.reset(NewContext(NULL)); 1289 context->set_allowed_bytes_growth(1024); 1290 EXPECT_EQ(base::File::FILE_OK, 1291 ofu()->CreateDirectory(context.get(), url, exclusive, recursive)); 1292 EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth()); 1293 } 1294 1295 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) { 1296 FileSystemURL source_url = CreateURLFromUTF8("path0.txt"); 1297 FileSystemURL dest_url = CreateURLFromUTF8("path1.txt"); 1298 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1299 1300 bool is_copy_not_move = false; 1301 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1302 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, 1303 FileSystemOperation::OPTION_NONE, 1304 is_copy_not_move)); 1305 EXPECT_TRUE(change_observer()->HasNoChange()); 1306 context.reset(NewContext(NULL)); 1307 is_copy_not_move = true; 1308 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1309 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, 1310 FileSystemOperation::OPTION_NONE, 1311 is_copy_not_move)); 1312 EXPECT_TRUE(change_observer()->HasNoChange()); 1313 source_url = CreateURLFromUTF8("dir/dir/file"); 1314 bool exclusive = true; 1315 bool recursive = true; 1316 context.reset(NewContext(NULL)); 1317 ASSERT_EQ(base::File::FILE_OK, 1318 ofu()->CreateDirectory(context.get(), 1319 FileSystemURLDirName(source_url), 1320 exclusive, recursive)); 1321 EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); 1322 is_copy_not_move = false; 1323 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1324 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, 1325 FileSystemOperation::OPTION_NONE, 1326 is_copy_not_move)); 1327 EXPECT_TRUE(change_observer()->HasNoChange()); 1328 context.reset(NewContext(NULL)); 1329 is_copy_not_move = true; 1330 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1331 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, 1332 FileSystemOperation::OPTION_NONE, 1333 is_copy_not_move)); 1334 EXPECT_TRUE(change_observer()->HasNoChange()); 1335 } 1336 1337 TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) { 1338 const int64 kSourceLength = 5; 1339 const int64 kDestLength = 50; 1340 1341 for (size_t i = 0; i < arraysize(kCopyMoveTestCases); ++i) { 1342 SCOPED_TRACE(testing::Message() << "kCopyMoveTestCase " << i); 1343 const CopyMoveTestCaseRecord& test_case = kCopyMoveTestCases[i]; 1344 SCOPED_TRACE(testing::Message() << "\t is_copy_not_move " << 1345 test_case.is_copy_not_move); 1346 SCOPED_TRACE(testing::Message() << "\t source_path " << 1347 test_case.source_path); 1348 SCOPED_TRACE(testing::Message() << "\t dest_path " << 1349 test_case.dest_path); 1350 SCOPED_TRACE(testing::Message() << "\t cause_overwrite " << 1351 test_case.cause_overwrite); 1352 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1353 1354 bool exclusive = false; 1355 bool recursive = true; 1356 FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path); 1357 FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path); 1358 1359 context.reset(NewContext(NULL)); 1360 ASSERT_EQ(base::File::FILE_OK, 1361 ofu()->CreateDirectory(context.get(), 1362 FileSystemURLDirName(source_url), 1363 exclusive, recursive)); 1364 context.reset(NewContext(NULL)); 1365 ASSERT_EQ(base::File::FILE_OK, 1366 ofu()->CreateDirectory(context.get(), 1367 FileSystemURLDirName(dest_url), 1368 exclusive, recursive)); 1369 1370 bool created = false; 1371 context.reset(NewContext(NULL)); 1372 ASSERT_EQ(base::File::FILE_OK, 1373 ofu()->EnsureFileExists(context.get(), source_url, &created)); 1374 ASSERT_TRUE(created); 1375 context.reset(NewContext(NULL)); 1376 ASSERT_EQ(base::File::FILE_OK, 1377 ofu()->Truncate(context.get(), source_url, kSourceLength)); 1378 1379 if (test_case.cause_overwrite) { 1380 context.reset(NewContext(NULL)); 1381 created = false; 1382 ASSERT_EQ(base::File::FILE_OK, 1383 ofu()->EnsureFileExists(context.get(), dest_url, &created)); 1384 ASSERT_TRUE(created); 1385 context.reset(NewContext(NULL)); 1386 ASSERT_EQ(base::File::FILE_OK, 1387 ofu()->Truncate(context.get(), dest_url, kDestLength)); 1388 } 1389 1390 context.reset(NewContext(NULL)); 1391 EXPECT_EQ(base::File::FILE_OK, 1392 ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, 1393 FileSystemOperation::OPTION_NONE, 1394 test_case.is_copy_not_move)); 1395 1396 if (test_case.is_copy_not_move) { 1397 base::File::Info file_info; 1398 base::FilePath local_path; 1399 context.reset(NewContext(NULL)); 1400 EXPECT_EQ(base::File::FILE_OK, 1401 ofu()->GetFileInfo(context.get(), source_url, &file_info, 1402 &local_path)); 1403 EXPECT_EQ(kSourceLength, file_info.size); 1404 EXPECT_EQ(base::File::FILE_OK, 1405 ofu()->DeleteFile(context.get(), source_url)); 1406 } else { 1407 base::File::Info file_info; 1408 base::FilePath local_path; 1409 context.reset(NewContext(NULL)); 1410 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1411 ofu()->GetFileInfo(context.get(), source_url, &file_info, 1412 &local_path)); 1413 } 1414 base::File::Info file_info; 1415 base::FilePath local_path; 1416 EXPECT_EQ(base::File::FILE_OK, 1417 ofu()->GetFileInfo(context.get(), dest_url, &file_info, 1418 &local_path)); 1419 EXPECT_EQ(kSourceLength, file_info.size); 1420 1421 EXPECT_EQ(base::File::FILE_OK, 1422 ofu()->DeleteFile(context.get(), dest_url)); 1423 } 1424 } 1425 1426 TEST_F(ObfuscatedFileUtilTest, TestCopyPathQuotas) { 1427 FileSystemURL src_url = CreateURLFromUTF8("src path"); 1428 FileSystemURL dest_url = CreateURLFromUTF8("destination path"); 1429 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1430 bool created = false; 1431 ASSERT_EQ(base::File::FILE_OK, 1432 ofu()->EnsureFileExists(context.get(), src_url, &created)); 1433 1434 bool is_copy = true; 1435 // Copy, no overwrite. 1436 context->set_allowed_bytes_growth( 1437 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1); 1438 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, 1439 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, 1440 FileSystemOperation::OPTION_NONE, is_copy)); 1441 context.reset(NewContext(NULL)); 1442 context->set_allowed_bytes_growth( 1443 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path())); 1444 EXPECT_EQ(base::File::FILE_OK, 1445 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, 1446 FileSystemOperation::OPTION_NONE, is_copy)); 1447 1448 // Copy, with overwrite. 1449 context.reset(NewContext(NULL)); 1450 context->set_allowed_bytes_growth(0); 1451 EXPECT_EQ(base::File::FILE_OK, 1452 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, 1453 FileSystemOperation::OPTION_NONE, is_copy)); 1454 } 1455 1456 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) { 1457 FileSystemURL src_url = CreateURLFromUTF8("src path"); 1458 FileSystemURL dest_url = CreateURLFromUTF8("destination path"); 1459 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1460 bool created = false; 1461 ASSERT_EQ(base::File::FILE_OK, 1462 ofu()->EnsureFileExists(context.get(), src_url, &created)); 1463 1464 bool is_copy = false; 1465 // Move, rename, no overwrite. 1466 context.reset(NewContext(NULL)); 1467 context->set_allowed_bytes_growth( 1468 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1469 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1); 1470 EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, 1471 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, 1472 FileSystemOperation::OPTION_NONE, is_copy)); 1473 context.reset(NewContext(NULL)); 1474 context->set_allowed_bytes_growth( 1475 ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1476 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path())); 1477 EXPECT_EQ(base::File::FILE_OK, 1478 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, 1479 FileSystemOperation::OPTION_NONE, is_copy)); 1480 1481 context.reset(NewContext(NULL)); 1482 ASSERT_EQ(base::File::FILE_OK, 1483 ofu()->EnsureFileExists(context.get(), src_url, &created)); 1484 1485 // Move, rename, with overwrite. 1486 context.reset(NewContext(NULL)); 1487 context->set_allowed_bytes_growth(0); 1488 EXPECT_EQ(base::File::FILE_OK, 1489 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, 1490 FileSystemOperation::OPTION_NONE, is_copy)); 1491 } 1492 1493 TEST_F(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) { 1494 FileSystemURL src_url = CreateURLFromUTF8("src path"); 1495 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1496 bool created = false; 1497 ASSERT_EQ(base::File::FILE_OK, 1498 ofu()->EnsureFileExists(context.get(), src_url, &created)); 1499 1500 bool exclusive = true; 1501 bool recursive = false; 1502 FileSystemURL dir_url = CreateURLFromUTF8("directory path"); 1503 context.reset(NewContext(NULL)); 1504 ASSERT_EQ(base::File::FILE_OK, 1505 ofu()->CreateDirectory(context.get(), dir_url, exclusive, 1506 recursive)); 1507 1508 FileSystemURL dest_url = FileSystemURLAppend( 1509 dir_url, src_url.path().value()); 1510 1511 bool is_copy = false; 1512 int64 allowed_bytes_growth = -1000; // Over quota, this should still work. 1513 // Move, no rename, no overwrite. 1514 context.reset(NewContext(NULL)); 1515 context->set_allowed_bytes_growth(allowed_bytes_growth); 1516 EXPECT_EQ(base::File::FILE_OK, 1517 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, 1518 FileSystemOperation::OPTION_NONE, is_copy)); 1519 EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth()); 1520 1521 // Move, no rename, with overwrite. 1522 context.reset(NewContext(NULL)); 1523 ASSERT_EQ(base::File::FILE_OK, 1524 ofu()->EnsureFileExists(context.get(), src_url, &created)); 1525 context.reset(NewContext(NULL)); 1526 context->set_allowed_bytes_growth(allowed_bytes_growth); 1527 EXPECT_EQ(base::File::FILE_OK, 1528 ofu()->CopyOrMoveFile(context.get(), src_url, dest_url, 1529 FileSystemOperation::OPTION_NONE, is_copy)); 1530 EXPECT_EQ( 1531 allowed_bytes_growth + 1532 ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()), 1533 context->allowed_bytes_growth()); 1534 } 1535 1536 TEST_F(ObfuscatedFileUtilTest, TestCopyInForeignFile) { 1537 TestCopyInForeignFileHelper(false /* overwrite */); 1538 TestCopyInForeignFileHelper(true /* overwrite */); 1539 } 1540 1541 TEST_F(ObfuscatedFileUtilTest, TestEnumerator) { 1542 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1543 FileSystemURL src_url = CreateURLFromUTF8("source dir"); 1544 bool exclusive = true; 1545 bool recursive = false; 1546 ASSERT_EQ(base::File::FILE_OK, 1547 ofu()->CreateDirectory(context.get(), src_url, exclusive, 1548 recursive)); 1549 1550 std::set<base::FilePath::StringType> files; 1551 std::set<base::FilePath::StringType> directories; 1552 FillTestDirectory(src_url, &files, &directories); 1553 1554 FileSystemURL dest_url = CreateURLFromUTF8("destination dir"); 1555 1556 EXPECT_FALSE(DirectoryExists(dest_url)); 1557 ASSERT_EQ(base::File::FILE_OK, 1558 AsyncFileTestHelper::Copy( 1559 file_system_context(), src_url, dest_url)); 1560 1561 ValidateTestDirectory(dest_url, files, directories); 1562 EXPECT_TRUE(DirectoryExists(src_url)); 1563 EXPECT_TRUE(DirectoryExists(dest_url)); 1564 recursive = true; 1565 ASSERT_EQ(base::File::FILE_OK, 1566 AsyncFileTestHelper::Remove( 1567 file_system_context(), dest_url, recursive)); 1568 EXPECT_FALSE(DirectoryExists(dest_url)); 1569 } 1570 1571 TEST_F(ObfuscatedFileUtilTest, TestOriginEnumerator) { 1572 scoped_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> 1573 enumerator(ofu()->CreateOriginEnumerator()); 1574 // The test helper starts out with a single filesystem. 1575 EXPECT_TRUE(enumerator.get()); 1576 EXPECT_EQ(origin(), enumerator->Next()); 1577 ASSERT_TRUE(type() == kFileSystemTypeTemporary); 1578 EXPECT_TRUE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary)); 1579 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent)); 1580 EXPECT_EQ(GURL(), enumerator->Next()); 1581 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary)); 1582 EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent)); 1583 1584 std::set<GURL> origins_expected; 1585 origins_expected.insert(origin()); 1586 1587 for (size_t i = 0; i < arraysize(kOriginEnumerationTestRecords); ++i) { 1588 SCOPED_TRACE(testing::Message() << 1589 "Validating kOriginEnumerationTestRecords " << i); 1590 const OriginEnumerationTestRecord& record = 1591 kOriginEnumerationTestRecords[i]; 1592 GURL origin_url(record.origin_url); 1593 origins_expected.insert(origin_url); 1594 if (record.has_temporary) { 1595 scoped_ptr<SandboxFileSystemTestHelper> file_system( 1596 NewFileSystem(origin_url, kFileSystemTypeTemporary)); 1597 scoped_ptr<FileSystemOperationContext> context( 1598 NewContext(file_system.get())); 1599 bool created = false; 1600 ASSERT_EQ(base::File::FILE_OK, 1601 ofu()->EnsureFileExists( 1602 context.get(), 1603 file_system->CreateURLFromUTF8("file"), 1604 &created)); 1605 EXPECT_TRUE(created); 1606 } 1607 if (record.has_persistent) { 1608 scoped_ptr<SandboxFileSystemTestHelper> file_system( 1609 NewFileSystem(origin_url, kFileSystemTypePersistent)); 1610 scoped_ptr<FileSystemOperationContext> context( 1611 NewContext(file_system.get())); 1612 bool created = false; 1613 ASSERT_EQ(base::File::FILE_OK, 1614 ofu()->EnsureFileExists( 1615 context.get(), 1616 file_system->CreateURLFromUTF8("file"), 1617 &created)); 1618 EXPECT_TRUE(created); 1619 } 1620 } 1621 enumerator.reset(ofu()->CreateOriginEnumerator()); 1622 EXPECT_TRUE(enumerator.get()); 1623 std::set<GURL> origins_found; 1624 GURL origin_url; 1625 while (!(origin_url = enumerator->Next()).is_empty()) { 1626 origins_found.insert(origin_url); 1627 SCOPED_TRACE(testing::Message() << "Handling " << origin_url.spec()); 1628 bool found = false; 1629 for (size_t i = 0; !found && i < arraysize(kOriginEnumerationTestRecords); 1630 ++i) { 1631 const OriginEnumerationTestRecord& record = 1632 kOriginEnumerationTestRecords[i]; 1633 if (GURL(record.origin_url) != origin_url) 1634 continue; 1635 found = true; 1636 EXPECT_EQ(record.has_temporary, 1637 HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary)); 1638 EXPECT_EQ(record.has_persistent, 1639 HasFileSystemType(enumerator.get(), kFileSystemTypePersistent)); 1640 } 1641 // Deal with the default filesystem created by the test helper. 1642 if (!found && origin_url == origin()) { 1643 ASSERT_TRUE(type() == kFileSystemTypeTemporary); 1644 EXPECT_TRUE(HasFileSystemType(enumerator.get(), 1645 kFileSystemTypeTemporary)); 1646 EXPECT_FALSE(HasFileSystemType(enumerator.get(), 1647 kFileSystemTypePersistent)); 1648 found = true; 1649 } 1650 EXPECT_TRUE(found); 1651 } 1652 1653 std::set<GURL> diff; 1654 std::set_symmetric_difference(origins_expected.begin(), 1655 origins_expected.end(), origins_found.begin(), origins_found.end(), 1656 inserter(diff, diff.begin())); 1657 EXPECT_TRUE(diff.empty()); 1658 } 1659 1660 TEST_F(ObfuscatedFileUtilTest, TestRevokeUsageCache) { 1661 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1662 1663 int64 expected_quota = 0; 1664 1665 for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) { 1666 SCOPED_TRACE(testing::Message() << "Creating kRegularTestCase " << i); 1667 const FileSystemTestCaseRecord& test_case = 1668 kRegularFileSystemTestCases[i]; 1669 base::FilePath file_path(test_case.path); 1670 expected_quota += ObfuscatedFileUtil::ComputeFilePathCost(file_path); 1671 if (test_case.is_directory) { 1672 bool exclusive = true; 1673 bool recursive = false; 1674 ASSERT_EQ(base::File::FILE_OK, 1675 ofu()->CreateDirectory(context.get(), CreateURL(file_path), 1676 exclusive, recursive)); 1677 } else { 1678 bool created = false; 1679 ASSERT_EQ(base::File::FILE_OK, 1680 ofu()->EnsureFileExists(context.get(), CreateURL(file_path), 1681 &created)); 1682 ASSERT_TRUE(created); 1683 ASSERT_EQ(base::File::FILE_OK, 1684 ofu()->Truncate(context.get(), CreateURL(file_path), 1685 test_case.data_file_size)); 1686 expected_quota += test_case.data_file_size; 1687 } 1688 } 1689 1690 // Usually raw size in usage cache and the usage returned by QuotaUtil 1691 // should be same. 1692 EXPECT_EQ(expected_quota, SizeInUsageFile()); 1693 EXPECT_EQ(expected_quota, SizeByQuotaUtil()); 1694 1695 RevokeUsageCache(); 1696 EXPECT_EQ(-1, SizeInUsageFile()); 1697 EXPECT_EQ(expected_quota, SizeByQuotaUtil()); 1698 1699 // This should reconstruct the cache. 1700 GetUsageFromQuotaManager(); 1701 EXPECT_EQ(expected_quota, SizeInUsageFile()); 1702 EXPECT_EQ(expected_quota, SizeByQuotaUtil()); 1703 EXPECT_EQ(expected_quota, usage()); 1704 } 1705 1706 TEST_F(ObfuscatedFileUtilTest, TestInconsistency) { 1707 const FileSystemURL kPath1 = CreateURLFromUTF8("hoge"); 1708 const FileSystemURL kPath2 = CreateURLFromUTF8("fuga"); 1709 1710 scoped_ptr<FileSystemOperationContext> context; 1711 base::File::Info file_info; 1712 base::FilePath data_path; 1713 bool created = false; 1714 1715 // Create a non-empty file. 1716 context.reset(NewContext(NULL)); 1717 EXPECT_EQ(base::File::FILE_OK, 1718 ofu()->EnsureFileExists(context.get(), kPath1, &created)); 1719 EXPECT_TRUE(created); 1720 context.reset(NewContext(NULL)); 1721 EXPECT_EQ(base::File::FILE_OK, 1722 ofu()->Truncate(context.get(), kPath1, 10)); 1723 context.reset(NewContext(NULL)); 1724 EXPECT_EQ(base::File::FILE_OK, 1725 ofu()->GetFileInfo( 1726 context.get(), kPath1, &file_info, &data_path)); 1727 EXPECT_EQ(10, file_info.size); 1728 1729 // Destroy database to make inconsistency between database and filesystem. 1730 ofu()->DestroyDirectoryDatabase(origin(), type_string()); 1731 1732 // Try to get file info of broken file. 1733 EXPECT_FALSE(PathExists(kPath1)); 1734 context.reset(NewContext(NULL)); 1735 EXPECT_EQ(base::File::FILE_OK, 1736 ofu()->EnsureFileExists(context.get(), kPath1, &created)); 1737 EXPECT_TRUE(created); 1738 context.reset(NewContext(NULL)); 1739 EXPECT_EQ(base::File::FILE_OK, 1740 ofu()->GetFileInfo( 1741 context.get(), kPath1, &file_info, &data_path)); 1742 EXPECT_EQ(0, file_info.size); 1743 1744 // Make another broken file to |kPath2|. 1745 context.reset(NewContext(NULL)); 1746 EXPECT_EQ(base::File::FILE_OK, 1747 ofu()->EnsureFileExists(context.get(), kPath2, &created)); 1748 EXPECT_TRUE(created); 1749 1750 // Destroy again. 1751 ofu()->DestroyDirectoryDatabase(origin(), type_string()); 1752 1753 // Repair broken |kPath1|. 1754 context.reset(NewContext(NULL)); 1755 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1756 ofu()->Touch(context.get(), kPath1, base::Time::Now(), 1757 base::Time::Now())); 1758 EXPECT_EQ(base::File::FILE_OK, 1759 ofu()->EnsureFileExists(context.get(), kPath1, &created)); 1760 EXPECT_TRUE(created); 1761 1762 // Copy from sound |kPath1| to broken |kPath2|. 1763 context.reset(NewContext(NULL)); 1764 EXPECT_EQ(base::File::FILE_OK, 1765 ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2, 1766 FileSystemOperation::OPTION_NONE, 1767 true /* copy */)); 1768 1769 ofu()->DestroyDirectoryDatabase(origin(), type_string()); 1770 context.reset(NewContext(NULL)); 1771 base::File file = 1772 ofu()->CreateOrOpen(context.get(), kPath1, 1773 base::File::FLAG_READ | base::File::FLAG_CREATE); 1774 EXPECT_TRUE(file.IsValid()); 1775 EXPECT_TRUE(file.created()); 1776 1777 EXPECT_TRUE(file.GetInfo(&file_info)); 1778 EXPECT_EQ(0, file_info.size); 1779 } 1780 1781 TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) { 1782 const FileSystemURL kPath[] = { 1783 CreateURLFromUTF8("foo"), 1784 CreateURLFromUTF8("bar"), 1785 CreateURLFromUTF8("baz") 1786 }; 1787 const FileSystemURL empty_path = CreateURL(base::FilePath()); 1788 scoped_ptr<FileSystemOperationContext> context; 1789 1790 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kPath); ++i) { 1791 bool created = false; 1792 context.reset(NewContext(NULL)); 1793 EXPECT_EQ(base::File::FILE_OK, 1794 ofu()->EnsureFileExists(context.get(), kPath[i], &created)); 1795 EXPECT_TRUE(created); 1796 } 1797 1798 std::vector<fileapi::DirectoryEntry> entries; 1799 EXPECT_EQ(base::File::FILE_OK, 1800 AsyncFileTestHelper::ReadDirectory( 1801 file_system_context(), empty_path, &entries)); 1802 EXPECT_EQ(3u, entries.size()); 1803 1804 base::FilePath local_path; 1805 EXPECT_EQ(base::File::FILE_OK, 1806 ofu()->GetLocalFilePath(context.get(), kPath[0], &local_path)); 1807 EXPECT_TRUE(base::DeleteFile(local_path, false)); 1808 1809 entries.clear(); 1810 EXPECT_EQ(base::File::FILE_OK, 1811 AsyncFileTestHelper::ReadDirectory( 1812 file_system_context(), empty_path, &entries)); 1813 EXPECT_EQ(ARRAYSIZE_UNSAFE(kPath) - 1, entries.size()); 1814 } 1815 1816 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) { 1817 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1818 const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir"); 1819 1820 // Create working directory. 1821 EXPECT_EQ(base::File::FILE_OK, 1822 ofu()->CreateDirectory(context.get(), dir_url, false, false)); 1823 1824 // EnsureFileExists, create case. 1825 FileSystemURL url(FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_file")); 1826 bool created = false; 1827 ClearTimestamp(dir_url); 1828 context.reset(NewContext(NULL)); 1829 EXPECT_EQ(base::File::FILE_OK, 1830 ofu()->EnsureFileExists(context.get(), url, &created)); 1831 EXPECT_TRUE(created); 1832 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1833 1834 // non create case. 1835 created = true; 1836 ClearTimestamp(dir_url); 1837 context.reset(NewContext(NULL)); 1838 EXPECT_EQ(base::File::FILE_OK, 1839 ofu()->EnsureFileExists(context.get(), url, &created)); 1840 EXPECT_FALSE(created); 1841 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1842 1843 // fail case. 1844 url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir"); 1845 context.reset(NewContext(NULL)); 1846 EXPECT_EQ(base::File::FILE_OK, 1847 ofu()->CreateDirectory(context.get(), url, false, false)); 1848 1849 ClearTimestamp(dir_url); 1850 context.reset(NewContext(NULL)); 1851 EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE, 1852 ofu()->EnsureFileExists(context.get(), url, &created)); 1853 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1854 1855 // CreateOrOpen, create case. 1856 url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file"); 1857 ClearTimestamp(dir_url); 1858 context.reset(NewContext(NULL)); 1859 base::File file = 1860 ofu()->CreateOrOpen(context.get(), url, 1861 base::File::FLAG_CREATE | base::File::FLAG_WRITE); 1862 1863 EXPECT_TRUE(file.IsValid()); 1864 EXPECT_TRUE(file.created()); 1865 file.Close(); 1866 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1867 1868 // open case. 1869 ClearTimestamp(dir_url); 1870 context.reset(NewContext(NULL)); 1871 file = ofu()->CreateOrOpen(context.get(), url, 1872 base::File::FLAG_OPEN | base::File::FLAG_WRITE); 1873 EXPECT_TRUE(file.IsValid()); 1874 EXPECT_FALSE(file.created()); 1875 file.Close(); 1876 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1877 1878 // fail case 1879 ClearTimestamp(dir_url); 1880 context.reset(NewContext(NULL)); 1881 file = ofu()->CreateOrOpen(context.get(), url, 1882 base::File::FLAG_CREATE | base::File::FLAG_WRITE); 1883 EXPECT_FALSE(file.IsValid()); 1884 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details()); 1885 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1886 1887 // CreateDirectory, create case. 1888 // Creating CreateDirectory_dir and CreateDirectory_dir/subdir. 1889 url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir"); 1890 FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir")); 1891 ClearTimestamp(dir_url); 1892 context.reset(NewContext(NULL)); 1893 EXPECT_EQ(base::File::FILE_OK, 1894 ofu()->CreateDirectory(context.get(), subdir_url, 1895 true /* exclusive */, true /* recursive */)); 1896 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1897 1898 // create subdir case. 1899 // Creating CreateDirectory_dir/subdir2. 1900 subdir_url = FileSystemURLAppendUTF8(url, "subdir2"); 1901 ClearTimestamp(dir_url); 1902 ClearTimestamp(url); 1903 context.reset(NewContext(NULL)); 1904 EXPECT_EQ(base::File::FILE_OK, 1905 ofu()->CreateDirectory(context.get(), subdir_url, 1906 true /* exclusive */, true /* recursive */)); 1907 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1908 EXPECT_NE(base::Time(), GetModifiedTime(url)); 1909 1910 // fail case. 1911 url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir"); 1912 ClearTimestamp(dir_url); 1913 context.reset(NewContext(NULL)); 1914 EXPECT_EQ(base::File::FILE_ERROR_EXISTS, 1915 ofu()->CreateDirectory(context.get(), url, 1916 true /* exclusive */, true /* recursive */)); 1917 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1918 1919 // CopyInForeignFile, create case. 1920 url = FileSystemURLAppendUTF8(dir_url, "CopyInForeignFile_file"); 1921 FileSystemURL src_path = FileSystemURLAppendUTF8( 1922 dir_url, "CopyInForeignFile_src_file"); 1923 context.reset(NewContext(NULL)); 1924 EXPECT_EQ(base::File::FILE_OK, 1925 ofu()->EnsureFileExists(context.get(), src_path, &created)); 1926 EXPECT_TRUE(created); 1927 base::FilePath src_local_path; 1928 context.reset(NewContext(NULL)); 1929 EXPECT_EQ(base::File::FILE_OK, 1930 ofu()->GetLocalFilePath(context.get(), src_path, &src_local_path)); 1931 1932 ClearTimestamp(dir_url); 1933 context.reset(NewContext(NULL)); 1934 EXPECT_EQ(base::File::FILE_OK, 1935 ofu()->CopyInForeignFile(context.get(), 1936 src_local_path, 1937 url)); 1938 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1939 } 1940 1941 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) { 1942 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 1943 const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir"); 1944 1945 // Create working directory. 1946 EXPECT_EQ(base::File::FILE_OK, 1947 ofu()->CreateDirectory(context.get(), dir_url, false, false)); 1948 1949 // DeleteFile, delete case. 1950 FileSystemURL url = FileSystemURLAppendUTF8( 1951 dir_url, "DeleteFile_file"); 1952 bool created = false; 1953 context.reset(NewContext(NULL)); 1954 EXPECT_EQ(base::File::FILE_OK, 1955 ofu()->EnsureFileExists(context.get(), url, &created)); 1956 EXPECT_TRUE(created); 1957 1958 ClearTimestamp(dir_url); 1959 context.reset(NewContext(NULL)); 1960 EXPECT_EQ(base::File::FILE_OK, 1961 ofu()->DeleteFile(context.get(), url)); 1962 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1963 1964 // fail case. 1965 ClearTimestamp(dir_url); 1966 context.reset(NewContext(NULL)); 1967 EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, 1968 ofu()->DeleteFile(context.get(), url)); 1969 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1970 1971 // DeleteDirectory, fail case. 1972 url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir"); 1973 FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta")); 1974 context.reset(NewContext(NULL)); 1975 EXPECT_EQ(base::File::FILE_OK, 1976 ofu()->CreateDirectory(context.get(), url, true, true)); 1977 created = false; 1978 context.reset(NewContext(NULL)); 1979 EXPECT_EQ(base::File::FILE_OK, 1980 ofu()->EnsureFileExists(context.get(), file_path, &created)); 1981 EXPECT_TRUE(created); 1982 1983 ClearTimestamp(dir_url); 1984 context.reset(NewContext(NULL)); 1985 EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, 1986 ofu()->DeleteDirectory(context.get(), url)); 1987 EXPECT_EQ(base::Time(), GetModifiedTime(dir_url)); 1988 1989 // delete case. 1990 context.reset(NewContext(NULL)); 1991 EXPECT_EQ(base::File::FILE_OK, 1992 ofu()->DeleteFile(context.get(), file_path)); 1993 1994 ClearTimestamp(dir_url); 1995 context.reset(NewContext(NULL)); 1996 EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url)); 1997 EXPECT_NE(base::Time(), GetModifiedTime(dir_url)); 1998 } 1999 2000 TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCopyAndMove) { 2001 TestDirectoryTimestampHelper( 2002 CreateURLFromUTF8("copy overwrite"), true, true); 2003 TestDirectoryTimestampHelper( 2004 CreateURLFromUTF8("copy non-overwrite"), true, false); 2005 TestDirectoryTimestampHelper( 2006 CreateURLFromUTF8("move overwrite"), false, true); 2007 TestDirectoryTimestampHelper( 2008 CreateURLFromUTF8("move non-overwrite"), false, false); 2009 } 2010 2011 TEST_F(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) { 2012 FileSystemURL dir = CreateURLFromUTF8("foo"); 2013 FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar"); 2014 FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz"); 2015 2016 scoped_ptr<FileSystemOperationContext> context(NewContext(NULL)); 2017 EXPECT_EQ(base::File::FILE_OK, 2018 ofu()->CreateDirectory(context.get(), dir, false, false)); 2019 2020 bool created = false; 2021 context.reset(NewContext(NULL)); 2022 EXPECT_EQ(base::File::FILE_OK, 2023 ofu()->EnsureFileExists(context.get(), url1, &created)); 2024 EXPECT_TRUE(created); 2025 2026 context.reset(NewContext(NULL)); 2027 EXPECT_EQ(base::File::FILE_OK, 2028 ofu()->CreateDirectory(context.get(), url2, false, false)); 2029 2030 base::FilePath file_path; 2031 context.reset(NewContext(NULL)); 2032 EXPECT_EQ(base::File::FILE_OK, 2033 ofu()->GetLocalFilePath(context.get(), url1, &file_path)); 2034 EXPECT_FALSE(file_path.empty()); 2035 2036 context.reset(NewContext(NULL)); 2037 EXPECT_EQ(base::File::FILE_OK, 2038 ofu()->Touch(context.get(), url1, 2039 base::Time::Now() + base::TimeDelta::FromHours(1), 2040 base::Time())); 2041 2042 context.reset(NewContext(NULL)); 2043 scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> file_enum( 2044 ofu()->CreateFileEnumerator(context.get(), dir, false)); 2045 2046 int count = 0; 2047 base::FilePath file_path_each; 2048 while (!(file_path_each = file_enum->Next()).empty()) { 2049 context.reset(NewContext(NULL)); 2050 base::File::Info file_info; 2051 base::FilePath file_path; 2052 EXPECT_EQ(base::File::FILE_OK, 2053 ofu()->GetFileInfo(context.get(), 2054 FileSystemURL::CreateForTest( 2055 dir.origin(), 2056 dir.mount_type(), 2057 file_path_each), 2058 &file_info, &file_path)); 2059 EXPECT_EQ(file_info.is_directory, file_enum->IsDirectory()); 2060 EXPECT_EQ(file_info.last_modified, file_enum->LastModifiedTime()); 2061 EXPECT_EQ(file_info.size, file_enum->Size()); 2062 ++count; 2063 } 2064 EXPECT_EQ(2, count); 2065 } 2066 2067 // crbug.com/176470 2068 #if defined(OS_WIN) || defined(OS_ANDROID) 2069 #define MAYBE_TestQuotaOnCopyFile DISABLED_TestQuotaOnCopyFile 2070 #else 2071 #define MAYBE_TestQuotaOnCopyFile TestQuotaOnCopyFile 2072 #endif 2073 TEST_F(ObfuscatedFileUtilTest, MAYBE_TestQuotaOnCopyFile) { 2074 FileSystemURL from_file(CreateURLFromUTF8("fromfile")); 2075 FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile")); 2076 FileSystemURL to_file1(CreateURLFromUTF8("tofile1")); 2077 FileSystemURL to_file2(CreateURLFromUTF8("tofile2")); 2078 bool created; 2079 2080 int64 expected_total_file_size = 0; 2081 ASSERT_EQ(base::File::FILE_OK, 2082 ofu()->EnsureFileExists( 2083 AllowUsageIncrease(PathCost(from_file))->context(), 2084 from_file, &created)); 2085 ASSERT_TRUE(created); 2086 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2087 2088 ASSERT_EQ(base::File::FILE_OK, 2089 ofu()->EnsureFileExists( 2090 AllowUsageIncrease(PathCost(obstacle_file))->context(), 2091 obstacle_file, &created)); 2092 ASSERT_TRUE(created); 2093 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2094 2095 int64 from_file_size = 1020; 2096 expected_total_file_size += from_file_size; 2097 ASSERT_EQ(base::File::FILE_OK, 2098 ofu()->Truncate( 2099 AllowUsageIncrease(from_file_size)->context(), 2100 from_file, from_file_size)); 2101 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2102 2103 int64 obstacle_file_size = 1; 2104 expected_total_file_size += obstacle_file_size; 2105 ASSERT_EQ(base::File::FILE_OK, 2106 ofu()->Truncate( 2107 AllowUsageIncrease(obstacle_file_size)->context(), 2108 obstacle_file, obstacle_file_size)); 2109 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2110 2111 int64 to_file1_size = from_file_size; 2112 expected_total_file_size += to_file1_size; 2113 ASSERT_EQ(base::File::FILE_OK, 2114 ofu()->CopyOrMoveFile( 2115 AllowUsageIncrease( 2116 PathCost(to_file1) + to_file1_size)->context(), 2117 from_file, to_file1, 2118 FileSystemOperation::OPTION_NONE, 2119 true /* copy */)); 2120 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2121 2122 ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE, 2123 ofu()->CopyOrMoveFile( 2124 DisallowUsageIncrease( 2125 PathCost(to_file2) + from_file_size)->context(), 2126 from_file, to_file2, FileSystemOperation::OPTION_NONE, 2127 true /* copy */)); 2128 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2129 2130 int64 old_obstacle_file_size = obstacle_file_size; 2131 obstacle_file_size = from_file_size; 2132 expected_total_file_size += obstacle_file_size - old_obstacle_file_size; 2133 ASSERT_EQ(base::File::FILE_OK, 2134 ofu()->CopyOrMoveFile( 2135 AllowUsageIncrease( 2136 obstacle_file_size - old_obstacle_file_size)->context(), 2137 from_file, obstacle_file, 2138 FileSystemOperation::OPTION_NONE, 2139 true /* copy */)); 2140 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2141 2142 int64 old_from_file_size = from_file_size; 2143 from_file_size = old_from_file_size - 1; 2144 expected_total_file_size += from_file_size - old_from_file_size; 2145 ASSERT_EQ(base::File::FILE_OK, 2146 ofu()->Truncate( 2147 AllowUsageIncrease( 2148 from_file_size - old_from_file_size)->context(), 2149 from_file, from_file_size)); 2150 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2151 2152 // quota exceeded 2153 { 2154 old_obstacle_file_size = obstacle_file_size; 2155 obstacle_file_size = from_file_size; 2156 expected_total_file_size += obstacle_file_size - old_obstacle_file_size; 2157 scoped_ptr<UsageVerifyHelper> helper = AllowUsageIncrease( 2158 obstacle_file_size - old_obstacle_file_size); 2159 helper->context()->set_allowed_bytes_growth( 2160 helper->context()->allowed_bytes_growth() - 1); 2161 ASSERT_EQ(base::File::FILE_OK, 2162 ofu()->CopyOrMoveFile( 2163 helper->context(), 2164 from_file, obstacle_file, 2165 FileSystemOperation::OPTION_NONE, 2166 true /* copy */)); 2167 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2168 } 2169 } 2170 2171 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnMoveFile) { 2172 FileSystemURL from_file(CreateURLFromUTF8("fromfile")); 2173 FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile")); 2174 FileSystemURL to_file(CreateURLFromUTF8("tofile")); 2175 bool created; 2176 2177 int64 expected_total_file_size = 0; 2178 ASSERT_EQ(base::File::FILE_OK, 2179 ofu()->EnsureFileExists( 2180 AllowUsageIncrease(PathCost(from_file))->context(), 2181 from_file, &created)); 2182 ASSERT_TRUE(created); 2183 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2184 2185 int64 from_file_size = 1020; 2186 expected_total_file_size += from_file_size; 2187 ASSERT_EQ(base::File::FILE_OK, 2188 ofu()->Truncate( 2189 AllowUsageIncrease(from_file_size)->context(), 2190 from_file, from_file_size)); 2191 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2192 2193 int64 to_file_size ALLOW_UNUSED = from_file_size; 2194 from_file_size = 0; 2195 ASSERT_EQ(base::File::FILE_OK, 2196 ofu()->CopyOrMoveFile( 2197 AllowUsageIncrease(-PathCost(from_file) + 2198 PathCost(to_file))->context(), 2199 from_file, to_file, 2200 FileSystemOperation::OPTION_NONE, 2201 false /* move */)); 2202 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2203 2204 ASSERT_EQ(base::File::FILE_OK, 2205 ofu()->EnsureFileExists( 2206 AllowUsageIncrease(PathCost(from_file))->context(), 2207 from_file, &created)); 2208 ASSERT_TRUE(created); 2209 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2210 2211 ASSERT_EQ(base::File::FILE_OK, 2212 ofu()->EnsureFileExists( 2213 AllowUsageIncrease(PathCost(obstacle_file))->context(), 2214 obstacle_file, &created)); 2215 ASSERT_TRUE(created); 2216 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2217 2218 from_file_size = 1020; 2219 expected_total_file_size += from_file_size; 2220 ASSERT_EQ(base::File::FILE_OK, 2221 ofu()->Truncate( 2222 AllowUsageIncrease(from_file_size)->context(), 2223 from_file, from_file_size)); 2224 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2225 2226 int64 obstacle_file_size = 1; 2227 expected_total_file_size += obstacle_file_size; 2228 ASSERT_EQ(base::File::FILE_OK, 2229 ofu()->Truncate( 2230 AllowUsageIncrease(1)->context(), 2231 obstacle_file, obstacle_file_size)); 2232 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2233 2234 int64 old_obstacle_file_size = obstacle_file_size; 2235 obstacle_file_size = from_file_size; 2236 from_file_size = 0; 2237 expected_total_file_size -= old_obstacle_file_size; 2238 ASSERT_EQ(base::File::FILE_OK, 2239 ofu()->CopyOrMoveFile( 2240 AllowUsageIncrease( 2241 -old_obstacle_file_size - PathCost(from_file))->context(), 2242 from_file, obstacle_file, 2243 FileSystemOperation::OPTION_NONE, 2244 false /* move */)); 2245 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2246 2247 ASSERT_EQ(base::File::FILE_OK, 2248 ofu()->EnsureFileExists( 2249 AllowUsageIncrease(PathCost(from_file))->context(), 2250 from_file, &created)); 2251 ASSERT_TRUE(created); 2252 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2253 2254 from_file_size = 10; 2255 expected_total_file_size += from_file_size; 2256 ASSERT_EQ(base::File::FILE_OK, 2257 ofu()->Truncate( 2258 AllowUsageIncrease(from_file_size)->context(), 2259 from_file, from_file_size)); 2260 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2261 2262 // quota exceeded even after operation 2263 old_obstacle_file_size = obstacle_file_size; 2264 obstacle_file_size = from_file_size; 2265 from_file_size = 0; 2266 expected_total_file_size -= old_obstacle_file_size; 2267 scoped_ptr<FileSystemOperationContext> context = 2268 LimitedContext(-old_obstacle_file_size - PathCost(from_file) - 1); 2269 ASSERT_EQ(base::File::FILE_OK, 2270 ofu()->CopyOrMoveFile( 2271 context.get(), from_file, obstacle_file, 2272 FileSystemOperation::OPTION_NONE, 2273 false /* move */)); 2274 ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize()); 2275 context.reset(); 2276 } 2277 2278 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnRemove) { 2279 FileSystemURL dir(CreateURLFromUTF8("dir")); 2280 FileSystemURL file(CreateURLFromUTF8("file")); 2281 FileSystemURL dfile1(CreateURLFromUTF8("dir/dfile1")); 2282 FileSystemURL dfile2(CreateURLFromUTF8("dir/dfile2")); 2283 bool created; 2284 2285 ASSERT_EQ(base::File::FILE_OK, 2286 ofu()->EnsureFileExists( 2287 AllowUsageIncrease(PathCost(file))->context(), 2288 file, &created)); 2289 ASSERT_TRUE(created); 2290 ASSERT_EQ(0, ComputeTotalFileSize()); 2291 2292 ASSERT_EQ(base::File::FILE_OK, 2293 ofu()->CreateDirectory( 2294 AllowUsageIncrease(PathCost(dir))->context(), 2295 dir, false, false)); 2296 ASSERT_EQ(0, ComputeTotalFileSize()); 2297 2298 ASSERT_EQ(base::File::FILE_OK, 2299 ofu()->EnsureFileExists( 2300 AllowUsageIncrease(PathCost(dfile1))->context(), 2301 dfile1, &created)); 2302 ASSERT_TRUE(created); 2303 ASSERT_EQ(0, ComputeTotalFileSize()); 2304 2305 ASSERT_EQ(base::File::FILE_OK, 2306 ofu()->EnsureFileExists( 2307 AllowUsageIncrease(PathCost(dfile2))->context(), 2308 dfile2, &created)); 2309 ASSERT_TRUE(created); 2310 ASSERT_EQ(0, ComputeTotalFileSize()); 2311 2312 ASSERT_EQ(base::File::FILE_OK, 2313 ofu()->Truncate( 2314 AllowUsageIncrease(340)->context(), 2315 file, 340)); 2316 ASSERT_EQ(340, ComputeTotalFileSize()); 2317 2318 ASSERT_EQ(base::File::FILE_OK, 2319 ofu()->Truncate( 2320 AllowUsageIncrease(1020)->context(), 2321 dfile1, 1020)); 2322 ASSERT_EQ(1360, ComputeTotalFileSize()); 2323 2324 ASSERT_EQ(base::File::FILE_OK, 2325 ofu()->Truncate( 2326 AllowUsageIncrease(120)->context(), 2327 dfile2, 120)); 2328 ASSERT_EQ(1480, ComputeTotalFileSize()); 2329 2330 ASSERT_EQ(base::File::FILE_OK, 2331 ofu()->DeleteFile( 2332 AllowUsageIncrease(-PathCost(file) - 340)->context(), 2333 file)); 2334 ASSERT_EQ(1140, ComputeTotalFileSize()); 2335 2336 ASSERT_EQ(base::File::FILE_OK, 2337 AsyncFileTestHelper::Remove( 2338 file_system_context(), dir, true /* recursive */)); 2339 ASSERT_EQ(0, ComputeTotalFileSize()); 2340 } 2341 2342 TEST_F(ObfuscatedFileUtilTest, TestQuotaOnOpen) { 2343 FileSystemURL url(CreateURLFromUTF8("file")); 2344 2345 bool created; 2346 // Creating a file. 2347 ASSERT_EQ(base::File::FILE_OK, 2348 ofu()->EnsureFileExists( 2349 AllowUsageIncrease(PathCost(url))->context(), 2350 url, &created)); 2351 ASSERT_TRUE(created); 2352 ASSERT_EQ(0, ComputeTotalFileSize()); 2353 2354 // Opening it, which shouldn't change the usage. 2355 base::File file = 2356 ofu()->CreateOrOpen(AllowUsageIncrease(0)->context(), url, 2357 base::File::FLAG_OPEN | base::File::FLAG_WRITE); 2358 ASSERT_TRUE(file.IsValid()); 2359 ASSERT_EQ(0, ComputeTotalFileSize()); 2360 file.Close(); 2361 2362 const int length = 33; 2363 ASSERT_EQ(base::File::FILE_OK, 2364 ofu()->Truncate( 2365 AllowUsageIncrease(length)->context(), url, length)); 2366 ASSERT_EQ(length, ComputeTotalFileSize()); 2367 2368 // Opening it with CREATE_ALWAYS flag, which should truncate the file size. 2369 file = ofu()->CreateOrOpen( 2370 AllowUsageIncrease(-length)->context(), url, 2371 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); 2372 ASSERT_TRUE(file.IsValid()); 2373 ASSERT_EQ(0, ComputeTotalFileSize()); 2374 file.Close(); 2375 2376 // Extending the file again. 2377 ASSERT_EQ(base::File::FILE_OK, 2378 ofu()->Truncate( 2379 AllowUsageIncrease(length)->context(), url, length)); 2380 ASSERT_EQ(length, ComputeTotalFileSize()); 2381 2382 // Opening it with TRUNCATED flag, which should truncate the file size. 2383 file = ofu()->CreateOrOpen( 2384 AllowUsageIncrease(-length)->context(), url, 2385 base::File::FLAG_OPEN_TRUNCATED | base::File::FLAG_WRITE); 2386 ASSERT_TRUE(file.IsValid()); 2387 ASSERT_EQ(0, ComputeTotalFileSize()); 2388 file.Close(); 2389 } 2390 2391 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) { 2392 MaybeDropDatabasesAliveCaseTestBody(); 2393 } 2394 2395 TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) { 2396 MaybeDropDatabasesAlreadyDeletedCaseTestBody(); 2397 } 2398 2399 TEST_F(ObfuscatedFileUtilTest, DestroyDirectoryDatabase_Isolated) { 2400 DestroyDirectoryDatabase_IsolatedTestBody(); 2401 } 2402 2403 TEST_F(ObfuscatedFileUtilTest, GetDirectoryDatabase_Isolated) { 2404 GetDirectoryDatabase_IsolatedTestBody(); 2405 } 2406 2407 TEST_F(ObfuscatedFileUtilTest, MigrationBackFromIsolated) { 2408 MigrationBackFromIsolatedTestBody(); 2409 } 2410 2411 TEST_F(ObfuscatedFileUtilTest, OpenPathInNonDirectory) { 2412 FileSystemURL url(CreateURLFromUTF8("file")); 2413 FileSystemURL path_in_file(CreateURLFromUTF8("file/file")); 2414 bool created; 2415 2416 ASSERT_EQ(base::File::FILE_OK, 2417 ofu()->EnsureFileExists(UnlimitedContext().get(), url, &created)); 2418 ASSERT_TRUE(created); 2419 2420 int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE; 2421 base::File file = 2422 ofu()->CreateOrOpen(UnlimitedContext().get(), path_in_file, file_flags); 2423 ASSERT_FALSE(file.IsValid()); 2424 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, file.error_details()); 2425 2426 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, 2427 ofu()->CreateDirectory(UnlimitedContext().get(), 2428 path_in_file, 2429 false /* exclusive */, 2430 false /* recursive */)); 2431 } 2432 2433 TEST_F(ObfuscatedFileUtilTest, CreateDirectory_NotADirectoryInRecursive) { 2434 FileSystemURL file(CreateURLFromUTF8("file")); 2435 FileSystemURL path_in_file(CreateURLFromUTF8("file/child")); 2436 FileSystemURL path_in_file_in_file( 2437 CreateURLFromUTF8("file/child/grandchild")); 2438 bool created; 2439 2440 ASSERT_EQ(base::File::FILE_OK, 2441 ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created)); 2442 ASSERT_TRUE(created); 2443 2444 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, 2445 ofu()->CreateDirectory(UnlimitedContext().get(), 2446 path_in_file, 2447 false /* exclusive */, 2448 true /* recursive */)); 2449 ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, 2450 ofu()->CreateDirectory(UnlimitedContext().get(), 2451 path_in_file_in_file, 2452 false /* exclusive */, 2453 true /* recursive */)); 2454 } 2455 2456 } // namespace content 2457