1 // Copyright 2017 The Chromium Authors
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/features.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/metrics/field_trial_params.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace base::test {
17
18 namespace {
19
20 BASE_FEATURE(kTestFeature1, "TestFeature1", FEATURE_DISABLED_BY_DEFAULT);
21 BASE_FEATURE(kTestFeature2, "TestFeature2", FEATURE_DISABLED_BY_DEFAULT);
22
23 BASE_FEATURE_PARAM(bool,
24 kTestFeatureParam1,
25 &kTestFeature1,
26 "TestFeatureParam1",
27 false);
28
ExpectFeatures(const std::string & enabled_features,const std::string & disabled_features)29 void ExpectFeatures(const std::string& enabled_features,
30 const std::string& disabled_features) {
31 FeatureList* list = FeatureList::GetInstance();
32 std::string actual_enabled_features;
33 std::string actual_disabled_features;
34
35 list->GetFeatureOverrides(&actual_enabled_features,
36 &actual_disabled_features);
37
38 EXPECT_EQ(enabled_features, actual_enabled_features);
39 EXPECT_EQ(disabled_features, actual_disabled_features);
40 }
41
GetActiveFieldTrialGroupName(const std::string & trial_name)42 std::string GetActiveFieldTrialGroupName(const std::string& trial_name) {
43 FieldTrial::ActiveGroups groups;
44 FieldTrialList::GetActiveFieldTrialGroups(&groups);
45 for (const auto& group : groups) {
46 if (group.trial_name == trial_name) {
47 return group.group_name;
48 }
49 }
50 return std::string();
51 }
52
53 } // namespace
54
55 class ScopedFeatureListTest : public testing::Test {
56 public:
ScopedFeatureListTest()57 ScopedFeatureListTest() {
58 // Clear default feature list.
59 std::unique_ptr<FeatureList> feature_list(new FeatureList);
60 feature_list->InitFromCommandLine(std::string(), std::string());
61 original_feature_list_ = FeatureList::ClearInstanceForTesting();
62 FeatureList::SetInstance(std::move(feature_list));
63 }
64
65 ScopedFeatureListTest(const ScopedFeatureListTest&) = delete;
66 ScopedFeatureListTest& operator=(const ScopedFeatureListTest&) = delete;
67
~ScopedFeatureListTest()68 ~ScopedFeatureListTest() override {
69 // Restore feature list.
70 if (original_feature_list_) {
71 FeatureList::ClearInstanceForTesting();
72 FeatureList::RestoreInstanceForTesting(std::move(original_feature_list_));
73 }
74 }
75
76 private:
77 // Save the present FeatureList and restore it after test finish.
78 std::unique_ptr<FeatureList> original_feature_list_;
79 };
80
TEST_F(ScopedFeatureListTest,BasicScoped)81 TEST_F(ScopedFeatureListTest, BasicScoped) {
82 ExpectFeatures(std::string(), std::string());
83 EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1));
84 {
85 test::ScopedFeatureList feature_list1;
86 feature_list1.InitFromCommandLine("TestFeature1", std::string());
87 ExpectFeatures("TestFeature1", std::string());
88 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
89 }
90 ExpectFeatures(std::string(), std::string());
91 EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1));
92 }
93
TEST_F(ScopedFeatureListTest,InitFromCommandLineWithFeatureParams)94 TEST_F(ScopedFeatureListTest, InitFromCommandLineWithFeatureParams) {
95 const std::map<std::string, std::string> feature_params1 = {{"x", "uma"},
96 {"y", "ukm"}};
97 const std::map<std::string, std::string> feature_params2 = {{"x", "ukm"},
98 {"y", "uma"}};
99
100 test::ScopedFeatureList feature_list1;
101 feature_list1.InitFromCommandLine("TestFeature1<foo.bar:x/uma/y/ukm", "");
102
103 // Check initial state. Field trial and parameters should be set correctly.
104 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
105 FieldTrial::ActiveGroups active_groups;
106 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
107 EXPECT_EQ(1u, active_groups.size());
108 FieldTrial* original_field_trial =
109 FieldTrialList::Find(active_groups[0].trial_name);
110 std::map<std::string, std::string> actualParams;
111 EXPECT_TRUE(GetFieldTrialParamsByFeature(kTestFeature1, &actualParams));
112 EXPECT_EQ(feature_params1, actualParams);
113
114 {
115 // Override feature with existing field trial.
116 test::ScopedFeatureList feature_list2;
117
118 feature_list2.InitAndEnableFeatureWithParameters(kTestFeature1,
119 feature_params2);
120 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
121 EXPECT_NE(original_field_trial, FeatureList::GetFieldTrial(kTestFeature1));
122 actualParams.clear();
123 EXPECT_TRUE(GetFieldTrialParamsByFeature(kTestFeature1, &actualParams));
124 EXPECT_EQ(feature_params2, actualParams);
125 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
126 }
127
128 // Check that initial state is restored.
129 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
130 active_groups.clear();
131 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
132 EXPECT_EQ(1u, active_groups.size());
133 EXPECT_EQ(original_field_trial, FeatureList::GetFieldTrial(kTestFeature1));
134 actualParams.clear();
135 EXPECT_TRUE(GetFieldTrialParamsByFeature(kTestFeature1, &actualParams));
136 EXPECT_EQ(feature_params1, actualParams);
137 }
138
TEST_F(ScopedFeatureListTest,EnableWithFeatureParameters)139 TEST_F(ScopedFeatureListTest, EnableWithFeatureParameters) {
140 const char kParam1[] = "param_1";
141 const char kParam2[] = "param_2";
142 const char kValue1[] = "value_1";
143 const char kValue2[] = "value_2";
144 std::map<std::string, std::string> parameters;
145 parameters[kParam1] = kValue1;
146 parameters[kParam2] = kValue2;
147
148 ExpectFeatures(std::string(), std::string());
149 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
150 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
151 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
152 FieldTrial::ActiveGroups active_groups;
153 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
154 EXPECT_EQ(0u, active_groups.size());
155
156 {
157 test::ScopedFeatureList feature_list;
158
159 feature_list.InitAndEnableFeatureWithParameters(kTestFeature1, parameters);
160 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
161 EXPECT_EQ(kValue1,
162 GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
163 EXPECT_EQ(kValue2,
164 GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
165 active_groups.clear();
166 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
167 EXPECT_EQ(1u, active_groups.size());
168 }
169
170 ExpectFeatures(std::string(), std::string());
171 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
172 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
173 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
174 active_groups.clear();
175 FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
176 EXPECT_EQ(0u, active_groups.size());
177 }
178
TEST_F(ScopedFeatureListTest,OverrideWithFeatureParameters)179 TEST_F(ScopedFeatureListTest, OverrideWithFeatureParameters) {
180 scoped_refptr<FieldTrial> trial =
181 FieldTrialList::CreateFieldTrial("foo", "bar");
182 const char kParam[] = "param_1";
183 const char kValue[] = "value_1";
184 const char kValue0[] = "value_0";
185 std::map<std::string, std::string> parameters;
186 parameters[kParam] = kValue;
187
188 test::ScopedFeatureList feature_list1;
189 feature_list1.InitFromCommandLine(
190 "TestFeature1<foo.bar:param_1/value_0,TestFeature2", std::string());
191
192 // Check initial state.
193 ExpectFeatures("TestFeature1<foo,TestFeature2", std::string());
194 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
195 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
196 // ScopedFeatureList always scope features, field trials and their associated
197 // parameters. So ScopedFeatureList::InitFromCommandLine() creates another
198 // FieldTrial instance whose trial name, group name and associated parameters
199 // are the same as |trial|, and changes |kTestFeature1|'s field trial to
200 // be the newly created one.
201 EXPECT_NE(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
202 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
203 EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
204 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
205 EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
206
207 FieldTrial* trial_for_test_feature1 =
208 FeatureList::GetFieldTrial(kTestFeature1);
209 EXPECT_EQ("foo", trial_for_test_feature1->trial_name());
210 EXPECT_EQ("bar", trial_for_test_feature1->group_name());
211
212 {
213 // Override feature with existing field trial.
214 test::ScopedFeatureList feature_list2;
215
216 feature_list2.InitAndEnableFeatureWithParameters(kTestFeature1, parameters);
217 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
218 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
219 EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
220 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
221 EXPECT_NE(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
222 EXPECT_NE(trial_for_test_feature1,
223 FeatureList::GetFieldTrial(kTestFeature1));
224 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
225 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
226 }
227
228 {
229 // Override feature with existing field trial.
230 test::ScopedFeatureList feature_list2;
231
232 feature_list2.InitFromCommandLine("TestFeature1<foo.bar2:param_1/value_1",
233 std::string());
234 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
235 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
236 EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
237 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
238 EXPECT_NE(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
239 EXPECT_NE(trial_for_test_feature1,
240 FeatureList::GetFieldTrial(kTestFeature1));
241 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
242 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
243
244 // foo's active group is now bar2, not bar.
245 EXPECT_TRUE(FieldTrialList::IsTrialActive("foo"));
246 EXPECT_EQ("bar2", GetActiveFieldTrialGroupName("foo"));
247 }
248
249 // Check that initial state is restored.
250 ExpectFeatures("TestFeature1<foo,TestFeature2", std::string());
251 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
252 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
253 EXPECT_EQ(trial_for_test_feature1, FeatureList::GetFieldTrial(kTestFeature1));
254 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
255 EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
256 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
257 // foo's active group is bar, because initial state is restored.
258 EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
259
260 {
261 // Override feature with no existing field trial.
262 test::ScopedFeatureList feature_list2;
263
264 feature_list2.InitAndEnableFeatureWithParameters(kTestFeature2, parameters);
265 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
266 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
267 EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
268 EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
269 EXPECT_EQ(trial_for_test_feature1->trial_name(),
270 FeatureList::GetFieldTrial(kTestFeature1)->trial_name());
271 EXPECT_EQ(trial_for_test_feature1->group_name(),
272 FeatureList::GetFieldTrial(kTestFeature1)->group_name());
273 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
274 }
275
276 // Check that initial state is restored.
277 ExpectFeatures("TestFeature1<foo,TestFeature2", std::string());
278 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
279 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
280 EXPECT_EQ(trial_for_test_feature1, FeatureList::GetFieldTrial(kTestFeature1));
281 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
282 EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
283 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
284 }
285
TEST_F(ScopedFeatureListTest,OverrideWithFeatureMultipleParameters)286 TEST_F(ScopedFeatureListTest, OverrideWithFeatureMultipleParameters) {
287 const char kParam1[] = "param_1";
288 const char kValue1[] = "value_1";
289 const char kParam2[] = "param_2";
290 const char kValue2[] = "value_2";
291 const char kValue3[] = "value_3";
292 std::map<std::string, std::string> parameters;
293 parameters[kParam1] = kValue3;
294
295 test::ScopedFeatureList feature_list1;
296 feature_list1.InitFromCommandLine(
297 "TestFeature1<foo.bar:param_1/value_1/param_2/"
298 "value_2,TestFeature2:param_1/value_2",
299 std::string());
300
301 // Check initial state.
302 ExpectFeatures("TestFeature1<foo,TestFeature2<StudyTestFeature2",
303 std::string());
304 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
305 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
306 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
307 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
308 EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
309 EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
310 EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
311 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
312
313 FieldTrial* trial = FieldTrialList::Find("foo");
314 EXPECT_EQ("bar", trial->GetGroupNameWithoutActivation());
315 EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
316
317 FieldTrial* trial2 = FieldTrialList::Find("StudyTestFeature2");
318 EXPECT_EQ("GroupTestFeature2", trial2->GetGroupNameWithoutActivation());
319 EXPECT_EQ("GroupTestFeature2",
320 GetActiveFieldTrialGroupName("StudyTestFeature2"));
321
322 {
323 // Override feature with existing field trial.
324 test::ScopedFeatureList feature_list2;
325
326 feature_list2.InitAndEnableFeatureWithParameters(kTestFeature1, parameters);
327 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
328 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
329 EXPECT_EQ(kValue3,
330 GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
331 // param_2 is not set.
332 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
333 EXPECT_EQ(kValue2,
334 GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
335 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
336 EXPECT_NE(trial, FeatureList::GetFieldTrial(kTestFeature1));
337 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
338 EXPECT_NE(trial2, FeatureList::GetFieldTrial(kTestFeature2));
339 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
340 }
341
342 // Check that initial state is restored.
343 ExpectFeatures("TestFeature1<foo,TestFeature2<StudyTestFeature2",
344 std::string());
345 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
346 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
347 EXPECT_EQ(trial, FeatureList::GetFieldTrial(kTestFeature1));
348 EXPECT_EQ(trial2, FeatureList::GetFieldTrial(kTestFeature2));
349 EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
350 EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
351 EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
352 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
353 // foo's active group is bar, because initial state is restored.
354 EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
355 EXPECT_EQ("GroupTestFeature2",
356 GetActiveFieldTrialGroupName("StudyTestFeature2"));
357
358 {
359 // Override feature with existing field trial.
360 test::ScopedFeatureList feature_list2;
361
362 feature_list2.InitFromCommandLine("TestFeature1<foo.bar2:param_2/value_3",
363 std::string());
364 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
365 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
366 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
367 EXPECT_EQ(kValue3,
368 GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
369 EXPECT_EQ(kValue2,
370 GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
371 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
372 EXPECT_NE(trial, FeatureList::GetFieldTrial(kTestFeature1));
373 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
374 EXPECT_EQ("foo", FeatureList::GetFieldTrial(kTestFeature1)->trial_name());
375 EXPECT_EQ("bar2", FeatureList::GetFieldTrial(kTestFeature1)->group_name());
376 EXPECT_NE(trial2, FeatureList::GetFieldTrial(kTestFeature2));
377 EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
378
379 // foo's active group is now bar2, not bar.
380 EXPECT_TRUE(FieldTrialList::IsTrialActive("foo"));
381 EXPECT_EQ("bar2", GetActiveFieldTrialGroupName("foo"));
382 }
383
384 // Check that initial state is restored.
385 ExpectFeatures("TestFeature1<foo,TestFeature2<StudyTestFeature2",
386 std::string());
387 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
388 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
389 EXPECT_EQ(trial, FeatureList::GetFieldTrial(kTestFeature1));
390 EXPECT_EQ(trial2, FeatureList::GetFieldTrial(kTestFeature2));
391 EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
392 EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
393 EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
394 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
395 EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
396 }
397
TEST_F(ScopedFeatureListTest,OverrideMultipleFeaturesWithParameters)398 TEST_F(ScopedFeatureListTest, OverrideMultipleFeaturesWithParameters) {
399 scoped_refptr<FieldTrial> trial1 =
400 FieldTrialList::CreateFieldTrial("foo1", "bar1");
401 const char kParam[] = "param_1";
402 const char kValue0[] = "value_0";
403 const char kValue1[] = "value_1";
404 const char kValue2[] = "value_2";
405 std::map<std::string, std::string> parameters1;
406 parameters1[kParam] = kValue1;
407 std::map<std::string, std::string> parameters2;
408 parameters2[kParam] = kValue2;
409
410 test::ScopedFeatureList feature_list1;
411 feature_list1.InitFromCommandLine(
412 "TestFeature1<foo1:param_1/value_0,TestFeature2", std::string());
413
414 // Check initial state.
415 ExpectFeatures("TestFeature1<foo1,TestFeature2", std::string());
416 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
417 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
418 EXPECT_EQ("foo1", FeatureList::GetFieldTrial(kTestFeature1)->trial_name());
419 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
420 EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
421 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
422
423 // InitFromCommandLine() scopes field trials.
424 FieldTrial* trial = FieldTrialList::Find("foo1");
425 // --enable-features will create a group whose name is "Group" + feature
426 // name if no group name is specified. In this case, the feature name is
427 // "TestFeature1". So the group name is "GroupTestFeature1".
428 EXPECT_EQ("GroupTestFeature1", trial->GetGroupNameWithoutActivation());
429 EXPECT_NE(trial1.get(), trial);
430 // Because of "scoped", "bar1" disappears. Instead, "GroupTestFeature1"
431 // is created and activated.
432 EXPECT_NE("bar1", GetActiveFieldTrialGroupName("foo1"));
433 EXPECT_EQ("GroupTestFeature1", GetActiveFieldTrialGroupName("foo1"));
434
435 {
436 // Override multiple features with parameters.
437 test::ScopedFeatureList feature_list2;
438 feature_list2.InitWithFeaturesAndParameters(
439 {{kTestFeature1, parameters1}, {kTestFeature2, parameters2}}, {});
440
441 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
442 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
443 EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
444 EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
445 }
446
447 {
448 // Override a feature with a parameter and disable another one.
449 test::ScopedFeatureList feature_list2;
450 feature_list2.InitWithFeaturesAndParameters({{kTestFeature1, parameters2}},
451 {kTestFeature2});
452
453 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
454 EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature2));
455 EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
456 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
457 }
458
459 // Check that initial state is restored.
460 ExpectFeatures("TestFeature1<foo1,TestFeature2", std::string());
461 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
462 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
463 EXPECT_EQ(trial, FeatureList::GetFieldTrial(kTestFeature1));
464 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
465 EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
466 EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
467 }
468
TEST_F(ScopedFeatureListTest,ParamsWithSpecialCharsPreserved)469 TEST_F(ScopedFeatureListTest, ParamsWithSpecialCharsPreserved) {
470 // Check that special characters in param names and values are preserved.
471 const char kParam[] = ";_\\<:>/_!?";
472 const char kValue[] = ",;:/'!?";
473 FieldTrialParams params0 = {{kParam, kValue}};
474
475 test::ScopedFeatureList feature_list0;
476 feature_list0.InitWithFeaturesAndParameters({{kTestFeature1, params0}}, {});
477 EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
478
479 {
480 const char kValue1[] = "normal";
481 FieldTrialParams params1 = {{kParam, kValue1}};
482 test::ScopedFeatureList feature_list1;
483 feature_list1.InitWithFeaturesAndParameters({{kTestFeature1, params1}}, {});
484
485 EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
486 }
487 EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
488
489 {
490 const char kValue2[] = "[<(2)>]";
491 FieldTrialParams params2 = {{kParam, kValue2}};
492 test::ScopedFeatureList feature_list2;
493 feature_list2.InitWithFeaturesAndParameters({{kTestFeature2, params2}}, {});
494
495 EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
496 EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
497 }
498 EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
499 }
500
TEST_F(ScopedFeatureListTest,ParamsWithEmptyValue)501 TEST_F(ScopedFeatureListTest, ParamsWithEmptyValue) {
502 const char kParam[] = "p";
503 const char kEmptyValue[] = "";
504 FieldTrialParams params = {{kParam, kEmptyValue}};
505
506 test::ScopedFeatureList feature_list0;
507 feature_list0.InitWithFeaturesAndParameters({{kTestFeature1, params}}, {});
508 EXPECT_EQ(kEmptyValue,
509 GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
510 {
511 const char kValue1[] = "normal";
512 FieldTrialParams params1 = {{kParam, kValue1}};
513 test::ScopedFeatureList feature_list1;
514 feature_list1.InitWithFeaturesAndParameters({{kTestFeature1, params1}}, {});
515
516 EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
517 }
518 EXPECT_EQ(kEmptyValue,
519 GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
520 }
521
TEST_F(ScopedFeatureListTest,EnableFeatureOverrideDisable)522 TEST_F(ScopedFeatureListTest, EnableFeatureOverrideDisable) {
523 test::ScopedFeatureList feature_list1;
524 feature_list1.InitWithFeatures({}, {kTestFeature1});
525
526 {
527 test::ScopedFeatureList feature_list2;
528 feature_list2.InitWithFeatures({kTestFeature1}, {});
529 ExpectFeatures("TestFeature1", std::string());
530 }
531 }
532
TEST_F(ScopedFeatureListTest,FeatureOverrideNotMakeDuplicate)533 TEST_F(ScopedFeatureListTest, FeatureOverrideNotMakeDuplicate) {
534 test::ScopedFeatureList feature_list1;
535 feature_list1.InitWithFeatures({}, {kTestFeature1});
536
537 {
538 test::ScopedFeatureList feature_list2;
539 feature_list2.InitWithFeatures({}, {kTestFeature1});
540 ExpectFeatures(std::string(), "TestFeature1");
541 }
542 }
543
TEST_F(ScopedFeatureListTest,FeatureOverrideFeatureWithDefault)544 TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault) {
545 test::ScopedFeatureList feature_list1;
546 feature_list1.InitFromCommandLine("*TestFeature1", std::string());
547
548 {
549 test::ScopedFeatureList feature_list2;
550 feature_list2.InitWithFeatures({kTestFeature1}, {});
551 ExpectFeatures("TestFeature1", std::string());
552 }
553 }
554
TEST_F(ScopedFeatureListTest,FeatureOverrideFeatureWithDefault2)555 TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault2) {
556 test::ScopedFeatureList feature_list1;
557 feature_list1.InitFromCommandLine("*TestFeature1", std::string());
558
559 {
560 test::ScopedFeatureList feature_list2;
561 feature_list2.InitWithFeatures({}, {kTestFeature1});
562 ExpectFeatures(std::string(), "TestFeature1");
563 }
564 }
565
TEST_F(ScopedFeatureListTest,FeatureOverrideFeatureWithEnabledFieldTrial)566 TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithEnabledFieldTrial) {
567 test::ScopedFeatureList feature_list1;
568
569 std::unique_ptr<FeatureList> feature_list(new FeatureList);
570 FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A");
571 feature_list->RegisterFieldTrialOverride(
572 kTestFeature1.name, FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
573 feature_list1.InitWithFeatureList(std::move(feature_list));
574
575 {
576 test::ScopedFeatureList feature_list2;
577 feature_list2.InitWithFeatures({kTestFeature1}, {});
578 ExpectFeatures("TestFeature1", std::string());
579 }
580 }
581
TEST_F(ScopedFeatureListTest,FeatureOverrideFeatureWithDisabledFieldTrial)582 TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDisabledFieldTrial) {
583 test::ScopedFeatureList feature_list1;
584
585 std::unique_ptr<FeatureList> feature_list(new FeatureList);
586 FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A");
587 feature_list->RegisterFieldTrialOverride(
588 kTestFeature1.name, FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
589 feature_list1.InitWithFeatureList(std::move(feature_list));
590
591 {
592 test::ScopedFeatureList feature_list2;
593 feature_list2.InitWithFeatures({kTestFeature1}, {});
594 ExpectFeatures("TestFeature1", std::string());
595 }
596 }
597
TEST_F(ScopedFeatureListTest,FeatureOverrideKeepsOtherExistingFeature)598 TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature) {
599 test::ScopedFeatureList feature_list1;
600 feature_list1.InitWithFeatures({}, {kTestFeature1});
601
602 {
603 test::ScopedFeatureList feature_list2;
604 feature_list2.InitWithFeatures({}, {kTestFeature2});
605 EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1));
606 EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature2));
607 }
608 }
609
TEST_F(ScopedFeatureListTest,FeatureOverrideKeepsOtherExistingFeature2)610 TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature2) {
611 test::ScopedFeatureList feature_list1;
612 feature_list1.InitWithFeatures({}, {kTestFeature1});
613
614 {
615 test::ScopedFeatureList feature_list2;
616 feature_list2.InitWithFeatures({kTestFeature2}, {});
617 ExpectFeatures("TestFeature2", "TestFeature1");
618 }
619 }
620
TEST_F(ScopedFeatureListTest,FeatureOverrideKeepsOtherExistingDefaultFeature)621 TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingDefaultFeature) {
622 test::ScopedFeatureList feature_list1;
623 feature_list1.InitFromCommandLine("*TestFeature1", std::string());
624
625 {
626 test::ScopedFeatureList feature_list2;
627 feature_list2.InitWithFeatures({}, {kTestFeature2});
628 ExpectFeatures("*TestFeature1", "TestFeature2");
629 }
630 }
631
TEST_F(ScopedFeatureListTest,ScopedFeatureListIsNoopWhenNotInitialized)632 TEST_F(ScopedFeatureListTest, ScopedFeatureListIsNoopWhenNotInitialized) {
633 test::ScopedFeatureList feature_list1;
634 feature_list1.InitFromCommandLine("*TestFeature1", std::string());
635
636 // A ScopedFeatureList on which Init() is not called should not reset things
637 // when going out of scope.
638 { test::ScopedFeatureList feature_list2; }
639
640 ExpectFeatures("*TestFeature1", std::string());
641 }
642
TEST_F(ScopedFeatureListTest,RestoreFieldTrialParamsCorrectlyWhenLeakedFieldTrialCreated)643 TEST_F(ScopedFeatureListTest,
644 RestoreFieldTrialParamsCorrectlyWhenLeakedFieldTrialCreated) {
645 test::ScopedFeatureList feature_list1;
646 feature_list1.InitFromCommandLine("TestFeature1:TestParam/TestValue1", "");
647 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
648 EXPECT_EQ("TestValue1",
649 GetFieldTrialParamValueByFeature(kTestFeature1, "TestParam"));
650
651 // content::InitializeFieldTrialAndFeatureList() creates a leaked
652 // FieldTrialList. To emulate the leaked one, declare
653 // unique_ptr<FieldTriaList> here and initialize it inside the following
654 // child scope.
655 std::unique_ptr<FieldTrialList> leaked_field_trial_list;
656 {
657 test::ScopedFeatureList feature_list2;
658 feature_list2.InitWithNullFeatureAndFieldTrialLists();
659
660 leaked_field_trial_list = std::make_unique<FieldTrialList>();
661 FeatureList::InitInstance("TestFeature1:TestParam/TestValue2", "", {});
662 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
663 EXPECT_EQ("TestValue2",
664 GetFieldTrialParamValueByFeature(kTestFeature1, "TestParam"));
665 }
666 EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
667 EXPECT_EQ("TestValue1",
668 GetFieldTrialParamValueByFeature(kTestFeature1, "TestParam"));
669
670 {
671 FieldTrialList* backup_field_trial =
672 FieldTrialList::BackupInstanceForTesting();
673
674 // To free leaked_field_trial_list, need RestoreInstanceForTesting()
675 // to pass DCHECK_EQ(this, global_) at ~FieldTrialList().
676 FieldTrialList::RestoreInstanceForTesting(leaked_field_trial_list.get());
677 leaked_field_trial_list.reset();
678 FieldTrialList::RestoreInstanceForTesting(backup_field_trial);
679 }
680 }
681
TEST(ScopedFeatureListTestWithMemberList,ScopedFeatureListLocalOverride)682 TEST(ScopedFeatureListTestWithMemberList, ScopedFeatureListLocalOverride) {
683 test::ScopedFeatureList initial_feature_list;
684 initial_feature_list.InitAndDisableFeature(kTestFeature1);
685 {
686 base::test::ScopedFeatureList scoped_features;
687 scoped_features.InitAndEnableFeatureWithParameters(kTestFeature1,
688 {{"mode", "nobugs"}});
689 ASSERT_TRUE(FeatureList::IsEnabled(kTestFeature1));
690 }
691 }
692
TEST_F(ScopedFeatureListTest,InitWithFeatureStates)693 TEST_F(ScopedFeatureListTest, InitWithFeatureStates) {
694 test::ScopedFeatureList feature_list1;
695 feature_list1.InitWithFeatureStates(
696 {{kTestFeature1, true}, {kTestFeature2, false}});
697 ExpectFeatures(/*enabled_features=*/"TestFeature1",
698 /*disabled_features=*/"TestFeature2");
699
700 {
701 test::ScopedFeatureList feature_list2;
702 feature_list2.InitWithFeatureStates(
703 {{kTestFeature1, false}, {kTestFeature2, true}});
704 ExpectFeatures(/*enabled_features=*/"TestFeature2",
705 /*disabled_features=*/"TestFeature1");
706 }
707 }
708
TEST_F(ScopedFeatureListTest,FeatureParameterCache)709 TEST_F(ScopedFeatureListTest, FeatureParameterCache) {
710 // Check the default parameter, and bring it on its local cache if the cache
711 // is enabled.
712 ASSERT_FALSE(kTestFeatureParam1.Get());
713
714 // Ensure if the parameter override works if the cache feature is enabled
715 // outside the ScopedFeatureList.
716 test::ScopedFeatureList feature_list_to_override_cached_parameter;
717 feature_list_to_override_cached_parameter.InitAndEnableFeatureWithParameters(
718 kTestFeature1, {{kTestFeatureParam1.name, "true"}});
719 ASSERT_TRUE(kTestFeatureParam1.Get());
720 }
721
722 } // namespace base::test
723