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

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, make DownloadWorker cache some states. 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 28 matching lines...) Expand all
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 : ParallelDownloadJob(download_item, 43 : ParallelDownloadJob(download_item,
44 std::move(request_handle), 44 std::move(request_handle),
45 create_info), 45 create_info),
46 request_count_(request_count) {} 46 request_count_(request_count) {}
47 47
48 void CreateRequest(int64_t offset, int64_t length) override { 48 void CreateRequest(int64_t offset, int64_t length) override {
49 fake_tasks_.push_back(std::pair<int64_t, int64_t>(offset, length)); 49 std::unique_ptr<DownloadWorker> worker =
50 base::MakeUnique<DownloadWorker>(this, offset, length);
51
52 DCHECK(workers_.find(offset) == workers_.end());
53 workers_[offset] = std::move(worker);
50 } 54 }
51 55
56 ParallelDownloadJob::WorkerMap& workers() { return workers_; }
57
52 int GetParallelRequestCount() const override { return request_count_; } 58 int GetParallelRequestCount() const override { return request_count_; }
53 59
54 std::vector<std::pair<int64_t, int64_t>> fake_tasks_; 60 void OnByteStreamReady(
61 DownloadWorker* worker,
62 std::unique_ptr<ByteStreamReader> stream_reader) override {
63 CountOnByteStreamReady();
64 }
65
66 MOCK_METHOD0(CountOnByteStreamReady, void());
55 67
56 private: 68 private:
57 int request_count_; 69 int request_count_;
58 DISALLOW_COPY_AND_ASSIGN(ParallelDownloadJobForTest); 70 DISALLOW_COPY_AND_ASSIGN(ParallelDownloadJobForTest);
59 }; 71 };
60 72
61 class ParallelDownloadJobTest : public testing::Test { 73 class ParallelDownloadJobTest : public testing::Test {
62 public: 74 public:
63 void CreateParallelJob(int64_t offset, 75 void CreateParallelJob(int64_t offset,
64 int64_t content_length, 76 int64_t content_length,
65 const DownloadItem::ReceivedSlices& slices, 77 const DownloadItem::ReceivedSlices& slices,
66 int request_count) { 78 int request_count) {
67 item_delegate_ = base::MakeUnique<DownloadItemImplDelegate>(); 79 item_delegate_ = base::MakeUnique<DownloadItemImplDelegate>();
68 download_item_ = base::MakeUnique<NiceMock<MockDownloadItemImpl>>( 80 download_item_ = base::MakeUnique<NiceMock<MockDownloadItemImpl>>(
69 item_delegate_.get(), slices); 81 item_delegate_.get(), slices);
70 DownloadCreateInfo info; 82 DownloadCreateInfo info;
71 info.offset = offset; 83 info.offset = offset;
72 info.total_bytes = content_length; 84 info.total_bytes = content_length;
85 std::unique_ptr<MockDownloadRequestHandle> request_handle =
86 base::MakeUnique<MockDownloadRequestHandle>();
87 mock_request_handle_ = request_handle.get();
73 job_ = base::MakeUnique<ParallelDownloadJobForTest>( 88 job_ = base::MakeUnique<ParallelDownloadJobForTest>(
74 download_item_.get(), base::MakeUnique<MockDownloadRequestHandle>(), 89 download_item_.get(), std::move(request_handle), info, request_count);
75 info, request_count);
76 } 90 }
77 91
78 void DestroyParallelJob() { 92 void DestroyParallelJob() {
79 job_.reset(); 93 job_.reset();
80 download_item_.reset(); 94 download_item_.reset();
81 item_delegate_.reset(); 95 item_delegate_.reset();
96 mock_request_handle_ = nullptr;
82 } 97 }
83 98
84 void BuildParallelRequests() { job_->BuildParallelRequests(); } 99 void BuildParallelRequests() { job_->BuildParallelRequests(); }
85 100
101 void MakeWorkerReady(
102 DownloadWorker* worker,
103 std::unique_ptr<MockDownloadRequestHandle> request_handle) {
104 UrlDownloader::Delegate* delegate =
105 static_cast<UrlDownloader::Delegate*>(worker);
106 std::unique_ptr<DownloadCreateInfo> create_info =
107 base::MakeUnique<DownloadCreateInfo>();
108 create_info->request_handle = std::move(request_handle);
109 delegate->OnUrlDownloaderStarted(
110 std::move(create_info), std::unique_ptr<ByteStreamReader>(),
111 DownloadUrlParameters::OnStartedCallback());
112 }
113
114 void VerifyWorker(int64_t offset, int64_t length) const {
115 EXPECT_TRUE(job_->workers_.find(offset) != job_->workers_.end());
116 EXPECT_EQ(offset, job_->workers_[offset]->offset());
117 EXPECT_EQ(length, job_->workers_[offset]->length());
118 }
119
86 content::TestBrowserThreadBundle browser_threads_; 120 content::TestBrowserThreadBundle browser_threads_;
87 std::unique_ptr<DownloadItemImplDelegate> item_delegate_; 121 std::unique_ptr<DownloadItemImplDelegate> item_delegate_;
88 std::unique_ptr<MockDownloadItemImpl> download_item_; 122 std::unique_ptr<MockDownloadItemImpl> download_item_;
89 std::unique_ptr<ParallelDownloadJobForTest> job_; 123 std::unique_ptr<ParallelDownloadJobForTest> job_;
124 // Request handle for the original request.
125 MockDownloadRequestHandle* mock_request_handle_;
90 }; 126 };
91 127
92 // Test if parallel requests can be built correctly for a new download. 128 // Test if parallel requests can be built correctly for a new download.
93 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequests) { 129 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequests) {
94 // Totally 2 requests for 100 bytes. 130 // Totally 2 requests for 100 bytes.
95 // Original request: Range:0-49, for 50 bytes. 131 // Original request: Range:0-49, for 50 bytes.
96 // Task 1: Range:50-, for 50 bytes. 132 // Task 1: Range:50-, for 50 bytes.
97 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2); 133 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2);
98 BuildParallelRequests(); 134 BuildParallelRequests();
99 EXPECT_EQ(1, static_cast<int>(job_->fake_tasks_.size())); 135 EXPECT_EQ(1, static_cast<int>(job_->workers().size()));
100 EXPECT_EQ(50, job_->fake_tasks_[0].first); 136 VerifyWorker(50, 0);
101 EXPECT_EQ(0, job_->fake_tasks_[0].second);
102 job_->fake_tasks_.clear();
103 DestroyParallelJob(); 137 DestroyParallelJob();
104 138
105 // Totally 3 requests for 100 bytes. 139 // Totally 3 requests for 100 bytes.
106 // Original request: Range:0-32, for 33 bytes. 140 // Original request: Range:0-32, for 33 bytes.
107 // Task 1: Range:33-65, for 33 bytes. 141 // Task 1: Range:33-65, for 33 bytes.
108 // Task 2: Range:66-, for 34 bytes. 142 // Task 2: Range:66-, for 34 bytes.
109 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3); 143 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3);
110 BuildParallelRequests(); 144 BuildParallelRequests();
111 EXPECT_EQ(2, static_cast<int>(job_->fake_tasks_.size())); 145 EXPECT_EQ(2, static_cast<int>(job_->workers().size()));
112 EXPECT_EQ(33, job_->fake_tasks_[0].first); 146 VerifyWorker(33, 33);
113 EXPECT_EQ(33, job_->fake_tasks_[0].second); 147 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(); 148 DestroyParallelJob();
118 149
119 // Totally 3 requests for 100 bytes. Start from the 17th byte. 150 // Totally 3 requests for 100 bytes. Start from the 17th byte.
120 // Original request: Range:17-43, for 27 bytes. 151 // Original request: Range:17-43, for 27 bytes.
121 // Task 1: Range:44-70, for 27 bytes. 152 // Task 1: Range:44-70, for 27 bytes.
122 // Task 2: Range:71-99, for 29 bytes. 153 // Task 2: Range:71-99, for 29 bytes.
123 CreateParallelJob(17, 83, DownloadItem::ReceivedSlices(), 3); 154 CreateParallelJob(17, 83, DownloadItem::ReceivedSlices(), 3);
124 BuildParallelRequests(); 155 BuildParallelRequests();
125 EXPECT_EQ(2, static_cast<int>(job_->fake_tasks_.size())); 156 EXPECT_EQ(2, static_cast<int>(job_->workers().size()));
126 EXPECT_EQ(44, job_->fake_tasks_[0].first); 157 VerifyWorker(44, 27);
127 EXPECT_EQ(27, job_->fake_tasks_[0].second); 158 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(); 159 DestroyParallelJob();
132 160
133 // Less than 2 requests, do nothing. 161 // Less than 2 requests, do nothing.
134 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 1); 162 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 1);
135 BuildParallelRequests(); 163 BuildParallelRequests();
136 EXPECT_TRUE(job_->fake_tasks_.empty()); 164 EXPECT_TRUE(job_->workers().empty());
137 DestroyParallelJob(); 165 DestroyParallelJob();
138 166
139 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 0); 167 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 0);
140 BuildParallelRequests(); 168 BuildParallelRequests();
141 EXPECT_TRUE(job_->fake_tasks_.empty()); 169 EXPECT_TRUE(job_->workers().empty());
142 DestroyParallelJob(); 170 DestroyParallelJob();
143 171
144 // Content-length is 0, do nothing. 172 // Content-length is 0, do nothing.
145 CreateParallelJob(100, 0, DownloadItem::ReceivedSlices(), 3); 173 CreateParallelJob(100, 0, DownloadItem::ReceivedSlices(), 3);
146 BuildParallelRequests(); 174 BuildParallelRequests();
147 EXPECT_TRUE(job_->fake_tasks_.empty()); 175 EXPECT_TRUE(job_->workers().empty());
148 DestroyParallelJob(); 176 DestroyParallelJob();
149 177
150 CreateParallelJob(0, 0, DownloadItem::ReceivedSlices(), 3); 178 CreateParallelJob(0, 0, DownloadItem::ReceivedSlices(), 3);
151 BuildParallelRequests(); 179 BuildParallelRequests();
152 EXPECT_TRUE(job_->fake_tasks_.empty()); 180 EXPECT_TRUE(job_->workers().empty());
153 DestroyParallelJob(); 181 DestroyParallelJob();
154 182
155 // 2 bytes left for 3 additional requests. Only 1 are built. 183 // 2 bytes left for 3 additional requests. Only 1 are built.
156 // Original request: Range:98-98, for 1 byte. 184 // Original request: Range:98-98, for 1 byte.
157 // Task 1: Range:99-, for 1 byte. 185 // Task 1: Range:99-, for 1 byte.
158 CreateParallelJob(98, 2, DownloadItem::ReceivedSlices(), 4); 186 CreateParallelJob(98, 2, DownloadItem::ReceivedSlices(), 4);
159 BuildParallelRequests(); 187 BuildParallelRequests();
160 EXPECT_EQ(1, static_cast<int>(job_->fake_tasks_.size())); 188 EXPECT_EQ(1, static_cast<int>(job_->workers().size()));
161 EXPECT_EQ(99, job_->fake_tasks_[0].first); 189 VerifyWorker(99, 0);
162 EXPECT_EQ(0, job_->fake_tasks_[0].second);
163 job_->fake_tasks_.clear();
164 DestroyParallelJob(); 190 DestroyParallelJob();
165 } 191 }
166 192
193 // Pause, cancel, resume can be called before or after the worker establish
194 // the byte stream.
195 // These tests ensure the states consistency between the job and workers.
196
197 // Ensure cancel before building the requests will result in no requests are
198 // built.
199 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeBuildRequests) {
200 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2);
201 EXPECT_CALL(*mock_request_handle_, CancelRequest());
202
203 // Job is canceled before building parallel requests.
204 job_->Cancel(true);
205 EXPECT_TRUE(job_->is_canceled());
206
207 BuildParallelRequests();
208 EXPECT_TRUE(job_->workers().empty());
209
210 DestroyParallelJob();
211 }
212
213 // Ensure cancel before adding the byte stream will result in workers being
214 // canceled.
215 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeByteStreamReady) {
216 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2);
217 EXPECT_CALL(*mock_request_handle_, CancelRequest());
218
219 BuildParallelRequests();
220 VerifyWorker(50, 0);
221
222 // Job is canceled after building parallel requests and before byte streams
223 // are added to the file sink.
224 job_->Cancel(true);
225 EXPECT_TRUE(job_->is_canceled());
226
227 for (auto& worker : job_->workers()) {
228 std::unique_ptr<MockDownloadRequestHandle> mock_handle =
229 base::MakeUnique<MockDownloadRequestHandle>();
230 EXPECT_CALL(*mock_handle.get(), CancelRequest());
231 MakeWorkerReady(worker.second.get(), std::move(mock_handle));
232 }
233
234 DestroyParallelJob();
235 }
236
237 // Ensure pause before adding the byte stream will result in workers being
238 // paused.
239 TEST_F(ParallelDownloadJobTest, EarlyPauseBeforeByteStreamReady) {
240 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2);
241 EXPECT_CALL(*mock_request_handle_, PauseRequest());
242
243 BuildParallelRequests();
244 VerifyWorker(50, 0);
245
246 // Job is paused after building parallel requests and before adding the byte
247 // stream to the file sink.
248 job_->Pause();
249 EXPECT_TRUE(job_->is_paused());
250
251 for (auto& worker : job_->workers()) {
252 EXPECT_CALL(*job_.get(), CountOnByteStreamReady());
253 std::unique_ptr<MockDownloadRequestHandle> mock_handle =
254 base::MakeUnique<MockDownloadRequestHandle>();
255 EXPECT_CALL(*mock_handle.get(), PauseRequest());
256 MakeWorkerReady(worker.second.get(), std::move(mock_handle));
257 }
258
259 DestroyParallelJob();
260 }
261
167 } // namespace content 262 } // namespace content
OLDNEW
« content/browser/download/download_job.h ('K') | « content/browser/download/parallel_download_job.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698