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

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

Issue 2767593003: Handle early pause, cancel for parallel requests. (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 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 13 matching lines...) Expand all
24 class MockDownloadRequestHandle : public DownloadRequestHandleInterface { 24 class MockDownloadRequestHandle : public DownloadRequestHandleInterface {
25 public: 25 public:
26 MOCK_CONST_METHOD0(GetWebContents, WebContents*()); 26 MOCK_CONST_METHOD0(GetWebContents, WebContents*());
27 MOCK_CONST_METHOD0(GetDownloadManager, DownloadManager*()); 27 MOCK_CONST_METHOD0(GetDownloadManager, DownloadManager*());
28 MOCK_CONST_METHOD0(PauseRequest, void()); 28 MOCK_CONST_METHOD0(PauseRequest, void());
29 MOCK_CONST_METHOD0(ResumeRequest, void()); 29 MOCK_CONST_METHOD0(ResumeRequest, void());
30 MOCK_CONST_METHOD0(CancelRequest, void()); 30 MOCK_CONST_METHOD0(CancelRequest, void());
31 MOCK_CONST_METHOD0(DebugString, std::string()); 31 MOCK_CONST_METHOD0(DebugString, std::string());
32 }; 32 };
33 33
34 class DownloadWorkerForTest : public DownloadWorker {
35 public:
36 DownloadWorkerForTest(DownloadWorker::Delegate* delegate,
37 int64_t offset,
38 int64_t length)
39 : DownloadWorker(delegate, offset, length) {}
40
41 void MakeResponseReady(
42 std::unique_ptr<MockDownloadRequestHandle> request_handle) {
43 UrlDownloader::Delegate* delegate =
44 static_cast<UrlDownloader::Delegate*>(this);
45 std::unique_ptr<DownloadCreateInfo> create_info =
46 base::MakeUnique<DownloadCreateInfo>();
47 create_info->request_handle = std::move(request_handle);
48 delegate->OnUrlDownloaderStarted(
49 std::move(create_info), std::unique_ptr<ByteStreamReader>(),
50 DownloadUrlParameters::OnStartedCallback());
51 }
52 };
53
34 } // namespace 54 } // namespace
35 55
36 class ParallelDownloadJobForTest : public ParallelDownloadJob { 56 class ParallelDownloadJobForTest : public ParallelDownloadJob {
37 public: 57 public:
38 ParallelDownloadJobForTest( 58 ParallelDownloadJobForTest(
39 DownloadItemImpl* download_item, 59 DownloadItemImpl* download_item,
40 std::unique_ptr<DownloadRequestHandleInterface> request_handle, 60 std::unique_ptr<DownloadRequestHandleInterface> request_handle,
41 const DownloadCreateInfo& create_info, 61 const DownloadCreateInfo& create_info,
42 int request_count) 62 int request_count)
43 : ParallelDownloadJob(download_item, 63 : ParallelDownloadJob(download_item,
44 std::move(request_handle), 64 std::move(request_handle),
45 create_info), 65 create_info),
46 request_count_(request_count) {} 66 request_count_(request_count) {}
47 67
68 const std::vector<DownloadWorkerForTest*>& mock_workers() {
69 return mock_workers_;
70 }
71
48 void CreateRequest(int64_t offset, int64_t length) override { 72 void CreateRequest(int64_t offset, int64_t length) override {
49 fake_tasks_.push_back(std::pair<int64_t, int64_t>(offset, length)); 73 std::unique_ptr<DownloadWorkerForTest> mock_worker =
74 base::MakeUnique<DownloadWorkerForTest>(this, offset, length);
75 mock_workers_.push_back(mock_worker.get());
76
77 DCHECK(workers_.find(offset) == workers_.end());
78 workers_[offset] = std::move(mock_worker);
50 } 79 }
51 80
52 int GetParallelRequestCount() const override { return request_count_; } 81 int GetParallelRequestCount() const override { return request_count_; }
53 82
54 std::vector<std::pair<int64_t, int64_t>> fake_tasks_; 83 void OnByteStreamReady(
84 DownloadWorker* worker,
85 std::unique_ptr<ByteStreamReader> stream_reader) override {
86 CountOnByteStreamReady();
87 }
88
89 MOCK_METHOD0(CountOnByteStreamReady, void());
55 90
56 private: 91 private:
92 std::vector<DownloadWorkerForTest*> mock_workers_;
qinmin 2017/03/22 05:50:29 looks like you only need to check the size of this
xingliu 2017/03/22 23:54:06 Done, Good catch, this is no longer needed.
57 int request_count_; 93 int request_count_;
58 DISALLOW_COPY_AND_ASSIGN(ParallelDownloadJobForTest); 94 DISALLOW_COPY_AND_ASSIGN(ParallelDownloadJobForTest);
59 }; 95 };
60 96
61 class ParallelDownloadJobTest : public testing::Test { 97 class ParallelDownloadJobTest : public testing::Test {
62 public: 98 public:
63 void CreateParallelJob(int64_t offset, 99 void CreateParallelJob(int64_t offset,
64 int64_t content_length, 100 int64_t content_length,
65 const DownloadItem::ReceivedSlices& slices, 101 const DownloadItem::ReceivedSlices& slices,
66 int request_count) { 102 int request_count) {
67 item_delegate_ = base::MakeUnique<DownloadItemImplDelegate>(); 103 item_delegate_ = base::MakeUnique<DownloadItemImplDelegate>();
68 download_item_ = base::MakeUnique<NiceMock<MockDownloadItemImpl>>( 104 download_item_ = base::MakeUnique<NiceMock<MockDownloadItemImpl>>(
69 item_delegate_.get(), slices); 105 item_delegate_.get(), slices);
70 DownloadCreateInfo info; 106 DownloadCreateInfo info;
71 info.offset = offset; 107 info.offset = offset;
72 info.total_bytes = content_length; 108 info.total_bytes = content_length;
109 std::unique_ptr<MockDownloadRequestHandle> request_handle =
110 base::MakeUnique<MockDownloadRequestHandle>();
111 mock_request_handle_ = request_handle.get();
73 job_ = base::MakeUnique<ParallelDownloadJobForTest>( 112 job_ = base::MakeUnique<ParallelDownloadJobForTest>(
74 download_item_.get(), base::MakeUnique<MockDownloadRequestHandle>(), 113 download_item_.get(), std::move(request_handle), info, request_count);
75 info, request_count);
76 } 114 }
77 115
78 void DestroyParallelJob() { 116 void DestroyParallelJob() {
79 job_.reset(); 117 job_.reset();
80 download_item_.reset(); 118 download_item_.reset();
81 item_delegate_.reset(); 119 item_delegate_.reset();
120 mock_request_handle_ = nullptr;
82 } 121 }
83 122
84 void BuildParallelRequests() { job_->BuildParallelRequests(); } 123 void BuildParallelRequests() { job_->BuildParallelRequests(); }
85 124
125 void VerifyWorker(int64_t offset, int64_t length) const {
126 EXPECT_TRUE(job_->workers_.find(offset) != job_->workers_.end());
127 EXPECT_EQ(offset, job_->workers_[offset]->offset());
128 EXPECT_EQ(length, job_->workers_[offset]->length());
129 }
130
86 content::TestBrowserThreadBundle browser_threads_; 131 content::TestBrowserThreadBundle browser_threads_;
87 std::unique_ptr<DownloadItemImplDelegate> item_delegate_; 132 std::unique_ptr<DownloadItemImplDelegate> item_delegate_;
88 std::unique_ptr<MockDownloadItemImpl> download_item_; 133 std::unique_ptr<MockDownloadItemImpl> download_item_;
89 std::unique_ptr<ParallelDownloadJobForTest> job_; 134 std::unique_ptr<ParallelDownloadJobForTest> job_;
135 // Request handle for the original request.
136 MockDownloadRequestHandle* mock_request_handle_;
90 }; 137 };
91 138
92 // Test if parallel requests can be built correctly for a new download. 139 // Test if parallel requests can be built correctly for a new download.
93 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequests) { 140 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequests) {
94 // Totally 2 requests for 100 bytes. 141 // Totally 2 requests for 100 bytes.
95 // Original request: Range:0-49, for 50 bytes. 142 // Original request: Range:0-49, for 50 bytes.
96 // Task 1: Range:50-, for 50 bytes. 143 // Task 1: Range:50-, for 50 bytes.
97 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2); 144 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2);
98 BuildParallelRequests(); 145 BuildParallelRequests();
99 EXPECT_EQ(1, static_cast<int>(job_->fake_tasks_.size())); 146 EXPECT_EQ(1, static_cast<int>(job_->mock_workers().size()));
100 EXPECT_EQ(50, job_->fake_tasks_[0].first); 147 VerifyWorker(50, 0);
101 EXPECT_EQ(0, job_->fake_tasks_[0].second);
102 job_->fake_tasks_.clear();
103 DestroyParallelJob(); 148 DestroyParallelJob();
104 149
105 // Totally 3 requests for 100 bytes. 150 // Totally 3 requests for 100 bytes.
106 // Original request: Range:0-32, for 33 bytes. 151 // Original request: Range:0-32, for 33 bytes.
107 // Task 1: Range:33-65, for 33 bytes. 152 // Task 1: Range:33-65, for 33 bytes.
108 // Task 2: Range:66-, for 34 bytes. 153 // Task 2: Range:66-, for 34 bytes.
109 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3); 154 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3);
110 BuildParallelRequests(); 155 BuildParallelRequests();
111 EXPECT_EQ(2, static_cast<int>(job_->fake_tasks_.size())); 156 EXPECT_EQ(2, static_cast<int>(job_->mock_workers().size()));
112 EXPECT_EQ(33, job_->fake_tasks_[0].first); 157 VerifyWorker(33, 33);
113 EXPECT_EQ(33, job_->fake_tasks_[0].second); 158 VerifyWorker(66, 0);
114 EXPECT_EQ(66, job_->fake_tasks_[1].first);
115 EXPECT_EQ(0, job_->fake_tasks_[1].second);
116 job_->fake_tasks_.clear();
117 DestroyParallelJob(); 159 DestroyParallelJob();
118 160
119 // Totally 3 requests for 100 bytes. Start from the 17th byte. 161 // Totally 3 requests for 100 bytes. Start from the 17th byte.
120 // Original request: Range:17-43, for 27 bytes. 162 // Original request: Range:17-43, for 27 bytes.
121 // Task 1: Range:44-70, for 27 bytes. 163 // Task 1: Range:44-70, for 27 bytes.
122 // Task 2: Range:71-99, for 29 bytes. 164 // Task 2: Range:71-99, for 29 bytes.
123 CreateParallelJob(17, 83, DownloadItem::ReceivedSlices(), 3); 165 CreateParallelJob(17, 83, DownloadItem::ReceivedSlices(), 3);
124 BuildParallelRequests(); 166 BuildParallelRequests();
125 EXPECT_EQ(2, static_cast<int>(job_->fake_tasks_.size())); 167 EXPECT_EQ(2, static_cast<int>(job_->mock_workers().size()));
126 EXPECT_EQ(44, job_->fake_tasks_[0].first); 168 VerifyWorker(44, 27);
127 EXPECT_EQ(27, job_->fake_tasks_[0].second); 169 VerifyWorker(71, 0);
128 EXPECT_EQ(71, job_->fake_tasks_[1].first);
129 EXPECT_EQ(0, job_->fake_tasks_[1].second);
130 job_->fake_tasks_.clear();
131 DestroyParallelJob(); 170 DestroyParallelJob();
132 171
133 // Less than 2 requests, do nothing. 172 // Less than 2 requests, do nothing.
134 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 1); 173 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 1);
135 BuildParallelRequests(); 174 BuildParallelRequests();
136 EXPECT_TRUE(job_->fake_tasks_.empty()); 175 EXPECT_TRUE(job_->mock_workers().empty());
137 DestroyParallelJob(); 176 DestroyParallelJob();
138 177
139 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 0); 178 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 0);
140 BuildParallelRequests(); 179 BuildParallelRequests();
141 EXPECT_TRUE(job_->fake_tasks_.empty()); 180 EXPECT_TRUE(job_->mock_workers().empty());
142 DestroyParallelJob(); 181 DestroyParallelJob();
143 182
144 // Content-length is 0, do nothing. 183 // Content-length is 0, do nothing.
145 CreateParallelJob(100, 0, DownloadItem::ReceivedSlices(), 3); 184 CreateParallelJob(100, 0, DownloadItem::ReceivedSlices(), 3);
146 BuildParallelRequests(); 185 BuildParallelRequests();
147 EXPECT_TRUE(job_->fake_tasks_.empty()); 186 EXPECT_TRUE(job_->mock_workers().empty());
148 DestroyParallelJob(); 187 DestroyParallelJob();
149 188
150 CreateParallelJob(0, 0, DownloadItem::ReceivedSlices(), 3); 189 CreateParallelJob(0, 0, DownloadItem::ReceivedSlices(), 3);
151 BuildParallelRequests(); 190 BuildParallelRequests();
152 EXPECT_TRUE(job_->fake_tasks_.empty()); 191 EXPECT_TRUE(job_->mock_workers().empty());
153 DestroyParallelJob(); 192 DestroyParallelJob();
154 193
155 // 2 bytes left for 3 additional requests. Only 1 are built. 194 // 2 bytes left for 3 additional requests. Only 1 are built.
156 // Original request: Range:98-98, for 1 byte. 195 // Original request: Range:98-98, for 1 byte.
157 // Task 1: Range:99-, for 1 byte. 196 // Task 1: Range:99-, for 1 byte.
158 CreateParallelJob(98, 2, DownloadItem::ReceivedSlices(), 4); 197 CreateParallelJob(98, 2, DownloadItem::ReceivedSlices(), 4);
159 BuildParallelRequests(); 198 BuildParallelRequests();
160 EXPECT_EQ(1, static_cast<int>(job_->fake_tasks_.size())); 199 EXPECT_EQ(1, static_cast<int>(job_->mock_workers().size()));
161 EXPECT_EQ(99, job_->fake_tasks_[0].first); 200 VerifyWorker(99, 0);
162 EXPECT_EQ(0, job_->fake_tasks_[0].second);
163 job_->fake_tasks_.clear();
164 DestroyParallelJob(); 201 DestroyParallelJob();
165 } 202 }
166 203
204 // Pause, cancel, resume can be called before or after the worker establish
205 // the byte stream.
206 // These tests ensure the states consistency between the job and workers.
207
208 // Ensure cancel before building the requests will result in workers being
209 // canceled.
210 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeBuildRequests) {
211 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2);
212 EXPECT_CALL(*mock_request_handle_, CancelRequest());
213
214 // Job is canceled before building parallel requests.
215 job_->Cancel(true);
216 EXPECT_TRUE(job_->is_canceled());
217
218 BuildParallelRequests();
219 VerifyWorker(50, 0);
220
221 for (auto* worker : job_->mock_workers()) {
222 std::unique_ptr<MockDownloadRequestHandle> mock_handle =
223 base::MakeUnique<MockDownloadRequestHandle>();
224 EXPECT_CALL(*mock_handle.get(), CancelRequest());
225 worker->MakeResponseReady(std::move(mock_handle));
226 }
227
228 DestroyParallelJob();
229 }
230
231 // Ensure cancel before adding the byte stream will result in workers being
232 // canceled.
233 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeByteStreamReady) {
234 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2);
235 EXPECT_CALL(*mock_request_handle_, CancelRequest());
236
237 BuildParallelRequests();
238 VerifyWorker(50, 0);
239
240 // Job is canceled after building parallel requests and before byte streams
241 // are added to the file sink.
242 job_->Cancel(true);
243 EXPECT_TRUE(job_->is_canceled());
244
245 for (auto* worker : job_->mock_workers()) {
246 std::unique_ptr<MockDownloadRequestHandle> mock_handle =
247 base::MakeUnique<MockDownloadRequestHandle>();
248 EXPECT_CALL(*mock_handle.get(), CancelRequest());
249 worker->MakeResponseReady(std::move(mock_handle));
250 }
251
252 DestroyParallelJob();
253 }
254
255 // Ensure pause before building the requests will result in workers being
256 // paused.
257 TEST_F(ParallelDownloadJobTest, EarlyPauseBeforeBuildRequests) {
258 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2);
259 EXPECT_CALL(*mock_request_handle_, PauseRequest());
260
261 // Job is paused before building parallel requests.
262 job_->Pause();
263 EXPECT_TRUE(job_->is_paused());
264
265 BuildParallelRequests();
266 VerifyWorker(50, 0);
267
268 for (auto* worker : job_->mock_workers()) {
269 EXPECT_CALL(*job_.get(), CountOnByteStreamReady());
270 std::unique_ptr<MockDownloadRequestHandle> mock_handle =
271 base::MakeUnique<MockDownloadRequestHandle>();
272 EXPECT_CALL(*mock_handle.get(), PauseRequest());
273 worker->MakeResponseReady(std::move(mock_handle));
274 }
275
276 DestroyParallelJob();
277 }
278
279 // Ensure pause before adding the byte stream will result in workers being
280 // paused.
281 TEST_F(ParallelDownloadJobTest, EarlyPauseBeforeByteStreamReady) {
282 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2);
283 EXPECT_CALL(*mock_request_handle_, PauseRequest());
284
285 BuildParallelRequests();
286 VerifyWorker(50, 0);
287
288 // Job is paused after building parallel requests and before adding the byte
289 // stream to the file sink.
290 job_->Pause();
291 EXPECT_TRUE(job_->is_paused());
292
293 for (auto* worker : job_->mock_workers()) {
294 EXPECT_CALL(*job_.get(), CountOnByteStreamReady());
295 std::unique_ptr<MockDownloadRequestHandle> mock_handle =
296 base::MakeUnique<MockDownloadRequestHandle>();
297 EXPECT_CALL(*mock_handle.get(), PauseRequest());
298 worker->MakeResponseReady(std::move(mock_handle));
299 }
300
301 DestroyParallelJob();
302 }
303
167 } // namespace content 304 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698