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 |