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