OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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/persistent_scheduler.h" | |
24 #include "components/ntp_snippets/remote/remote_suggestions_provider.h" | |
25 #include "components/ntp_snippets/remote/test_utils.h" | |
26 #include "components/ntp_snippets/user_classifier.h" | |
27 #include "components/prefs/testing_pref_service.h" | |
28 #include "components/variations/variations_params_manager.h" | |
29 #include "testing/gmock/include/gmock/gmock.h" | |
30 #include "testing/gtest/include/gtest/gtest.h" | |
31 | |
32 using testing::ElementsAre; | |
33 using testing::Eq; | |
34 using testing::InSequence; | |
35 using testing::Invoke; | |
36 using testing::IsEmpty; | |
37 using testing::Mock; | |
38 using testing::MockFunction; | |
39 using testing::NiceMock; | |
40 using testing::Not; | |
41 using testing::SaveArg; | |
42 using testing::SizeIs; | |
43 using testing::StartsWith; | |
44 using testing::WithArgs; | |
45 using testing::_; | |
46 | |
47 namespace ntp_snippets { | |
48 | |
49 namespace { | |
50 | |
51 const char* kDifferentWiFiInterval = "2"; | |
52 | |
53 class MockPersistentScheduler : public PersistentScheduler { | |
54 public: | |
55 MOCK_METHOD2(Schedule, | |
56 bool(base::TimeDelta period_wifi, | |
57 base::TimeDelta period_fallback)); | |
58 MOCK_METHOD0(Unschedule, bool()); | |
59 }; | |
60 | |
61 class MockRemoteSuggestionsProvider : public RemoteSuggestionsProvider { | |
62 public: | |
63 MOCK_METHOD2(Schedule, | |
64 bool(base::TimeDelta period_wifi, | |
65 base::TimeDelta period_fallback)); | |
66 MOCK_METHOD0(Unschedule, bool()); | |
67 }; | |
68 | |
69 } // namespace | |
70 | |
71 class SchedulingRemoteSuggestionsProviderTest : public ::testing::Test { | |
72 public: | |
73 SchedulingRemoteSuggestionsProviderTest() | |
74 : user_classifier_(/*pref_service=*/nullptr) { | |
75 SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs( | |
76 utils_.pref_service()->registry()); | |
77 } | |
78 | |
79 std::unique_ptr<SchedulingRemoteSuggestionsProvider> MakeProvider { | |
80 auto provider = base::MakeUnique<MockRemoteSuggestionsProvider>(); | |
81 provider_ = provider_.get(); | |
82 | |
83 auto scheduling_provider = | |
84 base::MakeUnique<SchedulingRemoteSuggestionsProvider>( | |
85 /*observer=*/nullptr, /*category_factory=*/nullptr, | |
86 std::move(provider), mock_persistent_scheduler(), &user_classifier_, | |
87 utils_.pref_service()); | |
88 return scheduler; | |
89 } | |
90 | |
91 protected: | |
92 MockPersistentScheduler* mock_persistent_scheduler() { | |
93 return &persistent_scheduler_; | |
94 } | |
95 | |
96 private: | |
97 test::RemoteSuggestionsTestUtils utils_; | |
98 UserClassifier user_classifier_; | |
99 NiceMock<MockPersistentScheduler> persistent_scheduler_; | |
100 NiceMock<MockUpdater> updater_; | |
101 MockRemoteSuggestionsProvider* provider_; | |
102 | |
103 DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsSchedulerTest); | |
104 }; | |
105 | |
106 | |
107 | |
108 TEST_F(RemoteSuggestionsProviderTest, DontRescheduleAfterFailedFetch) { | |
109 // We should get two |Schedule| calls: The first when initialization | |
110 // completes, the second one after the automatic (since the service doesn't | |
111 // have any data yet) fetch finishes. | |
112 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)).Times(2); | |
113 auto service = MakeSnippetsService(); | |
114 | |
115 // A failed fetch should NOT trigger another |Schedule|. | |
116 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)).Times(0); | |
117 LoadFromJSONString(service.get(), GetTestJson({GetInvalidSnippet()})); | |
118 } | |
119 | |
120 TEST_F(RemoteSuggestionsProviderTest, RescheduleOnStateChange) { | |
121 { | |
122 InSequence s; | |
123 // Initial startup. | |
124 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)).Times(2); | |
125 // Service gets disabled. | |
126 EXPECT_CALL(mock_persistent_scheduler(), Unschedule()); | |
127 // Service gets enabled again. | |
128 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)).Times(2); | |
129 } | |
130 auto service = MakeSnippetsService(); | |
131 ASSERT_TRUE(service->ready()); | |
132 | |
133 service->OnStatusChanged(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN, | |
134 RemoteSuggestionsStatus::EXPLICITLY_DISABLED); | |
135 ASSERT_FALSE(service->ready()); | |
136 base::RunLoop().RunUntilIdle(); | |
137 | |
138 service->OnStatusChanged(RemoteSuggestionsStatus::EXPLICITLY_DISABLED, | |
139 RemoteSuggestionsStatus::ENABLED_AND_SIGNED_OUT); | |
140 ASSERT_TRUE(service->ready()); | |
141 base::RunLoop().RunUntilIdle(); | |
142 } | |
143 | |
144 | |
tschumann
2016/12/19 11:07:19
drop consecutive blank lines.
same in line 106/107
jkrcal
2016/12/20 16:39:47
Done.
| |
145 | |
146 | |
147 TEST_F(RemoteSuggestionsSchedulerTest, SchedulesOnStart) { | |
148 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
149 EXPECT_CALL(mock_persistent_scheduler(), Unschedule()).Times(0); | |
150 | |
151 auto scheduler = MakeScheduler(/*enabled=*/true); | |
152 } | |
153 | |
154 TEST_F(RemoteSuggestionsSchedulerTest, UnschedulesAfterBeingScheduled) { | |
155 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
156 auto scheduler = MakeScheduler(/*enabled=*/true); | |
157 | |
158 Mock::VerifyAndClearExpectations(mock_persistent_scheduler()); | |
159 EXPECT_CALL(mock_persistent_scheduler(), Unschedule()); | |
160 scheduler->Unschedule(); | |
161 } | |
162 | |
163 TEST_F(RemoteSuggestionsSchedulerTest, DoesNotUnscheduleOnShutdown) { | |
164 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
165 EXPECT_CALL(mock_persistent_scheduler(), Unschedule()).Times(0); | |
166 | |
167 auto scheduler = MakeScheduler(/*enabled=*/true); | |
168 | |
169 // The scheduler will go out of scope and gets destroyed. | |
170 } | |
171 | |
172 TEST_F(RemoteSuggestionsSchedulerTest, UnschedulesOnlyOnce) { | |
173 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
174 auto scheduler = MakeScheduler(/*enabled=*/true); | |
175 | |
176 // Unschedule for the first time. | |
177 Mock::VerifyAndClearExpectations(mock_persistent_scheduler()); | |
178 EXPECT_CALL(mock_persistent_scheduler(), Unschedule()); | |
179 scheduler->Unschedule(); | |
180 | |
181 // When unscheduling again, we should not get any |Schedule| calls: | |
182 // The tasks are already unscheduled, so no need to do it again. | |
183 Mock::VerifyAndClearExpectations(mock_persistent_scheduler()); | |
184 EXPECT_CALL(mock_persistent_scheduler(), Unschedule()).Times(0); | |
185 scheduler->Unschedule(); | |
186 } | |
187 | |
188 TEST_F(RemoteSuggestionsSchedulerTest, SchedulesOnlyOnce) { | |
189 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
190 | |
191 auto scheduler = MakeScheduler(/*enabled=*/true); | |
192 | |
193 // When scheduling again, we should not get any |Schedule| calls: | |
194 // The tasks are already scheduled with the correct intervals, so no need to | |
195 // do it again. | |
196 Mock::VerifyAndClearExpectations(mock_persistent_scheduler()); | |
197 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)).Times(0); | |
198 scheduler->Schedule(); | |
199 } | |
200 | |
201 TEST_F(RemoteSuggestionsSchedulerTest, ReschedulesWhenWifiParamChanges) { | |
202 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
203 auto scheduler = MakeScheduler(/*enabled=*/true); | |
204 | |
205 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is | |
206 // null. Change the wifi interval for this class. | |
207 variations::testing::VariationParamsManager params_manager( | |
208 ntp_snippets::kStudyName, | |
209 {{"fetching_interval_hours-wifi-active_ntp_user", | |
210 kDifferentWiFiInterval}}, | |
211 {kArticleSuggestionsFeature.name}); | |
212 | |
213 Mock::VerifyAndClearExpectations(mock_persistent_scheduler()); | |
214 // After the change of a paramter, it should reschedule. | |
215 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
216 scheduler->Schedule(); | |
217 } | |
218 | |
219 TEST_F(RemoteSuggestionsSchedulerTest, ReschedulesWhenFallbackParamChanges) { | |
220 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
221 auto scheduler = MakeScheduler(/*enabled=*/true); | |
222 | |
223 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is | |
224 // null. Change the wifi interval for this class. | |
225 variations::testing::VariationParamsManager params_manager( | |
226 ntp_snippets::kStudyName, | |
227 {{"fetching_interval_hours-fallback-active_ntp_user", | |
228 kDifferentWiFiInterval}}, | |
229 {kArticleSuggestionsFeature.name}); | |
230 | |
231 Mock::VerifyAndClearExpectations(mock_persistent_scheduler()); | |
232 // After the change of a paramter, it should reschedule. | |
233 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
234 scheduler->Schedule(); | |
235 } | |
236 | |
237 TEST_F(RemoteSuggestionsSchedulerTest, HandlesForcedReschedules) { | |
238 { | |
239 InSequence s; | |
240 // The initial scheduling. | |
241 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
242 // Forced rescheduling. | |
243 EXPECT_CALL(mock_persistent_scheduler(), Unschedule()); | |
244 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
245 } | |
246 | |
247 auto scheduler = MakeScheduler(/*enabled=*/true); | |
248 // Forced reschedule | |
249 scheduler->Unschedule(); | |
250 scheduler->Schedule(); | |
251 } | |
252 | |
253 TEST_F(RemoteSuggestionsSchedulerTest, ReschedulesAfterSuccessfulUpdate) { | |
254 // The initial scheduling. | |
255 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
256 auto scheduler = MakeScheduler(/*enabled=*/true); | |
257 Mock::VerifyAndClearExpectations(mock_persistent_scheduler()); | |
258 | |
259 // Simulate a successful update. | |
260 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
261 scheduler->PerformHardUpdate(); | |
262 } | |
263 | |
264 TEST_F(RemoteSuggestionsSchedulerTest, DoesNotRescheduleAfterFailedUpdate) { | |
265 // The initial scheduling. | |
266 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
267 auto scheduler = MakeScheduler(/*enabled=*/true); | |
268 Mock::VerifyAndClearExpectations(mock_persistent_scheduler()); | |
269 | |
270 // Simulate a succesfull update. | |
271 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)).Times(0); | |
272 scheduler->PerformHardUpdate(); | |
273 // Failed -> do not call OnSuccessfulUpdate(). | |
274 } | |
275 | |
276 TEST_F(RemoteSuggestionsSchedulerTest, CallsUpdater) { | |
277 // The initial scheduling. | |
278 EXPECT_CALL(mock_persistent_scheduler(), Schedule(_, _)); | |
279 auto scheduler = MakeScheduler(/*enabled=*/true); | |
280 | |
281 // Simulate a succesfull update. | |
282 EXPECT_CALL(updater(), UpdateRemoteSuggestionsBySchedule()); | |
283 scheduler->PerformHardUpdate(); | |
284 } | |
285 | |
286 } // namespace ntp_snippets | |
OLD | NEW |