| 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 <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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |