// 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/ntp_snippets/content_suggestions_service.h"

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

#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "base/time/default_clock.h"
#include "components/ntp_snippets/category_info.h"
#include "components/ntp_snippets/category_rankers/constant_category_ranker.h"
#include "components/ntp_snippets/category_rankers/fake_category_ranker.h"
#include "components/ntp_snippets/category_rankers/mock_category_ranker.h"
#include "components/ntp_snippets/category_status.h"
#include "components/ntp_snippets/content_suggestion.h"
#include "components/ntp_snippets/content_suggestions_provider.h"
#include "components/ntp_snippets/logger.h"
#include "components/ntp_snippets/mock_content_suggestions_provider.h"
#include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h"
#include "components/ntp_snippets/user_classifier.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/image/image.h"

using testing::_;
using testing::ElementsAre;
using testing::Eq;
using testing::InvokeWithoutArgs;
using testing::IsEmpty;
using testing::Mock;
using testing::Property;
using testing::Return;
using testing::SizeIs;
using testing::StrictMock;
using testing::UnorderedElementsAre;

namespace ntp_snippets {

namespace {

class MockServiceObserver : public ContentSuggestionsService::Observer {
 public:
  MockServiceObserver() = default;
  ~MockServiceObserver() override = default;

  MOCK_METHOD1(OnNewSuggestions, void(Category category));
  MOCK_METHOD2(OnCategoryStatusChanged,
               void(Category changed_category, CategoryStatus new_status));
  MOCK_METHOD1(OnSuggestionInvalidated,
               void(const ContentSuggestion::ID& suggestion_id));
  MOCK_METHOD0(OnFullRefreshRequired, void());
  MOCK_METHOD0(ContentSuggestionsServiceShutdown, void());

 private:
  DISALLOW_COPY_AND_ASSIGN(MockServiceObserver);
};

}  // namespace

class ContentSuggestionsServiceTest : public testing::Test {
 public:
  ContentSuggestionsServiceTest()
      : pref_service_(std::make_unique<TestingPrefServiceSimple>()),
        category_ranker_(std::make_unique<ConstantCategoryRanker>()) {}

  void SetUp() override {
    RegisterPrefs();
    CreateContentSuggestionsService(ContentSuggestionsService::State::ENABLED);
  }

  void TearDown() override {
    service_->Shutdown();
    service_.reset();
  }

  // Verifies that exactly the suggestions with the given |numbers| are
  // returned by the service for the given |category|.
  void ExpectThatSuggestionsAre(Category category, std::vector<int> numbers) {
    std::vector<Category> categories = service()->GetCategories();
    auto position = std::find(categories.begin(), categories.end(), category);
    if (!numbers.empty()) {
      EXPECT_NE(categories.end(), position);
    }

    for (const auto& suggestion :
         service()->GetSuggestionsForCategory(category)) {
      std::string id_within_category = suggestion.id().id_within_category();
      int id;
      ASSERT_TRUE(base::StringToInt(id_within_category, &id));
      auto position = std::find(numbers.begin(), numbers.end(), id);
      if (position == numbers.end()) {
        ADD_FAILURE() << "Unexpected suggestion with ID " << id;
      } else {
        numbers.erase(position);
      }
    }
    for (int number : numbers) {
      ADD_FAILURE() << "Suggestion number " << number
                    << " not present, though expected";
    }
  }

  const std::map<Category, ContentSuggestionsProvider*, Category::CompareByID>&
  providers() {
    return service()->providers_by_category_;
  }

  const std::map<Category, ContentSuggestionsProvider*, Category::CompareByID>&
  dismissed_providers() {
    return service()->dismissed_providers_by_category_;
  }

  MockContentSuggestionsProvider* MakeRegisteredMockProvider(
      Category provided_category) {
    return MakeRegisteredMockProvider(
        std::vector<Category>({provided_category}));
  }

  MockContentSuggestionsProvider* MakeRegisteredMockProvider(
      const std::vector<Category>& provided_categories) {
    auto provider =
        std::make_unique<testing::StrictMock<MockContentSuggestionsProvider>>(
            service(), provided_categories);
    MockContentSuggestionsProvider* result = provider.get();
    service()->RegisterProvider(std::move(provider));
    return result;
  }

  void SetCategoryRanker(std::unique_ptr<CategoryRanker> category_ranker) {
    category_ranker_ = std::move(category_ranker);
  }

  MOCK_METHOD1(OnImageFetched, void(const gfx::Image&));

 protected:
  void RegisterPrefs() {
    ContentSuggestionsService::RegisterProfilePrefs(pref_service_->registry());
    RemoteSuggestionsProviderImpl::RegisterProfilePrefs(
        pref_service_->registry());
    UserClassifier::RegisterProfilePrefs(pref_service_->registry());
  }

  void CreateContentSuggestionsService(
      ContentSuggestionsService::State enabled) {
    ASSERT_FALSE(service_);

    // TODO(jkrcal): Replace by a mock.
    auto user_classifier = std::make_unique<UserClassifier>(
        pref_service_.get(), base::DefaultClock::GetInstance());

    service_ = std::make_unique<ContentSuggestionsService>(
        enabled, /*identity_manager=*/nullptr, /*history_service=*/nullptr,
        /*large_icon_service=*/nullptr, pref_service_.get(),
        std::move(category_ranker_), std::move(user_classifier),
        /*scheduler=*/nullptr, /*debug_logger=*/std::make_unique<Logger>());
  }

  void ResetService() {
    service_->Shutdown();
    service_.reset();
    CreateContentSuggestionsService(ContentSuggestionsService::State::ENABLED);
  }

  ContentSuggestionsService* service() { return service_.get(); }

  // Returns a suggestion instance for testing.
  ContentSuggestion CreateSuggestion(Category category, int number) {
    return ContentSuggestion(
        category, base::NumberToString(number),
        GURL("http://testsuggestion/" + base::NumberToString(number)));
  }

  std::vector<ContentSuggestion> CreateSuggestions(
      Category category,
      const std::vector<int>& numbers) {
    std::vector<ContentSuggestion> result;
    for (int number : numbers) {
      result.push_back(CreateSuggestion(category, number));
    }
    return result;
  }

 private:
  std::unique_ptr<ContentSuggestionsService> service_;
  std::unique_ptr<TestingPrefServiceSimple> pref_service_;
  std::unique_ptr<CategoryRanker> category_ranker_;

  DISALLOW_COPY_AND_ASSIGN(ContentSuggestionsServiceTest);
};

class ContentSuggestionsServiceDisabledTest
    : public ContentSuggestionsServiceTest {
 public:
  void SetUp() override {
    RegisterPrefs();
    CreateContentSuggestionsService(ContentSuggestionsService::State::DISABLED);
  }
};

TEST_F(ContentSuggestionsServiceTest, ShouldRegisterProviders) {
  EXPECT_THAT(service()->state(),
              Eq(ContentSuggestionsService::State::ENABLED));
  Category articles_category =
      Category::FromKnownCategory(KnownCategories::ARTICLES);
  ASSERT_THAT(providers(), IsEmpty());
  EXPECT_THAT(service()->GetCategories(), IsEmpty());
  EXPECT_THAT(service()->GetCategoryStatus(articles_category),
              Eq(CategoryStatus::NOT_PROVIDED));

  MockContentSuggestionsProvider* provider1 =
      MakeRegisteredMockProvider(articles_category);
  provider1->FireCategoryStatusChangedWithCurrentStatus(articles_category);
  ASSERT_THAT(providers().count(articles_category), Eq(1ul));
  EXPECT_THAT(providers().at(articles_category), Eq(provider1));
  EXPECT_THAT(providers().size(), Eq(1ul));
  EXPECT_THAT(service()->GetCategories(),
              UnorderedElementsAre(articles_category));
  EXPECT_THAT(service()->GetCategoryStatus(articles_category),
              Eq(CategoryStatus::AVAILABLE));
}

TEST_F(ContentSuggestionsServiceDisabledTest, ShouldDoNothingWhenDisabled) {
  Category articles_category =
      Category::FromKnownCategory(KnownCategories::ARTICLES);
  EXPECT_THAT(service()->state(),
              Eq(ContentSuggestionsService::State::DISABLED));
  EXPECT_THAT(providers(), IsEmpty());
  EXPECT_THAT(service()->GetCategoryStatus(articles_category),
              Eq(CategoryStatus::ALL_SUGGESTIONS_EXPLICITLY_DISABLED));
  EXPECT_THAT(service()->GetCategories(), IsEmpty());
  EXPECT_THAT(service()->GetSuggestionsForCategory(articles_category),
              IsEmpty());
}

TEST_F(ContentSuggestionsServiceTest, ShouldRedirectFetchSuggestionImage) {
  Category articles_category =
      Category::FromKnownCategory(KnownCategories::ARTICLES);
  MockContentSuggestionsProvider* provider1 =
      MakeRegisteredMockProvider(articles_category);

  provider1->FireSuggestionsChanged(articles_category,
                                    CreateSuggestions(articles_category, {1}));
  ContentSuggestion::ID suggestion_id(articles_category, "1");

  EXPECT_CALL(*provider1, FetchSuggestionImageMock(suggestion_id, _));
  service()->FetchSuggestionImage(
      suggestion_id,
      base::BindOnce(&ContentSuggestionsServiceTest::OnImageFetched,
                     base::Unretained(this)));
}

TEST_F(ContentSuggestionsServiceTest,
       ShouldCallbackEmptyImageForUnavailableProvider) {
  base::test::ScopedTaskEnvironment scoped_task_environment;

  base::RunLoop run_loop;
  // Assuming there will never be a category with the id below.
  ContentSuggestion::ID suggestion_id(Category::FromIDValue(21563), "TestID");
  EXPECT_CALL(*this, OnImageFetched(Property(&gfx::Image::IsEmpty, Eq(true))))
      .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
  service()->FetchSuggestionImage(
      suggestion_id,
      base::BindOnce(&ContentSuggestionsServiceTest::OnImageFetched,
                     base::Unretained(this)));
  run_loop.Run();
}

TEST_F(ContentSuggestionsServiceTest, ShouldRedirectSuggestionInvalidated) {
  Category articles_category =
      Category::FromKnownCategory(KnownCategories::ARTICLES);

  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider(articles_category);
  MockServiceObserver observer;
  service()->AddObserver(&observer);

  provider->FireSuggestionsChanged(
      articles_category, CreateSuggestions(articles_category, {11, 12, 13}));
  ExpectThatSuggestionsAre(articles_category, {11, 12, 13});

  ContentSuggestion::ID suggestion_id(articles_category, "12");
  EXPECT_CALL(observer, OnSuggestionInvalidated(suggestion_id));
  provider->FireSuggestionInvalidated(suggestion_id);
  ExpectThatSuggestionsAre(articles_category, {11, 13});
  Mock::VerifyAndClearExpectations(&observer);

  // Unknown IDs must be forwarded (though no change happens to the service's
  // internal data structures) because previously opened UIs, which can still
  // show the invalidated suggestion, must be notified.
  ContentSuggestion::ID unknown_id(articles_category, "1234");
  EXPECT_CALL(observer, OnSuggestionInvalidated(unknown_id));
  provider->FireSuggestionInvalidated(unknown_id);
  ExpectThatSuggestionsAre(articles_category, {11, 13});
  Mock::VerifyAndClearExpectations(&observer);

  service()->RemoveObserver(&observer);
}

TEST_F(ContentSuggestionsServiceTest, ShouldForwardSuggestions) {
  Category articles_category =
      Category::FromKnownCategory(KnownCategories::ARTICLES);

  // Create and register providers
  MockContentSuggestionsProvider* provider1 =
      MakeRegisteredMockProvider(articles_category);
  provider1->FireCategoryStatusChangedWithCurrentStatus(articles_category);
  ASSERT_THAT(providers().count(articles_category), Eq(1ul));
  EXPECT_THAT(providers().at(articles_category), Eq(provider1));

  // Create and register observer
  MockServiceObserver observer;
  service()->AddObserver(&observer);

  // Send suggestions 1 and 2
  EXPECT_CALL(observer, OnNewSuggestions(articles_category));
  provider1->FireSuggestionsChanged(
      articles_category, CreateSuggestions(articles_category, {1, 2}));
  ExpectThatSuggestionsAre(articles_category, {1, 2});
  Mock::VerifyAndClearExpectations(&observer);

  // Send them again, make sure they're not reported twice
  EXPECT_CALL(observer, OnNewSuggestions(articles_category));
  provider1->FireSuggestionsChanged(
      articles_category, CreateSuggestions(articles_category, {1, 2}));
  ExpectThatSuggestionsAre(articles_category, {1, 2});
  Mock::VerifyAndClearExpectations(&observer);

  // Send suggestion 1 only
  EXPECT_CALL(observer, OnNewSuggestions(articles_category));
  provider1->FireSuggestionsChanged(articles_category,
                                    CreateSuggestions(articles_category, {1}));
  ExpectThatSuggestionsAre(articles_category, {1});
  Mock::VerifyAndClearExpectations(&observer);

  // Shutdown the service
  EXPECT_CALL(observer, ContentSuggestionsServiceShutdown());
  service()->Shutdown();
  service()->RemoveObserver(&observer);
  // The service will receive two Shutdown() calls.
}

TEST_F(ContentSuggestionsServiceTest,
       ShouldNotReturnCategoryInfoForNonexistentCategory) {
  Category category =
      Category::FromKnownCategory(KnownCategories::READING_LIST);
  base::Optional<CategoryInfo> result = service()->GetCategoryInfo(category);
  EXPECT_FALSE(result.has_value());
}

TEST_F(ContentSuggestionsServiceTest, ShouldReturnCategoryInfo) {
  Category category =
      Category::FromKnownCategory(KnownCategories::READING_LIST);
  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider(category);
  provider->FireCategoryStatusChangedWithCurrentStatus(category);
  base::Optional<CategoryInfo> result = service()->GetCategoryInfo(category);
  ASSERT_TRUE(result.has_value());
  CategoryInfo expected = provider->GetCategoryInfo(category);
  const CategoryInfo& actual = result.value();
  EXPECT_THAT(expected.title(), Eq(actual.title()));
  EXPECT_THAT(expected.card_layout(), Eq(actual.card_layout()));
  EXPECT_THAT(expected.additional_action(), Eq(actual.additional_action()));
}

TEST_F(ContentSuggestionsServiceTest,
       ShouldRegisterNewCategoryOnNewSuggestions) {
  Category category =
      Category::FromKnownCategory(KnownCategories::READING_LIST);
  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider(category);
  provider->FireCategoryStatusChangedWithCurrentStatus(category);
  MockServiceObserver observer;
  service()->AddObserver(&observer);

  // Provider starts providing |new_category| without calling
  // |OnCategoryStatusChanged|. This is supported for now until further
  // reconsideration.
  Category new_category =
      Category::FromKnownCategory(KnownCategories::ARTICLES);
  provider->SetProvidedCategories(
      std::vector<Category>({category, new_category}));

  EXPECT_CALL(observer, OnNewSuggestions(new_category));
  EXPECT_CALL(observer,
              OnCategoryStatusChanged(new_category, CategoryStatus::AVAILABLE));
  provider->FireSuggestionsChanged(new_category,
                                   CreateSuggestions(new_category, {1, 2}));

  ExpectThatSuggestionsAre(new_category, {1, 2});
  ASSERT_THAT(providers().count(category), Eq(1ul));
  EXPECT_THAT(providers().at(category), Eq(provider));
  EXPECT_THAT(service()->GetCategoryStatus(category),
              Eq(CategoryStatus::AVAILABLE));
  ASSERT_THAT(providers().count(new_category), Eq(1ul));
  EXPECT_THAT(providers().at(new_category), Eq(provider));
  EXPECT_THAT(service()->GetCategoryStatus(new_category),
              Eq(CategoryStatus::AVAILABLE));

  service()->RemoveObserver(&observer);
}

TEST_F(ContentSuggestionsServiceTest,
       ShouldRegisterNewCategoryOnCategoryStatusChanged) {
  Category category =
      Category::FromKnownCategory(KnownCategories::READING_LIST);
  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider(category);
  provider->FireCategoryStatusChangedWithCurrentStatus(category);
  MockServiceObserver observer;
  service()->AddObserver(&observer);

  // Provider starts providing |new_category| and calls
  // |OnCategoryStatusChanged|, but the category is not yet available.
  Category new_category =
      Category::FromKnownCategory(KnownCategories::ARTICLES);
  provider->SetProvidedCategories(
      std::vector<Category>({category, new_category}));
  EXPECT_CALL(observer, OnCategoryStatusChanged(new_category,
                                                CategoryStatus::INITIALIZING));
  provider->FireCategoryStatusChanged(new_category,
                                      CategoryStatus::INITIALIZING);

  ASSERT_THAT(providers().count(new_category), Eq(1ul));
  EXPECT_THAT(providers().at(new_category), Eq(provider));
  ExpectThatSuggestionsAre(new_category, std::vector<int>());
  EXPECT_THAT(service()->GetCategoryStatus(new_category),
              Eq(CategoryStatus::INITIALIZING));
  EXPECT_THAT(service()->GetCategories(),
              UnorderedElementsAre(category, new_category));

  service()->RemoveObserver(&observer);
}

TEST_F(ContentSuggestionsServiceTest, ShouldRemoveCategoryWhenNotProvided) {
  Category category =
      Category::FromKnownCategory(KnownCategories::READING_LIST);
  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider(category);
  MockServiceObserver observer;
  service()->AddObserver(&observer);

  provider->FireSuggestionsChanged(category,
                                   CreateSuggestions(category, {1, 2}));
  ExpectThatSuggestionsAre(category, {1, 2});

  EXPECT_CALL(observer,
              OnCategoryStatusChanged(category, CategoryStatus::NOT_PROVIDED));
  provider->FireCategoryStatusChanged(category, CategoryStatus::NOT_PROVIDED);

  EXPECT_THAT(service()->GetCategoryStatus(category),
              Eq(CategoryStatus::NOT_PROVIDED));
  EXPECT_TRUE(service()->GetCategories().empty());
  ExpectThatSuggestionsAre(category, std::vector<int>());

  service()->RemoveObserver(&observer);
}

TEST_F(ContentSuggestionsServiceTest,
       ShouldForwardClearHistoryToCategoryRanker) {
  auto mock_ranker = std::make_unique<MockCategoryRanker>();
  MockCategoryRanker* raw_mock_ranker = mock_ranker.get();
  SetCategoryRanker(std::move(mock_ranker));

  // The service is recreated to pick up the new ranker.
  ResetService();

  base::Time begin = base::Time::FromTimeT(123),
             end = base::Time::FromTimeT(456);
  EXPECT_CALL(*raw_mock_ranker, ClearHistory(begin, end));
  base::Callback<bool(const GURL& url)> filter;
  service()->ClearHistory(begin, end, filter);
}

TEST_F(ContentSuggestionsServiceTest, ShouldForwardFetch) {
  Category category = Category::FromKnownCategory(KnownCategories::ARTICLES);
  std::set<std::string> known_suggestions;
  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider(category);
  provider->FireCategoryStatusChangedWithCurrentStatus(category);
  EXPECT_CALL(*provider, FetchMock(category, known_suggestions, _));
  service()->Fetch(category, known_suggestions, FetchDoneCallback());
}

TEST_F(ContentSuggestionsServiceTest, DismissAndRestoreCategory) {
  // Register a category with one suggestion.
  Category category = Category::FromKnownCategory(KnownCategories::ARTICLES);
  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider(category);
  provider->FireCategoryStatusChangedWithCurrentStatus(category);
  provider->FireSuggestionsChanged(category, CreateSuggestions(category, {42}));

  EXPECT_THAT(service()->GetCategories(), UnorderedElementsAre(category));
  EXPECT_THAT(service()->GetCategoryStatus(category),
              Eq(CategoryStatus::AVAILABLE));
  ExpectThatSuggestionsAre(category, {42});
  EXPECT_THAT(providers().count(category), Eq(1ul));
  EXPECT_THAT(dismissed_providers(), IsEmpty());

  // Dismissing the category clears the suggestions for it.
  service()->DismissCategory(category);

  EXPECT_THAT(service()->GetCategories(), IsEmpty());
  EXPECT_THAT(service()->GetCategoryStatus(category),
              Eq(CategoryStatus::NOT_PROVIDED));
  EXPECT_THAT(service()->GetSuggestionsForCategory(category), IsEmpty());
  EXPECT_THAT(providers(), IsEmpty());
  EXPECT_THAT(dismissed_providers().count(category), Eq(1ul));

  // Restoring the dismissed category makes it available again but it is still
  // empty.
  service()->RestoreDismissedCategories();

  EXPECT_THAT(service()->GetCategories(), UnorderedElementsAre(category));
  EXPECT_THAT(service()->GetCategoryStatus(category),
              Eq(CategoryStatus::AVAILABLE));
  EXPECT_THAT(service()->GetSuggestionsForCategory(category), IsEmpty());
  EXPECT_THAT(providers().count(category), Eq(1ul));
  EXPECT_THAT(dismissed_providers(), IsEmpty());
}

TEST_F(ContentSuggestionsServiceTest, ShouldRestoreDismissedCategories) {
  // Create and register provider.
  Category category1 = Category::FromIDValue(1);
  Category category2 = Category::FromIDValue(2);

  // Setup and verify initial state.
  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider({category1, category2});
  provider->FireCategoryStatusChangedWithCurrentStatus(category1);
  provider->FireCategoryStatusChangedWithCurrentStatus(category2);

  ASSERT_THAT(service()->GetCategoryStatus(category1),
              Eq(CategoryStatus::AVAILABLE));
  ASSERT_THAT(service()->GetCategoryStatus(category2),
              Eq(CategoryStatus::AVAILABLE));

  // Dismiss all the categories. None should be provided now.
  service()->DismissCategory(category1);
  service()->DismissCategory(category2);

  ASSERT_THAT(service()->GetCategoryStatus(category1),
              Eq(CategoryStatus::NOT_PROVIDED));
  ASSERT_THAT(service()->GetCategoryStatus(category2),
              Eq(CategoryStatus::NOT_PROVIDED));

  // Receiving a status change notification should not change anything.
  provider->FireCategoryStatusChanged(category1, CategoryStatus::AVAILABLE);

  EXPECT_THAT(service()->GetCategoryStatus(category1),
              Eq(CategoryStatus::NOT_PROVIDED));
  EXPECT_THAT(service()->GetCategoryStatus(category2),
              Eq(CategoryStatus::NOT_PROVIDED));

  // Receiving a notification without suggestions should not change anything.
  provider->FireSuggestionsChanged(category1, std::vector<ContentSuggestion>());

  EXPECT_THAT(service()->GetCategoryStatus(category1),
              Eq(CategoryStatus::NOT_PROVIDED));
  EXPECT_THAT(service()->GetCategoryStatus(category2),
              Eq(CategoryStatus::NOT_PROVIDED));

  // Receiving suggestions should make the notified category available.
  provider->FireSuggestionsChanged(category1,
                                   CreateSuggestions(category1, {1, 2}));

  EXPECT_THAT(service()->GetCategoryStatus(category1),
              Eq(CategoryStatus::AVAILABLE));
  EXPECT_THAT(service()->GetCategoryStatus(category2),
              Eq(CategoryStatus::NOT_PROVIDED));
}

TEST_F(ContentSuggestionsServiceTest, ShouldRestoreDismissalsFromPrefs) {
  // Register a category with one suggestion.
  Category category = Category::FromKnownCategory(KnownCategories::ARTICLES);
  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider(category);
  provider->FireCategoryStatusChangedWithCurrentStatus(category);

  // For a regular initialisation, the category is not dismissed.
  ASSERT_FALSE(service()->IsCategoryDismissed(category));

  // Dismiss the category.
  service()->DismissCategory(category);
  ASSERT_TRUE(service()->IsCategoryDismissed(category));

  // Simulate a Chrome restart. The category should still be dismissed.
  ResetService();
  EXPECT_TRUE(service()->IsCategoryDismissed(category));

  // Ensure that the provider registered at initialisation is used after
  // restoration.
  provider = MakeRegisteredMockProvider(category);
  provider->FireCategoryStatusChangedWithCurrentStatus(category);
  EXPECT_TRUE(service()->IsCategoryDismissed(category));

  service()->RestoreDismissedCategories();
  EXPECT_FALSE(service()->IsCategoryDismissed(category));
  EXPECT_THAT(providers().find(category)->second, Eq(provider));
}

TEST_F(ContentSuggestionsServiceTest, ShouldReturnCategoriesInOrderToDisplay) {
  const Category first_category = Category::FromRemoteCategory(1);
  const Category second_category = Category::FromRemoteCategory(2);

  auto fake_ranker = std::make_unique<FakeCategoryRanker>();
  FakeCategoryRanker* raw_fake_ranker = fake_ranker.get();
  SetCategoryRanker(std::move(fake_ranker));

  raw_fake_ranker->SetOrder({first_category, second_category});

  // The service is recreated to pick up the new ranker.
  ResetService();

  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider({first_category, second_category});
  provider->FireCategoryStatusChangedWithCurrentStatus(first_category);
  provider->FireCategoryStatusChangedWithCurrentStatus(second_category);

  EXPECT_THAT(service()->GetCategories(),
              ElementsAre(first_category, second_category));

  // The order to display (in the ranker) changes.
  raw_fake_ranker->SetOrder({second_category, first_category});

  // Categories order should reflect the new order.
  EXPECT_THAT(service()->GetCategories(),
              ElementsAre(second_category, first_category));
}

TEST_F(ContentSuggestionsServiceTest,
       ShouldForwardDismissedCategoryToCategoryRanker) {
  auto mock_ranker = std::make_unique<MockCategoryRanker>();
  MockCategoryRanker* raw_mock_ranker = mock_ranker.get();
  SetCategoryRanker(std::move(mock_ranker));

  // The service is recreated to pick up the new ranker.
  ResetService();

  Category category = Category::FromKnownCategory(KnownCategories::ARTICLES);
  MockContentSuggestionsProvider* provider =
      MakeRegisteredMockProvider(category);
  provider->FireCategoryStatusChangedWithCurrentStatus(category);

  EXPECT_CALL(*raw_mock_ranker, OnCategoryDismissed(category));
  service()->DismissCategory(category);
}

}  // namespace ntp_snippets
