// Copyright 2014 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/suggestions/suggestions_service_impl.h"

#include <stdint.h>

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

#include "base/bind.h"
#include "base/macros.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "components/suggestions/blacklist_store.h"
#include "components/suggestions/features.h"
#include "components/suggestions/proto/suggestions.pb.h"
#include "components/suggestions/suggestions_store.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/driver/test_sync_service.h"
#include "net/base/url_util.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_status.h"
#include "net/url_request/url_request_test_util.h"
#include "services/identity/public/cpp/identity_manager.h"
#include "services/identity/public/cpp/identity_test_environment.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "services/network/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/image/image.h"

using syncer::SyncServiceObserver;
using testing::_;
using testing::AnyNumber;
using testing::DoAll;
using testing::Mock;
using testing::Return;
using testing::SetArgPointee;
using testing::StrictMock;

namespace {

const char kEmail[] = "foo_email";
const char kSuggestionsUrlPath[] = "/chromesuggestions";
const char kBlacklistUrlPath[] = "/chromesuggestions/blacklist";
const char kBlacklistClearUrlPath[] = "/chromesuggestions/blacklist/clear";
const char kTestTitle[] = "a title";
const char kTestUrl[] = "http://go.com";
const char kTestFaviconUrl[] =
    "https://s2.googleusercontent.com/s2/favicons?domain_url="
    "http://go.com&alt=s&sz=32";
const char kBlacklistedUrl[] = "http://blacklist.com";
const int64_t kTestSetExpiry = 12121212;  // This timestamp lies in the past.

// GMock matcher for protobuf equality.
MATCHER_P(EqualsProto, message, "") {
  // This implementation assumes protobuf serialization is deterministic, which
  // is true in practice but technically not something that code is supposed
  // to rely on.  However, it vastly simplifies the implementation.
  std::string expected_serialized, actual_serialized;
  message.SerializeToString(&expected_serialized);
  arg.SerializeToString(&actual_serialized);
  return expected_serialized == actual_serialized;
}

}  // namespace

namespace suggestions {

SuggestionsProfile CreateSuggestionsProfile() {
  SuggestionsProfile profile;
  profile.set_timestamp(123);
  ChromeSuggestion* suggestion = profile.add_suggestions();
  suggestion->set_title(kTestTitle);
  suggestion->set_url(kTestUrl);
  return profile;
}

class TestSuggestionsStore : public suggestions::SuggestionsStore {
 public:
  TestSuggestionsStore() { cached_suggestions = CreateSuggestionsProfile(); }
  bool LoadSuggestions(SuggestionsProfile* suggestions) override {
    suggestions->CopyFrom(cached_suggestions);
    return cached_suggestions.suggestions_size();
  }
  bool StoreSuggestions(const SuggestionsProfile& suggestions) override {
    cached_suggestions.CopyFrom(suggestions);
    return true;
  }
  void ClearSuggestions() override {
    cached_suggestions = SuggestionsProfile();
  }

  SuggestionsProfile cached_suggestions;
};

class MockBlacklistStore : public suggestions::BlacklistStore {
 public:
  MOCK_METHOD1(BlacklistUrl, bool(const GURL&));
  MOCK_METHOD0(ClearBlacklist, void());
  MOCK_METHOD1(GetTimeUntilReadyForUpload, bool(base::TimeDelta*));
  MOCK_METHOD2(GetTimeUntilURLReadyForUpload,
               bool(const GURL&, base::TimeDelta*));
  MOCK_METHOD1(GetCandidateForUpload, bool(GURL*));
  MOCK_METHOD1(RemoveUrl, bool(const GURL&));
  MOCK_METHOD1(FilterSuggestions, void(SuggestionsProfile*));
};

class SuggestionsServiceTest : public testing::Test {
 protected:
  SuggestionsServiceTest() {
    identity_test_env_.MakePrimaryAccountAvailable(kEmail);
    identity_test_env_.SetAutomaticIssueOfAccessTokens(true);
  }

  ~SuggestionsServiceTest() override {}

  void SetUp() override {
    sync_service()->SetPreferredDataTypes({syncer::HISTORY_DELETE_DIRECTIVES});
    sync_service()->SetActiveDataTypes({syncer::HISTORY_DELETE_DIRECTIVES});

    // These objects are owned by the SuggestionsService, but we keep the
    // pointers around for testing.
    test_suggestions_store_ = new TestSuggestionsStore();
    mock_blacklist_store_ = new StrictMock<MockBlacklistStore>();
    suggestions_service_ = std::make_unique<SuggestionsServiceImpl>(
        identity_test_env_.identity_manager(), sync_service(),
        base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
            url_loader_factory()),
        base::WrapUnique(test_suggestions_store_),
        base::WrapUnique(mock_blacklist_store_),
        scoped_task_environment_.GetMockTickClock());
  }

  GURL GetCurrentlyQueriedUrl() {
    if (url_loader_factory()->NumPending() == 0)
      return GURL();

    return url_loader_factory()->pending_requests()->front().request.url;
  }

  bool RespondToSuggestionsFetch(const std::string& response_body,
                                 net::HttpStatusCode response_code,
                                 int net_error = net::OK) {
    return RespondToFetch(SuggestionsServiceImpl::BuildSuggestionsURL(),
                          response_body, response_code, net_error);
  }

  bool RespondToBlacklistFetch(const std::string& response_body,
                               net::HttpStatusCode response_code,
                               int net_error = net::OK) {
    return RespondToFetch(SuggestionsServiceImpl::BuildSuggestionsBlacklistURL(
                              GURL(kBlacklistedUrl)),
                          response_body, response_code, net_error);
  }

  bool RespondToFetchWithProfile(const SuggestionsProfile& suggestions) {
    return RespondToFetch(SuggestionsServiceImpl::BuildSuggestionsURL(),
                          suggestions.SerializeAsString(), net::HTTP_OK);
  }

  bool RespondToFetch(const GURL& url,
                      const std::string& response_body,
                      net::HttpStatusCode response_code,
                      int net_error = net::OK) {
    bool rv = url_loader_factory()->SimulateResponseForPendingRequest(
        url, network::URLLoaderCompletionStatus(net_error),
        network::CreateResourceResponseHead(response_code), response_body);
    scoped_task_environment_.RunUntilIdle();
    return rv;
  }

  syncer::TestSyncService* sync_service() { return &test_sync_service_; }

  MockBlacklistStore* blacklist_store() { return mock_blacklist_store_; }

  TestSuggestionsStore* suggestions_store() { return test_suggestions_store_; }

  SuggestionsServiceImpl* suggestions_service() {
    return suggestions_service_.get();
  }

  identity::IdentityTestEnvironment* identity_test_env() {
    return &identity_test_env_;
  }

  network::TestURLLoaderFactory* url_loader_factory() {
    return &url_loader_factory_;
  }

  base::test::ScopedTaskEnvironment scoped_task_environment_{
      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};

 private:
  identity::IdentityTestEnvironment identity_test_env_;
  syncer::TestSyncService test_sync_service_;
  network::TestURLLoaderFactory url_loader_factory_;

  // Owned by the SuggestionsService.
  MockBlacklistStore* mock_blacklist_store_ = nullptr;
  TestSuggestionsStore* test_suggestions_store_ = nullptr;

  std::unique_ptr<SuggestionsServiceImpl> suggestions_service_;

  DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest);
};

TEST_F(SuggestionsServiceTest, FetchSuggestionsData) {
  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_));
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(Return(false));

  // Send the request. The data should be returned to the callback.
  suggestions_service()->FetchSuggestionsData();

  EXPECT_CALL(callback, Run(_));

  // Wait for the eventual network request.
  scoped_task_environment_.RunUntilIdle();
  ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid());
  EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kSuggestionsUrlPath);
  ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile()));

  SuggestionsProfile suggestions;
  suggestions_store()->LoadSuggestions(&suggestions);
  ASSERT_EQ(1, suggestions.suggestions_size());
  EXPECT_EQ(kTestTitle, suggestions.suggestions(0).title());
  EXPECT_EQ(kTestUrl, suggestions.suggestions(0).url());
  EXPECT_EQ(kTestFaviconUrl, suggestions.suggestions(0).favicon_url());
}

TEST_F(SuggestionsServiceTest, IgnoresNoopSyncChange) {
  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  EXPECT_CALL(callback, Run(_)).Times(0);
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  // An no-op change should not result in a suggestions refresh.
  static_cast<SyncServiceObserver*>(suggestions_service())
      ->OnStateChanged(sync_service());

  // Wait for eventual (but unexpected) network requests.
  scoped_task_environment_.RunUntilIdle();
  EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}

TEST_F(SuggestionsServiceTest, PersistentAuthErrorState) {
  // Put some suggestions in.
  suggestions_store()->StoreSuggestions(CreateSuggestionsProfile());

  GoogleServiceAuthError error =
      GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR);
  sync_service()->SetAuthError(std::move(error));
  // An no-op change should not result in a suggestions refresh.
  static_cast<SyncServiceObserver*>(suggestions_service())
      ->OnStateChanged(sync_service());

  // Wait for eventual (but unexpected) network requests.
  scoped_task_environment_.RunUntilIdle();
  EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());

  SuggestionsProfile empty_suggestions;
  EXPECT_FALSE(suggestions_store()->LoadSuggestions(&empty_suggestions));
}

TEST_F(SuggestionsServiceTest, IgnoresUninterestingSyncChange) {
  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  EXPECT_CALL(callback, Run(_)).Times(0);
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  // An uninteresting change should not result in a network request (the
  // SyncState is INITIALIZED_ENABLED_HISTORY before and after).
  sync_service()->SetActiveDataTypes(
      {syncer::HISTORY_DELETE_DIRECTIVES, syncer::BOOKMARKS});
  static_cast<SyncServiceObserver*>(suggestions_service())
      ->OnStateChanged(sync_service());

  // Wait for eventual (but unexpected) network requests.
  scoped_task_environment_.RunUntilIdle();
  EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}

// During startup, the state changes from NOT_INITIALIZED_ENABLED to
// INITIALIZED_ENABLED_HISTORY (for a signed-in user with history sync enabled).
// This should *not* result in an automatic fetch.
TEST_F(SuggestionsServiceTest, DoesNotFetchOnStartup) {
  // The sync service starts out inactive.
  sync_service()->SetTransportState(
      syncer::SyncService::TransportState::INITIALIZING);
  static_cast<SyncServiceObserver*>(suggestions_service())
      ->OnStateChanged(sync_service());

  scoped_task_environment_.RunUntilIdle();
  ASSERT_FALSE(suggestions_service()->HasPendingRequestForTesting());

  // Sync getting enabled should not result in a fetch.
  sync_service()->SetTransportState(
      syncer::SyncService::TransportState::ACTIVE);
  static_cast<SyncServiceObserver*>(suggestions_service())
      ->OnStateChanged(sync_service());

  // Wait for eventual (but unexpected) network requests.
  scoped_task_environment_.RunUntilIdle();
  EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}

TEST_F(SuggestionsServiceTest, BuildUrlWithDefaultMinZeroParamForFewFeature) {
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitAndEnableFeature(kUseSuggestionsEvenIfFewFeature);

  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_));
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(Return(false));

  // Send the request. The data should be returned to the callback.
  suggestions_service()->FetchSuggestionsData();

  // Wait for the eventual network request.
  scoped_task_environment_.RunUntilIdle();
  ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid());
  EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kSuggestionsUrlPath);
  std::string min_suggestions;
  EXPECT_TRUE(net::GetValueForKeyInQuery(GetCurrentlyQueriedUrl(), "num",
                                         &min_suggestions));
  EXPECT_EQ(min_suggestions, "0");
  ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile()));
}

TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncNotInitializedEnabled) {
  sync_service()->SetTransportState(
      syncer::SyncService::TransportState::INITIALIZING);
  static_cast<SyncServiceObserver*>(suggestions_service())
      ->OnStateChanged(sync_service());

  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  EXPECT_CALL(callback, Run(_)).Times(0);
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  // Try to fetch suggestions. Since sync is not active, no network request
  // should be sent.
  suggestions_service()->FetchSuggestionsData();

  // Wait for eventual (but unexpected) network requests.
  scoped_task_environment_.RunUntilIdle();
  EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());

  // |suggestions_store()| should still contain the default values.
  SuggestionsProfile suggestions;
  suggestions_store()->LoadSuggestions(&suggestions);
  EXPECT_THAT(suggestions, EqualsProto(CreateSuggestionsProfile()));
}

TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncDisabled) {
  sync_service()->SetDisableReasons(
      syncer::SyncService::DISABLE_REASON_USER_CHOICE);
  sync_service()->SetTransportState(
      syncer::SyncService::TransportState::DISABLED);

  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  // Tell SuggestionsService that the sync state changed. The cache should be
  // cleared and empty data returned to the callback.
  EXPECT_CALL(callback, Run(EqualsProto(SuggestionsProfile())));
  static_cast<SyncServiceObserver*>(suggestions_service())
      ->OnStateChanged(sync_service());

  // Try to fetch suggestions. Since sync is not active, no network request
  // should be sent.
  suggestions_service()->FetchSuggestionsData();

  // Wait for eventual (but unexpected) network requests.
  scoped_task_environment_.RunUntilIdle();
  EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}

TEST_F(SuggestionsServiceTest, FetchSuggestionsDataNoAccessToken) {
  identity_test_env()->SetAutomaticIssueOfAccessTokens(false);

  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  EXPECT_CALL(callback, Run(_)).Times(0);
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(Return(false));

  suggestions_service()->FetchSuggestionsData();

  identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
      GoogleServiceAuthError(
          GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));

  // Wait for eventual (but unexpected) network requests.
  scoped_task_environment_.RunUntilIdle();
  EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting());
}

TEST_F(SuggestionsServiceTest, FetchingSuggestionsIgnoresRequestFailure) {
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(Return(false));

  suggestions_service()->FetchSuggestionsData();

  // Wait for the eventual network request.
  scoped_task_environment_.RunUntilIdle();
  ASSERT_TRUE(RespondToSuggestionsFetch("irrelevant", net::HTTP_OK,
                                        net::ERR_INVALID_RESPONSE));
}

TEST_F(SuggestionsServiceTest, FetchingSuggestionsClearsStoreIfResponseNotOK) {
  suggestions_store()->StoreSuggestions(CreateSuggestionsProfile());

  // Expect that an upload to the blacklist is scheduled.
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(Return(false));

  // Send the request. Empty data will be returned to the callback.
  suggestions_service()->FetchSuggestionsData();

  // Wait for the eventual network request.
  scoped_task_environment_.RunUntilIdle();
  ASSERT_TRUE(RespondToSuggestionsFetch("irrelevant", net::HTTP_BAD_REQUEST));

  SuggestionsProfile empty_suggestions;
  EXPECT_FALSE(suggestions_store()->LoadSuggestions(&empty_suggestions));
}

TEST_F(SuggestionsServiceTest, BlacklistURL) {
  const base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0);

  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  EXPECT_CALL(*blacklist_store(), BlacklistUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(true));
  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)).Times(2);
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true)))
      .WillOnce(Return(false));
  EXPECT_CALL(*blacklist_store(), GetCandidateForUpload(_))
      .WillOnce(DoAll(SetArgPointee<0>(GURL(kBlacklistedUrl)), Return(true)));
  EXPECT_CALL(*blacklist_store(), RemoveUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(true));

  EXPECT_CALL(callback, Run(_)).Times(2);

  EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl)));

  // Wait on the upload task, the blacklist request and the next blacklist
  // scheduling task.
  scoped_task_environment_.FastForwardUntilNoTasksRemain();

  EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlacklistUrlPath);
  // The blacklist fetch needs to contain a valid profile or the favicon will
  // not be set.
  ASSERT_TRUE(RespondToBlacklistFetch(
      CreateSuggestionsProfile().SerializeAsString(), net::HTTP_OK));
  scoped_task_environment_.RunUntilIdle();

  SuggestionsProfile suggestions;
  suggestions_store()->LoadSuggestions(&suggestions);
  ASSERT_EQ(1, suggestions.suggestions_size());
  EXPECT_EQ(kTestTitle, suggestions.suggestions(0).title());
  EXPECT_EQ(kTestUrl, suggestions.suggestions(0).url());
  EXPECT_EQ(kTestFaviconUrl, suggestions.suggestions(0).favicon_url());
}

TEST_F(SuggestionsServiceTest, BlacklistURLFails) {
  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  EXPECT_CALL(callback, Run(_)).Times(0);
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  EXPECT_CALL(*blacklist_store(), BlacklistUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(false));

  EXPECT_FALSE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl)));
}

TEST_F(SuggestionsServiceTest, RetryBlacklistURLRequestAfterFailure) {
  const base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0);

  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  // Set expectations for first, failing request.
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .Times(AnyNumber())
      .WillRepeatedly(DoAll(SetArgPointee<0>(no_delay), Return(true)));
  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_));
  EXPECT_CALL(*blacklist_store(), BlacklistUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(true));
  EXPECT_CALL(*blacklist_store(), GetCandidateForUpload(_))
      .WillOnce(DoAll(SetArgPointee<0>(GURL(kBlacklistedUrl)), Return(true)));

  EXPECT_CALL(callback, Run(_)).Times(2);

  // Blacklist call, first request attempt.
  EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl)));

  // Wait for the first scheduling receiving a failing response.
  scoped_task_environment_.FastForwardUntilNoTasksRemain();
  ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid());
  EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlacklistUrlPath);
  ASSERT_TRUE(RespondToBlacklistFetch("irrelevant", net::HTTP_OK,
                                      net::ERR_INVALID_RESPONSE));

  // Assert that the failure was processed as expected.
  Mock::VerifyAndClearExpectations(blacklist_store());

  // Now expect the retried request to succeed.
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .Times(AnyNumber())
      .WillRepeatedly(DoAll(SetArgPointee<0>(no_delay), Return(true)));
  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_));
  EXPECT_CALL(*blacklist_store(), GetCandidateForUpload(_))
      .WillOnce(DoAll(SetArgPointee<0>(GURL(kBlacklistedUrl)), Return(true)));
  EXPECT_CALL(*blacklist_store(), RemoveUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(true));

  // Wait for the second scheduling followed by a successful response.
  scoped_task_environment_.FastForwardUntilNoTasksRemain();
  ASSERT_TRUE(suggestions_service()->HasPendingRequestForTesting());
  ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid());
  EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlacklistUrlPath);
  ASSERT_TRUE(RespondToBlacklistFetch(
      CreateSuggestionsProfile().SerializeAsString(), net::HTTP_OK));

  SuggestionsProfile suggestions;
  suggestions_store()->LoadSuggestions(&suggestions);
  ASSERT_EQ(1, suggestions.suggestions_size());
  EXPECT_EQ(kTestTitle, suggestions.suggestions(0).title());
  EXPECT_EQ(kTestUrl, suggestions.suggestions(0).url());
  EXPECT_EQ(kTestFaviconUrl, suggestions.suggestions(0).favicon_url());
}

TEST_F(SuggestionsServiceTest, UndoBlacklistURL) {
  // Ensure scheduling the request doesn't happen before undo.
  const base::TimeDelta delay = base::TimeDelta::FromHours(1);

  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  // Blacklist expectations.
  EXPECT_CALL(*blacklist_store(), BlacklistUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(true));
  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)).Times(AnyNumber());
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
  // Undo expectations.
  EXPECT_CALL(*blacklist_store(),
              GetTimeUntilURLReadyForUpload(GURL(kBlacklistedUrl), _))
      .WillOnce(DoAll(SetArgPointee<1>(delay), Return(true)));
  EXPECT_CALL(*blacklist_store(), RemoveUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(true));

  EXPECT_CALL(callback, Run(_)).Times(2);
  EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl)));
  EXPECT_TRUE(suggestions_service()->UndoBlacklistURL(GURL(kBlacklistedUrl)));
}

TEST_F(SuggestionsServiceTest, ClearBlacklist) {
  const base::TimeDelta delay = base::TimeDelta::FromHours(1);

  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  // Blacklist expectations.
  EXPECT_CALL(*blacklist_store(), BlacklistUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(true));
  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)).Times(AnyNumber());
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
  EXPECT_CALL(*blacklist_store(), ClearBlacklist());

  EXPECT_CALL(callback, Run(_)).Times(2);
  EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl)));
  suggestions_service()->ClearBlacklist();

  // Wait for the eventual network request.
  scoped_task_environment_.RunUntilIdle();
  ASSERT_TRUE(suggestions_service()->HasPendingRequestForTesting());
  EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlacklistClearUrlPath);
}

TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfNotInBlacklist) {
  // Ensure scheduling the request doesn't happen before undo.
  const base::TimeDelta delay = base::TimeDelta::FromHours(1);

  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  // Blacklist expectations.
  EXPECT_CALL(*blacklist_store(), BlacklistUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(true));
  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_));
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));
  // Undo expectations.
  // URL is not in local blacklist.
  EXPECT_CALL(*blacklist_store(),
              GetTimeUntilURLReadyForUpload(GURL(kBlacklistedUrl), _))
      .WillOnce(Return(false));

  EXPECT_CALL(callback, Run(_));

  EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl)));
  EXPECT_FALSE(suggestions_service()->UndoBlacklistURL(GURL(kBlacklistedUrl)));
}

TEST_F(SuggestionsServiceTest, UndoBlacklistURLFailsIfAlreadyCandidate) {
  // Ensure scheduling the request doesn't happen before undo.
  const base::TimeDelta delay = base::TimeDelta::FromHours(1);

  base::MockCallback<SuggestionsService::ResponseCallback> callback;
  auto subscription = suggestions_service()->AddCallback(callback.Get());

  // Blacklist expectations.
  EXPECT_CALL(*blacklist_store(), BlacklistUrl(GURL(kBlacklistedUrl)))
      .WillOnce(Return(true));
  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_));
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true)));

  // URL is not yet candidate for upload.
  const base::TimeDelta negative_delay = base::TimeDelta::FromHours(-1);
  EXPECT_CALL(*blacklist_store(),
              GetTimeUntilURLReadyForUpload(GURL(kBlacklistedUrl), _))
      .WillOnce(DoAll(SetArgPointee<1>(negative_delay), Return(true)));

  EXPECT_CALL(callback, Run(_));

  EXPECT_TRUE(suggestions_service()->BlacklistURL(GURL(kBlacklistedUrl)));
  EXPECT_FALSE(suggestions_service()->UndoBlacklistURL(GURL(kBlacklistedUrl)));
}

TEST_F(SuggestionsServiceTest, TemporarilyIncreasesBlacklistDelayOnFailure) {
  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_)).Times(AnyNumber());
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .Times(AnyNumber())
      .WillRepeatedly(Return(false));
  const base::TimeDelta initial_delay =
      suggestions_service()->BlacklistDelayForTesting();

  // Delay unchanged on success.
  suggestions_service()->FetchSuggestionsData();
  scoped_task_environment_.RunUntilIdle();
  ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile()));
  EXPECT_EQ(initial_delay, suggestions_service()->BlacklistDelayForTesting());

  // Delay increases on failure.
  suggestions_service()->FetchSuggestionsData();
  scoped_task_environment_.RunUntilIdle();
  ASSERT_TRUE(RespondToSuggestionsFetch("irrelevant", net::HTTP_BAD_REQUEST));
  base::TimeDelta delay_after_fail =
      suggestions_service()->BlacklistDelayForTesting();
  EXPECT_GT(delay_after_fail, initial_delay);

  // Success resets future delays, but the current horizon remains. Since no
  // time has passed, the actual current delay stays the same.
  suggestions_service()->FetchSuggestionsData();
  scoped_task_environment_.RunUntilIdle();
  ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile()));
  EXPECT_EQ(delay_after_fail,
            suggestions_service()->BlacklistDelayForTesting());

  // After the current horizon has passed, we're back at the initial delay.
  scoped_task_environment_.FastForwardBy(delay_after_fail);
  suggestions_service()->FetchSuggestionsData();
  scoped_task_environment_.RunUntilIdle();
  ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile()));
  EXPECT_EQ(initial_delay, suggestions_service()->BlacklistDelayForTesting());
}

TEST_F(SuggestionsServiceTest, DoesNotOverrideDefaultExpiryTime) {
  EXPECT_CALL(*blacklist_store(), FilterSuggestions(_));
  EXPECT_CALL(*blacklist_store(), GetTimeUntilReadyForUpload(_))
      .WillOnce(Return(false));

  suggestions_service()->FetchSuggestionsData();

  scoped_task_environment_.RunUntilIdle();
  // Creates one suggestion without timestamp and adds a second with timestamp.
  SuggestionsProfile profile = CreateSuggestionsProfile();
  ChromeSuggestion* suggestion = profile.add_suggestions();
  suggestion->set_title(kTestTitle);
  suggestion->set_url(kTestUrl);
  suggestion->set_expiry_ts(kTestSetExpiry);
  ASSERT_TRUE(RespondToFetchWithProfile(profile));

  SuggestionsProfile suggestions;
  suggestions_store()->LoadSuggestions(&suggestions);
  ASSERT_EQ(2, suggestions.suggestions_size());
  // Suggestion[0] had no time stamp and should be ahead of the old suggestion.
  EXPECT_LT(kTestSetExpiry, suggestions.suggestions(0).expiry_ts());
  // Suggestion[1] had a very old time stamp but should not be updated.
  EXPECT_EQ(kTestSetExpiry, suggestions.suggestions(1).expiry_ts());
}

}  // namespace suggestions
