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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 21 matching lines...) Expand all
32 #include "net/base/net_errors.h" 32 #include "net/base/net_errors.h"
33 #include "net/log/net_log_with_source.h" 33 #include "net/log/net_log_with_source.h"
34 #include "testing/gmock/include/gmock/gmock.h" 34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h" 35 #include "testing/gtest/include/gtest/gtest.h"
36 36
37 using ::testing::_; 37 using ::testing::_;
38 using ::testing::AnyNumber; 38 using ::testing::AnyNumber;
39 using ::testing::DoAll; 39 using ::testing::DoAll;
40 using ::testing::InSequence; 40 using ::testing::InSequence;
41 using ::testing::Return; 41 using ::testing::Return;
42 using ::testing::Sequence;
42 using ::testing::SetArgPointee; 43 using ::testing::SetArgPointee;
43 using ::testing::StrictMock; 44 using ::testing::StrictMock;
44 45
45 namespace content { 46 namespace content {
46 namespace { 47 namespace {
47 48
48 // Struct for SourceStream states verification. 49 // Struct for SourceStream states verification.
49 struct SourceStreamTestData { 50 struct SourceStreamTestData {
50 SourceStreamTestData(int64_t offset, int64_t bytes_written, bool finished) 51 SourceStreamTestData(int64_t offset, int64_t bytes_written, bool finished)
51 : offset(offset), bytes_written(bytes_written), finished(finished) {} 52 : offset(offset), bytes_written(bytes_written), finished(finished) {}
52 int64_t offset; 53 int64_t offset;
53 int64_t bytes_written; 54 int64_t bytes_written;
54 bool finished; 55 bool finished;
55 }; 56 };
56 57
58 int64_t GetBuffersLength(const char** buffers, size_t num_buffer) {
59 int64_t result = 0;
60 for (size_t i = 0; i < num_buffer; ++i)
61 result += static_cast<int64_t>(strlen(buffers[i]));
62 return result;
63 }
64
57 std::string GetHexEncodedHashValue(crypto::SecureHash* hash_state) { 65 std::string GetHexEncodedHashValue(crypto::SecureHash* hash_state) {
58 if (!hash_state) 66 if (!hash_state)
59 return std::string(); 67 return std::string();
60 std::vector<char> hash_value(hash_state->GetHashLength()); 68 std::vector<char> hash_value(hash_state->GetHashLength());
61 hash_state->Finish(&hash_value.front(), hash_value.size()); 69 hash_state->Finish(&hash_value.front(), hash_value.size());
62 return base::HexEncode(&hash_value.front(), hash_value.size()); 70 return base::HexEncode(&hash_value.front(), hash_value.size());
63 } 71 }
64 72
65 class MockByteStreamReader : public ByteStreamReader { 73 class MockByteStreamReader : public ByteStreamReader {
66 public: 74 public:
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 151
144 } // namespace 152 } // namespace
145 153
146 class DownloadFileTest : public testing::Test { 154 class DownloadFileTest : public testing::Test {
147 public: 155 public:
148 static const char kTestData1[]; 156 static const char kTestData1[];
149 static const char kTestData2[]; 157 static const char kTestData2[];
150 static const char kTestData3[]; 158 static const char kTestData3[];
151 static const char kTestData4[]; 159 static const char kTestData4[];
152 static const char kTestData5[]; 160 static const char kTestData5[];
161 static const char* kTestData6[];
162 static const char* kTestData7[];
163 static const char* kTestData8[];
153 static const char kDataHash[]; 164 static const char kDataHash[];
154 static const char kEmptyHash[]; 165 static const char kEmptyHash[];
155 static const uint32_t kDummyDownloadId; 166 static const uint32_t kDummyDownloadId;
156 static const int kDummyChildId; 167 static const int kDummyChildId;
157 static const int kDummyRequestId; 168 static const int kDummyRequestId;
158 169
159 DownloadFileTest() 170 DownloadFileTest()
160 : observer_(new StrictMock<MockDownloadDestinationObserver>), 171 : observer_(new StrictMock<MockDownloadDestinationObserver>),
161 observer_factory_(observer_.get()), 172 observer_factory_(observer_.get()),
162 input_stream_(NULL), 173 input_stream_(NULL),
163 input_stream_1_(NULL), 174 additional_streams_(
175 std::vector<StrictMock<MockByteStreamReader>*>{nullptr, nullptr}),
164 bytes_(-1), 176 bytes_(-1),
165 bytes_per_sec_(-1) {} 177 bytes_per_sec_(-1) {}
166 178
167 ~DownloadFileTest() override {} 179 ~DownloadFileTest() override {}
168 180
169 void SetUpdateDownloadInfo( 181 void SetUpdateDownloadInfo(
170 int64_t bytes, int64_t bytes_per_sec, 182 int64_t bytes, int64_t bytes_per_sec,
171 const std::vector<DownloadItem::ReceivedSlice>& received_slices) { 183 const std::vector<DownloadItem::ReceivedSlice>& received_slices) {
172 bytes_ = bytes; 184 bytes_ = bytes;
173 bytes_per_sec_ = bytes_per_sec; 185 bytes_per_sec_ = bytes_per_sec;
(...skipping 14 matching lines...) Expand all
188 sink_callback_ = sink_callback; 200 sink_callback_ = sink_callback;
189 } 201 }
190 202
191 void SetInterruptReasonCallback(const base::Closure& closure, 203 void SetInterruptReasonCallback(const base::Closure& closure,
192 DownloadInterruptReason* reason_p, 204 DownloadInterruptReason* reason_p,
193 DownloadInterruptReason reason) { 205 DownloadInterruptReason reason) {
194 *reason_p = reason; 206 *reason_p = reason;
195 closure.Run(); 207 closure.Run();
196 } 208 }
197 209
210 bool CreateDownloadFile(int offset, bool calculate_hash) {
211 return CreateDownloadFile(offset, 0, calculate_hash, false,
212 DownloadItem::ReceivedSlices());
213 }
214
198 bool CreateDownloadFile(int offset, 215 bool CreateDownloadFile(int offset,
216 int length,
199 bool calculate_hash, 217 bool calculate_hash,
200 bool is_sparse_file = false) { 218 bool is_sparse_file,
219 const DownloadItem::ReceivedSlices& received_slices) {
201 // There can be only one. 220 // There can be only one.
202 DCHECK(!download_file_.get()); 221 DCHECK(!download_file_.get());
203 222
204 input_stream_ = new StrictMock<MockByteStreamReader>(); 223 input_stream_ = new StrictMock<MockByteStreamReader>();
205 224
206 // TODO: Need to actually create a function that'll set the variables 225 // TODO: Need to actually create a function that'll set the variables
207 // based on the inputs from the callback. 226 // based on the inputs from the callback.
208 EXPECT_CALL(*input_stream_, RegisterCallback(_)) 227 EXPECT_CALL(*input_stream_, RegisterCallback(_))
209 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback)) 228 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback))
210 .RetiresOnSaturation(); 229 .RetiresOnSaturation();
211 230
212 std::unique_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); 231 std::unique_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
232 save_info->offset = offset;
233 save_info->length = length;
234
213 download_file_.reset(new TestDownloadFileImpl( 235 download_file_.reset(new TestDownloadFileImpl(
214 std::move(save_info), base::FilePath(), 236 std::move(save_info), base::FilePath(),
215 std::unique_ptr<ByteStreamReader>(input_stream_), 237 std::unique_ptr<ByteStreamReader>(input_stream_), received_slices,
216 std::vector<DownloadItem::ReceivedSlice>(),
217 net::NetLogWithSource(), is_sparse_file, 238 net::NetLogWithSource(), is_sparse_file,
218 observer_factory_.GetWeakPtr())); 239 observer_factory_.GetWeakPtr()));
219 240
220 EXPECT_CALL(*input_stream_, Read(_, _)) 241 EXPECT_CALL(*input_stream_, Read(_, _))
221 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) 242 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY))
222 .RetiresOnSaturation(); 243 .RetiresOnSaturation();
223 244
224 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this); 245 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this);
225 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE; 246 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
226 base::RunLoop loop_runner; 247 base::RunLoop loop_runner;
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 base::Bind(&DownloadFileTest::SetRenameResult, 409 base::Bind(&DownloadFileTest::SetRenameResult,
389 base::Unretained(this), 410 base::Unretained(this),
390 loop_runner.QuitClosure(), 411 loop_runner.QuitClosure(),
391 &result_reason, 412 &result_reason,
392 result_path_p); 413 result_path_p);
393 InvokeRenameMethod(method, full_path, completion_callback); 414 InvokeRenameMethod(method, full_path, completion_callback);
394 loop_runner.Run(); 415 loop_runner.Run();
395 return result_reason; 416 return result_reason;
396 } 417 }
397 418
398 // Prepare two byte streams to write to the same file sink. If 419 // Prepare a byte stream to write to the file sink.
399 // |first_stream_completes_early| is true, the first stream will complete 420 void PrepareStream(StrictMock<MockByteStreamReader>** stream,
400 // before the second stream starts. If |first_stream_write_all_data| is true, 421 int64_t offset,
401 // the first stream will write all the data before the 2nd stream starts. 422 bool create_stream,
402 void PrepareMultipleStreams(bool first_stream_completes_early, 423 bool will_finish,
403 bool first_stream_write_all_data, 424 const char** buffers,
404 int64_t second_stream_length) { 425 size_t num_buffer) {
405 // Create a sparse file. 426 if (create_stream)
406 ASSERT_TRUE(CreateDownloadFile(0, true, true)); 427 *stream = new StrictMock<MockByteStreamReader>();
407 base::FilePath initial_path(download_file_->FullPath());
408 EXPECT_TRUE(base::PathExists(initial_path));
409 DCHECK(download_file_);
410
411 const char* stream_0_data[] = {kTestData1, kTestData2};
412 const char* stream_1_data[] = {kTestData4, kTestData5};
413 const char* all_data[] = {kTestData1, kTestData2, kTestData4, kTestData5};
414 size_t stream_1_offset = strlen(kTestData1) + strlen(kTestData2);
415
416 // Register second SourceStream entry for the second stream.
417 // The first stream should be registered in ctor of DownloadFile.
418 DownloadFileImpl::SourceStreams& source_streams =
419 download_file_->source_streams_;
420 EXPECT_EQ(static_cast<size_t>(1), source_streams.size());
421 source_streams[stream_1_offset] =
422 base::MakeUnique<DownloadFileImpl::SourceStream>(stream_1_offset,
423 second_stream_length);
424
425 // Create the second byte stream. Will be moved to DownloadFile.
426 input_stream_1_ = new MockByteStreamReader();
427
428 ::testing::Sequence s0;
429 ::testing::Sequence s1;
430 if (first_stream_write_all_data) {
431 SetupDataAppend(all_data, 4, input_stream_, s0, 0);
432 // The 2nd stream will abort after the first read
433 SetupDataAppend(stream_1_data, 1, input_stream_1_, s1, stream_1_offset);
434 } else {
435 SetupDataAppend(stream_0_data, 2, input_stream_, s0, 0);
436 SetupDataAppend(stream_1_data, 2, input_stream_1_, s1, stream_1_offset);
437 }
438
439 // If the first stream doesn't finish before the second stream starts
440 // writing, its length will be cut short by the second stream. So
441 // STREAM_COMPLETE will never get called.
442 if (first_stream_completes_early)
443 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_, s0);
444 else
445 EXPECT_CALL(*input_stream_, RegisterCallback(_)).RetiresOnSaturation();
446 428
447 // Expectation on MockByteStreamReader for MultipleStreams tests: 429 // Expectation on MockByteStreamReader for MultipleStreams tests:
448 // 1. RegisterCallback: Must called twice. One to set the callback, the 430 // 1. RegisterCallback: Must called twice. One to set the callback, the
449 // other to release the stream. 431 // other to release the stream.
450 // 2. Read: If filled with N buffer, called (N+1) times, where the last Read 432 // 2. Read: If filled with N buffer, called (N+1) times, where the last Read
451 // call doesn't read any data but returns STREAM_COMPLETE. 433 // call doesn't read any data but returns STRAM_COMPLETE.
452 // The stream may terminate in the middle and less Read calls are expected. 434 // The stream may terminate in the middle and less Read calls are expected.
453 // 3. GetStatus: Only called if the stream is completed and last Read call 435 // 3. GetStatus: Only called if the stream is completed and last Read call
454 // returns STREAM_COMPLETE. 436 // returns STREAM_COMPLETE.
455 if (second_stream_length == 0 && !first_stream_write_all_data) 437 Sequence seq;
456 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_1_, s1); 438 SetupDataAppend(buffers, num_buffer, *stream, seq, offset);
457 else 439 if (will_finish)
458 EXPECT_CALL(*input_stream_1_, RegisterCallback(_)).RetiresOnSaturation(); 440 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, *stream, seq);
459
460 EXPECT_CALL(*input_stream_1_, RegisterCallback(_)).RetiresOnSaturation();
461 } 441 }
462 442
463 void VerifySourceStreamsStates(const SourceStreamTestData& data) { 443 void VerifySourceStreamsStates(const SourceStreamTestData& data) {
464 DCHECK(download_file_->source_streams_.find(data.offset) != 444 DCHECK(download_file_->source_streams_.find(data.offset) !=
465 download_file_->source_streams_.end()); 445 download_file_->source_streams_.end());
466 DownloadFileImpl::SourceStream* stream = 446 DownloadFileImpl::SourceStream* stream =
467 download_file_->source_streams_[data.offset].get(); 447 download_file_->source_streams_[data.offset].get();
468 DCHECK(stream); 448 DCHECK(stream);
469 EXPECT_EQ(data.offset, stream->offset()); 449 EXPECT_EQ(data.offset, stream->offset());
470 EXPECT_EQ(data.bytes_written, stream->bytes_written()); 450 EXPECT_EQ(data.bytes_written, stream->bytes_written());
471 EXPECT_EQ(data.finished, stream->is_finished()); 451 EXPECT_EQ(data.finished, stream->is_finished());
472 } 452 }
473 453
474 int64_t TotalBytesReceived() const { 454 int64_t TotalBytesReceived() const {
475 DCHECK(download_file_); 455 DCHECK(download_file_);
476 return download_file_->TotalBytesReceived(); 456 return download_file_->TotalBytesReceived();
477 } 457 }
478 458
479 std::unique_ptr<StrictMock<MockDownloadDestinationObserver>> observer_; 459 std::unique_ptr<StrictMock<MockDownloadDestinationObserver>> observer_;
480 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_; 460 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_;
481 461
482 // DownloadFile instance we are testing. 462 // DownloadFile instance we are testing.
483 std::unique_ptr<DownloadFileImpl> download_file_; 463 std::unique_ptr<DownloadFileImpl> download_file_;
484 464
485 // Stream for sending data into the download file. 465 // Stream for sending data into the download file.
486 // Owned by download_file_; will be alive for lifetime of download_file_. 466 // Owned by download_file_; will be alive for lifetime of download_file_.
487 StrictMock<MockByteStreamReader>* input_stream_; 467 StrictMock<MockByteStreamReader>* input_stream_;
488 468
489 // A second byte stream to test multiple stream write. 469 // Additional streams to test multiple stream write.
490 MockByteStreamReader* input_stream_1_; 470 std::vector<StrictMock<MockByteStreamReader>*> additional_streams_;
491 471
492 // Sink callback data for stream. 472 // Sink callback data for stream.
493 base::Closure sink_callback_; 473 base::Closure sink_callback_;
494 474
495 // Latest update sent to the observer. 475 // Latest update sent to the observer.
496 int64_t bytes_; 476 int64_t bytes_;
497 int64_t bytes_per_sec_; 477 int64_t bytes_per_sec_;
498 478
499 private: 479 private:
500 void SetRenameResult(const base::Closure& closure, 480 void SetRenameResult(const base::Closure& closure,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 DownloadFileTestWithRename, 521 DownloadFileTestWithRename,
542 ::testing::Values(RENAME_AND_ANNOTATE, 522 ::testing::Values(RENAME_AND_ANNOTATE,
543 RENAME_AND_UNIQUIFY)); 523 RENAME_AND_UNIQUIFY));
544 524
545 const char DownloadFileTest::kTestData1[] = 525 const char DownloadFileTest::kTestData1[] =
546 "Let's write some data to the file!\n"; 526 "Let's write some data to the file!\n";
547 const char DownloadFileTest::kTestData2[] = "Writing more data.\n"; 527 const char DownloadFileTest::kTestData2[] = "Writing more data.\n";
548 const char DownloadFileTest::kTestData3[] = "Final line."; 528 const char DownloadFileTest::kTestData3[] = "Final line.";
549 const char DownloadFileTest::kTestData4[] = "abcdefg"; 529 const char DownloadFileTest::kTestData4[] = "abcdefg";
550 const char DownloadFileTest::kTestData5[] = "01234"; 530 const char DownloadFileTest::kTestData5[] = "01234";
531 const char* DownloadFileTest::kTestData6[] = {kTestData1, kTestData2};
532 const char* DownloadFileTest::kTestData7[] = {kTestData4, kTestData5};
533 const char* DownloadFileTest::kTestData8[] = {kTestData1, kTestData2,
534 kTestData4, kTestData5};
535
551 const char DownloadFileTest::kDataHash[] = 536 const char DownloadFileTest::kDataHash[] =
552 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8"; 537 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8";
553 const char DownloadFileTest::kEmptyHash[] = 538 const char DownloadFileTest::kEmptyHash[] =
554 "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"; 539 "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855";
555 540
556 const uint32_t DownloadFileTest::kDummyDownloadId = 23; 541 const uint32_t DownloadFileTest::kDummyDownloadId = 23;
557 const int DownloadFileTest::kDummyChildId = 3; 542 const int DownloadFileTest::kDummyChildId = 3;
558 const int DownloadFileTest::kDummyRequestId = 67; 543 const int DownloadFileTest::kDummyRequestId = 67;
559 544
560 // Rename the file before any data is downloaded, after some has, after it all 545 // Rename the file before any data is downloaded, after some has, after it all
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
915 sink_callback_.Run(); 900 sink_callback_.Run();
916 base::RunLoop().RunUntilIdle(); 901 base::RunLoop().RunUntilIdle();
917 VerifyStreamAndSize(); 902 VerifyStreamAndSize();
918 DestroyDownloadFile(0); 903 DestroyDownloadFile(0);
919 } 904 }
920 905
921 // Tests for concurrent streams handling, used for parallel download. 906 // Tests for concurrent streams handling, used for parallel download.
922 // 907 //
923 // Activate both streams at the same time. 908 // Activate both streams at the same time.
924 TEST_F(DownloadFileTest, MutipleStreamsWrite) { 909 TEST_F(DownloadFileTest, MutipleStreamsWrite) {
925 PrepareMultipleStreams(false, false, 0); 910 int64_t stream_0_length = GetBuffersLength(kTestData6, 2);
911 int64_t stream_1_length = GetBuffersLength(kTestData7, 2);
912
913 ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true, true,
914 DownloadItem::ReceivedSlices()));
915
916 PrepareStream(&input_stream_, 0, false, true, kTestData6, 2);
917 PrepareStream(&additional_streams_[0], stream_0_length, true, true,
918 kTestData7, 2);
919
920 EXPECT_CALL(*additional_streams_[0], RegisterCallback(_))
921 .RetiresOnSaturation();
926 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); 922 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
927 923
928 int64_t stream_0_length = 924 // Activate the streams.
929 static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2));
930 int64_t stream_1_length =
931 static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5));
932
933 download_file_->AddByteStream( 925 download_file_->AddByteStream(
934 std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length); 926 std::unique_ptr<MockByteStreamReader>(additional_streams_[0]),
927 stream_0_length, DownloadSaveInfo::kLengthFullContent);
935 sink_callback_.Run(); 928 sink_callback_.Run();
936 base::RunLoop().RunUntilIdle(); 929 base::RunLoop().RunUntilIdle();
937 930
938 SourceStreamTestData stream_data_0(0, stream_0_length, true); 931 SourceStreamTestData stream_data_0(0, stream_0_length, true);
939 SourceStreamTestData stream_data_1(stream_0_length, stream_1_length, true); 932 SourceStreamTestData stream_data_1(stream_0_length, stream_1_length, true);
940 VerifySourceStreamsStates(stream_data_0); 933 VerifySourceStreamsStates(stream_data_0);
941 VerifySourceStreamsStates(stream_data_1); 934 VerifySourceStreamsStates(stream_data_1);
942 EXPECT_EQ(stream_0_length + stream_1_length, TotalBytesReceived()); 935 EXPECT_EQ(stream_0_length + stream_1_length, TotalBytesReceived());
943 936
944 DestroyDownloadFile(0); 937 DestroyDownloadFile(0);
945 } 938 }
946 939
947 // Activate and deplete one stream, later add the second stream. 940 // 3 streams write to one sink, the second stream has a limited length.
948 TEST_F(DownloadFileTest, MutipleStreamsOneStreamFirst) { 941 TEST_F(DownloadFileTest, MutipleStreamsLimitedLength) {
949 PrepareMultipleStreams(true, false, 0); 942 int64_t stream_0_length = GetBuffersLength(kTestData6, 2);
950 943
951 int64_t stream_0_length = 944 // The second stream has a limited length and should be partially written
952 static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2)); 945 // to disk. When we prepare the stream, we fill the stream with 2 full buffer.
953 int64_t stream_1_length = 946 int64_t stream_1_length = GetBuffersLength(kTestData7, 2) - 1;
954 static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5));
955 947
956 // Deplete the first stream. 948 // The last stream can't have length limit, it's a half open request, e.g
957 sink_callback_.Run(); 949 // "Range:50-".
958 base::RunLoop().RunUntilIdle(); 950 int64_t stream_2_length = GetBuffersLength(kTestData6, 2);
959 951
960 SourceStreamTestData stream_data_0(0, stream_0_length, true); 952 ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true, true,
961 SourceStreamTestData stream_data_1(stream_0_length, 0, false); 953 DownloadItem::ReceivedSlices()));
962 VerifySourceStreamsStates(stream_data_0);
963 VerifySourceStreamsStates(stream_data_1);
964 EXPECT_EQ(stream_0_length, TotalBytesReceived());
965 954
966 // Won't inform the observer until the second stream is depleted. 955 PrepareStream(&input_stream_, 0, false, true, kTestData6, 2);
956 PrepareStream(&additional_streams_[0], stream_0_length, true, false,
957 kTestData7, 2);
958 PrepareStream(&additional_streams_[1], stream_0_length + stream_1_length,
959 true, true, kTestData6, 2);
960
961 EXPECT_CALL(*additional_streams_[0], RegisterCallback(_))
962 .Times(2)
963 .RetiresOnSaturation();
964
965 EXPECT_CALL(*additional_streams_[1], RegisterCallback(_))
966 .RetiresOnSaturation();
967
967 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); 968 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
968 969
969 // Drain the second stream after the first stream is depleted. 970 // Activate all the streams.
970 download_file_->AddByteStream( 971 download_file_->AddByteStream(
971 std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length); 972 std::unique_ptr<MockByteStreamReader>(additional_streams_[0]),
972 base::RunLoop().RunUntilIdle(); 973 stream_0_length, stream_1_length);
973
974 stream_data_1.bytes_written = stream_1_length;
975 stream_data_1.finished = true;
976 VerifySourceStreamsStates(stream_data_0);
977 VerifySourceStreamsStates(stream_data_1);
978 EXPECT_EQ(stream_0_length + stream_1_length, TotalBytesReceived());
979
980 DestroyDownloadFile(0);
981 }
982
983 // Two streams write to one sink, the second stream has a limited length.
984 TEST_F(DownloadFileTest, MutipleStreamsLimitedLength) {
985 // The second stream has two buffers, kTestData4 and kTestData5.
986 // The length limit is set to less than the length of kTestData4.
987 // kTestData4 should be partially written to disk, where kTestData5 should be
988 // ignored.
989 int64_t stream_0_length =
990 static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2));
991 int64_t stream_1_length = static_cast<int64_t>(strlen(kTestData4)) - 1;
992 PrepareMultipleStreams(false, false, stream_1_length);
993
994 download_file_->AddByteStream( 974 download_file_->AddByteStream(
995 std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length); 975 std::unique_ptr<MockByteStreamReader>(additional_streams_[1]),
976 stream_0_length + stream_1_length, DownloadSaveInfo::kLengthFullContent);
996 sink_callback_.Run(); 977 sink_callback_.Run();
997 base::RunLoop().RunUntilIdle(); 978 base::RunLoop().RunUntilIdle();
998 979
999 SourceStreamTestData stream_data_0(0, stream_0_length, true); 980 SourceStreamTestData stream_data_0(0, stream_0_length, true);
1000 SourceStreamTestData stream_data_1(stream_0_length, stream_1_length, true); 981 SourceStreamTestData stream_data_1(stream_0_length, stream_1_length, true);
982 SourceStreamTestData stream_data_2(stream_0_length + stream_1_length,
983 stream_2_length, true);
984
1001 VerifySourceStreamsStates(stream_data_0); 985 VerifySourceStreamsStates(stream_data_0);
1002 VerifySourceStreamsStates(stream_data_1); 986 VerifySourceStreamsStates(stream_data_1);
1003 EXPECT_EQ(stream_0_length + stream_1_length, TotalBytesReceived()); 987 VerifySourceStreamsStates(stream_data_2);
1004 988
1005 std::string disk_data, expected_data; 989 EXPECT_EQ(stream_0_length + stream_1_length + stream_2_length,
1006 EXPECT_TRUE(base::ReadFileToString(download_file_->FullPath(), &disk_data)); 990 TotalBytesReceived());
1007 expected_data.append(kTestData1).append(kTestData2).append(kTestData4);
1008 expected_data = expected_data.substr(0, stream_0_length + stream_1_length);
1009 EXPECT_EQ(expected_data, disk_data);
1010
1011 // Finish the second stream.
1012 // TODO(xingliu): Refactor test code to deal with unfinished streams.
1013 scoped_refptr<net::IOBuffer> data = new net::IOBuffer(strlen(kTestData5));
1014 size_t size;
1015 input_stream_1_->Read(&data, &size);
1016 991
1017 download_file_->Cancel(); 992 download_file_->Cancel();
1018 DestroyDownloadFile(0, false); 993 DestroyDownloadFile(0, false);
1019 } 994 }
1020 995
1021 // Two streams write to one sink, the first stream writes the whole file before 996 // Activate and deplete one stream, later add the second stream.
1022 // the seconds stream was able to start
1023 TEST_F(DownloadFileTest, MutipleStreamsFirstStreamWriteAllData) { 997 TEST_F(DownloadFileTest, MutipleStreamsFirstStreamWriteAllData) {
1024 PrepareMultipleStreams(true, true, 0); 998 int64_t stream_0_length = GetBuffersLength(kTestData8, 4);
1025 int64_t stream_0_length = 999
1026 static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2) + 1000 ASSERT_TRUE(CreateDownloadFile(0, DownloadSaveInfo::kLengthFullContent, true,
1027 strlen(kTestData4) + strlen(kTestData5)); 1001 true, DownloadItem::ReceivedSlices()));
1028 int64_t stream_1_length = 1002
1029 static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5)); 1003 PrepareStream(&input_stream_, 0, false, true, kTestData8, 4);
1004
1005 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
1006
1030 sink_callback_.Run(); 1007 sink_callback_.Run();
1031 base::RunLoop().RunUntilIdle(); 1008 base::RunLoop().RunUntilIdle();
1032 1009
1033 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); 1010 // Add another stream, the file is already closed, so nothing should be
1011 // called.
1012 EXPECT_FALSE(download_file_->InProgress());
1034 1013
1014 additional_streams_[0] = new StrictMock<MockByteStreamReader>();
1035 download_file_->AddByteStream( 1015 download_file_->AddByteStream(
1036 std::unique_ptr<MockByteStreamReader>(input_stream_1_), 1016 std::unique_ptr<MockByteStreamReader>(additional_streams_[0]),
1037 stream_0_length - stream_1_length); 1017 stream_0_length - 1, DownloadSaveInfo::kLengthFullContent);
1038 base::RunLoop().RunUntilIdle(); 1018 base::RunLoop().RunUntilIdle();
1039 1019
1040 SourceStreamTestData stream_data_0(0, stream_0_length, true); 1020 SourceStreamTestData stream_data_0(0, stream_0_length, true);
1041 SourceStreamTestData stream_data_1(stream_0_length - stream_1_length, 0, 1021 SourceStreamTestData stream_data_1(stream_0_length - 1, 0, false);
1042 true);
1043 VerifySourceStreamsStates(stream_data_0); 1022 VerifySourceStreamsStates(stream_data_0);
1044 VerifySourceStreamsStates(stream_data_1); 1023 VerifySourceStreamsStates(stream_data_1);
1045 EXPECT_EQ(stream_0_length, TotalBytesReceived()); 1024 EXPECT_EQ(stream_0_length, TotalBytesReceived());
1046 1025
1047 DestroyDownloadFile(0); 1026 DestroyDownloadFile(0);
1048 } 1027 }
1049 1028
1050 } // namespace content 1029 } // namespace content
OLDNEW
« 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