zero_suggest_provider_unittest.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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.
4
5#include "chrome/browser/autocomplete/zero_suggest_provider.h"
6
7#include "base/metrics/field_trial.h"
8#include "base/prefs/pref_service.h"
9#include "base/run_loop.h"
10#include "base/strings/utf_string_conversions.h"
11#include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
12#include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
13#include "chrome/browser/search_engines/template_url_service_factory.h"
14#include "chrome/common/pref_names.h"
15#include "chrome/test/base/testing_profile.h"
16#include "components/metrics/proto/omnibox_event.pb.h"
17#include "components/omnibox/autocomplete_provider_listener.h"
18#include "components/omnibox/omnibox_field_trial.h"
19#include "components/search_engines/template_url.h"
20#include "components/search_engines/template_url_service.h"
21#include "components/variations/entropy_provider.h"
22#include "components/variations/variations_associated_data.h"
23#include "content/public/test/test_browser_thread_bundle.h"
24#include "net/url_request/test_url_fetcher_factory.h"
25#include "testing/gtest/include/gtest/gtest.h"
26
27class ZeroSuggestProviderTest : public testing::Test,
28                                public AutocompleteProviderListener {
29 public:
30  ZeroSuggestProviderTest();
31
32  virtual void SetUp() OVERRIDE;
33  virtual void TearDown() OVERRIDE;
34
35 protected:
36  // AutocompleteProviderListener:
37  virtual void OnProviderUpdate(bool updated_matches) OVERRIDE;
38
39  void ResetFieldTrialList();
40
41  void CreatePersonalizedFieldTrial();
42
43  // Set up threads for testing; this needs to be instantiated before
44  // |profile_|.
45  content::TestBrowserThreadBundle thread_bundle_;
46
47  // Needed for OmniboxFieldTrial::ActivateStaticTrials().
48  scoped_ptr<base::FieldTrialList> field_trial_list_;
49
50  // URLFetcherFactory implementation registered.
51  net::TestURLFetcherFactory test_factory_;
52
53  // Profile we use.
54  TestingProfile profile_;
55
56  // ZeroSuggestProvider object under test.
57  scoped_refptr<ZeroSuggestProvider> provider_;
58
59  // Default template URL.
60  TemplateURL* default_t_url_;
61};
62
63ZeroSuggestProviderTest::ZeroSuggestProviderTest() {
64  ResetFieldTrialList();
65}
66
67void ZeroSuggestProviderTest::SetUp() {
68  // Make sure that fetchers are automatically ungregistered upon destruction.
69  test_factory_.set_remove_fetcher_on_delete(true);
70  TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
71      &profile_, &TemplateURLServiceFactory::BuildInstanceFor);
72  AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse(
73      &profile_, &AutocompleteClassifierFactory::BuildInstanceFor);
74
75  TemplateURLService* turl_model =
76      TemplateURLServiceFactory::GetForProfile(&profile_);
77  turl_model->Load();
78
79  TemplateURLData data;
80  data.short_name = base::ASCIIToUTF16("t");
81  data.SetURL("https://www.google.com/?q={searchTerms}");
82  data.suggestions_url = "https://www.google.com/complete/?q={searchTerms}";
83  data.instant_url = "https://does/not/exist?strk=1";
84  data.search_terms_replacement_key = "strk";
85  default_t_url_ = new TemplateURL(data);
86  turl_model->Add(default_t_url_);
87  turl_model->SetUserSelectedDefaultSearchProvider(default_t_url_);
88
89  provider_ = ZeroSuggestProvider::Create(this, turl_model, &profile_);
90}
91
92void ZeroSuggestProviderTest::TearDown() {
93  // Shutdown the provider before the profile.
94  provider_ = NULL;
95}
96
97void ZeroSuggestProviderTest::OnProviderUpdate(bool updated_matches) {
98}
99
100void ZeroSuggestProviderTest::ResetFieldTrialList() {
101  // Destroy the existing FieldTrialList before creating a new one to avoid
102  // a DCHECK.
103  field_trial_list_.reset();
104  field_trial_list_.reset(new base::FieldTrialList(
105      new metrics::SHA1EntropyProvider("foo")));
106  variations::testing::ClearAllVariationParams();
107}
108
109void ZeroSuggestProviderTest::CreatePersonalizedFieldTrial() {
110  std::map<std::string, std::string> params;
111  params[std::string(OmniboxFieldTrial::kZeroSuggestRule)] = "true";
112  params[std::string(OmniboxFieldTrial::kZeroSuggestVariantRule)] =
113      "Personalized";
114  variations::AssociateVariationParams(
115      OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params);
116  base::FieldTrialList::CreateFieldTrial(
117      OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A");
118}
119
120TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestCachingFirstRun) {
121  CreatePersonalizedFieldTrial();
122
123  // Ensure the cache is empty.
124  PrefService* prefs = profile_.GetPrefs();
125  prefs->SetString(prefs::kZeroSuggestCachedResults, std::string());
126
127  std::string url("http://www.cnn.com");
128  AutocompleteInput input(base::ASCIIToUTF16(url), base::string16::npos,
129                          base::string16(), GURL(url),
130                          metrics::OmniboxEventProto::INVALID_SPEC, true, false,
131                          true, true,
132                          ChromeAutocompleteSchemeClassifier(&profile_));
133
134  provider_->Start(input, false);
135
136  EXPECT_TRUE(prefs->GetString(prefs::kZeroSuggestCachedResults).empty());
137  EXPECT_TRUE(provider_->matches().empty());
138
139  net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(1);
140  ASSERT_TRUE(fetcher);
141  fetcher->set_response_code(200);
142  std::string json_response("[\"\",[\"search1\", \"search2\", \"search3\"],"
143      "[],[],{\"google:suggestrelevance\":[602, 601, 600],"
144      "\"google:verbatimrelevance\":1300}]");
145  fetcher->SetResponseString(json_response);
146  fetcher->delegate()->OnURLFetchComplete(fetcher);
147
148  base::RunLoop().RunUntilIdle();
149
150  EXPECT_EQ(4U, provider_->matches().size());  // 3 results + verbatim
151  EXPECT_EQ(json_response, prefs->GetString(prefs::kZeroSuggestCachedResults));
152}
153
154TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestHasCachedResults) {
155  CreatePersonalizedFieldTrial();
156
157  std::string url("http://www.cnn.com");
158  AutocompleteInput input(base::ASCIIToUTF16(url), base::string16::npos,
159                          base::string16(), GURL(url),
160                          metrics::OmniboxEventProto::INVALID_SPEC, true, false,
161                          true, true,
162                          ChromeAutocompleteSchemeClassifier(&profile_));
163
164  // Set up the pref to cache the response from the previous run.
165  std::string json_response("[\"\",[\"search1\", \"search2\", \"search3\"],"
166      "[],[],{\"google:suggestrelevance\":[602, 601, 600],"
167      "\"google:verbatimrelevance\":1300}]");
168  PrefService* prefs = profile_.GetPrefs();
169  prefs->SetString(prefs::kZeroSuggestCachedResults, json_response);
170
171  provider_->Start(input, false);
172
173  // Expect that matches get populated synchronously out of the cache.
174  ASSERT_EQ(4U, provider_->matches().size());
175  EXPECT_EQ(base::ASCIIToUTF16("search1"), provider_->matches()[1].contents);
176  EXPECT_EQ(base::ASCIIToUTF16("search2"), provider_->matches()[2].contents);
177  EXPECT_EQ(base::ASCIIToUTF16("search3"), provider_->matches()[3].contents);
178
179  net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(1);
180  ASSERT_TRUE(fetcher);
181  fetcher->set_response_code(200);
182  std::string json_response2("[\"\",[\"search4\", \"search5\", \"search6\"],"
183      "[],[],{\"google:suggestrelevance\":[602, 601, 600],"
184      "\"google:verbatimrelevance\":1300}]");
185  fetcher->SetResponseString(json_response2);
186  fetcher->delegate()->OnURLFetchComplete(fetcher);
187
188  base::RunLoop().RunUntilIdle();
189
190  // Expect the same 4 results after the response has been handled.
191  ASSERT_EQ(4U, provider_->matches().size());
192  EXPECT_EQ(base::ASCIIToUTF16("search1"), provider_->matches()[1].contents);
193  EXPECT_EQ(base::ASCIIToUTF16("search2"), provider_->matches()[2].contents);
194  EXPECT_EQ(base::ASCIIToUTF16("search3"), provider_->matches()[3].contents);
195
196  // Expect the new results have been stored.
197  EXPECT_EQ(json_response2,
198            prefs->GetString(prefs::kZeroSuggestCachedResults));
199}
200
201TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestReceivedEmptyResults) {
202  CreatePersonalizedFieldTrial();
203
204  std::string url("http://www.cnn.com");
205  AutocompleteInput input(base::ASCIIToUTF16(url), base::string16::npos,
206                          base::string16(), GURL(url),
207                          metrics::OmniboxEventProto::INVALID_SPEC, true, false,
208                          true, true,
209                          ChromeAutocompleteSchemeClassifier(&profile_));
210
211  // Set up the pref to cache the response from the previous run.
212  std::string json_response("[\"\",[\"search1\", \"search2\", \"search3\"],"
213      "[],[],{\"google:suggestrelevance\":[602, 601, 600],"
214      "\"google:verbatimrelevance\":1300}]");
215  PrefService* prefs = profile_.GetPrefs();
216  prefs->SetString(prefs::kZeroSuggestCachedResults, json_response);
217
218  provider_->Start(input, false);
219
220  // Expect that matches get populated synchronously out of the cache.
221  ASSERT_EQ(4U, provider_->matches().size());
222  EXPECT_EQ(base::ASCIIToUTF16("search1"), provider_->matches()[1].contents);
223  EXPECT_EQ(base::ASCIIToUTF16("search2"), provider_->matches()[2].contents);
224  EXPECT_EQ(base::ASCIIToUTF16("search3"), provider_->matches()[3].contents);
225
226  net::TestURLFetcher* fetcher = test_factory_.GetFetcherByID(1);
227  ASSERT_TRUE(fetcher);
228  fetcher->set_response_code(200);
229  std::string empty_response("[\"\",[],[],[],{}]");
230  fetcher->SetResponseString(empty_response);
231  fetcher->delegate()->OnURLFetchComplete(fetcher);
232
233  base::RunLoop().RunUntilIdle();
234
235  // Expect that the matches have been cleared.
236  ASSERT_TRUE(provider_->matches().empty());
237
238  // Expect the new results have been stored.
239  EXPECT_EQ(empty_response,
240            prefs->GetString(prefs::kZeroSuggestCachedResults));
241}
242