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/browser/autocomplete/autocomplete_input.h" 13#include "chrome/browser/search/search.h" 14#include "chrome/common/chrome_switches.h" 15#include "chrome/common/metrics/entropy_provider.h" 16#include "chrome/common/metrics/variations/variations_util.h" 17#include "testing/gtest/include/gtest/gtest.h" 18 19class OmniboxFieldTrialTest : public testing::Test { 20 public: 21 OmniboxFieldTrialTest() { 22 ResetFieldTrialList(); 23 } 24 25 void ResetFieldTrialList() { 26 // Destroy the existing FieldTrialList before creating a new one to avoid 27 // a DCHECK. 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(); 33 } 34 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( 39 name, group_name); 40 trial->group(); 41 return trial; 42 } 43 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); 49 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); 56 57 private: 58 scoped_ptr<base::FieldTrialList> field_trial_list_; 59 60 DISALLOW_COPY_AND_ASSIGN(OmniboxFieldTrialTest); 61}; 62 63// static 64void 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); 72} 73 74// static 75void OmniboxFieldTrialTest::ExpectRuleValue( 76 const std::string& rule_value, 77 const std::string& rule, 78 AutocompleteInput::PageClassification page_classification) { 79 EXPECT_EQ(rule_value, 80 OmniboxFieldTrial::GetValueForRuleInContext( 81 rule, page_classification)); 82} 83 84// Test if GetDisabledProviderTypes() properly parses various field trial 85// group names. 86TEST_F(OmniboxFieldTrialTest, GetDisabledProviderTypes) { 87 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes()); 88 89 { 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()); 99 } 100 101 { 102 SCOPED_TRACE("Valid group name, unsupported trial name."); 103 ResetFieldTrialList(); 104 CreateTestTrial("UnsupportedTrialName", "DisabledProviders_20"); 105 EXPECT_EQ(0, OmniboxFieldTrial::GetDisabledProviderTypes()); 106 } 107 108 { 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()); 116 } 117} 118 119// Test if InZeroSuggestFieldTrial() properly parses various field trial 120// group names. 121TEST_F(OmniboxFieldTrialTest, ZeroSuggestFieldTrial) { 122 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); 123 124 { 125 SCOPED_TRACE("Valid group name, unsupported trial name."); 126 ResetFieldTrialList(); 127 CreateTestTrial("UnsupportedTrialName", "EnableZeroSuggest"); 128 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); 129 130 ResetFieldTrialList(); 131 CreateTestTrial("UnsupportedTrialName", "EnableZeroSuggest_Queries"); 132 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); 133 134 ResetFieldTrialList(); 135 CreateTestTrial("UnsupportedTrialName", "EnableZeroSuggest_URLS"); 136 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); 137 } 138 139 { 140 SCOPED_TRACE("Valid trial name, unsupported group name."); 141 ResetFieldTrialList(); 142 CreateTestTrial("AutocompleteDynamicTrial_2", "UnrelatedGroup"); 143 EXPECT_FALSE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); 144 } 145 146 { 147 SCOPED_TRACE("Valid field and group name."); 148 ResetFieldTrialList(); 149 CreateTestTrial("AutocompleteDynamicTrial_2", "EnableZeroSuggest"); 150 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); 151 152 ResetFieldTrialList(); 153 CreateTestTrial("AutocompleteDynamicTrial_2", "EnableZeroSuggest_Queries"); 154 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); 155 156 ResetFieldTrialList(); 157 CreateTestTrial("AutocompleteDynamicTrial_3", "EnableZeroSuggest_URLs"); 158 EXPECT_TRUE(OmniboxFieldTrial::InZeroSuggestFieldTrial()); 159 } 160} 161 162TEST_F(OmniboxFieldTrialTest, GetDemotionsByTypeWithFallback) { 163 { 164 std::map<std::string, std::string> params; 165 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":1:*"] = 166 "1:50,2:0"; 167 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":3:*"] = 168 "5:100"; 169 params[std::string(OmniboxFieldTrial::kDemoteByTypeRule) + ":*:*"] = "1:25"; 170 ASSERT_TRUE(chrome_variations::AssociateVariationParams( 171 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params)); 172 } 173 base::FieldTrialList::CreateFieldTrial( 174 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); 175 OmniboxFieldTrial::DemotionMultipliers demotions_by_type; 176 OmniboxFieldTrial::GetDemotionsByType( 177 AutocompleteInput::NEW_TAB_PAGE, &demotions_by_type); 178 ASSERT_EQ(2u, demotions_by_type.size()); 179 VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_URL, 0.5); 180 VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_TITLE, 0.0); 181 OmniboxFieldTrial::GetDemotionsByType( 182 AutocompleteInput::HOMEPAGE, &demotions_by_type); 183 ASSERT_EQ(1u, demotions_by_type.size()); 184 VerifyDemotion(demotions_by_type, AutocompleteMatchType::NAVSUGGEST, 1.0); 185 OmniboxFieldTrial::GetDemotionsByType( 186 AutocompleteInput::BLANK, &demotions_by_type); 187 ASSERT_EQ(1u, demotions_by_type.size()); 188 VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_URL, 0.25); 189} 190 191TEST_F(OmniboxFieldTrialTest, GetValueForRuleInContext) { 192 // This test starts with Instant Extended off (the default state), then 193 // enables Instant Extended and tests again on the same rules. 194 195 { 196 std::map<std::string, std::string> params; 197 // Rule 1 has some exact matches and fallbacks at every level. 198 params["rule1:1:0"] = "rule1-1-0-value"; // NEW_TAB_PAGE 199 params["rule1:3:0"] = "rule1-3-0-value"; // HOMEPAGE 200 params["rule1:4:1"] = "rule1-4-1-value"; // OTHER 201 params["rule1:4:*"] = "rule1-4-*-value"; // OTHER 202 params["rule1:*:1"] = "rule1-*-1-value"; // global 203 params["rule1:*:*"] = "rule1-*-*-value"; // global 204 // Rule 2 has no exact matches but has fallbacks. 205 params["rule2:*:0"] = "rule2-*-0-value"; // global 206 params["rule2:1:*"] = "rule2-1-*-value"; // NEW_TAB_PAGE 207 params["rule2:*:*"] = "rule2-*-*-value"; // global 208 // Rule 3 has only a global fallback. 209 params["rule3:*:*"] = "rule3-*-*-value"; // global 210 // Rule 4 has an exact match but no fallbacks. 211 params["rule4:4:0"] = "rule4-4-0-value"; // OTHER 212 // Add a malformed rule to make sure it doesn't screw things up. 213 params["unrecognized"] = "unrecognized-value"; 214 ASSERT_TRUE(chrome_variations::AssociateVariationParams( 215 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A", params)); 216 } 217 218 base::FieldTrialList::CreateFieldTrial( 219 OmniboxFieldTrial::kBundledExperimentFieldTrialName, "A"); 220 221 // Tests with Instant Extended disabled. 222 // Tests for rule 1. 223 ExpectRuleValue("rule1-1-0-value", 224 "rule1", AutocompleteInput::NEW_TAB_PAGE); // exact match 225 ExpectRuleValue("rule1-1-0-value", 226 "rule1", AutocompleteInput::NEW_TAB_PAGE); // exact match 227 ExpectRuleValue("rule1-*-*-value", 228 "rule1", AutocompleteInput::BLANK); // fallback to global 229 ExpectRuleValue("rule1-3-0-value", 230 "rule1", AutocompleteInput::HOMEPAGE); // exact match 231 ExpectRuleValue("rule1-4-*-value", 232 "rule1", AutocompleteInput::OTHER); // partial fallback 233 ExpectRuleValue("rule1-*-*-value", 234 "rule1", 235 AutocompleteInput:: // fallback to global 236 SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT); 237 // Tests for rule 2. 238 ExpectRuleValue("rule2-*-0-value", 239 "rule2", AutocompleteInput::HOMEPAGE); // partial fallback 240 ExpectRuleValue("rule2-*-0-value", 241 "rule2", AutocompleteInput::OTHER); // partial fallback 242 243 // Tests for rule 3. 244 ExpectRuleValue("rule3-*-*-value", 245 "rule3", AutocompleteInput::HOMEPAGE); // fallback to global 246 ExpectRuleValue("rule3-*-*-value", 247 "rule3", AutocompleteInput::OTHER); // fallback to global 248 249 // Tests for rule 4. 250 ExpectRuleValue("", 251 "rule4", AutocompleteInput::BLANK); // no global fallback 252 ExpectRuleValue("", 253 "rule4", AutocompleteInput::HOMEPAGE); // no global fallback 254 ExpectRuleValue("rule4-4-0-value", 255 "rule4", AutocompleteInput::OTHER); // exact match 256 257 // Tests for rule 5 (a missing rule). 258 ExpectRuleValue("", 259 "rule5", AutocompleteInput::OTHER); // no rule at all 260 261 // Now change the Instant Extended state and run analogous tests. 262 // Instant Extended only works on non-mobile platforms. 263#if !defined(OS_IOS) && !defined(OS_ANDROID) 264 chrome::ResetInstantExtendedOptInStateGateForTest(); 265 CommandLine::ForCurrentProcess()->AppendSwitch( 266 switches::kEnableInstantExtendedAPI); 267 268 // Tests with Instant Extended enabled. 269 // Tests for rule 1. 270 ExpectRuleValue("rule1-4-1-value", 271 "rule1", AutocompleteInput::OTHER); // exact match 272 ExpectRuleValue("rule1-*-1-value", 273 "rule1", AutocompleteInput::BLANK); // partial fallback 274 ExpectRuleValue("rule1-*-1-value", 275 "rule1", 276 AutocompleteInput::NEW_TAB_PAGE); // partial fallback 277 278 // Tests for rule 2. 279 ExpectRuleValue("rule2-1-*-value", 280 "rule2", 281 AutocompleteInput::NEW_TAB_PAGE); // partial fallback 282 ExpectRuleValue("rule2-*-*-value", 283 "rule2", AutocompleteInput::OTHER); // global fallback 284 285 // Tests for rule 3. 286 ExpectRuleValue("rule3-*-*-value", 287 "rule3", AutocompleteInput::HOMEPAGE); // global fallback 288 ExpectRuleValue("rule3-*-*-value", 289 "rule3", AutocompleteInput::OTHER); // global fallback 290 291 // Tests for rule 4. 292 ExpectRuleValue("", 293 "rule4", AutocompleteInput::BLANK); // no global fallback 294 ExpectRuleValue("", 295 "rule4", AutocompleteInput::HOMEPAGE); // no global fallback 296 297 // Tests for rule 5 (a missing rule). 298 ExpectRuleValue("", 299 "rule5", AutocompleteInput::OTHER); // no rule at all 300#endif // !defined(OS_IOS) && !defined(OS_ANDROID) 301} 302