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 kTestImpressionUrl
[] =
43 "https://www.google.com/chromesuggestions/click?q=123&cd=-1";
44 const char kTestClickUrl
[] =
45 "https://www.google.com/chromesuggestions/click?q=123&cd=0";
46 const char kBlacklistUrl
[] = "http://blacklist.com";
47 const char kBlacklistUrlAlt
[] = "http://blacklist-atl.com";
48 const int64 kTestDefaultExpiry
= 1402200000000000;
49 const int64 kTestSetExpiry
= 1404792000000000;
51 scoped_ptr
<net::FakeURLFetcher
> CreateURLFetcher(
52 const GURL
& url
, net::URLFetcherDelegate
* delegate
,
53 const std::string
& response_data
, net::HttpStatusCode response_code
,
54 net::URLRequestStatus::Status status
) {
55 scoped_ptr
<net::FakeURLFetcher
> fetcher(new net::FakeURLFetcher(
56 url
, delegate
, response_data
, response_code
, status
));
58 if (response_code
== net::HTTP_OK
) {
59 scoped_refptr
<net::HttpResponseHeaders
> download_headers(
60 new net::HttpResponseHeaders(""));
61 download_headers
->AddHeader("Content-Type: text/html");
62 fetcher
->set_response_headers(download_headers
);
64 return fetcher
.Pass();
67 std::string
GetExpectedBlacklistRequestUrl(const GURL
& blacklist_url
) {
68 std::stringstream request_url
;
69 request_url
<< suggestions::kSuggestionsBlacklistURLPrefix
70 << net::EscapeQueryParamValue(blacklist_url
.spec(), true);
71 return request_url
.str();
74 // GMock matcher for protobuf equality.
75 MATCHER_P(EqualsProto
, message
, "") {
76 // This implementation assumes protobuf serialization is deterministic, which
77 // is true in practice but technically not something that code is supposed
78 // to rely on. However, it vastly simplifies the implementation.
79 std::string expected_serialized
, actual_serialized
;
80 message
.SerializeToString(&expected_serialized
);
81 arg
.SerializeToString(&actual_serialized
);
82 return expected_serialized
== actual_serialized
;
87 namespace suggestions
{
89 SuggestionsProfile
CreateSuggestionsProfile() {
90 SuggestionsProfile profile
;
91 profile
.set_timestamp(123);
92 ChromeSuggestion
* suggestion
= profile
.add_suggestions();
93 suggestion
->set_title(kTestTitle
);
94 suggestion
->set_url(kTestUrl
);
95 suggestion
->set_expiry_ts(kTestSetExpiry
);
99 // Creates one suggestion with expiry timestamp and one without.
100 SuggestionsProfile
CreateSuggestionsProfileWithExpiryTimestamps() {
101 SuggestionsProfile profile
;
102 profile
.set_timestamp(123);
103 ChromeSuggestion
* suggestion
= profile
.add_suggestions();
104 suggestion
->set_title(kTestTitle
);
105 suggestion
->set_url(kTestUrl
);
106 suggestion
->set_expiry_ts(kTestSetExpiry
);
108 suggestion
= profile
.add_suggestions();
109 suggestion
->set_title(kTestTitle
);
110 suggestion
->set_url(kTestUrl
);
115 class TestSuggestionsStore
: public suggestions::SuggestionsStore
{
117 TestSuggestionsStore() {
118 cached_suggestions
= CreateSuggestionsProfile();
120 bool LoadSuggestions(SuggestionsProfile
* suggestions
) override
{
121 suggestions
->CopyFrom(cached_suggestions
);
122 return cached_suggestions
.suggestions_size();
124 bool StoreSuggestions(const SuggestionsProfile
& suggestions
)
126 cached_suggestions
.CopyFrom(suggestions
);
129 void ClearSuggestions() override
{
130 cached_suggestions
= SuggestionsProfile();
133 SuggestionsProfile cached_suggestions
;
136 class MockImageManager
: public suggestions::ImageManager
{
138 MockImageManager() {}
139 virtual ~MockImageManager() {}
140 MOCK_METHOD1(Initialize
, void(const SuggestionsProfile
&));
141 MOCK_METHOD2(GetImageForURL
,
143 base::Callback
<void(const GURL
&, const SkBitmap
*)>));
144 MOCK_METHOD2(AddImageURL
, void(const GURL
&, const GURL
&));
147 class MockBlacklistStore
: public suggestions::BlacklistStore
{
149 MOCK_METHOD1(BlacklistUrl
, bool(const GURL
&));
150 MOCK_METHOD0(IsEmpty
, bool());
151 MOCK_METHOD1(GetTimeUntilReadyForUpload
, bool(base::TimeDelta
*));
152 MOCK_METHOD2(GetTimeUntilURLReadyForUpload
,
153 bool(const GURL
&, base::TimeDelta
*));
154 MOCK_METHOD1(GetCandidateForUpload
, bool(GURL
*));
155 MOCK_METHOD1(RemoveUrl
, bool(const GURL
&));
156 MOCK_METHOD1(FilterSuggestions
, void(SuggestionsProfile
*));
157 MOCK_METHOD0(ClearBlacklist
, void());
160 class SuggestionsServiceTest
: public testing::Test
{
162 void CheckCallback(const SuggestionsProfile
& suggestions_profile
) {
163 ++suggestions_data_callback_count_
;
166 void CheckSuggestionsData() {
167 SuggestionsProfile suggestions_profile
;
168 test_suggestions_store_
->LoadSuggestions(&suggestions_profile
);
169 EXPECT_EQ(1, suggestions_profile
.suggestions_size());
170 EXPECT_EQ(kTestTitle
, suggestions_profile
.suggestions(0).title());
171 EXPECT_EQ(kTestUrl
, suggestions_profile
.suggestions(0).url());
172 EXPECT_EQ(kTestFaviconUrl
,
173 suggestions_profile
.suggestions(0).favicon_url());
174 EXPECT_EQ(kTestImpressionUrl
,
175 suggestions_profile
.suggestions(0).impression_url());
176 EXPECT_EQ(kTestClickUrl
, suggestions_profile
.suggestions(0).click_url());
179 void SetBlacklistFailure() {
180 blacklisting_failed_
= true;
183 void SetUndoBlacklistFailure() {
184 undo_blacklisting_failed_
= true;
187 void ExpectEmptySuggestionsProfile(const SuggestionsProfile
& profile
) {
188 EXPECT_EQ(0, profile
.suggestions_size());
189 ++suggestions_empty_data_count_
;
192 int suggestions_data_callback_count_
;
193 int suggestions_empty_data_count_
;
194 bool blacklisting_failed_
;
195 bool undo_blacklisting_failed_
;
198 SuggestionsServiceTest()
199 : suggestions_data_callback_count_(0),
200 suggestions_empty_data_count_(0),
201 blacklisting_failed_(false),
202 undo_blacklisting_failed_(false),
203 factory_(NULL
, base::Bind(&CreateURLFetcher
)),
204 mock_thumbnail_manager_(NULL
),
205 mock_blacklist_store_(NULL
),
206 test_suggestions_store_(NULL
) {}
208 ~SuggestionsServiceTest() override
{}
210 void SetUp() override
{
212 new net::TestURLRequestContextGetter(io_message_loop_
.task_runner());
215 void FetchSuggestionsDataHelper(SyncState sync_state
) {
216 scoped_ptr
<SuggestionsService
> suggestions_service(
217 CreateSuggestionsServiceWithMocks());
218 EXPECT_TRUE(suggestions_service
!= NULL
);
220 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
222 // Set up net::FakeURLFetcherFactory.
223 factory_
.SetFakeResponse(GURL(kSuggestionsURL
),
224 suggestions_profile
.SerializeAsString(),
225 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
228 EXPECT_CALL(*mock_thumbnail_manager_
,
229 Initialize(EqualsProto(suggestions_profile
)));
230 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
231 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
232 .WillOnce(Return(false));
234 // Send the request. The data will be returned to the callback.
235 suggestions_service
->FetchSuggestionsData(
236 sync_state
, base::Bind(&SuggestionsServiceTest::CheckCallback
,
237 base::Unretained(this)));
239 // Ensure that CheckSuggestionsData() ran once.
240 EXPECT_EQ(1, suggestions_data_callback_count_
);
242 // Let the network request run.
243 io_message_loop_
.RunUntilIdle();
245 CheckSuggestionsData();
248 SuggestionsService
* CreateSuggestionsServiceWithMocks() {
249 // These objects are owned by the returned SuggestionsService, but we keep
250 // the pointer around for testing.
251 test_suggestions_store_
= new TestSuggestionsStore();
252 mock_thumbnail_manager_
= new StrictMock
<MockImageManager
>();
253 mock_blacklist_store_
= new StrictMock
<MockBlacklistStore
>();
254 return new SuggestionsService(
255 request_context_
.get(),
256 scoped_ptr
<SuggestionsStore
>(test_suggestions_store_
),
257 scoped_ptr
<ImageManager
>(mock_thumbnail_manager_
),
258 scoped_ptr
<BlacklistStore
>(mock_blacklist_store_
));
261 void Blacklist(SuggestionsService
* suggestions_service
, GURL url
) {
262 suggestions_service
->BlacklistURL(
263 url
, base::Bind(&SuggestionsServiceTest::CheckCallback
,
264 base::Unretained(this)),
265 base::Bind(&SuggestionsServiceTest::SetBlacklistFailure
,
266 base::Unretained(this)));
269 void UndoBlacklist(SuggestionsService
* suggestions_service
, GURL url
) {
270 suggestions_service
->UndoBlacklistURL(
271 url
, base::Bind(&SuggestionsServiceTest::CheckCallback
,
272 base::Unretained(this)),
273 base::Bind(&SuggestionsServiceTest::SetUndoBlacklistFailure
,
274 base::Unretained(this)));
277 // Helper for Undo failure tests. Depending on |is_uploaded|, tests either
278 // the case where the URL is no longer in the local blacklist or the case
279 // in which it's not yet candidate for upload.
280 void UndoBlacklistURLFailsHelper(bool is_uploaded
) {
281 scoped_ptr
<SuggestionsService
> suggestions_service(
282 CreateSuggestionsServiceWithMocks());
283 EXPECT_TRUE(suggestions_service
!= NULL
);
284 // Ensure scheduling the request doesn't happen before undo.
285 base::TimeDelta delay
= base::TimeDelta::FromHours(1);
286 suggestions_service
->set_blacklist_delay(delay
);
287 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
288 GURL
blacklist_url(kBlacklistUrl
);
290 // Blacklist expectations.
291 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
292 .WillOnce(Return(true));
293 EXPECT_CALL(*mock_thumbnail_manager_
,
294 Initialize(EqualsProto(suggestions_profile
)));
295 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
296 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
297 .WillOnce(DoAll(SetArgPointee
<0>(delay
), Return(true)));
298 // Undo expectations.
300 // URL is not in local blacklist.
301 EXPECT_CALL(*mock_blacklist_store_
,
302 GetTimeUntilURLReadyForUpload(Eq(blacklist_url
), _
))
303 .WillOnce(Return(false));
305 // URL is not yet candidate for upload.
306 base::TimeDelta negative_delay
= base::TimeDelta::FromHours(-1);
307 EXPECT_CALL(*mock_blacklist_store_
,
308 GetTimeUntilURLReadyForUpload(Eq(blacklist_url
), _
))
309 .WillOnce(DoAll(SetArgPointee
<1>(negative_delay
), Return(true)));
312 Blacklist(suggestions_service
.get(), blacklist_url
);
313 UndoBlacklist(suggestions_service
.get(), blacklist_url
);
315 EXPECT_EQ(1, suggestions_data_callback_count_
);
316 EXPECT_FALSE(blacklisting_failed_
);
317 EXPECT_TRUE(undo_blacklisting_failed_
);
321 base::MessageLoopForIO io_message_loop_
;
322 net::FakeURLFetcherFactory factory_
;
323 // Only used if the SuggestionsService is built with mocks. Not owned.
324 MockImageManager
* mock_thumbnail_manager_
;
325 MockBlacklistStore
* mock_blacklist_store_
;
326 TestSuggestionsStore
* test_suggestions_store_
;
327 scoped_refptr
<net::TestURLRequestContextGetter
> request_context_
;
330 DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest
);
333 TEST_F(SuggestionsServiceTest
, FetchSuggestionsData
) {
334 FetchSuggestionsDataHelper(INITIALIZED_ENABLED_HISTORY
);
337 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataSyncNotInitializedEnabled
) {
338 FetchSuggestionsDataHelper(NOT_INITIALIZED_ENABLED
);
341 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataSyncDisabled
) {
342 scoped_ptr
<SuggestionsService
> suggestions_service(
343 CreateSuggestionsServiceWithMocks());
344 EXPECT_TRUE(suggestions_service
!= NULL
);
346 // Send the request. Cache is cleared and empty data will be returned to the
348 suggestions_service
->FetchSuggestionsData(
349 SYNC_OR_HISTORY_SYNC_DISABLED
,
350 base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile
,
351 base::Unretained(this)));
353 // Ensure that ExpectEmptySuggestionsProfile ran once.
354 EXPECT_EQ(1, suggestions_empty_data_count_
);
357 TEST_F(SuggestionsServiceTest
, IssueRequestIfNoneOngoingError
) {
358 scoped_ptr
<SuggestionsService
> suggestions_service(
359 CreateSuggestionsServiceWithMocks());
360 EXPECT_TRUE(suggestions_service
!= NULL
);
362 // Fake a request error.
363 factory_
.SetFakeResponse(GURL(kSuggestionsURL
), "irrelevant", net::HTTP_OK
,
364 net::URLRequestStatus::FAILED
);
366 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
367 .WillOnce(Return(false));
369 // Send the request. Empty data will be returned to the callback.
370 suggestions_service
->IssueRequestIfNoneOngoing(GURL(kSuggestionsURL
));
372 // (Testing only) wait until suggestion fetch is complete.
373 io_message_loop_
.RunUntilIdle();
376 TEST_F(SuggestionsServiceTest
, IssueRequestIfNoneOngoingResponseNotOK
) {
377 scoped_ptr
<SuggestionsService
> suggestions_service(
378 CreateSuggestionsServiceWithMocks());
379 EXPECT_TRUE(suggestions_service
!= NULL
);
381 // Fake a non-200 response code.
382 factory_
.SetFakeResponse(GURL(kSuggestionsURL
), "irrelevant",
383 net::HTTP_BAD_REQUEST
,
384 net::URLRequestStatus::SUCCESS
);
386 // Expect that an upload to the blacklist is scheduled.
387 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
388 .WillOnce(Return(false));
390 // Send the request. Empty data will be returned to the callback.
391 suggestions_service
->IssueRequestIfNoneOngoing(GURL(kSuggestionsURL
));
393 // (Testing only) wait until suggestion fetch is complete.
394 io_message_loop_
.RunUntilIdle();
396 // Expect no suggestions in the cache.
397 SuggestionsProfile empty_suggestions
;
398 EXPECT_FALSE(test_suggestions_store_
->LoadSuggestions(&empty_suggestions
));
401 TEST_F(SuggestionsServiceTest
, BlacklistURL
) {
402 scoped_ptr
<SuggestionsService
> suggestions_service(
403 CreateSuggestionsServiceWithMocks());
404 EXPECT_TRUE(suggestions_service
!= NULL
);
405 base::TimeDelta no_delay
= base::TimeDelta::FromSeconds(0);
406 suggestions_service
->set_blacklist_delay(no_delay
);
408 GURL
blacklist_url(kBlacklistUrl
);
409 std::string request_url
= GetExpectedBlacklistRequestUrl(blacklist_url
);
410 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
411 factory_
.SetFakeResponse(GURL(request_url
),
412 suggestions_profile
.SerializeAsString(),
413 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
414 EXPECT_CALL(*mock_thumbnail_manager_
,
415 Initialize(EqualsProto(suggestions_profile
)));
417 // Expected calls to the blacklist store.
418 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
419 .WillOnce(Return(true));
420 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
421 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
422 .WillOnce(DoAll(SetArgPointee
<0>(no_delay
), Return(true)))
423 .WillOnce(Return(false));
424 EXPECT_CALL(*mock_blacklist_store_
, GetCandidateForUpload(_
))
425 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url
), Return(true)));
426 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url
)))
427 .WillOnce(Return(true));
429 Blacklist(suggestions_service
.get(), blacklist_url
);
431 // Wait on the upload task. This only works when the scheduling task is not
432 // for future execution (note how both the SuggestionsService's scheduling
433 // delay and the BlacklistStore's candidacy delay are zero). Then wait on
434 // the blacklist request, then again on the next blacklist scheduling task.
435 base::MessageLoop::current()->RunUntilIdle();
436 io_message_loop_
.RunUntilIdle();
437 base::MessageLoop::current()->RunUntilIdle();
439 EXPECT_EQ(1, suggestions_data_callback_count_
);
440 EXPECT_FALSE(blacklisting_failed_
);
441 CheckSuggestionsData();
444 TEST_F(SuggestionsServiceTest
, BlacklistURLFails
) {
445 scoped_ptr
<SuggestionsService
> suggestions_service(
446 CreateSuggestionsServiceWithMocks());
447 EXPECT_TRUE(suggestions_service
!= NULL
);
448 GURL
blacklist_url(kBlacklistUrl
);
449 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
450 .WillOnce(Return(false));
452 Blacklist(suggestions_service
.get(), blacklist_url
);
454 EXPECT_TRUE(blacklisting_failed_
);
455 EXPECT_EQ(0, suggestions_data_callback_count_
);
458 // Initial blacklist request fails, triggering a second which succeeds.
459 TEST_F(SuggestionsServiceTest
, BlacklistURLRequestFails
) {
460 scoped_ptr
<SuggestionsService
> suggestions_service(
461 CreateSuggestionsServiceWithMocks());
462 EXPECT_TRUE(suggestions_service
!= NULL
);
463 base::TimeDelta no_delay
= base::TimeDelta::FromSeconds(0);
464 suggestions_service
->set_blacklist_delay(no_delay
);
466 GURL
blacklist_url(kBlacklistUrl
);
467 std::string request_url
= GetExpectedBlacklistRequestUrl(blacklist_url
);
468 GURL
blacklist_url_alt(kBlacklistUrlAlt
);
469 std::string request_url_alt
= GetExpectedBlacklistRequestUrl(
471 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
473 // Note: we want to set the response for the blacklist URL to first
474 // succeed, then fail. This doesn't seem possible. For simplicity of testing,
475 // we'll pretend the URL changed in the BlacklistStore between the first and
476 // the second request, and adjust expectations accordingly.
477 factory_
.SetFakeResponse(GURL(request_url
), "irrelevant", net::HTTP_OK
,
478 net::URLRequestStatus::FAILED
);
479 factory_
.SetFakeResponse(GURL(request_url_alt
),
480 suggestions_profile
.SerializeAsString(),
481 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
484 EXPECT_CALL(*mock_thumbnail_manager_
,
485 Initialize(EqualsProto(suggestions_profile
)));
486 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
487 .WillOnce(Return(true));
488 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
489 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
490 .WillOnce(DoAll(SetArgPointee
<0>(no_delay
), Return(true)))
491 .WillOnce(DoAll(SetArgPointee
<0>(no_delay
), Return(true)))
492 .WillOnce(Return(false));
493 EXPECT_CALL(*mock_blacklist_store_
, GetCandidateForUpload(_
))
494 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url
), Return(true)))
495 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url_alt
), Return(true)));
496 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url_alt
)))
497 .WillOnce(Return(true));
499 // Blacklist call, first request attempt.
500 Blacklist(suggestions_service
.get(), blacklist_url
);
501 EXPECT_EQ(1, suggestions_data_callback_count_
);
502 EXPECT_FALSE(blacklisting_failed_
);
504 // Wait for the first scheduling, the first request, the second scheduling,
505 // second request and the third scheduling. Again, note that calling
506 // RunUntilIdle on the MessageLoop only works when the task is not posted for
508 base::MessageLoop::current()->RunUntilIdle();
509 io_message_loop_
.RunUntilIdle();
510 base::MessageLoop::current()->RunUntilIdle();
511 io_message_loop_
.RunUntilIdle();
512 base::MessageLoop::current()->RunUntilIdle();
513 CheckSuggestionsData();
516 TEST_F(SuggestionsServiceTest
, UndoBlacklistURL
) {
517 scoped_ptr
<SuggestionsService
> suggestions_service(
518 CreateSuggestionsServiceWithMocks());
519 EXPECT_TRUE(suggestions_service
!= NULL
);
520 // Ensure scheduling the request doesn't happen before undo.
521 base::TimeDelta delay
= base::TimeDelta::FromHours(1);
522 suggestions_service
->set_blacklist_delay(delay
);
523 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
524 GURL
blacklist_url(kBlacklistUrl
);
526 // Blacklist expectations.
527 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
528 .WillOnce(Return(true));
529 EXPECT_CALL(*mock_thumbnail_manager_
,
530 Initialize(EqualsProto(suggestions_profile
)))
532 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
))
534 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
535 .WillOnce(DoAll(SetArgPointee
<0>(delay
), Return(true)));
536 // Undo expectations.
537 EXPECT_CALL(*mock_blacklist_store_
,
538 GetTimeUntilURLReadyForUpload(Eq(blacklist_url
), _
))
539 .WillOnce(DoAll(SetArgPointee
<1>(delay
), Return(true)));
540 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url
)))
541 .WillOnce(Return(true));
543 Blacklist(suggestions_service
.get(), blacklist_url
);
544 UndoBlacklist(suggestions_service
.get(), blacklist_url
);
546 EXPECT_EQ(2, suggestions_data_callback_count_
);
547 EXPECT_FALSE(blacklisting_failed_
);
548 EXPECT_FALSE(undo_blacklisting_failed_
);
551 TEST_F(SuggestionsServiceTest
, ClearBlacklist
) {
552 scoped_ptr
<SuggestionsService
> suggestions_service(
553 CreateSuggestionsServiceWithMocks());
554 EXPECT_TRUE(suggestions_service
!= NULL
);
555 // Ensure scheduling the request doesn't happen before undo.
556 base::TimeDelta delay
= base::TimeDelta::FromHours(1);
557 suggestions_service
->set_blacklist_delay(delay
);
558 SuggestionsProfile suggestions_profile
= CreateSuggestionsProfile();
559 GURL
blacklist_url(kBlacklistUrl
);
561 factory_
.SetFakeResponse(GURL(suggestions::kSuggestionsBlacklistClearURL
),
562 suggestions_profile
.SerializeAsString(),
563 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
565 // Blacklist expectations.
566 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
567 .WillOnce(Return(true));
568 EXPECT_CALL(*mock_thumbnail_manager_
,
569 Initialize(EqualsProto(suggestions_profile
)))
571 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
)).Times(AnyNumber());
572 EXPECT_CALL(*mock_blacklist_store_
, GetTimeUntilReadyForUpload(_
))
573 .WillOnce(DoAll(SetArgPointee
<0>(delay
), Return(true)));
574 EXPECT_CALL(*mock_blacklist_store_
, ClearBlacklist());
576 Blacklist(suggestions_service
.get(), blacklist_url
);
577 suggestions_service
->ClearBlacklist(base::Bind(
578 &SuggestionsServiceTest::CheckCallback
, base::Unretained(this)));
580 EXPECT_EQ(2, suggestions_data_callback_count_
);
581 EXPECT_FALSE(blacklisting_failed_
);
584 TEST_F(SuggestionsServiceTest
, UndoBlacklistURLFailsIfNotInBlacklist
) {
585 UndoBlacklistURLFailsHelper(true);
588 TEST_F(SuggestionsServiceTest
, UndoBlacklistURLFailsIfAlreadyCandidate
) {
589 UndoBlacklistURLFailsHelper(false);
592 TEST_F(SuggestionsServiceTest
, GetBlacklistedUrl
) {
593 scoped_ptr
<GURL
> request_url
;
594 scoped_ptr
<net::FakeURLFetcher
> fetcher
;
597 // Not a blacklist request.
598 request_url
.reset(new GURL("http://not-blacklisting.com/a?b=c"));
599 fetcher
= CreateURLFetcher(*request_url
, NULL
, "", net::HTTP_OK
,
600 net::URLRequestStatus::SUCCESS
);
601 EXPECT_FALSE(SuggestionsService::GetBlacklistedUrl(*fetcher
, &retrieved_url
));
603 // An actual blacklist request.
604 string blacklisted_url
= "http://blacklisted.com/a?b=c&d=e";
605 string encoded_blacklisted_url
=
606 "http%3A%2F%2Fblacklisted.com%2Fa%3Fb%3Dc%26d%3De";
607 string
blacklist_request_prefix(kSuggestionsBlacklistURLPrefix
);
609 new GURL(blacklist_request_prefix
+ encoded_blacklisted_url
));
611 fetcher
= CreateURLFetcher(*request_url
, NULL
, "", net::HTTP_OK
,
612 net::URLRequestStatus::SUCCESS
);
613 EXPECT_TRUE(SuggestionsService::GetBlacklistedUrl(*fetcher
, &retrieved_url
));
614 EXPECT_EQ(blacklisted_url
, retrieved_url
.spec());
617 TEST_F(SuggestionsServiceTest
, UpdateBlacklistDelay
) {
618 scoped_ptr
<SuggestionsService
> suggestions_service(
619 CreateSuggestionsServiceWithMocks());
620 base::TimeDelta initial_delay
= suggestions_service
->blacklist_delay();
622 // Delay unchanged on success.
623 suggestions_service
->UpdateBlacklistDelay(true);
624 EXPECT_EQ(initial_delay
, suggestions_service
->blacklist_delay());
626 // Delay increases on failure.
627 suggestions_service
->UpdateBlacklistDelay(false);
628 EXPECT_GT(suggestions_service
->blacklist_delay(), initial_delay
);
630 // Delay resets on success.
631 suggestions_service
->UpdateBlacklistDelay(true);
632 EXPECT_EQ(initial_delay
, suggestions_service
->blacklist_delay());
635 TEST_F(SuggestionsServiceTest
, CheckDefaultTimeStamps
) {
636 scoped_ptr
<SuggestionsService
> suggestions_service(
637 CreateSuggestionsServiceWithMocks());
638 SuggestionsProfile suggestions
=
639 CreateSuggestionsProfileWithExpiryTimestamps();
640 suggestions_service
->SetDefaultExpiryTimestamp(&suggestions
,
642 EXPECT_EQ(kTestSetExpiry
, suggestions
.suggestions(0).expiry_ts());
643 EXPECT_EQ(kTestDefaultExpiry
, suggestions
.suggestions(1).expiry_ts());
646 TEST_F(SuggestionsServiceTest
, GetPageThumbnail
) {
647 scoped_ptr
<SuggestionsService
> suggestions_service(
648 CreateSuggestionsServiceWithMocks());
649 ASSERT_TRUE(suggestions_service
!= NULL
);
651 GURL
test_url(kTestUrl
);
652 GURL
thumbnail_url("https://www.thumbnails.com/thumb.jpg");
653 base::Callback
<void(const GURL
&, const SkBitmap
*)> dummy_callback
;
655 EXPECT_CALL(*mock_thumbnail_manager_
, GetImageForURL(test_url
, _
));
656 suggestions_service
->GetPageThumbnail(test_url
, dummy_callback
);
658 EXPECT_CALL(*mock_thumbnail_manager_
, AddImageURL(test_url
, thumbnail_url
));
659 EXPECT_CALL(*mock_thumbnail_manager_
, GetImageForURL(test_url
, _
));
660 suggestions_service
->GetPageThumbnailWithURL(test_url
, thumbnail_url
,
665 } // namespace suggestions