1 // Copyright 2014 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.
5 #include "components/suggestions/suggestions_service.h"
10 #include "base/bind.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/field_trial.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "components/suggestions/blacklist_store.h"
16 #include "components/suggestions/image_manager.h"
17 #include "components/suggestions/proto/suggestions.pb.h"
18 #include "components/suggestions/suggestions_store.h"
19 #include "components/suggestions/suggestions_utils.h"
20 #include "components/variations/entropy_provider.h"
21 #include "components/variations/variations_associated_data.h"
22 #include "net/http/http_response_headers.h"
23 #include "net/http/http_status_code.h"
24 #include "net/url_request/test_url_fetcher_factory.h"
25 #include "net/url_request/url_request_status.h"
26 #include "net/url_request/url_request_test_util.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
32 using ::testing::AnyNumber
;
34 using ::testing::Return
;
35 using testing::SetArgPointee
;
36 using ::testing::NiceMock
;
37 using ::testing::StrictMock
;
42 const char kTestTitle
[] = "a title";
43 const char kTestUrl
[] = "http://go.com";
44 const char kBlacklistUrl
[] = "http://blacklist.com";
45 const char kBlacklistUrlAlt
[] = "http://blacklist-atl.com";
46 const int64 kTestDefaultExpiry
= 1402200000000000;
47 const int64 kTestSetExpiry
= 1404792000000000;
49 scoped_ptr
<net::FakeURLFetcher
> CreateURLFetcher(
50 const GURL
& url
, net::URLFetcherDelegate
* delegate
,
51 const std::string
& response_data
, net::HttpStatusCode response_code
,
52 net::URLRequestStatus::Status status
) {
53 scoped_ptr
<net::FakeURLFetcher
> fetcher(new net::FakeURLFetcher(
54 url
, delegate
, response_data
, response_code
, status
));
56 if (response_code
== net::HTTP_OK
) {
57 scoped_refptr
<net::HttpResponseHeaders
> download_headers(
58 new net::HttpResponseHeaders(""));
59 download_headers
->AddHeader("Content-Type: text/html");
60 fetcher
->set_response_headers(download_headers
);
62 return fetcher
.Pass();
65 std::string
GetExpectedBlacklistRequestUrl(const GURL
& blacklist_url
) {
66 std::stringstream request_url
;
67 request_url
<< "https://www.google.com/chromesuggestions/blacklist?t=2&url="
68 << net::EscapeQueryParamValue(blacklist_url
.spec(), true);
69 return request_url
.str();
72 // GMock matcher for protobuf equality.
73 MATCHER_P(EqualsProto
, message
, "") {
74 // This implementation assumes protobuf serialization is deterministic, which
75 // is true in practice but technically not something that code is supposed
76 // to rely on. However, it vastly simplifies the implementation.
77 std::string expected_serialized
, actual_serialized
;
78 message
.SerializeToString(&expected_serialized
);
79 arg
.SerializeToString(&actual_serialized
);
80 return expected_serialized
== actual_serialized
;
85 namespace suggestions
{
87 SuggestionsProfile
CreateSuggestionsProfile() {
88 SuggestionsProfile profile
;
89 ChromeSuggestion
* suggestion
= profile
.add_suggestions();
90 suggestion
->set_title(kTestTitle
);
91 suggestion
->set_url(kTestUrl
);
92 suggestion
->set_expiry_ts(kTestSetExpiry
);
96 // Creates one suggestion with expiry timestamp and one without.
97 SuggestionsProfile
CreateSuggestionsProfileWithExpiryTimestamps() {
98 SuggestionsProfile profile
;
99 ChromeSuggestion
* suggestion
= profile
.add_suggestions();
100 suggestion
->set_title(kTestTitle
);
101 suggestion
->set_url(kTestUrl
);
102 suggestion
->set_expiry_ts(kTestSetExpiry
);
104 suggestion
= profile
.add_suggestions();
105 suggestion
->set_title(kTestTitle
);
106 suggestion
->set_url(kTestUrl
);
111 class TestSuggestionsStore
: public suggestions::SuggestionsStore
{
113 TestSuggestionsStore() {
114 cached_suggestions
= CreateSuggestionsProfile();
116 bool LoadSuggestions(SuggestionsProfile
* suggestions
) override
{
117 if (cached_suggestions
.suggestions_size()) {
118 *suggestions
= cached_suggestions
;
123 bool StoreSuggestions(const SuggestionsProfile
& suggestions
)
125 cached_suggestions
= suggestions
;
128 void ClearSuggestions() override
{
129 cached_suggestions
= SuggestionsProfile();
132 SuggestionsProfile cached_suggestions
;
135 class MockImageManager
: public suggestions::ImageManager
{
137 MockImageManager() {}
138 virtual ~MockImageManager() {}
139 MOCK_METHOD1(Initialize
, void(const SuggestionsProfile
&));
140 MOCK_METHOD2(GetImageForURL
,
142 base::Callback
<void(const GURL
&, const SkBitmap
*)>));
145 class MockBlacklistStore
: public suggestions::BlacklistStore
{
147 MOCK_METHOD1(BlacklistUrl
, bool(const GURL
&));
148 MOCK_METHOD0(IsEmpty
, bool());
149 MOCK_METHOD1(GetTimeUntilReadyForUpload
, bool(base::TimeDelta
*));
150 MOCK_METHOD2(GetTimeUntilURLReadyForUpload
,
151 bool(const GURL
&, base::TimeDelta
*));
152 MOCK_METHOD1(GetCandidateForUpload
, bool(GURL
*));
153 MOCK_METHOD1(RemoveUrl
, bool(const GURL
&));
154 MOCK_METHOD1(FilterSuggestions
, void(SuggestionsProfile
*));
157 class SuggestionsServiceTest
: public testing::Test
{
159 void CheckSuggestionsData(const SuggestionsProfile
& suggestions_profile
) {
160 EXPECT_EQ(1, suggestions_profile
.suggestions_size());
161 EXPECT_EQ(kTestTitle
, suggestions_profile
.suggestions(0).title());
162 EXPECT_EQ(kTestUrl
, suggestions_profile
.suggestions(0).url());
163 ++suggestions_data_check_count_
;
166 void SetBlacklistFailure() {
167 blacklisting_failed_
= true;
170 void SetUndoBlacklistFailure() {
171 undo_blacklisting_failed_
= true;
174 void ExpectEmptySuggestionsProfile(const SuggestionsProfile
& profile
) {
175 EXPECT_EQ(0, profile
.suggestions_size());
176 ++suggestions_empty_data_count_
;
179 int suggestions_data_check_count_
;
180 int suggestions_empty_data_count_
;
181 bool blacklisting_failed_
;
182 bool undo_blacklisting_failed_
;
185 SuggestionsServiceTest()
186 : suggestions_data_check_count_(0),
187 suggestions_empty_data_count_(0),
188 blacklisting_failed_(false),
189 undo_blacklisting_failed_(false),
190 factory_(NULL
, base::Bind(&CreateURLFetcher
)),
191 mock_thumbnail_manager_(NULL
),
192 mock_blacklist_store_(NULL
),
193 test_suggestions_store_(NULL
) {}
195 ~SuggestionsServiceTest() override
{}
197 void SetUp() override
{
198 request_context_
= new net::TestURLRequestContextGetter(
199 io_message_loop_
.message_loop_proxy());
202 void EnableFieldTrial(bool control_group
) {
203 // Clear the existing |field_trial_list_| to avoid firing a DCHECK.
204 field_trial_list_
.reset(NULL
);
205 field_trial_list_
.reset(
206 new base::FieldTrialList(new metrics::SHA1EntropyProvider("foo")));
208 variations::testing::ClearAllVariationParams();
209 std::map
<std::string
, std::string
> params
;
210 params
[kSuggestionsFieldTrialStateParam
] =
211 kSuggestionsFieldTrialStateEnabled
;
213 params
[kSuggestionsFieldTrialControlParam
] =
214 kSuggestionsFieldTrialStateEnabled
;
216 variations::AssociateVariationParams(kSuggestionsFieldTrialName
, "Group1",
218 field_trial_
= base::FieldTrialList::CreateFieldTrial(
219 kSuggestionsFieldTrialName
, "Group1");
220 field_trial_
->group();
223 void FetchSuggestionsDataHelper(SyncState sync_state
) {
224 scoped_ptr
<SuggestionsService
> suggestions_service(
225 CreateSuggestionsServiceWithMocks());
226 EXPECT_TRUE(suggestions_service
!= NULL
);
228 // Add some suggestions in the cache.
229 FillSuggestionsStore();
230 SuggestionsProfile suggestions_profile
;
231 test_suggestions_store_
->LoadSuggestions(&suggestions_profile
);
233 // Set up net::FakeURLFetcherFactory.
234 factory_
.SetFakeResponse(GURL(kSuggestionsURL
),
235 suggestions_profile
.SerializeAsString(),
236 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
239 EXPECT_CALL(*mock_thumbnail_manager_
,
240 Initialize(EqualsProto(suggestions_profile
)));
241 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
242 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
243 .WillOnce(Return(false));
245 // Send the request. The data will be returned to the callback.
246 suggestions_service
->FetchSuggestionsData(
248 base::Bind(&SuggestionsServiceTest::CheckSuggestionsData
,
249 base::Unretained(this)));
251 // Ensure that CheckSuggestionsData() ran once.
252 EXPECT_EQ(1, suggestions_data_check_count_
);
254 // Let the network request run.
255 io_message_loop_
.RunUntilIdle();
258 SuggestionsService
* CreateSuggestionsServiceWithMocks() {
259 // These objects are owned by the returned SuggestionsService, but we keep
260 // the pointer around for testing.
261 test_suggestions_store_
= new TestSuggestionsStore();
262 mock_thumbnail_manager_
= new StrictMock
<MockImageManager
>();
263 mock_blacklist_store_
= new StrictMock
<MockBlacklistStore
>();
264 return new SuggestionsService(
265 request_context_
.get(),
266 scoped_ptr
<SuggestionsStore
>(test_suggestions_store_
),
267 scoped_ptr
<ImageManager
>(mock_thumbnail_manager_
),
268 scoped_ptr
<BlacklistStore
>(mock_blacklist_store_
));
271 void FillSuggestionsStore() {
272 test_suggestions_store_
->StoreSuggestions(CreateSuggestionsProfile());
275 void Blacklist(SuggestionsService
* suggestions_service
, GURL url
) {
276 suggestions_service
->BlacklistURL(
278 base::Bind(&SuggestionsServiceTest::CheckSuggestionsData
,
279 base::Unretained(this)),
280 base::Bind(&SuggestionsServiceTest::SetBlacklistFailure
,
281 base::Unretained(this)));
284 void UndoBlacklist(SuggestionsService
* suggestions_service
, GURL url
) {
285 suggestions_service
->UndoBlacklistURL(
287 base::Bind(&SuggestionsServiceTest::CheckSuggestionsData
,
288 base::Unretained(this)),
289 base::Bind(&SuggestionsServiceTest::SetUndoBlacklistFailure
,
290 base::Unretained(this)));
293 // Helper for Undo failure tests. Depending on |is_uploaded|, tests either
294 // the case where the URL is no longer in the local blacklist or the case
295 // in which it's not yet candidate for upload.
296 void UndoBlacklistURLFailsHelper(bool is_uploaded
) {
297 scoped_ptr
<SuggestionsService
> suggestions_service(
298 CreateSuggestionsServiceWithMocks());
299 EXPECT_TRUE(suggestions_service
!= NULL
);
300 // Ensure scheduling the request doesn't happen before undo.
301 base::TimeDelta delay
= base::TimeDelta::FromHours(1);
302 suggestions_service
->set_blacklist_delay(delay
);
303 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
304 GURL
blacklist_url(kBlacklistUrl
);
306 // Blacklist expectations.
307 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
308 .WillOnce(Return(true));
309 EXPECT_CALL(*mock_thumbnail_manager_
,
310 Initialize(EqualsProto(suggestions_profile
)));
311 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
312 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
313 .WillOnce(DoAll(SetArgPointee
<0>(delay
), Return(true)));
314 // Undo expectations.
316 // URL is not in local blacklist.
317 EXPECT_CALL(*mock_blacklist_store_
,
318 GetTimeUntilURLReadyForUpload(Eq(blacklist_url
), _
))
319 .WillOnce(Return(false));
321 // URL is not yet candidate for upload.
322 base::TimeDelta negative_delay
= base::TimeDelta::FromHours(-1);
323 EXPECT_CALL(*mock_blacklist_store_
,
324 GetTimeUntilURLReadyForUpload(Eq(blacklist_url
), _
))
325 .WillOnce(DoAll(SetArgPointee
<1>(negative_delay
), Return(true)));
328 Blacklist(suggestions_service
.get(), blacklist_url
);
329 UndoBlacklist(suggestions_service
.get(), blacklist_url
);
331 EXPECT_EQ(1, suggestions_data_check_count_
);
332 EXPECT_FALSE(blacklisting_failed_
);
333 EXPECT_TRUE(undo_blacklisting_failed_
);
337 base::MessageLoopForIO io_message_loop_
;
338 net::FakeURLFetcherFactory factory_
;
339 // Only used if the SuggestionsService is built with mocks. Not owned.
340 MockImageManager
* mock_thumbnail_manager_
;
341 MockBlacklistStore
* mock_blacklist_store_
;
342 TestSuggestionsStore
* test_suggestions_store_
;
343 scoped_refptr
<net::TestURLRequestContextGetter
> request_context_
;
346 scoped_ptr
<base::FieldTrialList
> field_trial_list_
;
347 scoped_refptr
<base::FieldTrial
> field_trial_
;
349 DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest
);
352 TEST_F(SuggestionsServiceTest
, IsControlGroup
) {
353 EnableFieldTrial(false);
354 EXPECT_FALSE(SuggestionsService::IsControlGroup());
356 EnableFieldTrial(true);
357 EXPECT_TRUE(SuggestionsService::IsControlGroup());
360 TEST_F(SuggestionsServiceTest
, FetchSuggestionsData
) {
361 EnableFieldTrial(false);
362 FetchSuggestionsDataHelper(INITIALIZED_ENABLED_HISTORY
);
365 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataSyncNotInitializedEnabled
) {
366 EnableFieldTrial(false);
367 FetchSuggestionsDataHelper(NOT_INITIALIZED_ENABLED
);
370 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataSyncDisabled
) {
371 EnableFieldTrial(false);
372 scoped_ptr
<SuggestionsService
> suggestions_service(
373 CreateSuggestionsServiceWithMocks());
374 EXPECT_TRUE(suggestions_service
!= NULL
);
376 FillSuggestionsStore();
378 // Send the request. Cache is cleared and empty data will be returned to the
380 suggestions_service
->FetchSuggestionsData(
381 SYNC_OR_HISTORY_SYNC_DISABLED
,
382 base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile
,
383 base::Unretained(this)));
385 // Ensure that ExpectEmptySuggestionsProfile ran once.
386 EXPECT_EQ(1, suggestions_empty_data_count_
);
389 TEST_F(SuggestionsServiceTest
, IssueRequestIfNoneOngoingError
) {
390 EnableFieldTrial(false);
391 scoped_ptr
<SuggestionsService
> suggestions_service(
392 CreateSuggestionsServiceWithMocks());
393 EXPECT_TRUE(suggestions_service
!= NULL
);
395 // Fake a request error.
396 factory_
.SetFakeResponse(GURL(kSuggestionsURL
), "irrelevant", net::HTTP_OK
,
397 net::URLRequestStatus::FAILED
);
399 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
400 .WillOnce(Return(false));
402 // Send the request. Empty data will be returned to the callback.
403 suggestions_service
->IssueRequestIfNoneOngoing(GURL(kSuggestionsURL
));
405 // (Testing only) wait until suggestion fetch is complete.
406 io_message_loop_
.RunUntilIdle();
409 TEST_F(SuggestionsServiceTest
, IssueRequestIfNoneOngoingResponseNotOK
) {
410 EnableFieldTrial(false);
411 scoped_ptr
<SuggestionsService
> suggestions_service(
412 CreateSuggestionsServiceWithMocks());
413 EXPECT_TRUE(suggestions_service
!= NULL
);
415 // Add some suggestions in the cache.
416 FillSuggestionsStore();
418 // Fake a non-200 response code.
419 factory_
.SetFakeResponse(GURL(kSuggestionsURL
), "irrelevant",
420 net::HTTP_BAD_REQUEST
,
421 net::URLRequestStatus::SUCCESS
);
423 // Expect that an upload to the blacklist is scheduled.
424 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
425 .WillOnce(Return(false));
427 // Send the request. Empty data will be returned to the callback.
428 suggestions_service
->IssueRequestIfNoneOngoing(GURL(kSuggestionsURL
));
430 // (Testing only) wait until suggestion fetch is complete.
431 io_message_loop_
.RunUntilIdle();
433 // Expect no suggestions in the cache.
434 SuggestionsProfile empty_suggestions
;
435 EXPECT_FALSE(test_suggestions_store_
->LoadSuggestions(&empty_suggestions
));
438 TEST_F(SuggestionsServiceTest
, BlacklistURL
) {
439 EnableFieldTrial(false);
440 scoped_ptr
<SuggestionsService
> suggestions_service(
441 CreateSuggestionsServiceWithMocks());
442 EXPECT_TRUE(suggestions_service
!= NULL
);
443 base::TimeDelta no_delay
= base::TimeDelta::FromSeconds(0);
444 suggestions_service
->set_blacklist_delay(no_delay
);
446 GURL
blacklist_url(kBlacklistUrl
);
447 std::string request_url
= GetExpectedBlacklistRequestUrl(blacklist_url
);
448 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
449 factory_
.SetFakeResponse(GURL(request_url
),
450 suggestions_profile
.SerializeAsString(),
451 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
452 EXPECT_CALL(*mock_thumbnail_manager_
,
453 Initialize(EqualsProto(suggestions_profile
)));
455 // Expected calls to the blacklist store.
456 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
457 .WillOnce(Return(true));
458 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
459 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
460 .WillOnce(DoAll(SetArgPointee
<0>(no_delay
), Return(true)))
461 .WillOnce(Return(false));
462 EXPECT_CALL(*mock_blacklist_store_
, GetCandidateForUpload(_
))
463 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url
), Return(true)));
464 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url
)))
465 .WillOnce(Return(true));
467 Blacklist(suggestions_service
.get(), blacklist_url
);
469 // Wait on the upload task. This only works when the scheduling task is not
470 // for future execution (note how both the SuggestionsService's scheduling
471 // delay and the BlacklistStore's candidacy delay are zero). Then wait on
472 // the blacklist request, then again on the next blacklist scheduling task.
473 base::MessageLoop::current()->RunUntilIdle();
474 io_message_loop_
.RunUntilIdle();
475 base::MessageLoop::current()->RunUntilIdle();
477 // Ensure that CheckSuggestionsData() ran once.
478 EXPECT_EQ(1, suggestions_data_check_count_
);
479 EXPECT_FALSE(blacklisting_failed_
);
482 TEST_F(SuggestionsServiceTest
, BlacklistURLFails
) {
483 EnableFieldTrial(false);
484 scoped_ptr
<SuggestionsService
> suggestions_service(
485 CreateSuggestionsServiceWithMocks());
486 EXPECT_TRUE(suggestions_service
!= NULL
);
487 GURL
blacklist_url(kBlacklistUrl
);
488 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
489 .WillOnce(Return(false));
491 Blacklist(suggestions_service
.get(), blacklist_url
);
493 EXPECT_TRUE(blacklisting_failed_
);
494 EXPECT_EQ(0, suggestions_data_check_count_
);
497 // Initial blacklist request fails, triggering a second which succeeds.
498 TEST_F(SuggestionsServiceTest
, BlacklistURLRequestFails
) {
499 EnableFieldTrial(false);
500 scoped_ptr
<SuggestionsService
> suggestions_service(
501 CreateSuggestionsServiceWithMocks());
502 EXPECT_TRUE(suggestions_service
!= NULL
);
503 base::TimeDelta no_delay
= base::TimeDelta::FromSeconds(0);
504 suggestions_service
->set_blacklist_delay(no_delay
);
506 GURL
blacklist_url(kBlacklistUrl
);
507 std::string request_url
= GetExpectedBlacklistRequestUrl(blacklist_url
);
508 GURL
blacklist_url_alt(kBlacklistUrlAlt
);
509 std::string request_url_alt
= GetExpectedBlacklistRequestUrl(
511 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
513 // Note: we want to set the response for the blacklist URL to first
514 // succeed, then fail. This doesn't seem possible. For simplicity of testing,
515 // we'll pretend the URL changed in the BlacklistStore between the first and
516 // the second request, and adjust expectations accordingly.
517 factory_
.SetFakeResponse(GURL(request_url
), "irrelevant", net::HTTP_OK
,
518 net::URLRequestStatus::FAILED
);
519 factory_
.SetFakeResponse(GURL(request_url_alt
),
520 suggestions_profile
.SerializeAsString(),
521 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
524 EXPECT_CALL(*mock_thumbnail_manager_
,
525 Initialize(EqualsProto(suggestions_profile
)));
526 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
527 .WillOnce(Return(true));
528 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
529 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
530 .WillOnce(DoAll(SetArgPointee
<0>(no_delay
), Return(true)))
531 .WillOnce(DoAll(SetArgPointee
<0>(no_delay
), Return(true)))
532 .WillOnce(Return(false));
533 EXPECT_CALL(*mock_blacklist_store_
, GetCandidateForUpload(_
))
534 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url
), Return(true)))
535 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url_alt
), Return(true)));
536 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url_alt
)))
537 .WillOnce(Return(true));
539 // Blacklist call, first request attempt.
540 Blacklist(suggestions_service
.get(), blacklist_url
);
541 EXPECT_EQ(1, suggestions_data_check_count_
);
542 EXPECT_FALSE(blacklisting_failed_
);
544 // Wait for the first scheduling, the first request, the second scheduling,
545 // second request and the third scheduling. Again, note that calling
546 // RunUntilIdle on the MessageLoop only works when the task is not posted for
548 base::MessageLoop::current()->RunUntilIdle();
549 io_message_loop_
.RunUntilIdle();
550 base::MessageLoop::current()->RunUntilIdle();
551 io_message_loop_
.RunUntilIdle();
552 base::MessageLoop::current()->RunUntilIdle();
555 TEST_F(SuggestionsServiceTest
, UndoBlacklistURL
) {
556 EnableFieldTrial(false);
557 scoped_ptr
<SuggestionsService
> suggestions_service(
558 CreateSuggestionsServiceWithMocks());
559 EXPECT_TRUE(suggestions_service
!= NULL
);
560 // Ensure scheduling the request doesn't happen before undo.
561 base::TimeDelta delay
= base::TimeDelta::FromHours(1);
562 suggestions_service
->set_blacklist_delay(delay
);
563 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
564 GURL
blacklist_url(kBlacklistUrl
);
566 // Blacklist expectations.
567 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
568 .WillOnce(Return(true));
569 EXPECT_CALL(*mock_thumbnail_manager_
,
570 Initialize(EqualsProto(suggestions_profile
)))
572 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
))
574 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
575 .WillOnce(DoAll(SetArgPointee
<0>(delay
), Return(true)));
576 // Undo expectations.
577 EXPECT_CALL(*mock_blacklist_store_
,
578 GetTimeUntilURLReadyForUpload(Eq(blacklist_url
), _
))
579 .WillOnce(DoAll(SetArgPointee
<1>(delay
), Return(true)));
580 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url
)))
581 .WillOnce(Return(true));
583 Blacklist(suggestions_service
.get(), blacklist_url
);
584 UndoBlacklist(suggestions_service
.get(), blacklist_url
);
586 EXPECT_EQ(2, suggestions_data_check_count_
);
587 EXPECT_FALSE(blacklisting_failed_
);
588 EXPECT_FALSE(undo_blacklisting_failed_
);
592 TEST_F(SuggestionsServiceTest
, UndoBlacklistURLFailsIfNotInBlacklist
) {
593 EnableFieldTrial(false);
594 UndoBlacklistURLFailsHelper(true);
597 TEST_F(SuggestionsServiceTest
, UndoBlacklistURLFailsIfAlreadyCandidate
) {
598 EnableFieldTrial(false);
599 UndoBlacklistURLFailsHelper(false);
602 TEST_F(SuggestionsServiceTest
, GetBlacklistedUrl
) {
603 EnableFieldTrial(false);
604 scoped_ptr
<GURL
> request_url
;
605 scoped_ptr
<net::FakeURLFetcher
> fetcher
;
608 // Not a blacklist request.
609 request_url
.reset(new GURL("http://not-blacklisting.com/a?b=c"));
610 fetcher
= CreateURLFetcher(*request_url
, NULL
, "", net::HTTP_OK
,
611 net::URLRequestStatus::SUCCESS
);
612 EXPECT_FALSE(SuggestionsService::GetBlacklistedUrl(*fetcher
, &retrieved_url
));
614 // An actual blacklist request.
615 string blacklisted_url
= "http://blacklisted.com/a?b=c&d=e";
616 string encoded_blacklisted_url
=
617 "http%3A%2F%2Fblacklisted.com%2Fa%3Fb%3Dc%26d%3De";
618 string
blacklist_request_prefix(kSuggestionsBlacklistURLPrefix
);
620 new GURL(blacklist_request_prefix
+ encoded_blacklisted_url
));
622 fetcher
= CreateURLFetcher(*request_url
, NULL
, "", net::HTTP_OK
,
623 net::URLRequestStatus::SUCCESS
);
624 EXPECT_TRUE(SuggestionsService::GetBlacklistedUrl(*fetcher
, &retrieved_url
));
625 EXPECT_EQ(blacklisted_url
, retrieved_url
.spec());
628 TEST_F(SuggestionsServiceTest
, UpdateBlacklistDelay
) {
629 EnableFieldTrial(false);
630 scoped_ptr
<SuggestionsService
> suggestions_service(
631 CreateSuggestionsServiceWithMocks());
632 base::TimeDelta initial_delay
= suggestions_service
->blacklist_delay();
634 // Delay unchanged on success.
635 suggestions_service
->UpdateBlacklistDelay(true);
636 EXPECT_EQ(initial_delay
, suggestions_service
->blacklist_delay());
638 // Delay increases on failure.
639 suggestions_service
->UpdateBlacklistDelay(false);
640 EXPECT_GT(suggestions_service
->blacklist_delay(), initial_delay
);
642 // Delay resets on success.
643 suggestions_service
->UpdateBlacklistDelay(true);
644 EXPECT_EQ(initial_delay
, suggestions_service
->blacklist_delay());
647 TEST_F(SuggestionsServiceTest
, CheckDefaultTimeStamps
) {
648 EnableFieldTrial(false);
649 scoped_ptr
<SuggestionsService
> suggestions_service(
650 CreateSuggestionsServiceWithMocks());
651 SuggestionsProfile suggestions
=
652 CreateSuggestionsProfileWithExpiryTimestamps();
653 suggestions_service
->SetDefaultExpiryTimestamp(&suggestions
,
655 EXPECT_EQ(kTestSetExpiry
, suggestions
.suggestions(0).expiry_ts());
656 EXPECT_EQ(kTestDefaultExpiry
, suggestions
.suggestions(1).expiry_ts());
658 } // namespace suggestions