| 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 #include <utility> | 8 #include <utility> |
| 9 #include <vector> |
| 8 | 10 |
| 9 #include "base/files/file.h" | 11 #include "base/files/file.h" |
| 10 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 11 #include "base/location.h" | 13 #include "base/location.h" |
| 12 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
| 13 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
| 14 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/test/test_file_util.h" | 17 #include "base/test/test_file_util.h" |
| 16 #include "base/thread_task_runner_handle.h" | 18 #include "base/thread_task_runner_handle.h" |
| 17 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 18 #include "content/browser/browser_thread_impl.h" | 20 #include "content/browser/browser_thread_impl.h" |
| 19 #include "content/browser/byte_stream.h" | 21 #include "content/browser/byte_stream.h" |
| 20 #include "content/browser/download/download_create_info.h" | 22 #include "content/browser/download/download_create_info.h" |
| 23 #include "content/browser/download/download_destination_observer.h" |
| 21 #include "content/browser/download/download_file_impl.h" | 24 #include "content/browser/download/download_file_impl.h" |
| 22 #include "content/browser/download/download_request_handle.h" | 25 #include "content/browser/download/download_request_handle.h" |
| 23 #include "content/public/browser/download_destination_observer.h" | |
| 24 #include "content/public/browser/download_interrupt_reasons.h" | 26 #include "content/public/browser/download_interrupt_reasons.h" |
| 25 #include "content/public/browser/download_manager.h" | 27 #include "content/public/browser/download_manager.h" |
| 26 #include "content/public/test/mock_download_manager.h" | 28 #include "content/public/test/mock_download_manager.h" |
| 27 #include "net/base/file_stream.h" | 29 #include "net/base/file_stream.h" |
| 28 #include "net/base/mock_file_stream.h" | 30 #include "net/base/mock_file_stream.h" |
| 29 #include "net/base/net_errors.h" | 31 #include "net/base/net_errors.h" |
| 30 #include "testing/gmock/include/gmock/gmock.h" | 32 #include "testing/gmock/include/gmock/gmock.h" |
| 31 #include "testing/gtest/include/gtest/gtest.h" | 33 #include "testing/gtest/include/gtest/gtest.h" |
| 32 | 34 |
| 33 using ::testing::_; | 35 using ::testing::_; |
| 34 using ::testing::AnyNumber; | 36 using ::testing::AnyNumber; |
| 35 using ::testing::DoAll; | 37 using ::testing::DoAll; |
| 36 using ::testing::InSequence; | 38 using ::testing::InSequence; |
| 37 using ::testing::Return; | 39 using ::testing::Return; |
| 38 using ::testing::SetArgPointee; | 40 using ::testing::SetArgPointee; |
| 39 using ::testing::StrictMock; | 41 using ::testing::StrictMock; |
| 40 | 42 |
| 41 namespace content { | 43 namespace content { |
| 42 namespace { | 44 namespace { |
| 43 | 45 |
| 46 std::string GetHexEncodedHashValue(crypto::SecureHash* hash_state) { |
| 47 if (!hash_state) |
| 48 return std::string(); |
| 49 std::vector<char> hash_value(hash_state->GetHashLength()); |
| 50 hash_state->Finish(&hash_value.front(), hash_value.size()); |
| 51 return base::HexEncode(&hash_value.front(), hash_value.size()); |
| 52 } |
| 53 |
| 44 class MockByteStreamReader : public ByteStreamReader { | 54 class MockByteStreamReader : public ByteStreamReader { |
| 45 public: | 55 public: |
| 46 MockByteStreamReader() {} | 56 MockByteStreamReader() {} |
| 47 ~MockByteStreamReader() {} | 57 ~MockByteStreamReader() {} |
| 48 | 58 |
| 49 // ByteStream functions | 59 // ByteStream functions |
| 50 MOCK_METHOD2(Read, ByteStreamReader::StreamState( | 60 MOCK_METHOD2(Read, ByteStreamReader::StreamState( |
| 51 scoped_refptr<net::IOBuffer>*, size_t*)); | 61 scoped_refptr<net::IOBuffer>*, size_t*)); |
| 52 MOCK_CONST_METHOD0(GetStatus, int()); | 62 MOCK_CONST_METHOD0(GetStatus, int()); |
| 53 MOCK_METHOD1(RegisterCallback, void(const base::Closure&)); | 63 MOCK_METHOD1(RegisterCallback, void(const base::Closure&)); |
| 54 }; | 64 }; |
| 55 | 65 |
| 56 class MockDownloadDestinationObserver : public DownloadDestinationObserver { | 66 class MockDownloadDestinationObserver : public DownloadDestinationObserver { |
| 57 public: | 67 public: |
| 58 MOCK_METHOD3(DestinationUpdate, void(int64_t, int64_t, const std::string&)); | 68 MOCK_METHOD2(DestinationUpdate, void(int64_t, int64_t)); |
| 59 MOCK_METHOD1(DestinationError, void(DownloadInterruptReason)); | 69 void DestinationError(DownloadInterruptReason reason, |
| 60 MOCK_METHOD1(DestinationCompleted, void(const std::string&)); | 70 int64_t bytes_so_far, |
| 71 scoped_ptr<crypto::SecureHash> hash_state) override { |
| 72 MockDestinationError( |
| 73 reason, bytes_so_far, GetHexEncodedHashValue(hash_state.get())); |
| 74 } |
| 75 void DestinationCompleted( |
| 76 int64_t total_bytes, |
| 77 scoped_ptr<crypto::SecureHash> hash_state) override { |
| 78 MockDestinationCompleted(total_bytes, |
| 79 GetHexEncodedHashValue(hash_state.get())); |
| 80 } |
| 81 |
| 82 MOCK_METHOD3(MockDestinationError, |
| 83 void(DownloadInterruptReason, int64_t, const std::string&)); |
| 84 MOCK_METHOD2(MockDestinationCompleted, void(int64_t, const std::string&)); |
| 61 | 85 |
| 62 // Doesn't override any methods in the base class. Used to make sure | 86 // Doesn't override any methods in the base class. Used to make sure |
| 63 // that the last DestinationUpdate before a Destination{Completed,Error} | 87 // that the last DestinationUpdate before a Destination{Completed,Error} |
| 64 // had the right values. | 88 // had the right values. |
| 65 MOCK_METHOD3(CurrentUpdateStatus, void(int64_t, int64_t, const std::string&)); | 89 MOCK_METHOD2(CurrentUpdateStatus, void(int64_t, int64_t)); |
| 66 }; | 90 }; |
| 67 | 91 |
| 68 MATCHER(IsNullCallback, "") { return (arg.is_null()); } | 92 MATCHER(IsNullCallback, "") { return (arg.is_null()); } |
| 69 | 93 |
| 70 typedef void (DownloadFile::*DownloadFileRenameMethodType)( | 94 enum DownloadFileRenameMethodType { RENAME_AND_UNIQUIFY, RENAME_AND_ANNOTATE }; |
| 71 const base::FilePath&, | |
| 72 const DownloadFile::RenameCompletionCallback&); | |
| 73 | 95 |
| 74 // This is a test DownloadFileImpl that has no retry delay and, on Posix, | 96 // This is a test DownloadFileImpl that has no retry delay and, on Posix, |
| 75 // retries renames failed due to ACCESS_DENIED. | 97 // retries renames failed due to ACCESS_DENIED. |
| 76 class TestDownloadFileImpl : public DownloadFileImpl { | 98 class TestDownloadFileImpl : public DownloadFileImpl { |
| 77 public: | 99 public: |
| 78 TestDownloadFileImpl(const DownloadSaveInfo& save_info, | 100 TestDownloadFileImpl(scoped_ptr<DownloadSaveInfo> save_info, |
| 79 const base::FilePath& default_downloads_directory, | 101 const base::FilePath& default_downloads_directory, |
| 80 const GURL& url, | |
| 81 const GURL& referrer_url, | |
| 82 bool calculate_hash, | |
| 83 base::File file, | |
| 84 scoped_ptr<ByteStreamReader> stream, | 102 scoped_ptr<ByteStreamReader> stream, |
| 85 const net::BoundNetLog& bound_net_log, | 103 const net::BoundNetLog& bound_net_log, |
| 86 base::WeakPtr<DownloadDestinationObserver> observer) | 104 base::WeakPtr<DownloadDestinationObserver> observer) |
| 87 : DownloadFileImpl(save_info, | 105 : DownloadFileImpl(std::move(save_info), |
| 88 default_downloads_directory, | 106 default_downloads_directory, |
| 89 url, | |
| 90 referrer_url, | |
| 91 calculate_hash, | |
| 92 std::move(file), | |
| 93 std::move(stream), | 107 std::move(stream), |
| 94 bound_net_log, | 108 bound_net_log, |
| 95 observer) {} | 109 observer) {} |
| 96 | 110 |
| 97 protected: | 111 protected: |
| 98 base::TimeDelta GetRetryDelayForFailedRename(int attempt_count) override { | 112 base::TimeDelta GetRetryDelayForFailedRename(int attempt_count) override { |
| 99 return base::TimeDelta::FromMilliseconds(0); | 113 return base::TimeDelta::FromMilliseconds(0); |
| 100 } | 114 } |
| 101 | 115 |
| 102 #if !defined(OS_WIN) | 116 #if !defined(OS_WIN) |
| 103 // On Posix, we don't encounter transient errors during renames, except | 117 // On Posix, we don't encounter transient errors during renames, except |
| 104 // possibly EAGAIN, which is difficult to replicate reliably. So we resort to | 118 // possibly EAGAIN, which is difficult to replicate reliably. So we resort to |
| 105 // simulating a transient error using ACCESS_DENIED instead. | 119 // simulating a transient error using ACCESS_DENIED instead. |
| 106 bool ShouldRetryFailedRename(DownloadInterruptReason reason) override { | 120 bool ShouldRetryFailedRename(DownloadInterruptReason reason) override { |
| 107 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; | 121 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; |
| 108 } | 122 } |
| 109 #endif | 123 #endif |
| 110 }; | 124 }; |
| 111 | 125 |
| 112 } // namespace | 126 } // namespace |
| 113 | 127 |
| 114 class DownloadFileTest : public testing::Test { | 128 class DownloadFileTest : public testing::Test { |
| 115 public: | 129 public: |
| 116 | 130 static const char kTestData1[]; |
| 117 static const char* kTestData1; | 131 static const char kTestData2[]; |
| 118 static const char* kTestData2; | 132 static const char kTestData3[]; |
| 119 static const char* kTestData3; | 133 static const char kDataHash[]; |
| 120 static const char* kDataHash; | 134 static const char kEmptyHash[]; |
| 121 static const uint32_t kDummyDownloadId; | 135 static const uint32_t kDummyDownloadId; |
| 122 static const int kDummyChildId; | 136 static const int kDummyChildId; |
| 123 static const int kDummyRequestId; | 137 static const int kDummyRequestId; |
| 124 | 138 |
| 125 DownloadFileTest() : | 139 DownloadFileTest() : |
| 126 observer_(new StrictMock<MockDownloadDestinationObserver>), | 140 observer_(new StrictMock<MockDownloadDestinationObserver>), |
| 127 observer_factory_(observer_.get()), | 141 observer_factory_(observer_.get()), |
| 128 input_stream_(NULL), | 142 input_stream_(NULL), |
| 129 bytes_(-1), | 143 bytes_(-1), |
| 130 bytes_per_sec_(-1), | 144 bytes_per_sec_(-1), |
| 131 hash_state_("xyzzy"), | |
| 132 ui_thread_(BrowserThread::UI, &loop_), | 145 ui_thread_(BrowserThread::UI, &loop_), |
| 133 file_thread_(BrowserThread::FILE, &loop_) { | 146 file_thread_(BrowserThread::FILE, &loop_) { |
| 134 } | 147 } |
| 135 | 148 |
| 136 ~DownloadFileTest() override {} | 149 ~DownloadFileTest() override {} |
| 137 | 150 |
| 138 void SetUpdateDownloadInfo(int64_t bytes, | 151 void SetUpdateDownloadInfo(int64_t bytes, int64_t bytes_per_sec) { |
| 139 int64_t bytes_per_sec, | |
| 140 const std::string& hash_state) { | |
| 141 bytes_ = bytes; | 152 bytes_ = bytes; |
| 142 bytes_per_sec_ = bytes_per_sec; | 153 bytes_per_sec_ = bytes_per_sec; |
| 143 hash_state_ = hash_state; | |
| 144 } | 154 } |
| 145 | 155 |
| 146 void ConfirmUpdateDownloadInfo() { | 156 void ConfirmUpdateDownloadInfo() { |
| 147 observer_->CurrentUpdateStatus(bytes_, bytes_per_sec_, hash_state_); | 157 observer_->CurrentUpdateStatus(bytes_, bytes_per_sec_); |
| 148 } | 158 } |
| 149 | 159 |
| 150 void SetUp() override { | 160 void SetUp() override { |
| 151 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _)) | 161 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _)) |
| 152 .Times(AnyNumber()) | 162 .Times(AnyNumber()) |
| 153 .WillRepeatedly(Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo)); | 163 .WillRepeatedly(Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo)); |
| 154 } | 164 } |
| 155 | 165 |
| 156 // Mock calls to this function are forwarded here. | 166 // Mock calls to this function are forwarded here. |
| 157 void RegisterCallback(const base::Closure& sink_callback) { | 167 void RegisterCallback(const base::Closure& sink_callback) { |
| 158 sink_callback_ = sink_callback; | 168 sink_callback_ = sink_callback; |
| 159 } | 169 } |
| 160 | 170 |
| 161 void SetInterruptReasonCallback(const base::Closure& closure, | 171 void SetInterruptReasonCallback(const base::Closure& closure, |
| 162 DownloadInterruptReason* reason_p, | 172 DownloadInterruptReason* reason_p, |
| 163 DownloadInterruptReason reason) { | 173 DownloadInterruptReason reason) { |
| 164 *reason_p = reason; | 174 *reason_p = reason; |
| 165 closure.Run(); | 175 closure.Run(); |
| 166 } | 176 } |
| 167 | 177 |
| 168 bool CreateDownloadFile(int offset, bool calculate_hash) { | 178 bool CreateDownloadFile(int offset, bool calculate_hash) { |
| 169 // There can be only one. | 179 // There can be only one. |
| 170 DCHECK(!download_file_.get()); | 180 DCHECK(!download_file_.get()); |
| 171 | 181 |
| 172 input_stream_ = new StrictMock<MockByteStreamReader>(); | 182 input_stream_ = new StrictMock<MockByteStreamReader>(); |
| 173 | 183 |
| 174 // TODO: Need to actually create a function that'll set the variables | 184 // TODO: Need to actually create a function that'll set the variables |
| 175 // based on the inputs from the callback. | 185 // based on the inputs from the callback. |
| 176 EXPECT_CALL(*input_stream_, RegisterCallback(_)) | 186 EXPECT_CALL(*input_stream_, RegisterCallback(_)) |
| 177 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback)) | 187 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback)) |
| 178 .RetiresOnSaturation(); | 188 .RetiresOnSaturation(); |
| 179 | 189 |
| 180 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); | 190 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); |
| 181 download_file_.reset(new TestDownloadFileImpl( | 191 download_file_.reset( |
| 182 *save_info, base::FilePath(), | 192 new TestDownloadFileImpl(std::move(save_info), |
| 183 GURL(), // Source | 193 base::FilePath(), |
| 184 GURL(), // Referrer | 194 scoped_ptr<ByteStreamReader>(input_stream_), |
| 185 calculate_hash, std::move(save_info->file), | 195 net::BoundNetLog(), |
| 186 scoped_ptr<ByteStreamReader>(input_stream_), net::BoundNetLog(), | 196 observer_factory_.GetWeakPtr())); |
| 187 observer_factory_.GetWeakPtr())); | |
| 188 download_file_->SetClientGuid("12345678-ABCD-1234-DCBA-123456789ABC"); | |
| 189 | 197 |
| 190 EXPECT_CALL(*input_stream_, Read(_, _)) | 198 EXPECT_CALL(*input_stream_, Read(_, _)) |
| 191 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) | 199 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) |
| 192 .RetiresOnSaturation(); | 200 .RetiresOnSaturation(); |
| 193 | 201 |
| 194 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this); | 202 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this); |
| 195 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE; | 203 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE; |
| 196 base::RunLoop loop_runner; | 204 base::RunLoop loop_runner; |
| 197 download_file_->Initialize(base::Bind( | 205 download_file_->Initialize(base::Bind( |
| 198 &DownloadFileTest::SetInterruptReasonCallback, | 206 &DownloadFileTest::SetInterruptReasonCallback, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 .RetiresOnSaturation(); | 271 .RetiresOnSaturation(); |
| 264 EXPECT_CALL(*input_stream_, GetStatus()) | 272 EXPECT_CALL(*input_stream_, GetStatus()) |
| 265 .InSequence(s) | 273 .InSequence(s) |
| 266 .WillOnce(Return(interrupt_reason)) | 274 .WillOnce(Return(interrupt_reason)) |
| 267 .RetiresOnSaturation(); | 275 .RetiresOnSaturation(); |
| 268 EXPECT_CALL(*input_stream_, RegisterCallback(_)) | 276 EXPECT_CALL(*input_stream_, RegisterCallback(_)) |
| 269 .RetiresOnSaturation(); | 277 .RetiresOnSaturation(); |
| 270 } | 278 } |
| 271 | 279 |
| 272 void FinishStream(DownloadInterruptReason interrupt_reason, | 280 void FinishStream(DownloadInterruptReason interrupt_reason, |
| 273 bool check_observer) { | 281 bool check_observer, |
| 282 const std::string& expected_hash) { |
| 274 ::testing::Sequence s1; | 283 ::testing::Sequence s1; |
| 275 SetupFinishStream(interrupt_reason, s1); | 284 SetupFinishStream(interrupt_reason, s1); |
| 276 sink_callback_.Run(); | 285 sink_callback_.Run(); |
| 277 VerifyStreamAndSize(); | 286 VerifyStreamAndSize(); |
| 278 if (check_observer) { | 287 if (check_observer) { |
| 279 EXPECT_CALL(*(observer_.get()), DestinationCompleted(_)); | 288 EXPECT_CALL(*(observer_.get()), |
| 289 MockDestinationCompleted(_, expected_hash)); |
| 280 loop_.RunUntilIdle(); | 290 loop_.RunUntilIdle(); |
| 281 ::testing::Mock::VerifyAndClearExpectations(observer_.get()); | 291 ::testing::Mock::VerifyAndClearExpectations(observer_.get()); |
| 282 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _)) | 292 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _)) |
| 283 .Times(AnyNumber()) | 293 .Times(AnyNumber()) |
| 284 .WillRepeatedly(Invoke(this, | 294 .WillRepeatedly( |
| 285 &DownloadFileTest::SetUpdateDownloadInfo)); | 295 Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo)); |
| 286 } | 296 } |
| 287 } | 297 } |
| 288 | 298 |
| 289 DownloadInterruptReason RenameAndUniquify( | 299 DownloadInterruptReason RenameAndUniquify( |
| 290 const base::FilePath& full_path, | 300 const base::FilePath& full_path, |
| 291 base::FilePath* result_path_p) { | 301 base::FilePath* result_path_p) { |
| 292 return InvokeRenameMethodAndWaitForCallback( | 302 return InvokeRenameMethodAndWaitForCallback( |
| 293 &DownloadFile::RenameAndUniquify, full_path, result_path_p); | 303 RENAME_AND_UNIQUIFY, full_path, result_path_p); |
| 294 } | 304 } |
| 295 | 305 |
| 296 DownloadInterruptReason RenameAndAnnotate( | 306 DownloadInterruptReason RenameAndAnnotate( |
| 297 const base::FilePath& full_path, | 307 const base::FilePath& full_path, |
| 298 base::FilePath* result_path_p) { | 308 base::FilePath* result_path_p) { |
| 299 return InvokeRenameMethodAndWaitForCallback( | 309 return InvokeRenameMethodAndWaitForCallback( |
| 300 &DownloadFile::RenameAndAnnotate, full_path, result_path_p); | 310 RENAME_AND_ANNOTATE, full_path, result_path_p); |
| 301 } | 311 } |
| 302 | 312 |
| 303 void ExpectPermissionError(DownloadInterruptReason err) { | 313 void ExpectPermissionError(DownloadInterruptReason err) { |
| 304 EXPECT_TRUE(err == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR || | 314 EXPECT_TRUE(err == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR || |
| 305 err == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED) | 315 err == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED) |
| 306 << "Interrupt reason = " << err; | 316 << "Interrupt reason = " << err; |
| 307 } | 317 } |
| 308 | 318 |
| 309 protected: | 319 protected: |
| 320 void InvokeRenameMethod( |
| 321 DownloadFileRenameMethodType method, |
| 322 const base::FilePath& full_path, |
| 323 const DownloadFile::RenameCompletionCallback& completion_callback) { |
| 324 switch (method) { |
| 325 case RENAME_AND_UNIQUIFY: |
| 326 download_file_->RenameAndUniquify(full_path, completion_callback); |
| 327 break; |
| 328 |
| 329 case RENAME_AND_ANNOTATE: |
| 330 download_file_->RenameAndAnnotate( |
| 331 full_path, |
| 332 "12345678-ABCD-1234-DCBA-123456789ABC", |
| 333 GURL(), |
| 334 GURL(), |
| 335 completion_callback); |
| 336 break; |
| 337 } |
| 338 } |
| 339 |
| 310 DownloadInterruptReason InvokeRenameMethodAndWaitForCallback( | 340 DownloadInterruptReason InvokeRenameMethodAndWaitForCallback( |
| 311 DownloadFileRenameMethodType method, | 341 DownloadFileRenameMethodType method, |
| 312 const base::FilePath& full_path, | 342 const base::FilePath& full_path, |
| 313 base::FilePath* result_path_p) { | 343 base::FilePath* result_path_p) { |
| 314 DownloadInterruptReason result_reason(DOWNLOAD_INTERRUPT_REASON_NONE); | 344 DownloadInterruptReason result_reason(DOWNLOAD_INTERRUPT_REASON_NONE); |
| 315 base::FilePath result_path; | 345 base::FilePath result_path; |
| 316 | |
| 317 base::RunLoop loop_runner; | 346 base::RunLoop loop_runner; |
| 318 ((*download_file_).*method)(full_path, | 347 DownloadFile::RenameCompletionCallback completion_callback = |
| 319 base::Bind(&DownloadFileTest::SetRenameResult, | 348 base::Bind(&DownloadFileTest::SetRenameResult, |
| 320 base::Unretained(this), | 349 base::Unretained(this), |
| 321 loop_runner.QuitClosure(), | 350 loop_runner.QuitClosure(), |
| 322 &result_reason, | 351 &result_reason, |
| 323 result_path_p)); | 352 result_path_p); |
| 353 InvokeRenameMethod(method, full_path, completion_callback); |
| 324 loop_runner.Run(); | 354 loop_runner.Run(); |
| 325 return result_reason; | 355 return result_reason; |
| 326 } | 356 } |
| 327 | 357 |
| 328 scoped_ptr<StrictMock<MockDownloadDestinationObserver> > observer_; | 358 scoped_ptr<StrictMock<MockDownloadDestinationObserver> > observer_; |
| 329 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_; | 359 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_; |
| 330 | 360 |
| 331 // DownloadFile instance we are testing. | 361 // DownloadFile instance we are testing. |
| 332 scoped_ptr<DownloadFile> download_file_; | 362 scoped_ptr<DownloadFile> download_file_; |
| 333 | 363 |
| 334 // Stream for sending data into the download file. | 364 // Stream for sending data into the download file. |
| 335 // Owned by download_file_; will be alive for lifetime of download_file_. | 365 // Owned by download_file_; will be alive for lifetime of download_file_. |
| 336 StrictMock<MockByteStreamReader>* input_stream_; | 366 StrictMock<MockByteStreamReader>* input_stream_; |
| 337 | 367 |
| 338 // Sink callback data for stream. | 368 // Sink callback data for stream. |
| 339 base::Closure sink_callback_; | 369 base::Closure sink_callback_; |
| 340 | 370 |
| 341 // Latest update sent to the observer. | 371 // Latest update sent to the observer. |
| 342 int64_t bytes_; | 372 int64_t bytes_; |
| 343 int64_t bytes_per_sec_; | 373 int64_t bytes_per_sec_; |
| 344 std::string hash_state_; | |
| 345 | 374 |
| 346 base::MessageLoop loop_; | 375 base::MessageLoop loop_; |
| 347 | 376 |
| 348 private: | 377 private: |
| 349 void SetRenameResult(const base::Closure& closure, | 378 void SetRenameResult(const base::Closure& closure, |
| 350 DownloadInterruptReason* reason_p, | 379 DownloadInterruptReason* reason_p, |
| 351 base::FilePath* result_path_p, | 380 base::FilePath* result_path_p, |
| 352 DownloadInterruptReason reason, | 381 DownloadInterruptReason reason, |
| 353 const base::FilePath& result_path) { | 382 const base::FilePath& result_path) { |
| 354 if (reason_p) | 383 if (reason_p) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 384 } | 413 } |
| 385 }; | 414 }; |
| 386 | 415 |
| 387 // And now instantiate all DownloadFileTestWithRename tests using both | 416 // And now instantiate all DownloadFileTestWithRename tests using both |
| 388 // DownloadFile rename methods. Each test of the form | 417 // DownloadFile rename methods. Each test of the form |
| 389 // DownloadFileTestWithRename.<FooTest> will be instantiated once with | 418 // DownloadFileTestWithRename.<FooTest> will be instantiated once with |
| 390 // RenameAndAnnotate as the value parameter and once with RenameAndUniquify as | 419 // RenameAndAnnotate as the value parameter and once with RenameAndUniquify as |
| 391 // the value parameter. | 420 // the value parameter. |
| 392 INSTANTIATE_TEST_CASE_P(DownloadFile, | 421 INSTANTIATE_TEST_CASE_P(DownloadFile, |
| 393 DownloadFileTestWithRename, | 422 DownloadFileTestWithRename, |
| 394 ::testing::Values(&DownloadFile::RenameAndAnnotate, | 423 ::testing::Values(RENAME_AND_ANNOTATE, |
| 395 &DownloadFile::RenameAndUniquify)); | 424 RENAME_AND_UNIQUIFY)); |
| 396 | 425 |
| 397 const char* DownloadFileTest::kTestData1 = | 426 const char DownloadFileTest::kTestData1[] = |
| 398 "Let's write some data to the file!\n"; | 427 "Let's write some data to the file!\n"; |
| 399 const char* DownloadFileTest::kTestData2 = "Writing more data.\n"; | 428 const char DownloadFileTest::kTestData2[] = "Writing more data.\n"; |
| 400 const char* DownloadFileTest::kTestData3 = "Final line."; | 429 const char DownloadFileTest::kTestData3[] = "Final line."; |
| 401 const char* DownloadFileTest::kDataHash = | 430 const char DownloadFileTest::kDataHash[] = |
| 402 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8"; | 431 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8"; |
| 432 const char DownloadFileTest::kEmptyHash[] = |
| 433 "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"; |
| 403 | 434 |
| 404 const uint32_t DownloadFileTest::kDummyDownloadId = 23; | 435 const uint32_t DownloadFileTest::kDummyDownloadId = 23; |
| 405 const int DownloadFileTest::kDummyChildId = 3; | 436 const int DownloadFileTest::kDummyChildId = 3; |
| 406 const int DownloadFileTest::kDummyRequestId = 67; | 437 const int DownloadFileTest::kDummyRequestId = 67; |
| 407 | 438 |
| 408 // Rename the file before any data is downloaded, after some has, after it all | 439 // Rename the file before any data is downloaded, after some has, after it all |
| 409 // has, and after it's closed. | 440 // has, and after it's closed. |
| 410 TEST_P(DownloadFileTestWithRename, RenameFileFinal) { | 441 TEST_P(DownloadFileTestWithRename, RenameFileFinal) { |
| 411 ASSERT_TRUE(CreateDownloadFile(0, true)); | 442 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 412 base::FilePath initial_path(download_file_->FullPath()); | 443 base::FilePath initial_path(download_file_->FullPath()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, | 481 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, |
| 451 InvokeSelectedRenameMethod(path_3, &output_path)); | 482 InvokeSelectedRenameMethod(path_3, &output_path)); |
| 452 renamed_path = download_file_->FullPath(); | 483 renamed_path = download_file_->FullPath(); |
| 453 EXPECT_EQ(path_3, renamed_path); | 484 EXPECT_EQ(path_3, renamed_path); |
| 454 EXPECT_EQ(path_3, output_path); | 485 EXPECT_EQ(path_3, output_path); |
| 455 | 486 |
| 456 // Check the files. | 487 // Check the files. |
| 457 EXPECT_FALSE(base::PathExists(path_2)); | 488 EXPECT_FALSE(base::PathExists(path_2)); |
| 458 EXPECT_TRUE(base::PathExists(path_3)); | 489 EXPECT_TRUE(base::PathExists(path_3)); |
| 459 | 490 |
| 460 // Should not be able to get the hash until the file is closed. | 491 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kDataHash); |
| 461 std::string hash; | |
| 462 EXPECT_FALSE(download_file_->GetHash(&hash)); | |
| 463 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); | |
| 464 loop_.RunUntilIdle(); | 492 loop_.RunUntilIdle(); |
| 465 | 493 |
| 466 // Rename the file after downloading all the data and closing the file. | 494 // Rename the file after downloading all the data and closing the file. |
| 467 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, | 495 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, |
| 468 InvokeSelectedRenameMethod(path_4, &output_path)); | 496 InvokeSelectedRenameMethod(path_4, &output_path)); |
| 469 renamed_path = download_file_->FullPath(); | 497 renamed_path = download_file_->FullPath(); |
| 470 EXPECT_EQ(path_4, renamed_path); | 498 EXPECT_EQ(path_4, renamed_path); |
| 471 EXPECT_EQ(path_4, output_path); | 499 EXPECT_EQ(path_4, output_path); |
| 472 | 500 |
| 473 // Check the files. | 501 // Check the files. |
| 474 EXPECT_FALSE(base::PathExists(path_3)); | 502 EXPECT_FALSE(base::PathExists(path_3)); |
| 475 EXPECT_TRUE(base::PathExists(path_4)); | 503 EXPECT_TRUE(base::PathExists(path_4)); |
| 476 | 504 |
| 477 // Check the hash. | |
| 478 EXPECT_TRUE(download_file_->GetHash(&hash)); | |
| 479 EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size())); | |
| 480 | |
| 481 DestroyDownloadFile(0); | 505 DestroyDownloadFile(0); |
| 482 } | 506 } |
| 483 | 507 |
| 484 // Test to make sure the rename overwrites when requested. This is separate from | 508 // Test to make sure the rename overwrites when requested. This is separate from |
| 485 // the above test because it only applies to RenameAndAnnotate(). | 509 // the above test because it only applies to RenameAndAnnotate(). |
| 486 // RenameAndUniquify() doesn't overwrite by design. | 510 // RenameAndUniquify() doesn't overwrite by design. |
| 487 TEST_F(DownloadFileTest, RenameOverwrites) { | 511 TEST_F(DownloadFileTest, RenameOverwrites) { |
| 488 ASSERT_TRUE(CreateDownloadFile(0, true)); | 512 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 489 base::FilePath initial_path(download_file_->FullPath()); | 513 base::FilePath initial_path(download_file_->FullPath()); |
| 490 EXPECT_TRUE(base::PathExists(initial_path)); | 514 EXPECT_TRUE(base::PathExists(initial_path)); |
| 491 base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1")); | 515 base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1")); |
| 492 | 516 |
| 493 ASSERT_FALSE(base::PathExists(path_1)); | 517 ASSERT_FALSE(base::PathExists(path_1)); |
| 494 static const char file_data[] = "xyzzy"; | 518 static const char file_data[] = "xyzzy"; |
| 495 ASSERT_EQ(static_cast<int>(sizeof(file_data)), | 519 ASSERT_EQ(static_cast<int>(sizeof(file_data)), |
| 496 base::WriteFile(path_1, file_data, sizeof(file_data))); | 520 base::WriteFile(path_1, file_data, sizeof(file_data))); |
| 497 ASSERT_TRUE(base::PathExists(path_1)); | 521 ASSERT_TRUE(base::PathExists(path_1)); |
| 498 | 522 |
| 499 base::FilePath new_path; | 523 base::FilePath new_path; |
| 500 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, | 524 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, |
| 501 RenameAndAnnotate(path_1, &new_path)); | 525 RenameAndAnnotate(path_1, &new_path)); |
| 502 EXPECT_EQ(path_1.value(), new_path.value()); | 526 EXPECT_EQ(path_1.value(), new_path.value()); |
| 503 | 527 |
| 504 std::string file_contents; | 528 std::string file_contents; |
| 505 ASSERT_TRUE(base::ReadFileToString(new_path, &file_contents)); | 529 ASSERT_TRUE(base::ReadFileToString(new_path, &file_contents)); |
| 506 EXPECT_NE(std::string(file_data), file_contents); | 530 EXPECT_NE(std::string(file_data), file_contents); |
| 507 | 531 |
| 508 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); | 532 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash); |
| 509 loop_.RunUntilIdle(); | 533 loop_.RunUntilIdle(); |
| 510 DestroyDownloadFile(0); | 534 DestroyDownloadFile(0); |
| 511 } | 535 } |
| 512 | 536 |
| 513 // Test to make sure the rename uniquifies if we aren't overwriting | 537 // Test to make sure the rename uniquifies if we aren't overwriting |
| 514 // and there's a file where we're aiming. As above, not a | 538 // and there's a file where we're aiming. As above, not a |
| 515 // DownloadFileTestWithRename test because this only applies to | 539 // DownloadFileTestWithRename test because this only applies to |
| 516 // RenameAndUniquify(). | 540 // RenameAndUniquify(). |
| 517 TEST_F(DownloadFileTest, RenameUniquifies) { | 541 TEST_F(DownloadFileTest, RenameUniquifies) { |
| 518 ASSERT_TRUE(CreateDownloadFile(0, true)); | 542 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 519 base::FilePath initial_path(download_file_->FullPath()); | 543 base::FilePath initial_path(download_file_->FullPath()); |
| 520 EXPECT_TRUE(base::PathExists(initial_path)); | 544 EXPECT_TRUE(base::PathExists(initial_path)); |
| 521 base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1")); | 545 base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1")); |
| 522 base::FilePath path_1_suffixed(path_1.InsertBeforeExtensionASCII(" (1)")); | 546 base::FilePath path_1_suffixed(path_1.InsertBeforeExtensionASCII(" (1)")); |
| 523 | 547 |
| 524 ASSERT_FALSE(base::PathExists(path_1)); | 548 ASSERT_FALSE(base::PathExists(path_1)); |
| 525 static const char file_data[] = "xyzzy"; | 549 static const char file_data[] = "xyzzy"; |
| 526 ASSERT_EQ(static_cast<int>(sizeof(file_data)), | 550 ASSERT_EQ(static_cast<int>(sizeof(file_data)), |
| 527 base::WriteFile(path_1, file_data, sizeof(file_data))); | 551 base::WriteFile(path_1, file_data, sizeof(file_data))); |
| 528 ASSERT_TRUE(base::PathExists(path_1)); | 552 ASSERT_TRUE(base::PathExists(path_1)); |
| 529 | 553 |
| 530 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, RenameAndUniquify(path_1, NULL)); | 554 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, RenameAndUniquify(path_1, NULL)); |
| 531 EXPECT_TRUE(base::PathExists(path_1_suffixed)); | 555 EXPECT_TRUE(base::PathExists(path_1_suffixed)); |
| 532 | 556 |
| 533 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); | 557 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash); |
| 534 loop_.RunUntilIdle(); | 558 loop_.RunUntilIdle(); |
| 535 DestroyDownloadFile(0); | 559 DestroyDownloadFile(0); |
| 536 } | 560 } |
| 537 | 561 |
| 538 // Test that RenameAndUniquify doesn't try to uniquify in the case where the | 562 // Test that RenameAndUniquify doesn't try to uniquify in the case where the |
| 539 // target filename is the same as the current filename. | 563 // target filename is the same as the current filename. |
| 540 TEST_F(DownloadFileTest, RenameRecognizesSelfConflict) { | 564 TEST_F(DownloadFileTest, RenameRecognizesSelfConflict) { |
| 541 ASSERT_TRUE(CreateDownloadFile(0, true)); | 565 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 542 base::FilePath initial_path(download_file_->FullPath()); | 566 base::FilePath initial_path(download_file_->FullPath()); |
| 543 EXPECT_TRUE(base::PathExists(initial_path)); | 567 EXPECT_TRUE(base::PathExists(initial_path)); |
| 544 | 568 |
| 545 base::FilePath new_path; | 569 base::FilePath new_path; |
| 546 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, | 570 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, |
| 547 RenameAndUniquify(initial_path, &new_path)); | 571 RenameAndUniquify(initial_path, &new_path)); |
| 548 EXPECT_TRUE(base::PathExists(initial_path)); | 572 EXPECT_TRUE(base::PathExists(initial_path)); |
| 549 | 573 |
| 550 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); | 574 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash); |
| 551 loop_.RunUntilIdle(); | 575 loop_.RunUntilIdle(); |
| 552 DestroyDownloadFile(0); | 576 DestroyDownloadFile(0); |
| 553 EXPECT_EQ(initial_path.value(), new_path.value()); | 577 EXPECT_EQ(initial_path.value(), new_path.value()); |
| 554 } | 578 } |
| 555 | 579 |
| 556 // Test to make sure we get the proper error on failure. | 580 // Test to make sure we get the proper error on failure. |
| 557 TEST_P(DownloadFileTestWithRename, RenameError) { | 581 TEST_P(DownloadFileTestWithRename, RenameError) { |
| 558 ASSERT_TRUE(CreateDownloadFile(0, true)); | 582 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 559 base::FilePath initial_path(download_file_->FullPath()); | 583 base::FilePath initial_path(download_file_->FullPath()); |
| 560 | 584 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 575 { | 599 { |
| 576 base::FilePermissionRestorer restorer(target_dir); | 600 base::FilePermissionRestorer restorer(target_dir); |
| 577 ASSERT_TRUE(base::MakeFileUnwritable(target_dir)); | 601 ASSERT_TRUE(base::MakeFileUnwritable(target_dir)); |
| 578 | 602 |
| 579 // Expect nulling out of further processing. | 603 // Expect nulling out of further processing. |
| 580 EXPECT_CALL(*input_stream_, RegisterCallback(IsNullCallback())); | 604 EXPECT_CALL(*input_stream_, RegisterCallback(IsNullCallback())); |
| 581 ExpectPermissionError(InvokeSelectedRenameMethod(target_path, NULL)); | 605 ExpectPermissionError(InvokeSelectedRenameMethod(target_path, NULL)); |
| 582 EXPECT_FALSE(base::PathExists(target_path_suffixed)); | 606 EXPECT_FALSE(base::PathExists(target_path_suffixed)); |
| 583 } | 607 } |
| 584 | 608 |
| 585 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); | 609 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash); |
| 586 loop_.RunUntilIdle(); | 610 loop_.RunUntilIdle(); |
| 587 DestroyDownloadFile(0); | 611 DestroyDownloadFile(0); |
| 588 } | 612 } |
| 589 | 613 |
| 590 namespace { | 614 namespace { |
| 591 | 615 |
| 592 void TestRenameCompletionCallback(const base::Closure& closure, | 616 void TestRenameCompletionCallback(const base::Closure& closure, |
| 593 bool* did_run_callback, | 617 bool* did_run_callback, |
| 594 DownloadInterruptReason interrupt_reason, | 618 DownloadInterruptReason interrupt_reason, |
| 595 const base::FilePath& new_path) { | 619 const base::FilePath& new_path) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 #else | 662 #else |
| 639 // Simulate a transient failure by revoking write permission for target_dir. | 663 // Simulate a transient failure by revoking write permission for target_dir. |
| 640 // The TestDownloadFileImpl class treats this error as transient even though | 664 // The TestDownloadFileImpl class treats this error as transient even though |
| 641 // DownloadFileImpl itself doesn't. | 665 // DownloadFileImpl itself doesn't. |
| 642 base::FilePermissionRestorer restore_permissions_for(target_dir); | 666 base::FilePermissionRestorer restore_permissions_for(target_dir); |
| 643 ASSERT_TRUE(base::MakeFileUnwritable(target_dir)); | 667 ASSERT_TRUE(base::MakeFileUnwritable(target_dir)); |
| 644 #endif | 668 #endif |
| 645 | 669 |
| 646 // The Rename() should fail here and enqueue a retry task without invoking | 670 // The Rename() should fail here and enqueue a retry task without invoking |
| 647 // the completion callback. | 671 // the completion callback. |
| 648 ((*download_file_).*GetParam())(target_path, | 672 InvokeRenameMethod(GetParam(), |
| 649 base::Bind(&TestRenameCompletionCallback, | 673 target_path, |
| 650 succeeding_run.QuitClosure(), | 674 base::Bind(&TestRenameCompletionCallback, |
| 651 &did_run_callback)); | 675 succeeding_run.QuitClosure(), |
| 676 &did_run_callback)); |
| 652 EXPECT_FALSE(did_run_callback); | 677 EXPECT_FALSE(did_run_callback); |
| 653 | 678 |
| 654 base::RunLoop first_failing_run; | 679 base::RunLoop first_failing_run; |
| 655 // Queue the QuitClosure() on the MessageLoop now. Any tasks queued by the | 680 // Queue the QuitClosure() on the MessageLoop now. Any tasks queued by the |
| 656 // Rename() will be in front of the QuitClosure(). Running the message loop | 681 // Rename() will be in front of the QuitClosure(). Running the message loop |
| 657 // now causes the just the first retry task to be run. The rename still | 682 // now causes the just the first retry task to be run. The rename still |
| 658 // fails, so another retry task would get queued behind the QuitClosure(). | 683 // fails, so another retry task would get queued behind the QuitClosure(). |
| 659 base::ThreadTaskRunnerHandle::Get()->PostTask( | 684 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 660 FROM_HERE, first_failing_run.QuitClosure()); | 685 FROM_HERE, first_failing_run.QuitClosure()); |
| 661 first_failing_run.Run(); | 686 first_failing_run.Run(); |
| 662 EXPECT_FALSE(did_run_callback); | 687 EXPECT_FALSE(did_run_callback); |
| 663 | 688 |
| 664 // Running another loop should have the same effect as the above as long as | 689 // Running another loop should have the same effect as the above as long as |
| 665 // kMaxRenameRetries is greater than 2. | 690 // kMaxRenameRetries is greater than 2. |
| 666 base::RunLoop second_failing_run; | 691 base::RunLoop second_failing_run; |
| 667 base::ThreadTaskRunnerHandle::Get()->PostTask( | 692 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 668 FROM_HERE, second_failing_run.QuitClosure()); | 693 FROM_HERE, second_failing_run.QuitClosure()); |
| 669 second_failing_run.Run(); | 694 second_failing_run.Run(); |
| 670 EXPECT_FALSE(did_run_callback); | 695 EXPECT_FALSE(did_run_callback); |
| 671 } | 696 } |
| 672 | 697 |
| 673 // This time the QuitClosure from succeeding_run should get executed. | 698 // This time the QuitClosure from succeeding_run should get executed. |
| 674 succeeding_run.Run(); | 699 succeeding_run.Run(); |
| 675 EXPECT_TRUE(did_run_callback); | 700 EXPECT_TRUE(did_run_callback); |
| 676 | 701 |
| 677 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); | 702 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash); |
| 678 loop_.RunUntilIdle(); | 703 loop_.RunUntilIdle(); |
| 679 DestroyDownloadFile(0); | 704 DestroyDownloadFile(0); |
| 680 } | 705 } |
| 681 | 706 |
| 682 // Various tests of the StreamActive method. | 707 // Various tests of the StreamActive method. |
| 683 TEST_F(DownloadFileTest, StreamEmptySuccess) { | 708 TEST_F(DownloadFileTest, StreamEmptySuccess) { |
| 684 ASSERT_TRUE(CreateDownloadFile(0, true)); | 709 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 685 base::FilePath initial_path(download_file_->FullPath()); | 710 base::FilePath initial_path(download_file_->FullPath()); |
| 686 EXPECT_TRUE(base::PathExists(initial_path)); | 711 EXPECT_TRUE(base::PathExists(initial_path)); |
| 687 | 712 |
| 688 // Test that calling the sink_callback_ on an empty stream shouldn't | 713 // Test that calling the sink_callback_ on an empty stream shouldn't |
| 689 // do anything. | 714 // do anything. |
| 690 AppendDataToFile(NULL, 0); | 715 AppendDataToFile(NULL, 0); |
| 691 | 716 |
| 692 // Finish the download this way and make sure we see it on the | 717 // Finish the download this way and make sure we see it on the observer. |
| 693 // observer. | 718 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash); |
| 694 EXPECT_CALL(*(observer_.get()), DestinationCompleted(_)); | |
| 695 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, false); | |
| 696 loop_.RunUntilIdle(); | 719 loop_.RunUntilIdle(); |
| 697 | 720 |
| 698 DestroyDownloadFile(0); | 721 DestroyDownloadFile(0); |
| 699 } | 722 } |
| 700 | 723 |
| 701 TEST_F(DownloadFileTest, StreamEmptyError) { | 724 TEST_F(DownloadFileTest, StreamEmptyError) { |
| 702 ASSERT_TRUE(CreateDownloadFile(0, true)); | 725 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 703 base::FilePath initial_path(download_file_->FullPath()); | 726 base::FilePath initial_path(download_file_->FullPath()); |
| 704 EXPECT_TRUE(base::PathExists(initial_path)); | 727 EXPECT_TRUE(base::PathExists(initial_path)); |
| 705 | 728 |
| 706 // Finish the download in error and make sure we see it on the | 729 // Finish the download in error and make sure we see it on the |
| 707 // observer. | 730 // observer. |
| 708 EXPECT_CALL(*(observer_.get()), | 731 EXPECT_CALL( |
| 709 DestinationError( | 732 *(observer_.get()), |
| 710 DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED)) | 733 MockDestinationError( |
| 734 DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, 0, kEmptyHash)) |
| 711 .WillOnce(InvokeWithoutArgs( | 735 .WillOnce(InvokeWithoutArgs( |
| 712 this, &DownloadFileTest::ConfirmUpdateDownloadInfo)); | 736 this, &DownloadFileTest::ConfirmUpdateDownloadInfo)); |
| 713 | 737 |
| 714 // If this next EXPECT_CALL fails flakily, it's probably a real failure. | 738 // If this next EXPECT_CALL fails flakily, it's probably a real failure. |
| 715 // We'll be getting a stream of UpdateDownload calls from the timer, and | 739 // We'll be getting a stream of UpdateDownload calls from the timer, and |
| 716 // the last one may have the correct information even if the failure | 740 // the last one may have the correct information even if the failure |
| 717 // doesn't produce an update, as the timer update may have triggered at the | 741 // doesn't produce an update, as the timer update may have triggered at the |
| 718 // same time. | 742 // same time. |
| 719 EXPECT_CALL(*(observer_.get()), CurrentUpdateStatus(0, _, _)); | 743 EXPECT_CALL(*(observer_.get()), CurrentUpdateStatus(0, _)); |
| 720 | 744 |
| 721 FinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, false); | 745 FinishStream( |
| 746 DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, false, kEmptyHash); |
| 722 | 747 |
| 723 loop_.RunUntilIdle(); | 748 loop_.RunUntilIdle(); |
| 724 | 749 |
| 725 DestroyDownloadFile(0); | 750 DestroyDownloadFile(0); |
| 726 } | 751 } |
| 727 | 752 |
| 728 TEST_F(DownloadFileTest, StreamNonEmptySuccess) { | 753 TEST_F(DownloadFileTest, StreamNonEmptySuccess) { |
| 729 ASSERT_TRUE(CreateDownloadFile(0, true)); | 754 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 730 base::FilePath initial_path(download_file_->FullPath()); | 755 base::FilePath initial_path(download_file_->FullPath()); |
| 731 EXPECT_TRUE(base::PathExists(initial_path)); | 756 EXPECT_TRUE(base::PathExists(initial_path)); |
| 732 | 757 |
| 733 const char* chunks1[] = { kTestData1, kTestData2 }; | 758 const char* chunks1[] = { kTestData1, kTestData2 }; |
| 734 ::testing::Sequence s1; | 759 ::testing::Sequence s1; |
| 735 SetupDataAppend(chunks1, 2, s1); | 760 SetupDataAppend(chunks1, 2, s1); |
| 736 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, s1); | 761 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, s1); |
| 737 EXPECT_CALL(*(observer_.get()), DestinationCompleted(_)); | 762 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); |
| 738 sink_callback_.Run(); | 763 sink_callback_.Run(); |
| 739 VerifyStreamAndSize(); | 764 VerifyStreamAndSize(); |
| 740 loop_.RunUntilIdle(); | 765 loop_.RunUntilIdle(); |
| 741 DestroyDownloadFile(0); | 766 DestroyDownloadFile(0); |
| 742 } | 767 } |
| 743 | 768 |
| 744 TEST_F(DownloadFileTest, StreamNonEmptyError) { | 769 TEST_F(DownloadFileTest, StreamNonEmptyError) { |
| 745 ASSERT_TRUE(CreateDownloadFile(0, true)); | 770 ASSERT_TRUE(CreateDownloadFile(0, true)); |
| 746 base::FilePath initial_path(download_file_->FullPath()); | 771 base::FilePath initial_path(download_file_->FullPath()); |
| 747 EXPECT_TRUE(base::PathExists(initial_path)); | 772 EXPECT_TRUE(base::PathExists(initial_path)); |
| 748 | 773 |
| 749 const char* chunks1[] = { kTestData1, kTestData2 }; | 774 const char* chunks1[] = { kTestData1, kTestData2 }; |
| 750 ::testing::Sequence s1; | 775 ::testing::Sequence s1; |
| 751 SetupDataAppend(chunks1, 2, s1); | 776 SetupDataAppend(chunks1, 2, s1); |
| 752 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, s1); | 777 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, s1); |
| 753 | 778 |
| 754 EXPECT_CALL(*(observer_.get()), | 779 EXPECT_CALL(*(observer_.get()), |
| 755 DestinationError( | 780 MockDestinationError( |
| 756 DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED)) | 781 DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, _, _)) |
| 757 .WillOnce(InvokeWithoutArgs( | 782 .WillOnce(InvokeWithoutArgs( |
| 758 this, &DownloadFileTest::ConfirmUpdateDownloadInfo)); | 783 this, &DownloadFileTest::ConfirmUpdateDownloadInfo)); |
| 759 | 784 |
| 760 // If this next EXPECT_CALL fails flakily, it's probably a real failure. | 785 // If this next EXPECT_CALL fails flakily, it's probably a real failure. |
| 761 // We'll be getting a stream of UpdateDownload calls from the timer, and | 786 // We'll be getting a stream of UpdateDownload calls from the timer, and |
| 762 // the last one may have the correct information even if the failure | 787 // the last one may have the correct information even if the failure |
| 763 // doesn't produce an update, as the timer update may have triggered at the | 788 // doesn't produce an update, as the timer update may have triggered at the |
| 764 // same time. | 789 // same time. |
| 765 EXPECT_CALL(*(observer_.get()), | 790 EXPECT_CALL(*(observer_.get()), |
| 766 CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2), | 791 CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2), _)); |
| 767 _, _)); | |
| 768 | 792 |
| 769 sink_callback_.Run(); | 793 sink_callback_.Run(); |
| 770 loop_.RunUntilIdle(); | 794 loop_.RunUntilIdle(); |
| 771 VerifyStreamAndSize(); | 795 VerifyStreamAndSize(); |
| 772 DestroyDownloadFile(0); | 796 DestroyDownloadFile(0); |
| 773 } | 797 } |
| 774 | 798 |
| 775 // Send some data, wait 3/4s of a second, run the message loop, and | |
| 776 // confirm the values the observer received are correct. | |
| 777 TEST_F(DownloadFileTest, ConfirmUpdate) { | |
| 778 CreateDownloadFile(0, true); | |
| 779 | |
| 780 const char* chunks1[] = { kTestData1, kTestData2 }; | |
| 781 AppendDataToFile(chunks1, 2); | |
| 782 | |
| 783 // Run the message loops for 750ms and check for results. | |
| 784 loop_.task_runner()->PostDelayedTask(FROM_HERE, | |
| 785 base::MessageLoop::QuitWhenIdleClosure(), | |
| 786 base::TimeDelta::FromMilliseconds(750)); | |
| 787 loop_.Run(); | |
| 788 | |
| 789 EXPECT_EQ(static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2)), | |
| 790 bytes_); | |
| 791 EXPECT_EQ(download_file_->GetHashState(), hash_state_); | |
| 792 | |
| 793 FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true); | |
| 794 DestroyDownloadFile(0); | |
| 795 } | |
| 796 | |
| 797 } // namespace content | 799 } // namespace content |
| OLD | NEW |