// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "extensions/common/feature_switch.h" #include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/field_trial.h" #include "testing/gtest/include/gtest/gtest.h" using extensions::FeatureSwitch; namespace { const char kSwitchName[] = "test-switch"; const char kFieldTrialName[] = "field-trial"; // Create and register a field trial named |field_trial_name| that will always // return the given |group_name|. scoped_refptr<base::FieldTrial> CreateFieldTrialWithName( const std::string& field_trial_name, const std::string& group_name) { const int kTotalProbability = 10; // Note: This code will probably fail in the year 5000. But all the cycles we // save in the next 3000 years by not determining the current year will be // worth it. scoped_refptr<base::FieldTrial> trial = base::FieldTrialList::FactoryGetFieldTrial( field_trial_name, kTotalProbability, "default", 5000, 1, 1, base::FieldTrial::SESSION_RANDOMIZED, nullptr); trial->AppendGroup(group_name, kTotalProbability); return trial; } // Create and register a field trial that will always return the given // |group_name|. scoped_refptr<base::FieldTrial> CreateFieldTrial( const std::string& group_name) { return CreateFieldTrialWithName(kFieldTrialName, group_name); } template<FeatureSwitch::DefaultValue T> class FeatureSwitchTest : public testing::Test { public: FeatureSwitchTest() : command_line_(base::CommandLine::NO_PROGRAM), feature_(&command_line_, kSwitchName, T) {} protected: base::CommandLine command_line_; FeatureSwitch feature_; }; typedef FeatureSwitchTest<FeatureSwitch::DEFAULT_DISABLED> FeatureSwitchDisabledTest; typedef FeatureSwitchTest<FeatureSwitch::DEFAULT_ENABLED> FeatureSwitchEnabledTest; } // namespace TEST_F(FeatureSwitchDisabledTest, NoSwitchValue) { EXPECT_FALSE(feature_.IsEnabled()); } TEST_F(FeatureSwitchDisabledTest, FalseSwitchValue) { command_line_.AppendSwitchASCII(kSwitchName, "0"); EXPECT_FALSE(feature_.IsEnabled()); } TEST_F(FeatureSwitchDisabledTest, GibberishSwitchValue) { command_line_.AppendSwitchASCII(kSwitchName, "monkey"); EXPECT_FALSE(feature_.IsEnabled()); } TEST_F(FeatureSwitchDisabledTest, Override) { { FeatureSwitch::ScopedOverride override(&feature_, false); EXPECT_FALSE(feature_.IsEnabled()); } EXPECT_FALSE(feature_.IsEnabled()); { FeatureSwitch::ScopedOverride override(&feature_, true); EXPECT_TRUE(feature_.IsEnabled()); } EXPECT_FALSE(feature_.IsEnabled()); } TEST_F(FeatureSwitchDisabledTest, TrueSwitchValue) { command_line_.AppendSwitchASCII(kSwitchName, "1"); EXPECT_TRUE(feature_.IsEnabled()); { FeatureSwitch::ScopedOverride override(&feature_, false); EXPECT_FALSE(feature_.IsEnabled()); } EXPECT_TRUE(feature_.IsEnabled()); { FeatureSwitch::ScopedOverride override(&feature_, true); EXPECT_TRUE(feature_.IsEnabled()); } EXPECT_TRUE(feature_.IsEnabled()); } TEST_F(FeatureSwitchDisabledTest, TrimSwitchValue) { command_line_.AppendSwitchASCII(kSwitchName, " \t 1\n "); EXPECT_TRUE(feature_.IsEnabled()); } TEST_F(FeatureSwitchEnabledTest, NoSwitchValue) { EXPECT_TRUE(feature_.IsEnabled()); } TEST_F(FeatureSwitchEnabledTest, TrueSwitchValue) { command_line_.AppendSwitchASCII(kSwitchName, "1"); EXPECT_TRUE(feature_.IsEnabled()); } TEST_F(FeatureSwitchEnabledTest, GibberishSwitchValue) { command_line_.AppendSwitchASCII(kSwitchName, "monkey"); EXPECT_TRUE(feature_.IsEnabled()); } TEST_F(FeatureSwitchEnabledTest, Override) { { FeatureSwitch::ScopedOverride override(&feature_, true); EXPECT_TRUE(feature_.IsEnabled()); } EXPECT_TRUE(feature_.IsEnabled()); { FeatureSwitch::ScopedOverride override(&feature_, false); EXPECT_FALSE(feature_.IsEnabled()); } EXPECT_TRUE(feature_.IsEnabled()); } TEST_F(FeatureSwitchEnabledTest, FalseSwitchValue) { command_line_.AppendSwitchASCII(kSwitchName, "0"); EXPECT_FALSE(feature_.IsEnabled()); { FeatureSwitch::ScopedOverride override(&feature_, true); EXPECT_TRUE(feature_.IsEnabled()); } EXPECT_FALSE(feature_.IsEnabled()); { FeatureSwitch::ScopedOverride override(&feature_, false); EXPECT_FALSE(feature_.IsEnabled()); } EXPECT_FALSE(feature_.IsEnabled()); } TEST_F(FeatureSwitchEnabledTest, TrimSwitchValue) { command_line_.AppendSwitchASCII(kSwitchName, "\t\t 0 \n"); EXPECT_FALSE(feature_.IsEnabled()); } TEST_F(FeatureSwitchEnabledTest, TrueFieldTrialValue) { // Construct a fake field trial that defaults to the group "Enabled". base::FieldTrialList field_trials(nullptr); scoped_refptr<base::FieldTrial> enabled_trial = CreateFieldTrial("Enabled"); { // A default-enabled switch should be enabled (naturally). FeatureSwitch default_enabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_ENABLED); EXPECT_TRUE(default_enabled_switch.IsEnabled()); // Scoped overrides override everything. FeatureSwitch::ScopedOverride scoped_override(&default_enabled_switch, false); EXPECT_FALSE(default_enabled_switch.IsEnabled()); } { // A default-disabled switch should be enabled because of the field trial. FeatureSwitch default_disabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_DISABLED); EXPECT_TRUE(default_disabled_switch.IsEnabled()); // Scoped overrides override everything. FeatureSwitch::ScopedOverride scoped_override(&default_disabled_switch, false); EXPECT_FALSE(default_disabled_switch.IsEnabled()); } } TEST_F(FeatureSwitchEnabledTest, TrueFieldTrialDogfoodValue) { // Construct a fake field trial that defaults to the group "Enabled_Dogfood". base::FieldTrialList field_trials(nullptr); scoped_refptr<base::FieldTrial> enabled_trial = CreateFieldTrial("Enabled_Dogfood"); { // A default-enabled switch should be enabled (naturally). FeatureSwitch default_enabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_ENABLED); EXPECT_TRUE(default_enabled_switch.IsEnabled()); // Scoped overrides override everything. FeatureSwitch::ScopedOverride scoped_override(&default_enabled_switch, false); EXPECT_FALSE(default_enabled_switch.IsEnabled()); } { // A default-disabled switch should be enabled because of the field trial. FeatureSwitch default_disabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_DISABLED); EXPECT_TRUE(default_disabled_switch.IsEnabled()); // Scoped overrides override everything. FeatureSwitch::ScopedOverride scoped_override(&default_disabled_switch, false); EXPECT_FALSE(default_disabled_switch.IsEnabled()); } } TEST_F(FeatureSwitchEnabledTest, FalseFieldTrialValue) { // Construct a fake field trial that defaults to the group "Disabled". base::FieldTrialList field_trials(nullptr); scoped_refptr<base::FieldTrial> disabled_trial = CreateFieldTrial("Disabled"); { // A default-enabled switch should be disabled because of the field trial. FeatureSwitch default_enabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_ENABLED); EXPECT_FALSE(default_enabled_switch.IsEnabled()); // Scoped overrides override everything. FeatureSwitch::ScopedOverride scoped_override(&default_enabled_switch, true); EXPECT_TRUE(default_enabled_switch.IsEnabled()); } { // A default-disabled switch should remain disabled. FeatureSwitch default_disabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_DISABLED); EXPECT_FALSE(default_disabled_switch.IsEnabled()); // Scoped overrides override everything. FeatureSwitch::ScopedOverride scoped_override(&default_disabled_switch, true); EXPECT_TRUE(default_disabled_switch.IsEnabled()); } } TEST_F(FeatureSwitchEnabledTest, FalseFieldTrialDogfoodValue) { // Construct a fake field trial that defaults to the group "Disabled_Dogfood". base::FieldTrialList field_trials(nullptr); scoped_refptr<base::FieldTrial> disabled_trial = CreateFieldTrial("Disabled_Dogfood"); { // A default-enabled switch should be disabled because of the field trial. FeatureSwitch default_enabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_ENABLED); EXPECT_FALSE(default_enabled_switch.IsEnabled()); } { // A default-disabled switch should remain disabled. FeatureSwitch default_disabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_DISABLED); EXPECT_FALSE(default_disabled_switch.IsEnabled()); } } TEST_F(FeatureSwitchEnabledTest, InvalidGroupFieldTrial) { // Construct a fake field trial that defaults to the group "InvalidGroup". base::FieldTrialList field_trials(nullptr); scoped_refptr<base::FieldTrial> disabled_trial = CreateFieldTrial("InvalidGroup"); { // A default-enabled switch should be enabled (the group has no effect). FeatureSwitch default_enabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_ENABLED); EXPECT_TRUE(default_enabled_switch.IsEnabled()); } { // A default-disabled switch should remain disabled. FeatureSwitch default_disabled_switch( &command_line_, kSwitchName, std::vector<std::string>(1, kFieldTrialName), FeatureSwitch::DEFAULT_DISABLED); EXPECT_FALSE(default_disabled_switch.IsEnabled()); } } TEST_F(FeatureSwitchEnabledTest, TrueFieldTrialValueAndTrueRequiredFieldTrialValue) { std::vector<std::string> required_trials; base::FieldTrialList field_trials(nullptr); scoped_refptr<base::FieldTrial> enabled_trial = CreateFieldTrial("Enabled"); required_trials.push_back(kFieldTrialName); const char* required_trial_name = "required-trial"; scoped_refptr<base::FieldTrial> enabled_required_trial = CreateFieldTrialWithName(required_trial_name, "Enabled"); required_trials.push_back(required_trial_name); FeatureSwitch trial_enabled_switch(&command_line_, kSwitchName, required_trials, FeatureSwitch::DEFAULT_DISABLED); EXPECT_TRUE(trial_enabled_switch.IsEnabled()); } TEST_F(FeatureSwitchEnabledTest, TrueFieldTrialValueAndFalseRequiredFieldTrialValue) { std::vector<std::string> required_trials; base::FieldTrialList field_trials(nullptr); scoped_refptr<base::FieldTrial> enabled_trial = CreateFieldTrial("Enabled"); required_trials.push_back(kFieldTrialName); const char* required_trial_name = "required-trial"; scoped_refptr<base::FieldTrial> enabled_required_trial = CreateFieldTrialWithName(required_trial_name, "Disabled"); required_trials.push_back(required_trial_name); FeatureSwitch trial_enabled_switch(&command_line_, kSwitchName, required_trials, FeatureSwitch::DEFAULT_DISABLED); EXPECT_FALSE(trial_enabled_switch.IsEnabled()); }