| Index: content/browser/background_fetch/background_fetch_job_controller_unittest.cc | 
| diff --git a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc | 
| index 18513b2b8f8477d47b396a9070cdbf202b870163..94848a36d8e3d560cb5412601f2c25842ed6d0d1 100644 | 
| --- a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc | 
| +++ b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc | 
| @@ -4,15 +4,20 @@ | 
|  | 
| #include "content/browser/background_fetch/background_fetch_job_controller.h" | 
|  | 
| +#include <string> | 
| +#include <vector> | 
| + | 
| #include "base/bind_helpers.h" | 
| #include "base/callback_helpers.h" | 
| +#include "base/guid.h" | 
| #include "base/memory/ptr_util.h" | 
| #include "base/run_loop.h" | 
| +#include "base/strings/string_number_conversions.h" | 
| #include "content/browser/background_fetch/background_fetch_data_manager.h" | 
| #include "content/browser/background_fetch/background_fetch_job_info.h" | 
| #include "content/browser/background_fetch/background_fetch_request_info.h" | 
| #include "content/public/browser/browser_thread.h" | 
| -#include "content/public/test/mock_download_item.h" | 
| +#include "content/public/test/fake_download_item.h" | 
| #include "content/public/test/mock_download_manager.h" | 
| #include "content/public/test/test_browser_context.h" | 
| #include "content/public/test/test_browser_thread_bundle.h" | 
| @@ -30,36 +35,42 @@ const char kTag[] = "testTag"; | 
|  | 
| namespace content { | 
|  | 
| -// Use the basic MockDownloadItem, but override it to provide a valid GUID. | 
| -class MockDownloadItemWithValues : public MockDownloadItem { | 
| - public: | 
| -  const std::string& GetGuid() const override { return guid_; } | 
| -  void SetGuid(const std::string& guid) { guid_ = guid; } | 
| - | 
| - private: | 
| -  std::string guid_; | 
| -}; | 
| - | 
| // Use the basic MockDownloadManager, but override it so that it implements the | 
| // functionality that the JobController requires. | 
| class MockDownloadManagerWithCallback : public MockDownloadManager { | 
| public: | 
| void DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override { | 
| +    base::RunLoop run_loop; | 
| DownloadUrlMock(params.get()); | 
| +    std::string guid = base::GenerateGUID(); | 
| +    std::unique_ptr<FakeDownloadItem> item = | 
| +        base::MakeUnique<FakeDownloadItem>(); | 
| +    item->SetState(DownloadItem::DownloadState::IN_PROGRESS); | 
| +    item->SetGuid(guid); | 
| BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 
| -                            base::Bind(params->callback(), &download_item_, | 
| +                            base::Bind(params->callback(), item.get(), | 
| DOWNLOAD_INTERRUPT_REASON_NONE)); | 
| +    download_items_.push_back(std::move(item)); | 
| +    run_loop.RunUntilIdle(); | 
| } | 
|  | 
| +  // This is called during shutdown for each DownloadItem so can be an | 
| +  // O(n^2) where n is controlled by the users of the API. If n is expected to | 
| +  // be larger or the method is called in more places, consider alternatives. | 
| DownloadItem* GetDownloadByGuid(const std::string& guid) override { | 
| -    DCHECK_EQ(download_item_.GetGuid(), guid); | 
| -    return &download_item_; | 
| +    for (const auto& item : download_items_) { | 
| +      if (item->GetGuid() == guid) | 
| +        return item.get(); | 
| +    } | 
| +    return nullptr; | 
| } | 
|  | 
| -  MockDownloadItemWithValues* download_item() { return &download_item_; } | 
| +  const std::vector<std::unique_ptr<FakeDownloadItem>>& download_items() const { | 
| +    return download_items_; | 
| +  } | 
|  | 
| private: | 
| -  MockDownloadItemWithValues download_item_; | 
| +  std::vector<std::unique_ptr<FakeDownloadItem>> download_items_; | 
| }; | 
|  | 
| class BackgroundFetchJobControllerTest : public ::testing::Test { | 
| @@ -115,21 +126,18 @@ class BackgroundFetchJobControllerTest : public ::testing::Test { | 
| MockDownloadManagerWithCallback* download_manager_; | 
| }; | 
|  | 
| -TEST_F(BackgroundFetchJobControllerTest, StartDownload) { | 
| +TEST_F(BackgroundFetchJobControllerTest, SingleRequestJob) { | 
| BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), | 
| kServiceWorkerRegistrationId); | 
| BackgroundFetchRequestInfo request_info(GURL(kTestUrl), kJobGuid); | 
| std::vector<BackgroundFetchRequestInfo> request_infos{request_info}; | 
|  | 
| -  // Create a MockDownloadItem that the test can manipulate. | 
| -  MockDownloadItemWithValues* item = download_manager()->download_item(); | 
| -  item->SetGuid("foo"); | 
| - | 
| // Get a JobData to give to the JobController. The JobController then gets | 
| // the BackgroundFetchRequestInfos from the JobData. | 
| -  std::unique_ptr<BackgroundFetchJobData> job_data = | 
| +  std::unique_ptr<BackgroundFetchJobData> owned_job_data = | 
| base::MakeUnique<BackgroundFetchJobData>(request_infos); | 
| -  InitializeJobController(std::move(job_data)); | 
| +  BackgroundFetchJobData* job_data = owned_job_data.get(); | 
| +  InitializeJobController(std::move(owned_job_data)); | 
|  | 
| EXPECT_CALL(*(download_manager()), | 
| DownloadUrlMock(::testing::Pointee(::testing::Property( | 
| @@ -137,6 +145,72 @@ TEST_F(BackgroundFetchJobControllerTest, StartDownload) { | 
| .Times(1); | 
|  | 
| StartProcessing(); | 
| + | 
| +  // Get one of the pending downloads from the download manager. | 
| +  auto& download_items = download_manager()->download_items(); | 
| +  ASSERT_EQ(1U, download_items.size()); | 
| +  FakeDownloadItem* item = download_items[0].get(); | 
| + | 
| +  // Update the observer with no actual change. | 
| +  ItemObserver()->OnDownloadUpdated(item); | 
| +  EXPECT_FALSE(job_data->IsComplete()); | 
| + | 
| +  // Update the item to be completed then update the observer. The JobController | 
| +  // should update the JobData that the request is complete. | 
| +  item->SetState(DownloadItem::DownloadState::COMPLETE); | 
| +  ItemObserver()->OnDownloadUpdated(item); | 
| +  EXPECT_TRUE(job_data->IsComplete()); | 
| +} | 
| + | 
| +TEST_F(BackgroundFetchJobControllerTest, MultipleRequestJob) { | 
| +  BackgroundFetchJobInfo job_info(kTag, url::Origin(GURL(kOrigin)), | 
| +                                  kServiceWorkerRegistrationId); | 
| +  std::vector<BackgroundFetchRequestInfo> request_infos; | 
| +  for (int i = 0; i < 10; i++) { | 
| +    request_infos.emplace_back(GURL(kTestUrl), base::IntToString(i)); | 
| +  } | 
| + | 
| +  // Get a JobData to give to the JobController. The JobController then gets | 
| +  // the BackgroundFetchRequestInfos from the JobData. | 
| +  std::unique_ptr<BackgroundFetchJobData> owned_job_data = | 
| +      base::MakeUnique<BackgroundFetchJobData>(request_infos); | 
| +  BackgroundFetchJobData* job_data = owned_job_data.get(); | 
| +  InitializeJobController(std::move(owned_job_data)); | 
| + | 
| +  EXPECT_CALL(*(download_manager()), | 
| +              DownloadUrlMock(::testing::Pointee(::testing::Property( | 
| +                  &DownloadUrlParameters::url, GURL(kTestUrl))))) | 
| +      .Times(10); | 
| + | 
| +  StartProcessing(); | 
| + | 
| +  // Get one of the pending downloads from the download manager. | 
| +  auto& download_items = download_manager()->download_items(); | 
| +  ASSERT_EQ(1U, download_items.size()); | 
| +  FakeDownloadItem* item = download_items[0].get(); | 
| + | 
| +  // Update the observer with no actual change. | 
| +  ItemObserver()->OnDownloadUpdated(item); | 
| +  EXPECT_FALSE(job_data->IsComplete()); | 
| +  ASSERT_EQ(1U, download_items.size()); | 
| + | 
| +  for (size_t i = 0; i < 9; i++) { | 
| +    // Update the next item to be completed then update the observer. | 
| +    ASSERT_EQ(i + 1, download_items.size()); | 
| +    item = download_items[i].get(); | 
| +    item->SetState(DownloadItem::DownloadState::COMPLETE); | 
| +    ItemObserver()->OnDownloadUpdated(item); | 
| +    EXPECT_FALSE(job_data->IsComplete()); | 
| +  } | 
| +  EXPECT_FALSE(job_data->HasRequestsRemaining()); | 
| + | 
| +  // Finally, update the last request to be complete. The JobController should | 
| +  // see that there are no more requests and mark the job as done. | 
| +  ASSERT_EQ(10U, download_items.size()); | 
| +  item = download_items[9].get(); | 
| +  item->SetState(DownloadItem::DownloadState::COMPLETE); | 
| +  ItemObserver()->OnDownloadUpdated(item); | 
| +  EXPECT_TRUE(job_data->IsComplete()); | 
| } | 
|  | 
| }  // namespace content | 
|  |