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 "components/suggestions/blacklist_store.h"
13 #include "components/suggestions/image_manager.h"
14 #include "components/suggestions/proto/suggestions.pb.h"
15 #include "components/suggestions/suggestions_store.h"
16 #include "components/suggestions/suggestions_utils.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/http/http_status_code.h"
19 #include "net/url_request/test_url_fetcher_factory.h"
20 #include "net/url_request/url_request_status.h"
21 #include "net/url_request/url_request_test_util.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
27 using ::testing::AnyNumber
;
29 using ::testing::Return
;
30 using testing::SetArgPointee
;
31 using ::testing::NiceMock
;
32 using ::testing::StrictMock
;
37 const char kTestTitle
[] = "a title";
38 const char kTestUrl
[] = "http://go.com";
39 const char kTestFaviconUrl
[] =
40 "https://s2.googleusercontent.com/s2/favicons?domain_url="
41 "http://go.com&alt=s&sz=32";
42 const char kBlacklistUrl
[] = "http://blacklist.com";
43 const char kBlacklistUrlAlt
[] = "http://blacklist-atl.com";
44 const int64 kTestDefaultExpiry
= 1402200000000000;
45 const int64 kTestSetExpiry
= 1404792000000000;
47 scoped_ptr
<net::FakeURLFetcher
> CreateURLFetcher(
48 const GURL
& url
, net::URLFetcherDelegate
* delegate
,
49 const std::string
& response_data
, net::HttpStatusCode response_code
,
50 net::URLRequestStatus::Status status
) {
51 scoped_ptr
<net::FakeURLFetcher
> fetcher(new net::FakeURLFetcher(
52 url
, delegate
, response_data
, response_code
, status
));
54 if (response_code
== net::HTTP_OK
) {
55 scoped_refptr
<net::HttpResponseHeaders
> download_headers(
56 new net::HttpResponseHeaders(""));
57 download_headers
->AddHeader("Content-Type: text/html");
58 fetcher
->set_response_headers(download_headers
);
60 return fetcher
.Pass();
63 std::string
GetExpectedBlacklistRequestUrl(const GURL
& blacklist_url
) {
64 std::stringstream request_url
;
65 request_url
<< suggestions::kSuggestionsBlacklistURLPrefix
66 << net::EscapeQueryParamValue(blacklist_url
.spec(), true);
67 return request_url
.str();
70 // GMock matcher for protobuf equality.
71 MATCHER_P(EqualsProto
, message
, "") {
72 // This implementation assumes protobuf serialization is deterministic, which
73 // is true in practice but technically not something that code is supposed
74 // to rely on. However, it vastly simplifies the implementation.
75 std::string expected_serialized
, actual_serialized
;
76 message
.SerializeToString(&expected_serialized
);
77 arg
.SerializeToString(&actual_serialized
);
78 return expected_serialized
== actual_serialized
;
83 namespace suggestions
{
85 SuggestionsProfile
CreateSuggestionsProfile() {
86 SuggestionsProfile profile
;
87 ChromeSuggestion
* suggestion
= profile
.add_suggestions();
88 suggestion
->set_title(kTestTitle
);
89 suggestion
->set_url(kTestUrl
);
90 suggestion
->set_expiry_ts(kTestSetExpiry
);
94 // Creates one suggestion with expiry timestamp and one without.
95 SuggestionsProfile
CreateSuggestionsProfileWithExpiryTimestamps() {
96 SuggestionsProfile profile
;
97 ChromeSuggestion
* suggestion
= profile
.add_suggestions();
98 suggestion
->set_title(kTestTitle
);
99 suggestion
->set_url(kTestUrl
);
100 suggestion
->set_expiry_ts(kTestSetExpiry
);
102 suggestion
= profile
.add_suggestions();
103 suggestion
->set_title(kTestTitle
);
104 suggestion
->set_url(kTestUrl
);
109 class TestSuggestionsStore
: public suggestions::SuggestionsStore
{
111 TestSuggestionsStore() {
112 cached_suggestions
= CreateSuggestionsProfile();
114 bool LoadSuggestions(SuggestionsProfile
* suggestions
) override
{
115 suggestions
->CopyFrom(cached_suggestions
);
116 return cached_suggestions
.suggestions_size();
118 bool StoreSuggestions(const SuggestionsProfile
& suggestions
)
120 cached_suggestions
.CopyFrom(suggestions
);
123 void ClearSuggestions() override
{
124 cached_suggestions
= SuggestionsProfile();
127 SuggestionsProfile cached_suggestions
;
130 class MockImageManager
: public suggestions::ImageManager
{
132 MockImageManager() {}
133 virtual ~MockImageManager() {}
134 MOCK_METHOD1(Initialize
, void(const SuggestionsProfile
&));
135 MOCK_METHOD2(GetImageForURL
,
137 base::Callback
<void(const GURL
&, const SkBitmap
*)>));
140 class MockBlacklistStore
: public suggestions::BlacklistStore
{
142 MOCK_METHOD1(BlacklistUrl
, bool(const GURL
&));
143 MOCK_METHOD0(IsEmpty
, bool());
144 MOCK_METHOD1(GetTimeUntilReadyForUpload
, bool(base::TimeDelta
*));
145 MOCK_METHOD2(GetTimeUntilURLReadyForUpload
,
146 bool(const GURL
&, base::TimeDelta
*));
147 MOCK_METHOD1(GetCandidateForUpload
, bool(GURL
*));
148 MOCK_METHOD1(RemoveUrl
, bool(const GURL
&));
149 MOCK_METHOD1(FilterSuggestions
, void(SuggestionsProfile
*));
150 MOCK_METHOD0(ClearBlacklist
, void());
153 class SuggestionsServiceTest
: public testing::Test
{
155 void CheckCallback(const SuggestionsProfile
& suggestions_profile
) {
156 ++suggestions_data_callback_count_
;
159 void CheckSuggestionsData() {
160 SuggestionsProfile suggestions_profile
;
161 test_suggestions_store_
->LoadSuggestions(&suggestions_profile
);
162 EXPECT_EQ(1, suggestions_profile
.suggestions_size());
163 EXPECT_EQ(kTestTitle
, suggestions_profile
.suggestions(0).title());
164 EXPECT_EQ(kTestUrl
, suggestions_profile
.suggestions(0).url());
165 EXPECT_EQ(kTestFaviconUrl
,
166 suggestions_profile
.suggestions(0).favicon_url());
169 void SetBlacklistFailure() {
170 blacklisting_failed_
= true;
173 void SetUndoBlacklistFailure() {
174 undo_blacklisting_failed_
= true;
177 void ExpectEmptySuggestionsProfile(const SuggestionsProfile
& profile
) {
178 EXPECT_EQ(0, profile
.suggestions_size());
179 ++suggestions_empty_data_count_
;
182 int suggestions_data_callback_count_
;
183 int suggestions_empty_data_count_
;
184 bool blacklisting_failed_
;
185 bool undo_blacklisting_failed_
;
188 SuggestionsServiceTest()
189 : suggestions_data_callback_count_(0),
190 suggestions_empty_data_count_(0),
191 blacklisting_failed_(false),
192 undo_blacklisting_failed_(false),
193 factory_(NULL
, base::Bind(&CreateURLFetcher
)),
194 mock_thumbnail_manager_(NULL
),
195 mock_blacklist_store_(NULL
),
196 test_suggestions_store_(NULL
) {}
198 ~SuggestionsServiceTest() override
{}
200 void SetUp() override
{
202 new net::TestURLRequestContextGetter(io_message_loop_
.task_runner());
205 void FetchSuggestionsDataHelper(SyncState sync_state
) {
206 scoped_ptr
<SuggestionsService
> suggestions_service(
207 CreateSuggestionsServiceWithMocks());
208 EXPECT_TRUE(suggestions_service
!= NULL
);
210 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
212 // Set up net::FakeURLFetcherFactory.
213 factory_
.SetFakeResponse(GURL(kSuggestionsURL
),
214 suggestions_profile
.SerializeAsString(),
215 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
218 EXPECT_CALL(*mock_thumbnail_manager_
,
219 Initialize(EqualsProto(suggestions_profile
)));
220 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
221 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
222 .WillOnce(Return(false));
224 // Send the request. The data will be returned to the callback.
225 suggestions_service
->FetchSuggestionsData(
226 sync_state
, base::Bind(&SuggestionsServiceTest::CheckCallback
,
227 base::Unretained(this)));
229 // Ensure that CheckSuggestionsData() ran once.
230 EXPECT_EQ(1, suggestions_data_callback_count_
);
232 // Let the network request run.
233 io_message_loop_
.RunUntilIdle();
235 CheckSuggestionsData();
238 SuggestionsService
* CreateSuggestionsServiceWithMocks() {
239 // These objects are owned by the returned SuggestionsService, but we keep
240 // the pointer around for testing.
241 test_suggestions_store_
= new TestSuggestionsStore();
242 mock_thumbnail_manager_
= new StrictMock
<MockImageManager
>();
243 mock_blacklist_store_
= new StrictMock
<MockBlacklistStore
>();
244 return new SuggestionsService(
245 request_context_
.get(),
246 scoped_ptr
<SuggestionsStore
>(test_suggestions_store_
),
247 scoped_ptr
<ImageManager
>(mock_thumbnail_manager_
),
248 scoped_ptr
<BlacklistStore
>(mock_blacklist_store_
));
251 void Blacklist(SuggestionsService
* suggestions_service
, GURL url
) {
252 suggestions_service
->BlacklistURL(
253 url
, base::Bind(&SuggestionsServiceTest::CheckCallback
,
254 base::Unretained(this)),
255 base::Bind(&SuggestionsServiceTest::SetBlacklistFailure
,
256 base::Unretained(this)));
259 void UndoBlacklist(SuggestionsService
* suggestions_service
, GURL url
) {
260 suggestions_service
->UndoBlacklistURL(
261 url
, base::Bind(&SuggestionsServiceTest::CheckCallback
,
262 base::Unretained(this)),
263 base::Bind(&SuggestionsServiceTest::SetUndoBlacklistFailure
,
264 base::Unretained(this)));
267 // Helper for Undo failure tests. Depending on |is_uploaded|, tests either
268 // the case where the URL is no longer in the local blacklist or the case
269 // in which it's not yet candidate for upload.
270 void UndoBlacklistURLFailsHelper(bool is_uploaded
) {
271 scoped_ptr
<SuggestionsService
> suggestions_service(
272 CreateSuggestionsServiceWithMocks());
273 EXPECT_TRUE(suggestions_service
!= NULL
);
274 // Ensure scheduling the request doesn't happen before undo.
275 base::TimeDelta delay
= base::TimeDelta::FromHours(1);
276 suggestions_service
->set_blacklist_delay(delay
);
277 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
278 GURL
blacklist_url(kBlacklistUrl
);
280 // Blacklist expectations.
281 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
282 .WillOnce(Return(true));
283 EXPECT_CALL(*mock_thumbnail_manager_
,
284 Initialize(EqualsProto(suggestions_profile
)));
285 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
286 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
287 .WillOnce(DoAll(SetArgPointee
<0>(delay
), Return(true)));
288 // Undo expectations.
290 // URL is not in local blacklist.
291 EXPECT_CALL(*mock_blacklist_store_
,
292 GetTimeUntilURLReadyForUpload(Eq(blacklist_url
), _
))
293 .WillOnce(Return(false));
295 // URL is not yet candidate for upload.
296 base::TimeDelta negative_delay
= base::TimeDelta::FromHours(-1);
297 EXPECT_CALL(*mock_blacklist_store_
,
298 GetTimeUntilURLReadyForUpload(Eq(blacklist_url
), _
))
299 .WillOnce(DoAll(SetArgPointee
<1>(negative_delay
), Return(true)));
302 Blacklist(suggestions_service
.get(), blacklist_url
);
303 UndoBlacklist(suggestions_service
.get(), blacklist_url
);
305 EXPECT_EQ(1, suggestions_data_callback_count_
);
306 EXPECT_FALSE(blacklisting_failed_
);
307 EXPECT_TRUE(undo_blacklisting_failed_
);
311 base::MessageLoopForIO io_message_loop_
;
312 net::FakeURLFetcherFactory factory_
;
313 // Only used if the SuggestionsService is built with mocks. Not owned.
314 MockImageManager
* mock_thumbnail_manager_
;
315 MockBlacklistStore
* mock_blacklist_store_
;
316 TestSuggestionsStore
* test_suggestions_store_
;
317 scoped_refptr
<net::TestURLRequestContextGetter
> request_context_
;
320 DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest
);
323 TEST_F(SuggestionsServiceTest
, FetchSuggestionsData
) {
324 FetchSuggestionsDataHelper(INITIALIZED_ENABLED_HISTORY
);
327 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataSyncNotInitializedEnabled
) {
328 FetchSuggestionsDataHelper(NOT_INITIALIZED_ENABLED
);
331 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataSyncDisabled
) {
332 scoped_ptr
<SuggestionsService
> suggestions_service(
333 CreateSuggestionsServiceWithMocks());
334 EXPECT_TRUE(suggestions_service
!= NULL
);
336 // Send the request. Cache is cleared and empty data will be returned to the
338 suggestions_service
->FetchSuggestionsData(
339 SYNC_OR_HISTORY_SYNC_DISABLED
,
340 base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile
,
341 base::Unretained(this)));
343 // Ensure that ExpectEmptySuggestionsProfile ran once.
344 EXPECT_EQ(1, suggestions_empty_data_count_
);
347 TEST_F(SuggestionsServiceTest
, IssueRequestIfNoneOngoingError
) {
348 scoped_ptr
<SuggestionsService
> suggestions_service(
349 CreateSuggestionsServiceWithMocks());
350 EXPECT_TRUE(suggestions_service
!= NULL
);
352 // Fake a request error.
353 factory_
.SetFakeResponse(GURL(kSuggestionsURL
), "irrelevant", net::HTTP_OK
,
354 net::URLRequestStatus::FAILED
);
356 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
357 .WillOnce(Return(false));
359 // Send the request. Empty data will be returned to the callback.
360 suggestions_service
->IssueRequestIfNoneOngoing(GURL(kSuggestionsURL
));
362 // (Testing only) wait until suggestion fetch is complete.
363 io_message_loop_
.RunUntilIdle();
366 TEST_F(SuggestionsServiceTest
, IssueRequestIfNoneOngoingResponseNotOK
) {
367 scoped_ptr
<SuggestionsService
> suggestions_service(
368 CreateSuggestionsServiceWithMocks());
369 EXPECT_TRUE(suggestions_service
!= NULL
);
371 // Fake a non-200 response code.
372 factory_
.SetFakeResponse(GURL(kSuggestionsURL
), "irrelevant",
373 net::HTTP_BAD_REQUEST
,
374 net::URLRequestStatus::SUCCESS
);
376 // Expect that an upload to the blacklist is scheduled.
377 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
378 .WillOnce(Return(false));
380 // Send the request. Empty data will be returned to the callback.
381 suggestions_service
->IssueRequestIfNoneOngoing(GURL(kSuggestionsURL
));
383 // (Testing only) wait until suggestion fetch is complete.
384 io_message_loop_
.RunUntilIdle();
386 // Expect no suggestions in the cache.
387 SuggestionsProfile empty_suggestions
;
388 EXPECT_FALSE(test_suggestions_store_
->LoadSuggestions(&empty_suggestions
));
391 TEST_F(SuggestionsServiceTest
, BlacklistURL
) {
392 scoped_ptr
<SuggestionsService
> suggestions_service(
393 CreateSuggestionsServiceWithMocks());
394 EXPECT_TRUE(suggestions_service
!= NULL
);
395 base::TimeDelta no_delay
= base::TimeDelta::FromSeconds(0);
396 suggestions_service
->set_blacklist_delay(no_delay
);
398 GURL
blacklist_url(kBlacklistUrl
);
399 std::string request_url
= GetExpectedBlacklistRequestUrl(blacklist_url
);
400 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
401 factory_
.SetFakeResponse(GURL(request_url
),
402 suggestions_profile
.SerializeAsString(),
403 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
404 EXPECT_CALL(*mock_thumbnail_manager_
,
405 Initialize(EqualsProto(suggestions_profile
)));
407 // Expected calls to the blacklist store.
408 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
409 .WillOnce(Return(true));
410 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
411 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
412 .WillOnce(DoAll(SetArgPointee
<0>(no_delay
), Return(true)))
413 .WillOnce(Return(false));
414 EXPECT_CALL(*mock_blacklist_store_
, GetCandidateForUpload(_
))
415 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url
), Return(true)));
416 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url
)))
417 .WillOnce(Return(true));
419 Blacklist(suggestions_service
.get(), blacklist_url
);
421 // Wait on the upload task. This only works when the scheduling task is not
422 // for future execution (note how both the SuggestionsService's scheduling
423 // delay and the BlacklistStore's candidacy delay are zero). Then wait on
424 // the blacklist request, then again on the next blacklist scheduling task.
425 base::MessageLoop::current()->RunUntilIdle();
426 io_message_loop_
.RunUntilIdle();
427 base::MessageLoop::current()->RunUntilIdle();
429 EXPECT_EQ(1, suggestions_data_callback_count_
);
430 EXPECT_FALSE(blacklisting_failed_
);
431 CheckSuggestionsData();
434 TEST_F(SuggestionsServiceTest
, BlacklistURLFails
) {
435 scoped_ptr
<SuggestionsService
> suggestions_service(
436 CreateSuggestionsServiceWithMocks());
437 EXPECT_TRUE(suggestions_service
!= NULL
);
438 GURL
blacklist_url(kBlacklistUrl
);
439 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
440 .WillOnce(Return(false));
442 Blacklist(suggestions_service
.get(), blacklist_url
);
444 EXPECT_TRUE(blacklisting_failed_
);
445 EXPECT_EQ(0, suggestions_data_callback_count_
);
448 // Initial blacklist request fails, triggering a second which succeeds.
449 TEST_F(SuggestionsServiceTest
, BlacklistURLRequestFails
) {
450 scoped_ptr
<SuggestionsService
> suggestions_service(
451 CreateSuggestionsServiceWithMocks());
452 EXPECT_TRUE(suggestions_service
!= NULL
);
453 base::TimeDelta no_delay
= base::TimeDelta::FromSeconds(0);
454 suggestions_service
->set_blacklist_delay(no_delay
);
456 GURL
blacklist_url(kBlacklistUrl
);
457 std::string request_url
= GetExpectedBlacklistRequestUrl(blacklist_url
);
458 GURL
blacklist_url_alt(kBlacklistUrlAlt
);
459 std::string request_url_alt
= GetExpectedBlacklistRequestUrl(
461 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
463 // Note: we want to set the response for the blacklist URL to first
464 // succeed, then fail. This doesn't seem possible. For simplicity of testing,
465 // we'll pretend the URL changed in the BlacklistStore between the first and
466 // the second request, and adjust expectations accordingly.
467 factory_
.SetFakeResponse(GURL(request_url
), "irrelevant", net::HTTP_OK
,
468 net::URLRequestStatus::FAILED
);
469 factory_
.SetFakeResponse(GURL(request_url_alt
),
470 suggestions_profile
.SerializeAsString(),
471 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
474 EXPECT_CALL(*mock_thumbnail_manager_
,
475 Initialize(EqualsProto(suggestions_profile
)));
476 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
477 .WillOnce(Return(true));
478 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
479 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
480 .WillOnce(DoAll(SetArgPointee
<0>(no_delay
), Return(true)))
481 .WillOnce(DoAll(SetArgPointee
<0>(no_delay
), Return(true)))
482 .WillOnce(Return(false));
483 EXPECT_CALL(*mock_blacklist_store_
, GetCandidateForUpload(_
))
484 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url
), Return(true)))
485 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url_alt
), Return(true)));
486 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url_alt
)))
487 .WillOnce(Return(true));
489 // Blacklist call, first request attempt.
490 Blacklist(suggestions_service
.get(), blacklist_url
);
491 EXPECT_EQ(1, suggestions_data_callback_count_
);
492 EXPECT_FALSE(blacklisting_failed_
);
494 // Wait for the first scheduling, the first request, the second scheduling,
495 // second request and the third scheduling. Again, note that calling
496 // RunUntilIdle on the MessageLoop only works when the task is not posted for
498 base::MessageLoop::current()->RunUntilIdle();
499 io_message_loop_
.RunUntilIdle();
500 base::MessageLoop::current()->RunUntilIdle();
501 io_message_loop_
.RunUntilIdle();
502 base::MessageLoop::current()->RunUntilIdle();
503 CheckSuggestionsData();
506 TEST_F(SuggestionsServiceTest
, UndoBlacklistURL
) {
507 scoped_ptr
<SuggestionsService
> suggestions_service(
508 CreateSuggestionsServiceWithMocks());
509 EXPECT_TRUE(suggestions_service
!= NULL
);
510 // Ensure scheduling the request doesn't happen before undo.
511 base::TimeDelta delay
= base::TimeDelta::FromHours(1);
512 suggestions_service
->set_blacklist_delay(delay
);
513 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
514 GURL
blacklist_url(kBlacklistUrl
);
516 // Blacklist expectations.
517 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
518 .WillOnce(Return(true));
519 EXPECT_CALL(*mock_thumbnail_manager_
,
520 Initialize(EqualsProto(suggestions_profile
)))
522 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
))
524 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
525 .WillOnce(DoAll(SetArgPointee
<0>(delay
), Return(true)));
526 // Undo expectations.
527 EXPECT_CALL(*mock_blacklist_store_
,
528 GetTimeUntilURLReadyForUpload(Eq(blacklist_url
), _
))
529 .WillOnce(DoAll(SetArgPointee
<1>(delay
), Return(true)));
530 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url
)))
531 .WillOnce(Return(true));
533 Blacklist(suggestions_service
.get(), blacklist_url
);
534 UndoBlacklist(suggestions_service
.get(), blacklist_url
);
536 EXPECT_EQ(2, suggestions_data_callback_count_
);
537 EXPECT_FALSE(blacklisting_failed_
);
538 EXPECT_FALSE(undo_blacklisting_failed_
);
541 TEST_F(SuggestionsServiceTest
, ClearBlacklist
) {
542 scoped_ptr
<SuggestionsService
> suggestions_service(
543 CreateSuggestionsServiceWithMocks());
544 EXPECT_TRUE(suggestions_service
!= NULL
);
545 // Ensure scheduling the request doesn't happen before undo.
546 base::TimeDelta delay
= base::TimeDelta::FromHours(1);
547 suggestions_service
->set_blacklist_delay(delay
);
548 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
549 GURL
blacklist_url(kBlacklistUrl
);
551 factory_
.SetFakeResponse(GURL(suggestions::kSuggestionsBlacklistClearURL
),
552 suggestions_profile
.SerializeAsString(),
553 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
555 // Blacklist expectations.
556 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
557 .WillOnce(Return(true));
558 EXPECT_CALL(*mock_thumbnail_manager_
,
559 Initialize(EqualsProto(suggestions_profile
)))
561 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
)).Times(AnyNumber());
562 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
563 .WillOnce(DoAll(SetArgPointee
<0>(delay
), Return(true)));
564 EXPECT_CALL(*mock_blacklist_store_
, ClearBlacklist());
566 Blacklist(suggestions_service
.get(), blacklist_url
);
567 suggestions_service
->ClearBlacklist(base::Bind(
568 &SuggestionsServiceTest::CheckCallback
, base::Unretained(this)));
570 EXPECT_EQ(2, suggestions_data_callback_count_
);
571 EXPECT_FALSE(blacklisting_failed_
);
574 TEST_F(SuggestionsServiceTest
, UndoBlacklistURLFailsIfNotInBlacklist
) {
575 UndoBlacklistURLFailsHelper(true);
578 TEST_F(SuggestionsServiceTest
, UndoBlacklistURLFailsIfAlreadyCandidate
) {
579 UndoBlacklistURLFailsHelper(false);
582 TEST_F(SuggestionsServiceTest
, GetBlacklistedUrl
) {
583 scoped_ptr
<GURL
> request_url
;
584 scoped_ptr
<net::FakeURLFetcher
> fetcher
;
587 // Not a blacklist request.
588 request_url
.reset(new GURL("http://not-blacklisting.com/a?b=c"));
589 fetcher
= CreateURLFetcher(*request_url
, NULL
, "", net::HTTP_OK
,
590 net::URLRequestStatus::SUCCESS
);
591 EXPECT_FALSE(SuggestionsService::GetBlacklistedUrl(*fetcher
, &retrieved_url
));
593 // An actual blacklist request.
594 string blacklisted_url
= "http://blacklisted.com/a?b=c&d=e";
595 string encoded_blacklisted_url
=
596 "http%3A%2F%2Fblacklisted.com%2Fa%3Fb%3Dc%26d%3De";
597 string
blacklist_request_prefix(kSuggestionsBlacklistURLPrefix
);
599 new GURL(blacklist_request_prefix
+ encoded_blacklisted_url
));
601 fetcher
= CreateURLFetcher(*request_url
, NULL
, "", net::HTTP_OK
,
602 net::URLRequestStatus::SUCCESS
);
603 EXPECT_TRUE(SuggestionsService::GetBlacklistedUrl(*fetcher
, &retrieved_url
));
604 EXPECT_EQ(blacklisted_url
, retrieved_url
.spec());
607 TEST_F(SuggestionsServiceTest
, UpdateBlacklistDelay
) {
608 scoped_ptr
<SuggestionsService
> suggestions_service(
609 CreateSuggestionsServiceWithMocks());
610 base::TimeDelta initial_delay
= suggestions_service
->blacklist_delay();
612 // Delay unchanged on success.
613 suggestions_service
->UpdateBlacklistDelay(true);
614 EXPECT_EQ(initial_delay
, suggestions_service
->blacklist_delay());
616 // Delay increases on failure.
617 suggestions_service
->UpdateBlacklistDelay(false);
618 EXPECT_GT(suggestions_service
->blacklist_delay(), initial_delay
);
620 // Delay resets on success.
621 suggestions_service
->UpdateBlacklistDelay(true);
622 EXPECT_EQ(initial_delay
, suggestions_service
->blacklist_delay());
625 TEST_F(SuggestionsServiceTest
, CheckDefaultTimeStamps
) {
626 scoped_ptr
<SuggestionsService
> suggestions_service(
627 CreateSuggestionsServiceWithMocks());
628 SuggestionsProfile suggestions
=
629 CreateSuggestionsProfileWithExpiryTimestamps();
630 suggestions_service
->SetDefaultExpiryTimestamp(&suggestions
,
632 EXPECT_EQ(kTestSetExpiry
, suggestions
.suggestions(0).expiry_ts());
633 EXPECT_EQ(kTestDefaultExpiry
, suggestions
.suggestions(1).expiry_ts());
635 } // namespace suggestions