| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "chrome/browser/omnibox/omnibox_field_trial.h" | |
| 6 | |
| 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/common/chrome_switches.h" | |
| 13 #include "components/metrics/proto/omnibox_event.pb.h" | |
| 14 #include "components/search/search.h" | |
| 15 #include "components/variations/entropy_provider.h" | |
| 16 #include "components/variations/variations_associated_data.h" | |
| 17 #include "testing/gtest/include/gtest/gtest.h" | |
| 18 | |
| 19 using metrics::OmniboxEventProto; | |
| 20 | |
| 21 class OmniboxFieldTrialTest : public testing::Test { | |
| 22 public: | |
| 23 OmniboxFieldTrialTest() { | |
| 24 ResetFieldTrialList(); | |
| 25 } | |
| 26 | |
| 27 void ResetFieldTrialList() { | |
| 28 // Destroy the existing FieldTrialList before creating a new one to avoid | |
| 29 // a DCHECK. | |
| 30 field_trial_list_.reset(); | |
| 31 field_trial_list_.reset(new base::FieldTrialList( | |
| 32 new metrics::SHA1EntropyProvider("foo"))); | |
| 33 variations::testing::ClearAllVariationParams(); | |
| 34 OmniboxFieldTrial::ActivateDynamicTrials(); | |
| 35 } | |
| 36 | |
| 37 // Creates and activates a field trial. | |
| 38 static base::FieldTrial* CreateTestTrial(const std::string& name, | |
| 39 const std::string& group_name) { | |
| 40 base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial( | |
| 41 name, group_name); | |
| 42 trial->group(); | |
| 43 return trial; | |
| 44 } | |
| 45 | |
| 46 // Add a field trial disabling ZeroSuggest. | |
| 47 static void CreateDisableZeroSuggestTrial() { | |
| 48 std::map<std::string, std::string> params; | |
| 49 params[std::string(OmniboxFieldTrial::kZeroSuggestRule)] = "false"; | |
| 50 variations::AssociateVariationParams( | |
| 51 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params); | |
| 52 base::FieldTrialList::CreateFieldTrial( | |
| 53 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); | |
| 54 } | |
| 55 | |
| 56 // EXPECTS that demotions[match_type] exists with value expected_value. | |
| 57 static void VerifyDemotion( | |
| 58 const OmniboxFieldTrial::DemotionMultipliers& demotions, | |
| 59 AutocompleteMatchType::Type match_type, | |
| 60 float expected_value); | |
| 61 | |
| 62 // EXPECT()s that OmniboxFieldTrial::GetValueForRuleInContext(|rule|, | |
| 63 // |page_classification|) returns |rule_value|. | |
| 64 static void ExpectRuleValue( | |
| 65 const std::string& rule_value, | |
| 66 const std::string& rule, | |
| 67 OmniboxEventProto::PageClassification page_classification); | |
| 68 | |
| 69 private: | |
| 70 scoped_ptr<base::FieldTrialList> field_trial_list_; | |
| 71 | |
| 72 DISALLOW_COPY_AND_ASSIGN(OmniboxFieldTrialTest); | |
| 73 }; | |
| 74 | |
| 75 // static | |
| 76 void OmniboxFieldTrialTest::VerifyDemotion( | |
| 77 const OmniboxFieldTrial::DemotionMultipliers& demotions, | |
| 78 AutocompleteMatchType::Type match_type, | |
| 79 float expected_value) { | |
| 80 OmniboxFieldTrial::DemotionMultipliers::const_iterator demotion_it = | |
| 81 demotions.find(match_type); | |
| 82 ASSERT_TRUE(demotion_it != demotions.end()); | |
| 83 EXPECT_FLOAT_EQ(expected_value, demotion_it->second); | |
| 84 } | |
| 85 | |
| 86 // static | |
| 87 void OmniboxFieldTrialTest::ExpectRuleValue( | |
| 88 const std::string& rule_value, | |
| 89 const std::string& rule, | |
| 90 OmniboxEventProto::PageClassification page_classification) { | |
| 91 EXPECT_EQ(rule_value, | |
| 92 OmniboxFieldTrial::GetValueForRuleInContext( | |
| 93 rule, page_classification)); | |
| 94 } | |
| 95 | |
| 96 // Test if GetDisabledProviderTypes() properly parses various field trial | |
| 97 // group names. | |
| 98 TEST_F(OmniboxFieldTrialTest, GetDisabledProviderTypes) { | |
| 99 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes()); | |
| 100 | |
| 101 { | |
| 102 SCOPED_TRACE("Invalid groups"); | |
| 103 CreateTestTrial("AutocompleteDynamicTrial_0", "DisabledProviders_"); | |
| 104 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes()); | |
| 105 ResetFieldTrialList(); | |
| 106 CreateTestTrial("AutocompleteDynamicTrial_1", "DisabledProviders_XXX"); | |
| 107 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes()); | |
| 108 ResetFieldTrialList(); | |
| 109 CreateTestTrial("AutocompleteDynamicTrial_1", "DisabledProviders_12abc"); | |
| 110 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes()); | |
| 111 } | |
| 112 | |
| 113 { | |
| 114 SCOPED_TRACE("Valid group name, unsupported trial name."); | |
| 115 ResetFieldTrialList(); | |
| 116 CreateTestTrial("UnsupportedTrialName", "DisabledProviders_20"); | |
| 117 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes()); | |
| 118 } | |
| 119 | |
| 120 { | |
| 121 SCOPED_TRACE("Valid field and group name."); | |
| 122 ResetFieldTrialList(); | |
| 123 CreateTestTrial("AutocompleteDynamicTrial_2", "DisabledProviders_3"); | |
| 124 EXPECT_EQ(3, OmniboxFieldTrial::GetDisabledProviderTypes()); | |
| 125 // Two groups should be OR-ed together. | |
| 126 CreateTestTrial("AutocompleteDynamicTrial_3", "DisabledProviders_6"); | |
| 127 EXPECT_EQ(7, OmniboxFieldTrial::GetDisabledProviderTypes()); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 // Test if InZeroSuggestFieldTrial() properly parses various field trial | |
| 132 // group names. | |
| 133 TEST_F(OmniboxFieldTrialTest, ZeroSuggestFieldTrial) { | |
| 134 // Default ZeroSuggest setting depends on OS. | |
| 135 #if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_LINUX) || \ | |
| 136 (defined(OS_MACOSX) && !defined(OS_IOS)) | |
| 137 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); | |
| 138 #else | |
| 139 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); | |
| 140 #endif | |
| 141 | |
| 142 { | |
| 143 SCOPED_TRACE("Disable ZeroSuggest."); | |
| 144 ResetFieldTrialList(); | |
| 145 CreateDisableZeroSuggestTrial(); | |
| 146 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); | |
| 147 } | |
| 148 | |
| 149 { | |
| 150 SCOPED_TRACE("Bundled field trial parameters."); | |
| 151 ResetFieldTrialList(); | |
| 152 std::map<std::string, std::string> params; | |
| 153 params[std::string(OmniboxFieldTrial::kZeroSuggestRule)] = "true"; | |
| 154 ASSERT_TRUE(variations::AssociateVariationParams( | |
| 155 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params)); | |
| 156 base::FieldTrialList::CreateFieldTrial( | |
| 157 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); | |
| 158 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); | |
| 159 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()); | |
| 160 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial()); | |
| 161 | |
| 162 ResetFieldTrialList(); | |
| 163 params[std::string(OmniboxFieldTrial::kZeroSuggestVariantRule)] = | |
| 164 "MostVisited"; | |
| 165 ASSERT_TRUE(variations::AssociateVariationParams( | |
| 166 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params)); | |
| 167 base::FieldTrialList::CreateFieldTrial( | |
| 168 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); | |
| 169 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); | |
| 170 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()); | |
| 171 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial()); | |
| 172 | |
| 173 ResetFieldTrialList(); | |
| 174 params[std::string(OmniboxFieldTrial::kZeroSuggestVariantRule)] = | |
| 175 "AfterTyping"; | |
| 176 base::FieldTrialList::CreateFieldTrial( | |
| 177 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); | |
| 178 ASSERT_TRUE(variations::AssociateVariationParams( | |
| 179 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params)); | |
| 180 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); | |
| 181 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()); | |
| 182 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial()); | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 TEST_F(OmniboxFieldTrialTest, GetDemotionsByTypeWithFallback) { | |
| 187 { | |
| 188 std::map<std::string, std::string> params; | |
| 189 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":1:*"] = | |
| 190 "1:50,2:0"; | |
| 191 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":3:*"] = | |
| 192 "5:100"; | |
| 193 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":*:*"] = "1:25"; | |
| 194 ASSERT_TRUE(variations::AssociateVariationParams( | |
| 195 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params)); | |
| 196 } | |
| 197 base::FieldTrialList::CreateFieldTrial( | |
| 198 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); | |
| 199 OmniboxFieldTrial::DemotionMultipliers demotions_by_type; | |
| 200 OmniboxFieldTrial::GetDemotionsByType( | |
| 201 OmniboxEventProto::NTP, &demotions_by_type); | |
| 202 ASSERT_EQ(2u, demotions_by_type.size()); | |
| 203 VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_URL, 0.5); | |
| 204 VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_TITLE, 0.0); | |
| 205 OmniboxFieldTrial::GetDemotionsByType( | |
| 206 OmniboxEventProto::HOME_PAGE, &demotions_by_type); | |
| 207 ASSERT_EQ(1u, demotions_by_type.size()); | |
| 208 VerifyDemotion(demotions_by_type, AutocompleteMatchType::NAVSUGGEST, 1.0); | |
| 209 OmniboxFieldTrial::GetDemotionsByType( | |
| 210 OmniboxEventProto::BLANK, &demotions_by_type); | |
| 211 ASSERT_EQ(1u, demotions_by_type.size()); | |
| 212 VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_URL, 0.25); | |
| 213 } | |
| 214 | |
| 215 TEST_F(OmniboxFieldTrialTest, GetValueForRuleInContext) { | |
| 216 { | |
| 217 std::map<std::string, std::string> params; | |
| 218 // Rule 1 has some exact matches and fallbacks at every level. | |
| 219 params["rule1:1:0"] = "rule1-1-0-value"; // NTP | |
| 220 params["rule1:3:0"] = "rule1-3-0-value"; // HOME_PAGE | |
| 221 params["rule1:4:1"] = "rule1-4-1-value"; // OTHER | |
| 222 params["rule1:4:*"] = "rule1-4-*-value"; // OTHER | |
| 223 params["rule1:*:1"] = "rule1-*-1-value"; // global | |
| 224 params["rule1:*:*"] = "rule1-*-*-value"; // global | |
| 225 // Rule 2 has no exact matches but has fallbacks. | |
| 226 params["rule2:*:0"] = "rule2-*-0-value"; // global | |
| 227 params["rule2:1:*"] = "rule2-1-*-value"; // NTP | |
| 228 params["rule2:*:*"] = "rule2-*-*-value"; // global | |
| 229 // Rule 3 has only a global fallback. | |
| 230 params["rule3:*:*"] = "rule3-*-*-value"; // global | |
| 231 // Rule 4 has an exact match but no fallbacks. | |
| 232 params["rule4:4:0"] = "rule4-4-0-value"; // OTHER | |
| 233 // Add a malformed rule to make sure it doesn't screw things up. | |
| 234 params["unrecognized"] = "unrecognized-value"; | |
| 235 ASSERT_TRUE(variations::AssociateVariationParams( | |
| 236 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params)); | |
| 237 } | |
| 238 | |
| 239 base::FieldTrialList::CreateFieldTrial( | |
| 240 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); | |
| 241 | |
| 242 if (chrome::IsInstantExtendedAPIEnabled()) { | |
| 243 // Tests with Instant Extended enabled. | |
| 244 // Tests for rule 1. | |
| 245 ExpectRuleValue("rule1-4-1-value", | |
| 246 "rule1", OmniboxEventProto::OTHER); // exact match | |
| 247 ExpectRuleValue("rule1-*-1-value", | |
| 248 "rule1", OmniboxEventProto::BLANK); // partial fallback | |
| 249 ExpectRuleValue("rule1-*-1-value", | |
| 250 "rule1", | |
| 251 OmniboxEventProto::NTP); // partial fallback | |
| 252 | |
| 253 // Tests for rule 2. | |
| 254 ExpectRuleValue("rule2-1-*-value", | |
| 255 "rule2", | |
| 256 OmniboxEventProto::NTP); // partial fallback | |
| 257 ExpectRuleValue("rule2-*-*-value", | |
| 258 "rule2", OmniboxEventProto::OTHER); // global fallback | |
| 259 | |
| 260 // Tests for rule 3. | |
| 261 ExpectRuleValue("rule3-*-*-value", | |
| 262 "rule3", | |
| 263 OmniboxEventProto::HOME_PAGE); // global fallback | |
| 264 ExpectRuleValue("rule3-*-*-value", | |
| 265 "rule3", | |
| 266 OmniboxEventProto::OTHER); // global fallback | |
| 267 | |
| 268 // Tests for rule 4. | |
| 269 ExpectRuleValue("", | |
| 270 "rule4", | |
| 271 OmniboxEventProto::BLANK); // no global fallback | |
| 272 ExpectRuleValue("", | |
| 273 "rule4", | |
| 274 OmniboxEventProto::HOME_PAGE); // no global fallback | |
| 275 | |
| 276 // Tests for rule 5 (a missing rule). | |
| 277 ExpectRuleValue("", | |
| 278 "rule5", OmniboxEventProto::OTHER); // no rule at all | |
| 279 } else { | |
| 280 // Tests for rule 1. | |
| 281 ExpectRuleValue("rule1-1-0-value", | |
| 282 "rule1", OmniboxEventProto::NTP); // exact match | |
| 283 ExpectRuleValue("rule1-1-0-value", | |
| 284 "rule1", OmniboxEventProto::NTP); // exact match | |
| 285 ExpectRuleValue("rule1-*-*-value", | |
| 286 "rule1", OmniboxEventProto::BLANK); // fallback to global | |
| 287 ExpectRuleValue("rule1-3-0-value", | |
| 288 "rule1", | |
| 289 OmniboxEventProto::HOME_PAGE); // exact match | |
| 290 ExpectRuleValue("rule1-4-*-value", | |
| 291 "rule1", OmniboxEventProto::OTHER); // partial fallback | |
| 292 ExpectRuleValue("rule1-*-*-value", | |
| 293 "rule1", | |
| 294 OmniboxEventProto:: // fallback to global | |
| 295 SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT); | |
| 296 // Tests for rule 2. | |
| 297 ExpectRuleValue("rule2-*-0-value", | |
| 298 "rule2", | |
| 299 OmniboxEventProto::HOME_PAGE); // partial fallback | |
| 300 ExpectRuleValue("rule2-*-0-value", | |
| 301 "rule2", OmniboxEventProto::OTHER); // partial fallback | |
| 302 | |
| 303 // Tests for rule 3. | |
| 304 ExpectRuleValue("rule3-*-*-value", | |
| 305 "rule3", | |
| 306 OmniboxEventProto::HOME_PAGE); // fallback to global | |
| 307 ExpectRuleValue("rule3-*-*-value", | |
| 308 "rule3", OmniboxEventProto::OTHER); // fallback to global | |
| 309 | |
| 310 // Tests for rule 4. | |
| 311 ExpectRuleValue("", | |
| 312 "rule4", OmniboxEventProto::BLANK); // no global fallback | |
| 313 ExpectRuleValue("", | |
| 314 "rule4", | |
| 315 OmniboxEventProto::HOME_PAGE); // no global fallback | |
| 316 ExpectRuleValue("rule4-4-0-value", | |
| 317 "rule4", OmniboxEventProto::OTHER); // exact match | |
| 318 | |
| 319 // Tests for rule 5 (a missing rule). | |
| 320 ExpectRuleValue("", | |
| 321 "rule5", OmniboxEventProto::OTHER); // no rule at all | |
| 322 } | |
| 323 } | |
| 324 | |
| 325 TEST_F(OmniboxFieldTrialTest, HUPNewScoringFieldTrial) { | |
| 326 { | |
| 327 std::map<std::string, std::string> params; | |
| 328 params[std::string(OmniboxFieldTrial::kHUPNewScoringEnabledParam)] = "1"; | |
| 329 params[std::string( | |
| 330 OmniboxFieldTrial::kHUPNewScoringTypedCountRelevanceCapParam)] = "56"; | |
| 331 params[std::string( | |
| 332 OmniboxFieldTrial::kHUPNewScoringTypedCountHalfLifeTimeParam)] = "77"; | |
| 333 params[std::string( | |
| 334 OmniboxFieldTrial::kHUPNewScoringTypedCountScoreBucketsParam)] = | |
| 335 "0.2:25,0.1:1001,2.3:777"; | |
| 336 params[std::string( | |
| 337 OmniboxFieldTrial::kHUPNewScoringVisitedCountRelevanceCapParam)] = "11"; | |
| 338 params[std::string( | |
| 339 OmniboxFieldTrial::kHUPNewScoringVisitedCountHalfLifeTimeParam)] = "31"; | |
| 340 params[std::string( | |
| 341 OmniboxFieldTrial::kHUPNewScoringVisitedCountScoreBucketsParam)] = | |
| 342 "5:300,0:200"; | |
| 343 ASSERT_TRUE(variations::AssociateVariationParams( | |
| 344 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params)); | |
| 345 } | |
| 346 base::FieldTrialList::CreateFieldTrial( | |
| 347 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); | |
| 348 | |
| 349 HUPScoringParams scoring_params; | |
| 350 OmniboxFieldTrial::GetExperimentalHUPScoringParams(&scoring_params); | |
| 351 EXPECT_TRUE(scoring_params.experimental_scoring_enabled); | |
| 352 EXPECT_EQ(56, scoring_params.typed_count_buckets.relevance_cap()); | |
| 353 EXPECT_EQ(77, scoring_params.typed_count_buckets.half_life_days()); | |
| 354 ASSERT_EQ(3u, scoring_params.typed_count_buckets.buckets().size()); | |
| 355 EXPECT_EQ(std::make_pair(2.3, 777), | |
| 356 scoring_params.typed_count_buckets.buckets()[0]); | |
| 357 EXPECT_EQ(std::make_pair(0.2, 25), | |
| 358 scoring_params.typed_count_buckets.buckets()[1]); | |
| 359 EXPECT_EQ(std::make_pair(0.1, 1001), | |
| 360 scoring_params.typed_count_buckets.buckets()[2]); | |
| 361 EXPECT_EQ(11, scoring_params.visited_count_buckets.relevance_cap()); | |
| 362 EXPECT_EQ(31, scoring_params.visited_count_buckets.half_life_days()); | |
| 363 ASSERT_EQ(2u, scoring_params.visited_count_buckets.buckets().size()); | |
| 364 EXPECT_EQ(std::make_pair(5.0, 300), | |
| 365 scoring_params.visited_count_buckets.buckets()[0]); | |
| 366 EXPECT_EQ(std::make_pair(0.0, 200), | |
| 367 scoring_params.visited_count_buckets.buckets()[1]); | |
| 368 } | |
| 369 | |
| 370 TEST_F(OmniboxFieldTrialTest, HalfLifeTimeDecay) { | |
| 371 HUPScoringParams::ScoreBuckets buckets; | |
| 372 | |
| 373 // No decay by default. | |
| 374 EXPECT_EQ(1.0, buckets.HalfLifeTimeDecay(base::TimeDelta::FromDays(7))); | |
| 375 | |
| 376 buckets.set_half_life_days(7); | |
| 377 EXPECT_EQ(0.5, buckets.HalfLifeTimeDecay(base::TimeDelta::FromDays(7))); | |
| 378 EXPECT_EQ(0.25, buckets.HalfLifeTimeDecay(base::TimeDelta::FromDays(14))); | |
| 379 EXPECT_EQ(1.0, buckets.HalfLifeTimeDecay(base::TimeDelta::FromDays(0))); | |
| 380 EXPECT_EQ(1.0, buckets.HalfLifeTimeDecay(base::TimeDelta::FromDays(-1))); | |
| 381 } | |
| OLD | NEW |