// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/offline_pages/core/background/request_coordinator.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/containers/circular_deque.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
#include "base/system/sys_info.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/offline_items_collection/core/pending_state.h"
#include "components/offline_pages/core/background/device_conditions.h"
#include "components/offline_pages/core/background/offliner.h"
#include "components/offline_pages/core/background/offliner_policy.h"
#include "components/offline_pages/core/background/offliner_stub.h"
#include "components/offline_pages/core/background/request_coordinator_stub_taco.h"
#include "components/offline_pages/core/background/request_queue.h"
#include "components/offline_pages/core/background/request_queue_store.h"
#include "components/offline_pages/core/background/save_page_request.h"
#include "components/offline_pages/core/background/scheduler.h"
#include "components/offline_pages/core/background/scheduler_stub.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/offline_clock.h"
#include "components/offline_pages/core/offline_page_feature.h"
#include "services/network/test/test_network_quality_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace offline_pages {

namespace {
// put test constants here
const GURL kUrl1("http://universe.com/everything");
const GURL kUrl2("http://universe.com/toinfinityandbeyond");
const std::string kClientNamespace("bookmark");
const std::string kId1("42");
const std::string kId2("life*universe+everything");
const ClientId kClientId1(kClientNamespace, kId1);
const ClientId kClientId2(kClientNamespace, kId2);
const int kRequestId1(1);
const int kRequestId2(2);
const long kTestTimeBudgetSeconds = 200;
const int kBatteryPercentageHigh = 75;
const int kMaxCompletedTries = 3;
const bool kPowerRequired = true;
const bool kUserRequested = true;
const int kAttemptCount = 1;
const std::string kRequestOrigin("abc.xyz");

class ObserverStub : public RequestCoordinator::Observer {
 public:
  ObserverStub()
      : added_called_(false),
        completed_called_(false),
        changed_called_(false),
        network_progress_called_(false),
        network_progress_bytes_(0),
        last_status_(RequestCoordinator::BackgroundSavePageResult::SUCCESS),
        state_(SavePageRequest::RequestState::OFFLINING) {}

  void Clear() {
    added_called_ = false;
    completed_called_ = false;
    changed_called_ = false;
    network_progress_called_ = false;
    network_progress_bytes_ = 0;
    state_ = SavePageRequest::RequestState::OFFLINING;
    last_status_ = RequestCoordinator::BackgroundSavePageResult::SUCCESS;
  }

  void OnAdded(const SavePageRequest& request) override {
    added_called_ = true;
    state_ = request.request_state();
    pending_state_ = request.pending_state();
  }

  void OnCompleted(
      const SavePageRequest& request,
      RequestCoordinator::BackgroundSavePageResult status) override {
    completed_called_ = true;
    last_status_ = status;
  }

  void OnChanged(const SavePageRequest& request) override {
    changed_called_ = true;
    state_ = request.request_state();
    pending_state_ = request.pending_state();
  }

  void OnNetworkProgress(const SavePageRequest& request,
                         int64_t received_bytes) override {
    network_progress_called_ = true;
    network_progress_bytes_ = received_bytes;
  }

  bool added_called() { return added_called_; }
  bool completed_called() { return completed_called_; }
  bool changed_called() { return changed_called_; }
  bool network_progress_called() { return network_progress_called_; }
  int64_t network_progress_bytes() { return network_progress_bytes_; }
  RequestCoordinator::BackgroundSavePageResult last_status() {
    return last_status_;
  }
  SavePageRequest::RequestState state() { return state_; }
  PendingState pending_state() { return pending_state_; }

 private:
  bool added_called_;
  bool completed_called_;
  bool changed_called_;
  bool network_progress_called_;
  int64_t network_progress_bytes_;
  RequestCoordinator::BackgroundSavePageResult last_status_;
  SavePageRequest::RequestState state_;
  PendingState pending_state_;
};

class ActiveTabInfoStub : public RequestCoordinator::ActiveTabInfo {
 public:
  ~ActiveTabInfoStub() override {}
  bool DoesActiveTabMatch(const GURL&) override {
    return does_active_tab_match_;
  }
  void set_does_active_tab_match(bool match) { does_active_tab_match_ = match; }

 private:
  bool does_active_tab_match_ = false;
};

}  // namespace

// This class is a friend of RequestCoordinator, and can't be in the anonymous
// namespace.
class RequestCoordinatorTest : public testing::Test {
 public:
  using RequestCoordinatorState = RequestCoordinator::RequestCoordinatorState;

  RequestCoordinatorTest();
  ~RequestCoordinatorTest() override;

  void SetUp() override;
  void TearDown() override {
    PumpLoop();
    coordinator_taco_.reset();
    // Ensure cleanup tasks are complete, or we may leak memory.
    task_runner_->FastForwardUntilNoTasksRemain();
  }
  void PumpLoop();

  RequestCoordinator* coordinator() const {
    return coordinator_taco_->request_coordinator();
  }
  OfflinerStub* offliner() const { return offliner_; }
  SchedulerStub* scheduler_stub() const {
    return reinterpret_cast<SchedulerStub*>(coordinator()->scheduler());
  }
  RequestQueue* queue() {
    return coordinator_taco_->request_coordinator()->queue_for_testing();
  }
  RequestCoordinatorState state() { return coordinator()->state(); }

  // Test processing callback function.
  void ProcessingCallbackFunction(bool result) {
    processing_callback_called_ = true;
    processing_callback_result_ = result;
  }

  // Callback function which releases a wait for it.
  void WaitingCallbackFunction(bool result) { waiter_.Signal(); }

  net::NetworkChangeNotifier::ConnectionType GetConnectionType() {
    return coordinator()->current_conditions_->GetNetConnectionType();
  }

  // Callback for Add requests.
  void AddRequestDone(AddRequestResult result, const SavePageRequest& request);

  // Callback for getting requests.
  void GetRequestsDone(GetRequestsResult result,
                       std::vector<std::unique_ptr<SavePageRequest>> requests);

  // Callback for removing requests.
  void RemoveRequestsDone(const MultipleItemStatuses& results);

  // Callback for getting request statuses.
  void GetQueuedRequestsDone(
      std::vector<std::unique_ptr<SavePageRequest>> requests);

  void SetupForOfflinerDoneCallbackTest(
      offline_pages::SavePageRequest* request);

  void SendOfflinerDoneCallback(const SavePageRequest& request,
                                Offliner::RequestStatus status);

  GetRequestsResult last_get_requests_result() const {
    return last_get_requests_result_;
  }

  const std::vector<std::unique_ptr<SavePageRequest>>& last_requests() const {
    return last_requests_;
  }

  const MultipleItemStatuses& last_remove_results() const {
    return last_remove_results_;
  }

  void DisableLoading() { offliner_->disable_loading(); }

  void EnableOfflinerCallback(bool enable) {
    offliner_->enable_callback(enable);
  }

  void EnableSnapshotOnLastRetry() {
    offliner_->enable_snapshot_on_last_retry();
  }

  bool OfflinerCalled() const { return offliner_->load_and_save_called(); }

  void SetEffectiveConnectionTypeForTest(net::EffectiveConnectionType type) {
    network_quality_tracker_->ReportEffectiveConnectionTypeForTesting(type);
  }

  void SetNetworkConnected(bool connected) {
    if (connected) {
      DeviceConditions device_conditions(
          !kPowerRequired, kBatteryPercentageHigh,
          net::NetworkChangeNotifier::CONNECTION_3G);
      SetDeviceConditionsForTest(device_conditions);
      SetEffectiveConnectionTypeForTest(
          net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G);
    } else {
      DeviceConditions device_conditions(
          !kPowerRequired, kBatteryPercentageHigh,
          net::NetworkChangeNotifier::CONNECTION_NONE);
      SetDeviceConditionsForTest(device_conditions);
      SetEffectiveConnectionTypeForTest(
          net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
    }
  }

  void CallConnectionTypeObserver() {
    if (coordinator()->connection_notifier_) {
      coordinator()->connection_notifier_->OnNetworkChanged(
          GetConnectionType());
    }
  }

  void SetIsLowEndDeviceForTest(bool is_low_end_device) {
    coordinator()->is_low_end_device_ = is_low_end_device;
  }

  void SetProcessingStateForTest(
      RequestCoordinator::ProcessingWindowState processing_state) {
    coordinator()->processing_state_ = processing_state;
  }

  void SetOperationStartTimeForTest(base::Time start_time) {
    coordinator()->operation_start_time_ = start_time;
  }

  void ScheduleForTest() { coordinator()->ScheduleAsNeeded(); }

  void CallRequestNotPicked(bool non_user_requested_tasks_remaining,
                            bool disabled_tasks_remaining) {
    if (disabled_tasks_remaining)
      coordinator()->disabled_requests_.insert(kRequestId1);
    else
      coordinator()->disabled_requests_.clear();

    coordinator()->RequestNotPicked(non_user_requested_tasks_remaining, false,
                                    base::Time());
  }

  void SetDeviceConditionsForTest(DeviceConditions device_conditions) {
    coordinator()->SetDeviceConditionsForTest(device_conditions);
  }

  DeviceConditions* GetDeviceConditions() {
    return coordinator()->current_conditions_.get();
  }

  void WaitForCallback() { waiter_.Wait(); }

  void AdvanceClockBy(base::TimeDelta delta) {
    task_runner_->FastForwardBy(delta);
  }

  SavePageRequest AddRequest1();

  SavePageRequest AddRequest2();

  void SavePageRequestCallback(AddRequestResult result) {
    ASSERT_EQ(expected_add_request_result_, result);
    add_request_callback_called_ = true;
  }

  int64_t SavePageLater() {
    RequestCoordinator::SavePageLaterParams params;
    params.url = kUrl1;
    params.client_id = kClientId1;
    params.user_requested = kUserRequested;
    params.request_origin = kRequestOrigin;
    return coordinator()->SavePageLater(
        params, base::BindOnce(&RequestCoordinatorTest::SavePageRequestCallback,
                               base::Unretained(this)));
  }

  int64_t SavePageLaterWithAvailability(
      RequestCoordinator::RequestAvailability availability) {
    RequestCoordinator::SavePageLaterParams params;
    params.url = kUrl1;
    params.client_id = kClientId1;
    params.user_requested = kUserRequested;
    params.availability = availability;
    params.request_origin = kRequestOrigin;
    return coordinator()->SavePageLater(
        params, base::BindOnce(&RequestCoordinatorTest::SavePageRequestCallback,
                               base::Unretained(this)));
  }

  Offliner::RequestStatus last_offlining_status() const {
    return coordinator()->last_offlining_status_;
  }

  // Calls the private method |StopProcessing| on |coordinator()|.
  void StopProcessing(Offliner::RequestStatus stop_status) {
    coordinator()->StopProcessing(stop_status);
  }

  bool OfflinerWasCanceled() const { return offliner_->cancel_called(); }

  void ResetOfflinerWasCanceled() { offliner_->reset_cancel_called(); }

  ObserverStub observer() { return observer_; }

  DeviceConditions device_conditions() { return device_conditions_; }

  base::RepeatingCallback<void(bool)> processing_callback() {
    return processing_callback_;
  }

  base::RepeatingCallback<void(bool)> waiting_callback() {
    return waiting_callback_;
  }

  bool processing_callback_called() const {
    return processing_callback_called_;
  }

  bool processing_callback_result() const {
    return processing_callback_result_;
  }

  const base::HistogramTester& histograms() const { return histogram_tester_; }

  const std::set<int64_t>& disabled_requests() {
    return coordinator()->disabled_requests_;
  }

  const base::circular_deque<int64_t>& prioritized_requests() {
    return coordinator()->prioritized_requests_;
  }

  bool add_request_callback_called() { return add_request_callback_called_; }

  scoped_refptr<base::TestMockTimeTaskRunner> task_runner() const {
    return task_runner_;
  }

 protected:
  ActiveTabInfoStub* active_tab_info_ = nullptr;

 private:
  GetRequestsResult last_get_requests_result_;
  MultipleItemStatuses last_remove_results_;
  std::vector<std::unique_ptr<SavePageRequest>> last_requests_;
  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
  base::ThreadTaskRunnerHandle task_runner_handle_;
  network::NetworkQualityTracker* network_quality_tracker_;
  std::unique_ptr<RequestCoordinatorStubTaco> coordinator_taco_;
  OfflinerStub* offliner_;
  base::WaitableEvent waiter_;
  ObserverStub observer_;
  AddRequestResult expected_add_request_result_;
  bool add_request_callback_called_;
  bool processing_callback_called_;
  bool processing_callback_result_;
  DeviceConditions device_conditions_;
  base::RepeatingCallback<void(bool)> processing_callback_;
  base::RepeatingCallback<void(bool)> waiting_callback_;
  base::HistogramTester histogram_tester_;
};

RequestCoordinatorTest::RequestCoordinatorTest()
    : last_get_requests_result_(GetRequestsResult::STORE_FAILURE),
      task_runner_(new base::TestMockTimeTaskRunner),
      task_runner_handle_(task_runner_),
      offliner_(nullptr),
      waiter_(base::WaitableEvent::ResetPolicy::MANUAL,
              base::WaitableEvent::InitialState::NOT_SIGNALED),
      expected_add_request_result_(AddRequestResult::SUCCESS),
      add_request_callback_called_(false),
      processing_callback_called_(false),
      processing_callback_result_(false),
      device_conditions_(!kPowerRequired,
                         kBatteryPercentageHigh,
                         net::NetworkChangeNotifier::CONNECTION_3G) {}

RequestCoordinatorTest::~RequestCoordinatorTest() {}

void RequestCoordinatorTest::SetUp() {
  coordinator_taco_ = std::make_unique<RequestCoordinatorStubTaco>();

  std::unique_ptr<OfflinerStub> offliner(new OfflinerStub());
  // Save raw pointer for use by the tests.
  offliner_ = offliner.get();
  coordinator_taco_->SetOffliner(std::move(offliner));

  std::unique_ptr<network::NetworkQualityTracker> test_network_quality_tracker(
      std::make_unique<network::TestNetworkQualityTracker>());
  // Save raw pointer for use by the tests.
  network_quality_tracker_ = test_network_quality_tracker.get();
  coordinator_taco_->SetNetworkQualityProvider(
      std::move(test_network_quality_tracker));
  auto delegate = std::make_unique<ActiveTabInfoStub>();
  active_tab_info_ = delegate.get();
  coordinator_taco_->SetRequestCoordinatorDelegate(std::move(delegate));

  coordinator_taco_->CreateRequestCoordinator();

  coordinator()->AddObserver(&observer_);
  SetNetworkConnected(true);
  processing_callback_ =
      base::BindRepeating(&RequestCoordinatorTest::ProcessingCallbackFunction,
                          base::Unretained(this));
  // Override the normal immediate callback with a wait releasing callback.
  waiting_callback_ = base::BindRepeating(
      &RequestCoordinatorTest::WaitingCallbackFunction, base::Unretained(this));
  SetDeviceConditionsForTest(device_conditions_);
  // Ensure not low-end device so immediate start can happen for most tests.
  SetIsLowEndDeviceForTest(false);
  EnableOfflinerCallback(true);
}

void RequestCoordinatorTest::PumpLoop() {
  task_runner_->RunUntilIdle();
}

void RequestCoordinatorTest::GetRequestsDone(
    GetRequestsResult result,
    std::vector<std::unique_ptr<SavePageRequest>> requests) {
  last_get_requests_result_ = result;
  last_requests_ = std::move(requests);
}

void RequestCoordinatorTest::RemoveRequestsDone(
    const MultipleItemStatuses& results) {
  last_remove_results_ = results;
  waiter_.Signal();
}

void RequestCoordinatorTest::GetQueuedRequestsDone(
    std::vector<std::unique_ptr<SavePageRequest>> requests) {
  last_requests_ = std::move(requests);
  waiter_.Signal();
}

void RequestCoordinatorTest::AddRequestDone(AddRequestResult result,
                                            const SavePageRequest& request) {}

void RequestCoordinatorTest::SetupForOfflinerDoneCallbackTest(
    offline_pages::SavePageRequest* request) {
  // Mark request as started and add it to the queue,
  // then wait for callback to finish.
  request->MarkAttemptStarted(OfflineTimeNow());
  queue()->AddRequest(*request,
                      base::BindOnce(&RequestCoordinatorTest::AddRequestDone,
                                     base::Unretained(this)));
  PumpLoop();

  // Override the processing callback for test visiblity.
  base::RepeatingCallback<void(bool)> callback =
      base::BindRepeating(&RequestCoordinatorTest::ProcessingCallbackFunction,
                          base::Unretained(this));
  coordinator()->SetProcessingCallbackForTest(callback);

  // Mock that coordinator is in actively processing state starting now.
  SetProcessingStateForTest(
      RequestCoordinator::ProcessingWindowState::IMMEDIATE_WINDOW);
  SetOperationStartTimeForTest(OfflineTimeNow());
}

void RequestCoordinatorTest::SendOfflinerDoneCallback(
    const SavePageRequest& request,
    Offliner::RequestStatus status) {
  // Using the fact that the test class is a friend, call to the callback
  coordinator()->OfflinerDoneCallback(request, status);
}

SavePageRequest RequestCoordinatorTest::AddRequest1() {
  offline_pages::SavePageRequest request1(kRequestId1, kUrl1, kClientId1,
                                          OfflineTimeNow(), kUserRequested);
  queue()->AddRequest(request1,
                      base::BindOnce(&RequestCoordinatorTest::AddRequestDone,
                                     base::Unretained(this)));
  return request1;
}

SavePageRequest RequestCoordinatorTest::AddRequest2() {
  offline_pages::SavePageRequest request2(kRequestId2, kUrl2, kClientId2,
                                          OfflineTimeNow(), kUserRequested);
  queue()->AddRequest(request2,
                      base::BindOnce(&RequestCoordinatorTest::AddRequestDone,
                                     base::Unretained(this)));
  return request2;
}

TEST_F(RequestCoordinatorTest, StartScheduledProcessingWithNoRequests) {
  // Set low-end device status to actual status.
  SetIsLowEndDeviceForTest(base::SysInfo::IsLowEndDevice());

  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));
  PumpLoop();

  EXPECT_TRUE(processing_callback_called());

  // Verify queue depth UMA for starting scheduled processing on empty queue.
  if (base::SysInfo::IsLowEndDevice()) {
    histograms().ExpectBucketCount(
        "OfflinePages.Background.ScheduledStart.AvailableRequestCount.Svelte",
        0, 1);
  } else {
    histograms().ExpectBucketCount(
        "OfflinePages.Background.ScheduledStart.AvailableRequestCount", 0, 1);
  }
}

TEST_F(RequestCoordinatorTest, NetworkProgressCallback) {
  EXPECT_NE(0, SavePageLater());
  PumpLoop();
  EXPECT_TRUE(observer().network_progress_called());
  EXPECT_GT(observer().network_progress_bytes(), 0LL);
}

TEST_F(RequestCoordinatorTest, StartScheduledProcessingWithRequestInProgress) {
  // Start processing for this request.
  EXPECT_NE(0, SavePageLater());

  // Ensure that the forthcoming request does not finish - we simulate it being
  // in progress by asking it to skip making the completion callback.
  EnableOfflinerCallback(false);

  // Sending the request to the offliner should make it busy.
  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));
  PumpLoop();

  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
  // Since the offliner is disabled, this callback should not be called.
  EXPECT_FALSE(processing_callback_called());

  // Now trying to start processing should return false since already busy.
  EXPECT_FALSE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                       processing_callback()));
}

TEST_F(RequestCoordinatorTest, StartImmediateProcessingWithNoRequests) {
  EXPECT_TRUE(coordinator()->StartImmediateProcessing(processing_callback()));
  PumpLoop();

  EXPECT_TRUE(processing_callback_called());

  histograms().ExpectBucketCount("OfflinePages.Background.ImmediateStartStatus",
                                 0 /* STARTED */, 1);
}

TEST_F(RequestCoordinatorTest, StartImmediateProcessingOnSvelte) {
  // Set as low-end device to verfiy immediate processing will not start.
  SetIsLowEndDeviceForTest(true);

  EXPECT_FALSE(coordinator()->StartImmediateProcessing(processing_callback()));
  histograms().ExpectBucketCount("OfflinePages.Background.ImmediateStartStatus",
                                 5 /* NOT_STARTED_ON_SVELTE */, 1);
}

TEST_F(RequestCoordinatorTest, StartImmediateProcessingWhenDisconnected) {
  DeviceConditions disconnected_conditions(
      !kPowerRequired, kBatteryPercentageHigh,
      net::NetworkChangeNotifier::CONNECTION_NONE);
  SetDeviceConditionsForTest(disconnected_conditions);
  EXPECT_FALSE(coordinator()->StartImmediateProcessing(processing_callback()));
  histograms().ExpectBucketCount("OfflinePages.Background.ImmediateStartStatus",
                                 3 /* NO_CONNECTION */, 1);
}

TEST_F(RequestCoordinatorTest, StartImmediateProcessingWithRequestInProgress) {
  // Start processing for this request.
  EXPECT_NE(0, SavePageLater());

  // Disable the automatic offliner callback.
  EnableOfflinerCallback(false);

  // Sending the request to the offliner should make it busy.
  EXPECT_TRUE(coordinator()->StartImmediateProcessing(processing_callback()));
  PumpLoop();

  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
  // Since the offliner is disabled, this callback should not be called.
  EXPECT_FALSE(processing_callback_called());

  // Now trying to start processing should return false since already busy.
  EXPECT_FALSE(coordinator()->StartImmediateProcessing(processing_callback()));

  histograms().ExpectBucketCount("OfflinePages.Background.ImmediateStartStatus",
                                 1 /* BUSY */, 1);
}

TEST_F(RequestCoordinatorTest, SavePageLater) {
  // The user-requested request which gets processed by SavePageLater
  // would invoke user request callback.
  coordinator()->SetInternalStartProcessingCallbackForTest(
      processing_callback());

  // Use default values for |user_requested| and |availability|.
  RequestCoordinator::SavePageLaterParams params;
  params.url = kUrl1;
  params.client_id = kClientId1;
  params.original_url = kUrl2;
  params.request_origin = kRequestOrigin;
  EXPECT_NE(0, coordinator()->SavePageLater(
                   params, base::BindOnce(
                               &RequestCoordinatorTest::SavePageRequestCallback,
                               base::Unretained(this))));

  // Expect that a request got placed on the queue.
  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));

  // Expect that the request is not added to the disabled list by default.
  EXPECT_TRUE(disabled_requests().empty());

  // Wait for callbacks to finish, both request queue and offliner.
  PumpLoop();
  EXPECT_TRUE(processing_callback_called());
  EXPECT_TRUE(add_request_callback_called());

  // Check the request queue is as expected.
  ASSERT_EQ(1UL, last_requests().size());
  EXPECT_EQ(kUrl1, last_requests().at(0)->url());
  EXPECT_EQ(kClientId1, last_requests().at(0)->client_id());
  EXPECT_TRUE(last_requests().at(0)->user_requested());
  EXPECT_EQ(kUrl2, last_requests().at(0)->original_url());
  EXPECT_EQ(kRequestOrigin, last_requests().at(0)->request_origin());

  // Expect that the scheduler got notified.
  EXPECT_TRUE(scheduler_stub()->schedule_called());
  EXPECT_EQ(coordinator()
                ->GetTriggerConditions(last_requests()[0]->user_requested())
                .minimum_battery_percentage,
            scheduler_stub()->trigger_conditions()->minimum_battery_percentage);

  // Check that the observer got the notification that a page is available
  EXPECT_TRUE(observer().added_called());

  // Verify queue depth UMA for starting immediate processing.
  histograms().ExpectBucketCount(
      "OfflinePages.Background.ImmediateStart.AvailableRequestCount", 1, 1);
}

TEST_F(RequestCoordinatorTest, SavePageLaterFailed) {
  // Set low-end device status to actual status.
  SetIsLowEndDeviceForTest(base::SysInfo::IsLowEndDevice());

  // The user-requested request which gets processed by SavePageLater
  // would invoke user request callback.
  coordinator()->SetInternalStartProcessingCallbackForTest(
      processing_callback());

  EXPECT_NE(0, SavePageLater());

  // Expect that a request got placed on the queue.
  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));

  // Wait for callbacks to finish, both request queue and offliner.
  PumpLoop();

  // On low-end devices the callback will be called with false since the
  // processing started but failed due to svelte devices.
  EXPECT_TRUE(processing_callback_called());
  if (base::SysInfo::IsLowEndDevice()) {
    EXPECT_FALSE(processing_callback_result());
  } else {
    EXPECT_TRUE(processing_callback_result());
  }

  EXPECT_TRUE(add_request_callback_called());
  // Check the request queue is as expected.
  EXPECT_EQ(1UL, last_requests().size());
  EXPECT_EQ(kUrl1, last_requests().at(0)->url());
  EXPECT_EQ(kClientId1, last_requests().at(0)->client_id());

  // Expect that the scheduler got notified.
  EXPECT_TRUE(scheduler_stub()->schedule_called());
  EXPECT_EQ(coordinator()
                ->GetTriggerConditions(last_requests()[0]->user_requested())
                .minimum_battery_percentage,
            scheduler_stub()->trigger_conditions()->minimum_battery_percentage);

  // Check that the observer got the notification that a page is available
  EXPECT_TRUE(observer().added_called());
}

TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceeded) {
  // Add a request to the queue, wait for callbacks to finish.
  offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1,
                                         OfflineTimeNow(), kUserRequested);
  SetupForOfflinerDoneCallbackTest(&request);

  // Call the OfflinerDoneCallback to simulate the page being completed, wait
  // for callbacks.
  SendOfflinerDoneCallback(request, Offliner::RequestStatus::SAVED);
  PumpLoop();
  EXPECT_TRUE(processing_callback_called());

  // Verify the request gets removed from the queue, and wait for callbacks.
  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));
  PumpLoop();

  // We should not find any requests in the queue anymore.
  // RequestPicker should *not* have tried to start an additional job,
  // because the request queue is empty now.
  EXPECT_EQ(0UL, last_requests().size());
  // Check that the observer got the notification that we succeeded, and that
  // the request got removed from the queue.
  EXPECT_TRUE(observer().completed_called());
  histograms().ExpectBucketCount(
      "OfflinePages.Background.FinalSavePageResult.bookmark", 0 /* SUCCESS */,
      1);
  EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::SUCCESS,
            observer().last_status());
}

TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceededButLostNetwork) {
  // Add a request to the queue and set offliner done callback for it.
  offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1,
                                         OfflineTimeNow(), kUserRequested);
  SetupForOfflinerDoneCallbackTest(&request);
  EnableOfflinerCallback(false);

  // Add a 2nd request to the queue.
  AddRequest2();

  // Disconnect network.
  SetNetworkConnected(false);

  // Call the OfflinerDoneCallback to simulate the page being completed, wait
  // for callbacks.
  SendOfflinerDoneCallback(request, Offliner::RequestStatus::SAVED);
  PumpLoop();
  EXPECT_TRUE(processing_callback_called());

  // Verify not busy with 2nd request (since no connection).
  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);

  // Now connect network and verify processing starts.
  SetNetworkConnected(true);
  CallConnectionTypeObserver();
  PumpLoop();
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}

TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) {
  // Add a request to the queue, wait for callbacks to finish.
  offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1,
                                         OfflineTimeNow(), kUserRequested);
  request.set_completed_attempt_count(kMaxCompletedTries - 1);
  SetupForOfflinerDoneCallbackTest(&request);
  // Stop processing before completing the second request on the queue.
  EnableOfflinerCallback(false);

  // Add second request to the queue to check handling when first fails.
  AddRequest2();
  PumpLoop();

  // Call the OfflinerDoneCallback to simulate the request failed, wait
  // for callbacks.
  SendOfflinerDoneCallback(request, Offliner::RequestStatus::LOADING_FAILED);
  PumpLoop();

  // For retriable failure, processing should continue to 2nd request so
  // no scheduler callback yet.
  EXPECT_FALSE(processing_callback_called());

  // Busy processing 2nd request.
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);

  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));
  PumpLoop();

  // Now just one request in the queue since failed request removed
  // (max number of attempts exceeded).
  EXPECT_EQ(1UL, last_requests().size());
  // Check that the observer got the notification that we failed (and the
  // subsequent notification that the request was removed) since we exceeded
  // retry count.
  EXPECT_TRUE(observer().completed_called());
  histograms().ExpectBucketCount(
      "OfflinePages.Background.FinalSavePageResult.bookmark",
      6 /* RETRY_COUNT_EXCEEDED */, 1);
  EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::RETRY_COUNT_EXCEEDED,
            observer().last_status());
}

TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoRetryFailure) {
  // Add a request to the queue, wait for callbacks to finish.
  offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1,
                                         OfflineTimeNow(), kUserRequested);
  SetupForOfflinerDoneCallbackTest(&request);
  EnableOfflinerCallback(false);

  // Add second request to the queue to check handling when first fails.
  AddRequest2();
  PumpLoop();

  // Call the OfflinerDoneCallback to simulate the request failed, wait
  // for callbacks.
  SendOfflinerDoneCallback(request,
                           Offliner::RequestStatus::LOADING_FAILED_NO_RETRY);
  PumpLoop();

  // For no retry failure, processing should continue to 2nd request so
  // no scheduler callback yet.
  EXPECT_FALSE(processing_callback_called());

  // Busy processing 2nd request.
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);

  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));
  PumpLoop();

  // Now just one request in the queue since non-retryable failure.
  EXPECT_EQ(1UL, last_requests().size());
  // Check that the observer got the notification that we failed (and the
  // subsequent notification that the request was removed).
  EXPECT_TRUE(observer().completed_called());
  EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::LOADING_FAILURE,
            observer().last_status());
  // We should have a histogram entry for the effective network conditions
  // when this failed request began.
  histograms().ExpectBucketCount(
      "OfflinePages.Background.EffectiveConnectionType.OffliningStartType."
      "bookmark",
      net::NetworkChangeNotifier::CONNECTION_UNKNOWN, 1);
}

TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoNextFailure) {
  // Add a request to the queue, wait for callbacks to finish.
  offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1,
                                         OfflineTimeNow(), kUserRequested);
  SetupForOfflinerDoneCallbackTest(&request);
  EnableOfflinerCallback(false);

  // Add second request to the queue to check handling when first fails.
  AddRequest2();
  PumpLoop();

  // Call the OfflinerDoneCallback to simulate the request failed, wait
  // for callbacks.
  SendOfflinerDoneCallback(request,
                           Offliner::RequestStatus::LOADING_FAILED_NO_NEXT);
  PumpLoop();

  // For no next failure, processing should not continue to 2nd request so
  // expect scheduler callback.
  EXPECT_TRUE(processing_callback_called());

  // Not busy for NO_NEXT failure.
  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);

  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));
  PumpLoop();

  // Both requests still in queue.
  EXPECT_EQ(2UL, last_requests().size());
}

TEST_F(RequestCoordinatorTest, OfflinerDoneForegroundCancel) {
  // Add a request to the queue, wait for callbacks to finish.
  offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1,
                                         OfflineTimeNow(), kUserRequested);
  SetupForOfflinerDoneCallbackTest(&request);

  // Call the OfflinerDoneCallback to simulate the request failed, wait
  // for callbacks.
  SendOfflinerDoneCallback(request,
                           Offliner::RequestStatus::FOREGROUND_CANCELED);
  PumpLoop();
  EXPECT_TRUE(processing_callback_called());

  // Verify the request is not removed from the queue, and wait for callbacks.
  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));
  PumpLoop();

  // Request no longer in the queue (for single attempt policy).
  EXPECT_EQ(1UL, last_requests().size());
  // Verify foreground cancel not counted as an attempt after all.
  EXPECT_EQ(0L, last_requests().at(0)->completed_attempt_count());
}

TEST_F(RequestCoordinatorTest, RequestDeferred) {
  // Test handling of requests that can be deferred due to
  // defer_while_page_is_active.
  active_tab_info_->set_does_active_tab_match(true);
  RequestCoordinator::SavePageLaterParams params;
  params.url = kUrl1;
  // Auto-async uses defer_background_fetch_while_page_is_active.
  params.client_id = ClientId(kAutoAsyncNamespace, "1");
  coordinator()->SavePageLater(params, base::DoNothing());
  PumpLoop();

  // Verify the request is not removed from the queue, and wait for callbacks.
  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));
  PumpLoop();

  // Request still in the queue.
  ASSERT_EQ(1UL, last_requests().size());
  EXPECT_EQ(1L, last_requests()[0]->started_attempt_count());
  EXPECT_EQ(1L, last_requests()[0]->completed_attempt_count());

  // The scheduler is called. Simulate the scheduler calling us back.
  // This time, the request was tried recently, and will not be retried again.
  // Since there are no requests this time, backup_schedule is called with a
  // delay that matches the deferral interval.
  ASSERT_TRUE(scheduler_stub()->schedule_called());
  coordinator()->StartScheduledProcessing(device_conditions(),
                                          processing_callback());

  PumpLoop();
  EXPECT_TRUE(scheduler_stub()->backup_schedule_called());
  // Add plenty of tolerance to avoid flakes.
  EXPECT_LT(PickRequestTask::kDeferInterval.InSeconds() - 10,
            scheduler_stub()->schedule_delay());
}

TEST_F(RequestCoordinatorTest, RequestNotDeferred) {
  // Test defer_while_page_is_active=true, but the DoesActiveTabMatch returns
  // false. The page should be offlined.
  active_tab_info_->set_does_active_tab_match(false);
  RequestCoordinator::SavePageLaterParams params;
  params.url = kUrl1;
  // Auto-async uses defer_background_fetch_while_page_is_active.
  params.client_id = ClientId(kAutoAsyncNamespace, "1");
  coordinator()->SavePageLater(params, base::DoNothing());
  PumpLoop();

  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));
  PumpLoop();

  // Request was completed.
  ASSERT_EQ(0UL, last_requests().size());
}

// If one item completes, and there are no more user requeted items left,
// we should make a scheduler entry for a non-user requested item.
TEST_F(RequestCoordinatorTest, RequestNotPickedDisabledItemsRemain) {
  coordinator()->StartScheduledProcessing(device_conditions(),
                                          processing_callback());
  EXPECT_TRUE(state() == RequestCoordinatorState::PICKING);

  // Call RequestNotPicked, simulating a request on the disabled list.
  CallRequestNotPicked(false, true);
  PumpLoop();

  EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);

  // The scheduler should have been called to schedule the disabled task for
  // 5 minutes from now.
  EXPECT_TRUE(scheduler_stub()->backup_schedule_called());
  EXPECT_TRUE(scheduler_stub()->unschedule_called());
}

// If one item completes, and there are no more user requeted items left,
// we should make a scheduler entry for a non-user requested item.
TEST_F(RequestCoordinatorTest, RequestNotPickedNonUserRequestedItemsRemain) {
  coordinator()->StartScheduledProcessing(device_conditions(),
                                          processing_callback());
  EXPECT_TRUE(state() == RequestCoordinatorState::PICKING);

  // Call RequestNotPicked, and make sure we pick schedule a task for non user
  // requested conditions, with no tasks on the disabled list.
  CallRequestNotPicked(true, false);
  PumpLoop();

  EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
  EXPECT_TRUE(processing_callback_called());

  // The scheduler should have been called to schedule the non-user requested
  // task.
  EXPECT_TRUE(scheduler_stub()->schedule_called());
  EXPECT_TRUE(scheduler_stub()->unschedule_called());
  const Scheduler::TriggerConditions* conditions =
      scheduler_stub()->trigger_conditions();
  EXPECT_EQ(conditions->require_power_connected,
            coordinator()->policy()->PowerRequired(!kUserRequested));
  EXPECT_EQ(
      conditions->minimum_battery_percentage,
      coordinator()->policy()->BatteryPercentageRequired(!kUserRequested));
  EXPECT_EQ(conditions->require_unmetered_network,
            coordinator()->policy()->UnmeteredNetworkRequired(!kUserRequested));
}

TEST_F(RequestCoordinatorTest, SchedulerGetsLeastRestrictiveConditions) {
  // Put two requests on the queue - The first is user requested, and
  // the second is not user requested.
  AddRequest1();
  offline_pages::SavePageRequest request2(kRequestId2, kUrl2, kClientId2,
                                          OfflineTimeNow(), !kUserRequested);
  queue()->AddRequest(request2,
                      base::BindOnce(&RequestCoordinatorTest::AddRequestDone,
                                     base::Unretained(this)));
  PumpLoop();

  // Trigger the scheduler to schedule for the least restrictive condition.
  ScheduleForTest();
  PumpLoop();

  // Expect that the scheduler got notified, and it is at user_requested
  // priority.
  const Scheduler::TriggerConditions* conditions =
      scheduler_stub()->trigger_conditions();
  EXPECT_TRUE(scheduler_stub()->schedule_called());
  EXPECT_EQ(conditions->require_power_connected,
            coordinator()->policy()->PowerRequired(kUserRequested));
  EXPECT_EQ(conditions->minimum_battery_percentage,
            coordinator()->policy()->BatteryPercentageRequired(kUserRequested));
  EXPECT_EQ(conditions->require_unmetered_network,
            coordinator()->policy()->UnmeteredNetworkRequired(kUserRequested));
}

TEST_F(RequestCoordinatorTest, StartScheduledProcessingWithLoadingDisabled) {
  // Add a request to the queue, wait for callbacks to finish.
  AddRequest1();
  PumpLoop();

  DisableLoading();
  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));

  // Let the async callbacks in the request coordinator run.
  PumpLoop();
  EXPECT_TRUE(processing_callback_called());

  EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
  EXPECT_EQ(Offliner::RequestStatus::LOADING_NOT_ACCEPTED,
            last_offlining_status());
}

// TODO(dougarnett): Add StartScheduledProcessing test for QUEUE_UPDATE_FAILED.

// This tests a StopProcessing call before we have actually started the
// offliner.
TEST_F(RequestCoordinatorTest,
       StartScheduledProcessingThenStopProcessingImmediately) {
  // Add a request to the queue, wait for callbacks to finish.
  AddRequest1();
  PumpLoop();

  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));
  EXPECT_TRUE(state() == RequestCoordinatorState::PICKING);

  // Now, quick, before it can do much (we haven't called PumpLoop), cancel it
  // with a status that precludes trying again.
  StopProcessing(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED);

  // Let the async callbacks in the request coordinator run.
  PumpLoop();
  EXPECT_TRUE(processing_callback_called());

  EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);

  // OfflinerDoneCallback will not end up getting called with status SAVED,
  // since we cancelled the event before it called offliner_->LoadAndSave().
  EXPECT_EQ(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED,
            last_offlining_status());

  // Since offliner was not started, it will not have seen cancel call.
  EXPECT_FALSE(OfflinerWasCanceled());
}

// This tests a StopProcessing call after the background loading has been
// started.
TEST_F(RequestCoordinatorTest,
       StartScheduledProcessingThenStopProcessingLater) {
  // Add a request to the queue, wait for callbacks to finish.
  AddRequest1();
  PumpLoop();

  // Ensure the start processing request stops before the completion callback.
  EnableOfflinerCallback(false);

  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));
  EXPECT_TRUE(state() == RequestCoordinatorState::PICKING);

  // Let all the async parts of the start processing pipeline run to completion.
  PumpLoop();

  // Observer called for starting processing.
  EXPECT_TRUE(observer().changed_called());
  EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state());
  observer().Clear();

  // Since the offliner is disabled, this callback should not be called.
  EXPECT_FALSE(processing_callback_called());

  // Coordinator should now be busy.
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
  EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);

  // Now we cancel it while the background loader is busy.
  StopProcessing(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED);

  // Let the async callbacks in the cancel run.
  PumpLoop();

  // Observer called for stopped processing.
  EXPECT_TRUE(observer().changed_called());
  EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
  observer().Clear();

  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);

  // OfflinerDoneCallback will not end up getting called with status SAVED,
  // since we cancelled the event before the LoadAndSave completed.
  EXPECT_EQ(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED,
            last_offlining_status());

  // Since offliner was started, it will have seen cancel call.
  EXPECT_TRUE(OfflinerWasCanceled());
}

// Test handling of StartScheduledProcessing before a previous attempt has been
// fully stopped.
TEST_F(RequestCoordinatorTest, StartAttemptBeforeFullyStopped) {
  // Add a request to the queue, wait for callbacks to finish.
  AddRequest1();
  PumpLoop();

  // Ensure the start processing request stops before the completion callback.
  EnableOfflinerCallback(false);

  ASSERT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));
  // Let all the async parts of the start processing pipeline run to completion.
  PumpLoop();

  // Observer called for starting processing.
  ASSERT_TRUE(observer().changed_called());
  ASSERT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state());
  observer().Clear();

  // Now we cancel it while the background loader is busy, and attempt to start
  // another request. Because the previous request hasn't completely stopped,
  // the second request will not start.
  StopProcessing(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED);

  AddRequest2();
  EXPECT_FALSE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                       processing_callback()));
  PumpLoop();
  EXPECT_FALSE(offliner()->has_pending_request());
}

// Verify the request coordinator can stop while in the picking state.
TEST_F(RequestCoordinatorTest, StopProcessingWhilePicking) {
  // Add a request and start processing.
  AddRequest1();
  ASSERT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));
  ASSERT_EQ(RequestCoordinatorState::PICKING, state());

  StopProcessing(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED);

  // Let all the async parts of the start processing pipeline run to completion.
  // The offliner should have never been called.
  PumpLoop();
  EXPECT_FALSE(OfflinerCalled());
}

// This tests that canceling a request will result in TryNextRequest() getting
// called.
TEST_F(RequestCoordinatorTest, RemoveInflightRequest) {
  // Add a request to the queue, wait for callbacks to finish.
  AddRequest1();
  PumpLoop();

  // Ensure the start processing request stops before the completion callback.
  EnableOfflinerCallback(false);

  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));

  // Let all the async parts of the start processing pipeline run to completion.
  PumpLoop();
  // Since the offliner is disabled, this callback should not be called.
  EXPECT_FALSE(processing_callback_called());

  // Remove the request while it is processing.
  std::vector<int64_t> request_ids{kRequestId1};
  coordinator()->RemoveRequests(
      request_ids, base::BindOnce(&RequestCoordinatorTest::RemoveRequestsDone,
                                  base::Unretained(this)));

  // Let the async callbacks in the cancel run.
  PumpLoop();

  // Since offliner was started, it will have seen cancel call.
  EXPECT_TRUE(OfflinerWasCanceled());
}

TEST_F(RequestCoordinatorTest, RemoveInflightRequestAndAddAnother) {
  // Add a request to the queue, wait for callbacks to finish.
  AddRequest1();
  PumpLoop();
  // Test a different ordering of tasks, by delaying the offliner cancellation.
  offliner()->set_cancel_delay(base::TimeDelta::FromSeconds(1));
  // Ensure the start processing request stops before the completion callback.
  EnableOfflinerCallback(false);

  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));

  // Let all the async parts of the start processing pipeline run to completion.
  PumpLoop();
  // Since the offliner is disabled, this callback should not be called.
  EXPECT_FALSE(processing_callback_called());

  // Add a new request, and remove current request while it is processing.
  RequestCoordinator::SavePageLaterParams request2;
  request2.url = kUrl2;
  request2.client_id = kClientId2;
  request2.user_requested = true;
  coordinator()->SavePageLater(request2, base::DoNothing());

  std::vector<int64_t> request_ids{kRequestId1};
  coordinator()->RemoveRequests(
      request_ids, base::BindOnce(&RequestCoordinatorTest::RemoveRequestsDone,
                                  base::Unretained(this)));

  AdvanceClockBy(base::TimeDelta::FromSeconds(2));

  // Since offliner was started, it will have seen cancel call.
  EXPECT_TRUE(OfflinerWasCanceled());
  // The second request should be offlining now.
  EXPECT_TRUE(offliner()->has_pending_request());
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}

TEST_F(RequestCoordinatorTest, MarkRequestCompleted) {
  int64_t request_id = SavePageLaterWithAvailability(
      RequestCoordinator::RequestAvailability::DISABLED_FOR_OFFLINER);

  // Verify that the request is added to the disabled list.
  EXPECT_FALSE(disabled_requests().empty());

  PumpLoop();
  EXPECT_NE(request_id, 0l);

  // Verify request added in OFFLINING state.
  EXPECT_TRUE(observer().added_called());
  EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state());

  // Call the method under test, making sure we send SUCCESS to the observer.
  coordinator()->MarkRequestCompleted(request_id);
  PumpLoop();

  // Our observer should have seen SUCCESS instead of USER_CANCELED.
  EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::SUCCESS,
            observer().last_status());
  EXPECT_TRUE(observer().completed_called());
}

TEST_F(RequestCoordinatorTest, EnableForOffliner) {
  // Pretend we are on low-end device so immediate start won't happen.
  SetIsLowEndDeviceForTest(true);

  int64_t request_id = SavePageLaterWithAvailability(
      RequestCoordinator::RequestAvailability::DISABLED_FOR_OFFLINER);

  // Verify that the request is added to the disabled list.
  EXPECT_FALSE(disabled_requests().empty());

  PumpLoop();
  EXPECT_NE(request_id, 0l);

  // Verify request added and initial change to OFFLINING (in foreground).
  EXPECT_TRUE(observer().added_called());
  EXPECT_TRUE(observer().changed_called());
  EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state());
  observer().Clear();

  // Ensure that the new request does not finish so we can verify state change.
  EnableOfflinerCallback(false);

  coordinator()->EnableForOffliner(request_id, kClientId1);
  PumpLoop();

  // Verify request changed again.
  EXPECT_TRUE(observer().changed_called());
  EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
}

TEST_F(RequestCoordinatorTest,
       WatchdogTimeoutForScheduledProcessingNoLastSnapshot) {
  // Build a request to use with the pre-renderer, and put it on the queue.
  offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1,
                                         OfflineTimeNow(), kUserRequested);
  // Set request to allow one more completed attempt.
  int max_tries = coordinator()->policy()->GetMaxCompletedTries();
  request.set_completed_attempt_count(max_tries - 1);
  queue()->AddRequest(request,
                      base::BindOnce(&RequestCoordinatorTest::AddRequestDone,
                                     base::Unretained(this)));
  PumpLoop();

  // Ensure that the new request does not finish - we simulate it being
  // in progress by asking it to skip making the completion callback.
  EnableOfflinerCallback(false);

  // Sending the request to the offliner.
  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      waiting_callback()));
  PumpLoop();

  // Advance the mock clock far enough to cause a watchdog timeout
  AdvanceClockBy(base::TimeDelta::FromSeconds(
      coordinator()
          ->policy()
          ->GetSinglePageTimeLimitWhenBackgroundScheduledInSeconds() +
      1));
  PumpLoop();

  // Wait for timeout to expire.  Use a TaskRunner with a DelayedTaskRunner
  // which won't time out immediately, so the watchdog thread doesn't kill valid
  // tasks too soon.
  WaitForCallback();
  PumpLoop();

  EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
  EXPECT_TRUE(OfflinerWasCanceled());
}

TEST_F(RequestCoordinatorTest,
       WatchdogTimeoutForImmediateProcessingNoLastSnapshot) {
  // Ensure that the new request does not finish - we simulate it being
  // in progress by asking it to skip making the completion callback.
  EnableOfflinerCallback(false);

  EXPECT_NE(0, SavePageLater());
  PumpLoop();

  // Verify that immediate start from adding the request did happen.
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);

  // Advance the mock clock 1 second before the watchdog timeout.
  AdvanceClockBy(base::TimeDelta::FromSeconds(
      coordinator()
          ->policy()
          ->GetSinglePageTimeLimitForImmediateLoadInSeconds() -
      1));
  PumpLoop();

  // Verify still busy.
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
  EXPECT_FALSE(OfflinerWasCanceled());

  // Advance the mock clock past the watchdog timeout now.
  AdvanceClockBy(base::TimeDelta::FromSeconds(2));
  PumpLoop();

  // Verify the request timed out.
  EXPECT_TRUE(OfflinerWasCanceled());
}

TEST_F(RequestCoordinatorTest, TimeBudgetExceeded) {
  EnableOfflinerCallback(false);
  // Build two requests to use with the pre-renderer, and put it on the queue.
  AddRequest1();
  // The second request will have a larger completed attempt count.
  offline_pages::SavePageRequest request2(kRequestId1 + 1, kUrl1, kClientId1,
                                          OfflineTimeNow(), kUserRequested);
  request2.set_completed_attempt_count(kAttemptCount);
  queue()->AddRequest(request2,
                      base::BindOnce(&RequestCoordinatorTest::AddRequestDone,
                                     base::Unretained(this)));
  PumpLoop();

  // Sending the request to the offliner.
  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      waiting_callback()));
  PumpLoop();

  // Advance the mock clock far enough to exceed our time budget.
  // The first request will time out, and because we are over time budget,
  // the second request will not be started.
  AdvanceClockBy(base::TimeDelta::FromSeconds(kTestTimeBudgetSeconds));
  PumpLoop();

  // TryNextRequest should decide that there is no more work to be done,
  // and call back to the scheduler, even though there is another request in the
  // queue.  Both requests should be left in the queue.
  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));
  PumpLoop();

  // We should find two requests in the queue.
  // The first request should now have a completed count of 1.
  EXPECT_EQ(2UL, last_requests().size());
  EXPECT_EQ(1L, last_requests().at(0)->completed_attempt_count());
}

TEST_F(RequestCoordinatorTest, TryNextRequestWithNoNetwork) {
  SavePageRequest request1 = AddRequest1();
  AddRequest2();
  PumpLoop();

  // Set up for the call to StartScheduledProcessing.
  EnableOfflinerCallback(false);

  // Sending the request to the offliner.
  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      waiting_callback()));
  PumpLoop();
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);

  // Now lose the network connection.
  SetNetworkConnected(false);

  // Complete first request and then TryNextRequest should decide not
  // to pick another request (because of no network connection).
  SendOfflinerDoneCallback(request1, Offliner::RequestStatus::SAVED);
  PumpLoop();

  // Not starting nor busy with next request.
  EXPECT_FALSE(state() == RequestCoordinatorState::PICKING);
  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);

  // Get queued requests.
  queue()->GetRequests(base::BindOnce(&RequestCoordinatorTest::GetRequestsDone,
                                      base::Unretained(this)));
  PumpLoop();

  // We should find one request in the queue.
  EXPECT_EQ(1UL, last_requests().size());
}

TEST_F(RequestCoordinatorTest, GetAllRequests) {
  // Add two requests to the queue.
  AddRequest1();
  AddRequest2();
  PumpLoop();

  // Start the async status fetching.
  coordinator()->GetAllRequests(base::BindOnce(
      &RequestCoordinatorTest::GetQueuedRequestsDone, base::Unretained(this)));
  PumpLoop();

  // Wait for async get to finish.
  WaitForCallback();
  PumpLoop();

  // Check that the statuses found in the callback match what we expect.
  EXPECT_EQ(2UL, last_requests().size());
  EXPECT_EQ(kRequestId1, last_requests().at(0)->request_id());
  EXPECT_EQ(kRequestId2, last_requests().at(1)->request_id());
}

TEST_F(RequestCoordinatorTest, PauseAndResumeObserver) {
  // Set low-end device status to actual status.
  SetIsLowEndDeviceForTest(base::SysInfo::IsLowEndDevice());

  // Add a request to the queue.
  AddRequest1();
  PumpLoop();

  // Pause the request.
  std::vector<int64_t> request_ids;
  request_ids.push_back(kRequestId1);
  coordinator()->PauseRequests(request_ids);
  PumpLoop();

  EXPECT_TRUE(observer().changed_called());
  EXPECT_EQ(SavePageRequest::RequestState::PAUSED, observer().state());

  // Clear out the observer before the next call.
  observer().Clear();

  // Resume the request.
  coordinator()->ResumeRequests(request_ids);
  PumpLoop();

  EXPECT_TRUE(observer().changed_called());

  // Now whether request is offlining or just available depends on whether test
  // is run on svelte device or not.
  if (base::SysInfo::IsLowEndDevice()) {
    EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
  } else {
    EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state());
  }
}

TEST_F(RequestCoordinatorTest, RemoveRequest) {
  // Add a request to the queue.
  AddRequest1();
  PumpLoop();

  // Remove the request.
  std::vector<int64_t> request_ids;
  request_ids.push_back(kRequestId1);
  coordinator()->RemoveRequests(
      request_ids, base::BindOnce(&RequestCoordinatorTest::RemoveRequestsDone,
                                  base::Unretained(this)));

  PumpLoop();
  WaitForCallback();
  PumpLoop();

  EXPECT_TRUE(observer().completed_called());
  EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::USER_CANCELED,
            observer().last_status());
  EXPECT_EQ(1UL, last_remove_results().size());
  EXPECT_EQ(kRequestId1, std::get<0>(last_remove_results().at(0)));
}

TEST_F(RequestCoordinatorTest,
       SavePageStartsProcessingWhenConnectedAndNotLowEndDevice) {
  // Turn off the callback so that the request stops before processing in
  // PumpLoop.
  EnableOfflinerCallback(false);
  EXPECT_NE(0, SavePageLater());
  PumpLoop();

  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}

TEST_F(RequestCoordinatorTest,
       SavePageStartsProcessingWhenConnectedOnLowEndDeviceIfFlagEnabled) {
  // Mark device as low-end device.
  SetIsLowEndDeviceForTest(true);
  EXPECT_FALSE(offline_pages::IsOfflinePagesSvelteConcurrentLoadingEnabled());

  // Make a request.
  EXPECT_NE(0, SavePageLater());
  PumpLoop();

  // Verify not immediately busy (since low-end device).
  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);

  // Set feature flag to allow concurrent loads.
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeature(
      kOfflinePagesSvelteConcurrentLoadingFeature);
  EXPECT_TRUE(offline_pages::IsOfflinePagesSvelteConcurrentLoadingEnabled());

  // Turn off the callback so that the request stops before processing in
  // PumpLoop.
  EnableOfflinerCallback(false);

  // Make another request.
  RequestCoordinator::SavePageLaterParams params;
  params.url = kUrl2;
  params.client_id = kClientId2;
  params.user_requested = kUserRequested;
  EXPECT_NE(0, coordinator()->SavePageLater(
                   params, base::BindOnce(
                               &RequestCoordinatorTest::SavePageRequestCallback,
                               base::Unretained(this))));
  PumpLoop();

  // Verify immediate processing did start this time.
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}

TEST_F(RequestCoordinatorTest, SavePageDoesntStartProcessingWhenDisconnected) {
  SetNetworkConnected(false);
  EnableOfflinerCallback(false);
  EXPECT_NE(0, SavePageLater());
  PumpLoop();
  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);

  // Now connect network and verify processing starts.
  SetNetworkConnected(true);
  CallConnectionTypeObserver();
  PumpLoop();
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}

TEST_F(RequestCoordinatorTest,
       SavePageDoesStartProcessingWhenPoorlyConnected) {
  // Set specific network type for 2G with poor effective connection.
  DeviceConditions device_conditions(!kPowerRequired, kBatteryPercentageHigh,
                                     net::NetworkChangeNotifier::CONNECTION_2G);
  SetDeviceConditionsForTest(device_conditions);
  SetEffectiveConnectionTypeForTest(
      net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_SLOW_2G);

  // Turn off the callback so that the request stops before processing in
  // PumpLoop.
  EnableOfflinerCallback(false);

  EXPECT_NE(0, SavePageLater());
  PumpLoop();
  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}

TEST_F(RequestCoordinatorTest,
       ResumeStartsProcessingWhenConnectedAndNotLowEndDevice) {
  // Start unconnected.
  SetNetworkConnected(false);

  // Turn off the callback so that the request stops before processing in
  // PumpLoop.
  EnableOfflinerCallback(false);

  // Add a request to the queue.
  AddRequest1();
  PumpLoop();
  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);

  // Pause the request.
  std::vector<int64_t> request_ids;
  request_ids.push_back(kRequestId1);
  coordinator()->PauseRequests(request_ids);
  PumpLoop();

  // Resume the request while disconnected.
  coordinator()->ResumeRequests(request_ids);
  PumpLoop();
  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
  EXPECT_EQ(1UL, prioritized_requests().size());

  // Pause the request again.
  coordinator()->PauseRequests(request_ids);
  PumpLoop();
  EXPECT_EQ(0UL, prioritized_requests().size());

  // Now simulate reasonable connection.
  SetNetworkConnected(true);

  // Resume the request while connected.
  coordinator()->ResumeRequests(request_ids);
  EXPECT_FALSE(state() == RequestCoordinatorState::OFFLINING);
  PumpLoop();
  EXPECT_EQ(1UL, prioritized_requests().size());

  EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);
}

TEST_F(RequestCoordinatorTest, SnapshotOnLastTryForScheduledProcessing) {
  // Build a request to use with the pre-renderer, and put it on the queue.
  offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1,
                                         OfflineTimeNow(), kUserRequested);
  // Set request to allow one more completed attempt. So that the next try would
  // be the last retry.
  int max_tries = coordinator()->policy()->GetMaxCompletedTries();
  request.set_completed_attempt_count(max_tries - 1);
  queue()->AddRequest(request,
                      base::BindOnce(&RequestCoordinatorTest::AddRequestDone,
                                     base::Unretained(this)));
  PumpLoop();

  // Ensure that the new request does not finish - we simulate it being
  // in progress by asking it to skip making the completion callback.
  // Also make snapshot on last retry happen in this case.
  EnableOfflinerCallback(false);
  EnableSnapshotOnLastRetry();

  // Sending the request to the offliner.
  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      waiting_callback()));
  PumpLoop();

  // Advance the mock clock far enough to cause a watchdog timeout
  AdvanceClockBy(base::TimeDelta::FromSeconds(
      coordinator()
          ->policy()
          ->GetSinglePageTimeLimitWhenBackgroundScheduledInSeconds() +
      1));
  PumpLoop();

  // Wait for timeout to expire.  Use a TaskRunner with a DelayedTaskRunner
  // which won't time out immediately, so the watchdog thread doesn't kill valid
  // tasks too soon.
  WaitForCallback();
  PumpLoop();

  // Check the offliner didn't get a cancel and the result was success.
  EXPECT_FALSE(OfflinerWasCanceled());
  EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::SUCCESS,
            observer().last_status());
  EXPECT_TRUE(observer().completed_called());
}

TEST_F(RequestCoordinatorTest, SnapshotOnLastTryForImmediateProcessing) {
  // Ensure that the new request does not finish - we simulate it being
  // in progress by asking it to skip making the completion callback.
  EnableOfflinerCallback(false);

  EXPECT_NE(0, SavePageLater());

  // Repeat the timeout for MaxCompleteTries - 1 times in order to increase the
  // completed tries on this request.
  int max_tries = coordinator()->policy()->GetMaxCompletedTries();
  for (int i = 0; i < max_tries - 1; i++) {
    PumpLoop();
    // Reset states.
    ResetOfflinerWasCanceled();
    observer().Clear();

    // Verify that the request is being processed.
    EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING);

    // Advance the mock clock 1 second more than the watchdog timeout.
    AdvanceClockBy(base::TimeDelta::FromSeconds(
        coordinator()
            ->policy()
            ->GetSinglePageTimeLimitForImmediateLoadInSeconds() +
        1));
    PumpLoop();

    // Verify the request timed out.
    EXPECT_TRUE(OfflinerWasCanceled());
    EXPECT_TRUE(observer().changed_called());
  }

  // Reset states.
  ResetOfflinerWasCanceled();
  observer().Clear();
  // Make snapshot on last retry happen.
  EnableSnapshotOnLastRetry();

  // Advance the mock clock 1 second more than the watchdog timeout.
  AdvanceClockBy(base::TimeDelta::FromSeconds(
      coordinator()
          ->policy()
          ->GetSinglePageTimeLimitForImmediateLoadInSeconds() +
      1));
  PumpLoop();

  // The last time would trigger the snapshot on last retry and succeed.
  EXPECT_FALSE(OfflinerWasCanceled());
  EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::SUCCESS,
            observer().last_status());
  EXPECT_TRUE(observer().completed_called());
}

TEST_F(RequestCoordinatorTest, RequestPendingNetworkOnResumeWithNoNetwork) {
  // Add a request to the queue.
  AddRequest1();
  PumpLoop();

  // Pause the request.
  std::vector<int64_t> request_ids;
  request_ids.push_back(kRequestId1);
  coordinator()->PauseRequests(request_ids);
  PumpLoop();

  SetNetworkConnected(false);

  // Resume the request.
  coordinator()->ResumeRequests(request_ids);
  PumpLoop();

  // Verify the request is waiting for network.
  EXPECT_TRUE(observer().changed_called());
  EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
  EXPECT_EQ(PendingState::PENDING_NETWORK, observer().pending_state());
}

TEST_F(RequestCoordinatorTest,
       RequestPendingDownloadOnResumeWithOffliningDownload) {
  // Add a request to the queue.
  AddRequest1();
  PumpLoop();

  // Pause the request.
  std::vector<int64_t> request_ids;
  request_ids.push_back(kRequestId1);
  coordinator()->PauseRequests(request_ids);
  PumpLoop();

  // Add a second request to the queue for offlining.
  AddRequest2();
  EnableOfflinerCallback(false);
  EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(),
                                                      processing_callback()));
  PumpLoop();

  // Resume the first request.
  coordinator()->ResumeRequests(request_ids);
  PumpLoop();

  // Verify the request is waiting for another download to complete.
  EXPECT_TRUE(observer().changed_called());
  EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
  EXPECT_EQ(PendingState::PENDING_ANOTHER_DOWNLOAD, observer().pending_state());
}

TEST_F(RequestCoordinatorTest, RequestPendingNetworkOnAddWithNoNetwork) {
  SetNetworkConnected(false);

  EXPECT_NE(0, SavePageLater());
  PumpLoop();

  // Verify the request is waiting for network.
  EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
  EXPECT_EQ(PendingState::PENDING_NETWORK, observer().pending_state());
}

TEST_F(RequestCoordinatorTest,
       RequestPendingDownloadOnAddedWithOffliningDownload) {
  // Make an offlining request.
  EnableOfflinerCallback(false);
  EXPECT_NE(0, SavePageLater());
  PumpLoop();

  // Make a second request.
  RequestCoordinator::SavePageLaterParams params;
  params.url = kUrl2;
  params.client_id = kClientId2;
  params.user_requested = kUserRequested;
  EXPECT_NE(0, coordinator()->SavePageLater(
                   params, base::BindOnce(
                               &RequestCoordinatorTest::SavePageRequestCallback,
                               base::Unretained(this))));
  PumpLoop();

  // Verify second request is waiting for another download to complete.
  EXPECT_TRUE(observer().added_called());
  EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state());
  EXPECT_EQ(PendingState::PENDING_ANOTHER_DOWNLOAD, observer().pending_state());
}

}  // namespace offline_pages
