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
ExpectFeatures(const std::string & enabled_features,const std::string & disabled_features)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:
ScopedFeatureListTest()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
~ScopedFeatureListTest()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
TEST_F(ScopedFeatureListTest,BasicScoped)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
TEST_F(ScopedFeatureListTest,EnableWithFeatureParameters)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
TEST_F(ScopedFeatureListTest,OverrideWithFeatureParameters)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
TEST_F(ScopedFeatureListTest,EnableFeatureOverrideDisable)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
TEST_F(ScopedFeatureListTest,FeatureOverrideNotMakeDuplicate)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
TEST_F(ScopedFeatureListTest,FeatureOverrideFeatureWithDefault)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
TEST_F(ScopedFeatureListTest,FeatureOverrideFeatureWithDefault2)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
TEST_F(ScopedFeatureListTest,FeatureOverrideFeatureWithEnabledFieldTrial)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
TEST_F(ScopedFeatureListTest,FeatureOverrideFeatureWithDisabledFieldTrial)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
TEST_F(ScopedFeatureListTest,FeatureOverrideKeepsOtherExistingFeature)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
TEST_F(ScopedFeatureListTest,FeatureOverrideKeepsOtherExistingFeature2)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
TEST_F(ScopedFeatureListTest,FeatureOverrideKeepsOtherExistingDefaultFeature)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
TEST_F(ScopedFeatureListTest,ScopedFeatureListIsNoopWhenNotInitialized)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