OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/ntp_snippets/remote/scheduling_remote_suggestions_provider. h" | |
6 | |
7 #include <memory> | |
8 #include <set> | |
9 #include <string> | |
10 #include <utility> | |
11 #include <vector> | |
12 | |
13 #include "base/command_line.h" | |
14 #include "base/macros.h" | |
15 #include "base/memory/ptr_util.h" | |
16 #include "base/message_loop/message_loop.h" | |
17 #include "base/run_loop.h" | |
18 #include "base/threading/thread_task_runner_handle.h" | |
19 #include "base/time/time.h" | |
20 #include "components/ntp_snippets/features.h" | |
21 #include "components/ntp_snippets/ntp_snippets_constants.h" | |
22 #include "components/ntp_snippets/pref_names.h" | |
23 #include "components/ntp_snippets/remote/remote_suggestions_hard_scheduler.h" | |
24 #include "components/ntp_snippets/remote/test_utils.h" | |
25 #include "components/ntp_snippets/user_classifier.h" | |
26 #include "components/prefs/testing_pref_service.h" | |
27 #include "components/variations/variations_params_manager.h" | |
28 #include "testing/gmock/include/gmock/gmock.h" | |
29 #include "testing/gtest/include/gtest/gtest.h" | |
30 | |
31 using testing::ElementsAre; | |
32 using testing::Eq; | |
33 using testing::InSequence; | |
34 using testing::Invoke; | |
35 using testing::IsEmpty; | |
36 using testing::Mock; | |
37 using testing::MockFunction; | |
38 using testing::NiceMock; | |
39 using testing::Not; | |
40 using testing::SaveArg; | |
41 using testing::SizeIs; | |
42 using testing::StartsWith; | |
43 using testing::WithArgs; | |
44 using testing::_; | |
45 | |
46 namespace ntp_snippets { | |
47 | |
48 namespace { | |
49 | |
50 const char* kDifferentWiFiInterval = "2"; | |
51 | |
52 class MockHardScheduler : public RemoteSuggestionsHardScheduler { | |
53 public: | |
54 MOCK_METHOD2(Schedule, | |
55 bool(base::TimeDelta period_wifi, | |
56 base::TimeDelta period_fallback)); | |
57 MOCK_METHOD0(Unschedule, bool()); | |
58 }; | |
59 | |
60 class MockUpdater : public RemoteSuggestionsScheduler::Updater { | |
61 public: | |
62 MOCK_METHOD0(UpdateRemoteSuggestionsBySchedule, void()); | |
63 }; | |
64 | |
65 } // namespace | |
66 | |
67 class RemoteSuggestionsSchedulerTest : public ::testing::Test { | |
68 public: | |
69 RemoteSuggestionsSchedulerTest() | |
70 : user_classifier_(/*pref_service=*/nullptr) { | |
71 RemoteSuggestionsScheduler::RegisterProfilePrefs( | |
72 utils_.pref_service()->registry()); | |
73 } | |
74 | |
75 std::unique_ptr<RemoteSuggestionsScheduler> MakeScheduler(bool enabled) { | |
76 auto scheduler = base::MakeUnique<RemoteSuggestionsScheduler>( | |
77 &mock_scheduler(), &user_classifier_, utils_.pref_service()); | |
78 | |
79 scheduler->SetUpdater(&updater()); | |
tschumann
2016/12/15 19:27:01
&updater_
jkrcal
2016/12/20 16:39:45
Not relevant any more.
| |
80 | |
81 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.
| |
82 scheduler->Schedule(); | |
83 } else { | |
84 scheduler->Unschedule(); | |
85 } | |
86 return scheduler; | |
87 } | |
88 | |
89 protected: | |
90 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.
| |
91 MockUpdater& updater() { return updater_; } | |
92 | |
93 private: | |
94 test::RemoteSuggestionsTestUtils utils_; | |
95 UserClassifier user_classifier_; | |
96 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.
| |
97 NiceMock<MockUpdater> updater_; | |
98 | |
99 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsSchedulerTest); | |
100 }; | |
101 | |
102 TEST_F(RemoteSuggestionsSchedulerTest, SchedulesOnStart) { | |
103 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.
| |
104 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.
| |
105 | |
106 auto scheduler = MakeScheduler(/*enabled=*/true); | |
107 } | |
108 | |
109 TEST_F(RemoteSuggestionsSchedulerTest, UnschedulesAfterBeingScheduled) { | |
110 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
111 auto scheduler = MakeScheduler(/*enabled=*/true); | |
112 | |
113 Mock::VerifyAndClearExpectations(&mock_scheduler()); | |
114 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1); | |
115 scheduler->Unschedule(); | |
116 } | |
117 | |
118 TEST_F(RemoteSuggestionsSchedulerTest, DoesNotUnscheduleOnShutdown) { | |
119 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
120 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); | |
121 | |
122 auto scheduler = MakeScheduler(/*enabled=*/true); | |
123 | |
124 scheduler.reset(); | |
125 } | |
126 | |
127 TEST_F(RemoteSuggestionsSchedulerTest, UnscheduleOnlyOnce) { | |
128 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
129 auto scheduler = MakeScheduler(/*enabled=*/true); | |
130 | |
131 // Unschedule for the first time. | |
132 Mock::VerifyAndClearExpectations(&mock_scheduler()); | |
133 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1); | |
134 scheduler->Unschedule(); | |
135 | |
136 // When unscheduling again, we should not get any |Schedule| calls: | |
137 // The tasks are already unscheduled, so no need to do it again. | |
138 Mock::VerifyAndClearExpectations(&mock_scheduler()); | |
139 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(0); | |
140 scheduler->Unschedule(); | |
141 } | |
142 | |
143 TEST_F(RemoteSuggestionsSchedulerTest, ScheduleOnlyOnce) { | |
144 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
145 | |
146 auto scheduler = MakeScheduler(/*enabled=*/true); | |
147 | |
148 // When scheduling again, we should not get any |Schedule| calls: | |
149 // The tasks are already scheduled with the correct intervals, so no need to | |
150 // do it again. | |
151 Mock::VerifyAndClearExpectations(&mock_scheduler()); | |
152 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0); | |
153 scheduler->Schedule(); | |
154 } | |
155 | |
156 TEST_F(RemoteSuggestionsSchedulerTest, RescheduleWhenWifiParamChanges) { | |
157 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
158 auto scheduler = MakeScheduler(/*enabled=*/true); | |
159 | |
160 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is | |
161 // null. Change the wifi interval for this class. | |
162 variations::testing::VariationParamsManager params_manager( | |
163 ntp_snippets::kStudyName, | |
164 {{"fetching_interval_hours-wifi-active_ntp_user", | |
165 kDifferentWiFiInterval}}, | |
166 {kArticleSuggestionsFeature.name}); | |
167 | |
168 Mock::VerifyAndClearExpectations(&mock_scheduler()); | |
169 // After the change of a paramter, it should reschedule. | |
170 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
171 scheduler->Schedule(); | |
172 } | |
173 | |
174 TEST_F(RemoteSuggestionsSchedulerTest, RescheduleWhenFallbackParamChanges) { | |
175 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
176 auto scheduler = MakeScheduler(/*enabled=*/true); | |
177 | |
178 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is | |
179 // null. Change the wifi interval for this class. | |
180 variations::testing::VariationParamsManager params_manager( | |
181 ntp_snippets::kStudyName, | |
182 {{"fetching_interval_hours-fallback-active_ntp_user", | |
183 kDifferentWiFiInterval}}, | |
184 {kArticleSuggestionsFeature.name}); | |
185 | |
186 Mock::VerifyAndClearExpectations(&mock_scheduler()); | |
187 // After the change of a paramter, it should reschedule. | |
188 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
189 scheduler->Schedule(); | |
190 } | |
191 | |
192 TEST_F(RemoteSuggestionsSchedulerTest, HandlesForcedReschedules) { | |
193 { | |
194 InSequence s; | |
195 // The initial scheduling. | |
196 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
197 // Forced rescheduling. | |
198 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1); | |
199 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
200 } | |
201 | |
202 auto scheduler = MakeScheduler(/*enabled=*/true); | |
203 // Forced reschedule | |
204 scheduler->Unschedule(); | |
205 scheduler->Schedule(); | |
206 } | |
207 | |
208 TEST_F(RemoteSuggestionsSchedulerTest, ReschedulesAfterSuccessfulUpdate) { | |
209 // The initial scheduling. | |
210 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
211 auto scheduler = MakeScheduler(/*enabled=*/true); | |
212 Mock::VerifyAndClearExpectations(&mock_scheduler()); | |
213 | |
214 // Simulate a succesfull update. | |
215 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
216 scheduler->PerformHardUpdate(); | |
217 scheduler->OnSuccessfulUpdate(); | |
218 } | |
219 | |
220 TEST_F(RemoteSuggestionsSchedulerTest, DoesNotRescheduleAfterFailedUpdate) { | |
221 // The initial scheduling. | |
222 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
223 auto scheduler = MakeScheduler(/*enabled=*/true); | |
224 Mock::VerifyAndClearExpectations(&mock_scheduler()); | |
225 | |
226 // Simulate a succesfull update. | |
227 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(0); | |
228 scheduler->PerformHardUpdate(); | |
229 // Failed -> do not call OnSuccessfulUpdate(). | |
230 } | |
231 | |
232 TEST_F(RemoteSuggestionsSchedulerTest, CallsUpdater) { | |
233 // The initial scheduling. | |
234 EXPECT_CALL(mock_scheduler(), Schedule(_, _)).Times(1); | |
235 auto scheduler = MakeScheduler(/*enabled=*/true); | |
236 | |
237 // Simulate a succesfull update. | |
238 EXPECT_CALL(updater(), UpdateRemoteSuggestionsBySchedule()).Times(1); | |
239 scheduler->PerformHardUpdate(); | |
240 } | |
241 | |
242 } // namespace ntp_snippets | |
OLD | NEW |