Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1861)

Side by Side Diff: components/ntp_snippets/remote/scheduling_remote_suggestions_provider_unittest.cc

Issue 2774663002: [Remote suggestions] Refactor the scheduler (Closed)
Patch Set: Marc's comments #2 Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/test/simple_test_clock.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "base/time/clock.h"
21 #include "base/time/default_clock.h"
22 #include "base/time/time.h"
23 #include "components/ntp_snippets/features.h"
24 #include "components/ntp_snippets/ntp_snippets_constants.h"
25 #include "components/ntp_snippets/pref_names.h"
26 #include "components/ntp_snippets/remote/persistent_scheduler.h"
27 #include "components/ntp_snippets/remote/remote_suggestions_provider.h"
28 #include "components/ntp_snippets/remote/test_utils.h"
29 #include "components/ntp_snippets/status.h"
30 #include "components/ntp_snippets/user_classifier.h"
31 #include "components/prefs/pref_registry_simple.h"
32 #include "components/prefs/testing_pref_service.h"
33 #include "components/variations/variations_params_manager.h"
34 #include "components/web_resource/web_resource_pref_names.h"
35 #include "testing/gmock/include/gmock/gmock.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37
38 using testing::ElementsAre;
39 using testing::Eq;
40 using testing::Field;
41 using testing::InSequence;
42 using testing::Invoke;
43 using testing::IsEmpty;
44 using testing::Mock;
45 using testing::MockFunction;
46 using testing::Not;
47 using testing::Return;
48 using testing::SaveArg;
49 using testing::SaveArgPointee;
50 using testing::SizeIs;
51 using testing::StartsWith;
52 using testing::StrictMock;
53 using testing::WithArgs;
54 using testing::_;
55
56 namespace ntp_snippets {
57
58 class RemoteSuggestionsFetcher;
59
60 namespace {
61
62 class MockPersistentScheduler : public PersistentScheduler {
63 public:
64 MOCK_METHOD2(Schedule,
65 bool(base::TimeDelta period_wifi,
66 base::TimeDelta period_fallback));
67 MOCK_METHOD0(Unschedule, bool());
68 };
69
70 // TODO(jkrcal): Move into its own library to reuse in other unit-tests?
71 class MockRemoteSuggestionsProvider : public RemoteSuggestionsProvider {
72 public:
73 MockRemoteSuggestionsProvider(Observer* observer)
74 : RemoteSuggestionsProvider(observer) {}
75
76 MOCK_METHOD1(SetRemoteSuggestionsScheduler,
77 void(RemoteSuggestionsScheduler*));
78
79 // Move-only params are not supported by GMock. We want to mock out
80 // RefetchInTheBackground() which takes a unique_ptr<>. Instead, we add a new
81 // mock function which takes a copy of the callback and override the
82 // RemoteSuggestionsProvider's method to forward the call into the new mock
83 // function.
84 void RefetchInTheBackground(
85 std::unique_ptr<RemoteSuggestionsProvider::FetchStatusCallback> callback)
86 override {
87 RefetchInTheBackground(*callback);
88 }
89 MOCK_METHOD1(RefetchInTheBackground,
90 void(RemoteSuggestionsProvider::FetchStatusCallback));
91
92 MOCK_CONST_METHOD0(suggestions_fetcher_for_debugging,
93 const RemoteSuggestionsFetcher*());
94
95 MOCK_METHOD1(GetCategoryStatus, CategoryStatus(Category));
96 MOCK_METHOD1(GetCategoryInfo, CategoryInfo(Category));
97 MOCK_METHOD3(ClearHistory,
98 void(base::Time begin,
99 base::Time end,
100 const base::Callback<bool(const GURL& url)>& filter));
101 MOCK_METHOD3(Fetch,
102 void(const Category&,
103 const std::set<std::string>&,
104 const FetchDoneCallback&));
105 MOCK_METHOD0(ReloadSuggestions, void());
106 MOCK_METHOD1(ClearCachedSuggestions, void(Category));
107 MOCK_METHOD1(ClearDismissedSuggestionsForDebugging, void(Category));
108 MOCK_METHOD1(DismissSuggestion, void(const ContentSuggestion::ID&));
109 MOCK_METHOD2(FetchSuggestionImage,
110 void(const ContentSuggestion::ID&, const ImageFetchedCallback&));
111 MOCK_METHOD2(GetDismissedSuggestionsForDebugging,
112 void(Category, const DismissedSuggestionsCallback&));
113 MOCK_METHOD0(OnSignInStateChanged, void());
114 };
115
116 } // namespace
117
118 class SchedulingRemoteSuggestionsProviderTest : public ::testing::Test {
119 public:
120 SchedulingRemoteSuggestionsProviderTest()
121 : // For the test we enabled all trigger types.
122 default_variation_params_{{"scheduler_trigger_types",
123 "persistent_scheduler_wake_up,ntp_opened,"
124 "browser_foregrounded,browser_cold_start"}},
125 params_manager_(ntp_snippets::kStudyName,
126 default_variation_params_,
127 {kArticleSuggestionsFeature.name}),
128 underlying_provider_(nullptr),
129 scheduling_provider_(nullptr),
130 user_classifier_(/*pref_service=*/nullptr,
131 base::MakeUnique<base::DefaultClock>()) {
132 SchedulingRemoteSuggestionsProvider::RegisterProfilePrefs(
133 utils_.pref_service()->registry());
134 RequestThrottler::RegisterProfilePrefs(utils_.pref_service()->registry());
135 // TODO(jkrcal) Create a static function in EulaAcceptedNotifier that
136 // registers this pref and replace the call in browser_process_impl.cc & in
137 // eula_accepted_notifier_unittest.cc with the new static function.
138 local_state_.registry()->RegisterBooleanPref(::prefs::kEulaAccepted, false);
139 ResetProvider();
140 }
141
142 void ResetProvider() {
143 auto underlying_provider =
144 base::MakeUnique<StrictMock<MockRemoteSuggestionsProvider>>(
145 /*observer=*/nullptr);
146 underlying_provider_ = underlying_provider.get();
147
148 auto test_clock = base::MakeUnique<base::SimpleTestClock>();
149 test_clock_ = test_clock.get();
150 test_clock_->SetNow(base::Time::Now());
151
152 scheduling_provider_ =
153 base::MakeUnique<SchedulingRemoteSuggestionsProvider>(
154 /*observer=*/nullptr, std::move(underlying_provider),
155 &persistent_scheduler_, &user_classifier_, utils_.pref_service(),
156 &local_state_, std::move(test_clock));
157 }
158
159 void SetVariationParameter(const std::string& param_name,
160 const std::string& param_value) {
161 std::map<std::string, std::string> params = default_variation_params_;
162 params[param_name] = param_value;
163
164 params_manager_.ClearAllVariationParams();
165 params_manager_.SetVariationParamsWithFeatureAssociations(
166 ntp_snippets::kStudyName, params,
167 {ntp_snippets::kArticleSuggestionsFeature.name});
168 }
169
170 bool IsEulaNotifierAvailable() {
171 // Create() returns a unique_ptr, so this is no leak.
172 return web_resource::EulaAcceptedNotifier::Create(&local_state_) != nullptr;
173 }
174
175 void SetEulaAcceptedPref() {
176 local_state_.SetBoolean(::prefs::kEulaAccepted, true);
177 }
178
179 // GMock cannot deal with move-only types. We need to pass the vector to the
180 // mock function as const ref using this wrapper callback.
181 void FetchDoneWrapper(
182 MockFunction<void(Status status_code,
183 const std::vector<ContentSuggestion>& suggestions)>*
184 fetch_done,
185 Status status_code,
186 std::vector<ContentSuggestion> suggestions) {
187 fetch_done->Call(status_code, suggestions);
188 }
189
190 protected:
191 std::map<std::string, std::string> default_variation_params_;
192 variations::testing::VariationParamsManager params_manager_;
193 StrictMock<MockPersistentScheduler> persistent_scheduler_;
194 StrictMock<MockRemoteSuggestionsProvider>* underlying_provider_;
195 std::unique_ptr<SchedulingRemoteSuggestionsProvider> scheduling_provider_;
196 base::SimpleTestClock* test_clock_;
197
198 void ActivateUnderlyingProvider() {
199 SetEulaAcceptedPref();
200 scheduling_provider_->OnProviderActivated();
201 }
202
203 void InactivateUnderlyingProvider() {
204 scheduling_provider_->OnProviderDeactivated();
205 }
206
207 private:
208 test::RemoteSuggestionsTestUtils utils_;
209 UserClassifier user_classifier_;
210 TestingPrefServiceSimple local_state_;
211
212 DISALLOW_COPY_AND_ASSIGN(SchedulingRemoteSuggestionsProviderTest);
213 };
214
215 TEST_F(SchedulingRemoteSuggestionsProviderTest,
216 ShouldIgnoreSignalsWhenNotEnabled) {
217 scheduling_provider_->OnPersistentSchedulerWakeUp();
218 scheduling_provider_->OnNTPOpened();
219 scheduling_provider_->OnBrowserForegrounded();
220 scheduling_provider_->OnBrowserColdStart();
221 }
222
223 TEST_F(SchedulingRemoteSuggestionsProviderTest,
224 ShouldIgnoreEulaStateOnPlatformsWhereNotAvaiable) {
225 // Only run this tests on platforms that don't support Eula.
226 if (IsEulaNotifierAvailable()) {
227 return;
228 }
229
230 // Activating the provider should schedule the persistent background fetches.
231 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
232 scheduling_provider_->OnProviderActivated();
233
234 // Verify fetches get triggered.
235 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
236 scheduling_provider_->OnPersistentSchedulerWakeUp();
237 }
238
239 TEST_F(SchedulingRemoteSuggestionsProviderTest,
240 ShouldIgnoreSignalsWhenEulaNotAccepted) {
241 // Only run this tests on platforms supporting Eula.
242 if (!IsEulaNotifierAvailable()) {
243 return;
244 }
245 // Activating the provider should schedule the persistent background fetches.
246 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
247 scheduling_provider_->OnProviderActivated();
248
249 // All signals are ignored because of Eula not being accepted.
250 scheduling_provider_->OnPersistentSchedulerWakeUp();
251 scheduling_provider_->OnNTPOpened();
252 scheduling_provider_->OnBrowserForegrounded();
253 scheduling_provider_->OnBrowserColdStart();
254 }
255
256 TEST_F(SchedulingRemoteSuggestionsProviderTest,
257 ShouldFetchWhenEulaGetsAccepted) {
258 // Only run this tests on platforms supporting Eula.
259 if (!IsEulaNotifierAvailable()) {
260 return;
261 }
262 // Activating the provider should schedule the persistent background fetches.
263 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
264 scheduling_provider_->OnProviderActivated();
265
266 // Make one (ignored) call to make sure we are interested in eula state.
267 scheduling_provider_->OnPersistentSchedulerWakeUp();
268
269 // Accepting Eula afterwards results in a background fetch.
270 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
271 SetEulaAcceptedPref();
272 }
273
274 TEST_F(SchedulingRemoteSuggestionsProviderTest,
275 ShouldIgnoreSignalsWhenDisabledByParam) {
276 // First set an empty list of allowed trigger types.
277 SetVariationParameter("scheduler_trigger_types", "-");
278 ResetProvider();
279
280 // Then enable the scheduler.
281 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
282 ActivateUnderlyingProvider();
283
284 scheduling_provider_->OnPersistentSchedulerWakeUp();
285 scheduling_provider_->OnNTPOpened();
286 scheduling_provider_->OnBrowserForegrounded();
287 scheduling_provider_->OnBrowserColdStart();
288 }
289
290 TEST_F(SchedulingRemoteSuggestionsProviderTest,
291 ShouldHandleEmptyParamForTriggerTypes) {
292 // First set an empty param for allowed trigger types -> should result in the
293 // default list.
294 SetVariationParameter("scheduler_trigger_types", "");
295 ResetProvider();
296
297 // Then enable the scheduler.
298 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
299 ActivateUnderlyingProvider();
300
301 // For instance, persistent scheduler wake up should be enabled by default.
302 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
303 scheduling_provider_->OnPersistentSchedulerWakeUp();
304 }
305
306 TEST_F(SchedulingRemoteSuggestionsProviderTest,
307 ShouldHandleIncorrentParamForTriggerTypes) {
308 // First set an invalid list of allowed trigger types.
309 SetVariationParameter("scheduler_trigger_types", "ntp_opened,foo;");
310 ResetProvider();
311
312 // Then enable the scheduler.
313 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
314 ActivateUnderlyingProvider();
315
316 // For instance, persistent scheduler wake up should be enabled by default.
317 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
318 scheduling_provider_->OnPersistentSchedulerWakeUp();
319 }
320
321 TEST_F(SchedulingRemoteSuggestionsProviderTest,
322 ShouldFetchOnPersistentSchedulerWakeUp) {
323 // First set only this type to be allowed.
324 SetVariationParameter("scheduler_trigger_types",
325 "persistent_scheduler_wake_up");
326 ResetProvider();
327
328 // Then enable the scheduler.
329 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
330 ActivateUnderlyingProvider();
331
332 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
333 scheduling_provider_->OnPersistentSchedulerWakeUp();
334 }
335
336 TEST_F(SchedulingRemoteSuggestionsProviderTest,
337 ShouldFetchOnPersistentSchedulerWakeUpRepeated) {
338 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
339 {
340 InSequence s;
341 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
342 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
343 .WillOnce(SaveArg<0>(&signal_fetch_done));
344 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
345 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
346 }
347 // First enable the scheduler -- calling Schedule() for the first time.
348 ActivateUnderlyingProvider();
349 // Make the first persistent fetch successful -- calling Schedule() again.
350 scheduling_provider_->OnPersistentSchedulerWakeUp();
351 signal_fetch_done.Run(Status::Success());
352 // Make the second fetch.
353 scheduling_provider_->OnPersistentSchedulerWakeUp();
354 }
355
356 TEST_F(SchedulingRemoteSuggestionsProviderTest,
357 ShouldNotTriggerBackgroundFetchIfAlreadyInProgess) {
358 {
359 InSequence s;
360 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
361 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
362 // RefetchInTheBackground is not called after the second trigger.
363 }
364 // First enable the scheduler -- calling Schedule() for the first time.
365 ActivateUnderlyingProvider();
366 // Make the first persistent fetch never finish.
367 scheduling_provider_->OnPersistentSchedulerWakeUp();
368 // Make the second fetch.
369 scheduling_provider_->OnPersistentSchedulerWakeUp();
370 }
371
372 TEST_F(SchedulingRemoteSuggestionsProviderTest,
373 ShouldFetchOnNTPOpenedForTheFirstTime) {
374 // First set only this type to be allowed.
375 SetVariationParameter("scheduler_trigger_types", "ntp_opened");
376 ResetProvider();
377
378 // Then enable the scheduler.
379 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
380 ActivateUnderlyingProvider();
381
382 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
383 scheduling_provider_->OnNTPOpened();
384 }
385
386 TEST_F(SchedulingRemoteSuggestionsProviderTest,
387 ShouldFetchOnBrowserForegroundedForTheFirstTime) {
388 // First set only this type to be allowed.
389 SetVariationParameter("scheduler_trigger_types", "browser_foregrounded");
390 ResetProvider();
391
392 // Then enable the scheduler.
393 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
394 ActivateUnderlyingProvider();
395
396 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
397 scheduling_provider_->OnBrowserForegrounded();
398 }
399
400 TEST_F(SchedulingRemoteSuggestionsProviderTest,
401 ShouldFetchOnBrowserColdStartForTheFirstTime) {
402 // First set only this type to be allowed.
403 SetVariationParameter("scheduler_trigger_types", "browser_cold_start");
404 ResetProvider();
405
406 // Then enable the scheduler.
407 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
408 ActivateUnderlyingProvider();
409
410 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
411 scheduling_provider_->OnBrowserColdStart();
412 }
413
414 TEST_F(SchedulingRemoteSuggestionsProviderTest,
415 ShouldNotFetchOnNTPOpenedAfterSuccessfulSoftFetch) {
416 // First enable the scheduler; the second Schedule is called after the
417 // successful fetch.
418 EXPECT_CALL(persistent_scheduler_, Schedule(_, _)).Times(2);
419 ActivateUnderlyingProvider();
420
421 // Make the first soft fetch successful.
422 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
423 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
424 .WillOnce(SaveArg<0>(&signal_fetch_done));
425 scheduling_provider_->OnNTPOpened();
426 signal_fetch_done.Run(Status::Success());
427 // The second call is ignored if it happens right after the first one.
428 scheduling_provider_->OnNTPOpened();
429 }
430
431 TEST_F(SchedulingRemoteSuggestionsProviderTest,
432 ShouldNotFetchOnNTPOpenedAfterSuccessfulPersistentFetch) {
433 // First enable the scheduler; the second Schedule is called after the
434 // successful fetch.
435 EXPECT_CALL(persistent_scheduler_, Schedule(_, _)).Times(2);
436 ActivateUnderlyingProvider();
437
438 // Make the first persistent fetch successful.
439 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
440 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
441 .WillOnce(SaveArg<0>(&signal_fetch_done));
442 scheduling_provider_->OnPersistentSchedulerWakeUp();
443 signal_fetch_done.Run(Status::Success());
444 // The second call is ignored if it happens right after the first one.
445 scheduling_provider_->OnNTPOpened();
446 }
447
448 TEST_F(SchedulingRemoteSuggestionsProviderTest,
449 ShouldNotFetchOnNTPOpenedAfterFailedSoftFetch) {
450 // First enable the scheduler.
451 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
452 ActivateUnderlyingProvider();
453
454 // Make the first soft fetch failed.
455 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
456 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
457 .WillOnce(SaveArg<0>(&signal_fetch_done));
458 scheduling_provider_->OnNTPOpened();
459 signal_fetch_done.Run(Status(StatusCode::PERMANENT_ERROR, ""));
460
461 // The second call is ignored if it happens right after the first one.
462 scheduling_provider_->OnNTPOpened();
463 }
464
465 TEST_F(SchedulingRemoteSuggestionsProviderTest,
466 ShouldNotFetchOnNTPOpenedAfterFailedPersistentFetch) {
467 // First enable the scheduler.
468 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
469 ActivateUnderlyingProvider();
470
471 // Make the first persistent fetch failed.
472 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
473 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
474 .WillOnce(SaveArg<0>(&signal_fetch_done));
475 scheduling_provider_->OnPersistentSchedulerWakeUp();
476 signal_fetch_done.Run(Status(StatusCode::PERMANENT_ERROR, ""));
477
478 // The second call is ignored if it happens right after the first one.
479 scheduling_provider_->OnNTPOpened();
480 }
481
482 TEST_F(SchedulingRemoteSuggestionsProviderTest,
483 ShouldFetchAgainOnBrowserForgroundLaterAgain) {
484 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
485 {
486 InSequence s;
487 // Initial scheduling after being enabled.
488 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
489 // The first call to NTPOpened results in a fetch.
490 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
491 .WillOnce(SaveArg<0>(&signal_fetch_done));
492 // Rescheduling after a succesful fetch.
493 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
494 // The second call to NTPOpened 2hrs later again results in a fetch.
495 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
496 }
497
498 // First enable the scheduler.
499 ActivateUnderlyingProvider();
500 // Make the first soft fetch successful.
501 scheduling_provider_->OnBrowserForegrounded();
502 signal_fetch_done.Run(Status::Success());
503 // Open NTP again after 2hrs.
504 test_clock_->Advance(base::TimeDelta::FromHours(2));
505 scheduling_provider_->OnBrowserForegrounded();
506 }
507
508 TEST_F(SchedulingRemoteSuggestionsProviderTest,
509 ShouldRescheduleOnRescheduleFetching) {
510 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
511 scheduling_provider_->RescheduleFetching();
512 }
513
514 TEST_F(SchedulingRemoteSuggestionsProviderTest, ShouldScheduleOnActivation) {
515 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
516 ActivateUnderlyingProvider();
517 }
518
519 TEST_F(SchedulingRemoteSuggestionsProviderTest,
520 ShouldUnscheduleOnLaterInactivation) {
521 {
522 InSequence s;
523 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
524 EXPECT_CALL(persistent_scheduler_, Unschedule());
525 }
526 ActivateUnderlyingProvider();
527 InactivateUnderlyingProvider();
528 }
529
530 TEST_F(SchedulingRemoteSuggestionsProviderTest,
531 ShouldScheduleOnLaterActivation) {
532 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
533 // There is no schedule yet, so inactivation does not trigger unschedule.
534 InactivateUnderlyingProvider();
535 ActivateUnderlyingProvider();
536 }
537
538 TEST_F(SchedulingRemoteSuggestionsProviderTest,
539 ShouldRescheduleAfterSuccessfulFetch) {
540 // First reschedule on becoming active.
541 EXPECT_CALL(persistent_scheduler_, Schedule(_, _)).Times(2);
542 ActivateUnderlyingProvider();
543
544 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
545 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
546 .WillOnce(SaveArg<0>(&signal_fetch_done));
547
548 // Trigger a fetch.
549 scheduling_provider_->OnPersistentSchedulerWakeUp();
550 // Second reschedule after a successful fetch.
551 signal_fetch_done.Run(Status::Success());
552 }
553
554 TEST_F(SchedulingRemoteSuggestionsProviderTest,
555 ShouldNotRescheduleAfterFailedFetch) {
556 // Only reschedule on becoming active.
557 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
558 ActivateUnderlyingProvider();
559
560 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
561 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
562 .WillOnce(SaveArg<0>(&signal_fetch_done));
563
564 // Trigger a fetch.
565 scheduling_provider_->OnPersistentSchedulerWakeUp();
566 // No furter reschedule after a failure.
567 signal_fetch_done.Run(Status(StatusCode::PERMANENT_ERROR, ""));
568 }
569
570 TEST_F(SchedulingRemoteSuggestionsProviderTest, ShouldScheduleOnlyOnce) {
571 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
572 ActivateUnderlyingProvider();
573 // No further call to Schedule on a second status callback.
574 ActivateUnderlyingProvider();
575 }
576
577 TEST_F(SchedulingRemoteSuggestionsProviderTest, ShouldUnscheduleOnlyOnce) {
578 {
579 InSequence s;
580 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
581 EXPECT_CALL(persistent_scheduler_, Unschedule());
582 }
583 // First schedule so that later we really unschedule.
584 ActivateUnderlyingProvider();
585 InactivateUnderlyingProvider();
586 // No further call to Unschedule on second status callback.
587 InactivateUnderlyingProvider();
588 }
589
590 TEST_F(SchedulingRemoteSuggestionsProviderTest,
591 ReschedulesWhenWifiParamChanges) {
592 EXPECT_CALL(persistent_scheduler_, Schedule(_, _)).Times(2);
593 ActivateUnderlyingProvider();
594
595 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
596 // null. Change the wifi interval for this class.
597 SetVariationParameter("fetching_interval_hours-wifi-active_ntp_user", "1.5");
598
599 // Schedule() should get called for the second time after params have changed.
600 ActivateUnderlyingProvider();
601 }
602
603 TEST_F(SchedulingRemoteSuggestionsProviderTest,
604 ReschedulesWhenFallbackParamChanges) {
605 EXPECT_CALL(persistent_scheduler_, Schedule(_, _)).Times(2);
606 ActivateUnderlyingProvider();
607
608 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
609 // null. Change the fallback interval for this class.
610 SetVariationParameter("fetching_interval_hours-fallback-active_ntp_user",
611 "1.5");
612
613 // Schedule() should get called for the second time after params have changed.
614 ActivateUnderlyingProvider();
615 }
616
617 TEST_F(SchedulingRemoteSuggestionsProviderTest,
618 ReschedulesWhenOnUsageEventParamChanges) {
619 EXPECT_CALL(persistent_scheduler_, Schedule(_, _)).Times(2);
620 ActivateUnderlyingProvider();
621
622 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
623 // null. Change the on usage interval for this class.
624 SetVariationParameter("soft_fetching_interval_hours-active-active_ntp_user",
625 "1.5");
626
627 // Schedule() should get called for the second time after params have changed.
628 ActivateUnderlyingProvider();
629 }
630
631 TEST_F(SchedulingRemoteSuggestionsProviderTest,
632 ReschedulesWhenOnNtpOpenedParamChanges) {
633 EXPECT_CALL(persistent_scheduler_, Schedule(_, _)).Times(2);
634 ActivateUnderlyingProvider();
635
636 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
637 // null. Change the fallback interval for this class.
638 SetVariationParameter("soft_on_ntp_opened_interval_hours-active_ntp_user",
639 "1.5");
640
641 // Schedule() should get called for the second time after params have changed.
642 ActivateUnderlyingProvider();
643 }
644
645 TEST_F(SchedulingRemoteSuggestionsProviderTest,
646 FetchIntervalForNtpOpenedTrigger) {
647 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
648 {
649 InSequence s;
650 // Initial scheduling after being enabled.
651 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
652 // The first call to NTPOpened results in a fetch.
653 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
654 .WillOnce(SaveArg<0>(&signal_fetch_done));
655 // Rescheduling after a succesful fetch.
656 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
657 // The third call to NTPOpened 35min later again results in a fetch.
658 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
659 }
660
661 ActivateUnderlyingProvider();
662
663 scheduling_provider_->OnNTPOpened();
664 signal_fetch_done.Run(Status::Success());
665
666 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER which uses a 2h time
667 // interval by default for soft backgroudn fetches on ntp open events.
668
669 // Open NTP again after 20min. This time no fetch is executed.
670 test_clock_->Advance(base::TimeDelta::FromMinutes(20));
671 scheduling_provider_->OnNTPOpened();
672
673 // Open NTP again after 101min (121min since first opened). Since the default
674 // time interval has passed refetch again.
675 test_clock_->Advance(base::TimeDelta::FromMinutes(101));
676 scheduling_provider_->OnNTPOpened();
677 }
678
679 TEST_F(SchedulingRemoteSuggestionsProviderTest,
680 OverrideFetchIntervalForNtpOpenedTrigger) {
681 // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
682 // null. Change the on usage interval for this class from 2h to 30min.
683 SetVariationParameter("soft_on_ntp_opened_interval_hours-active_ntp_user",
684 "0.5");
685
686 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
687 {
688 InSequence s;
689 // Initial scheduling after being enabled.
690 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
691 // The first call to NTPOpened results in a fetch.
692 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
693 .WillOnce(SaveArg<0>(&signal_fetch_done));
694 // Rescheduling after a succesful fetch.
695 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
696 // The third call to NTPOpened 35min later again results in a fetch.
697 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
698 }
699
700 ActivateUnderlyingProvider();
701
702 scheduling_provider_->OnNTPOpened();
703 signal_fetch_done.Run(Status::Success());
704
705 // Open NTP again after 20min. No fetch request is issues since the 30 min
706 // time interval has not passed yet.
707 test_clock_->Advance(base::TimeDelta::FromMinutes(20));
708 scheduling_provider_->OnNTPOpened();
709
710 // Open NTP again after 15min (35min since first opened)
711 test_clock_->Advance(base::TimeDelta::FromMinutes(15));
712 scheduling_provider_->OnNTPOpened();
713 }
714
715 TEST_F(SchedulingRemoteSuggestionsProviderTest,
716 ShouldBlockFetchingForSomeTimeAfterHistoryCleared) {
717 // First enable the scheduler -- this will trigger the persistent scheduling.
718 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
719 ActivateUnderlyingProvider();
720 // Clear the history.
721 scheduling_provider_->OnHistoryCleared();
722
723 // A trigger after 15 minutes is ignored.
724 test_clock_->Advance(base::TimeDelta::FromMinutes(15));
725 scheduling_provider_->OnBrowserForegrounded();
726
727 // A trigger after another 16 minutes is performed (more than 30m after
728 // clearing the history).
729 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
730 test_clock_->Advance(base::TimeDelta::FromMinutes(16));
731 scheduling_provider_->OnBrowserForegrounded();
732 }
733
734 TEST_F(SchedulingRemoteSuggestionsProviderTest,
735 ShouldImmediatelyFetchAfterSuggestionsCleared) {
736 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
737
738 // First enable the scheduler -- this will trigger the persistent scheduling.
739 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
740 ActivateUnderlyingProvider();
741
742 // The first trigger results in a fetch.
743 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
744 .WillOnce(SaveArg<0>(&signal_fetch_done));
745 scheduling_provider_->OnBrowserForegrounded();
746 // Make the fetch successful -- this results in rescheduling.
747 EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
748 signal_fetch_done.Run(Status::Success());
749
750 // Clear the suggestions - results in an immediate fetch.
751 EXPECT_CALL(*underlying_provider_, ReloadSuggestions());
752 scheduling_provider_->OnSuggestionsCleared();
753 }
754
755 TEST_F(SchedulingRemoteSuggestionsProviderTest,
756 ShouldThrottleInteractiveRequests) {
757 // Change the quota for interactive requests ("active NTP user" is the default
758 // class in tests).
759 SetVariationParameter("interactive_quota_SuggestionFetcherActiveNTPUser",
760 "10");
761 ResetProvider();
762
763 Category category = Category::FromKnownCategory(KnownCategories::ARTICLES);
764 std::set<std::string> known_suggestions;
765
766 // Both Fetch(..) and ReloadSuggestions() consume the same quota. As long as
767 // the quota suffices, the call gets through.
768 EXPECT_CALL(*underlying_provider_, ReloadSuggestions()).Times(5);
769 for (int x = 0; x < 5; ++x) {
770 scheduling_provider_->ReloadSuggestions();
771 }
772
773 // Expect underlying provider being called and store the callback to inform
774 // scheduling provider.
775 FetchDoneCallback signal_fetch_done_from_underlying_provider;
776 EXPECT_CALL(*underlying_provider_, Fetch(_, _, _))
777 .Times(5)
778 .WillRepeatedly(SaveArg<2>(&signal_fetch_done_from_underlying_provider));
779 // Expect scheduling provider to pass the information through.
780 MockFunction<void(Status status_code,
781 const std::vector<ContentSuggestion>& suggestions)>
782 fetch_done_from_scheduling_provider;
783 EXPECT_CALL(fetch_done_from_scheduling_provider,
784 Call(Field(&Status::code, StatusCode::SUCCESS), _))
785 .Times(5);
786 // Scheduling is not activated, each successful fetch results in Unschedule().
787 EXPECT_CALL(persistent_scheduler_, Unschedule()).Times(5);
788 for (int x = 0; x < 5; ++x) {
789 scheduling_provider_->Fetch(
790 category, known_suggestions,
791 base::Bind(&SchedulingRemoteSuggestionsProviderTest::FetchDoneWrapper,
792 base::Unretained(this),
793 &fetch_done_from_scheduling_provider));
794 // Inform scheduling provider the fetc is successful (with no suggestions).
795 signal_fetch_done_from_underlying_provider.Run(
796 Status::Success(), std::vector<ContentSuggestion>{});
797 }
798
799 // When the quota expires, it is blocked by the scheduling provider, directly
800 // calling the callback.
801 EXPECT_CALL(fetch_done_from_scheduling_provider,
802 Call(Field(&Status::code, StatusCode::TEMPORARY_ERROR), _));
803 scheduling_provider_->ReloadSuggestions();
804 scheduling_provider_->Fetch(
805 category, known_suggestions,
806 base::Bind(&SchedulingRemoteSuggestionsProviderTest::FetchDoneWrapper,
807 base::Unretained(this), &fetch_done_from_scheduling_provider));
808 }
809
810 TEST_F(SchedulingRemoteSuggestionsProviderTest,
811 ShouldThrottleNonInteractiveRequests) {
812 // Change the quota for interactive requests ("active NTP user" is the default
813 // class in tests).
814 SetVariationParameter("quota_SuggestionFetcherActiveNTPUser", "5");
815 ResetProvider();
816
817 // One scheduling on start, 5 times after successful fetches.
818 EXPECT_CALL(persistent_scheduler_, Schedule(_, _)).Times(6);
819
820 // First enable the scheduler -- this will trigger the persistent scheduling.
821 ActivateUnderlyingProvider();
822
823 // As long as the quota suffices, the call gets through.
824 RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
825 EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
826 .Times(5)
827 .WillRepeatedly(SaveArg<0>(&signal_fetch_done));
828 for (int x = 0; x < 5; ++x) {
829 scheduling_provider_->OnPersistentSchedulerWakeUp();
830 signal_fetch_done.Run(Status::Success());
831 }
832
833 // For the 6th time, it is blocked by the scheduling provider.
834 scheduling_provider_->OnPersistentSchedulerWakeUp();
835 }
836
837 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698