| OLD | NEW |
| 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 Loading... |
| 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 bool IsJobCanceled() const { return job_->is_canceled_; }; |
| 102 |
| 103 void MakeWorkerReady( |
| 104 DownloadWorker* worker, |
| 105 std::unique_ptr<MockDownloadRequestHandle> request_handle) { |
| 106 UrlDownloader::Delegate* delegate = |
| 107 static_cast<UrlDownloader::Delegate*>(worker); |
| 108 std::unique_ptr<DownloadCreateInfo> create_info = |
| 109 base::MakeUnique<DownloadCreateInfo>(); |
| 110 create_info->request_handle = std::move(request_handle); |
| 111 delegate->OnUrlDownloaderStarted( |
| 112 std::move(create_info), std::unique_ptr<ByteStreamReader>(), |
| 113 DownloadUrlParameters::OnStartedCallback()); |
| 114 } |
| 115 |
| 116 void VerifyWorker(int64_t offset, int64_t length) const { |
| 117 EXPECT_TRUE(job_->workers_.find(offset) != job_->workers_.end()); |
| 118 EXPECT_EQ(offset, job_->workers_[offset]->offset()); |
| 119 EXPECT_EQ(length, job_->workers_[offset]->length()); |
| 120 } |
| 121 |
| 86 content::TestBrowserThreadBundle browser_threads_; | 122 content::TestBrowserThreadBundle browser_threads_; |
| 87 std::unique_ptr<DownloadItemImplDelegate> item_delegate_; | 123 std::unique_ptr<DownloadItemImplDelegate> item_delegate_; |
| 88 std::unique_ptr<MockDownloadItemImpl> download_item_; | 124 std::unique_ptr<MockDownloadItemImpl> download_item_; |
| 89 std::unique_ptr<ParallelDownloadJobForTest> job_; | 125 std::unique_ptr<ParallelDownloadJobForTest> job_; |
| 126 // Request handle for the original request. |
| 127 MockDownloadRequestHandle* mock_request_handle_; |
| 90 }; | 128 }; |
| 91 | 129 |
| 92 // Test if parallel requests can be built correctly for a new download. | 130 // Test if parallel requests can be built correctly for a new download. |
| 93 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequests) { | 131 TEST_F(ParallelDownloadJobTest, CreateNewDownloadRequests) { |
| 94 // Totally 2 requests for 100 bytes. | 132 // Totally 2 requests for 100 bytes. |
| 95 // Original request: Range:0-49, for 50 bytes. | 133 // Original request: Range:0-49, for 50 bytes. |
| 96 // Task 1: Range:50-, for 50 bytes. | 134 // Task 1: Range:50-, for 50 bytes. |
| 97 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2); | 135 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2); |
| 98 BuildParallelRequests(); | 136 BuildParallelRequests(); |
| 99 EXPECT_EQ(1, static_cast<int>(job_->fake_tasks_.size())); | 137 EXPECT_EQ(1, static_cast<int>(job_->workers().size())); |
| 100 EXPECT_EQ(50, job_->fake_tasks_[0].first); | 138 VerifyWorker(50, 0); |
| 101 EXPECT_EQ(0, job_->fake_tasks_[0].second); | |
| 102 job_->fake_tasks_.clear(); | |
| 103 DestroyParallelJob(); | 139 DestroyParallelJob(); |
| 104 | 140 |
| 105 // Totally 3 requests for 100 bytes. | 141 // Totally 3 requests for 100 bytes. |
| 106 // Original request: Range:0-32, for 33 bytes. | 142 // Original request: Range:0-32, for 33 bytes. |
| 107 // Task 1: Range:33-65, for 33 bytes. | 143 // Task 1: Range:33-65, for 33 bytes. |
| 108 // Task 2: Range:66-, for 34 bytes. | 144 // Task 2: Range:66-, for 34 bytes. |
| 109 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3); | 145 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 3); |
| 110 BuildParallelRequests(); | 146 BuildParallelRequests(); |
| 111 EXPECT_EQ(2, static_cast<int>(job_->fake_tasks_.size())); | 147 EXPECT_EQ(2, static_cast<int>(job_->workers().size())); |
| 112 EXPECT_EQ(33, job_->fake_tasks_[0].first); | 148 VerifyWorker(33, 33); |
| 113 EXPECT_EQ(33, job_->fake_tasks_[0].second); | 149 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(); | 150 DestroyParallelJob(); |
| 118 | 151 |
| 119 // Totally 3 requests for 100 bytes. Start from the 17th byte. | 152 // Totally 3 requests for 100 bytes. Start from the 17th byte. |
| 120 // Original request: Range:17-43, for 27 bytes. | 153 // Original request: Range:17-43, for 27 bytes. |
| 121 // Task 1: Range:44-70, for 27 bytes. | 154 // Task 1: Range:44-70, for 27 bytes. |
| 122 // Task 2: Range:71-99, for 29 bytes. | 155 // Task 2: Range:71-99, for 29 bytes. |
| 123 CreateParallelJob(17, 83, DownloadItem::ReceivedSlices(), 3); | 156 CreateParallelJob(17, 83, DownloadItem::ReceivedSlices(), 3); |
| 124 BuildParallelRequests(); | 157 BuildParallelRequests(); |
| 125 EXPECT_EQ(2, static_cast<int>(job_->fake_tasks_.size())); | 158 EXPECT_EQ(2, static_cast<int>(job_->workers().size())); |
| 126 EXPECT_EQ(44, job_->fake_tasks_[0].first); | 159 VerifyWorker(44, 27); |
| 127 EXPECT_EQ(27, job_->fake_tasks_[0].second); | 160 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(); | 161 DestroyParallelJob(); |
| 132 | 162 |
| 133 // Less than 2 requests, do nothing. | 163 // Less than 2 requests, do nothing. |
| 134 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 1); | 164 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 1); |
| 135 BuildParallelRequests(); | 165 BuildParallelRequests(); |
| 136 EXPECT_TRUE(job_->fake_tasks_.empty()); | 166 EXPECT_TRUE(job_->workers().empty()); |
| 137 DestroyParallelJob(); | 167 DestroyParallelJob(); |
| 138 | 168 |
| 139 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 0); | 169 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 0); |
| 140 BuildParallelRequests(); | 170 BuildParallelRequests(); |
| 141 EXPECT_TRUE(job_->fake_tasks_.empty()); | 171 EXPECT_TRUE(job_->workers().empty()); |
| 142 DestroyParallelJob(); | 172 DestroyParallelJob(); |
| 143 | 173 |
| 144 // Content-length is 0, do nothing. | 174 // Content-length is 0, do nothing. |
| 145 CreateParallelJob(100, 0, DownloadItem::ReceivedSlices(), 3); | 175 CreateParallelJob(100, 0, DownloadItem::ReceivedSlices(), 3); |
| 146 BuildParallelRequests(); | 176 BuildParallelRequests(); |
| 147 EXPECT_TRUE(job_->fake_tasks_.empty()); | 177 EXPECT_TRUE(job_->workers().empty()); |
| 148 DestroyParallelJob(); | 178 DestroyParallelJob(); |
| 149 | 179 |
| 150 CreateParallelJob(0, 0, DownloadItem::ReceivedSlices(), 3); | 180 CreateParallelJob(0, 0, DownloadItem::ReceivedSlices(), 3); |
| 151 BuildParallelRequests(); | 181 BuildParallelRequests(); |
| 152 EXPECT_TRUE(job_->fake_tasks_.empty()); | 182 EXPECT_TRUE(job_->workers().empty()); |
| 153 DestroyParallelJob(); | 183 DestroyParallelJob(); |
| 154 | 184 |
| 155 // 2 bytes left for 3 additional requests. Only 1 are built. | 185 // 2 bytes left for 3 additional requests. Only 1 are built. |
| 156 // Original request: Range:98-98, for 1 byte. | 186 // Original request: Range:98-98, for 1 byte. |
| 157 // Task 1: Range:99-, for 1 byte. | 187 // Task 1: Range:99-, for 1 byte. |
| 158 CreateParallelJob(98, 2, DownloadItem::ReceivedSlices(), 4); | 188 CreateParallelJob(98, 2, DownloadItem::ReceivedSlices(), 4); |
| 159 BuildParallelRequests(); | 189 BuildParallelRequests(); |
| 160 EXPECT_EQ(1, static_cast<int>(job_->fake_tasks_.size())); | 190 EXPECT_EQ(1, static_cast<int>(job_->workers().size())); |
| 161 EXPECT_EQ(99, job_->fake_tasks_[0].first); | 191 VerifyWorker(99, 0); |
| 162 EXPECT_EQ(0, job_->fake_tasks_[0].second); | |
| 163 job_->fake_tasks_.clear(); | |
| 164 DestroyParallelJob(); | 192 DestroyParallelJob(); |
| 165 } | 193 } |
| 166 | 194 |
| 195 // Pause, cancel, resume can be called before or after the worker establish |
| 196 // the byte stream. |
| 197 // These tests ensure the states consistency between the job and workers. |
| 198 |
| 199 // Ensure cancel before building the requests will result in no requests are |
| 200 // built. |
| 201 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeBuildRequests) { |
| 202 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2); |
| 203 EXPECT_CALL(*mock_request_handle_, CancelRequest()); |
| 204 |
| 205 // Job is canceled before building parallel requests. |
| 206 job_->Cancel(true); |
| 207 EXPECT_TRUE(IsJobCanceled()); |
| 208 |
| 209 BuildParallelRequests(); |
| 210 EXPECT_TRUE(job_->workers().empty()); |
| 211 |
| 212 DestroyParallelJob(); |
| 213 } |
| 214 |
| 215 // Ensure cancel before adding the byte stream will result in workers being |
| 216 // canceled. |
| 217 TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeByteStreamReady) { |
| 218 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2); |
| 219 EXPECT_CALL(*mock_request_handle_, CancelRequest()); |
| 220 |
| 221 BuildParallelRequests(); |
| 222 VerifyWorker(50, 0); |
| 223 |
| 224 // Job is canceled after building parallel requests and before byte streams |
| 225 // are added to the file sink. |
| 226 job_->Cancel(true); |
| 227 EXPECT_TRUE(IsJobCanceled()); |
| 228 |
| 229 for (auto& worker : job_->workers()) { |
| 230 std::unique_ptr<MockDownloadRequestHandle> mock_handle = |
| 231 base::MakeUnique<MockDownloadRequestHandle>(); |
| 232 EXPECT_CALL(*mock_handle.get(), CancelRequest()); |
| 233 MakeWorkerReady(worker.second.get(), std::move(mock_handle)); |
| 234 } |
| 235 |
| 236 DestroyParallelJob(); |
| 237 } |
| 238 |
| 239 // Ensure pause before adding the byte stream will result in workers being |
| 240 // paused. |
| 241 TEST_F(ParallelDownloadJobTest, EarlyPauseBeforeByteStreamReady) { |
| 242 CreateParallelJob(0, 100, DownloadItem::ReceivedSlices(), 2); |
| 243 EXPECT_CALL(*mock_request_handle_, PauseRequest()); |
| 244 |
| 245 BuildParallelRequests(); |
| 246 VerifyWorker(50, 0); |
| 247 |
| 248 // Job is paused after building parallel requests and before adding the byte |
| 249 // stream to the file sink. |
| 250 job_->Pause(); |
| 251 EXPECT_TRUE(job_->is_paused()); |
| 252 |
| 253 for (auto& worker : job_->workers()) { |
| 254 EXPECT_CALL(*job_.get(), CountOnByteStreamReady()); |
| 255 std::unique_ptr<MockDownloadRequestHandle> mock_handle = |
| 256 base::MakeUnique<MockDownloadRequestHandle>(); |
| 257 EXPECT_CALL(*mock_handle.get(), PauseRequest()); |
| 258 MakeWorkerReady(worker.second.get(), std::move(mock_handle)); |
| 259 } |
| 260 |
| 261 DestroyParallelJob(); |
| 262 } |
| 263 |
| 167 } // namespace content | 264 } // namespace content |
| OLD | NEW |