1 // Copyright (c) 2013 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/omnibox/omnibox_field_trial.h"
7 #include "base/basictypes.h"
8 #include "base/command_line.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/strings/string16.h"
12 #include "chrome/browser/autocomplete/autocomplete_input.h"
13 #include "chrome/browser/search/search.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "components/variations/entropy_provider.h"
16 #include "components/variations/variations_associated_data.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 class OmniboxFieldTrialTest
: public testing::Test
{
21 OmniboxFieldTrialTest() {
22 ResetFieldTrialList();
25 void ResetFieldTrialList() {
26 // Destroy the existing FieldTrialList before creating a new one to avoid
28 field_trial_list_
.reset();
29 field_trial_list_
.reset(new base::FieldTrialList(
30 new metrics::SHA1EntropyProvider("foo")));
31 chrome_variations::testing::ClearAllVariationParams();
32 OmniboxFieldTrial::ActivateDynamicTrials();
35 // Creates and activates a field trial.
36 static base::FieldTrial
* CreateTestTrial(const std::string
& name
,
37 const std::string
& group_name
) {
38 base::FieldTrial
* trial
= base::FieldTrialList::CreateFieldTrial(
44 // EXPECTS that demotions[match_type] exists with value expected_value.
45 static void VerifyDemotion(
46 const OmniboxFieldTrial::DemotionMultipliers
& demotions
,
47 AutocompleteMatchType::Type match_type
,
48 float expected_value
);
50 // EXPECT()s that OmniboxFieldTrial::GetValueForRuleInContext(|rule|,
51 // |page_classification|) returns |rule_value|.
52 static void ExpectRuleValue(
53 const std::string
& rule_value
,
54 const std::string
& rule
,
55 AutocompleteInput::PageClassification page_classification
);
58 scoped_ptr
<base::FieldTrialList
> field_trial_list_
;
60 DISALLOW_COPY_AND_ASSIGN(OmniboxFieldTrialTest
);
64 void OmniboxFieldTrialTest::VerifyDemotion(
65 const OmniboxFieldTrial::DemotionMultipliers
& demotions
,
66 AutocompleteMatchType::Type match_type
,
67 float expected_value
) {
68 OmniboxFieldTrial::DemotionMultipliers::const_iterator demotion_it
=
69 demotions
.find(match_type
);
70 ASSERT_TRUE(demotion_it
!= demotions
.end());
71 EXPECT_FLOAT_EQ(expected_value
, demotion_it
->second
);
75 void OmniboxFieldTrialTest::ExpectRuleValue(
76 const std::string
& rule_value
,
77 const std::string
& rule
,
78 AutocompleteInput::PageClassification page_classification
) {
80 OmniboxFieldTrial::GetValueForRuleInContext(
81 rule
, page_classification
));
84 // Test if GetDisabledProviderTypes() properly parses various field trial
86 TEST_F(OmniboxFieldTrialTest
, GetDisabledProviderTypes
) {
87 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
90 SCOPED_TRACE("Invalid groups");
91 CreateTestTrial("AutocompleteDynamicTrial_0", "DisabledProviders_");
92 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
93 ResetFieldTrialList();
94 CreateTestTrial("AutocompleteDynamicTrial_1", "DisabledProviders_XXX");
95 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
96 ResetFieldTrialList();
97 CreateTestTrial("AutocompleteDynamicTrial_1", "DisabledProviders_12abc");
98 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
102 SCOPED_TRACE("Valid group name, unsupported trial name.");
103 ResetFieldTrialList();
104 CreateTestTrial("UnsupportedTrialName", "DisabledProviders_20");
105 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
109 SCOPED_TRACE("Valid field and group name.");
110 ResetFieldTrialList();
111 CreateTestTrial("AutocompleteDynamicTrial_2", "DisabledProviders_3");
112 EXPECT_EQ(3, OmniboxFieldTrial::GetDisabledProviderTypes());
113 // Two groups should be OR-ed together.
114 CreateTestTrial("AutocompleteDynamicTrial_3", "DisabledProviders_6");
115 EXPECT_EQ(7, OmniboxFieldTrial::GetDisabledProviderTypes());
119 // Test if InZeroSuggestFieldTrial() properly parses various field trial
121 TEST_F(OmniboxFieldTrialTest
, ZeroSuggestFieldTrial
) {
122 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
125 SCOPED_TRACE("Valid group name, unsupported trial name.");
126 ResetFieldTrialList();
127 CreateTestTrial("UnsupportedTrialName", "EnableZeroSuggest");
128 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
130 ResetFieldTrialList();
131 CreateTestTrial("UnsupportedTrialName", "EnableZeroSuggest_Queries");
132 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
134 ResetFieldTrialList();
135 CreateTestTrial("UnsupportedTrialName", "EnableZeroSuggest_URLS");
136 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
140 SCOPED_TRACE("Valid trial name, unsupported group name.");
141 ResetFieldTrialList();
142 CreateTestTrial("AutocompleteDynamicTrial_2", "UnrelatedGroup");
143 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
147 SCOPED_TRACE("Valid field and group name.");
148 ResetFieldTrialList();
149 CreateTestTrial("AutocompleteDynamicTrial_2", "EnableZeroSuggest");
150 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
152 ResetFieldTrialList();
153 CreateTestTrial("AutocompleteDynamicTrial_2", "EnableZeroSuggest_Queries");
154 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
156 ResetFieldTrialList();
157 CreateTestTrial("AutocompleteDynamicTrial_3", "EnableZeroSuggest_URLs");
158 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
162 SCOPED_TRACE("Bundled field trial parameters.");
163 ResetFieldTrialList();
164 std::map
<std::string
, std::string
> params
;
165 params
[std::string(OmniboxFieldTrial::kZeroSuggestRule
)] = "true";
166 ASSERT_TRUE(chrome_variations::AssociateVariationParams(
167 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
168 base::FieldTrialList::CreateFieldTrial(
169 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
170 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
171 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial());
172 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial());
174 ResetFieldTrialList();
175 params
[std::string(OmniboxFieldTrial::kZeroSuggestVariantRule
)] =
177 ASSERT_TRUE(chrome_variations::AssociateVariationParams(
178 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
179 base::FieldTrialList::CreateFieldTrial(
180 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
181 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
182 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial());
183 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial());
185 ResetFieldTrialList();
186 params
[std::string(OmniboxFieldTrial::kZeroSuggestVariantRule
)] =
188 base::FieldTrialList::CreateFieldTrial(
189 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
190 ASSERT_TRUE(chrome_variations::AssociateVariationParams(
191 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
192 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
193 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial());
194 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial());
198 TEST_F(OmniboxFieldTrialTest
, GetDemotionsByTypeWithFallback
) {
200 std::map
<std::string
, std::string
> params
;
201 params
[std::string(OmniboxFieldTrial::kDemoteByTypeRule
) + ":1:*"] =
203 params
[std::string(OmniboxFieldTrial::kDemoteByTypeRule
) + ":3:*"] =
205 params
[std::string(OmniboxFieldTrial::kDemoteByTypeRule
) + ":*:*"] = "1:25";
206 ASSERT_TRUE(chrome_variations::AssociateVariationParams(
207 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
209 base::FieldTrialList::CreateFieldTrial(
210 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
211 OmniboxFieldTrial::DemotionMultipliers demotions_by_type
;
212 OmniboxFieldTrial::GetDemotionsByType(
213 AutocompleteInput::NTP
, &demotions_by_type
);
214 ASSERT_EQ(2u, demotions_by_type
.size());
215 VerifyDemotion(demotions_by_type
, AutocompleteMatchType::HISTORY_URL
, 0.5);
216 VerifyDemotion(demotions_by_type
, AutocompleteMatchType::HISTORY_TITLE
, 0.0);
217 OmniboxFieldTrial::GetDemotionsByType(
218 AutocompleteInput::HOME_PAGE
, &demotions_by_type
);
219 ASSERT_EQ(1u, demotions_by_type
.size());
220 VerifyDemotion(demotions_by_type
, AutocompleteMatchType::NAVSUGGEST
, 1.0);
221 OmniboxFieldTrial::GetDemotionsByType(
222 AutocompleteInput::BLANK
, &demotions_by_type
);
223 ASSERT_EQ(1u, demotions_by_type
.size());
224 VerifyDemotion(demotions_by_type
, AutocompleteMatchType::HISTORY_URL
, 0.25);
227 TEST_F(OmniboxFieldTrialTest
, GetValueForRuleInContext
) {
229 std::map
<std::string
, std::string
> params
;
230 // Rule 1 has some exact matches and fallbacks at every level.
231 params
["rule1:1:0"] = "rule1-1-0-value"; // NTP
232 params
["rule1:3:0"] = "rule1-3-0-value"; // HOME_PAGE
233 params
["rule1:4:1"] = "rule1-4-1-value"; // OTHER
234 params
["rule1:4:*"] = "rule1-4-*-value"; // OTHER
235 params
["rule1:*:1"] = "rule1-*-1-value"; // global
236 params
["rule1:*:*"] = "rule1-*-*-value"; // global
237 // Rule 2 has no exact matches but has fallbacks.
238 params
["rule2:*:0"] = "rule2-*-0-value"; // global
239 params
["rule2:1:*"] = "rule2-1-*-value"; // NTP
240 params
["rule2:*:*"] = "rule2-*-*-value"; // global
241 // Rule 3 has only a global fallback.
242 params
["rule3:*:*"] = "rule3-*-*-value"; // global
243 // Rule 4 has an exact match but no fallbacks.
244 params
["rule4:4:0"] = "rule4-4-0-value"; // OTHER
245 // Add a malformed rule to make sure it doesn't screw things up.
246 params
["unrecognized"] = "unrecognized-value";
247 ASSERT_TRUE(chrome_variations::AssociateVariationParams(
248 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
251 base::FieldTrialList::CreateFieldTrial(
252 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
254 if (chrome::IsInstantExtendedAPIEnabled()) {
255 // Tests with Instant Extended enabled.
257 ExpectRuleValue("rule1-4-1-value",
258 "rule1", AutocompleteInput::OTHER
); // exact match
259 ExpectRuleValue("rule1-*-1-value",
260 "rule1", AutocompleteInput::BLANK
); // partial fallback
261 ExpectRuleValue("rule1-*-1-value",
263 AutocompleteInput::NTP
); // partial fallback
266 ExpectRuleValue("rule2-1-*-value",
268 AutocompleteInput::NTP
); // partial fallback
269 ExpectRuleValue("rule2-*-*-value",
270 "rule2", AutocompleteInput::OTHER
); // global fallback
273 ExpectRuleValue("rule3-*-*-value",
275 AutocompleteInput::HOME_PAGE
); // global fallback
276 ExpectRuleValue("rule3-*-*-value",
278 AutocompleteInput::OTHER
); // global fallback
283 AutocompleteInput::BLANK
); // no global fallback
286 AutocompleteInput::HOME_PAGE
); // no global fallback
288 // Tests for rule 5 (a missing rule).
290 "rule5", AutocompleteInput::OTHER
); // no rule at all
293 ExpectRuleValue("rule1-1-0-value",
294 "rule1", AutocompleteInput::NTP
); // exact match
295 ExpectRuleValue("rule1-1-0-value",
296 "rule1", AutocompleteInput::NTP
); // exact match
297 ExpectRuleValue("rule1-*-*-value",
298 "rule1", AutocompleteInput::BLANK
); // fallback to global
299 ExpectRuleValue("rule1-3-0-value",
301 AutocompleteInput::HOME_PAGE
); // exact match
302 ExpectRuleValue("rule1-4-*-value",
303 "rule1", AutocompleteInput::OTHER
); // partial fallback
304 ExpectRuleValue("rule1-*-*-value",
306 AutocompleteInput:: // fallback to global
307 SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT
);
309 ExpectRuleValue("rule2-*-0-value",
311 AutocompleteInput::HOME_PAGE
); // partial fallback
312 ExpectRuleValue("rule2-*-0-value",
313 "rule2", AutocompleteInput::OTHER
); // partial fallback
316 ExpectRuleValue("rule3-*-*-value",
318 AutocompleteInput::HOME_PAGE
); // fallback to global
319 ExpectRuleValue("rule3-*-*-value",
320 "rule3", AutocompleteInput::OTHER
); // fallback to global
324 "rule4", AutocompleteInput::BLANK
); // no global fallback
327 AutocompleteInput::HOME_PAGE
); // no global fallback
328 ExpectRuleValue("rule4-4-0-value",
329 "rule4", AutocompleteInput::OTHER
); // exact match
331 // Tests for rule 5 (a missing rule).
333 "rule5", AutocompleteInput::OTHER
); // no rule at all
337 TEST_F(OmniboxFieldTrialTest
, HUPNewScoringFieldTrial
) {
339 std::map
<std::string
, std::string
> params
;
340 params
[std::string(OmniboxFieldTrial::kHUPNewScoringEnabledParam
)] = "1";
342 OmniboxFieldTrial::kHUPNewScoringTypedCountRelevanceCapParam
)] = "56";
344 OmniboxFieldTrial::kHUPNewScoringTypedCountHalfLifeTimeParam
)] = "77";
346 OmniboxFieldTrial::kHUPNewScoringTypedCountScoreBucketsParam
)] =
347 "0.2:25,0.1:1001,2.3:777";
349 OmniboxFieldTrial::kHUPNewScoringVisitedCountRelevanceCapParam
)] = "11";
351 OmniboxFieldTrial::kHUPNewScoringVisitedCountHalfLifeTimeParam
)] = "31";
353 OmniboxFieldTrial::kHUPNewScoringVisitedCountScoreBucketsParam
)] =
355 ASSERT_TRUE(chrome_variations::AssociateVariationParams(
356 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
358 base::FieldTrialList::CreateFieldTrial(
359 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
361 HUPScoringParams scoring_params
;
362 OmniboxFieldTrial::GetExperimentalHUPScoringParams(&scoring_params
);
363 EXPECT_TRUE(scoring_params
.experimental_scoring_enabled
);
364 EXPECT_EQ(56, scoring_params
.typed_count_buckets
.relevance_cap());
365 EXPECT_EQ(77, scoring_params
.typed_count_buckets
.half_life_days());
366 ASSERT_EQ(3u, scoring_params
.typed_count_buckets
.buckets().size());
367 EXPECT_EQ(std::make_pair(2.3, 777),
368 scoring_params
.typed_count_buckets
.buckets()[0]);
369 EXPECT_EQ(std::make_pair(0.2, 25),
370 scoring_params
.typed_count_buckets
.buckets()[1]);
371 EXPECT_EQ(std::make_pair(0.1, 1001),
372 scoring_params
.typed_count_buckets
.buckets()[2]);
373 EXPECT_EQ(11, scoring_params
.visited_count_buckets
.relevance_cap());
374 EXPECT_EQ(31, scoring_params
.visited_count_buckets
.half_life_days());
375 ASSERT_EQ(2u, scoring_params
.visited_count_buckets
.buckets().size());
376 EXPECT_EQ(std::make_pair(5.0, 300),
377 scoring_params
.visited_count_buckets
.buckets()[0]);
378 EXPECT_EQ(std::make_pair(0.0, 200),
379 scoring_params
.visited_count_buckets
.buckets()[1]);
382 TEST_F(OmniboxFieldTrialTest
, HalfLifeTimeDecay
) {
383 HUPScoringParams::ScoreBuckets buckets
;
385 // No decay by default.
386 EXPECT_EQ(1.0, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(7)));
388 buckets
.set_half_life_days(7);
389 EXPECT_EQ(0.5, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(7)));
390 EXPECT_EQ(0.25, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(14)));
391 EXPECT_EQ(1.0, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(0)));
392 EXPECT_EQ(1.0, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(-1)));