Chromium Code Reviews| Index: chrome/browser/search/suggestions/suggestions_service_unittest.cc |
| diff --git a/chrome/browser/search/suggestions/suggestions_service_unittest.cc b/chrome/browser/search/suggestions/suggestions_service_unittest.cc |
| index 674d7bc941b4c317cbd4eb517404d3ed5b82a2fe..1d6a2c6715f8d67f4dc86e4f1d4a3b8c34ac4625 100644 |
| --- a/chrome/browser/search/suggestions/suggestions_service_unittest.cc |
| +++ b/chrome/browser/search/suggestions/suggestions_service_unittest.cc |
| @@ -5,6 +5,7 @@ |
| #include "chrome/browser/search/suggestions/suggestions_service.h" |
| #include <map> |
| +#include <sstream> |
| #include <string> |
| #include "base/bind.h" |
| @@ -13,6 +14,7 @@ |
| #include "base/prefs/pref_service.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/history/history_types.h" |
| +#include "chrome/browser/search/suggestions/blacklist_store.h" |
| #include "chrome/browser/search/suggestions/proto/suggestions.pb.h" |
| #include "chrome/browser/search/suggestions/suggestions_service_factory.h" |
| #include "chrome/browser/search/suggestions/suggestions_store.h" |
| @@ -28,15 +30,19 @@ |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| +using testing::DoAll; |
| +using ::testing::Eq; |
| using ::testing::Return; |
| +using testing::SetArgPointee; |
| using ::testing::StrictMock; |
| using ::testing::_; |
| namespace { |
| const char kFakeSuggestionsURL[] = "https://mysuggestions.com/proto"; |
| -const char kFakeSuggestionsSuffix[] = "?foo=bar"; |
| -const char kFakeBlacklistSuffix[] = "/blacklist?foo=bar&baz="; |
| +const char kFakeSuggestionsCommonParams[] = "foo=bar"; |
| +const char kFakeBlacklistPath[] = "/blacklist"; |
| +const char kFakeBlacklistUrlParam[] = "baz"; |
| const char kTestTitle[] = "a title"; |
| const char kTestUrl[] = "http://go.com"; |
| @@ -58,6 +64,14 @@ scoped_ptr<net::FakeURLFetcher> CreateURLFetcher( |
| return fetcher.Pass(); |
| } |
| +std::string GetExpectedBlacklistRequestUrl(const GURL& blacklist_url) { |
| + std::stringstream request_url; |
| + request_url << kFakeSuggestionsURL << kFakeBlacklistPath << "?" |
| + << kFakeSuggestionsCommonParams << "&" << kFakeBlacklistUrlParam |
| + << "=" << net::EscapeQueryParamValue(blacklist_url.spec(), true); |
| + return request_url.str(); |
| +} |
| + |
| // GMock matcher for protobuf equality. |
| MATCHER_P(EqualsProto, message, "") { |
| // This implementation assumes protobuf serialization is deterministic, which |
| @@ -90,6 +104,14 @@ class MockSuggestionsStore : public suggestions::SuggestionsStore { |
| MOCK_METHOD0(ClearSuggestions, void()); |
| }; |
| +class MockBlacklistStore : public suggestions::BlacklistStore { |
| + public: |
| + MOCK_METHOD1(BlacklistUrl, bool(const GURL&)); |
| + MOCK_METHOD1(GetFirstUrlFromBlacklist, bool(GURL*)); |
| + MOCK_METHOD1(RemoveUrl, bool(const GURL&)); |
| + MOCK_METHOD1(FilterSuggestions, void(SuggestionsProfile*)); |
| +}; |
| + |
| } // namespace |
| class SuggestionsServiceTest : public testing::Test { |
| @@ -121,8 +143,9 @@ class SuggestionsServiceTest : public testing::Test { |
| // Enables the "ChromeSuggestions.Group1" field trial. |
| void EnableFieldTrial(const std::string& url, |
| - const std::string& suggestions_suffix, |
| - const std::string& blacklist_suffix) { |
| + const std::string& common_params, |
| + const std::string& blacklist_path, |
| + const std::string& blacklist_url_param) { |
| // Clear the existing |field_trial_list_| to avoid firing a DCHECK. |
| field_trial_list_.reset(NULL); |
| field_trial_list_.reset( |
| @@ -133,8 +156,9 @@ class SuggestionsServiceTest : public testing::Test { |
| params[kSuggestionsFieldTrialStateParam] = |
| kSuggestionsFieldTrialStateEnabled; |
| params[kSuggestionsFieldTrialURLParam] = url; |
| - params[kSuggestionsFieldTrialSuggestionsSuffixParam] = suggestions_suffix; |
| - params[kSuggestionsFieldTrialBlacklistSuffixParam] = blacklist_suffix; |
| + params[kSuggestionsFieldTrialCommonParamsParam] = common_params; |
| + params[kSuggestionsFieldTrialBlacklistPathParam] = blacklist_path; |
| + params[kSuggestionsFieldTrialBlacklistUrlParamParam] = blacklist_url_param; |
| chrome_variations::AssociateVariationParams(kSuggestionsFieldTrialName, |
| "Group1", params); |
| field_trial_ = base::FieldTrialList::CreateFieldTrial( |
| @@ -150,25 +174,27 @@ class SuggestionsServiceTest : public testing::Test { |
| // Should not be called more than once per test since it stashes the |
| // SuggestionsStore in |mock_suggestions_store_|. |
| - SuggestionsService* CreateSuggestionsServiceWithMockStore() { |
| + SuggestionsService* CreateSuggestionsServiceWithMocks() { |
| mock_suggestions_store_ = new StrictMock<MockSuggestionsStore>(); |
| + mock_blacklist_store_ = new MockBlacklistStore(); |
| return new SuggestionsService( |
| - profile_.get(), scoped_ptr<SuggestionsStore>(mock_suggestions_store_)); |
| + profile_.get(), scoped_ptr<SuggestionsStore>(mock_suggestions_store_), |
| + scoped_ptr<BlacklistStore>(mock_blacklist_store_)); |
| } |
| void FetchSuggestionsDataNoTimeoutHelper(bool interleaved_requests) { |
| // Field trial enabled with a specific suggestions URL. |
| - EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsSuffix, |
| - kFakeBlacklistSuffix); |
| + EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsCommonParams, |
| + kFakeBlacklistPath, kFakeBlacklistUrlParam); |
| scoped_ptr<SuggestionsService> suggestions_service( |
| - CreateSuggestionsServiceWithMockStore()); |
| + CreateSuggestionsServiceWithMocks()); |
| EXPECT_TRUE(suggestions_service != NULL); |
| scoped_ptr<SuggestionsProfile> suggestions_profile( |
| CreateSuggestionsProfile()); |
| // Set up net::FakeURLFetcherFactory. |
| std::string expected_url = |
| - std::string(kFakeSuggestionsURL) + kFakeSuggestionsSuffix; |
| + (std::string(kFakeSuggestionsURL) + "?") + kFakeSuggestionsCommonParams; |
| factory_.SetFakeResponse(GURL(expected_url), |
| suggestions_profile->SerializeAsString(), |
| net::HTTP_OK, net::URLRequestStatus::SUCCESS); |
| @@ -177,13 +203,20 @@ class SuggestionsServiceTest : public testing::Test { |
| // whether the second request is issued (it won't be issued if the second |
| // fetch occurs before the first request has completed). |
| int expected_count = 2; |
| - if (interleaved_requests) |
| - expected_count = 1; |
| + if (interleaved_requests) expected_count = 1; |
| EXPECT_CALL(*mock_suggestions_store_, |
| StoreSuggestions(EqualsProto(*suggestions_profile))) |
| .Times(expected_count) |
| .WillRepeatedly(Return(true)); |
| + // Expect a call to the blacklist store. Return that there's nothing to |
| + // blacklist. |
| + EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)) |
| + .Times(expected_count); |
| + EXPECT_CALL(*mock_blacklist_store_, GetFirstUrlFromBlacklist(_)) |
| + .Times(expected_count) |
| + .WillRepeatedly(Return(false)); |
| + |
| // Send the request. The data will be returned to the callback. |
| suggestions_service->FetchSuggestionsDataNoTimeout(base::Bind( |
| &SuggestionsServiceTest::CheckSuggestionsData, base::Unretained(this))); |
| @@ -204,9 +237,9 @@ class SuggestionsServiceTest : public testing::Test { |
| protected: |
| net::FakeURLFetcherFactory factory_; |
| - // Only used if the SuggestionsService is built with a MockSuggestionsStore. |
| - // Not owned. |
| + // Only used if the SuggestionsService is built with a mocks. Not owned. |
| MockSuggestionsStore* mock_suggestions_store_; |
| + MockBlacklistStore* mock_blacklist_store_; |
| private: |
| content::TestBrowserThreadBundle thread_bundle_; |
| @@ -223,7 +256,7 @@ TEST_F(SuggestionsServiceTest, ServiceBeingCreated) { |
| EXPECT_TRUE(CreateSuggestionsService() == NULL); |
| // Field trial enabled. |
| - EnableFieldTrial("", "", ""); |
| + EnableFieldTrial("", "", "", ""); |
| EXPECT_TRUE(CreateSuggestionsService() != NULL); |
| } |
| @@ -237,15 +270,15 @@ TEST_F(SuggestionsServiceTest, FetchSuggestionsDataNoTimeoutInterleaved) { |
| TEST_F(SuggestionsServiceTest, FetchSuggestionsDataRequestError) { |
| // Field trial enabled with a specific suggestions URL. |
| - EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsSuffix, |
| - kFakeBlacklistSuffix); |
| + EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsCommonParams, |
| + kFakeBlacklistPath, kFakeBlacklistUrlParam); |
| scoped_ptr<SuggestionsService> suggestions_service( |
| - CreateSuggestionsServiceWithMockStore()); |
| + CreateSuggestionsServiceWithMocks()); |
| EXPECT_TRUE(suggestions_service != NULL); |
| // Fake a request error. |
| std::string expected_url = |
| - std::string(kFakeSuggestionsURL) + kFakeSuggestionsSuffix; |
| + (std::string(kFakeSuggestionsURL) + "?") + kFakeSuggestionsCommonParams; |
| factory_.SetFakeResponse(GURL(expected_url), "irrelevant", net::HTTP_OK, |
| net::URLRequestStatus::FAILED); |
| @@ -253,6 +286,12 @@ TEST_F(SuggestionsServiceTest, FetchSuggestionsDataRequestError) { |
| EXPECT_CALL(*mock_suggestions_store_, LoadSuggestions(_)) |
| .WillOnce(Return(true)); |
| + // Expect a call to the blacklist store. Return that there's nothing to |
| + // blacklist. |
| + EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)); |
| + EXPECT_CALL(*mock_blacklist_store_, GetFirstUrlFromBlacklist(_)) |
| + .WillOnce(Return(false)); |
| + |
| // Send the request. Empty data will be returned to the callback. |
| suggestions_service->FetchSuggestionsData( |
| base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile, |
| @@ -267,15 +306,15 @@ TEST_F(SuggestionsServiceTest, FetchSuggestionsDataRequestError) { |
| TEST_F(SuggestionsServiceTest, FetchSuggestionsDataResponseNotOK) { |
| // Field trial enabled with a specific suggestions URL. |
| - EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsSuffix, |
| - kFakeBlacklistSuffix); |
| + EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsCommonParams, |
| + kFakeBlacklistPath, kFakeBlacklistUrlParam); |
| scoped_ptr<SuggestionsService> suggestions_service( |
| - CreateSuggestionsServiceWithMockStore()); |
| + CreateSuggestionsServiceWithMocks()); |
| EXPECT_TRUE(suggestions_service != NULL); |
| // Response code != 200. |
| std::string expected_url = |
| - std::string(kFakeSuggestionsURL) + kFakeSuggestionsSuffix; |
| + (std::string(kFakeSuggestionsURL) + "?") + kFakeSuggestionsCommonParams; |
| factory_.SetFakeResponse(GURL(expected_url), "irrelevant", |
| net::HTTP_BAD_REQUEST, |
| net::URLRequestStatus::SUCCESS); |
| @@ -283,6 +322,11 @@ TEST_F(SuggestionsServiceTest, FetchSuggestionsDataResponseNotOK) { |
| // Set up expectations on the SuggestionsStore. |
| EXPECT_CALL(*mock_suggestions_store_, ClearSuggestions()); |
| + // Expect a call to the blacklist store. Return that there's nothing to |
| + // blacklist. |
| + EXPECT_CALL(*mock_blacklist_store_, GetFirstUrlFromBlacklist(_)) |
| + .WillOnce(Return(false)); |
| + |
| // Send the request. Empty data will be returned to the callback. |
| suggestions_service->FetchSuggestionsData( |
| base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile, |
| @@ -296,18 +340,17 @@ TEST_F(SuggestionsServiceTest, FetchSuggestionsDataResponseNotOK) { |
| } |
| TEST_F(SuggestionsServiceTest, BlacklistURL) { |
| - EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsSuffix, |
| - kFakeBlacklistSuffix); |
| + EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsCommonParams, |
| + kFakeBlacklistPath, kFakeBlacklistUrlParam); |
| scoped_ptr<SuggestionsService> suggestions_service( |
| - CreateSuggestionsServiceWithMockStore()); |
| + CreateSuggestionsServiceWithMocks()); |
| EXPECT_TRUE(suggestions_service != NULL); |
| - std::string expected_url(kFakeSuggestionsURL); |
| - expected_url.append(kFakeBlacklistSuffix) |
| - .append(net::EscapeQueryParamValue(GURL(kBlacklistUrl).spec(), true)); |
| + GURL blacklist_url(kBlacklistUrl); |
| + std::string request_url = GetExpectedBlacklistRequestUrl(blacklist_url); |
| scoped_ptr<SuggestionsProfile> suggestions_profile( |
| CreateSuggestionsProfile()); |
| - factory_.SetFakeResponse(GURL(expected_url), |
| + factory_.SetFakeResponse(GURL(request_url), |
| suggestions_profile->SerializeAsString(), |
| net::HTTP_OK, net::URLRequestStatus::SUCCESS); |
| @@ -316,11 +359,19 @@ TEST_F(SuggestionsServiceTest, BlacklistURL) { |
| StoreSuggestions(EqualsProto(*suggestions_profile))) |
| .WillOnce(Return(true)); |
| + // Expected calls to the blacklist store. |
| + EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklist_url))) |
| + .WillOnce(Return(true)); |
| + EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklist_url))) |
| + .WillOnce(Return(true)); |
| + EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)); |
| + EXPECT_CALL(*mock_blacklist_store_, GetFirstUrlFromBlacklist(_)) |
| + .WillOnce(Return(false)); |
| + |
| // Send the request. The data will be returned to the callback. |
| suggestions_service->BlacklistURL( |
| - GURL(kBlacklistUrl), |
| - base::Bind(&SuggestionsServiceTest::CheckSuggestionsData, |
| - base::Unretained(this))); |
| + blacklist_url, base::Bind(&SuggestionsServiceTest::CheckSuggestionsData, |
| + base::Unretained(this))); |
| // (Testing only) wait until blacklist request is complete. |
| base::MessageLoop::current()->RunUntilIdle(); |
| @@ -329,4 +380,108 @@ TEST_F(SuggestionsServiceTest, BlacklistURL) { |
| EXPECT_EQ(1, suggestions_data_check_count_); |
| } |
| +// Initial blacklist request fails, triggering a scheduled upload which |
| +// succeeds. |
| +TEST_F(SuggestionsServiceTest, BlacklistURLFails) { |
| + EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsCommonParams, |
| + kFakeBlacklistPath, kFakeBlacklistUrlParam); |
| + scoped_ptr<SuggestionsService> suggestions_service( |
| + CreateSuggestionsServiceWithMocks()); |
| + EXPECT_TRUE(suggestions_service != NULL); |
| + suggestions_service->SetBlacklistDelay(0); // Don't wait during a test! |
| + scoped_ptr<SuggestionsProfile> suggestions_profile( |
| + CreateSuggestionsProfile()); |
| + GURL blacklist_url(kBlacklistUrl); |
| + |
| + // Set up behavior for the first call to blacklist. |
| + std::string request_url = GetExpectedBlacklistRequestUrl(blacklist_url); |
| + factory_.SetFakeResponse(GURL(request_url), "irrelevant", net::HTTP_OK, |
| + net::URLRequestStatus::FAILED); |
| + |
| + // Expectations specific to the first request. |
| + EXPECT_CALL(*mock_blacklist_store_, BlacklistUrl(Eq(blacklist_url))) |
| + .WillOnce(Return(true)); |
| + EXPECT_CALL(*mock_suggestions_store_, LoadSuggestions(_)) |
| + .WillOnce(DoAll(SetArgPointee<0>(*suggestions_profile), Return(true))); |
| + |
| + // Expectations specific to the second request. |
|
Mathieu
2014/06/18 13:56:23
Can this be a bit closer to the "second request"
manzagop (departed)
2014/06/18 18:44:55
I believe (could be wrong) all expectations should
|
| + EXPECT_CALL(*mock_suggestions_store_, |
| + StoreSuggestions(EqualsProto(*suggestions_profile))) |
| + .WillOnce(Return(true)); |
| + EXPECT_CALL(*mock_blacklist_store_, RemoveUrl(Eq(blacklist_url))) |
| + .WillOnce(Return(true)); |
| + |
| + // Expectations pertaining to both requests. |
| + EXPECT_CALL(*mock_blacklist_store_, FilterSuggestions(_)).Times(2); |
| + EXPECT_CALL(*mock_blacklist_store_, GetFirstUrlFromBlacklist(_)) |
| + .WillOnce(Return(true)) |
| + .WillOnce(DoAll(SetArgPointee<0>(blacklist_url), Return(true))) |
| + .WillOnce(Return(false)); |
| + |
| + // Send the request. The data will be returned to the callback. |
| + suggestions_service->BlacklistURL( |
| + blacklist_url, base::Bind(&SuggestionsServiceTest::CheckSuggestionsData, |
| + base::Unretained(this))); |
| + |
| + // The first FakeURLFetcher was created; we can now set up behavior for the |
| + // second call to blacklist. |
| + factory_.SetFakeResponse(GURL(request_url), |
| + suggestions_profile->SerializeAsString(), |
| + net::HTTP_OK, net::URLRequestStatus::SUCCESS); |
| + |
| + // (Testing only) wait until both requests are complete. |
| + base::MessageLoop::current()->RunUntilIdle(); |
| + base::MessageLoop::current()->RunUntilIdle(); |
|
Mathieu
2014/06/18 13:56:23
pretty sure two calls is redundant
manzagop (departed)
2014/06/18 18:44:55
Done.
|
| + |
| + // Ensure that CheckSuggestionsData() ran once. |
| + EXPECT_EQ(1, suggestions_data_check_count_); |
| +} |
| + |
| +TEST_F(SuggestionsServiceTest, GetBlacklistedUrl) { |
| + EnableFieldTrial(kFakeSuggestionsURL, kFakeSuggestionsCommonParams, |
| + kFakeBlacklistPath, kFakeBlacklistUrlParam); |
| + |
| + scoped_ptr<GURL> request_url; |
| + scoped_ptr<net::FakeURLFetcher> fetcher; |
| + GURL retrieved_url; |
| + |
| + // Not a blacklist request. |
| + request_url.reset(new GURL("http://not-blacklisting.com/a?b=c")); |
| + fetcher = CreateURLFetcher(*request_url, NULL, "", net::HTTP_OK, |
| + net::URLRequestStatus::SUCCESS); |
| + EXPECT_FALSE(SuggestionsService::GetBlacklistedUrl(*fetcher, &retrieved_url)); |
| + |
| + // An actual blacklist request. |
| + string blacklisted_url = "http://blacklisted.com/a?b=c&d=e"; |
| + string encoded_blacklisted_url = |
| + "http%3A%2F%2Fblacklisted.com%2Fa%3Fb%3Dc%26d%3De"; |
| + string blacklist_request_prefix = |
| + "https://mysuggestions.com/proto/blacklist?foo=bar&baz="; |
| + request_url.reset( |
| + new GURL(blacklist_request_prefix + encoded_blacklisted_url)); |
| + fetcher.reset(); |
| + fetcher = CreateURLFetcher(*request_url, NULL, "", net::HTTP_OK, |
| + net::URLRequestStatus::SUCCESS); |
| + EXPECT_TRUE(SuggestionsService::GetBlacklistedUrl(*fetcher, &retrieved_url)); |
| + EXPECT_EQ(blacklisted_url, retrieved_url.spec()); |
| +} |
| + |
| +TEST_F(SuggestionsServiceTest, UpdateBlacklistDelay) { |
| + scoped_ptr<SuggestionsService> suggestions_service( |
| + CreateSuggestionsServiceWithMocks()); |
| + int initial_delay = suggestions_service->GetBlacklistDelay(); |
| + |
| + // Delay unchanged on success. |
| + suggestions_service->UpdateBlacklistDelay(true); |
| + EXPECT_EQ(initial_delay, suggestions_service->GetBlacklistDelay()); |
| + |
| + // Delay increases on failure. |
| + suggestions_service->UpdateBlacklistDelay(false); |
| + EXPECT_GE(suggestions_service->GetBlacklistDelay(), initial_delay); |
|
Mathieu
2014/06/18 13:56:23
EXPECT_GT?
manzagop (departed)
2014/06/18 18:44:55
Done. You're right it's probably better to break t
|
| + |
| + // Delay resets on success. |
| + suggestions_service->UpdateBlacklistDelay(true); |
| + EXPECT_EQ(initial_delay, suggestions_service->GetBlacklistDelay()); |
| +} |
| + |
| } // namespace suggestions |