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

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

Issue 2806923002: Don't create parallel request if download is about to complete (Closed)
Patch Set: add UMA and finch Created 3 years, 8 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 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "content/browser/download/parallel_download_job.h" 5 #include "content/browser/download/parallel_download_job.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
(...skipping 22 matching lines...) Expand all
33 33
34 } // namespace 34 } // namespace
35 35
36 class ParallelDownloadJobForTest : public ParallelDownloadJob { 36 class ParallelDownloadJobForTest : public ParallelDownloadJob {
37 public: 37 public:
38 ParallelDownloadJobForTest( 38 ParallelDownloadJobForTest(
39 DownloadItemImpl* download_item, 39 DownloadItemImpl* download_item,
40 std::unique_ptr<DownloadRequestHandleInterface> request_handle, 40 std::unique_ptr<DownloadRequestHandleInterface> request_handle,
41 const DownloadCreateInfo& create_info, 41 const DownloadCreateInfo& create_info,
42 int request_count, 42 int request_count,
43 int64_t min_slice_size) 43 int64_t min_slice_size,
44 int min_remaining_time)
44 : ParallelDownloadJob(download_item, 45 : ParallelDownloadJob(download_item,
45 std::move(request_handle), 46 std::move(request_handle),
46 create_info), 47 create_info),
47 request_count_(request_count), 48 request_count_(request_count),
48 min_slice_size_(min_slice_size) {} 49 min_slice_size_(min_slice_size),
50 min_remaining_time_(min_remaining_time) {}
49 51
50 void CreateRequest(int64_t offset, int64_t length) override { 52 void CreateRequest(int64_t offset, int64_t length) override {
51 std::unique_ptr<DownloadWorker> worker = 53 std::unique_ptr<DownloadWorker> worker =
52 base::MakeUnique<DownloadWorker>(this, offset, length); 54 base::MakeUnique<DownloadWorker>(this, offset, length);
53 55
54 DCHECK(workers_.find(offset) == workers_.end()); 56 DCHECK(workers_.find(offset) == workers_.end());
55 workers_[offset] = std::move(worker); 57 workers_[offset] = std::move(worker);
56 } 58 }
57 59
58 ParallelDownloadJob::WorkerMap& workers() { return workers_; } 60 ParallelDownloadJob::WorkerMap& workers() { return workers_; }
59 61
60 int GetParallelRequestCount() const override { return request_count_; } 62 int GetParallelRequestCount() const override { return request_count_; }
61 int64_t GetMinSliceSize() const override { return min_slice_size_; } 63 int64_t GetMinSliceSize() const override { return min_slice_size_; }
64 int GetMinRemainingTimeInSeconds() const override {
65 return min_remaining_time_;
66 }
62 67
63 void OnByteStreamReady( 68 void OnByteStreamReady(
64 DownloadWorker* worker, 69 DownloadWorker* worker,
65 std::unique_ptr<ByteStreamReader> stream_reader) override { 70 std::unique_ptr<ByteStreamReader> stream_reader) override {
66 CountOnByteStreamReady(); 71 CountOnByteStreamReady();
67 } 72 }
68 73
69 MOCK_METHOD0(CountOnByteStreamReady, void()); 74 MOCK_METHOD0(CountOnByteStreamReady, void());
70 75
71 private: 76 private:
72 int request_count_; 77 int request_count_;
73 int min_slice_size_; 78 int min_slice_size_;
79 int min_remaining_time_;
74 DISALLOW_COPY_AND_ASSIGN(ParallelDownloadJobForTest); 80 DISALLOW_COPY_AND_ASSIGN(ParallelDownloadJobForTest);
75 }; 81 };
76 82
77 class ParallelDownloadJobTest : public testing::Test { 83 class ParallelDownloadJobTest : public testing::Test {
78 public: 84 public:
79 void CreateParallelJob(int64_t initial_request_offset, 85 void CreateParallelJob(int64_t initial_request_offset,
80 int64_t content_length, 86 int64_t content_length,
81 const DownloadItem::ReceivedSlices& slices, 87 const DownloadItem::ReceivedSlices& slices,
82 int request_count, 88 int request_count,
83 int64_t min_slice_size) { 89 int64_t min_slice_size,
90 int min_remaining_time) {
84 item_delegate_ = base::MakeUnique<DownloadItemImplDelegate>(); 91 item_delegate_ = base::MakeUnique<DownloadItemImplDelegate>();
85 download_item_ = base::MakeUnique<NiceMock<MockDownloadItemImpl>>( 92 download_item_ = base::MakeUnique<NiceMock<MockDownloadItemImpl>>(
86 item_delegate_.get(), slices); 93 item_delegate_.get(), slices);
94 EXPECT_CALL(*download_item_, GetTotalBytes())
95 .WillRepeatedly(
96 testing::Return(initial_request_offset + content_length));
97 EXPECT_CALL(*download_item_, GetReceivedBytes())
98 .WillRepeatedly(testing::Return(initial_request_offset));
99
87 DownloadCreateInfo info; 100 DownloadCreateInfo info;
88 info.offset = initial_request_offset; 101 info.offset = initial_request_offset;
89 info.total_bytes = content_length; 102 info.total_bytes = content_length;
90 std::unique_ptr<MockDownloadRequestHandle> request_handle = 103 std::unique_ptr<MockDownloadRequestHandle> request_handle =
91 base::MakeUnique<MockDownloadRequestHandle>(); 104 base::MakeUnique<MockDownloadRequestHandle>();
92 mock_request_handle_ = request_handle.get(); 105 mock_request_handle_ = request_handle.get();
93 job_ = base::MakeUnique<ParallelDownloadJobForTest>( 106 job_ = base::MakeUnique<ParallelDownloadJobForTest>(
94 download_item_.get(), std::move(request_handle), info, request_count, 107 download_item_.get(), std::move(request_handle), info, request_count,
95 min_slice_size); 108 min_slice_size, min_remaining_time);
96 } 109 }
97 110
98 void DestroyParallelJob() { 111 void DestroyParallelJob() {
99 job_.reset(); 112 job_.reset();
100 download_item_.reset(); 113 download_item_.reset();
101 item_delegate_.reset(); 114 item_delegate_.reset();
102 mock_request_handle_ = nullptr; 115 mock_request_handle_ = nullptr;
103 } 116 }
104 117
105 void BuildParallelRequests() { job_->BuildParallelRequests(); } 118 void BuildParallelRequests() { job_->BuildParallelRequests(); }
(...skipping 26 matching lines...) Expand all
132 // Request handle for the original request. 145 // Request handle for the original request.
133 MockDownloadRequestHandle* mock_request_handle_; 146 MockDownloadRequestHandle* mock_request_handle_;
134 }; 147 };
135 148
136 // Test if parallel requests can be built correctly for a new download without 149 // Test if parallel requests can be built correctly for a new download without
137 // existing slices. 150 // existing slices.
138 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequestsWithoutSlices) { 151 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequestsWithoutSlices) {
139 // Totally 2 requests for 100 bytes. 152 // Totally 2 requests for 100 bytes.
140 // Original request: Range:0-49, for 50 bytes. 153 // Original request: Range:0-49, for 50 bytes.
141 // Task 1: Range:50-, for 50 bytes. 154 // Task 1: Range:50-, for 50 bytes.
142 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1); 155 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1, 10);
143 BuildParallelRequests(); 156 BuildParallelRequests();
144 EXPECT_EQ(1, static_cast<int>(job_->workers().size())); 157 EXPECT_EQ(1, static_cast<int>(job_->workers().size()));
145 VerifyWorker(50, 0); 158 VerifyWorker(50, 0);
146 DestroyParallelJob(); 159 DestroyParallelJob();
147 160
148 // Totally 3 requests for 100 bytes. 161 // Totally 3 requests for 100 bytes.
149 // Original request: Range:0-32, for 33 bytes. 162 // Original request: Range:0-32, for 33 bytes.
150 // Task 1: Range:33-65, for 33 bytes. 163 // Task 1: Range:33-65, for 33 bytes.
151 // Task 2: Range:66-, for 34 bytes. 164 // Task 2: Range:66-, for 34 bytes.
152 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3, 1); 165 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3, 1, 10);
153 BuildParallelRequests(); 166 BuildParallelRequests();
154 EXPECT_EQ(2, static_cast<int>(job_->workers().size())); 167 EXPECT_EQ(2, static_cast<int>(job_->workers().size()));
155 VerifyWorker(33, 33); 168 VerifyWorker(33, 33);
156 VerifyWorker(66, 0); 169 VerifyWorker(66, 0);
157 DestroyParallelJob(); 170 DestroyParallelJob();
158 171
159 // Less than 2 requests, do nothing. 172 // Less than 2 requests, do nothing.
160 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 1, 1); 173 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 1, 1, 10);
161 BuildParallelRequests(); 174 BuildParallelRequests();
162 EXPECT_TRUE(job_->workers().empty()); 175 EXPECT_TRUE(job_->workers().empty());
163 DestroyParallelJob(); 176 DestroyParallelJob();
164 177
165 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 0, 1); 178 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 0, 1, 10);
166 BuildParallelRequests(); 179 BuildParallelRequests();
167 EXPECT_TRUE(job_->workers().empty()); 180 EXPECT_TRUE(job_->workers().empty());
168 DestroyParallelJob(); 181 DestroyParallelJob();
169 182
170 // Content-length is 0, do nothing. 183 // Content-length is 0, do nothing.
171 CreateParallelJob(0, 0, DownloadItem::ReceivedSlices(), 3, 1); 184 CreateParallelJob(0, 0, DownloadItem::ReceivedSlices(), 3, 1, 10);
172 BuildParallelRequests(); 185 BuildParallelRequests();
173 EXPECT_TRUE(job_->workers().empty()); 186 EXPECT_TRUE(job_->workers().empty());
174 DestroyParallelJob(); 187 DestroyParallelJob();
175 } 188 }
176 189
177 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequestsWithSlices) { 190 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequestsWithSlices) {
178 // File size: 100 bytes. 191 // File size: 100 bytes.
179 // Received slices: [0, 17] 192 // Received slices: [0, 17]
180 // Original request: Range:12-. Content-length: 88. 193 // Original request: Range:12-. Content-length: 88.
181 // Totally 3 requests for 83 bytes. 194 // Totally 3 requests for 83 bytes.
182 // Original request: Range:12-43. 195 // Original request: Range:12-43.
183 // Task 1: Range:44-70, for 27 bytes. 196 // Task 1: Range:44-70, for 27 bytes.
184 // Task 2: Range:71-, for 29 bytes. 197 // Task 2: Range:71-, for 29 bytes.
185 DownloadItem::ReceivedSlices slices = {DownloadItem::ReceivedSlice(0, 17)}; 198 DownloadItem::ReceivedSlices slices = {DownloadItem::ReceivedSlice(0, 17)};
186 CreateParallelJob(12, 88, slices, 3, 1); 199 CreateParallelJob(12, 88, slices, 3, 1, 10);
187 BuildParallelRequests(); 200 BuildParallelRequests();
188 EXPECT_EQ(2, static_cast<int>(job_->workers().size())); 201 EXPECT_EQ(2, static_cast<int>(job_->workers().size()));
189 VerifyWorker(44, 27); 202 VerifyWorker(44, 27);
190 VerifyWorker(71, 0); 203 VerifyWorker(71, 0);
191 DestroyParallelJob(); 204 DestroyParallelJob();
192 205
193 // File size: 100 bytes. 206 // File size: 100 bytes.
194 // Received slices: [0, 98], Range:0-97. 207 // Received slices: [0, 60], Range:0-59.
195 // Original request: Range:98-. Content-length: 2. 208 // Original request: Range:60-. Content-length: 40.
196 // 2 bytes left for 4 requests. Only 1 additional request. 209 // 40 bytes left for 4 requests. Only 1 additional request.
197 // Original request: Range:98-99, for 1 bytes. 210 // Original request: Range:60-79, for 20 bytes.
198 // Task 1: Range:99-, for 1 bytes. 211 // Task 1: Range:80-, for 20 bytes.
199 slices = {DownloadItem::ReceivedSlice(0, 98)}; 212 slices = {DownloadItem::ReceivedSlice(0, 60)};
200 CreateParallelJob(98, 2, slices, 4, 1); 213 CreateParallelJob(60, 40, slices, 4, 20, 10);
201 BuildParallelRequests(); 214 BuildParallelRequests();
202 EXPECT_EQ(1, static_cast<int>(job_->workers().size())); 215 EXPECT_EQ(1, static_cast<int>(job_->workers().size()));
203 VerifyWorker(99, 0); 216 VerifyWorker(80, 0);
204 DestroyParallelJob(); 217 DestroyParallelJob();
205 218
206 // Content-Length is 0, no additional requests. 219 // Content-Length is 0, no additional requests.
207 slices = {DownloadItem::ReceivedSlice(0, 100)}; 220 slices = {DownloadItem::ReceivedSlice(0, 100)};
208 CreateParallelJob(100, 0, slices, 3, 1); 221 CreateParallelJob(100, 0, slices, 3, 1, 10);
209 BuildParallelRequests(); 222 BuildParallelRequests();
210 EXPECT_TRUE(job_->workers().empty()); 223 EXPECT_TRUE(job_->workers().empty());
211 DestroyParallelJob(); 224 DestroyParallelJob();
212 225
213 // File size: 100 bytes. 226 // File size: 100 bytes.
214 // Original request: Range:0-. Content-length: 12(Incorrect server header). 227 // Original request: Range:0-. Content-length: 12(Incorrect server header).
215 // The request count is 2, however the file contains 3 holes, and we don't 228 // The request count is 2, however the file contains 3 holes, and we don't
216 // know if the last slice is completed, so there should be 3 requests in 229 // know if the last slice is completed, so there should be 3 requests in
217 // parallel and the last request is an out-of-range request. 230 // parallel and the last request is an out-of-range request.
218 slices = { 231 slices = {
219 DownloadItem::ReceivedSlice(10, 10), DownloadItem::ReceivedSlice(20, 10), 232 DownloadItem::ReceivedSlice(10, 10), DownloadItem::ReceivedSlice(20, 10),
220 DownloadItem::ReceivedSlice(40, 10), DownloadItem::ReceivedSlice(90, 10)}; 233 DownloadItem::ReceivedSlice(40, 10), DownloadItem::ReceivedSlice(90, 10)};
221 CreateParallelJob(0, 12, slices, 2, 1); 234 CreateParallelJob(0, 12, slices, 2, 1, 10);
222 BuildParallelRequests(); 235 BuildParallelRequests();
223 EXPECT_EQ(3, static_cast<int>(job_->workers().size())); 236 EXPECT_EQ(3, static_cast<int>(job_->workers().size()));
224 VerifyWorker(30, 10); 237 VerifyWorker(30, 10);
225 VerifyWorker(50, 40); 238 VerifyWorker(50, 40);
226 VerifyWorker(100, 0); 239 VerifyWorker(100, 0);
227 DestroyParallelJob(); 240 DestroyParallelJob();
228 } 241 }
229 242
230 // Pause, cancel, resume can be called before or after the worker establish 243 // Pause, cancel, resume can be called before or after the worker establish
231 // the byte stream. 244 // the byte stream.
232 // These tests ensure the states consistency between the job and workers. 245 // These tests ensure the states consistency between the job and workers.
233 246
234 // Ensure cancel before building the requests will result in no requests are 247 // Ensure cancel before building the requests will result in no requests are
235 // built. 248 // built.
236 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeBuildRequests) { 249 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeBuildRequests) {
237 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1); 250 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1, 10);
238 EXPECT_CALL(*mock_request_handle_, CancelRequest()); 251 EXPECT_CALL(*mock_request_handle_, CancelRequest());
239 252
240 // Job is canceled before building parallel requests. 253 // Job is canceled before building parallel requests.
241 job_->Cancel(true); 254 job_->Cancel(true);
242 EXPECT_TRUE(IsJobCanceled()); 255 EXPECT_TRUE(IsJobCanceled());
243 256
244 BuildParallelRequests(); 257 BuildParallelRequests();
245 EXPECT_TRUE(job_->workers().empty()); 258 EXPECT_TRUE(job_->workers().empty());
246 259
247 DestroyParallelJob(); 260 DestroyParallelJob();
248 } 261 }
249 262
250 // Ensure cancel before adding the byte stream will result in workers being 263 // Ensure cancel before adding the byte stream will result in workers being
251 // canceled. 264 // canceled.
252 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeByteStreamReady) { 265 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeByteStreamReady) {
253 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1); 266 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1, 10);
254 EXPECT_CALL(*mock_request_handle_, CancelRequest()); 267 EXPECT_CALL(*mock_request_handle_, CancelRequest());
255 268
256 BuildParallelRequests(); 269 BuildParallelRequests();
257 VerifyWorker(50, 0); 270 VerifyWorker(50, 0);
258 271
259 // Job is canceled after building parallel requests and before byte streams 272 // Job is canceled after building parallel requests and before byte streams
260 // are added to the file sink. 273 // are added to the file sink.
261 job_->Cancel(true); 274 job_->Cancel(true);
262 EXPECT_TRUE(IsJobCanceled()); 275 EXPECT_TRUE(IsJobCanceled());
263 276
264 for (auto& worker : job_->workers()) { 277 for (auto& worker : job_->workers()) {
265 std::unique_ptr<MockDownloadRequestHandle> mock_handle = 278 std::unique_ptr<MockDownloadRequestHandle> mock_handle =
266 base::MakeUnique<MockDownloadRequestHandle>(); 279 base::MakeUnique<MockDownloadRequestHandle>();
267 EXPECT_CALL(*mock_handle.get(), CancelRequest()); 280 EXPECT_CALL(*mock_handle.get(), CancelRequest());
268 MakeWorkerReady(worker.second.get(), std::move(mock_handle)); 281 MakeWorkerReady(worker.second.get(), std::move(mock_handle));
269 } 282 }
270 283
271 DestroyParallelJob(); 284 DestroyParallelJob();
272 } 285 }
273 286
274 // Ensure pause before adding the byte stream will result in workers being 287 // Ensure pause before adding the byte stream will result in workers being
275 // paused. 288 // paused.
276 TEST_F(ParallelDownloadJobTest, EarlyPauseBeforeByteStreamReady) { 289 TEST_F(ParallelDownloadJobTest, EarlyPauseBeforeByteStreamReady) {
277 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1); 290 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2, 1, 10);
278 EXPECT_CALL(*mock_request_handle_, PauseRequest()); 291 EXPECT_CALL(*mock_request_handle_, PauseRequest());
279 292
280 BuildParallelRequests(); 293 BuildParallelRequests();
281 VerifyWorker(50, 0); 294 VerifyWorker(50, 0);
282 295
283 // Job is paused after building parallel requests and before adding the byte 296 // Job is paused after building parallel requests and before adding the byte
284 // stream to the file sink. 297 // stream to the file sink.
285 job_->Pause(); 298 job_->Pause();
286 EXPECT_TRUE(job_->is_paused()); 299 EXPECT_TRUE(job_->is_paused());
287 300
288 for (auto& worker : job_->workers()) { 301 for (auto& worker : job_->workers()) {
289 EXPECT_CALL(*job_.get(), CountOnByteStreamReady()); 302 EXPECT_CALL(*job_.get(), CountOnByteStreamReady());
290 std::unique_ptr<MockDownloadRequestHandle> mock_handle = 303 std::unique_ptr<MockDownloadRequestHandle> mock_handle =
291 base::MakeUnique<MockDownloadRequestHandle>(); 304 base::MakeUnique<MockDownloadRequestHandle>();
292 EXPECT_CALL(*mock_handle.get(), PauseRequest()); 305 EXPECT_CALL(*mock_handle.get(), PauseRequest());
293 MakeWorkerReady(worker.second.get(), std::move(mock_handle)); 306 MakeWorkerReady(worker.second.get(), std::move(mock_handle));
294 } 307 }
295 308
296 DestroyParallelJob(); 309 DestroyParallelJob();
297 } 310 }
298 311
312 // Test that parallel request is not created if the remaining content can be
313 // finish downloading soon.
314 TEST_F(ParallelDownloadJobTest, RemainingContentWillFinishSoon) {
315 DownloadItem::ReceivedSlices slices = {DownloadItem::ReceivedSlice(0, 99)};
316 CreateParallelJob(99, 1, slices, 3, 1, 10);
317 BuildParallelRequests();
318 EXPECT_EQ(0, static_cast<int>(job_->workers().size()));
319
320 DestroyParallelJob();
321 }
322
299 } // namespace content 323 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/parallel_download_job.cc ('k') | content/browser/download/parallel_download_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698