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

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

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

Powered by Google App Engine
This is Rietveld 408576698