Chromium Code Reviews| Index: components/ntp_snippets/remote/remote_suggestions_scheduler_unittest.cc |
| diff --git a/components/ntp_snippets/remote/remote_suggestions_scheduler_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_scheduler_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1bf9caed0eb06270172339cc4aadf9141799bd36 |
| --- /dev/null |
| +++ b/components/ntp_snippets/remote/remote_suggestions_scheduler_unittest.cc |
| @@ -0,0 +1,242 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
|
Marc Treib
2016/12/09 12:25:27
2016
jkrcal
2016/12/19 09:40:23
Done.
|
| +// 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.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()); |
| + |
| + if (enabled) { |
|
Marc Treib
2016/12/09 12:25:27
Hm. Might be better to do this in the individual t
|
| + scheduler->Schedule(); |
| + } else { |
| + scheduler->Unschedule(); |
| + } |
| + return scheduler; |
| + } |
| + |
| + protected: |
| + MockHardScheduler& mock_scheduler() { return hard_scheduler_; } |
|
Marc Treib
2016/12/09 12:25:27
Please rename, otherwise it's difficult to keep th
jkrcal
2016/12/19 09:40:23
Done.
|
| + MockUpdater& updater() { return updater_; } |
| + |
| + private: |
| + test::RemoteSuggestionsTestUtils utils_; |
| + UserClassifier user_classifier_; |
| + NiceMock<MockHardScheduler> hard_scheduler_; |
| + NiceMock<MockUpdater> updater_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsSchedulerTest); |
| +}; |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, SchedulesOnStart) { |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); |
| + |
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, UnschedulesAfterBeingScheduled) { |
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
|
Marc Treib
2016/12/09 12:25:27
Probably you mostly copy-pasted this code, but: Ti
jkrcal
2016/12/19 09:40:23
Done.
|
| + auto scheduler = MakeScheduler(/*enabled=*/true); |
| + |
| + Mock::VerifyAndClearExpectations(&mock_scheduler()); |
|
Marc Treib
2016/12/09 12:25:27
FYI: Tim considers VerifyAndClearExpectations an a
|
| + 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(); |
|
Marc Treib
2016/12/09 12:25:27
Not really necessary; it'll go out of scope anyway
jkrcal
2016/12/19 09:40:24
Done.
|
| +} |
| + |
| +TEST_F(RemoteSuggestionsSchedulerTest, UnscheduleOnlyOnce) { |
|
Marc Treib
2016/12/09 12:25:27
nitty nit: UnschedulesOnlyOnce (add an "s")
jkrcal
2016/12/19 09:40:23
Done.
|
| + 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) { |
|
Marc Treib
2016/12/09 12:25:27
Also here: +s (and a few more below)
jkrcal
2016/12/19 09:40:23
Done.
|
| + 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. |
|
Marc Treib
2016/12/09 12:25:27
nitty nit: successful (only one "l")
jkrcal
2016/12/19 09:40:23
Done.
|
| + EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); |
| + scheduler->PerformHardUpdate(); |
| + scheduler->OnSuccessfulUpdate(); |
|
Marc Treib
2016/12/09 12:25:27
Why do we need both of these calls?
OnSuccessfulUp
jkrcal
2016/12/19 09:40:23
Done.
|
| +} |
| + |
| +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 |