1 // Copyright 2017 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 "base/test/scoped_feature_list.h" 6 7 #include <map> 8 #include <string> 9 #include <utility> 10 11 #include "base/metrics/field_trial.h" 12 #include "base/metrics/field_trial_params.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 namespace base { 16 namespace test { 17 18 namespace { 19 20 const Feature kTestFeature1{"TestFeature1", FEATURE_DISABLED_BY_DEFAULT}; 21 const Feature kTestFeature2{"TestFeature2", FEATURE_DISABLED_BY_DEFAULT}; 22 23 void ExpectFeatures(const std::string& enabled_features, 24 const std::string& disabled_features) { 25 FeatureList* list = FeatureList::GetInstance(); 26 std::string actual_enabled_features; 27 std::string actual_disabled_features; 28 29 list->GetFeatureOverrides(&actual_enabled_features, 30 &actual_disabled_features); 31 32 EXPECT_EQ(enabled_features, actual_enabled_features); 33 EXPECT_EQ(disabled_features, actual_disabled_features); 34 } 35 36 } // namespace 37 38 class ScopedFeatureListTest : public testing::Test { 39 public: 40 ScopedFeatureListTest() { 41 // Clear default feature list. 42 std::unique_ptr<FeatureList> feature_list(new FeatureList); 43 feature_list->InitializeFromCommandLine(std::string(), std::string()); 44 original_feature_list_ = FeatureList::ClearInstanceForTesting(); 45 FeatureList::SetInstance(std::move(feature_list)); 46 } 47 48 ~ScopedFeatureListTest() override { 49 // Restore feature list. 50 if (original_feature_list_) { 51 FeatureList::ClearInstanceForTesting(); 52 FeatureList::RestoreInstanceForTesting(std::move(original_feature_list_)); 53 } 54 } 55 56 private: 57 // Save the present FeatureList and restore it after test finish. 58 std::unique_ptr<FeatureList> original_feature_list_; 59 60 DISALLOW_COPY_AND_ASSIGN(ScopedFeatureListTest); 61 }; 62 63 TEST_F(ScopedFeatureListTest, BasicScoped) { 64 ExpectFeatures(std::string(), std::string()); 65 EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1)); 66 { 67 test::ScopedFeatureList feature_list1; 68 feature_list1.InitFromCommandLine("TestFeature1", std::string()); 69 ExpectFeatures("TestFeature1", std::string()); 70 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1)); 71 } 72 ExpectFeatures(std::string(), std::string()); 73 EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1)); 74 } 75 76 TEST_F(ScopedFeatureListTest, EnableWithFeatureParameters) { 77 const char kParam1[] = "param_1"; 78 const char kParam2[] = "param_2"; 79 const char kValue1[] = "value_1"; 80 const char kValue2[] = "value_2"; 81 std::map<std::string, std::string> parameters; 82 parameters[kParam1] = kValue1; 83 parameters[kParam2] = kValue2; 84 85 ExpectFeatures(std::string(), std::string()); 86 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature1)); 87 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1)); 88 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2)); 89 FieldTrial::ActiveGroups active_groups; 90 FieldTrialList::GetActiveFieldTrialGroups(&active_groups); 91 EXPECT_EQ(0u, active_groups.size()); 92 93 { 94 test::ScopedFeatureList feature_list; 95 96 feature_list.InitAndEnableFeatureWithParameters(kTestFeature1, parameters); 97 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1)); 98 EXPECT_EQ(kValue1, 99 GetFieldTrialParamValueByFeature(kTestFeature1, kParam1)); 100 EXPECT_EQ(kValue2, 101 GetFieldTrialParamValueByFeature(kTestFeature1, kParam2)); 102 active_groups.clear(); 103 FieldTrialList::GetActiveFieldTrialGroups(&active_groups); 104 EXPECT_EQ(1u, active_groups.size()); 105 } 106 107 ExpectFeatures(std::string(), std::string()); 108 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature1)); 109 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1)); 110 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2)); 111 active_groups.clear(); 112 FieldTrialList::GetActiveFieldTrialGroups(&active_groups); 113 EXPECT_EQ(0u, active_groups.size()); 114 } 115 116 TEST_F(ScopedFeatureListTest, OverrideWithFeatureParameters) { 117 FieldTrialList field_trial_list(nullptr); 118 scoped_refptr<FieldTrial> trial = 119 FieldTrialList::CreateFieldTrial("foo", "bar"); 120 const char kParam[] = "param_1"; 121 const char kValue[] = "value_1"; 122 std::map<std::string, std::string> parameters; 123 parameters[kParam] = kValue; 124 125 test::ScopedFeatureList feature_list1; 126 feature_list1.InitFromCommandLine("TestFeature1<foo,TestFeature2", 127 std::string()); 128 129 // Check initial state. 130 ExpectFeatures("TestFeature1<foo,TestFeature2", std::string()); 131 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1)); 132 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2)); 133 EXPECT_EQ(trial.get(), FeatureList::GetFieldTrial(kTestFeature1)); 134 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2)); 135 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam)); 136 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam)); 137 138 { 139 // Override feature with existing field trial. 140 test::ScopedFeatureList feature_list2; 141 142 feature_list2.InitAndEnableFeatureWithParameters(kTestFeature1, parameters); 143 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1)); 144 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2)); 145 EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam)); 146 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam)); 147 EXPECT_NE(trial.get(), FeatureList::GetFieldTrial(kTestFeature1)); 148 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1)); 149 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2)); 150 } 151 152 // Check that initial state is restored. 153 ExpectFeatures("TestFeature1<foo,TestFeature2", std::string()); 154 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1)); 155 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2)); 156 EXPECT_EQ(trial.get(), FeatureList::GetFieldTrial(kTestFeature1)); 157 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2)); 158 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam)); 159 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam)); 160 161 { 162 // Override feature with no existing field trial. 163 test::ScopedFeatureList feature_list2; 164 165 feature_list2.InitAndEnableFeatureWithParameters(kTestFeature2, parameters); 166 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1)); 167 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2)); 168 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam)); 169 EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature2, kParam)); 170 EXPECT_EQ(trial.get(), FeatureList::GetFieldTrial(kTestFeature1)); 171 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2)); 172 } 173 174 // Check that initial state is restored. 175 ExpectFeatures("TestFeature1<foo,TestFeature2", std::string()); 176 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1)); 177 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2)); 178 EXPECT_EQ(trial.get(), FeatureList::GetFieldTrial(kTestFeature1)); 179 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2)); 180 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam)); 181 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam)); 182 } 183 184 TEST_F(ScopedFeatureListTest, EnableFeatureOverrideDisable) { 185 test::ScopedFeatureList feature_list1; 186 feature_list1.InitWithFeatures({}, {kTestFeature1}); 187 188 { 189 test::ScopedFeatureList feature_list2; 190 feature_list2.InitWithFeatures({kTestFeature1}, {}); 191 ExpectFeatures("TestFeature1", std::string()); 192 } 193 } 194 195 TEST_F(ScopedFeatureListTest, FeatureOverrideNotMakeDuplicate) { 196 test::ScopedFeatureList feature_list1; 197 feature_list1.InitWithFeatures({}, {kTestFeature1}); 198 199 { 200 test::ScopedFeatureList feature_list2; 201 feature_list2.InitWithFeatures({}, {kTestFeature1}); 202 ExpectFeatures(std::string(), "TestFeature1"); 203 } 204 } 205 206 TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault) { 207 test::ScopedFeatureList feature_list1; 208 feature_list1.InitFromCommandLine("*TestFeature1", std::string()); 209 210 { 211 test::ScopedFeatureList feature_list2; 212 feature_list2.InitWithFeatures({kTestFeature1}, {}); 213 ExpectFeatures("TestFeature1", std::string()); 214 } 215 } 216 217 TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault2) { 218 test::ScopedFeatureList feature_list1; 219 feature_list1.InitFromCommandLine("*TestFeature1", std::string()); 220 221 { 222 test::ScopedFeatureList feature_list2; 223 feature_list2.InitWithFeatures({}, {kTestFeature1}); 224 ExpectFeatures(std::string(), "TestFeature1"); 225 } 226 } 227 228 TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithEnabledFieldTrial) { 229 test::ScopedFeatureList feature_list1; 230 231 std::unique_ptr<FeatureList> feature_list(new FeatureList); 232 FieldTrialList field_trial_list(nullptr); 233 FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A"); 234 feature_list->RegisterFieldTrialOverride( 235 kTestFeature1.name, FeatureList::OVERRIDE_ENABLE_FEATURE, trial); 236 feature_list1.InitWithFeatureList(std::move(feature_list)); 237 238 { 239 test::ScopedFeatureList feature_list2; 240 feature_list2.InitWithFeatures({kTestFeature1}, {}); 241 ExpectFeatures("TestFeature1", std::string()); 242 } 243 } 244 245 TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDisabledFieldTrial) { 246 test::ScopedFeatureList feature_list1; 247 248 std::unique_ptr<FeatureList> feature_list(new FeatureList); 249 FieldTrialList field_trial_list(nullptr); 250 FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A"); 251 feature_list->RegisterFieldTrialOverride( 252 kTestFeature1.name, FeatureList::OVERRIDE_DISABLE_FEATURE, trial); 253 feature_list1.InitWithFeatureList(std::move(feature_list)); 254 255 { 256 test::ScopedFeatureList feature_list2; 257 feature_list2.InitWithFeatures({kTestFeature1}, {}); 258 ExpectFeatures("TestFeature1", std::string()); 259 } 260 } 261 262 TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature) { 263 test::ScopedFeatureList feature_list1; 264 feature_list1.InitWithFeatures({}, {kTestFeature1}); 265 266 { 267 test::ScopedFeatureList feature_list2; 268 feature_list2.InitWithFeatures({}, {kTestFeature2}); 269 EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1)); 270 EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature2)); 271 } 272 } 273 274 TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature2) { 275 test::ScopedFeatureList feature_list1; 276 feature_list1.InitWithFeatures({}, {kTestFeature1}); 277 278 { 279 test::ScopedFeatureList feature_list2; 280 feature_list2.InitWithFeatures({kTestFeature2}, {}); 281 ExpectFeatures("TestFeature2", "TestFeature1"); 282 } 283 } 284 285 TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingDefaultFeature) { 286 test::ScopedFeatureList feature_list1; 287 feature_list1.InitFromCommandLine("*TestFeature1", std::string()); 288 289 { 290 test::ScopedFeatureList feature_list2; 291 feature_list2.InitWithFeatures({}, {kTestFeature2}); 292 ExpectFeatures("*TestFeature1", "TestFeature2"); 293 } 294 } 295 296 TEST_F(ScopedFeatureListTest, ScopedFeatureListIsNoopWhenNotInitialized) { 297 test::ScopedFeatureList feature_list1; 298 feature_list1.InitFromCommandLine("*TestFeature1", std::string()); 299 300 // A ScopedFeatureList on which Init() is not called should not reset things 301 // when going out of scope. 302 { test::ScopedFeatureList feature_list2; } 303 304 ExpectFeatures("*TestFeature1", std::string()); 305 } 306 307 } // namespace test 308 } // namespace base 309