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