| Index: content/browser/download/download_file_unittest.cc
|
| diff --git a/content/browser/download/download_file_unittest.cc b/content/browser/download/download_file_unittest.cc
|
| index 245fdcd078312e9f26fbd6356760999eef5d75da..d24eeb81392016f001ecf5499debde63a09f43d7 100644
|
| --- a/content/browser/download/download_file_unittest.cc
|
| +++ b/content/browser/download/download_file_unittest.cc
|
| @@ -4,7 +4,9 @@
|
|
|
| #include <stddef.h>
|
| #include <stdint.h>
|
| +
|
| #include <utility>
|
| +#include <vector>
|
|
|
| #include "base/files/file.h"
|
| #include "base/files/file_util.h"
|
| @@ -18,9 +20,9 @@
|
| #include "content/browser/browser_thread_impl.h"
|
| #include "content/browser/byte_stream.h"
|
| #include "content/browser/download/download_create_info.h"
|
| +#include "content/browser/download/download_destination_observer.h"
|
| #include "content/browser/download/download_file_impl.h"
|
| #include "content/browser/download/download_request_handle.h"
|
| -#include "content/public/browser/download_destination_observer.h"
|
| #include "content/public/browser/download_interrupt_reasons.h"
|
| #include "content/public/browser/download_manager.h"
|
| #include "content/public/test/mock_download_manager.h"
|
| @@ -41,6 +43,14 @@ using ::testing::StrictMock;
|
| namespace content {
|
| namespace {
|
|
|
| +std::string GetHexEncodedHashValue(crypto::SecureHash* hash_state) {
|
| + if (!hash_state)
|
| + return std::string();
|
| + std::vector<char> hash_value(hash_state->GetHashLength());
|
| + hash_state->Finish(&hash_value.front(), hash_value.size());
|
| + return base::HexEncode(&hash_value.front(), hash_value.size());
|
| +}
|
| +
|
| class MockByteStreamReader : public ByteStreamReader {
|
| public:
|
| MockByteStreamReader() {}
|
| @@ -55,41 +65,45 @@ class MockByteStreamReader : public ByteStreamReader {
|
|
|
| class MockDownloadDestinationObserver : public DownloadDestinationObserver {
|
| public:
|
| - MOCK_METHOD3(DestinationUpdate, void(int64_t, int64_t, const std::string&));
|
| - MOCK_METHOD1(DestinationError, void(DownloadInterruptReason));
|
| - MOCK_METHOD1(DestinationCompleted, void(const std::string&));
|
| + MOCK_METHOD2(DestinationUpdate, void(int64_t, int64_t));
|
| + void DestinationError(DownloadInterruptReason reason,
|
| + int64_t bytes_so_far,
|
| + scoped_ptr<crypto::SecureHash> hash_state) override {
|
| + MockDestinationError(
|
| + reason, bytes_so_far, GetHexEncodedHashValue(hash_state.get()));
|
| + }
|
| + void DestinationCompleted(
|
| + int64_t total_bytes,
|
| + scoped_ptr<crypto::SecureHash> hash_state) override {
|
| + MockDestinationCompleted(total_bytes,
|
| + GetHexEncodedHashValue(hash_state.get()));
|
| + }
|
| +
|
| + MOCK_METHOD3(MockDestinationError,
|
| + void(DownloadInterruptReason, int64_t, const std::string&));
|
| + MOCK_METHOD2(MockDestinationCompleted, void(int64_t, const std::string&));
|
|
|
| // Doesn't override any methods in the base class. Used to make sure
|
| // that the last DestinationUpdate before a Destination{Completed,Error}
|
| // had the right values.
|
| - MOCK_METHOD3(CurrentUpdateStatus, void(int64_t, int64_t, const std::string&));
|
| + MOCK_METHOD2(CurrentUpdateStatus, void(int64_t, int64_t));
|
| };
|
|
|
| MATCHER(IsNullCallback, "") { return (arg.is_null()); }
|
|
|
| -typedef void (DownloadFile::*DownloadFileRenameMethodType)(
|
| - const base::FilePath&,
|
| - const DownloadFile::RenameCompletionCallback&);
|
| +enum DownloadFileRenameMethodType { RENAME_AND_UNIQUIFY, RENAME_AND_ANNOTATE };
|
|
|
| // This is a test DownloadFileImpl that has no retry delay and, on Posix,
|
| // retries renames failed due to ACCESS_DENIED.
|
| class TestDownloadFileImpl : public DownloadFileImpl {
|
| public:
|
| - TestDownloadFileImpl(const DownloadSaveInfo& save_info,
|
| + TestDownloadFileImpl(scoped_ptr<DownloadSaveInfo> save_info,
|
| const base::FilePath& default_downloads_directory,
|
| - const GURL& url,
|
| - const GURL& referrer_url,
|
| - bool calculate_hash,
|
| - base::File file,
|
| scoped_ptr<ByteStreamReader> stream,
|
| const net::BoundNetLog& bound_net_log,
|
| base::WeakPtr<DownloadDestinationObserver> observer)
|
| - : DownloadFileImpl(save_info,
|
| + : DownloadFileImpl(std::move(save_info),
|
| default_downloads_directory,
|
| - url,
|
| - referrer_url,
|
| - calculate_hash,
|
| - std::move(file),
|
| std::move(stream),
|
| bound_net_log,
|
| observer) {}
|
| @@ -113,11 +127,11 @@ class TestDownloadFileImpl : public DownloadFileImpl {
|
|
|
| class DownloadFileTest : public testing::Test {
|
| public:
|
| -
|
| - static const char* kTestData1;
|
| - static const char* kTestData2;
|
| - static const char* kTestData3;
|
| - static const char* kDataHash;
|
| + static const char kTestData1[];
|
| + static const char kTestData2[];
|
| + static const char kTestData3[];
|
| + static const char kDataHash[];
|
| + static const char kEmptyHash[];
|
| static const uint32_t kDummyDownloadId;
|
| static const int kDummyChildId;
|
| static const int kDummyRequestId;
|
| @@ -128,27 +142,23 @@ class DownloadFileTest : public testing::Test {
|
| input_stream_(NULL),
|
| bytes_(-1),
|
| bytes_per_sec_(-1),
|
| - hash_state_("xyzzy"),
|
| ui_thread_(BrowserThread::UI, &loop_),
|
| file_thread_(BrowserThread::FILE, &loop_) {
|
| }
|
|
|
| ~DownloadFileTest() override {}
|
|
|
| - void SetUpdateDownloadInfo(int64_t bytes,
|
| - int64_t bytes_per_sec,
|
| - const std::string& hash_state) {
|
| + void SetUpdateDownloadInfo(int64_t bytes, int64_t bytes_per_sec) {
|
| bytes_ = bytes;
|
| bytes_per_sec_ = bytes_per_sec;
|
| - hash_state_ = hash_state;
|
| }
|
|
|
| void ConfirmUpdateDownloadInfo() {
|
| - observer_->CurrentUpdateStatus(bytes_, bytes_per_sec_, hash_state_);
|
| + observer_->CurrentUpdateStatus(bytes_, bytes_per_sec_);
|
| }
|
|
|
| void SetUp() override {
|
| - EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _))
|
| + EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _))
|
| .Times(AnyNumber())
|
| .WillRepeatedly(Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo));
|
| }
|
| @@ -178,14 +188,12 @@ class DownloadFileTest : public testing::Test {
|
| .RetiresOnSaturation();
|
|
|
| scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
|
| - download_file_.reset(new TestDownloadFileImpl(
|
| - *save_info, base::FilePath(),
|
| - GURL(), // Source
|
| - GURL(), // Referrer
|
| - calculate_hash, std::move(save_info->file),
|
| - scoped_ptr<ByteStreamReader>(input_stream_), net::BoundNetLog(),
|
| - observer_factory_.GetWeakPtr()));
|
| - download_file_->SetClientGuid("12345678-ABCD-1234-DCBA-123456789ABC");
|
| + download_file_.reset(
|
| + new TestDownloadFileImpl(std::move(save_info),
|
| + base::FilePath(),
|
| + scoped_ptr<ByteStreamReader>(input_stream_),
|
| + net::BoundNetLog(),
|
| + observer_factory_.GetWeakPtr()));
|
|
|
| EXPECT_CALL(*input_stream_, Read(_, _))
|
| .WillOnce(Return(ByteStreamReader::STREAM_EMPTY))
|
| @@ -270,19 +278,21 @@ class DownloadFileTest : public testing::Test {
|
| }
|
|
|
| void FinishStream(DownloadInterruptReason interrupt_reason,
|
| - bool check_observer) {
|
| + bool check_observer,
|
| + const std::string& expected_hash) {
|
| ::testing::Sequence s1;
|
| SetupFinishStream(interrupt_reason, s1);
|
| sink_callback_.Run();
|
| VerifyStreamAndSize();
|
| if (check_observer) {
|
| - EXPECT_CALL(*(observer_.get()), DestinationCompleted(_));
|
| + EXPECT_CALL(*(observer_.get()),
|
| + MockDestinationCompleted(_, expected_hash));
|
| loop_.RunUntilIdle();
|
| ::testing::Mock::VerifyAndClearExpectations(observer_.get());
|
| - EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _))
|
| + EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _))
|
| .Times(AnyNumber())
|
| - .WillRepeatedly(Invoke(this,
|
| - &DownloadFileTest::SetUpdateDownloadInfo));
|
| + .WillRepeatedly(
|
| + Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo));
|
| }
|
| }
|
|
|
| @@ -290,14 +300,14 @@ class DownloadFileTest : public testing::Test {
|
| const base::FilePath& full_path,
|
| base::FilePath* result_path_p) {
|
| return InvokeRenameMethodAndWaitForCallback(
|
| - &DownloadFile::RenameAndUniquify, full_path, result_path_p);
|
| + RENAME_AND_UNIQUIFY, full_path, result_path_p);
|
| }
|
|
|
| DownloadInterruptReason RenameAndAnnotate(
|
| const base::FilePath& full_path,
|
| base::FilePath* result_path_p) {
|
| return InvokeRenameMethodAndWaitForCallback(
|
| - &DownloadFile::RenameAndAnnotate, full_path, result_path_p);
|
| + RENAME_AND_ANNOTATE, full_path, result_path_p);
|
| }
|
|
|
| void ExpectPermissionError(DownloadInterruptReason err) {
|
| @@ -307,20 +317,40 @@ class DownloadFileTest : public testing::Test {
|
| }
|
|
|
| protected:
|
| + void InvokeRenameMethod(
|
| + DownloadFileRenameMethodType method,
|
| + const base::FilePath& full_path,
|
| + const DownloadFile::RenameCompletionCallback& completion_callback) {
|
| + switch (method) {
|
| + case RENAME_AND_UNIQUIFY:
|
| + download_file_->RenameAndUniquify(full_path, completion_callback);
|
| + break;
|
| +
|
| + case RENAME_AND_ANNOTATE:
|
| + download_file_->RenameAndAnnotate(
|
| + full_path,
|
| + "12345678-ABCD-1234-DCBA-123456789ABC",
|
| + GURL(),
|
| + GURL(),
|
| + completion_callback);
|
| + break;
|
| + }
|
| + }
|
| +
|
| DownloadInterruptReason InvokeRenameMethodAndWaitForCallback(
|
| DownloadFileRenameMethodType method,
|
| const base::FilePath& full_path,
|
| base::FilePath* result_path_p) {
|
| DownloadInterruptReason result_reason(DOWNLOAD_INTERRUPT_REASON_NONE);
|
| base::FilePath result_path;
|
| -
|
| base::RunLoop loop_runner;
|
| - ((*download_file_).*method)(full_path,
|
| - base::Bind(&DownloadFileTest::SetRenameResult,
|
| - base::Unretained(this),
|
| - loop_runner.QuitClosure(),
|
| - &result_reason,
|
| - result_path_p));
|
| + DownloadFile::RenameCompletionCallback completion_callback =
|
| + base::Bind(&DownloadFileTest::SetRenameResult,
|
| + base::Unretained(this),
|
| + loop_runner.QuitClosure(),
|
| + &result_reason,
|
| + result_path_p);
|
| + InvokeRenameMethod(method, full_path, completion_callback);
|
| loop_runner.Run();
|
| return result_reason;
|
| }
|
| @@ -341,7 +371,6 @@ class DownloadFileTest : public testing::Test {
|
| // Latest update sent to the observer.
|
| int64_t bytes_;
|
| int64_t bytes_per_sec_;
|
| - std::string hash_state_;
|
|
|
| base::MessageLoop loop_;
|
|
|
| @@ -391,15 +420,17 @@ class DownloadFileTestWithRename
|
| // the value parameter.
|
| INSTANTIATE_TEST_CASE_P(DownloadFile,
|
| DownloadFileTestWithRename,
|
| - ::testing::Values(&DownloadFile::RenameAndAnnotate,
|
| - &DownloadFile::RenameAndUniquify));
|
| + ::testing::Values(RENAME_AND_ANNOTATE,
|
| + RENAME_AND_UNIQUIFY));
|
|
|
| -const char* DownloadFileTest::kTestData1 =
|
| +const char DownloadFileTest::kTestData1[] =
|
| "Let's write some data to the file!\n";
|
| -const char* DownloadFileTest::kTestData2 = "Writing more data.\n";
|
| -const char* DownloadFileTest::kTestData3 = "Final line.";
|
| -const char* DownloadFileTest::kDataHash =
|
| +const char DownloadFileTest::kTestData2[] = "Writing more data.\n";
|
| +const char DownloadFileTest::kTestData3[] = "Final line.";
|
| +const char DownloadFileTest::kDataHash[] =
|
| "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8";
|
| +const char DownloadFileTest::kEmptyHash[] =
|
| + "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855";
|
|
|
| const uint32_t DownloadFileTest::kDummyDownloadId = 23;
|
| const int DownloadFileTest::kDummyChildId = 3;
|
| @@ -457,10 +488,7 @@ TEST_P(DownloadFileTestWithRename, RenameFileFinal) {
|
| EXPECT_FALSE(base::PathExists(path_2));
|
| EXPECT_TRUE(base::PathExists(path_3));
|
|
|
| - // Should not be able to get the hash until the file is closed.
|
| - std::string hash;
|
| - EXPECT_FALSE(download_file_->GetHash(&hash));
|
| - FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
|
| + FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kDataHash);
|
| loop_.RunUntilIdle();
|
|
|
| // Rename the file after downloading all the data and closing the file.
|
| @@ -474,10 +502,6 @@ TEST_P(DownloadFileTestWithRename, RenameFileFinal) {
|
| EXPECT_FALSE(base::PathExists(path_3));
|
| EXPECT_TRUE(base::PathExists(path_4));
|
|
|
| - // Check the hash.
|
| - EXPECT_TRUE(download_file_->GetHash(&hash));
|
| - EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size()));
|
| -
|
| DestroyDownloadFile(0);
|
| }
|
|
|
| @@ -505,7 +529,7 @@ TEST_F(DownloadFileTest, RenameOverwrites) {
|
| ASSERT_TRUE(base::ReadFileToString(new_path, &file_contents));
|
| EXPECT_NE(std::string(file_data), file_contents);
|
|
|
| - FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
|
| + FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
|
| loop_.RunUntilIdle();
|
| DestroyDownloadFile(0);
|
| }
|
| @@ -530,7 +554,7 @@ TEST_F(DownloadFileTest, RenameUniquifies) {
|
| EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, RenameAndUniquify(path_1, NULL));
|
| EXPECT_TRUE(base::PathExists(path_1_suffixed));
|
|
|
| - FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
|
| + FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
|
| loop_.RunUntilIdle();
|
| DestroyDownloadFile(0);
|
| }
|
| @@ -547,7 +571,7 @@ TEST_F(DownloadFileTest, RenameRecognizesSelfConflict) {
|
| RenameAndUniquify(initial_path, &new_path));
|
| EXPECT_TRUE(base::PathExists(initial_path));
|
|
|
| - FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
|
| + FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
|
| loop_.RunUntilIdle();
|
| DestroyDownloadFile(0);
|
| EXPECT_EQ(initial_path.value(), new_path.value());
|
| @@ -582,7 +606,7 @@ TEST_P(DownloadFileTestWithRename, RenameError) {
|
| EXPECT_FALSE(base::PathExists(target_path_suffixed));
|
| }
|
|
|
| - FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
|
| + FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
|
| loop_.RunUntilIdle();
|
| DestroyDownloadFile(0);
|
| }
|
| @@ -645,10 +669,11 @@ TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) {
|
|
|
| // The Rename() should fail here and enqueue a retry task without invoking
|
| // the completion callback.
|
| - ((*download_file_).*GetParam())(target_path,
|
| - base::Bind(&TestRenameCompletionCallback,
|
| - succeeding_run.QuitClosure(),
|
| - &did_run_callback));
|
| + InvokeRenameMethod(GetParam(),
|
| + target_path,
|
| + base::Bind(&TestRenameCompletionCallback,
|
| + succeeding_run.QuitClosure(),
|
| + &did_run_callback));
|
| EXPECT_FALSE(did_run_callback);
|
|
|
| base::RunLoop first_failing_run;
|
| @@ -674,7 +699,7 @@ TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) {
|
| succeeding_run.Run();
|
| EXPECT_TRUE(did_run_callback);
|
|
|
| - FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
|
| + FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
|
| loop_.RunUntilIdle();
|
| DestroyDownloadFile(0);
|
| }
|
| @@ -689,10 +714,8 @@ TEST_F(DownloadFileTest, StreamEmptySuccess) {
|
| // do anything.
|
| AppendDataToFile(NULL, 0);
|
|
|
| - // Finish the download this way and make sure we see it on the
|
| - // observer.
|
| - EXPECT_CALL(*(observer_.get()), DestinationCompleted(_));
|
| - FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, false);
|
| + // Finish the download this way and make sure we see it on the observer.
|
| + FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
|
| loop_.RunUntilIdle();
|
|
|
| DestroyDownloadFile(0);
|
| @@ -705,9 +728,10 @@ TEST_F(DownloadFileTest, StreamEmptyError) {
|
|
|
| // Finish the download in error and make sure we see it on the
|
| // observer.
|
| - EXPECT_CALL(*(observer_.get()),
|
| - DestinationError(
|
| - DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED))
|
| + EXPECT_CALL(
|
| + *(observer_.get()),
|
| + MockDestinationError(
|
| + DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, 0, kEmptyHash))
|
| .WillOnce(InvokeWithoutArgs(
|
| this, &DownloadFileTest::ConfirmUpdateDownloadInfo));
|
|
|
| @@ -716,9 +740,10 @@ TEST_F(DownloadFileTest, StreamEmptyError) {
|
| // the last one may have the correct information even if the failure
|
| // doesn't produce an update, as the timer update may have triggered at the
|
| // same time.
|
| - EXPECT_CALL(*(observer_.get()), CurrentUpdateStatus(0, _, _));
|
| + EXPECT_CALL(*(observer_.get()), CurrentUpdateStatus(0, _));
|
|
|
| - FinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, false);
|
| + FinishStream(
|
| + DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, false, kEmptyHash);
|
|
|
| loop_.RunUntilIdle();
|
|
|
| @@ -734,7 +759,7 @@ TEST_F(DownloadFileTest, StreamNonEmptySuccess) {
|
| ::testing::Sequence s1;
|
| SetupDataAppend(chunks1, 2, s1);
|
| SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, s1);
|
| - EXPECT_CALL(*(observer_.get()), DestinationCompleted(_));
|
| + EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
|
| sink_callback_.Run();
|
| VerifyStreamAndSize();
|
| loop_.RunUntilIdle();
|
| @@ -752,8 +777,8 @@ TEST_F(DownloadFileTest, StreamNonEmptyError) {
|
| SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, s1);
|
|
|
| EXPECT_CALL(*(observer_.get()),
|
| - DestinationError(
|
| - DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED))
|
| + MockDestinationError(
|
| + DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, _, _))
|
| .WillOnce(InvokeWithoutArgs(
|
| this, &DownloadFileTest::ConfirmUpdateDownloadInfo));
|
|
|
| @@ -763,8 +788,7 @@ TEST_F(DownloadFileTest, StreamNonEmptyError) {
|
| // doesn't produce an update, as the timer update may have triggered at the
|
| // same time.
|
| EXPECT_CALL(*(observer_.get()),
|
| - CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2),
|
| - _, _));
|
| + CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2), _));
|
|
|
| sink_callback_.Run();
|
| loop_.RunUntilIdle();
|
| @@ -772,26 +796,4 @@ TEST_F(DownloadFileTest, StreamNonEmptyError) {
|
| DestroyDownloadFile(0);
|
| }
|
|
|
| -// Send some data, wait 3/4s of a second, run the message loop, and
|
| -// confirm the values the observer received are correct.
|
| -TEST_F(DownloadFileTest, ConfirmUpdate) {
|
| - CreateDownloadFile(0, true);
|
| -
|
| - const char* chunks1[] = { kTestData1, kTestData2 };
|
| - AppendDataToFile(chunks1, 2);
|
| -
|
| - // Run the message loops for 750ms and check for results.
|
| - loop_.task_runner()->PostDelayedTask(FROM_HERE,
|
| - base::MessageLoop::QuitWhenIdleClosure(),
|
| - base::TimeDelta::FromMilliseconds(750));
|
| - loop_.Run();
|
| -
|
| - EXPECT_EQ(static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2)),
|
| - bytes_);
|
| - EXPECT_EQ(download_file_->GetHashState(), hash_state_);
|
| -
|
| - FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
|
| - DestroyDownloadFile(0);
|
| -}
|
| -
|
| } // namespace content
|
|
|