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 "content/browser/download/base_file.h" 6 7 #include "base/file_util.h" 8 #include "base/files/file.h" 9 #include "base/files/scoped_temp_dir.h" 10 #include "base/logging.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/strings/string_number_conversions.h" 13 #include "base/test/test_file_util.h" 14 #include "content/browser/browser_thread_impl.h" 15 #include "content/public/browser/download_interrupt_reasons.h" 16 #include "crypto/secure_hash.h" 17 #include "crypto/sha2.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 20 namespace content { 21 namespace { 22 23 const char kTestData1[] = "Let's write some data to the file!\n"; 24 const char kTestData2[] = "Writing more data.\n"; 25 const char kTestData3[] = "Final line."; 26 const char kTestData4[] = "supercalifragilisticexpialidocious"; 27 const int kTestDataLength1 = arraysize(kTestData1) - 1; 28 const int kTestDataLength2 = arraysize(kTestData2) - 1; 29 const int kTestDataLength3 = arraysize(kTestData3) - 1; 30 const int kTestDataLength4 = arraysize(kTestData4) - 1; 31 const int kElapsedTimeSeconds = 5; 32 const base::TimeDelta kElapsedTimeDelta = base::TimeDelta::FromSeconds( 33 kElapsedTimeSeconds); 34 35 } // namespace 36 37 class BaseFileTest : public testing::Test { 38 public: 39 static const unsigned char kEmptySha256Hash[crypto::kSHA256Length]; 40 41 BaseFileTest() 42 : expect_file_survives_(false), 43 expect_in_progress_(true), 44 expected_error_(DOWNLOAD_INTERRUPT_REASON_NONE), 45 file_thread_(BrowserThread::FILE, &message_loop_) { 46 } 47 48 virtual void SetUp() { 49 ResetHash(); 50 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 51 base_file_.reset(new BaseFile(base::FilePath(), 52 GURL(), 53 GURL(), 54 0, 55 false, 56 std::string(), 57 base::File(), 58 net::BoundNetLog())); 59 } 60 61 virtual void TearDown() { 62 EXPECT_FALSE(base_file_->in_progress()); 63 if (!expected_error_) { 64 EXPECT_EQ(static_cast<int64>(expected_data_.size()), 65 base_file_->bytes_so_far()); 66 } 67 68 base::FilePath full_path = base_file_->full_path(); 69 70 if (!expected_data_.empty() && !expected_error_) { 71 // Make sure the data has been properly written to disk. 72 std::string disk_data; 73 EXPECT_TRUE(base::ReadFileToString(full_path, &disk_data)); 74 EXPECT_EQ(expected_data_, disk_data); 75 } 76 77 // Make sure the mock BrowserThread outlives the BaseFile to satisfy 78 // thread checks inside it. 79 base_file_.reset(); 80 81 EXPECT_EQ(expect_file_survives_, base::PathExists(full_path)); 82 } 83 84 void ResetHash() { 85 secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256)); 86 memcpy(sha256_hash_, kEmptySha256Hash, crypto::kSHA256Length); 87 } 88 89 void UpdateHash(const char* data, size_t length) { 90 secure_hash_->Update(data, length); 91 } 92 93 std::string GetFinalHash() { 94 std::string hash; 95 secure_hash_->Finish(sha256_hash_, crypto::kSHA256Length); 96 hash.assign(reinterpret_cast<const char*>(sha256_hash_), 97 sizeof(sha256_hash_)); 98 return hash; 99 } 100 101 void MakeFileWithHash() { 102 base_file_.reset(new BaseFile(base::FilePath(), 103 GURL(), 104 GURL(), 105 0, 106 true, 107 std::string(), 108 base::File(), 109 net::BoundNetLog())); 110 } 111 112 bool InitializeFile() { 113 DownloadInterruptReason result = base_file_->Initialize(temp_dir_.path()); 114 EXPECT_EQ(expected_error_, result); 115 return result == DOWNLOAD_INTERRUPT_REASON_NONE; 116 } 117 118 bool AppendDataToFile(const std::string& data) { 119 EXPECT_EQ(expect_in_progress_, base_file_->in_progress()); 120 DownloadInterruptReason result = 121 base_file_->AppendDataToFile(data.data(), data.size()); 122 if (result == DOWNLOAD_INTERRUPT_REASON_NONE) 123 EXPECT_TRUE(expect_in_progress_) << " result = " << result; 124 125 EXPECT_EQ(expected_error_, result); 126 if (base_file_->in_progress()) { 127 expected_data_ += data; 128 if (expected_error_ == DOWNLOAD_INTERRUPT_REASON_NONE) { 129 EXPECT_EQ(static_cast<int64>(expected_data_.size()), 130 base_file_->bytes_so_far()); 131 } 132 } 133 return result == DOWNLOAD_INTERRUPT_REASON_NONE; 134 } 135 136 void set_expected_data(const std::string& data) { expected_data_ = data; } 137 138 // Helper functions. 139 // Create a file. Returns the complete file path. 140 base::FilePath CreateTestFile() { 141 base::FilePath file_name; 142 BaseFile file(base::FilePath(), 143 GURL(), 144 GURL(), 145 0, 146 false, 147 std::string(), 148 base::File(), 149 net::BoundNetLog()); 150 151 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 152 file.Initialize(temp_dir_.path())); 153 file_name = file.full_path(); 154 EXPECT_NE(base::FilePath::StringType(), file_name.value()); 155 156 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 157 file.AppendDataToFile(kTestData4, kTestDataLength4)); 158 159 // Keep the file from getting deleted when existing_file_name is deleted. 160 file.Detach(); 161 162 return file_name; 163 } 164 165 // Create a file with the specified file name. 166 void CreateFileWithName(const base::FilePath& file_name) { 167 EXPECT_NE(base::FilePath::StringType(), file_name.value()); 168 BaseFile duplicate_file(file_name, 169 GURL(), 170 GURL(), 171 0, 172 false, 173 std::string(), 174 base::File(), 175 net::BoundNetLog()); 176 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 177 duplicate_file.Initialize(temp_dir_.path())); 178 // Write something into it. 179 duplicate_file.AppendDataToFile(kTestData4, kTestDataLength4); 180 // Detach the file so it isn't deleted on destruction of |duplicate_file|. 181 duplicate_file.Detach(); 182 } 183 184 int64 CurrentSpeedAtTime(base::TimeTicks current_time) { 185 EXPECT_TRUE(base_file_.get()); 186 return base_file_->CurrentSpeedAtTime(current_time); 187 } 188 189 base::TimeTicks StartTick() { 190 EXPECT_TRUE(base_file_.get()); 191 return base_file_->start_tick_; 192 } 193 194 void set_expected_error(DownloadInterruptReason err) { 195 expected_error_ = err; 196 } 197 198 protected: 199 // BaseClass instance we are testing. 200 scoped_ptr<BaseFile> base_file_; 201 202 // Temporary directory for renamed downloads. 203 base::ScopedTempDir temp_dir_; 204 205 // Expect the file to survive deletion of the BaseFile instance. 206 bool expect_file_survives_; 207 208 // Expect the file to be in progress. 209 bool expect_in_progress_; 210 211 // Hash calculator. 212 scoped_ptr<crypto::SecureHash> secure_hash_; 213 214 unsigned char sha256_hash_[crypto::kSHA256Length]; 215 216 private: 217 // Keep track of what data should be saved to the disk file. 218 std::string expected_data_; 219 DownloadInterruptReason expected_error_; 220 221 // Mock file thread to satisfy debug checks in BaseFile. 222 base::MessageLoop message_loop_; 223 BrowserThreadImpl file_thread_; 224 }; 225 226 // This will initialize the entire array to zero. 227 const unsigned char BaseFileTest::kEmptySha256Hash[] = { 0 }; 228 229 // Test the most basic scenario: just create the object and do a sanity check 230 // on all its accessors. This is actually a case that rarely happens 231 // in production, where we would at least Initialize it. 232 TEST_F(BaseFileTest, CreateDestroy) { 233 EXPECT_EQ(base::FilePath().value(), base_file_->full_path().value()); 234 } 235 236 // Cancel the download explicitly. 237 TEST_F(BaseFileTest, Cancel) { 238 ASSERT_TRUE(InitializeFile()); 239 EXPECT_TRUE(base::PathExists(base_file_->full_path())); 240 base_file_->Cancel(); 241 EXPECT_FALSE(base::PathExists(base_file_->full_path())); 242 EXPECT_NE(base::FilePath().value(), base_file_->full_path().value()); 243 } 244 245 // Write data to the file and detach it, so it doesn't get deleted 246 // automatically when base_file_ is destructed. 247 TEST_F(BaseFileTest, WriteAndDetach) { 248 ASSERT_TRUE(InitializeFile()); 249 ASSERT_TRUE(AppendDataToFile(kTestData1)); 250 base_file_->Finish(); 251 base_file_->Detach(); 252 expect_file_survives_ = true; 253 } 254 255 // Write data to the file and detach it, and calculate its sha256 hash. 256 TEST_F(BaseFileTest, WriteWithHashAndDetach) { 257 // Calculate the final hash. 258 ResetHash(); 259 UpdateHash(kTestData1, kTestDataLength1); 260 std::string expected_hash = GetFinalHash(); 261 std::string expected_hash_hex = 262 base::HexEncode(expected_hash.data(), expected_hash.size()); 263 264 MakeFileWithHash(); 265 ASSERT_TRUE(InitializeFile()); 266 ASSERT_TRUE(AppendDataToFile(kTestData1)); 267 base_file_->Finish(); 268 269 std::string hash; 270 base_file_->GetHash(&hash); 271 EXPECT_EQ("0B2D3F3F7943AD64B860DF94D05CB56A8A97C6EC5768B5B70B930C5AA7FA9ADE", 272 expected_hash_hex); 273 EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size())); 274 275 base_file_->Detach(); 276 expect_file_survives_ = true; 277 } 278 279 // Rename the file after writing to it, then detach. 280 TEST_F(BaseFileTest, WriteThenRenameAndDetach) { 281 ASSERT_TRUE(InitializeFile()); 282 283 base::FilePath initial_path(base_file_->full_path()); 284 EXPECT_TRUE(base::PathExists(initial_path)); 285 base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile")); 286 EXPECT_FALSE(base::PathExists(new_path)); 287 288 ASSERT_TRUE(AppendDataToFile(kTestData1)); 289 290 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path)); 291 EXPECT_FALSE(base::PathExists(initial_path)); 292 EXPECT_TRUE(base::PathExists(new_path)); 293 294 base_file_->Finish(); 295 base_file_->Detach(); 296 expect_file_survives_ = true; 297 } 298 299 // Write data to the file once. 300 TEST_F(BaseFileTest, SingleWrite) { 301 ASSERT_TRUE(InitializeFile()); 302 ASSERT_TRUE(AppendDataToFile(kTestData1)); 303 base_file_->Finish(); 304 } 305 306 // Write data to the file multiple times. 307 TEST_F(BaseFileTest, MultipleWrites) { 308 ASSERT_TRUE(InitializeFile()); 309 ASSERT_TRUE(AppendDataToFile(kTestData1)); 310 ASSERT_TRUE(AppendDataToFile(kTestData2)); 311 ASSERT_TRUE(AppendDataToFile(kTestData3)); 312 std::string hash; 313 EXPECT_FALSE(base_file_->GetHash(&hash)); 314 base_file_->Finish(); 315 } 316 317 // Write data to the file once and calculate its sha256 hash. 318 TEST_F(BaseFileTest, SingleWriteWithHash) { 319 // Calculate the final hash. 320 ResetHash(); 321 UpdateHash(kTestData1, kTestDataLength1); 322 std::string expected_hash = GetFinalHash(); 323 std::string expected_hash_hex = 324 base::HexEncode(expected_hash.data(), expected_hash.size()); 325 326 MakeFileWithHash(); 327 ASSERT_TRUE(InitializeFile()); 328 // Can get partial hash states before Finish() is called. 329 EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str()); 330 ASSERT_TRUE(AppendDataToFile(kTestData1)); 331 EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str()); 332 base_file_->Finish(); 333 334 std::string hash; 335 base_file_->GetHash(&hash); 336 EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size())); 337 } 338 339 // Write data to the file multiple times and calculate its sha256 hash. 340 TEST_F(BaseFileTest, MultipleWritesWithHash) { 341 // Calculate the final hash. 342 ResetHash(); 343 UpdateHash(kTestData1, kTestDataLength1); 344 UpdateHash(kTestData2, kTestDataLength2); 345 UpdateHash(kTestData3, kTestDataLength3); 346 std::string expected_hash = GetFinalHash(); 347 std::string expected_hash_hex = 348 base::HexEncode(expected_hash.data(), expected_hash.size()); 349 350 std::string hash; 351 MakeFileWithHash(); 352 ASSERT_TRUE(InitializeFile()); 353 ASSERT_TRUE(AppendDataToFile(kTestData1)); 354 ASSERT_TRUE(AppendDataToFile(kTestData2)); 355 ASSERT_TRUE(AppendDataToFile(kTestData3)); 356 // No hash before Finish() is called. 357 EXPECT_FALSE(base_file_->GetHash(&hash)); 358 base_file_->Finish(); 359 360 EXPECT_TRUE(base_file_->GetHash(&hash)); 361 EXPECT_EQ("CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8", 362 expected_hash_hex); 363 EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size())); 364 } 365 366 // Write data to the file multiple times, interrupt it, and continue using 367 // another file. Calculate the resulting combined sha256 hash. 368 TEST_F(BaseFileTest, MultipleWritesInterruptedWithHash) { 369 // Calculate the final hash. 370 ResetHash(); 371 UpdateHash(kTestData1, kTestDataLength1); 372 UpdateHash(kTestData2, kTestDataLength2); 373 UpdateHash(kTestData3, kTestDataLength3); 374 std::string expected_hash = GetFinalHash(); 375 std::string expected_hash_hex = 376 base::HexEncode(expected_hash.data(), expected_hash.size()); 377 378 MakeFileWithHash(); 379 ASSERT_TRUE(InitializeFile()); 380 // Write some data 381 ASSERT_TRUE(AppendDataToFile(kTestData1)); 382 ASSERT_TRUE(AppendDataToFile(kTestData2)); 383 // Get the hash state and file name. 384 std::string hash_state; 385 hash_state = base_file_->GetHashState(); 386 // Finish the file. 387 base_file_->Finish(); 388 389 base::FilePath new_file_path(temp_dir_.path().Append( 390 base::FilePath(FILE_PATH_LITERAL("second_file")))); 391 392 ASSERT_TRUE(base::CopyFile(base_file_->full_path(), new_file_path)); 393 394 // Create another file 395 BaseFile second_file(new_file_path, 396 GURL(), 397 GURL(), 398 base_file_->bytes_so_far(), 399 true, 400 hash_state, 401 base::File(), 402 net::BoundNetLog()); 403 ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 404 second_file.Initialize(base::FilePath())); 405 std::string data(kTestData3); 406 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 407 second_file.AppendDataToFile(data.data(), data.size())); 408 second_file.Finish(); 409 410 std::string hash; 411 EXPECT_TRUE(second_file.GetHash(&hash)); 412 // This will fail until getting the hash state is supported in SecureHash. 413 EXPECT_STREQ(expected_hash_hex.c_str(), 414 base::HexEncode(hash.data(), hash.size()).c_str()); 415 } 416 417 // Rename the file after all writes to it. 418 TEST_F(BaseFileTest, WriteThenRename) { 419 ASSERT_TRUE(InitializeFile()); 420 421 base::FilePath initial_path(base_file_->full_path()); 422 EXPECT_TRUE(base::PathExists(initial_path)); 423 base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile")); 424 EXPECT_FALSE(base::PathExists(new_path)); 425 426 ASSERT_TRUE(AppendDataToFile(kTestData1)); 427 428 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, 429 base_file_->Rename(new_path)); 430 EXPECT_FALSE(base::PathExists(initial_path)); 431 EXPECT_TRUE(base::PathExists(new_path)); 432 433 base_file_->Finish(); 434 } 435 436 // Rename the file while the download is still in progress. 437 TEST_F(BaseFileTest, RenameWhileInProgress) { 438 ASSERT_TRUE(InitializeFile()); 439 440 base::FilePath initial_path(base_file_->full_path()); 441 EXPECT_TRUE(base::PathExists(initial_path)); 442 base::FilePath new_path(temp_dir_.path().AppendASCII("NewFile")); 443 EXPECT_FALSE(base::PathExists(new_path)); 444 445 ASSERT_TRUE(AppendDataToFile(kTestData1)); 446 447 EXPECT_TRUE(base_file_->in_progress()); 448 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path)); 449 EXPECT_FALSE(base::PathExists(initial_path)); 450 EXPECT_TRUE(base::PathExists(new_path)); 451 452 ASSERT_TRUE(AppendDataToFile(kTestData2)); 453 454 base_file_->Finish(); 455 } 456 457 // Test that a failed rename reports the correct error. 458 TEST_F(BaseFileTest, RenameWithError) { 459 ASSERT_TRUE(InitializeFile()); 460 461 // TestDir is a subdirectory in |temp_dir_| that we will make read-only so 462 // that the rename will fail. 463 base::FilePath test_dir(temp_dir_.path().AppendASCII("TestDir")); 464 ASSERT_TRUE(base::CreateDirectory(test_dir)); 465 466 base::FilePath new_path(test_dir.AppendASCII("TestFile")); 467 EXPECT_FALSE(base::PathExists(new_path)); 468 469 { 470 file_util::PermissionRestorer restore_permissions_for(test_dir); 471 ASSERT_TRUE(file_util::MakeFileUnwritable(test_dir)); 472 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED, 473 base_file_->Rename(new_path)); 474 } 475 476 base_file_->Finish(); 477 } 478 479 // Test that a failed write reports an error. 480 TEST_F(BaseFileTest, WriteWithError) { 481 base::FilePath path; 482 ASSERT_TRUE(base::CreateTemporaryFile(&path)); 483 484 // Pass a file handle which was opened without the WRITE flag. 485 // This should result in an error when writing. 486 base::File file(path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ); 487 base_file_.reset(new BaseFile(path, 488 GURL(), 489 GURL(), 490 0, 491 false, 492 std::string(), 493 file.Pass(), 494 net::BoundNetLog())); 495 ASSERT_TRUE(InitializeFile()); 496 #if defined(OS_WIN) 497 set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED); 498 #elif defined (OS_POSIX) 499 set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); 500 #endif 501 ASSERT_FALSE(AppendDataToFile(kTestData1)); 502 base_file_->Finish(); 503 } 504 505 // Try to write to uninitialized file. 506 TEST_F(BaseFileTest, UninitializedFile) { 507 expect_in_progress_ = false; 508 set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); 509 EXPECT_FALSE(AppendDataToFile(kTestData1)); 510 } 511 512 // Create two |BaseFile|s with the same file, and attempt to write to both. 513 // Overwrite base_file_ with another file with the same name and 514 // non-zero contents, and make sure the last file to close 'wins'. 515 TEST_F(BaseFileTest, DuplicateBaseFile) { 516 ASSERT_TRUE(InitializeFile()); 517 518 // Create another |BaseFile| referring to the file that |base_file_| owns. 519 CreateFileWithName(base_file_->full_path()); 520 521 ASSERT_TRUE(AppendDataToFile(kTestData1)); 522 base_file_->Finish(); 523 } 524 525 // Create a file and append to it. 526 TEST_F(BaseFileTest, AppendToBaseFile) { 527 // Create a new file. 528 base::FilePath existing_file_name = CreateTestFile(); 529 530 set_expected_data(kTestData4); 531 532 // Use the file we've just created. 533 base_file_.reset(new BaseFile(existing_file_name, 534 GURL(), 535 GURL(), 536 kTestDataLength4, 537 false, 538 std::string(), 539 base::File(), 540 net::BoundNetLog())); 541 542 ASSERT_TRUE(InitializeFile()); 543 544 const base::FilePath file_name = base_file_->full_path(); 545 EXPECT_NE(base::FilePath::StringType(), file_name.value()); 546 547 // Write into the file. 548 EXPECT_TRUE(AppendDataToFile(kTestData1)); 549 550 base_file_->Finish(); 551 base_file_->Detach(); 552 expect_file_survives_ = true; 553 } 554 555 // Create a read-only file and attempt to write to it. 556 TEST_F(BaseFileTest, ReadonlyBaseFile) { 557 // Create a new file. 558 base::FilePath readonly_file_name = CreateTestFile(); 559 560 // Restore permissions to the file when we are done with this test. 561 file_util::PermissionRestorer restore_permissions(readonly_file_name); 562 563 // Make it read-only. 564 EXPECT_TRUE(file_util::MakeFileUnwritable(readonly_file_name)); 565 566 // Try to overwrite it. 567 base_file_.reset(new BaseFile(readonly_file_name, 568 GURL(), 569 GURL(), 570 0, 571 false, 572 std::string(), 573 base::File(), 574 net::BoundNetLog())); 575 576 expect_in_progress_ = false; 577 set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED); 578 EXPECT_FALSE(InitializeFile()); 579 580 const base::FilePath file_name = base_file_->full_path(); 581 EXPECT_NE(base::FilePath::StringType(), file_name.value()); 582 583 // Write into the file. 584 set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); 585 EXPECT_FALSE(AppendDataToFile(kTestData1)); 586 587 base_file_->Finish(); 588 base_file_->Detach(); 589 expect_file_survives_ = true; 590 } 591 592 TEST_F(BaseFileTest, IsEmptyHash) { 593 std::string empty(crypto::kSHA256Length, '\x00'); 594 EXPECT_TRUE(BaseFile::IsEmptyHash(empty)); 595 std::string not_empty(crypto::kSHA256Length, '\x01'); 596 EXPECT_FALSE(BaseFile::IsEmptyHash(not_empty)); 597 EXPECT_FALSE(BaseFile::IsEmptyHash(std::string())); 598 599 std::string also_not_empty = empty; 600 also_not_empty[crypto::kSHA256Length - 1] = '\x01'; 601 EXPECT_FALSE(BaseFile::IsEmptyHash(also_not_empty)); 602 } 603 604 // Test that a temporary file is created in the default download directory. 605 TEST_F(BaseFileTest, CreatedInDefaultDirectory) { 606 ASSERT_TRUE(base_file_->full_path().empty()); 607 ASSERT_TRUE(InitializeFile()); 608 EXPECT_FALSE(base_file_->full_path().empty()); 609 610 // On Windows, CreateTemporaryFileInDir() will cause a path with short names 611 // to be expanded into a path with long names. Thus temp_dir.path() might not 612 // be a string-wise match to base_file_->full_path().DirName() even though 613 // they are in the same directory. 614 base::FilePath temp_file; 615 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &temp_file)); 616 ASSERT_FALSE(temp_file.empty()); 617 EXPECT_STREQ(temp_file.DirName().value().c_str(), 618 base_file_->full_path().DirName().value().c_str()); 619 base_file_->Finish(); 620 } 621 622 TEST_F(BaseFileTest, NoDoubleDeleteAfterCancel) { 623 ASSERT_TRUE(InitializeFile()); 624 base::FilePath full_path = base_file_->full_path(); 625 ASSERT_FALSE(full_path.empty()); 626 ASSERT_TRUE(base::PathExists(full_path)); 627 628 base_file_->Cancel(); 629 ASSERT_FALSE(base::PathExists(full_path)); 630 631 const char kData[] = "hello"; 632 const int kDataLength = static_cast<int>(arraysize(kData) - 1); 633 ASSERT_EQ(kDataLength, base::WriteFile(full_path, kData, kDataLength)); 634 // The file that we created here should stick around when the BaseFile is 635 // destroyed during TearDown. 636 expect_file_survives_ = true; 637 } 638 639 } // namespace content 640