Home | History | Annotate | Download | only in omnibox
      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 
     19 class 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
     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);
     72 }
     73 
     74 // static
     75 void 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.
     86 TEST_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.
    121 TEST_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 
    162 TEST_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 
    191 TEST_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