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 "chrome/browser/search/suggestions/suggestions_service.h"
10 #include "base/bind.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/history/history_types.h"
16 #include "chrome/browser/search/suggestions/proto/suggestions.pb.h"
17 #include "chrome/browser/search/suggestions/suggestions_service_factory.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "components/variations/entropy_provider.h"
20 #include "components/variations/variations_associated_data.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "net/http/http_response_headers.h"
23 #include "net/http/http_status_code.h"
24 #include "net/url_request/test_url_fetcher_factory.h"
25 #include "net/url_request/url_request_status.h"
26 #include "net/url_request/url_request_test_util.h"
27 #include "testing/gtest/include/gtest/gtest.h"
31 const char kFakeSuggestionsURL
[] = "https://mysuggestions.com/proto";
33 const char kTestTitle
[] = "a title";
34 const char kTestUrl
[] = "http://go.com";
36 scoped_ptr
<net::FakeURLFetcher
> CreateURLFetcher(
37 const GURL
& url
, net::URLFetcherDelegate
* delegate
,
38 const std::string
& response_data
, net::HttpStatusCode response_code
,
39 net::URLRequestStatus::Status status
) {
40 scoped_ptr
<net::FakeURLFetcher
> fetcher(new net::FakeURLFetcher(
41 url
, delegate
, response_data
, response_code
, status
));
43 if (response_code
== net::HTTP_OK
) {
44 scoped_refptr
<net::HttpResponseHeaders
> download_headers(
45 new net::HttpResponseHeaders(""));
46 download_headers
->AddHeader("Content-Type: text/html");
47 fetcher
->set_response_headers(download_headers
);
49 return fetcher
.Pass();
54 namespace suggestions
{
56 class SuggestionsServiceTest
: public testing::Test
{
58 void CheckSuggestionsData(const SuggestionsProfile
& suggestions_profile
) {
59 EXPECT_EQ(1, suggestions_profile
.suggestions_size());
60 EXPECT_EQ(kTestTitle
, suggestions_profile
.suggestions(0).title());
61 EXPECT_EQ(kTestUrl
, suggestions_profile
.suggestions(0).url());
62 ++suggestions_data_check_count_
;
65 void ExpectEmptySuggestionsProfile(const SuggestionsProfile
& profile
) {
66 EXPECT_EQ(0, profile
.suggestions_size());
67 ++suggestions_empty_data_count_
;
70 int suggestions_data_check_count_
;
71 int suggestions_empty_data_count_
;
74 SuggestionsServiceTest()
75 : suggestions_data_check_count_(0),
76 suggestions_empty_data_count_(0),
77 factory_(NULL
, base::Bind(&CreateURLFetcher
)) {
78 profile_
= profile_builder_
.Build();
80 virtual ~SuggestionsServiceTest() {}
82 // Enables the "ChromeSuggestions.Group1" field trial.
83 void EnableFieldTrial(const std::string
& url
) {
84 // Clear the existing |field_trial_list_| to avoid firing a DCHECK.
85 field_trial_list_
.reset(NULL
);
86 field_trial_list_
.reset(
87 new base::FieldTrialList(new metrics::SHA1EntropyProvider("foo")));
89 chrome_variations::testing::ClearAllVariationParams();
90 std::map
<std::string
, std::string
> params
;
91 params
[kSuggestionsFieldTrialStateParam
] =
92 kSuggestionsFieldTrialStateEnabled
;
93 params
[kSuggestionsFieldTrialURLParam
] = url
;
94 chrome_variations::AssociateVariationParams(kSuggestionsFieldTrialName
,
96 field_trial_
= base::FieldTrialList::CreateFieldTrial(
97 kSuggestionsFieldTrialName
, "Group1");
98 field_trial_
->group();
101 SuggestionsService
* CreateSuggestionsService() {
102 SuggestionsServiceFactory
* suggestions_service_factory
=
103 SuggestionsServiceFactory::GetInstance();
104 return suggestions_service_factory
->GetForProfile(profile_
.get());
108 net::FakeURLFetcherFactory factory_
;
111 content::TestBrowserThreadBundle thread_bundle_
;
112 scoped_ptr
<base::FieldTrialList
> field_trial_list_
;
113 scoped_refptr
<base::FieldTrial
> field_trial_
;
114 TestingProfile::Builder profile_builder_
;
115 scoped_ptr
<TestingProfile
> profile_
;
117 DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest
);
120 TEST_F(SuggestionsServiceTest
, ServiceBeingCreated
) {
121 // Field trial not enabled.
122 EXPECT_TRUE(CreateSuggestionsService() == NULL
);
124 // Field trial enabled.
125 EnableFieldTrial("");
126 EXPECT_TRUE(CreateSuggestionsService() != NULL
);
129 TEST_F(SuggestionsServiceTest
, FetchSuggestionsData
) {
130 // Field trial enabled with a specific suggestions URL.
131 EnableFieldTrial(kFakeSuggestionsURL
);
132 SuggestionsService
* suggestions_service
= CreateSuggestionsService();
133 EXPECT_TRUE(suggestions_service
!= NULL
);
135 SuggestionsProfile suggestions_profile
;
136 ChromeSuggestion
* suggestion
= suggestions_profile
.add_suggestions();
137 suggestion
->set_title(kTestTitle
);
138 suggestion
->set_url(kTestUrl
);
139 factory_
.SetFakeResponse(GURL(kFakeSuggestionsURL
),
140 suggestions_profile
.SerializeAsString(),
142 net::URLRequestStatus::SUCCESS
);
144 // Send the request. The data will be returned to the callback.
145 suggestions_service
->FetchSuggestionsData(
146 base::Bind(&SuggestionsServiceTest::CheckSuggestionsData
,
147 base::Unretained(this)));
149 // Send the request a second time.
150 suggestions_service
->FetchSuggestionsData(
151 base::Bind(&SuggestionsServiceTest::CheckSuggestionsData
,
152 base::Unretained(this)));
154 // (Testing only) wait until suggestion fetch is complete.
155 base::MessageLoop::current()->RunUntilIdle();
157 // Ensure that CheckSuggestionsData() ran twice.
158 EXPECT_EQ(2, suggestions_data_check_count_
);
161 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataRequestError
) {
162 // Field trial enabled with a specific suggestions URL.
163 EnableFieldTrial(kFakeSuggestionsURL
);
164 SuggestionsService
* suggestions_service
= CreateSuggestionsService();
165 EXPECT_TRUE(suggestions_service
!= NULL
);
167 // Fake a request error.
168 factory_
.SetFakeResponse(GURL(kFakeSuggestionsURL
),
171 net::URLRequestStatus::FAILED
);
173 // Send the request. Empty data will be returned to the callback.
174 suggestions_service
->FetchSuggestionsData(
175 base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile
,
176 base::Unretained(this)));
178 // (Testing only) wait until suggestion fetch is complete.
179 base::MessageLoop::current()->RunUntilIdle();
181 // Ensure that ExpectEmptySuggestionsProfile ran once.
182 EXPECT_EQ(1, suggestions_empty_data_count_
);
185 TEST_F(SuggestionsServiceTest
, FetchSuggestionsDataResponseNotOK
) {
186 // Field trial enabled with a specific suggestions URL.
187 EnableFieldTrial(kFakeSuggestionsURL
);
188 SuggestionsService
* suggestions_service
= CreateSuggestionsService();
189 EXPECT_TRUE(suggestions_service
!= NULL
);
191 // Response code != 200.
192 factory_
.SetFakeResponse(GURL(kFakeSuggestionsURL
),
194 net::HTTP_BAD_REQUEST
,
195 net::URLRequestStatus::SUCCESS
);
197 // Send the request. Empty data will be returned to the callback.
198 suggestions_service
->FetchSuggestionsData(
199 base::Bind(&SuggestionsServiceTest::ExpectEmptySuggestionsProfile
,
200 base::Unretained(this)));
202 // (Testing only) wait until suggestion fetch is complete.
203 base::MessageLoop::current()->RunUntilIdle();
205 // Ensure that ExpectEmptySuggestionsProfile ran once.
206 EXPECT_EQ(1, suggestions_empty_data_count_
);
209 } // namespace suggestions