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