Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Unified Diff: content/browser/download/download_file_unittest.cc

Issue 2742093002: Glue parallel download job and download file together. (Closed)
Patch Set: Rebase, and adjust unittests with recent landed CLs. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/download/download_file_impl.cc ('k') | content/browser/download/download_job.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 f585fe9639b2b5abe48a45c3208f190496827950..5435db3f0dcdc550978827ffc805a24b5d16f038 100644
--- a/content/browser/download/download_file_unittest.cc
+++ b/content/browser/download/download_file_unittest.cc
@@ -39,6 +39,7 @@ using ::testing::AnyNumber;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Return;
+using ::testing::Sequence;
using ::testing::SetArgPointee;
using ::testing::StrictMock;
@@ -54,6 +55,13 @@ struct SourceStreamTestData {
bool finished;
};
+int64_t GetBuffersLength(const char** buffers, size_t num_buffer) {
+ int64_t result = 0;
+ for (size_t i = 0; i < num_buffer; ++i)
+ result += static_cast<int64_t>(strlen(buffers[i]));
+ return result;
+}
+
std::string GetHexEncodedHashValue(crypto::SecureHash* hash_state) {
if (!hash_state)
return std::string();
@@ -150,6 +158,9 @@ class DownloadFileTest : public testing::Test {
static const char kTestData3[];
static const char kTestData4[];
static const char kTestData5[];
+ static const char* kTestData6[];
+ static const char* kTestData7[];
+ static const char* kTestData8[];
static const char kDataHash[];
static const char kEmptyHash[];
static const uint32_t kDummyDownloadId;
@@ -160,7 +171,8 @@ class DownloadFileTest : public testing::Test {
: observer_(new StrictMock<MockDownloadDestinationObserver>),
observer_factory_(observer_.get()),
input_stream_(NULL),
- input_stream_1_(NULL),
+ additional_streams_(
+ std::vector<StrictMock<MockByteStreamReader>*>{nullptr, nullptr}),
bytes_(-1),
bytes_per_sec_(-1) {}
@@ -195,9 +207,16 @@ class DownloadFileTest : public testing::Test {
closure.Run();
}
+ bool CreateDownloadFile(int offset, bool calculate_hash) {
+ return CreateDownloadFile(offset, 0, calculate_hash, false,
+ DownloadItem::ReceivedSlices());
+ }
+
bool CreateDownloadFile(int offset,
+ int length,
bool calculate_hash,
- bool is_sparse_file = false) {
+ bool is_sparse_file,
+ const DownloadItem::ReceivedSlices& received_slices) {
// There can be only one.
DCHECK(!download_file_.get());
@@ -210,10 +229,12 @@ class DownloadFileTest : public testing::Test {
.RetiresOnSaturation();
std::unique_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
+ save_info->offset = offset;
+ save_info->length = length;
+
download_file_.reset(new TestDownloadFileImpl(
std::move(save_info), base::FilePath(),
- std::unique_ptr<ByteStreamReader>(input_stream_),
- std::vector<DownloadItem::ReceivedSlice>(),
+ std::unique_ptr<ByteStreamReader>(input_stream_), received_slices,
net::NetLogWithSource(), is_sparse_file,
observer_factory_.GetWeakPtr()));
@@ -395,69 +416,28 @@ class DownloadFileTest : public testing::Test {
return result_reason;
}
- // Prepare two byte streams to write to the same file sink. If
- // |first_stream_completes_early| is true, the first stream will complete
- // before the second stream starts. If |first_stream_write_all_data| is true,
- // the first stream will write all the data before the 2nd stream starts.
- void PrepareMultipleStreams(bool first_stream_completes_early,
- bool first_stream_write_all_data,
- int64_t second_stream_length) {
- // Create a sparse file.
- ASSERT_TRUE(CreateDownloadFile(0, true, true));
- base::FilePath initial_path(download_file_->FullPath());
- EXPECT_TRUE(base::PathExists(initial_path));
- DCHECK(download_file_);
-
- const char* stream_0_data[] = {kTestData1, kTestData2};
- const char* stream_1_data[] = {kTestData4, kTestData5};
- const char* all_data[] = {kTestData1, kTestData2, kTestData4, kTestData5};
- size_t stream_1_offset = strlen(kTestData1) + strlen(kTestData2);
-
- // Register second SourceStream entry for the second stream.
- // The first stream should be registered in ctor of DownloadFile.
- DownloadFileImpl::SourceStreams& source_streams =
- download_file_->source_streams_;
- EXPECT_EQ(static_cast<size_t>(1), source_streams.size());
- source_streams[stream_1_offset] =
- base::MakeUnique<DownloadFileImpl::SourceStream>(stream_1_offset,
- second_stream_length);
-
- // Create the second byte stream. Will be moved to DownloadFile.
- input_stream_1_ = new MockByteStreamReader();
-
- ::testing::Sequence s0;
- ::testing::Sequence s1;
- if (first_stream_write_all_data) {
- SetupDataAppend(all_data, 4, input_stream_, s0, 0);
- // The 2nd stream will abort after the first read
- SetupDataAppend(stream_1_data, 1, input_stream_1_, s1, stream_1_offset);
- } else {
- SetupDataAppend(stream_0_data, 2, input_stream_, s0, 0);
- SetupDataAppend(stream_1_data, 2, input_stream_1_, s1, stream_1_offset);
- }
-
- // If the first stream doesn't finish before the second stream starts
- // writing, its length will be cut short by the second stream. So
- // STREAM_COMPLETE will never get called.
- if (first_stream_completes_early)
- SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_, s0);
- else
- EXPECT_CALL(*input_stream_, RegisterCallback(_)).RetiresOnSaturation();
+ // Prepare a byte stream to write to the file sink.
+ void PrepareStream(StrictMock<MockByteStreamReader>** stream,
+ int64_t offset,
+ bool create_stream,
+ bool will_finish,
+ const char** buffers,
+ size_t num_buffer) {
+ if (create_stream)
+ *stream = new StrictMock<MockByteStreamReader>();
// Expectation on MockByteStreamReader for MultipleStreams tests:
// 1. RegisterCallback: Must called twice. One to set the callback, the
// other to release the stream.
// 2. Read: If filled with N buffer, called (N+1) times, where the last Read
- // call doesn't read any data but returns STREAM_COMPLETE.
+ // call doesn't read any data but returns STRAM_COMPLETE.
// The stream may terminate in the middle and less Read calls are expected.
// 3. GetStatus: Only called if the stream is completed and last Read call
// returns STREAM_COMPLETE.
- if (second_stream_length == 0 && !first_stream_write_all_data)
- SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_1_, s1);
- else
- EXPECT_CALL(*input_stream_1_, RegisterCallback(_)).RetiresOnSaturation();
-
- EXPECT_CALL(*input_stream_1_, RegisterCallback(_)).RetiresOnSaturation();
+ Sequence seq;
+ SetupDataAppend(buffers, num_buffer, *stream, seq, offset);
+ if (will_finish)
+ SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, *stream, seq);
}
void VerifySourceStreamsStates(const SourceStreamTestData& data) {
@@ -486,8 +466,8 @@ class DownloadFileTest : public testing::Test {
// Owned by download_file_; will be alive for lifetime of download_file_.
StrictMock<MockByteStreamReader>* input_stream_;
- // A second byte stream to test multiple stream write.
- MockByteStreamReader* input_stream_1_;
+ // Additional streams to test multiple stream write.
+ std::vector<StrictMock<MockByteStreamReader>*> additional_streams_;
// Sink callback data for stream.
base::Closure sink_callback_;
@@ -548,6 +528,11 @@ const char DownloadFileTest::kTestData2[] = "Writing more data.\n";
const char DownloadFileTest::kTestData3[] = "Final line.";
const char DownloadFileTest::kTestData4[] = "abcdefg";
const char DownloadFileTest::kTestData5[] = "01234";
+const char* DownloadFileTest::kTestData6[] = {kTestData1, kTestData2};
+const char* DownloadFileTest::kTestData7[] = {kTestData4, kTestData5};
+const char* DownloadFileTest::kTestData8[] = {kTestData1, kTestData2,
+ kTestData4, kTestData5};
+
const char DownloadFileTest::kDataHash[] =
"CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8";
const char DownloadFileTest::kEmptyHash[] =
@@ -922,16 +907,24 @@ TEST_F(DownloadFileTest, StreamNonEmptyError) {
//
// Activate both streams at the same time.
TEST_F(DownloadFileTest, MutipleStreamsWrite) {
- PrepareMultipleStreams(false, false, 0);
- EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
+ int64_t stream_0_length = GetBuffersLength(kTestData6, 2);
+ int64_t stream_1_length = GetBuffersLength(kTestData7, 2);
+
+ ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true, true,
+ DownloadItem::ReceivedSlices()));
+
+ PrepareStream(&input_stream_, 0, false, true, kTestData6, 2);
+ PrepareStream(&additional_streams_[0], stream_0_length, true, true,
+ kTestData7, 2);
- int64_t stream_0_length =
- static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2));
- int64_t stream_1_length =
- static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5));
+ EXPECT_CALL(*additional_streams_[0], RegisterCallback(_))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
+ // Activate the streams.
download_file_->AddByteStream(
- std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length);
+ std::unique_ptr<MockByteStreamReader>(additional_streams_[0]),
+ stream_0_length, DownloadSaveInfo::kLengthFullContent);
sink_callback_.Run();
base::RunLoop().RunUntilIdle();
@@ -944,102 +937,88 @@ TEST_F(DownloadFileTest, MutipleStreamsWrite) {
DestroyDownloadFile(0);
}
-// Activate and deplete one stream, later add the second stream.
-TEST_F(DownloadFileTest, MutipleStreamsOneStreamFirst) {
- PrepareMultipleStreams(true, false, 0);
+// 3 streams write to one sink, the second stream has a limited length.
+TEST_F(DownloadFileTest, MutipleStreamsLimitedLength) {
+ int64_t stream_0_length = GetBuffersLength(kTestData6, 2);
- int64_t stream_0_length =
- static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2));
- int64_t stream_1_length =
- static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5));
+ // The second stream has a limited length and should be partially written
+ // to disk. When we prepare the stream, we fill the stream with 2 full buffer.
+ int64_t stream_1_length = GetBuffersLength(kTestData7, 2) - 1;
- // Deplete the first stream.
- sink_callback_.Run();
- base::RunLoop().RunUntilIdle();
+ // The last stream can't have length limit, it's a half open request, e.g
+ // "Range:50-".
+ int64_t stream_2_length = GetBuffersLength(kTestData6, 2);
- SourceStreamTestData stream_data_0(0, stream_0_length, true);
- SourceStreamTestData stream_data_1(stream_0_length, 0, false);
- VerifySourceStreamsStates(stream_data_0);
- VerifySourceStreamsStates(stream_data_1);
- EXPECT_EQ(stream_0_length, TotalBytesReceived());
-
- // Won't inform the observer until the second stream is depleted.
- EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
+ ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true, true,
+ DownloadItem::ReceivedSlices()));
- // Drain the second stream after the first stream is depleted.
- download_file_->AddByteStream(
- std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length);
- base::RunLoop().RunUntilIdle();
+ PrepareStream(&input_stream_, 0, false, true, kTestData6, 2);
+ PrepareStream(&additional_streams_[0], stream_0_length, true, false,
+ kTestData7, 2);
+ PrepareStream(&additional_streams_[1], stream_0_length + stream_1_length,
+ true, true, kTestData6, 2);
- stream_data_1.bytes_written = stream_1_length;
- stream_data_1.finished = true;
- VerifySourceStreamsStates(stream_data_0);
- VerifySourceStreamsStates(stream_data_1);
- EXPECT_EQ(stream_0_length + stream_1_length, TotalBytesReceived());
+ EXPECT_CALL(*additional_streams_[0], RegisterCallback(_))
+ .Times(2)
+ .RetiresOnSaturation();
- DestroyDownloadFile(0);
-}
+ EXPECT_CALL(*additional_streams_[1], RegisterCallback(_))
+ .RetiresOnSaturation();
-// Two streams write to one sink, the second stream has a limited length.
-TEST_F(DownloadFileTest, MutipleStreamsLimitedLength) {
- // The second stream has two buffers, kTestData4 and kTestData5.
- // The length limit is set to less than the length of kTestData4.
- // kTestData4 should be partially written to disk, where kTestData5 should be
- // ignored.
- int64_t stream_0_length =
- static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2));
- int64_t stream_1_length = static_cast<int64_t>(strlen(kTestData4)) - 1;
- PrepareMultipleStreams(false, false, stream_1_length);
+ EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
+ // Activate all the streams.
+ download_file_->AddByteStream(
+ std::unique_ptr<MockByteStreamReader>(additional_streams_[0]),
+ stream_0_length, stream_1_length);
download_file_->AddByteStream(
- std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length);
+ std::unique_ptr<MockByteStreamReader>(additional_streams_[1]),
+ stream_0_length + stream_1_length, DownloadSaveInfo::kLengthFullContent);
sink_callback_.Run();
base::RunLoop().RunUntilIdle();
SourceStreamTestData stream_data_0(0, stream_0_length, true);
SourceStreamTestData stream_data_1(stream_0_length, stream_1_length, true);
+ SourceStreamTestData stream_data_2(stream_0_length + stream_1_length,
+ stream_2_length, true);
+
VerifySourceStreamsStates(stream_data_0);
VerifySourceStreamsStates(stream_data_1);
- EXPECT_EQ(stream_0_length + stream_1_length, TotalBytesReceived());
-
- std::string disk_data, expected_data;
- EXPECT_TRUE(base::ReadFileToString(download_file_->FullPath(), &disk_data));
- expected_data.append(kTestData1).append(kTestData2).append(kTestData4);
- expected_data = expected_data.substr(0, stream_0_length + stream_1_length);
- EXPECT_EQ(expected_data, disk_data);
+ VerifySourceStreamsStates(stream_data_2);
- // Finish the second stream.
- // TODO(xingliu): Refactor test code to deal with unfinished streams.
- scoped_refptr<net::IOBuffer> data = new net::IOBuffer(strlen(kTestData5));
- size_t size;
- input_stream_1_->Read(&data, &size);
+ EXPECT_EQ(stream_0_length + stream_1_length + stream_2_length,
+ TotalBytesReceived());
download_file_->Cancel();
DestroyDownloadFile(0, false);
}
-// Two streams write to one sink, the first stream writes the whole file before
-// the seconds stream was able to start
+// Activate and deplete one stream, later add the second stream.
TEST_F(DownloadFileTest, MutipleStreamsFirstStreamWriteAllData) {
- PrepareMultipleStreams(true, true, 0);
- int64_t stream_0_length =
- static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2) +
- strlen(kTestData4) + strlen(kTestData5));
- int64_t stream_1_length =
- static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5));
+ int64_t stream_0_length = GetBuffersLength(kTestData8, 4);
+
+ ASSERT_TRUE(CreateDownloadFile(0, DownloadSaveInfo::kLengthFullContent, true,
+ true, DownloadItem::ReceivedSlices()));
+
+ PrepareStream(&input_stream_, 0, false, true, kTestData8, 4);
+
+ EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
+
sink_callback_.Run();
base::RunLoop().RunUntilIdle();
- EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
+ // Add another stream, the file is already closed, so nothing should be
+ // called.
+ EXPECT_FALSE(download_file_->InProgress());
+ additional_streams_[0] = new StrictMock<MockByteStreamReader>();
download_file_->AddByteStream(
- std::unique_ptr<MockByteStreamReader>(input_stream_1_),
- stream_0_length - stream_1_length);
+ std::unique_ptr<MockByteStreamReader>(additional_streams_[0]),
+ stream_0_length - 1, DownloadSaveInfo::kLengthFullContent);
base::RunLoop().RunUntilIdle();
SourceStreamTestData stream_data_0(0, stream_0_length, true);
- SourceStreamTestData stream_data_1(stream_0_length - stream_1_length, 0,
- true);
+ SourceStreamTestData stream_data_1(stream_0_length - 1, 0, false);
VerifySourceStreamsStates(stream_data_0);
VerifySourceStreamsStates(stream_data_1);
EXPECT_EQ(stream_0_length, TotalBytesReceived());
« no previous file with comments | « content/browser/download/download_file_impl.cc ('k') | content/browser/download/download_job.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698