Fix FullScreen crash in Webapp
[platform/framework/web/chromium-efl.git] / base / feature_list_unittest.cc
1 // Copyright 2015 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/feature_list.h"
6
7 #include <stddef.h>
8
9 #include <utility>
10 #include <vector>
11
12 #include "base/feature_list_buildflags.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/field_trial_param_associator.h"
17 #include "base/metrics/persistent_memory_allocator.h"
18 #include "base/ranges/algorithm.h"
19 #include "base/strings/strcat.h"
20 #include "base/strings/string_piece.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/test/scoped_feature_list.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace base {
27
28 namespace {
29
30 constexpr char kFeatureOnByDefaultName[] = "OnByDefault";
31 CONSTINIT Feature kFeatureOnByDefault(kFeatureOnByDefaultName,
32                                       FEATURE_ENABLED_BY_DEFAULT);
33
34 constexpr char kFeatureOffByDefaultName[] = "OffByDefault";
35 CONSTINIT Feature kFeatureOffByDefault(kFeatureOffByDefaultName,
36                                        FEATURE_DISABLED_BY_DEFAULT);
37
38 std::string SortFeatureListString(const std::string& feature_list) {
39   std::vector<base::StringPiece> features =
40       FeatureList::SplitFeatureListString(feature_list);
41   ranges::sort(features);
42   return JoinString(features, ",");
43 }
44
45 }  // namespace
46
47 class FeatureListTest : public testing::Test {
48  public:
49   FeatureListTest() {
50     // Provide an empty FeatureList to each test by default.
51     scoped_feature_list_.InitWithFeatureList(std::make_unique<FeatureList>());
52   }
53   FeatureListTest(const FeatureListTest&) = delete;
54   FeatureListTest& operator=(const FeatureListTest&) = delete;
55   ~FeatureListTest() override = default;
56
57  private:
58   test::ScopedFeatureList scoped_feature_list_;
59 };
60
61 TEST_F(FeatureListTest, DefaultStates) {
62   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
63   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
64 }
65
66 TEST_F(FeatureListTest, InitializeFromCommandLine) {
67   struct {
68     const char* enable_features;
69     const char* disable_features;
70     bool expected_feature_on_state;
71     bool expected_feature_off_state;
72   } test_cases[] = {
73       {"", "", true, false},
74       {"OffByDefault", "", true, true},
75       {"OffByDefault", "OnByDefault", false, true},
76       {"OnByDefault,OffByDefault", "", true, true},
77       {"", "OnByDefault,OffByDefault", false, false},
78       // In the case an entry is both, disable takes precedence.
79       {"OnByDefault", "OnByDefault,OffByDefault", false, false},
80   };
81
82   for (size_t i = 0; i < std::size(test_cases); ++i) {
83     const auto& test_case = test_cases[i];
84     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
85                                     test_case.enable_features,
86                                     test_case.disable_features));
87
88     auto feature_list = std::make_unique<FeatureList>();
89     feature_list->InitializeFromCommandLine(test_case.enable_features,
90                                             test_case.disable_features);
91     test::ScopedFeatureList scoped_feature_list;
92     scoped_feature_list.InitWithFeatureList(std::move(feature_list));
93
94     EXPECT_EQ(test_case.expected_feature_on_state,
95               FeatureList::IsEnabled(kFeatureOnByDefault))
96         << i;
97     EXPECT_EQ(test_case.expected_feature_off_state,
98               FeatureList::IsEnabled(kFeatureOffByDefault))
99         << i;
100
101     // Reading the state of each feature again will pull it from their
102     // respective caches instead of performing the full lookup, which should
103     // yield the same result.
104     EXPECT_EQ(test_case.expected_feature_on_state,
105               FeatureList::IsEnabled(kFeatureOnByDefault))
106         << i;
107     EXPECT_EQ(test_case.expected_feature_off_state,
108               FeatureList::IsEnabled(kFeatureOffByDefault))
109         << i;
110   }
111 }
112
113 TEST_F(FeatureListTest, InitializeFromCommandLineWithFeatureParams) {
114   struct {
115     const std::string enable_features;
116     const std::string expected_field_trial_created;
117     const std::map<std::string, std::string> expected_feature_params;
118   } test_cases[] = {
119       {"Feature:x/100/y/test", "StudyFeature", {{"x", "100"}, {"y", "test"}}},
120       {"Feature<Trial1:x/200/y/123", "Trial1", {{"x", "200"}, {"y", "123"}}},
121       {"Feature<Trial2.Group2:x/test/y/uma/z/ukm",
122        "Trial2",
123        {{"x", "test"}, {"y", "uma"}, {"z", "ukm"}}},
124   };
125
126   // Clear global state so that repeated runs of this test don't flake.
127   // When https://crrev.com/c/3694674 is submitted, we should be able to remove
128   // this.
129   base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
130
131   static BASE_FEATURE(kFeature, "Feature", FEATURE_DISABLED_BY_DEFAULT);
132   for (const auto& test_case : test_cases) {
133     SCOPED_TRACE(test_case.enable_features);
134
135     auto feature_list = std::make_unique<FeatureList>();
136     feature_list->InitializeFromCommandLine(test_case.enable_features, "");
137     test::ScopedFeatureList scoped_feature_list;
138     scoped_feature_list.InitWithFeatureList(std::move(feature_list));
139
140     EXPECT_TRUE(FeatureList::IsEnabled(kFeature));
141     EXPECT_TRUE(
142         FieldTrialList::IsTrialActive(test_case.expected_field_trial_created));
143     std::map<std::string, std::string> actual_params;
144     EXPECT_TRUE(GetFieldTrialParamsByFeature(kFeature, &actual_params));
145     EXPECT_EQ(test_case.expected_feature_params, actual_params);
146   }
147 }
148
149 TEST_F(FeatureListTest, CheckFeatureIdentity) {
150   // Tests that CheckFeatureIdentity() correctly detects when two different
151   // structs with the same feature name are passed to it.
152
153   test::ScopedFeatureList scoped_feature_list;
154   scoped_feature_list.InitWithFeatureList(std::make_unique<FeatureList>());
155   FeatureList* feature_list = FeatureList::GetInstance();
156
157   // Call it twice for each feature at the top of the file, since the first call
158   // makes it remember the entry and the second call will verify it.
159   EXPECT_TRUE(feature_list->CheckFeatureIdentity(kFeatureOnByDefault));
160   EXPECT_TRUE(feature_list->CheckFeatureIdentity(kFeatureOnByDefault));
161   EXPECT_TRUE(feature_list->CheckFeatureIdentity(kFeatureOffByDefault));
162   EXPECT_TRUE(feature_list->CheckFeatureIdentity(kFeatureOffByDefault));
163
164   // Now, call it with a distinct struct for |kFeatureOnByDefaultName|, which
165   // should return false.
166   struct Feature kFeatureOnByDefault2 {
167     kFeatureOnByDefaultName, FEATURE_ENABLED_BY_DEFAULT
168   };
169   EXPECT_FALSE(feature_list->CheckFeatureIdentity(kFeatureOnByDefault2));
170 }
171
172 TEST_F(FeatureListTest, FieldTrialOverrides) {
173   struct {
174     FeatureList::OverrideState trial1_state;
175     FeatureList::OverrideState trial2_state;
176   } test_cases[] = {
177       {FeatureList::OVERRIDE_DISABLE_FEATURE,
178        FeatureList::OVERRIDE_DISABLE_FEATURE},
179       {FeatureList::OVERRIDE_DISABLE_FEATURE,
180        FeatureList::OVERRIDE_ENABLE_FEATURE},
181       {FeatureList::OVERRIDE_ENABLE_FEATURE,
182        FeatureList::OVERRIDE_DISABLE_FEATURE},
183       {FeatureList::OVERRIDE_ENABLE_FEATURE,
184        FeatureList::OVERRIDE_ENABLE_FEATURE},
185   };
186
187   FieldTrial::ActiveGroup active_group;
188   for (size_t i = 0; i < std::size(test_cases); ++i) {
189     const auto& test_case = test_cases[i];
190     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
191
192     test::ScopedFeatureList outer_scope;
193     outer_scope.InitWithEmptyFeatureAndFieldTrialLists();
194
195     auto feature_list = std::make_unique<FeatureList>();
196
197     FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
198     FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
199     feature_list->RegisterFieldTrialOverride(kFeatureOnByDefaultName,
200                                              test_case.trial1_state, trial1);
201     feature_list->RegisterFieldTrialOverride(kFeatureOffByDefaultName,
202                                              test_case.trial2_state, trial2);
203     test::ScopedFeatureList scoped_feature_list;
204     scoped_feature_list.InitWithFeatureList(std::move(feature_list));
205
206     // Initially, neither trial should be active.
207     EXPECT_FALSE(FieldTrialList::IsTrialActive(trial1->trial_name()));
208     EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
209
210     const bool expected_enabled_1 =
211         (test_case.trial1_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
212     EXPECT_EQ(expected_enabled_1, FeatureList::IsEnabled(kFeatureOnByDefault));
213     // The above should have activated |trial1|.
214     EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
215     EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
216
217     const bool expected_enabled_2 =
218         (test_case.trial2_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
219     EXPECT_EQ(expected_enabled_2, FeatureList::IsEnabled(kFeatureOffByDefault));
220     // The above should have activated |trial2|.
221     EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
222     EXPECT_TRUE(FieldTrialList::IsTrialActive(trial2->trial_name()));
223   }
224 }
225
226 TEST_F(FeatureListTest, FieldTrialAssociateUseDefault) {
227   auto feature_list = std::make_unique<FeatureList>();
228
229   FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
230   FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
231   feature_list->RegisterFieldTrialOverride(
232       kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial1);
233   feature_list->RegisterFieldTrialOverride(
234       kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial2);
235   test::ScopedFeatureList scoped_feature_list;
236   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
237
238   // Initially, neither trial should be active.
239   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial1->trial_name()));
240   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
241
242   // Check the feature enabled state is its default.
243   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
244   // The above should have activated |trial1|.
245   EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
246   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
247
248   // Check the feature enabled state is its default.
249   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
250   // The above should have activated |trial2|.
251   EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
252   EXPECT_TRUE(FieldTrialList::IsTrialActive(trial2->trial_name()));
253 }
254
255 TEST_F(FeatureListTest, CommandLineEnableTakesPrecedenceOverFieldTrial) {
256   auto feature_list = std::make_unique<FeatureList>();
257
258   // The feature is explicitly enabled on the command-line.
259   feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
260
261   // But the FieldTrial would set the feature to disabled.
262   FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample2", "A");
263   feature_list->RegisterFieldTrialOverride(
264       kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
265   test::ScopedFeatureList scoped_feature_list;
266   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
267
268   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
269   // Command-line should take precedence.
270   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
271   // Since the feature is on due to the command-line, and not as a result of the
272   // field trial, the field trial should not be activated (since the Associate*
273   // API wasn't used.)
274   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
275 }
276
277 TEST_F(FeatureListTest, CommandLineDisableTakesPrecedenceOverFieldTrial) {
278   auto feature_list = std::make_unique<FeatureList>();
279
280   // The feature is explicitly disabled on the command-line.
281   feature_list->InitializeFromCommandLine("", kFeatureOffByDefaultName);
282
283   // But the FieldTrial would set the feature to enabled.
284   FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample2", "A");
285   feature_list->RegisterFieldTrialOverride(
286       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
287   test::ScopedFeatureList scoped_feature_list;
288   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
289
290   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
291   // Command-line should take precedence.
292   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
293   // Since the feature is on due to the command-line, and not as a result of the
294   // field trial, the field trial should not be activated (since the Associate*
295   // API wasn't used.)
296   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
297 }
298
299 TEST_F(FeatureListTest, IsFeatureOverriddenFromFieldTrial) {
300   auto feature_list = std::make_unique<FeatureList>();
301
302   // No features are overridden from the field trails yet.
303   EXPECT_FALSE(feature_list->IsFeatureOverridden(kFeatureOnByDefaultName));
304   EXPECT_FALSE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
305
306   // Now, register a field trial to override |kFeatureOnByDefaultName| state
307   // and check that the function still returns false for that feature.
308   feature_list->RegisterFieldTrialOverride(
309       kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT,
310       FieldTrialList::CreateFieldTrial("Trial1", "A"));
311   feature_list->RegisterFieldTrialOverride(
312       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
313       FieldTrialList::CreateFieldTrial("Trial2", "A"));
314   EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOnByDefaultName));
315   EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
316
317   test::ScopedFeatureList scoped_feature_list;
318   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
319   // Check the expected feature states for good measure.
320   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
321   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
322 }
323
324 TEST_F(FeatureListTest, IsFeatureOverriddenFromCommandLine) {
325   auto feature_list = std::make_unique<FeatureList>();
326
327   // No features are overridden from the command line yet
328   EXPECT_FALSE(feature_list->IsFeatureOverridden(kFeatureOnByDefaultName));
329   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
330       kFeatureOnByDefaultName));
331   EXPECT_FALSE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
332   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
333       kFeatureOffByDefaultName));
334   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
335       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
336   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
337       kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
338   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
339       kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
340   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
341       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
342
343   // Now, enable |kFeatureOffByDefaultName| via the command-line.
344   feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
345
346   // It should now be overridden for the enabled group.
347   EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
348   EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
349       kFeatureOffByDefaultName));
350   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
351       kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
352   EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
353       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
354
355   // Register a field trial to associate with the feature and ensure that the
356   // results are still the same.
357   feature_list->AssociateReportingFieldTrial(
358       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
359       FieldTrialList::CreateFieldTrial("Trial1", "A"));
360   EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOffByDefaultName));
361   EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
362       kFeatureOffByDefaultName));
363   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
364       kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
365   EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
366       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
367
368   // Now, register a field trial to override |kFeatureOnByDefaultName| state
369   // and check that the function still returns false for that feature.
370   feature_list->RegisterFieldTrialOverride(
371       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
372       FieldTrialList::CreateFieldTrial("Trial2", "A"));
373   EXPECT_TRUE(feature_list->IsFeatureOverridden(kFeatureOnByDefaultName));
374   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
375       kFeatureOnByDefaultName));
376   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
377       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
378   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
379       kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
380   test::ScopedFeatureList scoped_feature_list;
381   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
382
383   // Check the expected feature states for good measure.
384   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
385   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
386 }
387
388 TEST_F(FeatureListTest, AssociateReportingFieldTrial) {
389   struct {
390     const char* enable_features;
391     const char* disable_features;
392     bool expected_enable_trial_created;
393     bool expected_disable_trial_created;
394   } test_cases[] = {
395       // If no enable/disable flags are specified, no trials should be created.
396       {"", "", false, false},
397       // Enabling the feature should result in the enable trial created.
398       {kFeatureOffByDefaultName, "", true, false},
399       // Disabling the feature should result in the disable trial created.
400       {"", kFeatureOffByDefaultName, false, true},
401   };
402
403   const char kTrialName[] = "ForcingTrial";
404   const char kForcedOnGroupName[] = "ForcedOn";
405   const char kForcedOffGroupName[] = "ForcedOff";
406
407   for (size_t i = 0; i < std::size(test_cases); ++i) {
408     const auto& test_case = test_cases[i];
409     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
410                                     test_case.enable_features,
411                                     test_case.disable_features));
412
413     test::ScopedFeatureList outer_scope;
414     outer_scope.InitWithEmptyFeatureAndFieldTrialLists();
415
416     auto feature_list = std::make_unique<FeatureList>();
417     feature_list->InitializeFromCommandLine(test_case.enable_features,
418                                             test_case.disable_features);
419
420     FieldTrial* enable_trial = nullptr;
421     if (feature_list->IsFeatureOverriddenFromCommandLine(
422             kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE)) {
423       enable_trial = base::FieldTrialList::CreateFieldTrial(kTrialName,
424                                                             kForcedOnGroupName);
425       feature_list->AssociateReportingFieldTrial(
426           kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
427           enable_trial);
428     }
429     FieldTrial* disable_trial = nullptr;
430     if (feature_list->IsFeatureOverriddenFromCommandLine(
431             kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE)) {
432       disable_trial = base::FieldTrialList::CreateFieldTrial(
433           kTrialName, kForcedOffGroupName);
434       feature_list->AssociateReportingFieldTrial(
435           kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
436           disable_trial);
437     }
438     EXPECT_EQ(test_case.expected_enable_trial_created, enable_trial != nullptr);
439     EXPECT_EQ(test_case.expected_disable_trial_created,
440               disable_trial != nullptr);
441     test::ScopedFeatureList scoped_feature_list;
442     scoped_feature_list.InitWithFeatureList(std::move(feature_list));
443
444     EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
445     if (disable_trial) {
446       EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
447       EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
448       EXPECT_EQ(kForcedOffGroupName, disable_trial->group_name());
449     } else if (enable_trial) {
450       EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
451       EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
452       EXPECT_EQ(kForcedOnGroupName, enable_trial->group_name());
453     }
454   }
455 }
456
457 TEST_F(FeatureListTest, RegisterExtraFeatureOverrides) {
458   auto feature_list = std::make_unique<FeatureList>();
459   std::vector<FeatureList::FeatureOverrideInfo> overrides;
460   overrides.push_back({std::cref(kFeatureOnByDefault),
461                        FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE});
462   overrides.push_back({std::cref(kFeatureOffByDefault),
463                        FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE});
464   feature_list->RegisterExtraFeatureOverrides(std::move(overrides));
465   test::ScopedFeatureList scoped_feature_list;
466   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
467
468   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
469   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
470 }
471
472 TEST_F(FeatureListTest, InitializeFromCommandLineThenRegisterExtraOverrides) {
473   auto feature_list = std::make_unique<FeatureList>();
474   feature_list->InitializeFromCommandLine(kFeatureOnByDefaultName,
475                                           kFeatureOffByDefaultName);
476   std::vector<FeatureList::FeatureOverrideInfo> overrides;
477   overrides.push_back({std::cref(kFeatureOnByDefault),
478                        FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE});
479   overrides.push_back({std::cref(kFeatureOffByDefault),
480                        FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE});
481   feature_list->RegisterExtraFeatureOverrides(std::move(overrides));
482   test::ScopedFeatureList scoped_feature_list;
483   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
484
485   // The InitializeFromCommandLine supersedes the RegisterExtraFeatureOverrides
486   // because it was called first.
487   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
488   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
489
490   std::string enable_features;
491   std::string disable_features;
492   FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
493                                                   &disable_features);
494   EXPECT_EQ(kFeatureOnByDefaultName, SortFeatureListString(enable_features));
495   EXPECT_EQ(kFeatureOffByDefaultName, SortFeatureListString(disable_features));
496 }
497
498 TEST_F(FeatureListTest, GetFeatureOverrides) {
499   auto feature_list = std::make_unique<FeatureList>();
500   feature_list->InitializeFromCommandLine("A,X", "D");
501
502   Feature feature_b = {"B", FEATURE_ENABLED_BY_DEFAULT};
503   Feature feature_c = {"C", FEATURE_DISABLED_BY_DEFAULT};
504   std::vector<FeatureList::FeatureOverrideInfo> overrides;
505   overrides.push_back({std::cref(feature_b),
506                        FeatureList::OverrideState::OVERRIDE_DISABLE_FEATURE});
507   overrides.push_back({std::cref(feature_c),
508                        FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE});
509   feature_list->RegisterExtraFeatureOverrides(std::move(overrides));
510
511   FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
512   feature_list->RegisterFieldTrialOverride(kFeatureOffByDefaultName,
513                                            FeatureList::OVERRIDE_ENABLE_FEATURE,
514                                            trial);
515
516   test::ScopedFeatureList scoped_feature_list;
517   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
518
519   std::string enable_features;
520   std::string disable_features;
521   FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
522                                                   &disable_features);
523   EXPECT_EQ("A,C,OffByDefault<Trial,X", SortFeatureListString(enable_features));
524   EXPECT_EQ("B,D", SortFeatureListString(disable_features));
525
526   FeatureList::GetInstance()->GetCommandLineFeatureOverrides(&enable_features,
527                                                              &disable_features);
528   EXPECT_EQ("A,C,X", SortFeatureListString(enable_features));
529   EXPECT_EQ("B,D", SortFeatureListString(disable_features));
530 }
531
532 TEST_F(FeatureListTest, GetFeatureOverrides_UseDefault) {
533   auto feature_list = std::make_unique<FeatureList>();
534   feature_list->InitializeFromCommandLine("A,X", "D");
535
536   FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
537   feature_list->RegisterFieldTrialOverride(
538       kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial);
539
540   test::ScopedFeatureList scoped_feature_list;
541   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
542
543   std::string enable_features;
544   std::string disable_features;
545   FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
546                                                   &disable_features);
547   EXPECT_EQ("*OffByDefault<Trial,A,X", SortFeatureListString(enable_features));
548   EXPECT_EQ("D", SortFeatureListString(disable_features));
549 }
550
551 TEST_F(FeatureListTest, GetFieldTrial) {
552   FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
553   auto feature_list = std::make_unique<FeatureList>();
554   feature_list->RegisterFieldTrialOverride(
555       kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial);
556   test::ScopedFeatureList scoped_feature_list;
557   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
558
559   EXPECT_EQ(trial, FeatureList::GetFieldTrial(kFeatureOnByDefault));
560   EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kFeatureOffByDefault));
561 }
562
563 TEST_F(FeatureListTest, InitializeFromCommandLine_WithFieldTrials) {
564   FieldTrialList::CreateFieldTrial("Trial", "Group");
565   auto feature_list = std::make_unique<FeatureList>();
566   feature_list->InitializeFromCommandLine("A,OffByDefault<Trial,X", "D");
567   test::ScopedFeatureList scoped_feature_list;
568   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
569
570   EXPECT_FALSE(FieldTrialList::IsTrialActive("Trial"));
571   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
572   EXPECT_TRUE(FieldTrialList::IsTrialActive("Trial"));
573 }
574
575 TEST_F(FeatureListTest, InitializeFromCommandLine_UseDefault) {
576   FieldTrialList::CreateFieldTrial("T1", "Group");
577   FieldTrialList::CreateFieldTrial("T2", "Group");
578   auto feature_list = std::make_unique<FeatureList>();
579   feature_list->InitializeFromCommandLine(
580       "A,*OffByDefault<T1,*OnByDefault<T2,X", "D");
581   test::ScopedFeatureList scoped_feature_list;
582   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
583
584   EXPECT_FALSE(FieldTrialList::IsTrialActive("T1"));
585   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
586   EXPECT_TRUE(FieldTrialList::IsTrialActive("T1"));
587
588   EXPECT_FALSE(FieldTrialList::IsTrialActive("T2"));
589   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
590   EXPECT_TRUE(FieldTrialList::IsTrialActive("T2"));
591 }
592
593 TEST_F(FeatureListTest, InitializeInstance) {
594   std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
595   test::ScopedFeatureList scoped_feature_list;
596   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
597
598   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
599   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
600
601   // Initialize from command line if we haven't yet.
602   FeatureList::InitializeInstance("", kFeatureOnByDefaultName);
603   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
604   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
605
606   // Do not initialize from commandline if we have already.
607   FeatureList::InitializeInstance(kFeatureOffByDefaultName, "");
608   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
609   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
610 }
611
612 TEST_F(FeatureListTest, UninitializedInstance_IsEnabledReturnsFalse) {
613   std::unique_ptr<FeatureList> original_feature_list =
614       FeatureList::ClearInstanceForTesting();
615
616   // This test case simulates the calling pattern found in code which does not
617   // explicitly initialize the features list.
618   // All IsEnabled() calls should return the default value in this scenario.
619   EXPECT_EQ(nullptr, FeatureList::GetInstance());
620   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
621   EXPECT_EQ(nullptr, FeatureList::GetInstance());
622   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
623
624   if (original_feature_list)
625     FeatureList::RestoreInstanceForTesting(std::move(original_feature_list));
626 }
627
628 TEST_F(FeatureListTest, StoreAndRetrieveFeaturesFromSharedMemory) {
629   std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
630
631   // Create some overrides.
632   feature_list->RegisterOverride(kFeatureOffByDefaultName,
633                                  FeatureList::OVERRIDE_ENABLE_FEATURE, nullptr);
634   feature_list->RegisterOverride(
635       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE, nullptr);
636   feature_list->FinalizeInitialization();
637
638   // Create an allocator and store the overrides.
639   base::MappedReadOnlyRegion shm =
640       base::ReadOnlySharedMemoryRegion::Create(4 << 10);
641   WritableSharedPersistentMemoryAllocator allocator(std::move(shm.mapping), 1,
642                                                     "");
643   feature_list->AddFeaturesToAllocator(&allocator);
644
645   std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
646
647   // Check that the new feature list is empty.
648   EXPECT_FALSE(feature_list2->IsFeatureOverriddenFromCommandLine(
649       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
650   EXPECT_FALSE(feature_list2->IsFeatureOverriddenFromCommandLine(
651       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
652
653   feature_list2->InitializeFromSharedMemory(&allocator);
654   // Check that the new feature list now has 2 overrides.
655   EXPECT_TRUE(feature_list2->IsFeatureOverriddenFromCommandLine(
656       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
657   EXPECT_TRUE(feature_list2->IsFeatureOverriddenFromCommandLine(
658       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
659 }
660
661 TEST_F(FeatureListTest, StoreAndRetrieveAssociatedFeaturesFromSharedMemory) {
662   std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
663
664   // Create some overrides.
665   FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
666   FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
667   feature_list->RegisterFieldTrialOverride(
668       kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial1);
669   feature_list->RegisterFieldTrialOverride(
670       kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial2);
671   feature_list->FinalizeInitialization();
672
673   // Create an allocator and store the overrides.
674   base::MappedReadOnlyRegion shm =
675       base::ReadOnlySharedMemoryRegion::Create(4 << 10);
676   WritableSharedPersistentMemoryAllocator allocator(std::move(shm.mapping), 1,
677                                                     "");
678   feature_list->AddFeaturesToAllocator(&allocator);
679
680   std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
681   feature_list2->InitializeFromSharedMemory(&allocator);
682   feature_list2->FinalizeInitialization();
683
684   // Check that the field trials are still associated.
685   FieldTrial* associated_trial1 =
686       feature_list2->GetAssociatedFieldTrial(kFeatureOnByDefault);
687   FieldTrial* associated_trial2 =
688       feature_list2->GetAssociatedFieldTrial(kFeatureOffByDefault);
689   EXPECT_EQ(associated_trial1, trial1);
690   EXPECT_EQ(associated_trial2, trial2);
691 }
692
693 #if BUILDFLAG(ENABLE_BANNED_BASE_FEATURE_PREFIX) && \
694     defined(GTEST_HAS_DEATH_TEST)
695 using FeatureListDeathTest = FeatureListTest;
696 TEST_F(FeatureListDeathTest, DiesWithBadFeatureName) {
697   EXPECT_DEATH(
698       Feature(
699           StrCat({BUILDFLAG(BANNED_BASE_FEATURE_PREFIX), "MyFeature"}).c_str(),
700           FEATURE_DISABLED_BY_DEFAULT),
701       StrCat({"Invalid feature name ", BUILDFLAG(BANNED_BASE_FEATURE_PREFIX),
702               "MyFeature"}));
703 }
704 #endif  // BUILDFLAG(ENABLE_BANNED_BASE_FEATURE_PREFIX) &&
705         // defined(GTEST_HAS_DEATH_TEST)
706
707 TEST(FeatureListAccessorTest, DefaultStates) {
708   test::ScopedFeatureList scoped_feature_list;
709   auto feature_list = std::make_unique<FeatureList>();
710   auto feature_list_accessor = feature_list->ConstructAccessor();
711   scoped_feature_list.InitWithFeatureList(std::move(feature_list));
712
713   EXPECT_EQ(feature_list_accessor->GetOverrideStateByFeatureName(
714                 kFeatureOnByDefault.name),
715             FeatureList::OVERRIDE_USE_DEFAULT);
716   EXPECT_EQ(feature_list_accessor->GetOverrideStateByFeatureName(
717                 kFeatureOffByDefault.name),
718             FeatureList::OVERRIDE_USE_DEFAULT);
719 }
720
721 TEST(FeatureListAccessorTest, InitializeFromCommandLine) {
722   struct {
723     const char* enable_features;
724     const char* disable_features;
725     FeatureList::OverrideState expected_feature_on_state;
726     FeatureList::OverrideState expected_feature_off_state;
727   } test_cases[] = {
728       {"", "", FeatureList::OVERRIDE_USE_DEFAULT,
729        FeatureList::OVERRIDE_USE_DEFAULT},
730       {"OffByDefault", "", FeatureList::OVERRIDE_USE_DEFAULT,
731        FeatureList::OVERRIDE_ENABLE_FEATURE},
732       {"OffByDefault", "OnByDefault", FeatureList::OVERRIDE_DISABLE_FEATURE,
733        FeatureList::OVERRIDE_ENABLE_FEATURE},
734       {"OnByDefault,OffByDefault", "", FeatureList::OVERRIDE_ENABLE_FEATURE,
735        FeatureList::OVERRIDE_ENABLE_FEATURE},
736       {"", "OnByDefault,OffByDefault", FeatureList::OVERRIDE_DISABLE_FEATURE,
737        FeatureList::OVERRIDE_DISABLE_FEATURE},
738       // In the case an entry is both, disable takes precedence.
739       {"OnByDefault", "OnByDefault,OffByDefault",
740        FeatureList::OVERRIDE_DISABLE_FEATURE,
741        FeatureList::OVERRIDE_DISABLE_FEATURE},
742   };
743
744   for (size_t i = 0; i < std::size(test_cases); ++i) {
745     const auto& test_case = test_cases[i];
746     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
747                                     test_case.enable_features,
748                                     test_case.disable_features));
749
750     test::ScopedFeatureList scoped_feature_list;
751     auto feature_list = std::make_unique<FeatureList>();
752     auto feature_list_accessor = feature_list->ConstructAccessor();
753     feature_list->InitializeFromCommandLine(test_case.enable_features,
754                                             test_case.disable_features);
755     scoped_feature_list.InitWithFeatureList(std::move(feature_list));
756
757     EXPECT_EQ(test_case.expected_feature_on_state,
758               feature_list_accessor->GetOverrideStateByFeatureName(
759                   kFeatureOnByDefault.name))
760         << i;
761     EXPECT_EQ(test_case.expected_feature_off_state,
762               feature_list_accessor->GetOverrideStateByFeatureName(
763                   kFeatureOffByDefault.name))
764         << i;
765   }
766 }
767
768 TEST(FeatureListAccessorTest, InitializeFromCommandLineWithFeatureParams) {
769   struct {
770     const std::string enable_features;
771     const std::map<std::string, std::string> expected_feature_params;
772   } test_cases[] = {
773       {"Feature:x/100/y/test", {{"x", "100"}, {"y", "test"}}},
774       {"Feature<Trial:asdf/ghjkl/y/123", {{"asdf", "ghjkl"}, {"y", "123"}}},
775   };
776
777   // Clear global state so that repeated runs of this test don't flake.
778   // When https://crrev.com/c/3694674 is submitted, we should be able to remove
779   // this.
780   base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
781
782   for (size_t i = 0; i < std::size(test_cases); ++i) {
783     const auto& test_case = test_cases[i];
784     SCOPED_TRACE(test_case.enable_features);
785
786     test::ScopedFeatureList scoped_feature_list;
787     auto feature_list = std::make_unique<FeatureList>();
788     auto feature_list_accessor = feature_list->ConstructAccessor();
789     feature_list->InitializeFromCommandLine(test_case.enable_features, "");
790     scoped_feature_list.InitWithFeatureList(std::move(feature_list));
791
792     EXPECT_EQ(FeatureList::OVERRIDE_ENABLE_FEATURE,
793               feature_list_accessor->GetOverrideStateByFeatureName("Feature"))
794         << i;
795     std::map<std::string, std::string> actual_params;
796     EXPECT_TRUE(feature_list_accessor->GetParamsByFeatureName("Feature",
797                                                               &actual_params))
798         << i;
799     EXPECT_EQ(test_case.expected_feature_params, actual_params) << i;
800   }
801 }
802
803 }  // namespace base