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

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

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

Powered by Google App Engine
This is Rietveld 408576698