| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/download/base_file.h" | 5 #include "content/browser/download/base_file.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/scoped_temp_dir.h" | 10 #include "base/scoped_temp_dir.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 | 50 |
| 51 virtual void SetUp() { | 51 virtual void SetUp() { |
| 52 ResetHash(); | 52 ResetHash(); |
| 53 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 53 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 54 base_file_.reset(new BaseFile(FilePath(), | 54 base_file_.reset(new BaseFile(FilePath(), |
| 55 GURL(), | 55 GURL(), |
| 56 GURL(), | 56 GURL(), |
| 57 0, | 57 0, |
| 58 false, | 58 false, |
| 59 "", | 59 "", |
| 60 file_stream_, | 60 scoped_ptr<net::FileStream>().Pass(), |
| 61 net::BoundNetLog())); | 61 net::BoundNetLog())); |
| 62 } | 62 } |
| 63 | 63 |
| 64 virtual void TearDown() { | 64 virtual void TearDown() { |
| 65 EXPECT_FALSE(base_file_->in_progress()); | 65 EXPECT_FALSE(base_file_->in_progress()); |
| 66 if (!expected_error_) { | 66 if (!expected_error_) { |
| 67 EXPECT_EQ(static_cast<int64>(expected_data_.size()), | 67 EXPECT_EQ(static_cast<int64>(expected_data_.size()), |
| 68 base_file_->bytes_so_far()); | 68 base_file_->bytes_so_far()); |
| 69 } | 69 } |
| 70 | 70 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 101 return hash; | 101 return hash; |
| 102 } | 102 } |
| 103 | 103 |
| 104 void MakeFileWithHash() { | 104 void MakeFileWithHash() { |
| 105 base_file_.reset(new BaseFile(FilePath(), | 105 base_file_.reset(new BaseFile(FilePath(), |
| 106 GURL(), | 106 GURL(), |
| 107 GURL(), | 107 GURL(), |
| 108 0, | 108 0, |
| 109 true, | 109 true, |
| 110 "", | 110 "", |
| 111 file_stream_, | 111 scoped_ptr<net::FileStream>().Pass(), |
| 112 net::BoundNetLog())); | 112 net::BoundNetLog())); |
| 113 } | 113 } |
| 114 | 114 |
| 115 bool OpenMockFileStream() { | |
| 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 117 | |
| 118 FilePath path; | |
| 119 if (!file_util::CreateTemporaryFile(&path)) | |
| 120 return false; | |
| 121 | |
| 122 // Create a new file stream. | |
| 123 mock_file_stream_.reset(new net::testing::MockFileStream(NULL)); | |
| 124 if (mock_file_stream_->OpenSync( | |
| 125 path, | |
| 126 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE) != 0) { | |
| 127 mock_file_stream_.reset(); | |
| 128 return false; | |
| 129 } | |
| 130 | |
| 131 return true; | |
| 132 } | |
| 133 | |
| 134 void ForceError(net::Error error) { | |
| 135 mock_file_stream_->set_forced_error(error); | |
| 136 } | |
| 137 | |
| 138 int AppendDataToFile(const std::string& data) { | 115 int AppendDataToFile(const std::string& data) { |
| 139 EXPECT_EQ(expect_in_progress_, base_file_->in_progress()); | 116 EXPECT_EQ(expect_in_progress_, base_file_->in_progress()); |
| 140 expected_error_ = mock_file_stream_.get() && | |
| 141 (mock_file_stream_->forced_error() != net::OK); | |
| 142 int appended = base_file_->AppendDataToFile(data.data(), data.size()); | 117 int appended = base_file_->AppendDataToFile(data.data(), data.size()); |
| 143 if (appended == net::OK) | 118 if (appended == net::OK) |
| 144 EXPECT_TRUE(expect_in_progress_) | 119 EXPECT_TRUE(expect_in_progress_) |
| 145 << " appended = " << appended; | 120 << " appended = " << appended; |
| 146 if (base_file_->in_progress()) { | 121 if (base_file_->in_progress()) { |
| 147 expected_data_ += data; | 122 expected_data_ += data; |
| 148 if (!expected_error_) { | 123 if (!expected_error_) { |
| 149 EXPECT_EQ(static_cast<int64>(expected_data_.size()), | 124 EXPECT_EQ(static_cast<int64>(expected_data_.size()), |
| 150 base_file_->bytes_so_far()); | 125 base_file_->bytes_so_far()); |
| 151 } | 126 } |
| 152 } | 127 } |
| 153 return appended; | 128 return appended; |
| 154 } | 129 } |
| 155 | 130 |
| 156 void set_expected_data(const std::string& data) { expected_data_ = data; } | 131 void set_expected_data(const std::string& data) { expected_data_ = data; } |
| 157 | 132 |
| 158 // Helper functions. | 133 // Helper functions. |
| 159 // Create a file. Returns the complete file path. | 134 // Create a file. Returns the complete file path. |
| 160 FilePath CreateTestFile() { | 135 FilePath CreateTestFile() { |
| 161 FilePath file_name; | 136 FilePath file_name; |
| 162 linked_ptr<net::FileStream> dummy_file_stream; | |
| 163 BaseFile file(FilePath(), | 137 BaseFile file(FilePath(), |
| 164 GURL(), | 138 GURL(), |
| 165 GURL(), | 139 GURL(), |
| 166 0, | 140 0, |
| 167 false, | 141 false, |
| 168 "", | 142 "", |
| 169 dummy_file_stream, | 143 scoped_ptr<net::FileStream>(), |
| 170 net::BoundNetLog()); | 144 net::BoundNetLog()); |
| 171 | 145 |
| 172 EXPECT_EQ(net::OK, file.Initialize(temp_dir_.path())); | 146 EXPECT_EQ(net::OK, file.Initialize(temp_dir_.path())); |
| 173 file_name = file.full_path(); | 147 file_name = file.full_path(); |
| 174 EXPECT_NE(FilePath::StringType(), file_name.value()); | 148 EXPECT_NE(FilePath::StringType(), file_name.value()); |
| 175 | 149 |
| 176 EXPECT_EQ(net::OK, file.AppendDataToFile(kTestData4, kTestDataLength4)); | 150 EXPECT_EQ(net::OK, file.AppendDataToFile(kTestData4, kTestDataLength4)); |
| 177 | 151 |
| 178 // Keep the file from getting deleted when existing_file_name is deleted. | 152 // Keep the file from getting deleted when existing_file_name is deleted. |
| 179 file.Detach(); | 153 file.Detach(); |
| 180 | 154 |
| 181 return file_name; | 155 return file_name; |
| 182 } | 156 } |
| 183 | 157 |
| 184 // Create a file with the specified file name. | 158 // Create a file with the specified file name. |
| 185 void CreateFileWithName(const FilePath& file_name) { | 159 void CreateFileWithName(const FilePath& file_name) { |
| 186 EXPECT_NE(FilePath::StringType(), file_name.value()); | 160 EXPECT_NE(FilePath::StringType(), file_name.value()); |
| 187 linked_ptr<net::FileStream> dummy_file_stream; | |
| 188 BaseFile duplicate_file(file_name, | 161 BaseFile duplicate_file(file_name, |
| 189 GURL(), | 162 GURL(), |
| 190 GURL(), | 163 GURL(), |
| 191 0, | 164 0, |
| 192 false, | 165 false, |
| 193 "", | 166 "", |
| 194 dummy_file_stream, | 167 scoped_ptr<net::FileStream>(), |
| 195 net::BoundNetLog()); | 168 net::BoundNetLog()); |
| 196 EXPECT_EQ(net::OK, duplicate_file.Initialize(temp_dir_.path())); | 169 EXPECT_EQ(net::OK, duplicate_file.Initialize(temp_dir_.path())); |
| 197 // Write something into it. | 170 // Write something into it. |
| 198 duplicate_file.AppendDataToFile(kTestData4, kTestDataLength4); | 171 duplicate_file.AppendDataToFile(kTestData4, kTestDataLength4); |
| 199 // Detach the file so it isn't deleted on destruction of |duplicate_file|. | 172 // Detach the file so it isn't deleted on destruction of |duplicate_file|. |
| 200 duplicate_file.Detach(); | 173 duplicate_file.Detach(); |
| 201 } | 174 } |
| 202 | 175 |
| 203 int64 CurrentSpeedAtTime(base::TimeTicks current_time) { | 176 int64 CurrentSpeedAtTime(base::TimeTicks current_time) { |
| 204 EXPECT_TRUE(base_file_.get()); | 177 EXPECT_TRUE(base_file_.get()); |
| 205 return base_file_->CurrentSpeedAtTime(current_time); | 178 return base_file_->CurrentSpeedAtTime(current_time); |
| 206 } | 179 } |
| 207 | 180 |
| 208 base::TimeTicks StartTick() { | 181 base::TimeTicks StartTick() { |
| 209 EXPECT_TRUE(base_file_.get()); | 182 EXPECT_TRUE(base_file_.get()); |
| 210 return base_file_->start_tick_; | 183 return base_file_->start_tick_; |
| 211 } | 184 } |
| 212 | 185 |
| 186 void set_expected_error(net::Error err) { |
| 187 expected_error_ = err; |
| 188 } |
| 189 |
| 213 protected: | 190 protected: |
| 214 linked_ptr<net::FileStream> file_stream_; | |
| 215 linked_ptr<net::testing::MockFileStream> mock_file_stream_; | 191 linked_ptr<net::testing::MockFileStream> mock_file_stream_; |
| 216 | 192 |
| 217 // BaseClass instance we are testing. | 193 // BaseClass instance we are testing. |
| 218 scoped_ptr<BaseFile> base_file_; | 194 scoped_ptr<BaseFile> base_file_; |
| 219 | 195 |
| 220 // Temporary directory for renamed downloads. | 196 // Temporary directory for renamed downloads. |
| 221 ScopedTempDir temp_dir_; | 197 ScopedTempDir temp_dir_; |
| 222 | 198 |
| 223 // Expect the file to survive deletion of the BaseFile instance. | 199 // Expect the file to survive deletion of the BaseFile instance. |
| 224 bool expect_file_survives_; | 200 bool expect_file_survives_; |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 // Write some data | 374 // Write some data |
| 399 ASSERT_EQ(net::OK, AppendDataToFile(kTestData1)); | 375 ASSERT_EQ(net::OK, AppendDataToFile(kTestData1)); |
| 400 ASSERT_EQ(net::OK, AppendDataToFile(kTestData2)); | 376 ASSERT_EQ(net::OK, AppendDataToFile(kTestData2)); |
| 401 // Get the hash state and file name. | 377 // Get the hash state and file name. |
| 402 std::string hash_state; | 378 std::string hash_state; |
| 403 hash_state = base_file_->GetHashState(); | 379 hash_state = base_file_->GetHashState(); |
| 404 // Finish the file. | 380 // Finish the file. |
| 405 base_file_->Finish(); | 381 base_file_->Finish(); |
| 406 | 382 |
| 407 // Create another file | 383 // Create another file |
| 408 linked_ptr<net::FileStream> second_stream; | |
| 409 BaseFile second_file(FilePath(), | 384 BaseFile second_file(FilePath(), |
| 410 GURL(), | 385 GURL(), |
| 411 GURL(), | 386 GURL(), |
| 412 base_file_->bytes_so_far(), | 387 base_file_->bytes_so_far(), |
| 413 true, | 388 true, |
| 414 hash_state, | 389 hash_state, |
| 415 second_stream, | 390 scoped_ptr<net::FileStream>(), |
| 416 net::BoundNetLog()); | 391 net::BoundNetLog()); |
| 417 ASSERT_EQ(net::OK, second_file.Initialize(temp_dir_.path())); | 392 ASSERT_EQ(net::OK, second_file.Initialize(temp_dir_.path())); |
| 418 std::string data(kTestData3); | 393 std::string data(kTestData3); |
| 419 EXPECT_EQ(net::OK, second_file.AppendDataToFile(data.data(), data.size())); | 394 EXPECT_EQ(net::OK, second_file.AppendDataToFile(data.data(), data.size())); |
| 420 second_file.Finish(); | 395 second_file.Finish(); |
| 421 | 396 |
| 422 std::string hash; | 397 std::string hash; |
| 423 EXPECT_TRUE(second_file.GetHash(&hash)); | 398 EXPECT_TRUE(second_file.GetHash(&hash)); |
| 424 // This will fail until getting the hash state is supported in SecureHash. | 399 // This will fail until getting the hash state is supported in SecureHash. |
| 425 EXPECT_STREQ(expected_hash_hex.c_str(), | 400 EXPECT_STREQ(expected_hash_hex.c_str(), |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 file_util::PermissionRestorer restore_permissions_for(test_dir); | 456 file_util::PermissionRestorer restore_permissions_for(test_dir); |
| 482 ASSERT_TRUE(file_util::MakeFileUnwritable(test_dir)); | 457 ASSERT_TRUE(file_util::MakeFileUnwritable(test_dir)); |
| 483 EXPECT_EQ(net::ERR_ACCESS_DENIED, base_file_->Rename(new_path)); | 458 EXPECT_EQ(net::ERR_ACCESS_DENIED, base_file_->Rename(new_path)); |
| 484 } | 459 } |
| 485 | 460 |
| 486 base_file_->Finish(); | 461 base_file_->Finish(); |
| 487 } | 462 } |
| 488 | 463 |
| 489 // Write data to the file multiple times. | 464 // Write data to the file multiple times. |
| 490 TEST_F(BaseFileTest, MultipleWritesWithError) { | 465 TEST_F(BaseFileTest, MultipleWritesWithError) { |
| 491 ASSERT_TRUE(OpenMockFileStream()); | 466 FilePath path; |
| 492 base_file_.reset(new BaseFile(mock_file_stream_->get_path(), | 467 ASSERT_TRUE(file_util::CreateTemporaryFile(&path)); |
| 468 // Create a new file stream. scoped_ptr takes ownership and passes it to |
| 469 // BaseFile; we use the pointer anyway and rely on the BaseFile not |
| 470 // deleting the MockFileStream until the BaseFile is reset. |
| 471 net::testing::MockFileStream* mock_file_stream_p( |
| 472 new net::testing::MockFileStream(NULL)); |
| 473 scoped_ptr<net::FileStream> mock_file_stream(mock_file_stream_p); |
| 474 |
| 475 ASSERT_EQ(0, |
| 476 mock_file_stream_p->OpenSync( |
| 477 path, |
| 478 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE)); |
| 479 |
| 480 // Copy of mock_file_stream; we pass ownership and rely on the BaseFile |
| 481 // not deleting it until it is reset. |
| 482 |
| 483 base_file_.reset(new BaseFile(mock_file_stream_p->get_path(), |
| 493 GURL(), | 484 GURL(), |
| 494 GURL(), | 485 GURL(), |
| 495 0, | 486 0, |
| 496 false, | 487 false, |
| 497 "", | 488 "", |
| 498 mock_file_stream_, | 489 mock_file_stream.Pass(), |
| 499 net::BoundNetLog())); | 490 net::BoundNetLog())); |
| 500 EXPECT_EQ(net::OK, base_file_->Initialize(temp_dir_.path())); | 491 EXPECT_EQ(net::OK, base_file_->Initialize(temp_dir_.path())); |
| 501 ASSERT_EQ(net::OK, AppendDataToFile(kTestData1)); | 492 ASSERT_EQ(net::OK, AppendDataToFile(kTestData1)); |
| 502 ASSERT_EQ(net::OK, AppendDataToFile(kTestData2)); | 493 ASSERT_EQ(net::OK, AppendDataToFile(kTestData2)); |
| 503 ForceError(net::ERR_ACCESS_DENIED); | 494 mock_file_stream_p->set_forced_error(net::ERR_ACCESS_DENIED); |
| 495 set_expected_error(net::ERR_ACCESS_DENIED); |
| 504 ASSERT_NE(net::OK, AppendDataToFile(kTestData3)); | 496 ASSERT_NE(net::OK, AppendDataToFile(kTestData3)); |
| 505 std::string hash; | 497 std::string hash; |
| 506 EXPECT_FALSE(base_file_->GetHash(&hash)); | 498 EXPECT_FALSE(base_file_->GetHash(&hash)); |
| 507 base_file_->Finish(); | 499 base_file_->Finish(); |
| 508 } | 500 } |
| 509 | 501 |
| 510 // Try to write to uninitialized file. | 502 // Try to write to uninitialized file. |
| 511 TEST_F(BaseFileTest, UninitializedFile) { | 503 TEST_F(BaseFileTest, UninitializedFile) { |
| 512 expect_in_progress_ = false; | 504 expect_in_progress_ = false; |
| 513 EXPECT_EQ(net::ERR_INVALID_HANDLE, AppendDataToFile(kTestData1)); | 505 EXPECT_EQ(net::ERR_INVALID_HANDLE, AppendDataToFile(kTestData1)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 533 | 525 |
| 534 set_expected_data(kTestData4); | 526 set_expected_data(kTestData4); |
| 535 | 527 |
| 536 // Use the file we've just created. | 528 // Use the file we've just created. |
| 537 base_file_.reset(new BaseFile(existing_file_name, | 529 base_file_.reset(new BaseFile(existing_file_name, |
| 538 GURL(), | 530 GURL(), |
| 539 GURL(), | 531 GURL(), |
| 540 kTestDataLength4, | 532 kTestDataLength4, |
| 541 false, | 533 false, |
| 542 "", | 534 "", |
| 543 file_stream_, | 535 scoped_ptr<net::FileStream>().Pass(), |
| 544 net::BoundNetLog())); | 536 net::BoundNetLog())); |
| 545 | 537 |
| 546 EXPECT_EQ(net::OK, base_file_->Initialize(temp_dir_.path())); | 538 EXPECT_EQ(net::OK, base_file_->Initialize(temp_dir_.path())); |
| 547 | 539 |
| 548 const FilePath file_name = base_file_->full_path(); | 540 const FilePath file_name = base_file_->full_path(); |
| 549 EXPECT_NE(FilePath::StringType(), file_name.value()); | 541 EXPECT_NE(FilePath::StringType(), file_name.value()); |
| 550 | 542 |
| 551 // Write into the file. | 543 // Write into the file. |
| 552 EXPECT_EQ(net::OK, AppendDataToFile(kTestData1)); | 544 EXPECT_EQ(net::OK, AppendDataToFile(kTestData1)); |
| 553 | 545 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 567 // Make it read-only. | 559 // Make it read-only. |
| 568 EXPECT_TRUE(file_util::MakeFileUnwritable(readonly_file_name)); | 560 EXPECT_TRUE(file_util::MakeFileUnwritable(readonly_file_name)); |
| 569 | 561 |
| 570 // Try to overwrite it. | 562 // Try to overwrite it. |
| 571 base_file_.reset(new BaseFile(readonly_file_name, | 563 base_file_.reset(new BaseFile(readonly_file_name, |
| 572 GURL(), | 564 GURL(), |
| 573 GURL(), | 565 GURL(), |
| 574 0, | 566 0, |
| 575 false, | 567 false, |
| 576 "", | 568 "", |
| 577 file_stream_, | 569 scoped_ptr<net::FileStream>().Pass(), |
| 578 net::BoundNetLog())); | 570 net::BoundNetLog())); |
| 579 | 571 |
| 580 expect_in_progress_ = false; | 572 expect_in_progress_ = false; |
| 581 | 573 |
| 582 int init_error = base_file_->Initialize(temp_dir_.path()); | 574 int init_error = base_file_->Initialize(temp_dir_.path()); |
| 583 DVLOG(1) << " init_error = " << init_error; | 575 DVLOG(1) << " init_error = " << init_error; |
| 584 EXPECT_NE(net::OK, init_error); | 576 EXPECT_NE(net::OK, init_error); |
| 585 | 577 |
| 586 const FilePath file_name = base_file_->full_path(); | 578 const FilePath file_name = base_file_->full_path(); |
| 587 EXPECT_NE(FilePath::StringType(), file_name.value()); | 579 EXPECT_NE(FilePath::StringType(), file_name.value()); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 // be a string-wise match to base_file_->full_path().DirName() even though | 645 // be a string-wise match to base_file_->full_path().DirName() even though |
| 654 // they are in the same directory. | 646 // they are in the same directory. |
| 655 FilePath temp_file; | 647 FilePath temp_file; |
| 656 ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), | 648 ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(), |
| 657 &temp_file)); | 649 &temp_file)); |
| 658 ASSERT_FALSE(temp_file.empty()); | 650 ASSERT_FALSE(temp_file.empty()); |
| 659 EXPECT_STREQ(temp_file.DirName().value().c_str(), | 651 EXPECT_STREQ(temp_file.DirName().value().c_str(), |
| 660 base_file_->full_path().DirName().value().c_str()); | 652 base_file_->full_path().DirName().value().c_str()); |
| 661 base_file_->Finish(); | 653 base_file_->Finish(); |
| 662 } | 654 } |
| OLD | NEW |