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

Side by Side Diff: content/browser/download/download_file_unittest.cc

Issue 2712713007: Make DownloadFileImpl handle multiple byte streams. (Closed)
Patch Set: Remove the AppendDataToFile call, fix the browsertest. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/files/file.h" 11 #include "base/files/file.h"
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/memory/ptr_util.h"
14 #include "base/run_loop.h" 15 #include "base/run_loop.h"
15 #include "base/single_thread_task_runner.h" 16 #include "base/single_thread_task_runner.h"
16 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
17 #include "base/test/test_file_util.h" 18 #include "base/test/test_file_util.h"
18 #include "base/threading/thread_task_runner_handle.h" 19 #include "base/threading/thread_task_runner_handle.h"
19 #include "build/build_config.h" 20 #include "build/build_config.h"
20 #include "content/browser/byte_stream.h" 21 #include "content/browser/byte_stream.h"
21 #include "content/browser/download/download_create_info.h" 22 #include "content/browser/download/download_create_info.h"
22 #include "content/browser/download/download_destination_observer.h" 23 #include "content/browser/download/download_destination_observer.h"
23 #include "content/browser/download/download_file_impl.h" 24 #include "content/browser/download/download_file_impl.h"
(...skipping 13 matching lines...) Expand all
37 using ::testing::AnyNumber; 38 using ::testing::AnyNumber;
38 using ::testing::DoAll; 39 using ::testing::DoAll;
39 using ::testing::InSequence; 40 using ::testing::InSequence;
40 using ::testing::Return; 41 using ::testing::Return;
41 using ::testing::SetArgPointee; 42 using ::testing::SetArgPointee;
42 using ::testing::StrictMock; 43 using ::testing::StrictMock;
43 44
44 namespace content { 45 namespace content {
45 namespace { 46 namespace {
46 47
48 // Struct for SourceStream states verification.
49 struct SourceStreamTestData {
50 SourceStreamTestData(int64_t offset, int64_t bytes_written, bool finished)
51 : offset(offset), bytes_written(bytes_written), finished(finished) {}
52 int64_t offset;
53 int64_t bytes_written;
54 bool finished;
55 };
56
47 std::string GetHexEncodedHashValue(crypto::SecureHash* hash_state) { 57 std::string GetHexEncodedHashValue(crypto::SecureHash* hash_state) {
48 if (!hash_state) 58 if (!hash_state)
49 return std::string(); 59 return std::string();
50 std::vector<char> hash_value(hash_state->GetHashLength()); 60 std::vector<char> hash_value(hash_state->GetHashLength());
51 hash_state->Finish(&hash_value.front(), hash_value.size()); 61 hash_state->Finish(&hash_value.front(), hash_value.size());
52 return base::HexEncode(&hash_value.front(), hash_value.size()); 62 return base::HexEncode(&hash_value.front(), hash_value.size());
53 } 63 }
54 64
55 class MockByteStreamReader : public ByteStreamReader { 65 class MockByteStreamReader : public ByteStreamReader {
56 public: 66 public:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 enum DownloadFileRenameMethodType { RENAME_AND_UNIQUIFY, RENAME_AND_ANNOTATE }; 107 enum DownloadFileRenameMethodType { RENAME_AND_UNIQUIFY, RENAME_AND_ANNOTATE };
98 108
99 // This is a test DownloadFileImpl that has no retry delay and, on Posix, 109 // This is a test DownloadFileImpl that has no retry delay and, on Posix,
100 // retries renames failed due to ACCESS_DENIED. 110 // retries renames failed due to ACCESS_DENIED.
101 class TestDownloadFileImpl : public DownloadFileImpl { 111 class TestDownloadFileImpl : public DownloadFileImpl {
102 public: 112 public:
103 TestDownloadFileImpl(std::unique_ptr<DownloadSaveInfo> save_info, 113 TestDownloadFileImpl(std::unique_ptr<DownloadSaveInfo> save_info,
104 const base::FilePath& default_downloads_directory, 114 const base::FilePath& default_downloads_directory,
105 std::unique_ptr<ByteStreamReader> stream, 115 std::unique_ptr<ByteStreamReader> stream,
106 const net::NetLogWithSource& net_log, 116 const net::NetLogWithSource& net_log,
117 bool is_sparse_file,
107 base::WeakPtr<DownloadDestinationObserver> observer) 118 base::WeakPtr<DownloadDestinationObserver> observer)
108 : DownloadFileImpl(std::move(save_info), 119 : DownloadFileImpl(std::move(save_info),
109 default_downloads_directory, 120 default_downloads_directory,
110 std::move(stream), 121 std::move(stream),
111 net_log, 122 net_log,
123 is_sparse_file,
112 observer) {} 124 observer) {}
113 125
114 protected: 126 protected:
115 base::TimeDelta GetRetryDelayForFailedRename(int attempt_count) override { 127 base::TimeDelta GetRetryDelayForFailedRename(int attempt_count) override {
116 return base::TimeDelta::FromMilliseconds(0); 128 return base::TimeDelta::FromMilliseconds(0);
117 } 129 }
118 130
119 #if !defined(OS_WIN) 131 #if !defined(OS_WIN)
120 // On Posix, we don't encounter transient errors during renames, except 132 // On Posix, we don't encounter transient errors during renames, except
121 // possibly EAGAIN, which is difficult to replicate reliably. So we resort to 133 // possibly EAGAIN, which is difficult to replicate reliably. So we resort to
122 // simulating a transient error using ACCESS_DENIED instead. 134 // simulating a transient error using ACCESS_DENIED instead.
123 bool ShouldRetryFailedRename(DownloadInterruptReason reason) override { 135 bool ShouldRetryFailedRename(DownloadInterruptReason reason) override {
124 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; 136 return reason == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
125 } 137 }
126 #endif 138 #endif
127 }; 139 };
128 140
129 } // namespace 141 } // namespace
130 142
131 class DownloadFileTest : public testing::Test { 143 class DownloadFileTest : public testing::Test {
132 public: 144 public:
133 static const char kTestData1[]; 145 static const char kTestData1[];
134 static const char kTestData2[]; 146 static const char kTestData2[];
135 static const char kTestData3[]; 147 static const char kTestData3[];
148 static const char kTestData4[];
149 static const char kTestData5[];
136 static const char kDataHash[]; 150 static const char kDataHash[];
137 static const char kEmptyHash[]; 151 static const char kEmptyHash[];
138 static const uint32_t kDummyDownloadId; 152 static const uint32_t kDummyDownloadId;
139 static const int kDummyChildId; 153 static const int kDummyChildId;
140 static const int kDummyRequestId; 154 static const int kDummyRequestId;
141 155
142 DownloadFileTest() 156 DownloadFileTest()
143 : observer_(new StrictMock<MockDownloadDestinationObserver>), 157 : observer_(new StrictMock<MockDownloadDestinationObserver>),
144 observer_factory_(observer_.get()), 158 observer_factory_(observer_.get()),
145 input_stream_(NULL), 159 input_stream_(NULL),
160 input_stream_1_(NULL),
146 bytes_(-1), 161 bytes_(-1),
147 bytes_per_sec_(-1) {} 162 bytes_per_sec_(-1) {}
148 163
149 ~DownloadFileTest() override {} 164 ~DownloadFileTest() override {}
150 165
151 void SetUpdateDownloadInfo( 166 void SetUpdateDownloadInfo(
152 int64_t bytes, int64_t bytes_per_sec, 167 int64_t bytes, int64_t bytes_per_sec,
153 const std::vector<DownloadItem::ReceivedSlice>& received_slices) { 168 const std::vector<DownloadItem::ReceivedSlice>& received_slices) {
154 bytes_ = bytes; 169 bytes_ = bytes;
155 bytes_per_sec_ = bytes_per_sec; 170 bytes_per_sec_ = bytes_per_sec;
(...skipping 14 matching lines...) Expand all
170 sink_callback_ = sink_callback; 185 sink_callback_ = sink_callback;
171 } 186 }
172 187
173 void SetInterruptReasonCallback(const base::Closure& closure, 188 void SetInterruptReasonCallback(const base::Closure& closure,
174 DownloadInterruptReason* reason_p, 189 DownloadInterruptReason* reason_p,
175 DownloadInterruptReason reason) { 190 DownloadInterruptReason reason) {
176 *reason_p = reason; 191 *reason_p = reason;
177 closure.Run(); 192 closure.Run();
178 } 193 }
179 194
180 bool CreateDownloadFile(int offset, bool calculate_hash) { 195 bool CreateDownloadFile(int offset,
196 bool calculate_hash,
197 bool is_sparse_file = false) {
181 // There can be only one. 198 // There can be only one.
182 DCHECK(!download_file_.get()); 199 DCHECK(!download_file_.get());
183 200
184 input_stream_ = new StrictMock<MockByteStreamReader>(); 201 input_stream_ = new StrictMock<MockByteStreamReader>();
185 202
186 // TODO: Need to actually create a function that'll set the variables 203 // TODO: Need to actually create a function that'll set the variables
187 // based on the inputs from the callback. 204 // based on the inputs from the callback.
188 EXPECT_CALL(*input_stream_, RegisterCallback(_)) 205 EXPECT_CALL(*input_stream_, RegisterCallback(_))
189 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback)) 206 .WillOnce(Invoke(this, &DownloadFileTest::RegisterCallback))
190 .RetiresOnSaturation(); 207 .RetiresOnSaturation();
191 208
192 std::unique_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); 209 std::unique_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
193 download_file_.reset(new TestDownloadFileImpl( 210 download_file_.reset(new TestDownloadFileImpl(
194 std::move(save_info), base::FilePath(), 211 std::move(save_info), base::FilePath(),
195 std::unique_ptr<ByteStreamReader>(input_stream_), 212 std::unique_ptr<ByteStreamReader>(input_stream_),
196 net::NetLogWithSource(), observer_factory_.GetWeakPtr())); 213 net::NetLogWithSource(), is_sparse_file,
214 observer_factory_.GetWeakPtr()));
197 215
198 EXPECT_CALL(*input_stream_, Read(_, _)) 216 EXPECT_CALL(*input_stream_, Read(_, _))
199 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) 217 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY))
200 .RetiresOnSaturation(); 218 .RetiresOnSaturation();
201 219
202 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this); 220 base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this);
203 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE; 221 DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
204 base::RunLoop loop_runner; 222 base::RunLoop loop_runner;
205 download_file_->Initialize(base::Bind( 223 download_file_->Initialize(base::Bind(
206 &DownloadFileTest::SetInterruptReasonCallback, 224 &DownloadFileTest::SetInterruptReasonCallback,
207 weak_ptr_factory.GetWeakPtr(), loop_runner.QuitClosure(), &result)); 225 weak_ptr_factory.GetWeakPtr(), loop_runner.QuitClosure(), &result));
208 loop_runner.Run(); 226 loop_runner.Run();
209 227
210 ::testing::Mock::VerifyAndClearExpectations(input_stream_); 228 ::testing::Mock::VerifyAndClearExpectations(input_stream_);
211 return result == DOWNLOAD_INTERRUPT_REASON_NONE; 229 return result == DOWNLOAD_INTERRUPT_REASON_NONE;
212 } 230 }
213 231
214 void DestroyDownloadFile(int offset) { 232 void DestroyDownloadFile(int offset, bool compare_disk_data = true) {
215 EXPECT_FALSE(download_file_->InProgress()); 233 EXPECT_FALSE(download_file_->InProgress());
216 234
217 // Make sure the data has been properly written to disk. 235 // Make sure the data has been properly written to disk.
218 std::string disk_data; 236 if (compare_disk_data) {
219 EXPECT_TRUE(base::ReadFileToString(download_file_->FullPath(), &disk_data)); 237 std::string disk_data;
220 EXPECT_EQ(expected_data_, disk_data); 238 EXPECT_TRUE(
239 base::ReadFileToString(download_file_->FullPath(), &disk_data));
240 EXPECT_EQ(expected_data_, disk_data);
241 }
221 242
222 // Make sure the Browser and File threads outlive the DownloadFile 243 // Make sure the Browser and File threads outlive the DownloadFile
223 // to satisfy thread checks inside it. 244 // to satisfy thread checks inside it.
224 download_file_.reset(); 245 download_file_.reset();
225 } 246 }
226 247
227 // Setup the stream to do be a data append; don't actually trigger 248 // Setup the stream to append data or write from |offset| to the file.
228 // the callback or do verifications. 249 // Don't actually trigger the callback or do verifications.
229 void SetupDataAppend(const char **data_chunks, size_t num_chunks, 250 void SetupDataAppend(const char** data_chunks,
230 ::testing::Sequence s) { 251 size_t num_chunks,
231 DCHECK(input_stream_); 252 MockByteStreamReader* stream_reader,
253 ::testing::Sequence s,
254 int64_t offset = -1) {
255 DCHECK(stream_reader);
256 size_t current_pos = static_cast<size_t>(offset);
232 for (size_t i = 0; i < num_chunks; i++) { 257 for (size_t i = 0; i < num_chunks; i++) {
233 const char *source_data = data_chunks[i]; 258 const char *source_data = data_chunks[i];
234 size_t length = strlen(source_data); 259 size_t length = strlen(source_data);
235 scoped_refptr<net::IOBuffer> data = new net::IOBuffer(length); 260 scoped_refptr<net::IOBuffer> data = new net::IOBuffer(length);
236 memcpy(data->data(), source_data, length); 261 memcpy(data->data(), source_data, length);
237 EXPECT_CALL(*input_stream_, Read(_, _)) 262 EXPECT_CALL(*stream_reader, Read(_, _))
238 .InSequence(s) 263 .InSequence(s)
239 .WillOnce(DoAll(SetArgPointee<0>(data), 264 .WillOnce(DoAll(SetArgPointee<0>(data), SetArgPointee<1>(length),
240 SetArgPointee<1>(length),
241 Return(ByteStreamReader::STREAM_HAS_DATA))) 265 Return(ByteStreamReader::STREAM_HAS_DATA)))
242 .RetiresOnSaturation(); 266 .RetiresOnSaturation();
243 expected_data_ += source_data; 267
268 if (offset < 0) {
269 // Append data.
270 expected_data_ += source_data;
271 continue;
272 }
273
274 // Write from offset. May fill holes with '\0'.
275 size_t new_len = current_pos + length;
276 if (new_len > expected_data_.size())
277 expected_data_.append(new_len - expected_data_.size(), '\0');
278 expected_data_.replace(current_pos, length, source_data);
279 current_pos += length;
244 } 280 }
245 } 281 }
246 282
247 void VerifyStreamAndSize() { 283 void VerifyStreamAndSize() {
248 ::testing::Mock::VerifyAndClearExpectations(input_stream_); 284 ::testing::Mock::VerifyAndClearExpectations(input_stream_);
249 int64_t size; 285 int64_t size;
250 EXPECT_TRUE(base::GetFileSize(download_file_->FullPath(), &size)); 286 EXPECT_TRUE(base::GetFileSize(download_file_->FullPath(), &size));
251 EXPECT_EQ(expected_data_.size(), static_cast<size_t>(size)); 287 EXPECT_EQ(expected_data_.size(), static_cast<size_t>(size));
252 } 288 }
253 289
254 // TODO(rdsmith): Manage full percentage issues properly. 290 // TODO(rdsmith): Manage full percentage issues properly.
255 void AppendDataToFile(const char **data_chunks, size_t num_chunks) { 291 void AppendDataToFile(const char **data_chunks, size_t num_chunks) {
256 ::testing::Sequence s1; 292 ::testing::Sequence s1;
257 SetupDataAppend(data_chunks, num_chunks, s1); 293 SetupDataAppend(data_chunks, num_chunks, input_stream_, s1);
258 EXPECT_CALL(*input_stream_, Read(_, _)) 294 EXPECT_CALL(*input_stream_, Read(_, _))
259 .InSequence(s1) 295 .InSequence(s1)
260 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY)) 296 .WillOnce(Return(ByteStreamReader::STREAM_EMPTY))
261 .RetiresOnSaturation(); 297 .RetiresOnSaturation();
262 sink_callback_.Run(); 298 sink_callback_.Run();
263 VerifyStreamAndSize(); 299 VerifyStreamAndSize();
264 } 300 }
265 301
266 void SetupFinishStream(DownloadInterruptReason interrupt_reason, 302 void SetupFinishStream(DownloadInterruptReason interrupt_reason,
267 ::testing::Sequence s) { 303 MockByteStreamReader* stream_reader,
268 EXPECT_CALL(*input_stream_, Read(_, _)) 304 ::testing::Sequence s) {
305 EXPECT_CALL(*stream_reader, Read(_, _))
269 .InSequence(s) 306 .InSequence(s)
270 .WillOnce(Return(ByteStreamReader::STREAM_COMPLETE)) 307 .WillOnce(Return(ByteStreamReader::STREAM_COMPLETE))
271 .RetiresOnSaturation(); 308 .RetiresOnSaturation();
272 EXPECT_CALL(*input_stream_, GetStatus()) 309 EXPECT_CALL(*stream_reader, GetStatus())
273 .InSequence(s) 310 .InSequence(s)
274 .WillOnce(Return(interrupt_reason)) 311 .WillOnce(Return(interrupt_reason))
275 .RetiresOnSaturation(); 312 .RetiresOnSaturation();
276 EXPECT_CALL(*input_stream_, RegisterCallback(_)) 313 EXPECT_CALL(*stream_reader, RegisterCallback(_)).RetiresOnSaturation();
277 .RetiresOnSaturation();
278 } 314 }
279 315
280 void FinishStream(DownloadInterruptReason interrupt_reason, 316 void FinishStream(DownloadInterruptReason interrupt_reason,
281 bool check_observer, 317 bool check_observer,
282 const std::string& expected_hash) { 318 const std::string& expected_hash) {
283 ::testing::Sequence s1; 319 ::testing::Sequence s1;
284 SetupFinishStream(interrupt_reason, s1); 320 SetupFinishStream(interrupt_reason, input_stream_, s1);
285 sink_callback_.Run(); 321 sink_callback_.Run();
286 VerifyStreamAndSize(); 322 VerifyStreamAndSize();
287 if (check_observer) { 323 if (check_observer) {
288 EXPECT_CALL(*(observer_.get()), 324 EXPECT_CALL(*(observer_.get()),
289 MockDestinationCompleted(_, expected_hash)); 325 MockDestinationCompleted(_, expected_hash));
290 base::RunLoop().RunUntilIdle(); 326 base::RunLoop().RunUntilIdle();
291 ::testing::Mock::VerifyAndClearExpectations(observer_.get()); 327 ::testing::Mock::VerifyAndClearExpectations(observer_.get());
292 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _)) 328 EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _))
293 .Times(AnyNumber()) 329 .Times(AnyNumber())
294 .WillRepeatedly( 330 .WillRepeatedly(
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 base::Bind(&DownloadFileTest::SetRenameResult, 384 base::Bind(&DownloadFileTest::SetRenameResult,
349 base::Unretained(this), 385 base::Unretained(this),
350 loop_runner.QuitClosure(), 386 loop_runner.QuitClosure(),
351 &result_reason, 387 &result_reason,
352 result_path_p); 388 result_path_p);
353 InvokeRenameMethod(method, full_path, completion_callback); 389 InvokeRenameMethod(method, full_path, completion_callback);
354 loop_runner.Run(); 390 loop_runner.Run();
355 return result_reason; 391 return result_reason;
356 } 392 }
357 393
394 // Prepare two byte streams to write to the same file sink.
395 void PrepareMultipleStreams(int64_t second_stream_length) {
396 // Create a sparse file.
397 ASSERT_TRUE(CreateDownloadFile(0, true, true));
398 base::FilePath initial_path(download_file_->FullPath());
399 EXPECT_TRUE(base::PathExists(initial_path));
400 DCHECK(download_file_);
401
402 const char* stream_0_data[] = {kTestData1, kTestData2};
403 const char* stream_1_data[] = {kTestData4, kTestData5};
404 size_t stream_1_offset = strlen(kTestData1) + strlen(kTestData2);
405
406 // Register second SourceStream entry for the second stream.
407 // The first stream should be registered in ctor of DownloadFile.
408 DownloadFileImpl::SourceStreams& source_streams =
409 download_file_->source_streams_;
410 EXPECT_EQ(static_cast<size_t>(1), source_streams.size());
411 source_streams[stream_1_offset] =
412 base::MakeUnique<DownloadFileImpl::SourceStream>(stream_1_offset,
413 second_stream_length);
414
415 // Create the second byte stream. Will be moved to DownloadFile.
416 input_stream_1_ = new MockByteStreamReader();
417
418 ::testing::Sequence s0;
419 ::testing::Sequence s1;
420 SetupDataAppend(stream_1_data, 2, input_stream_1_, s1, stream_1_offset);
421 SetupDataAppend(stream_0_data, 2, input_stream_, s0, 0);
422 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_, s0);
423
424 // Expectation on MockByteStreamReader for MultipleStreams tests:
425 // 1. RegisterCallback: Must called twice. One to set the callback, the
426 // other to release the stream.
427 // 2. Read: If filled with N buffer, called (N+1) times, where the last Read
428 // call doesn't read any data but returns STRAM_COMPLETE.
429 // The stream may terminate in the middle and less Read calls are expected.
430 // 3. GetStatus: Only called if the stream is completed and last Read call
431 // returns STREAM_COMPLETE.
432 if (second_stream_length == 0)
433 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_1_, s1);
434 else
435 EXPECT_CALL(*input_stream_1_, RegisterCallback(_)).RetiresOnSaturation();
436
437 EXPECT_CALL(*input_stream_1_, RegisterCallback(_)).RetiresOnSaturation();
438 }
439
440 void VerifySourceStreamsStates(const SourceStreamTestData& data) {
441 DCHECK(download_file_->source_streams_.find(data.offset) !=
442 download_file_->source_streams_.end());
443 DownloadFileImpl::SourceStream* stream =
444 download_file_->source_streams_[data.offset].get();
445 DCHECK(stream);
446 EXPECT_EQ(data.offset, stream->offset());
447 EXPECT_EQ(data.bytes_written, stream->bytes_written());
448 EXPECT_EQ(data.finished, stream->is_finished());
449 }
450
451 int64_t TotalBytesReceived() const {
452 DCHECK(download_file_);
453 return download_file_->TotalBytesReceived();
454 }
455
358 std::unique_ptr<StrictMock<MockDownloadDestinationObserver>> observer_; 456 std::unique_ptr<StrictMock<MockDownloadDestinationObserver>> observer_;
359 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_; 457 base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_;
360 458
361 // DownloadFile instance we are testing. 459 // DownloadFile instance we are testing.
362 std::unique_ptr<DownloadFile> download_file_; 460 std::unique_ptr<DownloadFileImpl> download_file_;
363 461
364 // Stream for sending data into the download file. 462 // Stream for sending data into the download file.
365 // Owned by download_file_; will be alive for lifetime of download_file_. 463 // Owned by download_file_; will be alive for lifetime of download_file_.
366 StrictMock<MockByteStreamReader>* input_stream_; 464 StrictMock<MockByteStreamReader>* input_stream_;
367 465
466 // A second byte stream to test multiple stream write.
467 MockByteStreamReader* input_stream_1_;
468
368 // Sink callback data for stream. 469 // Sink callback data for stream.
369 base::Closure sink_callback_; 470 base::Closure sink_callback_;
370 471
371 // Latest update sent to the observer. 472 // Latest update sent to the observer.
372 int64_t bytes_; 473 int64_t bytes_;
373 int64_t bytes_per_sec_; 474 int64_t bytes_per_sec_;
374 475
375 private: 476 private:
376 void SetRenameResult(const base::Closure& closure, 477 void SetRenameResult(const base::Closure& closure,
377 DownloadInterruptReason* reason_p, 478 DownloadInterruptReason* reason_p,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 // the value parameter. 516 // the value parameter.
416 INSTANTIATE_TEST_CASE_P(DownloadFile, 517 INSTANTIATE_TEST_CASE_P(DownloadFile,
417 DownloadFileTestWithRename, 518 DownloadFileTestWithRename,
418 ::testing::Values(RENAME_AND_ANNOTATE, 519 ::testing::Values(RENAME_AND_ANNOTATE,
419 RENAME_AND_UNIQUIFY)); 520 RENAME_AND_UNIQUIFY));
420 521
421 const char DownloadFileTest::kTestData1[] = 522 const char DownloadFileTest::kTestData1[] =
422 "Let's write some data to the file!\n"; 523 "Let's write some data to the file!\n";
423 const char DownloadFileTest::kTestData2[] = "Writing more data.\n"; 524 const char DownloadFileTest::kTestData2[] = "Writing more data.\n";
424 const char DownloadFileTest::kTestData3[] = "Final line."; 525 const char DownloadFileTest::kTestData3[] = "Final line.";
526 const char DownloadFileTest::kTestData4[] = "abcdefg";
527 const char DownloadFileTest::kTestData5[] = "01234";
425 const char DownloadFileTest::kDataHash[] = 528 const char DownloadFileTest::kDataHash[] =
426 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8"; 529 "CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8";
427 const char DownloadFileTest::kEmptyHash[] = 530 const char DownloadFileTest::kEmptyHash[] =
428 "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"; 531 "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855";
429 532
430 const uint32_t DownloadFileTest::kDummyDownloadId = 23; 533 const uint32_t DownloadFileTest::kDummyDownloadId = 23;
431 const int DownloadFileTest::kDummyChildId = 3; 534 const int DownloadFileTest::kDummyChildId = 3;
432 const int DownloadFileTest::kDummyRequestId = 67; 535 const int DownloadFileTest::kDummyRequestId = 67;
433 536
434 // Rename the file before any data is downloaded, after some has, after it all 537 // Rename the file before any data is downloaded, after some has, after it all
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 DestroyDownloadFile(0); 848 DestroyDownloadFile(0);
746 } 849 }
747 850
748 TEST_F(DownloadFileTest, StreamNonEmptySuccess) { 851 TEST_F(DownloadFileTest, StreamNonEmptySuccess) {
749 ASSERT_TRUE(CreateDownloadFile(0, true)); 852 ASSERT_TRUE(CreateDownloadFile(0, true));
750 base::FilePath initial_path(download_file_->FullPath()); 853 base::FilePath initial_path(download_file_->FullPath());
751 EXPECT_TRUE(base::PathExists(initial_path)); 854 EXPECT_TRUE(base::PathExists(initial_path));
752 855
753 const char* chunks1[] = { kTestData1, kTestData2 }; 856 const char* chunks1[] = { kTestData1, kTestData2 };
754 ::testing::Sequence s1; 857 ::testing::Sequence s1;
755 SetupDataAppend(chunks1, 2, s1); 858 SetupDataAppend(chunks1, 2, input_stream_, s1);
756 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, s1); 859 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_, s1);
757 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); 860 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
758 sink_callback_.Run(); 861 sink_callback_.Run();
759 VerifyStreamAndSize(); 862 VerifyStreamAndSize();
760 base::RunLoop().RunUntilIdle(); 863 base::RunLoop().RunUntilIdle();
761 DestroyDownloadFile(0); 864 DestroyDownloadFile(0);
762 } 865 }
763 866
764 TEST_F(DownloadFileTest, StreamNonEmptyError) { 867 TEST_F(DownloadFileTest, StreamNonEmptyError) {
765 ASSERT_TRUE(CreateDownloadFile(0, true)); 868 ASSERT_TRUE(CreateDownloadFile(0, true));
766 base::FilePath initial_path(download_file_->FullPath()); 869 base::FilePath initial_path(download_file_->FullPath());
767 EXPECT_TRUE(base::PathExists(initial_path)); 870 EXPECT_TRUE(base::PathExists(initial_path));
768 871
769 const char* chunks1[] = { kTestData1, kTestData2 }; 872 const char* chunks1[] = { kTestData1, kTestData2 };
770 ::testing::Sequence s1; 873 ::testing::Sequence s1;
771 SetupDataAppend(chunks1, 2, s1); 874 SetupDataAppend(chunks1, 2, input_stream_, s1);
772 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, s1); 875 SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED,
876 input_stream_, s1);
773 877
774 EXPECT_CALL(*(observer_.get()), 878 EXPECT_CALL(*(observer_.get()),
775 MockDestinationError( 879 MockDestinationError(
776 DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, _, _)) 880 DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, _, _))
777 .WillOnce(InvokeWithoutArgs( 881 .WillOnce(InvokeWithoutArgs(
778 this, &DownloadFileTest::ConfirmUpdateDownloadInfo)); 882 this, &DownloadFileTest::ConfirmUpdateDownloadInfo));
779 883
780 // If this next EXPECT_CALL fails flakily, it's probably a real failure. 884 // If this next EXPECT_CALL fails flakily, it's probably a real failure.
781 // We'll be getting a stream of UpdateDownload calls from the timer, and 885 // We'll be getting a stream of UpdateDownload calls from the timer, and
782 // the last one may have the correct information even if the failure 886 // the last one may have the correct information even if the failure
783 // doesn't produce an update, as the timer update may have triggered at the 887 // doesn't produce an update, as the timer update may have triggered at the
784 // same time. 888 // same time.
785 EXPECT_CALL(*(observer_.get()), 889 EXPECT_CALL(*(observer_.get()),
786 CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2), _)); 890 CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2), _));
787 891
788 sink_callback_.Run(); 892 sink_callback_.Run();
789 base::RunLoop().RunUntilIdle(); 893 base::RunLoop().RunUntilIdle();
790 VerifyStreamAndSize(); 894 VerifyStreamAndSize();
791 DestroyDownloadFile(0); 895 DestroyDownloadFile(0);
792 } 896 }
793 897
898 // Tests for concurrent streams handling, used for parallel download.
899 //
900 // Activate both streams at the same time.
901 TEST_F(DownloadFileTest, MutipleStreamsWrite) {
902 PrepareMultipleStreams(0);
903 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
904
905 int64_t stream_0_length =
906 static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2));
907 int64_t stream_1_length =
908 static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5));
909
910 download_file_->AddByteStream(
911 std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length);
912 sink_callback_.Run();
913 base::RunLoop().RunUntilIdle();
914
915 SourceStreamTestData stream_data_0(0, stream_0_length, true);
916 SourceStreamTestData stream_data_1(stream_0_length, stream_1_length, true);
917 VerifySourceStreamsStates(stream_data_0);
918 VerifySourceStreamsStates(stream_data_1);
919 EXPECT_EQ(stream_0_length + stream_1_length, TotalBytesReceived());
920
921 DestroyDownloadFile(0);
922 }
923
924 // Activate and deplete one stream, later add the second stream.
925 TEST_F(DownloadFileTest, MutipleStreamsOneStreamFirst) {
926 PrepareMultipleStreams(0);
927
928 int64_t stream_0_length =
929 static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2));
930 int64_t stream_1_length =
931 static_cast<int64_t>(strlen(kTestData4) + strlen(kTestData5));
932
933 // Deplete the first stream.
934 sink_callback_.Run();
935 base::RunLoop().RunUntilIdle();
936
937 SourceStreamTestData stream_data_0(0, stream_0_length, true);
938 SourceStreamTestData stream_data_1(stream_0_length, 0, false);
939 VerifySourceStreamsStates(stream_data_0);
940 VerifySourceStreamsStates(stream_data_1);
941 EXPECT_EQ(stream_0_length, TotalBytesReceived());
942
943 // Won't inform the observer until the second stream is depleted.
944 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
945
946 // Drain the second stream after the first stream is depleted.
947 download_file_->AddByteStream(
948 std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length);
949 base::RunLoop().RunUntilIdle();
950
951 stream_data_1.bytes_written = stream_1_length;
952 stream_data_1.finished = true;
953 VerifySourceStreamsStates(stream_data_0);
954 VerifySourceStreamsStates(stream_data_1);
955 EXPECT_EQ(stream_0_length + stream_1_length, TotalBytesReceived());
956
957 DestroyDownloadFile(0);
958 }
959
960 // Two streams write to one sink, the second stream has a limited length.
961 TEST_F(DownloadFileTest, MutipleStreamsLimitedLength) {
962 // The second stream has two buffers, kTestData4 and kTestData5.
963 // The length limit is set to less than the length of kTestData4.
964 // kTestData4 should be partially written to disk, where kTestData5 should be
965 // ignored.
966 int64_t stream_0_length =
967 static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2));
968 int64_t stream_1_length = static_cast<int64_t>(strlen(kTestData4)) - 1;
969 PrepareMultipleStreams(stream_1_length);
970
971 EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
972
973 download_file_->AddByteStream(
974 std::unique_ptr<MockByteStreamReader>(input_stream_1_), stream_0_length);
975 sink_callback_.Run();
976 base::RunLoop().RunUntilIdle();
977
978 SourceStreamTestData stream_data_0(0, stream_0_length, true);
979 SourceStreamTestData stream_data_1(stream_0_length, stream_1_length, true);
980 VerifySourceStreamsStates(stream_data_0);
981 VerifySourceStreamsStates(stream_data_1);
982 EXPECT_EQ(stream_0_length + stream_1_length, TotalBytesReceived());
983
984 std::string disk_data, expected_data;
985 EXPECT_TRUE(base::ReadFileToString(download_file_->FullPath(), &disk_data));
986 expected_data.append(kTestData1).append(kTestData2).append(kTestData4);
987 expected_data = expected_data.substr(0, stream_0_length + stream_1_length);
988 EXPECT_EQ(expected_data, disk_data);
989
990 // Finish the second stream.
991 // TODO(xingliu): Refactor test code to deal with unfinished streams.
992 scoped_refptr<net::IOBuffer> data = new net::IOBuffer(strlen(kTestData5));
993 size_t size;
994 input_stream_1_->Read(&data, &size);
995
996 DestroyDownloadFile(0, false);
997 }
998
794 } // namespace content 999 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/download_file_impl.cc ('k') | content/browser/download/download_stats.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698