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/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 "components/metrics/proto/omnibox_event.pb.h"
13 #include "components/search/search.h"
14 #include "components/variations/entropy_provider.h"
15 #include "components/variations/variations_associated_data.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 using metrics::OmniboxEventProto
;
20 class OmniboxFieldTrialTest
: public testing::Test
{
22 OmniboxFieldTrialTest() {
23 ResetFieldTrialList();
26 void ResetFieldTrialList() {
27 // Destroy the existing FieldTrialList before creating a new one to avoid
29 field_trial_list_
.reset();
30 field_trial_list_
.reset(new base::FieldTrialList(
31 new metrics::SHA1EntropyProvider("foo")));
32 variations::testing::ClearAllVariationParams();
33 OmniboxFieldTrial::ActivateDynamicTrials();
36 // Creates and activates a field trial.
37 static base::FieldTrial
* CreateTestTrial(const std::string
& name
,
38 const std::string
& group_name
) {
39 base::FieldTrial
* trial
= base::FieldTrialList::CreateFieldTrial(
45 // Add a field trial disabling ZeroSuggest.
46 static void CreateDisableZeroSuggestTrial() {
47 std::map
<std::string
, std::string
> params
;
48 params
[std::string(OmniboxFieldTrial::kZeroSuggestRule
)] = "false";
49 variations::AssociateVariationParams(
50 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
);
51 base::FieldTrialList::CreateFieldTrial(
52 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
55 // EXPECTS that demotions[match_type] exists with value expected_value.
56 static void VerifyDemotion(
57 const OmniboxFieldTrial::DemotionMultipliers
& demotions
,
58 AutocompleteMatchType::Type match_type
,
59 float expected_value
);
61 // EXPECT()s that OmniboxFieldTrial::GetValueForRuleInContext(|rule|,
62 // |page_classification|) returns |rule_value|.
63 static void ExpectRuleValue(
64 const std::string
& rule_value
,
65 const std::string
& rule
,
66 OmniboxEventProto::PageClassification page_classification
);
69 scoped_ptr
<base::FieldTrialList
> field_trial_list_
;
71 DISALLOW_COPY_AND_ASSIGN(OmniboxFieldTrialTest
);
75 void OmniboxFieldTrialTest::VerifyDemotion(
76 const OmniboxFieldTrial::DemotionMultipliers
& demotions
,
77 AutocompleteMatchType::Type match_type
,
78 float expected_value
) {
79 OmniboxFieldTrial::DemotionMultipliers::const_iterator demotion_it
=
80 demotions
.find(match_type
);
81 ASSERT_TRUE(demotion_it
!= demotions
.end());
82 EXPECT_FLOAT_EQ(expected_value
, demotion_it
->second
);
86 void OmniboxFieldTrialTest::ExpectRuleValue(
87 const std::string
& rule_value
,
88 const std::string
& rule
,
89 OmniboxEventProto::PageClassification page_classification
) {
91 OmniboxFieldTrial::GetValueForRuleInContext(
92 rule
, page_classification
));
95 // Test if GetDisabledProviderTypes() properly parses various field trial
97 TEST_F(OmniboxFieldTrialTest
, GetDisabledProviderTypes
) {
98 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
101 SCOPED_TRACE("Invalid groups");
102 CreateTestTrial("AutocompleteDynamicTrial_0", "DisabledProviders_");
103 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
104 ResetFieldTrialList();
105 CreateTestTrial("AutocompleteDynamicTrial_1", "DisabledProviders_XXX");
106 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
107 ResetFieldTrialList();
108 CreateTestTrial("AutocompleteDynamicTrial_1", "DisabledProviders_12abc");
109 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
113 SCOPED_TRACE("Valid group name, unsupported trial name.");
114 ResetFieldTrialList();
115 CreateTestTrial("UnsupportedTrialName", "DisabledProviders_20");
116 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes());
120 SCOPED_TRACE("Valid field and group name.");
121 ResetFieldTrialList();
122 CreateTestTrial("AutocompleteDynamicTrial_2", "DisabledProviders_3");
123 EXPECT_EQ(3, OmniboxFieldTrial::GetDisabledProviderTypes());
124 // Two groups should be OR-ed together.
125 CreateTestTrial("AutocompleteDynamicTrial_3", "DisabledProviders_6");
126 EXPECT_EQ(7, OmniboxFieldTrial::GetDisabledProviderTypes());
130 // Test if InZeroSuggestFieldTrial() properly parses various field trial
132 TEST_F(OmniboxFieldTrialTest
, ZeroSuggestFieldTrial
) {
133 // Default ZeroSuggest setting depends on OS.
134 #if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_LINUX) || \
135 (defined(OS_MACOSX) && !defined(OS_IOS))
136 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
138 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
142 SCOPED_TRACE("Disable ZeroSuggest.");
143 ResetFieldTrialList();
144 CreateDisableZeroSuggestTrial();
145 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
149 SCOPED_TRACE("Bundled field trial parameters.");
150 ResetFieldTrialList();
151 std::map
<std::string
, std::string
> params
;
152 params
[std::string(OmniboxFieldTrial::kZeroSuggestRule
)] = "true";
153 ASSERT_TRUE(variations::AssociateVariationParams(
154 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
155 base::FieldTrialList::CreateFieldTrial(
156 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
157 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
158 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial());
159 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial());
161 ResetFieldTrialList();
162 params
[std::string(OmniboxFieldTrial::kZeroSuggestVariantRule
)] =
164 ASSERT_TRUE(variations::AssociateVariationParams(
165 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
166 base::FieldTrialList::CreateFieldTrial(
167 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
168 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
169 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial());
170 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial());
172 ResetFieldTrialList();
173 params
[std::string(OmniboxFieldTrial::kZeroSuggestVariantRule
)] =
175 base::FieldTrialList::CreateFieldTrial(
176 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
177 ASSERT_TRUE(variations::AssociateVariationParams(
178 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
179 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial());
180 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial());
181 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial());
185 TEST_F(OmniboxFieldTrialTest
, GetDemotionsByTypeWithFallback
) {
187 std::map
<std::string
, std::string
> params
;
188 params
[std::string(OmniboxFieldTrial::kDemoteByTypeRule
) + ":1:*"] =
190 params
[std::string(OmniboxFieldTrial::kDemoteByTypeRule
) + ":3:*"] =
192 params
[std::string(OmniboxFieldTrial::kDemoteByTypeRule
) + ":*:*"] = "1:25";
193 ASSERT_TRUE(variations::AssociateVariationParams(
194 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
196 base::FieldTrialList::CreateFieldTrial(
197 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
198 OmniboxFieldTrial::DemotionMultipliers demotions_by_type
;
199 OmniboxFieldTrial::GetDemotionsByType(
200 OmniboxEventProto::NTP
, &demotions_by_type
);
201 ASSERT_EQ(2u, demotions_by_type
.size());
202 VerifyDemotion(demotions_by_type
, AutocompleteMatchType::HISTORY_URL
, 0.5);
203 VerifyDemotion(demotions_by_type
, AutocompleteMatchType::HISTORY_TITLE
, 0.0);
204 OmniboxFieldTrial::GetDemotionsByType(
205 OmniboxEventProto::HOME_PAGE
, &demotions_by_type
);
206 ASSERT_EQ(1u, demotions_by_type
.size());
207 VerifyDemotion(demotions_by_type
, AutocompleteMatchType::NAVSUGGEST
, 1.0);
208 OmniboxFieldTrial::GetDemotionsByType(
209 OmniboxEventProto::BLANK
, &demotions_by_type
);
210 ASSERT_EQ(1u, demotions_by_type
.size());
211 VerifyDemotion(demotions_by_type
, AutocompleteMatchType::HISTORY_URL
, 0.25);
214 TEST_F(OmniboxFieldTrialTest
, GetValueForRuleInContext
) {
216 std::map
<std::string
, std::string
> params
;
217 // Rule 1 has some exact matches and fallbacks at every level.
218 params
["rule1:1:0"] = "rule1-1-0-value"; // NTP
219 params
["rule1:3:0"] = "rule1-3-0-value"; // HOME_PAGE
220 params
["rule1:4:1"] = "rule1-4-1-value"; // OTHER
221 params
["rule1:4:*"] = "rule1-4-*-value"; // OTHER
222 params
["rule1:*:1"] = "rule1-*-1-value"; // global
223 params
["rule1:*:*"] = "rule1-*-*-value"; // global
224 // Rule 2 has no exact matches but has fallbacks.
225 params
["rule2:*:0"] = "rule2-*-0-value"; // global
226 params
["rule2:1:*"] = "rule2-1-*-value"; // NTP
227 params
["rule2:*:*"] = "rule2-*-*-value"; // global
228 // Rule 3 has only a global fallback.
229 params
["rule3:*:*"] = "rule3-*-*-value"; // global
230 // Rule 4 has an exact match but no fallbacks.
231 params
["rule4:4:0"] = "rule4-4-0-value"; // OTHER
232 // Add a malformed rule to make sure it doesn't screw things up.
233 params
["unrecognized"] = "unrecognized-value";
234 ASSERT_TRUE(variations::AssociateVariationParams(
235 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
238 base::FieldTrialList::CreateFieldTrial(
239 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
241 if (chrome::IsInstantExtendedAPIEnabled()) {
242 // Tests with Instant Extended enabled.
244 ExpectRuleValue("rule1-4-1-value",
245 "rule1", OmniboxEventProto::OTHER
); // exact match
246 ExpectRuleValue("rule1-*-1-value",
247 "rule1", OmniboxEventProto::BLANK
); // partial fallback
248 ExpectRuleValue("rule1-*-1-value",
250 OmniboxEventProto::NTP
); // partial fallback
253 ExpectRuleValue("rule2-1-*-value",
255 OmniboxEventProto::NTP
); // partial fallback
256 ExpectRuleValue("rule2-*-*-value",
257 "rule2", OmniboxEventProto::OTHER
); // global fallback
260 ExpectRuleValue("rule3-*-*-value",
262 OmniboxEventProto::HOME_PAGE
); // global fallback
263 ExpectRuleValue("rule3-*-*-value",
265 OmniboxEventProto::OTHER
); // global fallback
270 OmniboxEventProto::BLANK
); // no global fallback
273 OmniboxEventProto::HOME_PAGE
); // no global fallback
275 // Tests for rule 5 (a missing rule).
277 "rule5", OmniboxEventProto::OTHER
); // no rule at all
280 ExpectRuleValue("rule1-1-0-value",
281 "rule1", OmniboxEventProto::NTP
); // exact match
282 ExpectRuleValue("rule1-1-0-value",
283 "rule1", OmniboxEventProto::NTP
); // exact match
284 ExpectRuleValue("rule1-*-*-value",
285 "rule1", OmniboxEventProto::BLANK
); // fallback to global
286 ExpectRuleValue("rule1-3-0-value",
288 OmniboxEventProto::HOME_PAGE
); // exact match
289 ExpectRuleValue("rule1-4-*-value",
290 "rule1", OmniboxEventProto::OTHER
); // partial fallback
291 ExpectRuleValue("rule1-*-*-value",
293 OmniboxEventProto:: // fallback to global
294 SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT
);
296 ExpectRuleValue("rule2-*-0-value",
298 OmniboxEventProto::HOME_PAGE
); // partial fallback
299 ExpectRuleValue("rule2-*-0-value",
300 "rule2", OmniboxEventProto::OTHER
); // partial fallback
303 ExpectRuleValue("rule3-*-*-value",
305 OmniboxEventProto::HOME_PAGE
); // fallback to global
306 ExpectRuleValue("rule3-*-*-value",
307 "rule3", OmniboxEventProto::OTHER
); // fallback to global
311 "rule4", OmniboxEventProto::BLANK
); // no global fallback
314 OmniboxEventProto::HOME_PAGE
); // no global fallback
315 ExpectRuleValue("rule4-4-0-value",
316 "rule4", OmniboxEventProto::OTHER
); // exact match
318 // Tests for rule 5 (a missing rule).
320 "rule5", OmniboxEventProto::OTHER
); // no rule at all
324 TEST_F(OmniboxFieldTrialTest
, HUPNewScoringFieldTrial
) {
326 std::map
<std::string
, std::string
> params
;
327 params
[std::string(OmniboxFieldTrial::kHUPNewScoringEnabledParam
)] = "1";
329 OmniboxFieldTrial::kHUPNewScoringTypedCountRelevanceCapParam
)] = "56";
331 OmniboxFieldTrial::kHUPNewScoringTypedCountHalfLifeTimeParam
)] = "77";
333 OmniboxFieldTrial::kHUPNewScoringTypedCountScoreBucketsParam
)] =
334 "0.2:25,0.1:1001,2.3:777";
336 OmniboxFieldTrial::kHUPNewScoringVisitedCountRelevanceCapParam
)] = "11";
338 OmniboxFieldTrial::kHUPNewScoringVisitedCountHalfLifeTimeParam
)] = "31";
340 OmniboxFieldTrial::kHUPNewScoringVisitedCountScoreBucketsParam
)] =
342 ASSERT_TRUE(variations::AssociateVariationParams(
343 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A", params
));
345 base::FieldTrialList::CreateFieldTrial(
346 OmniboxFieldTrial::kBundledExperimentFieldTrialName
, "A");
348 HUPScoringParams scoring_params
;
349 OmniboxFieldTrial::GetExperimentalHUPScoringParams(&scoring_params
);
350 EXPECT_TRUE(scoring_params
.experimental_scoring_enabled
);
351 EXPECT_EQ(56, scoring_params
.typed_count_buckets
.relevance_cap());
352 EXPECT_EQ(77, scoring_params
.typed_count_buckets
.half_life_days());
353 ASSERT_EQ(3u, scoring_params
.typed_count_buckets
.buckets().size());
354 EXPECT_EQ(std::make_pair(2.3, 777),
355 scoring_params
.typed_count_buckets
.buckets()[0]);
356 EXPECT_EQ(std::make_pair(0.2, 25),
357 scoring_params
.typed_count_buckets
.buckets()[1]);
358 EXPECT_EQ(std::make_pair(0.1, 1001),
359 scoring_params
.typed_count_buckets
.buckets()[2]);
360 EXPECT_EQ(11, scoring_params
.visited_count_buckets
.relevance_cap());
361 EXPECT_EQ(31, scoring_params
.visited_count_buckets
.half_life_days());
362 ASSERT_EQ(2u, scoring_params
.visited_count_buckets
.buckets().size());
363 EXPECT_EQ(std::make_pair(5.0, 300),
364 scoring_params
.visited_count_buckets
.buckets()[0]);
365 EXPECT_EQ(std::make_pair(0.0, 200),
366 scoring_params
.visited_count_buckets
.buckets()[1]);
369 TEST_F(OmniboxFieldTrialTest
, HalfLifeTimeDecay
) {
370 HUPScoringParams::ScoreBuckets buckets
;
372 // No decay by default.
373 EXPECT_EQ(1.0, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(7)));
375 buckets
.set_half_life_days(7);
376 EXPECT_EQ(0.5, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(7)));
377 EXPECT_EQ(0.25, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(14)));
378 EXPECT_EQ(1.0, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(0)));
379 EXPECT_EQ(1.0, buckets
.HalfLifeTimeDecay(base::TimeDelta::FromDays(-1)));