blob: d7857aa7fed23143130ec4e87ff238009ffe0179 [file] [log] [blame]
// 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/remote/remote_suggestions_scheduler_impl.h"
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "components/ntp_snippets/features.h"
#include "components/ntp_snippets/ntp_snippets_constants.h"
#include "components/ntp_snippets/pref_names.h"
#include "components/ntp_snippets/remote/persistent_scheduler.h"
#include "components/ntp_snippets/remote/remote_suggestions_provider.h"
#include "components/ntp_snippets/remote/test_utils.h"
#include "components/ntp_snippets/status.h"
#include "components/ntp_snippets/user_classifier.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/web_resource/web_resource_pref_names.h"
#include "net/base/mock_network_change_notifier.h"
#include "net/base/network_change_notifier.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::AnyNumber;
using testing::ElementsAre;
using testing::Eq;
using testing::Field;
using testing::InSequence;
using testing::Invoke;
using testing::InvokeArgument;
using testing::IsEmpty;
using testing::Mock;
using testing::MockFunction;
using testing::Not;
using testing::Return;
using testing::SaveArg;
using testing::SaveArgPointee;
using testing::SizeIs;
using testing::StartsWith;
using testing::StrictMock;
using testing::WithArgs;
using testing::_;
namespace ntp_snippets {
class RemoteSuggestionsFetcher;
namespace {
const int kDefaultStartupIntervalHours = 24;
ACTION_TEMPLATE(SaveArgByMove,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_1_VALUE_PARAMS(pointer)) {
*pointer = std::move(*::testing::get<k>(args));
}
class MockPersistentScheduler : public PersistentScheduler {
public:
MOCK_METHOD2(Schedule,
bool(base::TimeDelta period_wifi,
base::TimeDelta period_fallback));
MOCK_METHOD0(Unschedule, bool());
MOCK_METHOD0(IsOnUnmeteredConnection, bool());
};
// TODO(jkrcal): Move into its own library to reuse in other unit-tests?
class MockRemoteSuggestionsProvider : public RemoteSuggestionsProvider {
public:
MockRemoteSuggestionsProvider(Observer* observer)
: RemoteSuggestionsProvider(observer) {}
// Gmock cannot mock a method with movable-only type callback
// FetchStatusCallback as a parameter. As a work-around, this function calls
// the mock function with value passed by pointer. The mock function may then
// be checked with EXPECT_CALL.
void RefetchInTheBackground(
RemoteSuggestionsProvider::FetchStatusCallback callback) override {
RefetchInTheBackground(&callback);
}
MOCK_METHOD1(RefetchInTheBackground,
void(RemoteSuggestionsProvider::FetchStatusCallback*));
// Gmock cannot mock a method with movable-only type callback
// FetchStatusCallback as a parameter. As a work-around, this function calls
// the mock function with value passed by pointer. The mock function may then
// be checked with EXPECT_CALL.
void RefetchWhileDisplaying(
RemoteSuggestionsProvider::FetchStatusCallback callback) override {
RefetchWhileDisplaying(&callback);
}
MOCK_METHOD1(RefetchWhileDisplaying,
void(RemoteSuggestionsProvider::FetchStatusCallback*));
MOCK_CONST_METHOD0(suggestions_fetcher_for_debugging,
const RemoteSuggestionsFetcher*());
MOCK_CONST_METHOD1(GetUrlWithFavicon,
GURL(const ContentSuggestion::ID& suggestion_id));
MOCK_CONST_METHOD0(IsDisabled, bool());
MOCK_CONST_METHOD0(ready, bool());
MOCK_METHOD1(GetCategoryStatus, CategoryStatus(Category));
MOCK_METHOD1(GetCategoryInfo, CategoryInfo(Category));
MOCK_METHOD3(
ClearHistory,
void(base::Time begin,
base::Time end,
const base::RepeatingCallback<bool(const GURL& url)>& filter));
// Gmock cannot mock a method with movable-only type callback
// FetchDoneCallback as a parameter. As a work-around, this function calls the
// mock function with value passed by pointer. The mock function may then be
// checked with EXPECT_CALL.
void Fetch(const Category& category,
const std::set<std::string>& set,
FetchDoneCallback callback) override {
Fetch(category, set, &callback);
}
MOCK_METHOD3(Fetch,
void(const Category&,
const std::set<std::string>&,
FetchDoneCallback*));
MOCK_METHOD0(ReloadSuggestions, void());
MOCK_METHOD0(ClearCachedSuggestions, void());
MOCK_METHOD1(ClearDismissedSuggestionsForDebugging, void(Category));
MOCK_METHOD1(DismissSuggestion, void(const ContentSuggestion::ID&));
// Gmock cannot mock a method with movable-only type callback
// ImageFetchedCallback as a parameter. As a work-around, this function calls
// the mock function with value passed by pointer. The mock function may then
// be checked with EXPECT_CALL.
void FetchSuggestionImage(const ContentSuggestion::ID& id,
ImageFetchedCallback callback) override {
FetchSuggestionImage(id, &callback);
}
MOCK_METHOD2(FetchSuggestionImage,
void(const ContentSuggestion::ID&, ImageFetchedCallback*));
void FetchSuggestionImageData(const ContentSuggestion::ID& suggestion_id,
ImageDataFetchedCallback callback) override {
FetchSuggestionImageData(suggestion_id, &callback);
}
MOCK_METHOD2(FetchSuggestionImageData,
void(const ContentSuggestion::ID&, ImageDataFetchedCallback*));
void GetDismissedSuggestionsForDebugging(
Category category,
DismissedSuggestionsCallback callback) override {
GetDismissedSuggestionsForDebugging(category, &callback);
}
MOCK_METHOD2(GetDismissedSuggestionsForDebugging,
void(Category category, DismissedSuggestionsCallback* callback));
MOCK_METHOD1(OnSignInStateChanged, void(bool));
};
class FakeOfflineNetworkChangeNotifier {
public:
FakeOfflineNetworkChangeNotifier() {
notifier_->SetConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
}
private:
std::unique_ptr<net::test::MockNetworkChangeNotifier> notifier_ =
net::test::MockNetworkChangeNotifier::Create();
};
} // namespace
class RemoteSuggestionsSchedulerImplTest : public ::testing::Test {
public:
RemoteSuggestionsSchedulerImplTest()
: // For the test we enabled all trigger types.
default_variation_params_{{"scheduler_trigger_types",
"persistent_scheduler_wake_up,ntp_opened,"
"browser_foregrounded,browser_cold_start"}},
user_classifier_(/*pref_service=*/nullptr,
base::DefaultClock::GetInstance()) {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
ntp_snippets::kArticleSuggestionsFeature, default_variation_params_);
RemoteSuggestionsSchedulerImpl::RegisterProfilePrefs(
utils_.pref_service()->registry());
RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry());
// TODO(jkrcal) Create a static function in EulaAcceptedNotifier that
// registers this pref and replace the call in browser_process_impl.cc & in
// eula_accepted_notifier_unittest.cc with the new static function.
local_state_.registry()->RegisterBooleanPref(::prefs::kEulaAccepted, false);
// By default pretend we are on WiFi.
EXPECT_CALL(*persistent_scheduler(), IsOnUnmeteredConnection())
.WillRepeatedly(Return(true));
ResetProvider();
}
void ResetProvider() {
provider_ = std::make_unique<StrictMock<MockRemoteSuggestionsProvider>>(
/*observer=*/nullptr);
test_clock_.SetNow(base::Time::Now());
scheduler_ = std::make_unique<RemoteSuggestionsSchedulerImpl>(
&persistent_scheduler_, &user_classifier_, utils_.pref_service(),
&local_state_, &test_clock_);
scheduler_->SetProvider(provider_.get());
}
void SetVariationParameter(const std::string& param_name,
const std::string& param_value) {
std::map<std::string, std::string> params = default_variation_params_;
params[param_name] = param_value;
scoped_feature_list_.Reset();
scoped_feature_list_.InitAndEnableFeatureWithParameters(
ntp_snippets::kArticleSuggestionsFeature, params);
}
bool IsEulaNotifierAvailable() {
// Create() returns a unique_ptr, so this is no leak.
return web_resource::EulaAcceptedNotifier::Create(&local_state_) != nullptr;
}
void SetEulaAcceptedPref() {
local_state_.SetBoolean(::prefs::kEulaAccepted, true);
}
// GMock cannot deal with move-only types. We need to pass the vector to the
// mock function as const ref using this wrapper callback.
void FetchDoneWrapper(
MockFunction<void(Status status_code,
const std::vector<ContentSuggestion>& suggestions)>*
fetch_done,
Status status_code,
std::vector<ContentSuggestion> suggestions) {
fetch_done->Call(status_code, suggestions);
}
protected:
std::map<std::string, std::string> default_variation_params_;
base::test::ScopedFeatureList scoped_feature_list_;
void ActivateProviderAndEula() {
SetEulaAcceptedPref();
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(true));
scheduler_->OnProviderActivated();
}
void ActivateProvider() {
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(true));
scheduler_->OnProviderActivated();
}
void DeactivateProvider() {
scheduler_->OnProviderDeactivated();
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(true));
}
void ExpectOneRetiringRefetchInTheBackground() {
// After a successful fetch, the client updates it's schedule, so we expect
// another call here.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).RetiresOnSaturation();
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(Invoke(
[](RemoteSuggestionsProvider::FetchStatusCallback* callback) {
std::move(*callback).Run(Status::Success());
}))
.RetiresOnSaturation();
}
MockPersistentScheduler* persistent_scheduler() {
return &persistent_scheduler_;
}
base::SimpleTestClock* test_clock() { return &test_clock_; }
MockRemoteSuggestionsProvider* provider() { return provider_.get(); }
RemoteSuggestionsSchedulerImpl* scheduler() { return scheduler_.get(); }
private:
test::RemoteSuggestionsTestUtils utils_;
UserClassifier user_classifier_;
TestingPrefServiceSimple local_state_;
StrictMock<MockPersistentScheduler> persistent_scheduler_;
base::SimpleTestClock test_clock_;
std::unique_ptr<MockRemoteSuggestionsProvider> provider_;
std::unique_ptr<RemoteSuggestionsSchedulerImpl> scheduler_;
DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsSchedulerImplTest);
};
TEST_F(RemoteSuggestionsSchedulerImplTest, ShouldIgnoreSignalsWhenNotEnabled) {
// The signals should be ignored even if the provider itself claims it is
// ready.
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(true));
scheduler()->OnPersistentSchedulerWakeUp();
scheduler()->OnSuggestionsSurfaceOpened();
scheduler()->OnBrowserForegrounded();
scheduler()->OnBrowserColdStart();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldIgnoreEulaStateOnPlatformsWhereNotAvaiable) {
// Only run this tests on platforms that don't support Eula.
if (IsEulaNotifierAvailable()) {
return;
}
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProvider();
// Verify fetches get triggered.
ExpectOneRetiringRefetchInTheBackground();
scheduler()->OnPersistentSchedulerWakeUp();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldIgnoreSignalsWhenEulaNotAccepted) {
// Only run this tests on platforms supporting Eula.
if (!IsEulaNotifierAvailable()) {
return;
}
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProvider();
// All signals are ignored because of Eula not being accepted.
scheduler()->OnPersistentSchedulerWakeUp();
scheduler()->OnSuggestionsSurfaceOpened();
scheduler()->OnBrowserForegrounded();
scheduler()->OnBrowserColdStart();
}
TEST_F(RemoteSuggestionsSchedulerImplTest, ShouldFetchWhenEulaGetsAccepted) {
// Only run this tests on platforms supporting Eula.
if (!IsEulaNotifierAvailable()) {
return;
}
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProvider();
// Make one (ignored) call to make sure we are interested in eula state.
scheduler()->OnPersistentSchedulerWakeUp();
// Accepting Eula afterwards results in a background fetch.
ExpectOneRetiringRefetchInTheBackground();
SetEulaAcceptedPref();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldQueueBackgroundRequestIfEulaIsMissing) {
// Only run this tests on platforms supporting Eula.
if (!IsEulaNotifierAvailable()) {
return;
}
// Eula is not ready -- no fetch. But request should get queued.
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(false));
scheduler()->OnPersistentSchedulerWakeUp();
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
// Activate provider -- this should set up the schedule but cannot trigger a
// fetch due to Eula missing.
ActivateProvider();
// Accepting Eula picks up the queued fetch.
ExpectOneRetiringRefetchInTheBackground();
SetEulaAcceptedPref();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldQueueBackgroundRequestBeforeActivated) {
// Set the Eula bit to be sure we queue them because of not being activated.
SetEulaAcceptedPref();
// Activate provider -- this should set up the schedule and store it to prefs.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).RetiresOnSaturation();
ActivateProvider();
// Reset the provider after we have the schedule stored in prefs.
ResetProvider();
// Provider is not active -- no fetch. But request should get queued.
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(false));
scheduler()->OnPersistentSchedulerWakeUp();
ExpectOneRetiringRefetchInTheBackground();
// Activate provider -- this should trigger the fetch (the schedule was set up
// previously).
ActivateProvider();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldIgnoreSignalsWhenDisabledByParam) {
// First set an empty list of allowed trigger types.
SetVariationParameter("scheduler_trigger_types", "-");
ResetProvider();
// Then enable the scheduler.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
scheduler()->OnPersistentSchedulerWakeUp();
scheduler()->OnSuggestionsSurfaceOpened();
scheduler()->OnBrowserForegrounded();
scheduler()->OnBrowserColdStart();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldHandleEmptyParamForTriggerTypes) {
// First set an empty param for allowed trigger types -> should result in the
// default list.
SetVariationParameter("scheduler_trigger_types", "");
ResetProvider();
// Then enable the scheduler.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// For instance, persistent scheduler wake up should be enabled by default.
ExpectOneRetiringRefetchInTheBackground();
scheduler()->OnPersistentSchedulerWakeUp();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldHandleIncorrentParamForTriggerTypes) {
// First set an invalid list of allowed trigger types.
SetVariationParameter("scheduler_trigger_types", "ntp_opened,foo;");
ResetProvider();
// Then enable the scheduler.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// For instance, persistent scheduler wake up should be enabled by default.
ExpectOneRetiringRefetchInTheBackground();
scheduler()->OnPersistentSchedulerWakeUp();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldFetchOnPersistentSchedulerWakeUp) {
// First set only this type to be allowed.
SetVariationParameter("scheduler_trigger_types",
"persistent_scheduler_wake_up");
ResetProvider();
// Then enable the scheduler.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
ExpectOneRetiringRefetchInTheBackground();
scheduler()->OnPersistentSchedulerWakeUp();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldFetchOnPersistentSchedulerWakeUpRepeated) {
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
{
InSequence s;
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
}
// First enable the scheduler -- calling Schedule() for the first time.
ActivateProviderAndEula();
// Make the first persistent fetch successful -- calling Schedule() again.
scheduler()->OnPersistentSchedulerWakeUp();
std::move(signal_fetch_done).Run(Status::Success());
// Make the second fetch.
scheduler()->OnPersistentSchedulerWakeUp();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldNotTriggerBackgroundFetchIfAlreadyInProgess) {
{
InSequence s;
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
// We do not capture and execute the callback to keep the fetch in-flight.
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
// Refetch is not called after the second trigger.
}
// First enable the scheduler -- calling Schedule() for the first time.
ActivateProviderAndEula();
// Make the first persistent fetch never finish.
scheduler()->OnPersistentSchedulerWakeUp();
// Make the second fetch.
scheduler()->OnPersistentSchedulerWakeUp();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldFetchOnSuggestionsSurfaceOpenedForTheFirstTime) {
// First set only this type to be allowed.
SetVariationParameter("scheduler_trigger_types", "ntp_opened");
ResetProvider();
// Then enable the scheduler.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
ExpectOneRetiringRefetchInTheBackground();
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldFetchOnBrowserForegroundedForTheFirstTime) {
// First set only this type to be allowed.
SetVariationParameter("scheduler_trigger_types", "browser_foregrounded");
ResetProvider();
// Then enable the scheduler.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
ExpectOneRetiringRefetchInTheBackground();
scheduler()->OnBrowserForegrounded();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldFetchOnBrowserColdStartForTheFirstTime) {
// Then enable the scheduler.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
ExpectOneRetiringRefetchInTheBackground();
scheduler()->OnBrowserColdStart();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldQueueBackgroundFetchSignalsOnPersistentSchedulerWakeUp) {
// Enable EULA to make this test not depend on that setting (or it being
// flipped)
SetEulaAcceptedPref();
// On activation, the Schedule should get updated and the queued background
// fetch should get propagated.
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(false));
scheduler()->OnPersistentSchedulerWakeUp();
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ExpectOneRetiringRefetchInTheBackground();
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldQueueBackgroundFetchSignalsOnSurfaceOpened) {
// Enable EULA to make this test not depend on that setting (or it being
// flipped)
SetEulaAcceptedPref();
// On activation, the Schedule should get updated and the queued background
// fetch should get propagated.
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(false));
scheduler()->OnSuggestionsSurfaceOpened();
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ExpectOneRetiringRefetchInTheBackground();
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldQueueBackgroundFetchSignalsOnBrowserForegrounded) {
// Enable EULA to make this test not depend on that setting (or it being
// flipped)
SetEulaAcceptedPref();
// On activation, the Schedule should get updated and the queued background
// fetch should get propagated.
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(false));
scheduler()->OnBrowserForegrounded();
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ExpectOneRetiringRefetchInTheBackground();
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldQueueBackgroundFetchSignalsOnBrowserColdStart) {
// Enable EULA to make this test not depend on that setting (or it being
// flipped)
SetEulaAcceptedPref();
// On activation, the Schedule should get updated and the queued background
// fetch should get propagated.
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(false));
scheduler()->OnBrowserColdStart();
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ExpectOneRetiringRefetchInTheBackground();
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldQueueMultipleBackgroundFetchSignals) {
// Enable EULA to make this test not depend on that setting (or it being
// flipped)
SetEulaAcceptedPref();
// We want to store multiple events to respect lower thresholds for specific
// events properly. To test this, we do the following setup:
// (1) Force a fetch.
// (2) Simulate a stop of the browser, wait until surface-opened would trigger
// a fetch but start-up would not trigger a fetch yet.
// (3) simulate a very slow initialization, where the scheduler sees both
// events (cold start and surface opened) before being activated.
// (4) make sure that activation triggers a background fetch.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(AnyNumber());
ActivateProviderAndEula();
ExpectOneRetiringRefetchInTheBackground();
scheduler()->OnBrowserColdStart();
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER - we work with the
// default interval for this class here. This time would allow for a fetch on
// NTP open but not on cold start.
test_clock()->Advance(base::TimeDelta::FromHours(13));
// This should *not* trigger a fetch.
scheduler()->OnBrowserColdStart();
// Simulate a restart.
EXPECT_CALL(*persistent_scheduler(), Unschedule());
scheduler()->OnProviderDeactivated();
ResetProvider(); // Also resets the scheduler and test clock.
test_clock()->Advance(base::TimeDelta::FromHours(13));
EXPECT_CALL(*provider(), ready()).WillRepeatedly(Return(false));
scheduler()->OnSuggestionsSurfaceOpened();
scheduler()->OnBrowserColdStart();
ExpectOneRetiringRefetchInTheBackground();
// Signal the provider is ready (EULA check should still pass from the first
// start). We don't want to trigger EULA again as it will simulate a
// persistent fetch.
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldNotFetchOnSuggestionsSurfaceOpenedAfterSuccessfulSoftFetch) {
// First enable the scheduler; the second Schedule is called after the
// successful fetch.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
ActivateProviderAndEula();
// Make the first soft fetch successful.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnSuggestionsSurfaceOpened();
std::move(signal_fetch_done).Run(Status::Success());
// The second call is ignored if it happens right after the first one.
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldNotFetchOnSuggestionsSurfaceOpenedAfterSuccessfulPersistentFetch) {
// First enable the scheduler; the second Schedule is called after the
// successful fetch.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
ActivateProviderAndEula();
// Make the first persistent fetch successful.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnPersistentSchedulerWakeUp();
std::move(signal_fetch_done).Run(Status::Success());
// The second call is ignored if it happens right after the first one.
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldNotFetchOnSuggestionsSurfaceOpenedAfterFailedSoftFetch) {
// First enable the scheduler.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// Make the first soft fetch failed.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnSuggestionsSurfaceOpened();
std::move(signal_fetch_done).Run(Status(StatusCode::PERMANENT_ERROR, ""));
// The second call is ignored if it happens right after the first one.
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldNotFetchOnSuggestionsSurfaceOpenedAfterFailedPersistentFetch) {
// First enable the scheduler.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// Make the first persistent fetch failed.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnPersistentSchedulerWakeUp();
std::move(signal_fetch_done).Run(Status(StatusCode::PERMANENT_ERROR, ""));
// The second call is ignored if it happens right after the first one.
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldFetchAgainOnBrowserForgroundLaterAgain) {
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
{
InSequence s;
// Initial scheduling after being enabled.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
// The first call to NTPOpened results in a fetch.
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
// Rescheduling after a succesful fetch.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
// The second call to NTPOpened 4hrs later again results in a fetch.
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
}
// First enable the scheduler.
ActivateProviderAndEula();
// Make the first soft fetch successful.
scheduler()->OnBrowserForegrounded();
std::move(signal_fetch_done).Run(Status::Success());
test_clock()->Advance(
base::TimeDelta::FromHours(kDefaultStartupIntervalHours));
scheduler()->OnBrowserForegrounded();
}
TEST_F(RemoteSuggestionsSchedulerImplTest, ShouldRescheduleOnBrowserUpgraded) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
scheduler()->OnBrowserUpgraded();
}
TEST_F(RemoteSuggestionsSchedulerImplTest, ShouldScheduleOnActivation) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldUnscheduleOnLaterInactivation) {
{
InSequence s;
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
EXPECT_CALL(*persistent_scheduler(), Unschedule());
}
ActivateProviderAndEula();
DeactivateProvider();
}
TEST_F(RemoteSuggestionsSchedulerImplTest, ShouldScheduleOnLaterActivation) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
// There is no schedule yet, so inactivation does not trigger unschedule.
DeactivateProvider();
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldRescheduleAfterSuccessfulFetch) {
// First reschedule on becoming active.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
ActivateProviderAndEula();
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
// Trigger a fetch.
scheduler()->OnPersistentSchedulerWakeUp();
// Second reschedule after a successful fetch.
std::move(signal_fetch_done).Run(Status::Success());
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldNotRescheduleAfterFailedFetch) {
// Only reschedule on becoming active.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
// Trigger a fetch.
scheduler()->OnPersistentSchedulerWakeUp();
// No furter reschedule after a failure.
std::move(signal_fetch_done).Run(Status(StatusCode::PERMANENT_ERROR, ""));
}
TEST_F(RemoteSuggestionsSchedulerImplTest, ShouldScheduleOnlyOnce) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// No further call to Schedule on a second status callback.
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest, ShouldUnscheduleOnlyOnce) {
{
InSequence s;
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
EXPECT_CALL(*persistent_scheduler(), Unschedule());
}
// First schedule so that later we really unschedule.
ActivateProviderAndEula();
DeactivateProvider();
// No further call to Unschedule on second status callback.
DeactivateProvider();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ReschedulesWhenPersistentWifiParamChanges) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
ActivateProviderAndEula();
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
// null. Change the wifi interval for this class.
SetVariationParameter("fetching_interval_hours-wifi-active_ntp_user", "1.5");
// Schedule() should get called for the second time after params have changed.
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ReschedulesWhenPersistentFallbackParamChanges) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
ActivateProviderAndEula();
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
// null. Change the fallback interval for this class.
SetVariationParameter("fetching_interval_hours-fallback-active_ntp_user",
"1.5");
// Schedule() should get called for the second time after params have changed.
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ReschedulesWhenShownWifiParamChanges) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
ActivateProviderAndEula();
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
// null. Change the on usage interval for this class.
SetVariationParameter("soft_fetching_interval_hours-wifi-active_ntp_user",
"1.5");
// Schedule() should get called for the second time after params have changed.
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ReschedulesWhenShownFallbackParamChanges) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
ActivateProviderAndEula();
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
// null. Change the fallback interval for this class.
SetVariationParameter("soft_fetching_interval_hours-fallback-active_ntp_user",
"1.5");
// Schedule() should get called for the second time after params have changed.
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ReschedulesWhenStartupWifiParamChanges) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
ActivateProviderAndEula();
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
// null. Change the on usage interval for this class.
SetVariationParameter("startup_fetching_interval_hours-wifi-active_ntp_user",
"1.5");
// Schedule() should get called for the second time after params have changed.
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ReschedulesWhenStartupFallbackParamChanges) {
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
ActivateProviderAndEula();
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
// null. Change the fallback interval for this class.
SetVariationParameter(
"startup_fetching_interval_hours-fallback-active_ntp_user", "1.5");
// Schedule() should get called for the second time after params have changed.
ActivateProviderAndEula();
}
TEST_F(RemoteSuggestionsSchedulerImplTest, FetchIntervalForShownTriggerOnWifi) {
// Pretend we are on WiFi (already done in ctor, we make it explicit here).
EXPECT_CALL(*persistent_scheduler(), IsOnUnmeteredConnection())
.WillRepeatedly(Return(true));
// Initial scheduling after being enabled.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// The first call to NTPOpened results in a fetch.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnSuggestionsSurfaceOpened();
// Rescheduling after a succesful fetch.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
std::move(signal_fetch_done).Run(Status::Success());
// Open NTP again after too short delay (one minute missing). UserClassifier
// defaults to UserClass::ACTIVE_NTP_USER - we work with the default interval
// for this class here. This time no fetch is executed.
test_clock()->Advance(base::TimeDelta::FromHours(4) -
base::TimeDelta::FromMinutes(1));
scheduler()->OnSuggestionsSurfaceOpened();
// Open NTP after another delay, now together long enough to issue a fetch.
test_clock()->Advance(base::TimeDelta::FromMinutes(2));
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
OverrideFetchIntervalForShownTriggerOnWifi) {
// Pretend we are on WiFi (already done in ctor, we make it explicit here).
EXPECT_CALL(*persistent_scheduler(), IsOnUnmeteredConnection())
.WillRepeatedly(Return(true));
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
// null. Change the interval for this class from 4h to 30min.
SetVariationParameter("soft_fetching_interval_hours-wifi-active_ntp_user",
"0.5");
// Initial scheduling after being enabled.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// The first call to NTPOpened results in a fetch.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnSuggestionsSurfaceOpened();
// Rescheduling after a succesful fetch.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
std::move(signal_fetch_done).Run(Status::Success());
// Open NTP again after too short delay. This time no fetch is executed.
test_clock()->Advance(base::TimeDelta::FromMinutes(20));
scheduler()->OnSuggestionsSurfaceOpened();
// Open NTP after another delay, now together long enough to issue a fetch.
test_clock()->Advance(base::TimeDelta::FromMinutes(10));
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
FetchIntervalForShownTriggerOnFallback) {
// Pretend we are not on wifi -> fallback connection.
EXPECT_CALL(*persistent_scheduler(), IsOnUnmeteredConnection())
.WillRepeatedly(Return(false));
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER which uses a 12h time
// interval by default for shown trigger not on WiFi.
// Initial scheduling after being enabled.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// The first call to NTPOpened results in a fetch.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnSuggestionsSurfaceOpened();
// Rescheduling after a succesful fetch.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
std::move(signal_fetch_done).Run(Status::Success());
// Open NTP again after too short delay. This time no fetch is executed.
test_clock()->Advance(base::TimeDelta::FromHours(4) -
base::TimeDelta::FromMinutes(1));
scheduler()->OnSuggestionsSurfaceOpened();
// Open NTP after another delay, now together long enough to issue a fetch.
test_clock()->Advance(base::TimeDelta::FromMinutes(2));
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
OverrideFetchIntervalForShownTriggerOnFallback) {
// Pretend we are not on wifi -> fallback connection.
EXPECT_CALL(*persistent_scheduler(), IsOnUnmeteredConnection())
.WillRepeatedly(Return(false));
// UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
// null. Change the interval for this class from 4h to 30min.
SetVariationParameter("soft_fetching_interval_hours-fallback-active_ntp_user",
"0.5");
// Initial scheduling after being enabled.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// The first call to NTPOpened results in a fetch.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnSuggestionsSurfaceOpened();
// Rescheduling after a succesful fetch.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
std::move(signal_fetch_done).Run(Status::Success());
// Open NTP again after too short delay. This time no fetch is executed.
test_clock()->Advance(base::TimeDelta::FromMinutes(20));
scheduler()->OnSuggestionsSurfaceOpened();
// Open NTP after another delay, now together long enough to issue a fetch.
test_clock()->Advance(base::TimeDelta::FromMinutes(10));
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldBlockFetchingForSomeTimeAfterHistoryCleared) {
// First enable the scheduler -- this will trigger the persistent scheduling.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// Clear the history.
scheduler()->OnHistoryCleared();
// A trigger after 15 minutes is ignored.
test_clock()->Advance(base::TimeDelta::FromMinutes(15));
scheduler()->OnBrowserForegrounded();
// A trigger after another 16 minutes is performed (more than 30m after
// clearing the history).
EXPECT_CALL(*provider(), RefetchWhileDisplaying(_));
test_clock()->Advance(base::TimeDelta::FromMinutes(16));
scheduler()->OnBrowserForegrounded();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldImmediatelyFetchAfterSuggestionsCleared) {
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
// First enable the scheduler -- this will trigger the persistent scheduling.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// The first trigger results in a fetch.
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnBrowserForegrounded();
// Make the fetch successful -- this results in rescheduling.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
std::move(signal_fetch_done).Run(Status::Success());
// Clear the suggestions - results in an immediate fetch.
EXPECT_CALL(*provider(), RefetchWhileDisplaying(_));
scheduler()->OnSuggestionsCleared();
}
TEST_F(RemoteSuggestionsSchedulerImplTest, ShouldThrottleInteractiveRequests) {
// Change the quota for interactive requests ("active NTP user" is the default
// class in tests).
SetVariationParameter("interactive_quota_SuggestionFetcherActiveNTPUser",
"10");
ResetProvider();
for (int x = 0; x < 10; ++x) {
EXPECT_THAT(scheduler()->AcquireQuotaForInteractiveFetch(), Eq(true));
}
// Now the quota is over.
EXPECT_THAT(scheduler()->AcquireQuotaForInteractiveFetch(), Eq(false));
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldThrottleNonInteractiveRequests) {
// Change the quota for interactive requests ("active NTP user" is the default
// class in tests).
SetVariationParameter("quota_SuggestionFetcherActiveNTPUser", "5");
ResetProvider();
// One scheduling on start, 5 times after successful fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(6);
// First enable the scheduler -- this will trigger the persistent scheduling.
ActivateProviderAndEula();
// As long as the quota suffices, the call gets through.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.Times(5)
.WillRepeatedly(SaveArgByMove<0>(&signal_fetch_done));
for (int x = 0; x < 5; ++x) {
scheduler()->OnPersistentSchedulerWakeUp();
std::move(signal_fetch_done).Run(Status::Success());
}
// For the 6th time, it is blocked by the scheduling provider.
scheduler()->OnPersistentSchedulerWakeUp();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldIgnoreSubsequentStartupSignalsForM58) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
kRemoteSuggestionsEmulateM58FetchingSchedule);
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
// First enable the scheduler -- this will trigger the persistent scheduling.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// The startup triggers are ignored.
EXPECT_CALL(*provider(), RefetchInTheBackground(_)).Times(0);
scheduler()->OnBrowserForegrounded();
scheduler()->OnBrowserColdStart();
// Foreground the browser again after a very long delay. Again, no fetch is
// executed for neither Foregrounded, nor ColdStart.
test_clock()->Advance(base::TimeDelta::FromHours(100000));
scheduler()->OnBrowserForegrounded();
scheduler()->OnBrowserColdStart();
}
TEST_F(RemoteSuggestionsSchedulerImplTest, ShouldIgnoreSignalsWhenOffline) {
// Simulate being offline. NetworkChangeNotifier is a singleton, thus, this
// instance is actually globally accessible (from the static function
// NetworkChangeNotifier::IsOffline() that is called from the scheduler).
FakeOfflineNetworkChangeNotifier fake;
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _));
ActivateProviderAndEula();
// All signals are ignored because of being offline.
EXPECT_CALL(*provider(), RefetchInTheBackground(_)).Times(0);
scheduler()->OnPersistentSchedulerWakeUp();
scheduler()->OnSuggestionsSurfaceOpened();
scheduler()->OnBrowserForegrounded();
scheduler()->OnBrowserColdStart();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldNotRefetchWhileDisplayingBeforeDefaultDelay) {
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
// First enable the scheduler -- this will trigger the persistent scheduling.
ActivateProviderAndEula();
// The first refetch is never considered due to staleness.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnBrowserForegrounded();
std::move(signal_fetch_done).Run(Status::Success());
// The staleness threshold by default equals to the startup interval.
test_clock()->Advance(
base::TimeDelta::FromHours(kDefaultStartupIntervalHours) -
base::TimeDelta::FromMinutes(1));
// Not long enough: non-stale.
EXPECT_CALL(*provider(), RefetchWhileDisplaying(_)).Times(0);
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
// Use the SurfaceOpened trigger as this has the shortest intervals and thus
// allows to test both short and long delay in the same way.
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldRefetchWhileDisplayingAfterDefaultDelay) {
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
// First enable the scheduler -- this will trigger the persistent scheduling.
ActivateProviderAndEula();
// The first refetch is never considered due to staleness.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnBrowserForegrounded();
std::move(signal_fetch_done).Run(Status::Success());
// The staleness threshold by default equals to the startup interval.
test_clock()->Advance(
base::TimeDelta::FromHours(kDefaultStartupIntervalHours) +
base::TimeDelta::FromMinutes(1));
// Long enough: stale.
EXPECT_CALL(*provider(), RefetchWhileDisplaying(_));
EXPECT_CALL(*provider(), RefetchInTheBackground(_)).Times(0);
// Use the SurfaceOpened trigger as this has the shortest intervals and thus
// allows to test both short and long delay in the same way.
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldNotRefetchWhileDisplayingBeforeConfigurableDelay) {
constexpr int kStaleHours = 18;
SetVariationParameter("min_age_for_stale_fetch_hours",
base::NumberToString(kStaleHours));
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
// First enable the scheduler -- this will trigger the persistent scheduling.
ActivateProviderAndEula();
// The first refetch is never considered due to staleness.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnBrowserForegrounded();
std::move(signal_fetch_done).Run(Status::Success());
// The staleness threshold by default equals to the startup interval.
test_clock()->Advance(base::TimeDelta::FromHours(kStaleHours) -
base::TimeDelta::FromMinutes(1));
// Not long enough: non-stale.
EXPECT_CALL(*provider(), RefetchWhileDisplaying(_)).Times(0);
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
// Use the SurfaceOpened trigger as this has the shortest intervals and thus
// allows to test both short and long delay in the same way.
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldRefetchWhileDisplayingAfterConfigurableDelay) {
constexpr int kStaleHours = 18;
SetVariationParameter("min_age_for_stale_fetch_hours",
base::NumberToString(kStaleHours));
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
// First enable the scheduler -- this will trigger the persistent scheduling.
ActivateProviderAndEula();
// The first refetch is never considered due to staleness.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnBrowserForegrounded();
std::move(signal_fetch_done).Run(Status::Success());
test_clock()->Advance(base::TimeDelta::FromHours(kStaleHours) +
base::TimeDelta::FromMinutes(1));
// Long enough: stale.
EXPECT_CALL(*provider(), RefetchWhileDisplaying(_));
EXPECT_CALL(*provider(), RefetchInTheBackground(_)).Times(0);
// Use the SurfaceOpened trigger as this has the shortest intervals and thus
// allows to test both short and long delay in the same way.
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldNotRefetchWhileDisplayingBeforeFallbackConfigurableDelay) {
constexpr int kStartupHours = 12;
SetVariationParameter("startup_fetching_interval_hours-wifi-active_ntp_user",
base::NumberToString(kStartupHours));
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
// First enable the scheduler -- this will trigger the persistent scheduling.
ActivateProviderAndEula();
// The first refetch is never considered due to staleness.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnBrowserForegrounded();
std::move(signal_fetch_done).Run(Status::Success());
// The staleness threshold by default equals to the startup interval.
test_clock()->Advance(base::TimeDelta::FromHours(kStartupHours) -
base::TimeDelta::FromMinutes(1));
// Not long enough: non-stale.
EXPECT_CALL(*provider(), RefetchWhileDisplaying(_)).Times(0);
EXPECT_CALL(*provider(), RefetchInTheBackground(_));
// Use the SurfaceOpened trigger as this has the shortest intervals and thus
// allows to test both short and long delay in the same way.
scheduler()->OnSuggestionsSurfaceOpened();
}
TEST_F(RemoteSuggestionsSchedulerImplTest,
ShouldRefetchWhileDisplayingAfterFallbackConfigurableDelay) {
constexpr int kStartupHours = 12;
SetVariationParameter("startup_fetching_interval_hours-wifi-active_ntp_user",
base::NumberToString(kStartupHours));
// Activating the provider should schedule the persistent background fetches.
EXPECT_CALL(*persistent_scheduler(), Schedule(_, _)).Times(2);
// First enable the scheduler -- this will trigger the persistent scheduling.
ActivateProviderAndEula();
// The first refetch is never considered due to staleness.
RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
EXPECT_CALL(*provider(), RefetchInTheBackground(_))
.WillOnce(SaveArgByMove<0>(&signal_fetch_done));
scheduler()->OnBrowserForegrounded();
std::move(signal_fetch_done).Run(Status::Success());
test_clock()->Advance(base::TimeDelta::FromHours(kStartupHours) +
base::TimeDelta::FromMinutes(1));
// Long enough: stale.
EXPECT_CALL(*provider(), RefetchWhileDisplaying(_));
EXPECT_CALL(*provider(), RefetchInTheBackground(_)).Times(0);
// Use the SurfaceOpened trigger as this has the shortest intervals and thus
// allows to test both short and long delay in the same way.
scheduler()->OnSuggestionsSurfaceOpened();
}
} // namespace ntp_snippets