| 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 |
| 11 #include "base/files/file.h" | 11 #include "base/files/file.h" |
| 12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/memory/ptr_util.h" |
| 14 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
| 15 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 16 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/test/test_file_util.h" | 18 #include "base/test/test_file_util.h" |
| 18 #include "base/threading/thread_task_runner_handle.h" | 19 #include "base/threading/thread_task_runner_handle.h" |
| 19 #include "build/build_config.h" | 20 #include "build/build_config.h" |
| 20 #include "content/browser/byte_stream.h" | 21 #include "content/browser/byte_stream.h" |
| 21 #include "content/browser/download/download_create_info.h" | 22 #include "content/browser/download/download_create_info.h" |
| 22 #include "content/browser/download/download_destination_observer.h" | 23 #include "content/browser/download/download_destination_observer.h" |
| 23 #include "content/browser/download/download_file_impl.h" | 24 #include "content/browser/download/download_file_impl.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 enum DownloadFileRenameMethodType { RENAME_AND_UNIQUIFY, RENAME_AND_ANNOTATE }; | 97 enum DownloadFileRenameMethodType { RENAME_AND_UNIQUIFY, RENAME_AND_ANNOTATE }; |
| 97 | 98 |
| 98 // This is a test DownloadFileImpl that has no retry delay and, on Posix, | 99 // This is a test DownloadFileImpl that has no retry delay and, on Posix, |
| 99 // retries renames failed due to ACCESS_DENIED. | 100 // retries renames failed due to ACCESS_DENIED. |
| 100 class TestDownloadFileImpl : public DownloadFileImpl { | 101 class TestDownloadFileImpl : public DownloadFileImpl { |
| 101 public: | 102 public: |
| 102 TestDownloadFileImpl(std::unique_ptr<DownloadSaveInfo> save_info, | 103 TestDownloadFileImpl(std::unique_ptr<DownloadSaveInfo> save_info, |
| 103 const base::FilePath& default_downloads_directory, | 104 const base::FilePath& default_downloads_directory, |
| 104 std::unique_ptr<ByteStreamReader> stream, | 105 std::unique_ptr<ByteStreamReader> stream, |
| 105 const net::NetLogWithSource& net_log, | 106 const net::NetLogWithSource& net_log, |
| 107 bool is_sparse_file, |
| 106 base::WeakPtr<DownloadDestinationObserver> observer) | 108 base::WeakPtr<DownloadDestinationObserver> observer) |
| 107 : DownloadFileImpl(std::move(save_info), | 109 : DownloadFileImpl(std::move(save_info), |
| 108 default_downloads_directory, | 110 default_downloads_directory, |
| 109 std::move(stream), | 111 std::move(stream), |
| 110 net_log, | 112 net_log, |
| 113 is_sparse_file, |
| 111 observer) {} | 114 observer) {} |
| 112 | 115 |
| 113 protected: | 116 protected: |
| 114 base::TimeDelta GetRetryDelayForFailedRename(int attempt_count) override { | 117 base::TimeDelta GetRetryDelayForFailedRename(int attempt_count) override { |
| 115 return base::TimeDelta::FromMilliseconds(0); | 118 return base::TimeDelta::FromMilliseconds(0); |
| 116 } | 119 } |
| 117 | 120 |
| 118 #if !defined(OS_WIN) | 121 #if !defined(OS_WIN) |
| 119 // On Posix, we don't encounter transient errors during renames, except | 122 // On Posix, we don't encounter transient errors during renames, except |
| 120 // possibly EAGAIN, which is difficult to replicate reliably. So we resort to | 123 // possibly EAGAIN, which is difficult to replicate reliably. So we resort to |
| 121 // simulating a transient error using ACCESS_DENIED instead. | 124 // simulating a transient error using ACCESS_DENIED instead. |
| 122 bool ShouldRetryFailedRename(DownloadInterruptReason reason) override { | 125 bool ShouldRetryFailedRename(DownloadInterruptReason reason) override { |
| 123 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; | 126 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; |
| 124 } | 127 } |
| 125 #endif | 128 #endif |
| 126 }; | 129 }; |
| 127 | 130 |
| 128 } // namespace | 131 } // namespace |
| 129 | 132 |
| 130 class DownloadFileTest : public testing::Test { | 133 class DownloadFileTest : public testing::Test { |
| 131 public: | 134 public: |
| 132 static const char kTestData1[]; | 135 static const char kTestData1[]; |
| 133 static const char kTestData2[]; | 136 static const char kTestData2[]; |
| 134 static const char kTestData3[]; | 137 static const char kTestData3[]; |
| 138 static const char kTestData4[]; |
| 139 static const char kTestData5[]; |
| 135 static const char kDataHash[]; | 140 static const char kDataHash[]; |
| 136 static const char kEmptyHash[]; | 141 static const char kEmptyHash[]; |
| 137 static const uint32_t kDummyDownloadId; | 142 static const uint32_t kDummyDownloadId; |
| 138 static const int kDummyChildId; | 143 static const int kDummyChildId; |
| 139 static const int kDummyRequestId; | 144 static const int kDummyRequestId; |
| 140 | 145 |
| 141 DownloadFileTest() | 146 DownloadFileTest() |
| 142 : observer_(new StrictMock<MockDownloadDestinationObserver>), | 147 : observer_(new StrictMock<MockDownloadDestinationObserver>), |
| 143 observer_factory_(observer_.get()), | 148 observer_factory_(observer_.get()), |
| 144 input_stream_(NULL), | 149 input_stream_(NULL), |
| 150 input_stream_1_(NULL), |
| 145 bytes_(-1), | 151 bytes_(-1), |
| 146 bytes_per_sec_(-1) {} | 152 bytes_per_sec_(-1) {} |
| 147 | 153 |
| 148 ~DownloadFileTest() override {} | 154 ~DownloadFileTest() override {} |
| 149 | 155 |
| 150 void SetUpdateDownloadInfo(int64_t bytes, int64_t bytes_per_sec) { | 156 void SetUpdateDownloadInfo(int64_t bytes, int64_t bytes_per_sec) { |
| 151 bytes_ = bytes; | 157 bytes_ = bytes; |
| 152 bytes_per_sec_ = bytes_per_sec; | 158 bytes_per_sec_ = bytes_per_sec; |
| 153 } | 159 } |
| 154 | 160 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 167 sink_callback_ = sink_callback; | 173 sink_callback_ = sink_callback; |
| 168 } | 174 } |
| 169 | 175 |
| 170 void SetInterruptReasonCallback(const base::Closure& closure, | 176 void SetInterruptReasonCallback(const base::Closure& closure, |
| 171 DownloadInterruptReason* reason_p, | 177 DownloadInterruptReason* reason_p, |
| 172 DownloadInterruptReason reason) { | 178 DownloadInterruptReason reason) { |
| 173 *reason_p = reason; | 179 *reason_p = reason; |
| 174 closure.Run(); | 180 closure.Run(); |
| 175 } | 181 } |
| 176 | 182 |
| 177 bool CreateDownloadFile(int offset, bool calculate_hash) { | 183 bool CreateDownloadFile(int offset, |
| 184 bool calculate_hash, |
| 185 bool is_sparse_file = false) { |
| 178 // There can be only one. | 186 // There can be only one. |
| 179 DCHECK(!download_file_.get()); | 187 DCHECK(!download_file_.get()); |
| 180 | 188 |
| 181 input_stream_ = new StrictMock<MockByteStreamReader>(); | 189 input_stream_ = new StrictMock<MockByteStreamReader>(); |
| 182 | 190 |
| 183 // TODO: Need to actually create a function that'll set the variables | 191 // TODO: Need to actually create a function that'll set the variables |
| 184 // based on the inputs from the callback. | 192 // based on the inputs from the callback. |
| 185 EXPECT_CALL(*input_stream_, RegisterCallback(_)) | 193 EXPECT_CALL(*input_stream_, RegisterCallback(_)) |
| 186 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback)) | 194 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback)) |
| 187 .RetiresOnSaturation(); | 195 .RetiresOnSaturation(); |
| 188 | 196 |
| 189 std::unique_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); | 197 std::unique_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); |
| 190 download_file_.reset(new TestDownloadFileImpl( | 198 download_file_.reset(new TestDownloadFileImpl( |
| 191 std::move(save_info), base::FilePath(), | 199 std::move(save_info), base::FilePath(), |
| 192 std::unique_ptr<ByteStreamReader>(input_stream_), | 200 std::unique_ptr<ByteStreamReader>(input_stream_), |
| 193 net::NetLogWithSource(), observer_factory_.GetWeakPtr())); | 201 net::NetLogWithSource(), is_sparse_file, |
| 202 observer_factory_.GetWeakPtr())); |
| 194 | 203 |
| 195 EXPECT_CALL(*input_stream_, Read(_, _)) | 204 EXPECT_CALL(*input_stream_, Read(_, _)) |
| 196 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) | 205 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) |
| 197 .RetiresOnSaturation(); | 206 .RetiresOnSaturation(); |
| 198 | 207 |
| 199 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this); | 208 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this); |
| 200 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE; | 209 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 201 base::RunLoop loop_runner; | 210 base::RunLoop loop_runner; |
| 202 download_file_->Initialize(base::Bind( | 211 download_file_->Initialize(base::Bind( |
| 203 &DownloadFileTest::SetInterruptReasonCallback, | 212 &DownloadFileTest::SetInterruptReasonCallback, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 214 // Make sure the data has been properly written to disk. | 223 // Make sure the data has been properly written to disk. |
| 215 std::string disk_data; | 224 std::string disk_data; |
| 216 EXPECT_TRUE(base::ReadFileToString(download_file_->FullPath(), &disk_data)); | 225 EXPECT_TRUE(base::ReadFileToString(download_file_->FullPath(), &disk_data)); |
| 217 EXPECT_EQ(expected_data_, disk_data); | 226 EXPECT_EQ(expected_data_, disk_data); |
| 218 | 227 |
| 219 // Make sure the Browser and File threads outlive the DownloadFile | 228 // Make sure the Browser and File threads outlive the DownloadFile |
| 220 // to satisfy thread checks inside it. | 229 // to satisfy thread checks inside it. |
| 221 download_file_.reset(); | 230 download_file_.reset(); |
| 222 } | 231 } |
| 223 | 232 |
| 224 // Setup the stream to do be a data append; don't actually trigger | 233 // Setup the stream to append data or write from |offset| to the file. |
| 225 // the callback or do verifications. | 234 // Don't actually trigger the callback or do verifications. |
| 226 void SetupDataAppend(const char **data_chunks, size_t num_chunks, | 235 void SetupDataAppend(const char** data_chunks, |
| 227 ::testing::Sequence s) { | 236 size_t num_chunks, |
| 228 DCHECK(input_stream_); | 237 MockByteStreamReader* stream_reader, |
| 238 ::testing::Sequence s, |
| 239 int64_t offset = -1) { |
| 240 DCHECK(stream_reader); |
| 241 size_t current_pos = static_cast<size_t>(offset); |
| 229 for (size_t i = 0; i < num_chunks; i++) { | 242 for (size_t i = 0; i < num_chunks; i++) { |
| 230 const char *source_data = data_chunks[i]; | 243 const char *source_data = data_chunks[i]; |
| 231 size_t length = strlen(source_data); | 244 size_t length = strlen(source_data); |
| 232 scoped_refptr<net::IOBuffer> data = new net::IOBuffer(length); | 245 scoped_refptr<net::IOBuffer> data = new net::IOBuffer(length); |
| 233 memcpy(data->data(), source_data, length); | 246 memcpy(data->data(), source_data, length); |
| 234 EXPECT_CALL(*input_stream_, Read(_, _)) | 247 EXPECT_CALL(*stream_reader, Read(_, _)) |
| 235 .InSequence(s) | 248 .InSequence(s) |
| 236 .WillOnce(DoAll(SetArgPointee<0>(data), | 249 .WillOnce(DoAll(SetArgPointee<0>(data), SetArgPointee<1>(length), |
| 237 SetArgPointee<1>(length), | |
| 238 Return(ByteStreamReader::STREAM_HAS_DATA))) | 250 Return(ByteStreamReader::STREAM_HAS_DATA))) |
| 239 .RetiresOnSaturation(); | 251 .RetiresOnSaturation(); |
| 240 expected_data_ += source_data; | 252 |
| 253 if (offset < 0) { |
| 254 // Append data. |
| 255 expected_data_ += source_data; |
| 256 continue; |
| 257 } |
| 258 |
| 259 // Write from offset. May fill holes with '\0'. |
| 260 size_t new_len = current_pos + length; |
| 261 if (new_len > expected_data_.size()) |
| 262 expected_data_.append(new_len - expected_data_.size(), '\0'); |
| 263 expected_data_.replace(current_pos, length, source_data); |
| 264 current_pos += length; |
| 241 } | 265 } |
| 242 } | 266 } |
| 243 | 267 |
| 244 void VerifyStreamAndSize() { | 268 void VerifyStreamAndSize() { |
| 245 ::testing::Mock::VerifyAndClearExpectations(input_stream_); | 269 ::testing::Mock::VerifyAndClearExpectations(input_stream_); |
| 246 int64_t size; | 270 int64_t size; |
| 247 EXPECT_TRUE(base::GetFileSize(download_file_->FullPath(), &size)); | 271 EXPECT_TRUE(base::GetFileSize(download_file_->FullPath(), &size)); |
| 248 EXPECT_EQ(expected_data_.size(), static_cast<size_t>(size)); | 272 EXPECT_EQ(expected_data_.size(), static_cast<size_t>(size)); |
| 249 } | 273 } |
| 250 | 274 |
| 251 // TODO(rdsmith): Manage full percentage issues properly. | 275 // TODO(rdsmith): Manage full percentage issues properly. |
| 252 void AppendDataToFile(const char **data_chunks, size_t num_chunks) { | 276 void AppendDataToFile(const char **data_chunks, size_t num_chunks) { |
| 253 ::testing::Sequence s1; | 277 ::testing::Sequence s1; |
| 254 SetupDataAppend(data_chunks, num_chunks, s1); | 278 SetupDataAppend(data_chunks, num_chunks, input_stream_, s1); |
| 255 EXPECT_CALL(*input_stream_, Read(_, _)) | 279 EXPECT_CALL(*input_stream_, Read(_, _)) |
| 256 .InSequence(s1) | 280 .InSequence(s1) |
| 257 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) | 281 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) |
| 258 .RetiresOnSaturation(); | 282 .RetiresOnSaturation(); |
| 259 sink_callback_.Run(); | 283 sink_callback_.Run(); |
| 260 VerifyStreamAndSize(); | 284 VerifyStreamAndSize(); |
| 261 } | 285 } |
| 262 | 286 |
| 263 void SetupFinishStream(DownloadInterruptReason interrupt_reason, | 287 void SetupFinishStream(DownloadInterruptReason interrupt_reason, |
| 264 ::testing::Sequence s) { | 288 MockByteStreamReader* stream_reader, |
| 265 EXPECT_CALL(*input_stream_, Read(_, _)) | 289 ::testing::Sequence s) { |
| 290 EXPECT_CALL(*stream_reader, Read(_, _)) |
| 266 .InSequence(s) | 291 .InSequence(s) |
| 267 .WillOnce(Return(ByteStreamReader::STREAM_COMPLETE)) | 292 .WillOnce(Return(ByteStreamReader::STREAM_COMPLETE)) |
| 268 .RetiresOnSaturation(); | 293 .RetiresOnSaturation(); |
| 269 EXPECT_CALL(*input_stream_, GetStatus()) | 294 EXPECT_CALL(*stream_reader, GetStatus()) |
| 270 .InSequence(s) | 295 .InSequence(s) |
| 271 .WillOnce(Return(interrupt_reason)) | 296 .WillOnce(Return(interrupt_reason)) |
| 272 .RetiresOnSaturation(); | 297 .RetiresOnSaturation(); |
| 273 EXPECT_CALL(*input_stream_, RegisterCallback(_)) | 298 EXPECT_CALL(*stream_reader, RegisterCallback(_)).RetiresOnSaturation(); |
| 274 .RetiresOnSaturation(); | |
| 275 } | 299 } |
| 276 | 300 |
| 277 void FinishStream(DownloadInterruptReason interrupt_reason, | 301 void FinishStream(DownloadInterruptReason interrupt_reason, |
| 278 bool check_observer, | 302 bool check_observer, |
| 279 const std::string& expected_hash) { | 303 const std::string& expected_hash) { |
| 280 ::testing::Sequence s1; | 304 ::testing::Sequence s1; |
| 281 SetupFinishStream(interrupt_reason, s1); | 305 SetupFinishStream(interrupt_reason, input_stream_, s1); |
| 282 sink_callback_.Run(); | 306 sink_callback_.Run(); |
| 283 VerifyStreamAndSize(); | 307 VerifyStreamAndSize(); |
| 284 if (check_observer) { | 308 if (check_observer) { |
| 285 EXPECT_CALL(*(observer_.get()), | 309 EXPECT_CALL(*(observer_.get()), |
| 286 MockDestinationCompleted(_, expected_hash)); | 310 MockDestinationCompleted(_, expected_hash)); |
| 287 base::RunLoop().RunUntilIdle(); | 311 base::RunLoop().RunUntilIdle(); |
| 288 ::testing::Mock::VerifyAndClearExpectations(observer_.get()); | 312 ::testing::Mock::VerifyAndClearExpectations(observer_.get()); |
| 289 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _)) | 313 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _)) |
| 290 .Times(AnyNumber()) | 314 .Times(AnyNumber()) |
| 291 .WillRepeatedly( | 315 .WillRepeatedly( |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 base::Bind(&DownloadFileTest::SetRenameResult, | 369 base::Bind(&DownloadFileTest::SetRenameResult, |
| 346 base::Unretained(this), | 370 base::Unretained(this), |
| 347 loop_runner.QuitClosure(), | 371 loop_runner.QuitClosure(), |
| 348 &result_reason, | 372 &result_reason, |
| 349 result_path_p); | 373 result_path_p); |
| 350 InvokeRenameMethod(method, full_path, completion_callback); | 374 InvokeRenameMethod(method, full_path, completion_callback); |
| 351 loop_runner.Run(); | 375 loop_runner.Run(); |
| 352 return result_reason; | 376 return result_reason; |
| 353 } | 377 } |
| 354 | 378 |
| 379 // Prepare two byte streams to write to the same file sink. |
| 380 void PrepareMultipleStreams() { |
| 381 // Create a sparse file. |
| 382 ASSERT_TRUE(CreateDownloadFile(0, true, true)); |
| 383 base::FilePath initial_path(download_file_->FullPath()); |
| 384 EXPECT_TRUE(base::PathExists(initial_path)); |
| 385 DCHECK(download_file_); |
| 386 |
| 387 const char* stream_0_data[] = {kTestData1, kTestData2}; |
| 388 const char* stream_1_data[] = {kTestData4, kTestData5}; |
| 389 size_t stream_1_offset = strlen(kTestData1) + strlen(kTestData2); |
| 390 |
| 391 // Register second SourceStream entry for the second stream. |
| 392 // The first stream should be registered in ctor of DownloadFile. |
| 393 DownloadFileImpl::SourceStreams& source_streams = |
| 394 DownloadFileTest::source_streams(); |
| 395 EXPECT_EQ(static_cast<size_t>(1), source_streams.size()); |
| 396 source_streams[stream_1_offset] = |
| 397 base::MakeUnique<DownloadFileImpl::SourceStream>(stream_1_offset, 0); |
| 398 |
| 399 // Create the second byte stream. Will be moved to DownloadFile. |
| 400 input_stream_1_ = new MockByteStreamReader(); |
| 401 |
| 402 // Fill up two streams and setup expectation. |
| 403 ::testing::Sequence s0; |
| 404 ::testing::Sequence s1; |
| 405 SetupDataAppend(stream_1_data, 2, input_stream_1_, s1, stream_1_offset); |
| 406 SetupDataAppend(stream_0_data, 2, input_stream_, s0, 0); |
| 407 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_1_, s1); |
| 408 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_, s0); |
| 409 |
| 410 // Every ByteStreamReader should call RegisterCallback twice. |
| 411 // One to set the callback, the other to null the callback. |
| 412 EXPECT_CALL(*input_stream_1_, RegisterCallback(_)).RetiresOnSaturation(); |
| 413 } |
| 414 |
| 415 DownloadFileImpl::SourceStreams& source_streams() { |
| 416 DCHECK(download_file_); |
| 417 return download_file_->source_streams_; |
| 418 } |
| 419 |
| 420 int64_t TotalBytesReceived() const { |
| 421 DCHECK(download_file_); |
| 422 return download_file_->TotalBytesReceived(); |
| 423 } |
| 424 |
| 355 std::unique_ptr<StrictMock<MockDownloadDestinationObserver>> observer_; | 425 std::unique_ptr<StrictMock<MockDownloadDestinationObserver>> observer_; |
| 356 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_; | 426 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_; |
| 357 | 427 |
| 358 // DownloadFile instance we are testing. | 428 // DownloadFile instance we are testing. |
| 359 std::unique_ptr<DownloadFile> download_file_; | 429 std::unique_ptr<DownloadFileImpl> download_file_; |
| 360 | 430 |
| 361 // Stream for sending data into the download file. | 431 // Stream for sending data into the download file. |
| 362 // Owned by download_file_; will be alive for lifetime of download_file_. | 432 // Owned by download_file_; will be alive for lifetime of download_file_. |
| 363 StrictMock<MockByteStreamReader>* input_stream_; | 433 StrictMock<MockByteStreamReader>* input_stream_; |
| 364 | 434 |
| 435 // A second byte stream to test multiple stream write. |
| 436 MockByteStreamReader* input_stream_1_; |
| 437 |
| 365 // Sink callback data for stream. | 438 // Sink callback data for stream. |
| 366 base::Closure sink_callback_; | 439 base::Closure sink_callback_; |
| 367 | 440 |
| 368 // Latest update sent to the observer. | 441 // Latest update sent to the observer. |
| 369 int64_t bytes_; | 442 int64_t bytes_; |
| 370 int64_t bytes_per_sec_; | 443 int64_t bytes_per_sec_; |
| 371 | 444 |
| 372 private: | 445 private: |
| 373 void SetRenameResult(const base::Closure& closure, | 446 void SetRenameResult(const base::Closure& closure, |
| 374 DownloadInterruptReason* reason_p, | 447 DownloadInterruptReason* reason_p, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 // the value parameter. | 485 // the value parameter. |
| 413 INSTANTIATE_TEST_CASE_P(DownloadFile, | 486 INSTANTIATE_TEST_CASE_P(DownloadFile, |
| 414 DownloadFileTestWithRename, | 487 DownloadFileTestWithRename, |
| 415 ::testing::Values(RENAME_AND_ANNOTATE, | 488 ::testing::Values(RENAME_AND_ANNOTATE, |
| 416 RENAME_AND_UNIQUIFY)); | 489 RENAME_AND_UNIQUIFY)); |
| 417 | 490 |
| 418 const char DownloadFileTest::kTestData1[] = | 491 const char DownloadFileTest::kTestData1[] = |
| 419 "Let's write some data to the file!\n"; | 492 "Let's write some data to the file!\n"; |
| 420 const char DownloadFileTest::kTestData2[] = "Writing more data.\n"; | 493 const char DownloadFileTest::kTestData2[] = "Writing more data.\n"; |
| 421 const char DownloadFileTest::kTestData3[] = "Final line."; | 494 const char DownloadFileTest::kTestData3[] = "Final line."; |
| 495 const char DownloadFileTest::kTestData4[] = "abcdefg"; |
| 496 const char DownloadFileTest::kTestData5[] = "01234"; |
| 422 const char DownloadFileTest::kDataHash[] = | 497 const char DownloadFileTest::kDataHash[] = |
| 423 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8"; | 498 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8"; |
| 424 const char DownloadFileTest::kEmptyHash[] = | 499 const char DownloadFileTest::kEmptyHash[] = |
| 425 "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"; | 500 "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"; |
| 426 | 501 |
| 427 const uint32_t DownloadFileTest::kDummyDownloadId = 23; | 502 const uint32_t DownloadFileTest::kDummyDownloadId = 23; |
| 428 const int DownloadFileTest::kDummyChildId = 3; | 503 const int DownloadFileTest::kDummyChildId = 3; |
| 429 const int DownloadFileTest::kDummyRequestId = 67; | 504 const int DownloadFileTest::kDummyRequestId = 67; |
| 430 | 505 |
| 431 // Rename the file before any data is downloaded, after some has, after it all | 506 // Rename the file before any data is downloaded, after some has, after it all |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 DestroyDownloadFile(0); | 817 DestroyDownloadFile(0); |
| 743 } | 818 } |
| 744 | 819 |
| 745 TEST_F(DownloadFileTest, StreamNonEmptySuccess) { | 820 TEST_F(DownloadFileTest, StreamNonEmptySuccess) { |
| 746 ASSERT_TRUE(CreateDownloadFile(0, true)); | 821 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 747 base::FilePath initial_path(download_file_->FullPath()); | 822 base::FilePath initial_path(download_file_->FullPath()); |
| 748 EXPECT_TRUE(base::PathExists(initial_path)); | 823 EXPECT_TRUE(base::PathExists(initial_path)); |
| 749 | 824 |
| 750 const char* chunks1[] = { kTestData1, kTestData2 }; | 825 const char* chunks1[] = { kTestData1, kTestData2 }; |
| 751 ::testing::Sequence s1; | 826 ::testing::Sequence s1; |
| 752 SetupDataAppend(chunks1, 2, s1); | 827 SetupDataAppend(chunks1, 2, input_stream_, s1); |
| 753 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, s1); | 828 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_, s1); |
| 754 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); | 829 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); |
| 755 sink_callback_.Run(); | 830 sink_callback_.Run(); |
| 756 VerifyStreamAndSize(); | 831 VerifyStreamAndSize(); |
| 757 base::RunLoop().RunUntilIdle(); | 832 base::RunLoop().RunUntilIdle(); |
| 758 DestroyDownloadFile(0); | 833 DestroyDownloadFile(0); |
| 759 } | 834 } |
| 760 | 835 |
| 761 TEST_F(DownloadFileTest, StreamNonEmptyError) { | 836 TEST_F(DownloadFileTest, StreamNonEmptyError) { |
| 762 ASSERT_TRUE(CreateDownloadFile(0, true)); | 837 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 763 base::FilePath initial_path(download_file_->FullPath()); | 838 base::FilePath initial_path(download_file_->FullPath()); |
| 764 EXPECT_TRUE(base::PathExists(initial_path)); | 839 EXPECT_TRUE(base::PathExists(initial_path)); |
| 765 | 840 |
| 766 const char* chunks1[] = { kTestData1, kTestData2 }; | 841 const char* chunks1[] = { kTestData1, kTestData2 }; |
| 767 ::testing::Sequence s1; | 842 ::testing::Sequence s1; |
| 768 SetupDataAppend(chunks1, 2, s1); | 843 SetupDataAppend(chunks1, 2, input_stream_, s1); |
| 769 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, s1); | 844 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, |
| 845 input_stream_, s1); |
| 770 | 846 |
| 771 EXPECT_CALL(*(observer_.get()), | 847 EXPECT_CALL(*(observer_.get()), |
| 772 MockDestinationError( | 848 MockDestinationError( |
| 773 DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, _, _)) | 849 DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, _, _)) |
| 774 .WillOnce(InvokeWithoutArgs( | 850 .WillOnce(InvokeWithoutArgs( |
| 775 this, &DownloadFileTest::ConfirmUpdateDownloadInfo)); | 851 this, &DownloadFileTest::ConfirmUpdateDownloadInfo)); |
| 776 | 852 |
| 777 // If this next EXPECT_CALL fails flakily, it's probably a real failure. | 853 // If this next EXPECT_CALL fails flakily, it's probably a real failure. |
| 778 // We'll be getting a stream of UpdateDownload calls from the timer, and | 854 // We'll be getting a stream of UpdateDownload calls from the timer, and |
| 779 // the last one may have the correct information even if the failure | 855 // the last one may have the correct information even if the failure |
| 780 // doesn't produce an update, as the timer update may have triggered at the | 856 // doesn't produce an update, as the timer update may have triggered at the |
| 781 // same time. | 857 // same time. |
| 782 EXPECT_CALL(*(observer_.get()), | 858 EXPECT_CALL(*(observer_.get()), |
| 783 CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2), _)); | 859 CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2), _)); |
| 784 | 860 |
| 785 sink_callback_.Run(); | 861 sink_callback_.Run(); |
| 786 base::RunLoop().RunUntilIdle(); | 862 base::RunLoop().RunUntilIdle(); |
| 787 VerifyStreamAndSize(); | 863 VerifyStreamAndSize(); |
| 788 DestroyDownloadFile(0); | 864 DestroyDownloadFile(0); |
| 789 } | 865 } |
| 790 | 866 |
| 867 // Tests for concurrent streams handling, used for parallel download. |
| 868 // |
| 869 // Activate both streams at the same time. |
| 870 TEST_F(DownloadFileTest, MutipleStreamsWrite) { |
| 871 PrepareMultipleStreams(); |
| 872 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); |
| 873 |
| 874 DownloadFileImpl::SourceStreams& source_streams = |
| 875 DownloadFileTest::source_streams(); |
| 876 int64_t stream_0_length = |
| 877 static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2)); |
| 878 int64_t stream_1_length = |
| 879 static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5)); |
| 880 DownloadFileImpl::SourceStream* stream0 = source_streams[0].get(); |
| 881 DownloadFileImpl::SourceStream* stream1 = |
| 882 source_streams[stream_0_length].get(); |
| 883 |
| 884 download_file_->AddByteStream( |
| 885 std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length); |
| 886 sink_callback_.Run(); |
| 887 base::RunLoop().RunUntilIdle(); |
| 888 |
| 889 EXPECT_EQ(stream_0_length, stream0->bytes_received()); |
| 890 EXPECT_EQ(stream_1_length, stream1->bytes_received()); |
| 891 EXPECT_TRUE(stream0->is_finished()); |
| 892 EXPECT_TRUE(stream1->is_finished()); |
| 893 EXPECT_EQ(0, stream0->offset()); |
| 894 EXPECT_EQ(stream_0_length, stream1->offset()); |
| 895 EXPECT_EQ(stream0->bytes_received() + stream1->bytes_received(), |
| 896 TotalBytesReceived()); |
| 897 |
| 898 DestroyDownloadFile(0); |
| 899 } |
| 900 |
| 901 // Activate and deplete one stream, later add the second stream. |
| 902 TEST_F(DownloadFileTest, MutipleStreamsOneStreamFirst) { |
| 903 PrepareMultipleStreams(); |
| 904 |
| 905 DownloadFileImpl::SourceStreams& source_streams = |
| 906 DownloadFileTest::source_streams(); |
| 907 int64_t stream_0_length = |
| 908 static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2)); |
| 909 int64_t stream_1_length = |
| 910 static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5)); |
| 911 DownloadFileImpl::SourceStream* stream0 = source_streams[0].get(); |
| 912 DownloadFileImpl::SourceStream* stream1 = |
| 913 source_streams[stream_0_length].get(); |
| 914 |
| 915 // Deplete the first stream. |
| 916 sink_callback_.Run(); |
| 917 base::RunLoop().RunUntilIdle(); |
| 918 EXPECT_EQ(stream_0_length, stream0->bytes_received()); |
| 919 EXPECT_EQ(0, stream1->bytes_received()); |
| 920 EXPECT_TRUE(stream0->is_finished()); |
| 921 EXPECT_FALSE(stream1->is_finished()); |
| 922 EXPECT_EQ(stream_0_length, stream1->offset()); |
| 923 EXPECT_EQ(stream0->bytes_received(), TotalBytesReceived()); |
| 924 |
| 925 // Won't inform the observer utill the second stream is depleted. |
| 926 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); |
| 927 |
| 928 // Drain the second stream after the first stream is depleted. |
| 929 download_file_->AddByteStream( |
| 930 std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length); |
| 931 base::RunLoop().RunUntilIdle(); |
| 932 |
| 933 EXPECT_EQ(stream_0_length, stream0->bytes_received()); |
| 934 EXPECT_EQ(stream_1_length, stream1->bytes_received()); |
| 935 EXPECT_TRUE(stream0->is_finished()); |
| 936 EXPECT_TRUE(stream1->is_finished()); |
| 937 EXPECT_EQ(0, stream0->offset()); |
| 938 EXPECT_EQ(stream_0_length, stream1->offset()); |
| 939 EXPECT_EQ(stream0->bytes_received() + stream1->bytes_received(), |
| 940 TotalBytesReceived()); |
| 941 |
| 942 DestroyDownloadFile(0); |
| 943 } |
| 944 |
| 791 } // namespace content | 945 } // namespace content |
| OLD | NEW |