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"
11 #include "base/bind.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/metrics/field_trial.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "components/suggestions/blacklist_store.h"
18 #include "components/suggestions/image_manager.h"
19 #include "components/suggestions/proto/suggestions.pb.h"
20 #include "components/suggestions/suggestions_store.h"
21 #include "components/suggestions/suggestions_utils.h"
22 #include "components/variations/entropy_provider.h"
23 #include "components/variations/variations_associated_data.h"
24 #include "net/http/http_response_headers.h"
25 #include "net/http/http_status_code.h"
26 #include "net/url_request/test_url_fetcher_factory.h"
27 #include "net/url_request/url_request_status.h"
28 #include "net/url_request/url_request_test_util.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "testing/gtest/include/gtest/gtest.h"
34 using ::testing::Return
;
35 using testing::SetArgPointee
;
36 using ::testing::NiceMock
;
37 using ::testing::StrictMock
;
42 const char kFakeSuggestionsURL
[] = "https://mysuggestions.com/proto";
43 const char kFakeSuggestionsCommonParams
[] = "foo=bar";
44 const char kFakeBlacklistPath
[] = "/blacklist";
45 const char kFakeBlacklistUrlParam
[] = "baz";
47 const char kTestTitle
[] = "a title";
48 const char kTestUrl
[] = "http://go.com";
49 const char kBlacklistUrl
[] = "http://blacklist.com";
50 const int64 kTestDefaultExpiry
= 1402200000000000;
51 const int64 kTestSetExpiry
= 1404792000000000;
53 scoped_ptr
<net::FakeURLFetcher
> CreateURLFetcher(
54 const GURL
& url
, net::URLFetcherDelegate
* delegate
,
55 const std::string
& response_data
, net::HttpStatusCode response_code
,
56 net::URLRequestStatus::Status status
) {
57 scoped_ptr
<net::FakeURLFetcher
> fetcher(new net::FakeURLFetcher(
58 url
, delegate
, response_data
, response_code
, status
));
60 if (response_code
== net::HTTP_OK
) {
61 scoped_refptr
<net::HttpResponseHeaders
> download_headers(
62 new net::HttpResponseHeaders(""));
63 download_headers
->AddHeader("Content-Type: text/html");
64 fetcher
->set_response_headers(download_headers
);
66 return fetcher
.Pass();
69 std::string
GetExpectedBlacklistRequestUrl(const GURL
& blacklist_url
) {
70 std::stringstream request_url
;
71 request_url
<< kFakeSuggestionsURL
<< kFakeBlacklistPath
<< "?"
72 << kFakeSuggestionsCommonParams
<< "&" << kFakeBlacklistUrlParam
73 << "=" << net::EscapeQueryParamValue(blacklist_url
.spec(), true);
74 return request_url
.str();
77 // GMock matcher for protobuf equality.
78 MATCHER_P(EqualsProto
, message
, "") {
79 // This implementation assumes protobuf serialization is deterministic, which
80 // is true in practice but technically not something that code is supposed
81 // to rely on. However, it vastly simplifies the implementation.
82 std::string expected_serialized
, actual_serialized
;
83 message
.SerializeToString(&expected_serialized
);
84 arg
.SerializeToString(&actual_serialized
);
85 return expected_serialized
== actual_serialized
;
90 namespace suggestions
{
92 scoped_ptr
<SuggestionsProfile
> CreateSuggestionsProfile() {
93 scoped_ptr
<SuggestionsProfile
> profile(new SuggestionsProfile());
94 ChromeSuggestion
* suggestion
= profile
->add_suggestions();
95 suggestion
->set_title(kTestTitle
);
96 suggestion
->set_url(kTestUrl
);
97 suggestion
->set_expiry_ts(kTestSetExpiry
);
98 return profile
.Pass();
101 // Creates one suggestion with expiry timestamp and one without.
102 SuggestionsProfile
CreateSuggestionsProfileWithExpiryTimestamps() {
103 SuggestionsProfile profile
;
104 ChromeSuggestion
* suggestion
= profile
.add_suggestions();
105 suggestion
->set_title(kTestTitle
);
106 suggestion
->set_url(kTestUrl
);
107 suggestion
->set_expiry_ts(kTestSetExpiry
);
109 suggestion
= profile
.add_suggestions();
110 suggestion
->set_title(kTestTitle
);
111 suggestion
->set_url(kTestUrl
);
116 class MockSuggestionsStore
: public suggestions::SuggestionsStore
{
118 MOCK_METHOD1(LoadSuggestions
, bool(SuggestionsProfile
*));
119 MOCK_METHOD1(StoreSuggestions
, bool(const SuggestionsProfile
&));
120 MOCK_METHOD0(ClearSuggestions
, void());
123 class MockImageManager
: public suggestions::ImageManager
{
125 MockImageManager() {}
126 virtual ~MockImageManager() {}
127 MOCK_METHOD1(Initialize
, void(const SuggestionsProfile
&));
128 MOCK_METHOD2(GetImageForURL
,
130 base::Callback
<void(const GURL
&, const SkBitmap
*)>));
133 class MockBlacklistStore
: public suggestions::BlacklistStore
{
135 MOCK_METHOD1(BlacklistUrl
, bool(const GURL
&));
136 MOCK_METHOD1(GetFirstUrlFromBlacklist
, bool(GURL
*));
137 MOCK_METHOD1(RemoveUrl
, bool(const GURL
&));
138 MOCK_METHOD1(FilterSuggestions
, void(SuggestionsProfile
*));
141 class SuggestionsServiceTest
: public testing::Test
{
143 void CheckSuggestionsData(const SuggestionsProfile
& suggestions_profile
) {
144 EXPECT_EQ(1, suggestions_profile
.suggestions_size());
145 EXPECT_EQ(kTestTitle
, suggestions_profile
.suggestions(0).title());
146 EXPECT_EQ(kTestUrl
, suggestions_profile
.suggestions(0).url());
147 ++suggestions_data_check_count_
;
150 void ExpectEmptySuggestionsProfile(const SuggestionsProfile
& profile
) {
151 EXPECT_EQ(0, profile
.suggestions_size());
152 ++suggestions_empty_data_count_
;
155 int suggestions_data_check_count_
;
156 int suggestions_empty_data_count_
;
159 SuggestionsServiceTest()
160 : suggestions_data_check_count_(0),
161 suggestions_empty_data_count_(0),
162 factory_(NULL
, base::Bind(&CreateURLFetcher
)),
163 mock_suggestions_store_(NULL
),
164 mock_thumbnail_manager_(NULL
) {}
166 virtual ~SuggestionsServiceTest() {}
168 virtual void SetUp() OVERRIDE
{
169 request_context_
= new net::TestURLRequestContextGetter(
170 io_message_loop_
.message_loop_proxy());
173 // Enables the "ChromeSuggestions.Group1" field trial.
174 void EnableFieldTrial(const std::string
& url
,
175 const std::string
& common_params
,
176 const std::string
& blacklist_path
,
177 const std::string
& blacklist_url_param
,
178 bool control_group
) {
179 // Clear the existing |field_trial_list_| to avoid firing a DCHECK.
180 field_trial_list_
.reset(NULL
);
181 field_trial_list_
.reset(
182 new base::FieldTrialList(new metrics::SHA1EntropyProvider("foo")));
184 variations::testing::ClearAllVariationParams();
185 std::map
<std::string
, std::string
> params
;
186 params
[kSuggestionsFieldTrialStateParam
] =
187 kSuggestionsFieldTrialStateEnabled
;
189 params
[kSuggestionsFieldTrialControlParam
] =
190 kSuggestionsFieldTrialStateEnabled
;
192 params
[kSuggestionsFieldTrialURLParam
] = url
;
193 params
[kSuggestionsFieldTrialCommonParamsParam
] = common_params
;
194 params
[kSuggestionsFieldTrialBlacklistPathParam
] = blacklist_path
;
195 params
[kSuggestionsFieldTrialBlacklistUrlParam
] = blacklist_url_param
;
196 variations::AssociateVariationParams(kSuggestionsFieldTrialName
, "Group1",
198 field_trial_
= base::FieldTrialList::CreateFieldTrial(
199 kSuggestionsFieldTrialName
, "Group1");
200 field_trial_
->group();
203 // Should not be called more than once per test since it stashes the
204 // SuggestionsStore in |mock_suggestions_store_|.
205 SuggestionsService
* CreateSuggestionsServiceWithMocks() {
206 mock_suggestions_store_
= new StrictMock
<MockSuggestionsStore
>();
207 mock_thumbnail_manager_
= new StrictMock
<MockImageManager
>();
208 mock_blacklist_store_
= new MockBlacklistStore();
209 return new SuggestionsService(
210 request_context_
.get(),
211 scoped_ptr
<SuggestionsStore
>(mock_suggestions_store_
),
212 scoped_ptr
<ImageManager
>(mock_thumbnail_manager_
),
213 scoped_ptr
<BlacklistStore
>(mock_blacklist_store_
));
216 void FetchSuggestionsDataNoTimeoutHelper(bool interleaved_requests
) {
217 // Field trial enabled with a specific suggestions URL.
218 EnableFieldTrial(kFakeSuggestionsURL
, kFakeSuggestionsCommonParams
,
219 kFakeBlacklistPath
, kFakeBlacklistUrlParam
, false);
220 scoped_ptr
<SuggestionsService
> suggestions_service(
221 CreateSuggestionsServiceWithMocks());
222 EXPECT_TRUE(suggestions_service
!= NULL
);
223 scoped_ptr
<SuggestionsProfile
> suggestions_profile(
224 CreateSuggestionsProfile());
225 // Set up net::FakeURLFetcherFactory.
226 std::string expected_url
=
227 (std::string(kFakeSuggestionsURL
) + "?") + kFakeSuggestionsCommonParams
;
228 factory_
.SetFakeResponse(GURL(expected_url
),
229 suggestions_profile
->SerializeAsString(),
230 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
231 // Set up expectations on the SuggestionsStore. The number depends on
232 // whether the second request is issued (it won't be issued if the second
233 // fetch occurs before the first request has completed).
234 int expected_count
= interleaved_requests
? 1 : 2;
235 EXPECT_CALL(*mock_suggestions_store_
,
236 StoreSuggestions(EqualsProto(*suggestions_profile
)))
237 .Times(expected_count
)
238 .WillRepeatedly(Return(true));
240 // Since there are two requests below, Initialize() will be called twice.
241 EXPECT_CALL(*mock_thumbnail_manager_
,
242 Initialize(EqualsProto(*suggestions_profile
)))
243 .Times(expected_count
);
245 // Expect a call to the blacklist store. Return that there's nothing to
247 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
))
248 .Times(expected_count
);
249 EXPECT_CALL(*mock_blacklist_store_
, GetFirstUrlFromBlacklist(_
))
250 .Times(expected_count
)
251 .WillRepeatedly(Return(false));
253 // Send the request. The data will be returned to the callback.
254 suggestions_service
->FetchSuggestionsDataNoTimeout(base::Bind(
255 &SuggestionsServiceTest::CheckSuggestionsData
, base::Unretained(this)));
257 if (!interleaved_requests
)
258 io_message_loop_
.RunUntilIdle(); // Let request complete.
260 // Send the request a second time.
261 suggestions_service
->FetchSuggestionsDataNoTimeout(base::Bind(
262 &SuggestionsServiceTest::CheckSuggestionsData
, base::Unretained(this)));
264 // (Testing only) wait until suggestion fetch is complete.
265 io_message_loop_
.RunUntilIdle();
267 // Ensure that CheckSuggestionsData() ran twice.
268 EXPECT_EQ(2, suggestions_data_check_count_
);
272 base::MessageLoopForIO io_message_loop_
;
273 net::FakeURLFetcherFactory factory_
;
274 // Only used if the SuggestionsService is built with mocks. Not owned.
275 MockSuggestionsStore
* mock_suggestions_store_
;
276 MockImageManager
* mock_thumbnail_manager_
;
277 MockBlacklistStore
* mock_blacklist_store_
;
278 scoped_refptr
<net::TestURLRequestContextGetter
> request_context_
;
281 scoped_ptr
<base::FieldTrialList
> field_trial_list_
;
282 scoped_refptr
<base::FieldTrial
> field_trial_
;
284 DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest
);
287 TEST_F(SuggestionsServiceTest
, IsControlGroup
) {
288 // Field trial enabled.
289 EnableFieldTrial("", "", "", "", false);
290 EXPECT_FALSE(SuggestionsService::IsControlGroup());
292 EnableFieldTrial("", "", "", "", true);
293 EXPECT_TRUE(SuggestionsService::IsControlGroup());
296 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataNoTimeout
) {
297 FetchSuggestionsDataNoTimeoutHelper(false);
300 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataNoTimeoutInterleaved
) {
301 FetchSuggestionsDataNoTimeoutHelper(true);
304 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataRequestError
) {
305 // Field trial enabled with a specific suggestions URL.
306 EnableFieldTrial(kFakeSuggestionsURL
, kFakeSuggestionsCommonParams
,
307 kFakeBlacklistPath
, kFakeBlacklistUrlParam
, false);
308 scoped_ptr
<SuggestionsService
> suggestions_service(
309 CreateSuggestionsServiceWithMocks());
310 EXPECT_TRUE(suggestions_service
!= NULL
);
312 // Fake a request error.
313 std::string expected_url
=
314 (std::string(kFakeSuggestionsURL
) + "?") + kFakeSuggestionsCommonParams
;
315 factory_
.SetFakeResponse(GURL(expected_url
), "irrelevant", net::HTTP_OK
,
316 net::URLRequestStatus::FAILED
);
318 // Set up expectations on the SuggestionsStore.
319 EXPECT_CALL(*mock_suggestions_store_
, LoadSuggestions(_
))
320 .WillOnce(Return(true));
321 EXPECT_CALL(*mock_thumbnail_manager_
, Initialize(_
));
323 // Expect a call to the blacklist store. Return that there's nothing to
325 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
326 EXPECT_CALL(*mock_blacklist_store_
, GetFirstUrlFromBlacklist(_
))
327 .WillOnce(Return(false));
329 // Send the request. Empty data will be returned to the callback.
330 suggestions_service
->FetchSuggestionsData(
331 INITIALIZED_ENABLED_HISTORY
, // Normal mode.
332 base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile
,
333 base::Unretained(this)));
335 // (Testing only) wait until suggestion fetch is complete.
336 io_message_loop_
.RunUntilIdle();
338 // Ensure that ExpectEmptySuggestionsProfile ran once.
339 EXPECT_EQ(1, suggestions_empty_data_count_
);
342 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataResponseNotOK
) {
343 // Field trial enabled with a specific suggestions URL.
344 EnableFieldTrial(kFakeSuggestionsURL
, kFakeSuggestionsCommonParams
,
345 kFakeBlacklistPath
, kFakeBlacklistUrlParam
, false);
346 scoped_ptr
<SuggestionsService
> suggestions_service(
347 CreateSuggestionsServiceWithMocks());
348 EXPECT_TRUE(suggestions_service
!= NULL
);
350 // Response code != 200.
351 std::string expected_url
=
352 (std::string(kFakeSuggestionsURL
) + "?") + kFakeSuggestionsCommonParams
;
353 factory_
.SetFakeResponse(GURL(expected_url
), "irrelevant",
354 net::HTTP_BAD_REQUEST
,
355 net::URLRequestStatus::SUCCESS
);
357 // Set up expectations on the SuggestionsStore.
358 EXPECT_CALL(*mock_suggestions_store_
, ClearSuggestions());
360 // Expect a call to the blacklist store. Return that there's nothing to
362 EXPECT_CALL(*mock_blacklist_store_
, GetFirstUrlFromBlacklist(_
))
363 .WillOnce(Return(false));
365 // Send the request. Empty data will be returned to the callback.
366 suggestions_service
->FetchSuggestionsData(
367 INITIALIZED_ENABLED_HISTORY
, // Normal mode.
368 base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile
,
369 base::Unretained(this)));
371 // (Testing only) wait until suggestion fetch is complete.
372 io_message_loop_
.RunUntilIdle();
374 // Ensure that ExpectEmptySuggestionsProfile ran once.
375 EXPECT_EQ(1, suggestions_empty_data_count_
);
378 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataSyncDisabled
) {
379 // Field trial enabled with a specific suggestions URL.
380 EnableFieldTrial(kFakeSuggestionsURL
, kFakeSuggestionsCommonParams
,
381 kFakeBlacklistPath
, kFakeBlacklistUrlParam
, false);
382 scoped_ptr
<SuggestionsService
> suggestions_service(
383 CreateSuggestionsServiceWithMocks());
384 EXPECT_TRUE(suggestions_service
!= NULL
);
386 // Set up expectations on the SuggestionsStore.
387 EXPECT_CALL(*mock_suggestions_store_
, ClearSuggestions());
389 // Send the request. Cache is cleared and empty data will be returned to the
391 suggestions_service
->FetchSuggestionsData(
392 SYNC_OR_HISTORY_SYNC_DISABLED
,
393 base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile
,
394 base::Unretained(this)));
396 // Wait for posted task to complete.
397 base::MessageLoop::current()->RunUntilIdle();
399 // Ensure that ExpectEmptySuggestionsProfile ran once.
400 EXPECT_EQ(1, suggestions_empty_data_count_
);
403 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataSyncNotInitializedEnabled
) {
404 // Field trial enabled with a specific suggestions URL.
405 EnableFieldTrial(kFakeSuggestionsURL
, kFakeSuggestionsCommonParams
,
406 kFakeBlacklistPath
, kFakeBlacklistUrlParam
, false);
407 scoped_ptr
<SuggestionsService
> suggestions_service(
408 CreateSuggestionsServiceWithMocks());
409 EXPECT_TRUE(suggestions_service
!= NULL
);
410 scoped_ptr
<SuggestionsProfile
> suggestions_profile(
411 CreateSuggestionsProfile());
414 EXPECT_CALL(*mock_suggestions_store_
, LoadSuggestions(_
))
415 .WillOnce(DoAll(SetArgPointee
<0>(*suggestions_profile
), Return(true)));
416 EXPECT_CALL(*mock_thumbnail_manager_
,
417 Initialize(EqualsProto(*suggestions_profile
)));
418 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
420 // Send the request. In this state, cached data will be returned to the
422 suggestions_service
->FetchSuggestionsData(
423 NOT_INITIALIZED_ENABLED
,
424 base::Bind(&SuggestionsServiceTest::CheckSuggestionsData
,
425 base::Unretained(this)));
427 // Wait for posted task to complete.
428 base::MessageLoop::current()->RunUntilIdle();
430 // Ensure that CheckSuggestionsData ran once.
431 EXPECT_EQ(1, suggestions_data_check_count_
);
434 TEST_F(SuggestionsServiceTest
, BlacklistURL
) {
435 EnableFieldTrial(kFakeSuggestionsURL
, kFakeSuggestionsCommonParams
,
436 kFakeBlacklistPath
, kFakeBlacklistUrlParam
, false);
437 scoped_ptr
<SuggestionsService
> suggestions_service(
438 CreateSuggestionsServiceWithMocks());
439 EXPECT_TRUE(suggestions_service
!= NULL
);
441 GURL
blacklist_url(kBlacklistUrl
);
442 std::string request_url
= GetExpectedBlacklistRequestUrl(blacklist_url
);
443 scoped_ptr
<SuggestionsProfile
> suggestions_profile(
444 CreateSuggestionsProfile());
445 factory_
.SetFakeResponse(GURL(request_url
),
446 suggestions_profile
->SerializeAsString(),
447 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
449 // Set up expectations on the SuggestionsStore.
450 EXPECT_CALL(*mock_suggestions_store_
,
451 StoreSuggestions(EqualsProto(*suggestions_profile
)))
452 .WillOnce(Return(true));
453 EXPECT_CALL(*mock_thumbnail_manager_
,
454 Initialize(EqualsProto(*suggestions_profile
)));
456 // Expected calls to the blacklist store.
457 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
458 .WillOnce(Return(true));
459 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url
)))
460 .WillOnce(Return(true));
461 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
));
462 EXPECT_CALL(*mock_blacklist_store_
, GetFirstUrlFromBlacklist(_
))
463 .WillOnce(Return(false));
465 // Send the request. The data will be returned to the callback.
466 suggestions_service
->BlacklistURL(
467 blacklist_url
, base::Bind(&SuggestionsServiceTest::CheckSuggestionsData
,
468 base::Unretained(this)));
470 // (Testing only) wait until blacklist request is complete.
471 io_message_loop_
.RunUntilIdle();
473 // Ensure that CheckSuggestionsData() ran once.
474 EXPECT_EQ(1, suggestions_data_check_count_
);
477 // Initial blacklist request fails, triggering a scheduled upload which
479 TEST_F(SuggestionsServiceTest
, BlacklistURLFails
) {
480 EnableFieldTrial(kFakeSuggestionsURL
, kFakeSuggestionsCommonParams
,
481 kFakeBlacklistPath
, kFakeBlacklistUrlParam
, false);
482 scoped_ptr
<SuggestionsService
> suggestions_service(
483 CreateSuggestionsServiceWithMocks());
484 EXPECT_TRUE(suggestions_service
!= NULL
);
485 suggestions_service
->set_blacklist_delay(0); // Don't wait during a test!
486 scoped_ptr
<SuggestionsProfile
> suggestions_profile(
487 CreateSuggestionsProfile());
488 GURL
blacklist_url(kBlacklistUrl
);
490 // Set up behavior for the first call to blacklist.
491 std::string request_url
= GetExpectedBlacklistRequestUrl(blacklist_url
);
492 factory_
.SetFakeResponse(GURL(request_url
), "irrelevant", net::HTTP_OK
,
493 net::URLRequestStatus::FAILED
);
495 // Expectations specific to the first request.
496 EXPECT_CALL(*mock_blacklist_store_
, BlacklistUrl(Eq(blacklist_url
)))
497 .WillOnce(Return(true));
498 EXPECT_CALL(*mock_suggestions_store_
, LoadSuggestions(_
))
499 .WillOnce(DoAll(SetArgPointee
<0>(*suggestions_profile
), Return(true)));
501 // Expectations specific to the second request.
502 EXPECT_CALL(*mock_suggestions_store_
,
503 StoreSuggestions(EqualsProto(*suggestions_profile
)))
504 .WillOnce(Return(true));
505 EXPECT_CALL(*mock_blacklist_store_
, RemoveUrl(Eq(blacklist_url
)))
506 .WillOnce(Return(true));
508 // Expectations pertaining to both requests.
509 EXPECT_CALL(*mock_blacklist_store_
, FilterSuggestions(_
)).Times(2);
510 EXPECT_CALL(*mock_blacklist_store_
, GetFirstUrlFromBlacklist(_
))
511 .WillOnce(Return(true))
512 .WillOnce(DoAll(SetArgPointee
<0>(blacklist_url
), Return(true)))
513 .WillOnce(Return(false));
514 // There will be two calls to Initialize() (one store, one load).
515 EXPECT_CALL(*mock_thumbnail_manager_
,
516 Initialize(EqualsProto(*suggestions_profile
)))
519 // Send the request. The data will be returned to the callback.
520 suggestions_service
->BlacklistURL(
521 blacklist_url
, base::Bind(&SuggestionsServiceTest::CheckSuggestionsData
,
522 base::Unretained(this)));
524 // The first FakeURLFetcher was created; we can now set up behavior for the
525 // second call to blacklist.
526 factory_
.SetFakeResponse(GURL(request_url
),
527 suggestions_profile
->SerializeAsString(),
528 net::HTTP_OK
, net::URLRequestStatus::SUCCESS
);
530 // (Testing only) wait until both requests are complete.
531 io_message_loop_
.RunUntilIdle();
532 // ... Other task gets posted to the message loop.
533 base::MessageLoop::current()->RunUntilIdle();
534 // ... And completes.
535 io_message_loop_
.RunUntilIdle();
537 // Ensure that CheckSuggestionsData() ran once.
538 EXPECT_EQ(1, suggestions_data_check_count_
);
541 TEST_F(SuggestionsServiceTest
, GetBlacklistedUrl
) {
542 EnableFieldTrial(kFakeSuggestionsURL
, kFakeSuggestionsCommonParams
,
543 kFakeBlacklistPath
, kFakeBlacklistUrlParam
, false);
545 scoped_ptr
<GURL
> request_url
;
546 scoped_ptr
<net::FakeURLFetcher
> fetcher
;
549 // Not a blacklist request.
550 request_url
.reset(new GURL("http://not-blacklisting.com/a?b=c"));
551 fetcher
= CreateURLFetcher(*request_url
, NULL
, "", net::HTTP_OK
,
552 net::URLRequestStatus::SUCCESS
);
553 EXPECT_FALSE(SuggestionsService::GetBlacklistedUrl(*fetcher
, &retrieved_url
));
555 // An actual blacklist request.
556 string blacklisted_url
= "http://blacklisted.com/a?b=c&d=e";
557 string encoded_blacklisted_url
=
558 "http%3A%2F%2Fblacklisted.com%2Fa%3Fb%3Dc%26d%3De";
559 string blacklist_request_prefix
=
560 "https://mysuggestions.com/proto/blacklist?foo=bar&baz=";
562 new GURL(blacklist_request_prefix
+ encoded_blacklisted_url
));
564 fetcher
= CreateURLFetcher(*request_url
, NULL
, "", net::HTTP_OK
,
565 net::URLRequestStatus::SUCCESS
);
566 EXPECT_TRUE(SuggestionsService::GetBlacklistedUrl(*fetcher
, &retrieved_url
));
567 EXPECT_EQ(blacklisted_url
, retrieved_url
.spec());
570 TEST_F(SuggestionsServiceTest
, UpdateBlacklistDelay
) {
571 scoped_ptr
<SuggestionsService
> suggestions_service(
572 CreateSuggestionsServiceWithMocks());
573 int initial_delay
= suggestions_service
->blacklist_delay();
575 // Delay unchanged on success.
576 suggestions_service
->UpdateBlacklistDelay(true);
577 EXPECT_EQ(initial_delay
, suggestions_service
->blacklist_delay());
579 // Delay increases on failure.
580 suggestions_service
->UpdateBlacklistDelay(false);
581 EXPECT_GT(suggestions_service
->blacklist_delay(), initial_delay
);
583 // Delay resets on success.
584 suggestions_service
->UpdateBlacklistDelay(true);
585 EXPECT_EQ(initial_delay
, suggestions_service
->blacklist_delay());
588 TEST_F(SuggestionsServiceTest
, CheckDefaultTimeStamps
) {
589 scoped_ptr
<SuggestionsService
> suggestions_service(
590 CreateSuggestionsServiceWithMocks());
591 SuggestionsProfile suggestions
=
592 CreateSuggestionsProfileWithExpiryTimestamps();
593 suggestions_service
->SetDefaultExpiryTimestamp(&suggestions
,
595 EXPECT_EQ(kTestSetExpiry
, suggestions
.suggestions(0).expiry_ts());
596 EXPECT_EQ(kTestDefaultExpiry
, suggestions
.suggestions(1).expiry_ts());
598 } // namespace suggestions