1 // Copyright 2015 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.
5 #include "base/feature_list.h"
13 #include "base/format_macros.h"
14 #include "base/memory/read_only_shared_memory_region.h"
15 #include "base/metrics/field_trial.h"
16 #include "base/metrics/persistent_memory_allocator.h"
17 #include "base/stl_util.h"
18 #include "base/strings/string_piece.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/test/scoped_feature_list.h"
22 #include "base/test/scoped_field_trial_list_resetter.h"
23 #include "testing/gtest/include/gtest/gtest.h"
29 constexpr char kFeatureOnByDefaultName[] = "OnByDefault";
30 struct Feature kFeatureOnByDefault {
31 kFeatureOnByDefaultName, FEATURE_ENABLED_BY_DEFAULT
34 constexpr char kFeatureOffByDefaultName[] = "OffByDefault";
35 struct Feature kFeatureOffByDefault {
36 kFeatureOffByDefaultName, FEATURE_DISABLED_BY_DEFAULT
39 std::string SortFeatureListString(const std::string& feature_list) {
40 std::vector<base::StringPiece> features =
41 FeatureList::SplitFeatureListString(feature_list);
42 std::sort(features.begin(), features.end());
43 return JoinString(features, ",");
48 class FeatureListTest : public testing::Test {
51 // Provide an empty FeatureList to each test by default.
52 scoped_feature_list_.InitWithFeatureList(std::make_unique<FeatureList>());
54 ~FeatureListTest() override = default;
57 test::ScopedFeatureList scoped_feature_list_;
59 DISALLOW_COPY_AND_ASSIGN(FeatureListTest);
62 TEST_F(FeatureListTest, DefaultStates) {
63 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
64 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
67 TEST_F(FeatureListTest, InitializeFromCommandLine) {
69 const char* enable_features;
70 const char* disable_features;
71 bool expected_feature_on_state;
72 bool expected_feature_off_state;
74 {"", "", true, false},
75 {"OffByDefault", "", true, true},
76 {"OffByDefault", "OnByDefault", false, true},
77 {"OnByDefault,OffByDefault", "", true, true},
78 {"", "OnByDefault,OffByDefault", false, false},
79 // In the case an entry is both, disable takes precedence.
80 {"OnByDefault", "OnByDefault,OffByDefault", false, false},
83 for (size_t i = 0; i < base::size(test_cases); ++i) {
84 const auto& test_case = test_cases[i];
85 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
86 test_case.enable_features,
87 test_case.disable_features));
89 auto feature_list = std::make_unique<FeatureList>();
90 feature_list->InitializeFromCommandLine(test_case.enable_features,
91 test_case.disable_features);
92 test::ScopedFeatureList scoped_feature_list;
93 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
95 EXPECT_EQ(test_case.expected_feature_on_state,
96 FeatureList::IsEnabled(kFeatureOnByDefault))
98 EXPECT_EQ(test_case.expected_feature_off_state,
99 FeatureList::IsEnabled(kFeatureOffByDefault))
104 TEST_F(FeatureListTest, CheckFeatureIdentity) {
105 // Tests that CheckFeatureIdentity() correctly detects when two different
106 // structs with the same feature name are passed to it.
108 test::ScopedFeatureList scoped_feature_list;
109 scoped_feature_list.InitWithFeatureList(std::make_unique<FeatureList>());
110 FeatureList* feature_list = FeatureList::GetInstance();
112 // Call it twice for each feature at the top of the file, since the first call
113 // makes it remember the entry and the second call will verify it.
114 EXPECT_TRUE(feature_list->CheckFeatureIdentity(kFeatureOnByDefault));
115 EXPECT_TRUE(feature_list->CheckFeatureIdentity(kFeatureOnByDefault));
116 EXPECT_TRUE(feature_list->CheckFeatureIdentity(kFeatureOffByDefault));
117 EXPECT_TRUE(feature_list->CheckFeatureIdentity(kFeatureOffByDefault));
119 // Now, call it with a distinct struct for |kFeatureOnByDefaultName|, which
120 // should return false.
121 struct Feature kFeatureOnByDefault2 {
122 kFeatureOnByDefaultName, FEATURE_ENABLED_BY_DEFAULT
124 EXPECT_FALSE(feature_list->CheckFeatureIdentity(kFeatureOnByDefault2));
127 TEST_F(FeatureListTest, FieldTrialOverrides) {
129 FeatureList::OverrideState trial1_state;
130 FeatureList::OverrideState trial2_state;
132 {FeatureList::OVERRIDE_DISABLE_FEATURE,
133 FeatureList::OVERRIDE_DISABLE_FEATURE},
134 {FeatureList::OVERRIDE_DISABLE_FEATURE,
135 FeatureList::OVERRIDE_ENABLE_FEATURE},
136 {FeatureList::OVERRIDE_ENABLE_FEATURE,
137 FeatureList::OVERRIDE_DISABLE_FEATURE},
138 {FeatureList::OVERRIDE_ENABLE_FEATURE,
139 FeatureList::OVERRIDE_ENABLE_FEATURE},
142 FieldTrial::ActiveGroup active_group;
143 for (size_t i = 0; i < base::size(test_cases); ++i) {
144 const auto& test_case = test_cases[i];
145 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
147 test::ScopedFieldTrialListResetter resetter;
148 FieldTrialList field_trial_list(nullptr);
149 auto feature_list = std::make_unique<FeatureList>();
151 FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
152 FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
153 feature_list->RegisterFieldTrialOverride(kFeatureOnByDefaultName,
154 test_case.trial1_state, trial1);
155 feature_list->RegisterFieldTrialOverride(kFeatureOffByDefaultName,
156 test_case.trial2_state, trial2);
157 test::ScopedFeatureList scoped_feature_list;
158 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
160 // Initially, neither trial should be active.
161 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial1->trial_name()));
162 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
164 const bool expected_enabled_1 =
165 (test_case.trial1_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
166 EXPECT_EQ(expected_enabled_1, FeatureList::IsEnabled(kFeatureOnByDefault));
167 // The above should have activated |trial1|.
168 EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
169 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
171 const bool expected_enabled_2 =
172 (test_case.trial2_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
173 EXPECT_EQ(expected_enabled_2, FeatureList::IsEnabled(kFeatureOffByDefault));
174 // The above should have activated |trial2|.
175 EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
176 EXPECT_TRUE(FieldTrialList::IsTrialActive(trial2->trial_name()));
180 TEST_F(FeatureListTest, FieldTrialAssociateUseDefault) {
181 auto feature_list = std::make_unique<FeatureList>();
183 FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
184 FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
185 feature_list->RegisterFieldTrialOverride(
186 kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial1);
187 feature_list->RegisterFieldTrialOverride(
188 kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial2);
189 test::ScopedFeatureList scoped_feature_list;
190 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
192 // Initially, neither trial should be active.
193 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial1->trial_name()));
194 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
196 // Check the feature enabled state is its default.
197 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
198 // The above should have activated |trial1|.
199 EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
200 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
202 // Check the feature enabled state is its default.
203 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
204 // The above should have activated |trial2|.
205 EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
206 EXPECT_TRUE(FieldTrialList::IsTrialActive(trial2->trial_name()));
209 TEST_F(FeatureListTest, CommandLineEnableTakesPrecedenceOverFieldTrial) {
210 auto feature_list = std::make_unique<FeatureList>();
212 // The feature is explicitly enabled on the command-line.
213 feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
215 // But the FieldTrial would set the feature to disabled.
216 FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample2", "A");
217 feature_list->RegisterFieldTrialOverride(
218 kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
219 test::ScopedFeatureList scoped_feature_list;
220 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
222 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
223 // Command-line should take precedence.
224 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
225 // Since the feature is on due to the command-line, and not as a result of the
226 // field trial, the field trial should not be activated (since the Associate*
228 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
231 TEST_F(FeatureListTest, CommandLineDisableTakesPrecedenceOverFieldTrial) {
232 auto feature_list = std::make_unique<FeatureList>();
234 // The feature is explicitly disabled on the command-line.
235 feature_list->InitializeFromCommandLine("", kFeatureOffByDefaultName);
237 // But the FieldTrial would set the feature to enabled.
238 FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample2", "A");
239 feature_list->RegisterFieldTrialOverride(
240 kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
241 test::ScopedFeatureList scoped_feature_list;
242 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
244 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
245 // Command-line should take precedence.
246 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
247 // Since the feature is on due to the command-line, and not as a result of the
248 // field trial, the field trial should not be activated (since the Associate*
250 EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
253 TEST_F(FeatureListTest, IsFeatureOverriddenFromCommandLine) {
254 auto feature_list = std::make_unique<FeatureList>();
256 // No features are overridden from the command line yet
257 EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
258 kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
259 EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
260 kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
261 EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
262 kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
263 EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
264 kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
266 // Now, enable |kFeatureOffByDefaultName| via the command-line.
267 feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
269 // It should now be overridden for the enabled group.
270 EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
271 kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
272 EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
273 kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
275 // Register a field trial to associate with the feature and ensure that the
276 // results are still the same.
277 feature_list->AssociateReportingFieldTrial(
278 kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
279 FieldTrialList::CreateFieldTrial("Trial1", "A"));
280 EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
281 kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
282 EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
283 kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
285 // Now, register a field trial to override |kFeatureOnByDefaultName| state
286 // and check that the function still returns false for that feature.
287 feature_list->RegisterFieldTrialOverride(
288 kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
289 FieldTrialList::CreateFieldTrial("Trial2", "A"));
290 EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
291 kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
292 EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
293 kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
294 test::ScopedFeatureList scoped_feature_list;
295 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
297 // Check the expected feature states for good measure.
298 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
299 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
302 TEST_F(FeatureListTest, AssociateReportingFieldTrial) {
304 const char* enable_features;
305 const char* disable_features;
306 bool expected_enable_trial_created;
307 bool expected_disable_trial_created;
309 // If no enable/disable flags are specified, no trials should be created.
310 {"", "", false, false},
311 // Enabling the feature should result in the enable trial created.
312 {kFeatureOffByDefaultName, "", true, false},
313 // Disabling the feature should result in the disable trial created.
314 {"", kFeatureOffByDefaultName, false, true},
317 const char kTrialName[] = "ForcingTrial";
318 const char kForcedOnGroupName[] = "ForcedOn";
319 const char kForcedOffGroupName[] = "ForcedOff";
321 for (size_t i = 0; i < base::size(test_cases); ++i) {
322 const auto& test_case = test_cases[i];
323 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
324 test_case.enable_features,
325 test_case.disable_features));
327 test::ScopedFieldTrialListResetter resetter;
328 FieldTrialList field_trial_list(nullptr);
329 auto feature_list = std::make_unique<FeatureList>();
330 feature_list->InitializeFromCommandLine(test_case.enable_features,
331 test_case.disable_features);
333 FieldTrial* enable_trial = nullptr;
334 if (feature_list->IsFeatureOverriddenFromCommandLine(
335 kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE)) {
336 enable_trial = base::FieldTrialList::CreateFieldTrial(kTrialName,
338 feature_list->AssociateReportingFieldTrial(
339 kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
342 FieldTrial* disable_trial = nullptr;
343 if (feature_list->IsFeatureOverriddenFromCommandLine(
344 kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE)) {
345 disable_trial = base::FieldTrialList::CreateFieldTrial(
346 kTrialName, kForcedOffGroupName);
347 feature_list->AssociateReportingFieldTrial(
348 kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
351 EXPECT_EQ(test_case.expected_enable_trial_created, enable_trial != nullptr);
352 EXPECT_EQ(test_case.expected_disable_trial_created,
353 disable_trial != nullptr);
354 test::ScopedFeatureList scoped_feature_list;
355 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
357 EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
359 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
360 EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
361 EXPECT_EQ(kForcedOffGroupName, disable_trial->group_name());
362 } else if (enable_trial) {
363 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
364 EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
365 EXPECT_EQ(kForcedOnGroupName, enable_trial->group_name());
370 TEST_F(FeatureListTest, RegisterExtraFeatureOverrides) {
371 auto feature_list = std::make_unique<FeatureList>();
372 std::vector<FeatureList::FeatureOverrideInfo> overrides;
373 overrides.push_back({std::cref(kFeatureOnByDefault),
374 FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE});
375 overrides.push_back({std::cref(kFeatureOffByDefault),
376 FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE});
377 feature_list->RegisterExtraFeatureOverrides(std::move(overrides));
378 test::ScopedFeatureList scoped_feature_list;
379 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
381 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
382 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
385 TEST_F(FeatureListTest, InitializeFromCommandLineThenRegisterExtraOverrides) {
386 auto feature_list = std::make_unique<FeatureList>();
387 feature_list->InitializeFromCommandLine(kFeatureOnByDefaultName,
388 kFeatureOffByDefaultName);
389 std::vector<FeatureList::FeatureOverrideInfo> overrides;
390 overrides.push_back({std::cref(kFeatureOnByDefault),
391 FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE});
392 overrides.push_back({std::cref(kFeatureOffByDefault),
393 FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE});
394 feature_list->RegisterExtraFeatureOverrides(std::move(overrides));
395 test::ScopedFeatureList scoped_feature_list;
396 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
398 // The InitializeFromCommandLine supersedes the RegisterExtraFeatureOverrides
399 // because it was called first.
400 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
401 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
403 std::string enable_features;
404 std::string disable_features;
405 FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
407 EXPECT_EQ(kFeatureOnByDefaultName, SortFeatureListString(enable_features));
408 EXPECT_EQ(kFeatureOffByDefaultName, SortFeatureListString(disable_features));
411 TEST_F(FeatureListTest, GetFeatureOverrides) {
412 auto feature_list = std::make_unique<FeatureList>();
413 feature_list->InitializeFromCommandLine("A,X", "D");
415 Feature feature_b = {"B", FEATURE_ENABLED_BY_DEFAULT};
416 Feature feature_c = {"C", FEATURE_DISABLED_BY_DEFAULT};
417 std::vector<FeatureList::FeatureOverrideInfo> overrides;
418 overrides.push_back({std::cref(feature_b),
419 FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE});
420 overrides.push_back({std::cref(feature_c),
421 FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE});
422 feature_list->RegisterExtraFeatureOverrides(std::move(overrides));
424 FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
425 feature_list->RegisterFieldTrialOverride(kFeatureOffByDefaultName,
426 FeatureList::OVERRIDE_ENABLE_FEATURE,
429 test::ScopedFeatureList scoped_feature_list;
430 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
432 std::string enable_features;
433 std::string disable_features;
434 FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
436 EXPECT_EQ("A,C,OffByDefault<Trial,X", SortFeatureListString(enable_features));
437 EXPECT_EQ("B,D", SortFeatureListString(disable_features));
439 FeatureList::GetInstance()->GetCommandLineFeatureOverrides(&enable_features,
441 EXPECT_EQ("A,C,X", SortFeatureListString(enable_features));
442 EXPECT_EQ("B,D", SortFeatureListString(disable_features));
445 TEST_F(FeatureListTest, GetFeatureOverrides_UseDefault) {
446 auto feature_list = std::make_unique<FeatureList>();
447 feature_list->InitializeFromCommandLine("A,X", "D");
449 FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
450 feature_list->RegisterFieldTrialOverride(
451 kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial);
453 test::ScopedFeatureList scoped_feature_list;
454 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
456 std::string enable_features;
457 std::string disable_features;
458 FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
460 EXPECT_EQ("*OffByDefault<Trial,A,X", SortFeatureListString(enable_features));
461 EXPECT_EQ("D", SortFeatureListString(disable_features));
464 TEST_F(FeatureListTest, GetFieldTrial) {
465 FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
466 auto feature_list = std::make_unique<FeatureList>();
467 feature_list->RegisterFieldTrialOverride(
468 kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial);
469 test::ScopedFeatureList scoped_feature_list;
470 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
472 EXPECT_EQ(trial, FeatureList::GetFieldTrial(kFeatureOnByDefault));
473 EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kFeatureOffByDefault));
476 TEST_F(FeatureListTest, InitializeFromCommandLine_WithFieldTrials) {
477 FieldTrialList::CreateFieldTrial("Trial", "Group");
478 auto feature_list = std::make_unique<FeatureList>();
479 feature_list->InitializeFromCommandLine("A,OffByDefault<Trial,X", "D");
480 test::ScopedFeatureList scoped_feature_list;
481 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
483 EXPECT_FALSE(FieldTrialList::IsTrialActive("Trial"));
484 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
485 EXPECT_TRUE(FieldTrialList::IsTrialActive("Trial"));
488 TEST_F(FeatureListTest, InitializeFromCommandLine_UseDefault) {
489 FieldTrialList::CreateFieldTrial("T1", "Group");
490 FieldTrialList::CreateFieldTrial("T2", "Group");
491 auto feature_list = std::make_unique<FeatureList>();
492 feature_list->InitializeFromCommandLine(
493 "A,*OffByDefault<T1,*OnByDefault<T2,X", "D");
494 test::ScopedFeatureList scoped_feature_list;
495 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
497 EXPECT_FALSE(FieldTrialList::IsTrialActive("T1"));
498 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
499 EXPECT_TRUE(FieldTrialList::IsTrialActive("T1"));
501 EXPECT_FALSE(FieldTrialList::IsTrialActive("T2"));
502 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
503 EXPECT_TRUE(FieldTrialList::IsTrialActive("T2"));
506 TEST_F(FeatureListTest, InitializeInstance) {
507 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
508 test::ScopedFeatureList scoped_feature_list;
509 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
511 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
512 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
514 // Initialize from command line if we haven't yet.
515 FeatureList::InitializeInstance("", kFeatureOnByDefaultName);
516 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
517 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
519 // Do not initialize from commandline if we have already.
520 FeatureList::InitializeInstance(kFeatureOffByDefaultName, "");
521 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
522 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
525 TEST_F(FeatureListTest, UninitializedInstance_IsEnabledReturnsFalse) {
526 std::unique_ptr<FeatureList> original_feature_list =
527 FeatureList::ClearInstanceForTesting();
529 // This test case simulates the calling pattern found in code which does not
530 // explicitly initialize the features list.
531 // All IsEnabled() calls should return the default value in this scenario.
532 EXPECT_EQ(nullptr, FeatureList::GetInstance());
533 EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
534 EXPECT_EQ(nullptr, FeatureList::GetInstance());
535 EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
537 if (original_feature_list)
538 FeatureList::RestoreInstanceForTesting(std::move(original_feature_list));
541 TEST_F(FeatureListTest, StoreAndRetrieveFeaturesFromSharedMemory) {
542 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
544 // Create some overrides.
545 feature_list->RegisterOverride(kFeatureOffByDefaultName,
546 FeatureList::OVERRIDE_ENABLE_FEATURE, nullptr);
547 feature_list->RegisterOverride(
548 kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE, nullptr);
549 feature_list->FinalizeInitialization();
551 // Create an allocator and store the overrides.
552 base::MappedReadOnlyRegion shm =
553 base::ReadOnlySharedMemoryRegion::Create(4 << 10);
554 WritableSharedPersistentMemoryAllocator allocator(std::move(shm.mapping), 1,
556 feature_list->AddFeaturesToAllocator(&allocator);
558 std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
560 // Check that the new feature list is empty.
561 EXPECT_FALSE(feature_list2->IsFeatureOverriddenFromCommandLine(
562 kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
563 EXPECT_FALSE(feature_list2->IsFeatureOverriddenFromCommandLine(
564 kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
566 feature_list2->InitializeFromSharedMemory(&allocator);
567 // Check that the new feature list now has 2 overrides.
568 EXPECT_TRUE(feature_list2->IsFeatureOverriddenFromCommandLine(
569 kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
570 EXPECT_TRUE(feature_list2->IsFeatureOverriddenFromCommandLine(
571 kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
574 TEST_F(FeatureListTest, StoreAndRetrieveAssociatedFeaturesFromSharedMemory) {
575 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
577 // Create some overrides.
578 FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
579 FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
580 feature_list->RegisterFieldTrialOverride(
581 kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial1);
582 feature_list->RegisterFieldTrialOverride(
583 kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial2);
584 feature_list->FinalizeInitialization();
586 // Create an allocator and store the overrides.
587 base::MappedReadOnlyRegion shm =
588 base::ReadOnlySharedMemoryRegion::Create(4 << 10);
589 WritableSharedPersistentMemoryAllocator allocator(std::move(shm.mapping), 1,
591 feature_list->AddFeaturesToAllocator(&allocator);
593 std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
594 feature_list2->InitializeFromSharedMemory(&allocator);
595 feature_list2->FinalizeInitialization();
597 // Check that the field trials are still associated.
598 FieldTrial* associated_trial1 =
599 feature_list2->GetAssociatedFieldTrial(kFeatureOnByDefault);
600 FieldTrial* associated_trial2 =
601 feature_list2->GetAssociatedFieldTrial(kFeatureOffByDefault);
602 EXPECT_EQ(associated_trial1, trial1);
603 EXPECT_EQ(associated_trial2, trial2);