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

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

Powered by Google App Engine
This is Rietveld 408576698