| 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 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 |
| OLD | NEW |