Chromium Code Reviews| Index: components/ntp_snippets/remote/scheduling_remote_suggestions_provider_unittest.cc |
| diff --git a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider_unittest.cc b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4125b1591f8fe6824feff2626374c99b9656f040 |
| --- /dev/null |
| +++ b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider_unittest.cc |
| @@ -0,0 +1,242 @@ |
| +// Copyright 2015 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/scheduling_remote_suggestions_provider.h" |
| + |
| +#include <memory> |
| +#include <set> |
| +#include <string> |
| +#include <utility> |
| +#include <vector> |
| + |
| +#include "base/command_line.h" |
| +#include "base/macros.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "base/message_loop/message_loop.h" |
| +#include "base/run_loop.h" |
| +#include "base/threading/thread_task_runner_handle.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/remote_suggestions_hard_scheduler.h" |
| +#include "components/ntp_snippets/remote/test_utils.h" |
| +#include "components/ntp_snippets/user_classifier.h" |
| +#include "components/prefs/testing_pref_service.h" |
| +#include "components/variations/variations_params_manager.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +using testing::ElementsAre; |
| +using testing::Eq; |
| +using testing::InSequence; |
| +using testing::Invoke; |
| +using testing::IsEmpty; |
| +using testing::Mock; |
| +using testing::MockFunction; |
| +using testing::NiceMock; |
| +using testing::Not; |
| +using testing::SaveArg; |
| +using testing::SizeIs; |
| +using testing::StartsWith; |
| +using testing::WithArgs; |
| +using testing::_; |
| + |
| +namespace ntp_snippets { |
| + |
| +namespace { |
| + |
| +const char* kDifferentWiFiInterval = "2"; |
| + |
| +class MockHardScheduler : public RemoteSuggestionsHardScheduler { |
| + public: |
| + MOCK_METHOD2(Schedule, |
| + bool(base::TimeDelta period_wifi, |
| + base::TimeDelta period_fallback)); |
| + MOCK_METHOD0(Unschedule, bool()); |
| +}; |
| + |
| +class MockUpdater : public RemoteSuggestionsScheduler::Updater { |
| + public: |
| + MOCK_METHOD0(UpdateRemoteSuggestionsBySchedule, void()); |
| +}; |
| + |
| +} // namespace |
| + |
| +class RemoteSuggestionsSchedulerTest : public ::testing::Test { |
| + public: |
| + RemoteSuggestionsSchedulerTest() |
| + : user_classifier_(/*pref_service=*/nullptr) { |
| + RemoteSuggestionsScheduler::RegisterProfilePrefs( |
| + utils_.pref_service()->registry()); |
| + } |
| + |
| + std::unique_ptr<RemoteSuggestionsScheduler> MakeScheduler(bool enabled) { |
| + auto scheduler = base::MakeUnique<RemoteSuggestionsScheduler>( |
| + &mock_scheduler(), &user_classifier_, utils_.pref_service()); |
| + |
| + scheduler->SetUpdater(&updater()); |
|
tschumann
2016/12/15 19:27:01
&updater_
jkrcal
2016/12/20 16:39:45
Not relevant any more.
|
| + |
| + if (enabled) { |
|
tschumann
2016/12/15 19:27:01
let's not do this inside the MakeScheduler() funct
jkrcal
2016/12/20 16:39:46
Done.
|
| + scheduler->Schedule(); |
| + } else { |
| + scheduler->Unschedule(); |
| + } |
| + return scheduler; |
| + } |
| + |
| + protected: |
| + MockHardScheduler& mock_scheduler() { return hard_scheduler_; } |
|
tschumann
2016/12/15 19:27:01
i know that we followed this pattern in other test
jkrcal
2016/12/20 16:39:45
Done.
|
| + MockUpdater& updater() { return updater_; } |
| + |
| + private: |
| + test::RemoteSuggestionsTestUtils utils_; |
| + UserClassifier user_classifier_; |
| + NiceMock<MockHardScheduler> hard_scheduler_; |
|
tschumann
2016/12/15 19:27:01
are you sure you want them to be nice? From my exp
jkrcal
2016/12/20 16:39:45
Done.
|
| + NiceMock<MockUpdater> updater_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsSchedulerTest); |
| +}; |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, SchedulesOnStart) { |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
|
tschumann
2016/12/15 19:27:01
.Times(1) is implicit.
jkrcal
2016/12/20 16:39:45
Done.
|
| + EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); |
|
tschumann
2016/12/15 19:27:01
with a strict-mock that's the default behavior (it
jkrcal
2016/12/20 16:39:45
Done.
|
| + |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, UnschedulesAfterBeingScheduled) { |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + |
| + Mock::VerifyAndClearExpectations(&mock_scheduler()); |
| + EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1); |
| + scheduler->Unschedule(); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, DoesNotUnscheduleOnShutdown) { |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); |
| + |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + |
| + scheduler.reset(); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, UnscheduleOnlyOnce) { |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + |
| + // Unschedule for the first time. |
| + Mock::VerifyAndClearExpectations(&mock_scheduler()); |
| + EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1); |
| + scheduler->Unschedule(); |
| + |
| + // When unscheduling again, we should not get any |Schedule| calls: |
| + // The tasks are already unscheduled, so no need to do it again. |
| + Mock::VerifyAndClearExpectations(&mock_scheduler()); |
| + EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); |
| + scheduler->Unschedule(); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, ScheduleOnlyOnce) { |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + |
| + // When scheduling again, we should not get any |Schedule| calls: |
| + // The tasks are already scheduled with the correct intervals, so no need to |
| + // do it again. |
| + Mock::VerifyAndClearExpectations(&mock_scheduler()); |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0); |
| + scheduler->Schedule(); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, RescheduleWhenWifiParamChanges) { |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + |
| + // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is |
| + // null. Change the wifi interval for this class. |
| + variations::testing::VariationParamsManager params_manager( |
| + ntp_snippets::kStudyName, |
| + {{"fetching_interval_hours-wifi-active_ntp_user", |
| + kDifferentWiFiInterval}}, |
| + {kArticleSuggestionsFeature.name}); |
| + |
| + Mock::VerifyAndClearExpectations(&mock_scheduler()); |
| + // After the change of a paramter, it should reschedule. |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + scheduler->Schedule(); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, RescheduleWhenFallbackParamChanges) { |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + |
| + // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is |
| + // null. Change the wifi interval for this class. |
| + variations::testing::VariationParamsManager params_manager( |
| + ntp_snippets::kStudyName, |
| + {{"fetching_interval_hours-fallback-active_ntp_user", |
| + kDifferentWiFiInterval}}, |
| + {kArticleSuggestionsFeature.name}); |
| + |
| + Mock::VerifyAndClearExpectations(&mock_scheduler()); |
| + // After the change of a paramter, it should reschedule. |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + scheduler->Schedule(); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, HandlesForcedReschedules) { |
| + { |
| + InSequence s; |
| + // The initial scheduling. |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + // Forced rescheduling. |
| + EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1); |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + } |
| + |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + // Forced reschedule |
| + scheduler->Unschedule(); |
| + scheduler->Schedule(); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, ReschedulesAfterSuccessfulUpdate) { |
| + // The initial scheduling. |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + Mock::VerifyAndClearExpectations(&mock_scheduler()); |
| + |
| + // Simulate a succesfull update. |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + scheduler->PerformHardUpdate(); |
| + scheduler->OnSuccessfulUpdate(); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, DoesNotRescheduleAfterFailedUpdate) { |
| + // The initial scheduling. |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + Mock::VerifyAndClearExpectations(&mock_scheduler()); |
| + |
| + // Simulate a succesfull update. |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0); |
| + scheduler->PerformHardUpdate(); |
| + // Failed -> do not call OnSuccessfulUpdate(). |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, CallsUpdater) { |
| + // The initial scheduling. |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + |
| + // Simulate a succesfull update. |
| + EXPECT_CALL(updater(), UpdateRemoteSuggestionsBySchedule()).Times(1); |
| + scheduler->PerformHardUpdate(); |
| +} |
| + |
| +} // namespace ntp_snippets |