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 |