Chromium Code Reviews| 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/background_fetch/background_fetch_job_controller.h" | 5 #include "content/browser/background_fetch/background_fetch_job_controller.h" |
| 6 | 6 |
| 7 #include <string> | |
| 8 #include <vector> | |
| 9 | |
| 7 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 8 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/guid.h" | |
| 9 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 10 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
| 15 #include "base/strings/string_number_conversions.h" | |
| 11 #include "content/browser/background_fetch/background_fetch_data_manager.h" | 16 #include "content/browser/background_fetch/background_fetch_data_manager.h" |
| 12 #include "content/browser/background_fetch/background_fetch_job_info.h" | 17 #include "content/browser/background_fetch/background_fetch_job_info.h" |
| 13 #include "content/browser/background_fetch/background_fetch_request_info.h" | 18 #include "content/browser/background_fetch/background_fetch_request_info.h" |
| 14 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
| 15 #include "content/public/test/mock_download_item.h" | 20 #include "content/public/test/mock_download_item.h" |
| 16 #include "content/public/test/mock_download_manager.h" | 21 #include "content/public/test/mock_download_manager.h" |
| 17 #include "content/public/test/test_browser_context.h" | 22 #include "content/public/test/test_browser_context.h" |
| 18 #include "content/public/test/test_browser_thread_bundle.h" | 23 #include "content/public/test/test_browser_thread_bundle.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 25 |
| 21 namespace { | 26 namespace { |
| 22 | 27 |
| 23 const char kOrigin[] = "https://example.com/"; | 28 const char kOrigin[] = "https://example.com/"; |
| 24 const char kJobGuid[] = "TestRequestGuid"; | 29 const char kJobGuid[] = "TestRequestGuid"; |
| 25 constexpr int64_t kServiceWorkerRegistrationId = 9001; | 30 constexpr int64_t kServiceWorkerRegistrationId = 9001; |
| 26 const char kTestUrl[] = "http://www.example.com/example.html"; | 31 const char kTestUrl[] = "http://www.example.com/example.html"; |
| 27 const char kTag[] = "testTag"; | 32 const char kTag[] = "testTag"; |
| 28 | 33 |
| 29 } // namespace | 34 } // namespace |
| 30 | 35 |
| 31 namespace content { | 36 namespace content { |
| 32 | 37 |
| 33 // Use the basic MockDownloadItem, but override it to provide a valid GUID. | 38 // Use the basic MockDownloadItem, but override it to provide a valid GUID. |
| 34 class MockDownloadItemWithValues : public MockDownloadItem { | 39 class MockDownloadItemWithValues : public MockDownloadItem { |
|
Peter Beverloo
2017/03/10 00:55:14
How about moving //chrome/browser/ntp_snippets/fak
harkness
2017/03/10 13:50:57
Ah, good find, I hadn't seen that. I'll move it to
| |
| 35 public: | 40 public: |
| 41 MockDownloadItemWithValues(const std::string& guid) : guid_(guid) {} | |
| 42 | |
| 36 const std::string& GetGuid() const override { return guid_; } | 43 const std::string& GetGuid() const override { return guid_; } |
| 37 void SetGuid(const std::string& guid) { guid_ = guid; } | 44 void SetGuid(const std::string& guid) { guid_ = guid; } |
| 38 | 45 |
| 46 DownloadState GetState() const override { return state_; } | |
| 47 void SetState(DownloadState state) { state_ = state; } | |
| 48 | |
| 39 private: | 49 private: |
| 40 std::string guid_; | 50 std::string guid_; |
| 51 DownloadState state_ = DownloadItem::DownloadState::IN_PROGRESS; | |
| 41 }; | 52 }; |
| 42 | 53 |
| 43 // Use the basic MockDownloadManager, but override it so that it implements the | 54 // Use the basic MockDownloadManager, but override it so that it implements the |
| 44 // functionality that the JobController requires. | 55 // functionality that the JobController requires. |
| 45 class MockDownloadManagerWithCallback : public MockDownloadManager { | 56 class MockDownloadManagerWithCallback : public MockDownloadManager { |
| 46 public: | 57 public: |
| 47 void DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override { | 58 void DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override { |
| 48 DownloadUrlMock(params.get()); | 59 DownloadUrlMock(params.get()); |
| 49 params->callback().Run(&download_item_, DOWNLOAD_INTERRUPT_REASON_NONE); | 60 std::string guid = base::GenerateGUID(); |
| 61 download_items_.emplace_back( | |
| 62 base::MakeUnique<MockDownloadItemWithValues>(guid)); | |
| 63 params->callback().Run(download_items_.back().get(), | |
| 64 DOWNLOAD_INTERRUPT_REASON_NONE); | |
|
Peter Beverloo
2017/03/10 00:55:14
The `.back()` is a bit odd. What about:
std::
harkness
2017/03/10 13:50:57
Done.
| |
| 50 } | 65 } |
| 51 | 66 |
| 67 // This is very inefficient, but is only called during shutdown. | |
| 52 DownloadItem* GetDownloadByGuid(const std::string& guid) override { | 68 DownloadItem* GetDownloadByGuid(const std::string& guid) override { |
| 53 return &download_item_; | 69 for (const auto& item : download_items_) { |
| 70 if (item->GetGuid() == guid) | |
| 71 return item.get(); | |
| 72 } | |
| 73 return nullptr; | |
| 54 } | 74 } |
| 55 | 75 |
| 56 MockDownloadItemWithValues* download_item() { return &download_item_; } | 76 std::vector<std::unique_ptr<MockDownloadItemWithValues>>& download_items() { |
|
Peter Beverloo
2017/03/10 00:55:14
Two thoughts:
(1) This is a test, so it'd be OK
harkness
2017/03/10 13:50:57
If the property was on BackgroundFetchJObControlle
| |
| 77 return download_items_; | |
| 78 } | |
| 57 | 79 |
| 58 private: | 80 private: |
| 59 MockDownloadItemWithValues download_item_; | 81 std::vector<std::unique_ptr<MockDownloadItemWithValues>> download_items_; |
| 60 }; | 82 }; |
| 61 | 83 |
| 62 class BackgroundFetchJobControllerTest : public ::testing::Test { | 84 class BackgroundFetchJobControllerTest : public ::testing::Test { |
| 63 public: | 85 public: |
| 64 BackgroundFetchJobControllerTest() | 86 BackgroundFetchJobControllerTest() |
| 65 : download_manager_(new MockDownloadManagerWithCallback()) {} | 87 : download_manager_(new MockDownloadManagerWithCallback()) {} |
| 66 ~BackgroundFetchJobControllerTest() override = default; | 88 ~BackgroundFetchJobControllerTest() override = default; |
| 67 | 89 |
| 68 void SetUp() override { | 90 void SetUp() override { |
| 69 // The download_manager_ ownership is given to the BrowserContext, and the | 91 // The download_manager_ ownership is given to the BrowserContext, and the |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 | 126 |
| 105 DownloadItem::Observer* ItemObserver() const { return job_controller_.get(); } | 127 DownloadItem::Observer* ItemObserver() const { return job_controller_.get(); } |
| 106 | 128 |
| 107 private: | 129 private: |
| 108 TestBrowserThreadBundle thread_bundle_; | 130 TestBrowserThreadBundle thread_bundle_; |
| 109 TestBrowserContext browser_context_; | 131 TestBrowserContext browser_context_; |
| 110 std::unique_ptr<BackgroundFetchJobController> job_controller_; | 132 std::unique_ptr<BackgroundFetchJobController> job_controller_; |
| 111 MockDownloadManagerWithCallback* download_manager_; | 133 MockDownloadManagerWithCallback* download_manager_; |
| 112 }; | 134 }; |
| 113 | 135 |
| 114 TEST_F(BackgroundFetchJobControllerTest, StartDownload) { | 136 TEST_F(BackgroundFetchJobControllerTest, SingleRequestJob) { |
| 115 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), | 137 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), |
| 116 kServiceWorkerRegistrationId); | 138 kServiceWorkerRegistrationId); |
| 117 BackgroundFetchRequestInfo request_info(GURL(kTestUrl), kJobGuid); | 139 BackgroundFetchRequestInfo request_info(GURL(kTestUrl), kJobGuid); |
| 118 std::vector<BackgroundFetchRequestInfo> request_infos{request_info}; | 140 std::vector<BackgroundFetchRequestInfo> request_infos{request_info}; |
| 119 | 141 |
| 120 // Create a MockDownloadItem that the test can manipulate. | |
| 121 MockDownloadItemWithValues* item = download_manager()->download_item(); | |
| 122 item->SetGuid("foo"); | |
| 123 | |
| 124 // Get a JobData to give to the JobController. The JobController then gets | 142 // Get a JobData to give to the JobController. The JobController then gets |
| 125 // the BackgroundFetchRequestInfos from the JobData. The JobController will | 143 // the BackgroundFetchRequestInfos from the JobData. The JobController will |
| 126 // take ownership of the JobData. | 144 // take ownership of the JobData. |
| 127 BackgroundFetchJobData* job_data = new BackgroundFetchJobData(request_infos); | 145 BackgroundFetchJobData* job_data = new BackgroundFetchJobData(request_infos); |
| 128 InitializeJobController(job_data); | 146 InitializeJobController(job_data); |
| 129 | 147 |
| 130 EXPECT_CALL(*(download_manager()), | 148 EXPECT_CALL(*(download_manager()), |
| 131 DownloadUrlMock(::testing::Pointee(::testing::Property( | 149 DownloadUrlMock(::testing::Pointee(::testing::Property( |
| 132 &DownloadUrlParameters::url, GURL(kTestUrl))))) | 150 &DownloadUrlParameters::url, GURL(kTestUrl))))) |
| 133 .Times(1); | 151 .Times(1); |
| 134 | 152 |
| 135 StartProcessing(); | 153 StartProcessing(); |
| 154 | |
| 155 // Get one of the pending downloads from the download manager. | |
| 156 auto& download_items = download_manager()->download_items(); | |
| 157 EXPECT_EQ(1U, download_items.size()); | |
| 158 MockDownloadItemWithValues* item = download_items[0].get(); | |
|
Peter Beverloo
2017/03/10 00:55:14
Since we'd be accessing an invalid entry here if |
harkness
2017/03/10 13:50:57
Done.
| |
| 159 | |
| 160 // Update the observer with no actual change. | |
| 161 ItemObserver()->OnDownloadUpdated(item); | |
| 162 EXPECT_FALSE(job_data->IsComplete()); | |
| 163 | |
| 164 // Update the item to be completed then update the observer. The JobController | |
| 165 // should update the JobData that the request is complete. | |
| 166 item->SetState(DownloadItem::DownloadState::COMPLETE); | |
| 167 ItemObserver()->OnDownloadUpdated(item); | |
| 168 EXPECT_TRUE(job_data->IsComplete()); | |
| 169 } | |
| 170 | |
| 171 TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) { | |
| 172 BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), | |
| 173 kServiceWorkerRegistrationId); | |
| 174 std::vector<BackgroundFetchRequestInfo> request_infos; | |
| 175 for (int i = 0; i < 10; i++) { | |
| 176 request_infos.emplace_back( | |
| 177 BackgroundFetchRequestInfo(GURL(kTestUrl), base::IntToString(i))); | |
| 178 } | |
| 179 | |
| 180 // Get a JobData to give to the JobController. The JobController then gets | |
| 181 // the BackgroundFetchRequestInfos from the JobData. The JobController will | |
| 182 // take ownership of the JobData. | |
| 183 BackgroundFetchJobData* job_data = new BackgroundFetchJobData(request_infos); | |
| 184 InitializeJobController(job_data); | |
| 185 | |
| 186 EXPECT_CALL(*(download_manager()), | |
| 187 DownloadUrlMock(::testing::Pointee(::testing::Property( | |
| 188 &DownloadUrlParameters::url, GURL(kTestUrl))))) | |
| 189 .Times(10); | |
| 190 | |
| 191 StartProcessing(); | |
| 192 | |
| 193 // Get one of the pending downloads from the download manager. | |
| 194 auto& download_items = download_manager()->download_items(); | |
| 195 ASSERT_EQ(1U, download_items.size()); | |
| 196 MockDownloadItemWithValues* item = download_items[0].get(); | |
| 197 | |
| 198 // Update the observer with no actual change. | |
| 199 ItemObserver()->OnDownloadUpdated(item); | |
| 200 EXPECT_FALSE(job_data->IsComplete()); | |
| 201 EXPECT_EQ(1U, download_items.size()); | |
| 202 | |
| 203 for (size_t i = 0; i < 9; i++) { | |
| 204 // Update the next item to be completed then update the observer. | |
| 205 ASSERT_EQ(i + 1, download_items.size()); | |
| 206 item = download_items[i].get(); | |
| 207 item->SetState(DownloadItem::DownloadState::COMPLETE); | |
| 208 ItemObserver()->OnDownloadUpdated(item); | |
| 209 EXPECT_FALSE(job_data->IsComplete()); | |
| 210 } | |
| 211 EXPECT_FALSE(job_data->HasRequestsRemaining()); | |
| 212 | |
| 213 // Finally, update the last request to be complete. The JobController should | |
| 214 // see that there are no more requests and mark the job as done. | |
| 215 ASSERT_EQ(10U, download_items.size()); | |
| 216 item = download_items[9].get(); | |
| 217 item->SetState(DownloadItem::DownloadState::COMPLETE); | |
| 218 ItemObserver()->OnDownloadUpdated(item); | |
| 219 EXPECT_TRUE(job_data->IsComplete()); | |
| 136 } | 220 } |
| 137 | 221 |
| 138 } // namespace content | 222 } // namespace content |
| OLD | NEW |