• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "base/feature_list.h"
6 
7 #include <stddef.h>
8 
9 #include <algorithm>
10 #include <utility>
11 
12 #include "base/format_macros.h"
13 #include "base/macros.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/metrics/field_trial.h"
16 #include "base/metrics/persistent_memory_allocator.h"
17 #include "base/strings/string_piece.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace base {
23 
24 namespace {
25 
26 constexpr char kFeatureOnByDefaultName[] = "OnByDefault";
27 struct Feature kFeatureOnByDefault {
28   kFeatureOnByDefaultName, FEATURE_ENABLED_BY_DEFAULT
29 };
30 
31 constexpr char kFeatureOffByDefaultName[] = "OffByDefault";
32 struct Feature kFeatureOffByDefault {
33   kFeatureOffByDefaultName, FEATURE_DISABLED_BY_DEFAULT
34 };
35 
SortFeatureListString(const std::string & feature_list)36 std::string SortFeatureListString(const std::string& feature_list) {
37   std::vector<base::StringPiece> features =
38       FeatureList::SplitFeatureListString(feature_list);
39   std::sort(features.begin(), features.end());
40   return JoinString(features, ",");
41 }
42 
43 }  // namespace
44 
45 class FeatureListTest : public testing::Test {
46  public:
FeatureListTest()47   FeatureListTest() : feature_list_(nullptr) {
48     RegisterFeatureListInstance(WrapUnique(new FeatureList));
49   }
~FeatureListTest()50   ~FeatureListTest() override { ClearFeatureListInstance(); }
51 
RegisterFeatureListInstance(std::unique_ptr<FeatureList> feature_list)52   void RegisterFeatureListInstance(std::unique_ptr<FeatureList> feature_list) {
53     FeatureList::ClearInstanceForTesting();
54     feature_list_ = feature_list.get();
55     FeatureList::SetInstance(std::move(feature_list));
56   }
ClearFeatureListInstance()57   void ClearFeatureListInstance() {
58     FeatureList::ClearInstanceForTesting();
59     feature_list_ = nullptr;
60   }
61 
feature_list()62   FeatureList* feature_list() { return feature_list_; }
63 
64  private:
65   // Weak. Owned by the FeatureList::SetInstance().
66   FeatureList* feature_list_;
67 
68   DISALLOW_COPY_AND_ASSIGN(FeatureListTest);
69 };
70 
TEST_F(FeatureListTest,DefaultStates)71 TEST_F(FeatureListTest, DefaultStates) {
72   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
73   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
74 }
75 
TEST_F(FeatureListTest,InitializeFromCommandLine)76 TEST_F(FeatureListTest, InitializeFromCommandLine) {
77   struct {
78     const char* enable_features;
79     const char* disable_features;
80     bool expected_feature_on_state;
81     bool expected_feature_off_state;
82   } test_cases[] = {
83       {"", "", true, false},
84       {"OffByDefault", "", true, true},
85       {"OffByDefault", "OnByDefault", false, true},
86       {"OnByDefault,OffByDefault", "", true, true},
87       {"", "OnByDefault,OffByDefault", false, false},
88       // In the case an entry is both, disable takes precedence.
89       {"OnByDefault", "OnByDefault,OffByDefault", false, false},
90   };
91 
92   for (size_t i = 0; i < arraysize(test_cases); ++i) {
93     const auto& test_case = test_cases[i];
94     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
95                                     test_case.enable_features,
96                                     test_case.disable_features));
97 
98     ClearFeatureListInstance();
99     std::unique_ptr<FeatureList> feature_list(new FeatureList);
100     feature_list->InitializeFromCommandLine(test_case.enable_features,
101                                             test_case.disable_features);
102     RegisterFeatureListInstance(std::move(feature_list));
103 
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 
TEST_F(FeatureListTest,CheckFeatureIdentity)113 TEST_F(FeatureListTest, CheckFeatureIdentity) {
114   // Tests that CheckFeatureIdentity() correctly detects when two different
115   // structs with the same feature name are passed to it.
116 
117   // Call it twice for each feature at the top of the file, since the first call
118   // makes it remember the entry and the second call will verify it.
119   EXPECT_TRUE(feature_list()->CheckFeatureIdentity(kFeatureOnByDefault));
120   EXPECT_TRUE(feature_list()->CheckFeatureIdentity(kFeatureOnByDefault));
121   EXPECT_TRUE(feature_list()->CheckFeatureIdentity(kFeatureOffByDefault));
122   EXPECT_TRUE(feature_list()->CheckFeatureIdentity(kFeatureOffByDefault));
123 
124   // Now, call it with a distinct struct for |kFeatureOnByDefaultName|, which
125   // should return false.
126   struct Feature kFeatureOnByDefault2 {
127     kFeatureOnByDefaultName, FEATURE_ENABLED_BY_DEFAULT
128   };
129   EXPECT_FALSE(feature_list()->CheckFeatureIdentity(kFeatureOnByDefault2));
130 }
131 
TEST_F(FeatureListTest,FieldTrialOverrides)132 TEST_F(FeatureListTest, FieldTrialOverrides) {
133   struct {
134     FeatureList::OverrideState trial1_state;
135     FeatureList::OverrideState trial2_state;
136   } test_cases[] = {
137       {FeatureList::OVERRIDE_DISABLE_FEATURE,
138        FeatureList::OVERRIDE_DISABLE_FEATURE},
139       {FeatureList::OVERRIDE_DISABLE_FEATURE,
140        FeatureList::OVERRIDE_ENABLE_FEATURE},
141       {FeatureList::OVERRIDE_ENABLE_FEATURE,
142        FeatureList::OVERRIDE_DISABLE_FEATURE},
143       {FeatureList::OVERRIDE_ENABLE_FEATURE,
144        FeatureList::OVERRIDE_ENABLE_FEATURE},
145   };
146 
147   FieldTrial::ActiveGroup active_group;
148   for (size_t i = 0; i < arraysize(test_cases); ++i) {
149     const auto& test_case = test_cases[i];
150     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
151 
152     ClearFeatureListInstance();
153 
154     FieldTrialList field_trial_list(nullptr);
155     std::unique_ptr<FeatureList> feature_list(new FeatureList);
156 
157     FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
158     FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
159     feature_list->RegisterFieldTrialOverride(kFeatureOnByDefaultName,
160                                              test_case.trial1_state, trial1);
161     feature_list->RegisterFieldTrialOverride(kFeatureOffByDefaultName,
162                                              test_case.trial2_state, trial2);
163     RegisterFeatureListInstance(std::move(feature_list));
164 
165     // Initially, neither trial should be active.
166     EXPECT_FALSE(FieldTrialList::IsTrialActive(trial1->trial_name()));
167     EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
168 
169     const bool expected_enabled_1 =
170         (test_case.trial1_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
171     EXPECT_EQ(expected_enabled_1, FeatureList::IsEnabled(kFeatureOnByDefault));
172     // The above should have activated |trial1|.
173     EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
174     EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
175 
176     const bool expected_enabled_2 =
177         (test_case.trial2_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
178     EXPECT_EQ(expected_enabled_2, FeatureList::IsEnabled(kFeatureOffByDefault));
179     // The above should have activated |trial2|.
180     EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
181     EXPECT_TRUE(FieldTrialList::IsTrialActive(trial2->trial_name()));
182   }
183 }
184 
TEST_F(FeatureListTest,FieldTrialAssociateUseDefault)185 TEST_F(FeatureListTest, FieldTrialAssociateUseDefault) {
186   FieldTrialList field_trial_list(nullptr);
187   std::unique_ptr<FeatureList> feature_list(new FeatureList);
188 
189   FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
190   FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
191   feature_list->RegisterFieldTrialOverride(
192       kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial1);
193   feature_list->RegisterFieldTrialOverride(
194       kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial2);
195   RegisterFeatureListInstance(std::move(feature_list));
196 
197   // Initially, neither trial should be active.
198   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial1->trial_name()));
199   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
200 
201   // Check the feature enabled state is its default.
202   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
203   // The above should have activated |trial1|.
204   EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
205   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
206 
207   // Check the feature enabled state is its default.
208   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
209   // The above should have activated |trial2|.
210   EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
211   EXPECT_TRUE(FieldTrialList::IsTrialActive(trial2->trial_name()));
212 }
213 
TEST_F(FeatureListTest,CommandLineTakesPrecedenceOverFieldTrial)214 TEST_F(FeatureListTest, CommandLineTakesPrecedenceOverFieldTrial) {
215   ClearFeatureListInstance();
216 
217   FieldTrialList field_trial_list(nullptr);
218   std::unique_ptr<FeatureList> feature_list(new FeatureList);
219 
220   // The feature is explicitly enabled on the command-line.
221   feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
222 
223   // But the FieldTrial would set the feature to disabled.
224   FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample2", "A");
225   feature_list->RegisterFieldTrialOverride(
226       kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
227   RegisterFeatureListInstance(std::move(feature_list));
228 
229   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
230   // Command-line should take precedence.
231   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
232   // Since the feature is on due to the command-line, and not as a result of the
233   // field trial, the field trial should not be activated (since the Associate*
234   // API wasn't used.)
235   EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
236 }
237 
TEST_F(FeatureListTest,IsFeatureOverriddenFromCommandLine)238 TEST_F(FeatureListTest, IsFeatureOverriddenFromCommandLine) {
239   ClearFeatureListInstance();
240 
241   FieldTrialList field_trial_list(nullptr);
242   std::unique_ptr<FeatureList> feature_list(new FeatureList);
243 
244   // No features are overridden from the command line yet
245   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
246       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
247   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
248       kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
249   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
250       kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
251   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
252       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
253 
254   // Now, enable |kFeatureOffByDefaultName| via the command-line.
255   feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
256 
257   // It should now be overridden for the enabled group.
258   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
259       kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
260   EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
261       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
262 
263   // Register a field trial to associate with the feature and ensure that the
264   // results are still the same.
265   feature_list->AssociateReportingFieldTrial(
266       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
267       FieldTrialList::CreateFieldTrial("Trial1", "A"));
268   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
269       kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
270   EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
271       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
272 
273   // Now, register a field trial to override |kFeatureOnByDefaultName| state
274   // and check that the function still returns false for that feature.
275   feature_list->RegisterFieldTrialOverride(
276       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
277       FieldTrialList::CreateFieldTrial("Trial2", "A"));
278   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
279       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
280   EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
281       kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
282   RegisterFeatureListInstance(std::move(feature_list));
283 
284   // Check the expected feature states for good measure.
285   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
286   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
287 }
288 
TEST_F(FeatureListTest,AssociateReportingFieldTrial)289 TEST_F(FeatureListTest, AssociateReportingFieldTrial) {
290   struct {
291     const char* enable_features;
292     const char* disable_features;
293     bool expected_enable_trial_created;
294     bool expected_disable_trial_created;
295   } test_cases[] = {
296       // If no enable/disable flags are specified, no trials should be created.
297       {"", "", false, false},
298       // Enabling the feature should result in the enable trial created.
299       {kFeatureOffByDefaultName, "", true, false},
300       // Disabling the feature should result in the disable trial created.
301       {"", kFeatureOffByDefaultName, false, true},
302   };
303 
304   const char kTrialName[] = "ForcingTrial";
305   const char kForcedOnGroupName[] = "ForcedOn";
306   const char kForcedOffGroupName[] = "ForcedOff";
307 
308   for (size_t i = 0; i < arraysize(test_cases); ++i) {
309     const auto& test_case = test_cases[i];
310     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
311                                     test_case.enable_features,
312                                     test_case.disable_features));
313 
314     ClearFeatureListInstance();
315 
316     FieldTrialList field_trial_list(nullptr);
317     std::unique_ptr<FeatureList> feature_list(new FeatureList);
318     feature_list->InitializeFromCommandLine(test_case.enable_features,
319                                             test_case.disable_features);
320 
321     FieldTrial* enable_trial = nullptr;
322     if (feature_list->IsFeatureOverriddenFromCommandLine(
323             kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE)) {
324       enable_trial = base::FieldTrialList::CreateFieldTrial(kTrialName,
325                                                             kForcedOnGroupName);
326       feature_list->AssociateReportingFieldTrial(
327           kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
328           enable_trial);
329     }
330     FieldTrial* disable_trial = nullptr;
331     if (feature_list->IsFeatureOverriddenFromCommandLine(
332             kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE)) {
333       disable_trial = base::FieldTrialList::CreateFieldTrial(
334           kTrialName, kForcedOffGroupName);
335       feature_list->AssociateReportingFieldTrial(
336           kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
337           disable_trial);
338     }
339     EXPECT_EQ(test_case.expected_enable_trial_created, enable_trial != nullptr);
340     EXPECT_EQ(test_case.expected_disable_trial_created,
341               disable_trial != nullptr);
342     RegisterFeatureListInstance(std::move(feature_list));
343 
344     EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
345     if (disable_trial) {
346       EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
347       EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
348       EXPECT_EQ(kForcedOffGroupName, disable_trial->group_name());
349     } else if (enable_trial) {
350       EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
351       EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
352       EXPECT_EQ(kForcedOnGroupName, enable_trial->group_name());
353     }
354   }
355 }
356 
TEST_F(FeatureListTest,GetFeatureOverrides)357 TEST_F(FeatureListTest, GetFeatureOverrides) {
358   ClearFeatureListInstance();
359   FieldTrialList field_trial_list(nullptr);
360   std::unique_ptr<FeatureList> feature_list(new FeatureList);
361   feature_list->InitializeFromCommandLine("A,X", "D");
362 
363   FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
364   feature_list->RegisterFieldTrialOverride(kFeatureOffByDefaultName,
365                                            FeatureList::OVERRIDE_ENABLE_FEATURE,
366                                            trial);
367 
368   RegisterFeatureListInstance(std::move(feature_list));
369 
370   std::string enable_features;
371   std::string disable_features;
372   FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
373                                                   &disable_features);
374   EXPECT_EQ("A,OffByDefault<Trial,X", SortFeatureListString(enable_features));
375   EXPECT_EQ("D", SortFeatureListString(disable_features));
376 
377   FeatureList::GetInstance()->GetCommandLineFeatureOverrides(&enable_features,
378                                                              &disable_features);
379   EXPECT_EQ("A,X", SortFeatureListString(enable_features));
380   EXPECT_EQ("D", SortFeatureListString(disable_features));
381 }
382 
TEST_F(FeatureListTest,GetFeatureOverrides_UseDefault)383 TEST_F(FeatureListTest, GetFeatureOverrides_UseDefault) {
384   ClearFeatureListInstance();
385   FieldTrialList field_trial_list(nullptr);
386   std::unique_ptr<FeatureList> feature_list(new FeatureList);
387   feature_list->InitializeFromCommandLine("A,X", "D");
388 
389   FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
390   feature_list->RegisterFieldTrialOverride(
391       kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial);
392 
393   RegisterFeatureListInstance(std::move(feature_list));
394 
395   std::string enable_features;
396   std::string disable_features;
397   FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
398                                                   &disable_features);
399   EXPECT_EQ("*OffByDefault<Trial,A,X", SortFeatureListString(enable_features));
400   EXPECT_EQ("D", SortFeatureListString(disable_features));
401 }
402 
TEST_F(FeatureListTest,GetFieldTrial)403 TEST_F(FeatureListTest, GetFieldTrial) {
404   ClearFeatureListInstance();
405   FieldTrialList field_trial_list(nullptr);
406   FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
407   std::unique_ptr<FeatureList> feature_list(new FeatureList);
408   feature_list->RegisterFieldTrialOverride(
409       kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial);
410   RegisterFeatureListInstance(std::move(feature_list));
411 
412   EXPECT_EQ(trial, FeatureList::GetFieldTrial(kFeatureOnByDefault));
413   EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kFeatureOffByDefault));
414 }
415 
TEST_F(FeatureListTest,InitializeFromCommandLine_WithFieldTrials)416 TEST_F(FeatureListTest, InitializeFromCommandLine_WithFieldTrials) {
417   ClearFeatureListInstance();
418   FieldTrialList field_trial_list(nullptr);
419   FieldTrialList::CreateFieldTrial("Trial", "Group");
420   std::unique_ptr<FeatureList> feature_list(new FeatureList);
421   feature_list->InitializeFromCommandLine("A,OffByDefault<Trial,X", "D");
422   RegisterFeatureListInstance(std::move(feature_list));
423 
424   EXPECT_FALSE(FieldTrialList::IsTrialActive("Trial"));
425   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
426   EXPECT_TRUE(FieldTrialList::IsTrialActive("Trial"));
427 }
428 
TEST_F(FeatureListTest,InitializeFromCommandLine_UseDefault)429 TEST_F(FeatureListTest, InitializeFromCommandLine_UseDefault) {
430   ClearFeatureListInstance();
431   FieldTrialList field_trial_list(nullptr);
432   FieldTrialList::CreateFieldTrial("T1", "Group");
433   FieldTrialList::CreateFieldTrial("T2", "Group");
434   std::unique_ptr<FeatureList> feature_list(new FeatureList);
435   feature_list->InitializeFromCommandLine(
436       "A,*OffByDefault<T1,*OnByDefault<T2,X", "D");
437   RegisterFeatureListInstance(std::move(feature_list));
438 
439   EXPECT_FALSE(FieldTrialList::IsTrialActive("T1"));
440   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
441   EXPECT_TRUE(FieldTrialList::IsTrialActive("T1"));
442 
443   EXPECT_FALSE(FieldTrialList::IsTrialActive("T2"));
444   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
445   EXPECT_TRUE(FieldTrialList::IsTrialActive("T2"));
446 }
447 
TEST_F(FeatureListTest,InitializeInstance)448 TEST_F(FeatureListTest, InitializeInstance) {
449   ClearFeatureListInstance();
450 
451   std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
452   FeatureList::SetInstance(std::move(feature_list));
453   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
454   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
455 
456   // Initialize from command line if we haven't yet.
457   FeatureList::InitializeInstance("", kFeatureOnByDefaultName);
458   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
459   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
460 
461   // Do not initialize from commandline if we have already.
462   FeatureList::InitializeInstance(kFeatureOffByDefaultName, "");
463   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
464   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
465 }
466 
TEST_F(FeatureListTest,UninitializedInstance_IsEnabledReturnsFalse)467 TEST_F(FeatureListTest, UninitializedInstance_IsEnabledReturnsFalse) {
468   ClearFeatureListInstance();
469   // This test case simulates the calling pattern found in code which does not
470   // explicitly initialize the features list.
471   // All IsEnabled() calls should return the default value in this scenario.
472   EXPECT_EQ(nullptr, FeatureList::GetInstance());
473   EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
474   EXPECT_EQ(nullptr, FeatureList::GetInstance());
475   EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
476 }
477 
TEST_F(FeatureListTest,StoreAndRetrieveFeaturesFromSharedMemory)478 TEST_F(FeatureListTest, StoreAndRetrieveFeaturesFromSharedMemory) {
479   std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
480 
481   // Create some overrides.
482   feature_list->RegisterOverride(kFeatureOffByDefaultName,
483                                  FeatureList::OVERRIDE_ENABLE_FEATURE, nullptr);
484   feature_list->RegisterOverride(
485       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE, nullptr);
486   feature_list->FinalizeInitialization();
487 
488   // Create an allocator and store the overrides.
489   std::unique_ptr<SharedMemory> shm(new SharedMemory());
490   shm->CreateAndMapAnonymous(4 << 10);
491   SharedPersistentMemoryAllocator allocator(std::move(shm), 1, "", false);
492   feature_list->AddFeaturesToAllocator(&allocator);
493 
494   std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
495 
496   // Check that the new feature list is empty.
497   EXPECT_FALSE(feature_list2->IsFeatureOverriddenFromCommandLine(
498       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
499   EXPECT_FALSE(feature_list2->IsFeatureOverriddenFromCommandLine(
500       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
501 
502   feature_list2->InitializeFromSharedMemory(&allocator);
503   // Check that the new feature list now has 2 overrides.
504   EXPECT_TRUE(feature_list2->IsFeatureOverriddenFromCommandLine(
505       kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
506   EXPECT_TRUE(feature_list2->IsFeatureOverriddenFromCommandLine(
507       kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
508 }
509 
TEST_F(FeatureListTest,StoreAndRetrieveAssociatedFeaturesFromSharedMemory)510 TEST_F(FeatureListTest, StoreAndRetrieveAssociatedFeaturesFromSharedMemory) {
511   FieldTrialList field_trial_list(nullptr);
512   std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
513 
514   // Create some overrides.
515   FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
516   FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
517   feature_list->RegisterFieldTrialOverride(
518       kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial1);
519   feature_list->RegisterFieldTrialOverride(
520       kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial2);
521   feature_list->FinalizeInitialization();
522 
523   // Create an allocator and store the overrides.
524   std::unique_ptr<SharedMemory> shm(new SharedMemory());
525   shm->CreateAndMapAnonymous(4 << 10);
526   SharedPersistentMemoryAllocator allocator(std::move(shm), 1, "", false);
527   feature_list->AddFeaturesToAllocator(&allocator);
528 
529   std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
530   feature_list2->InitializeFromSharedMemory(&allocator);
531   feature_list2->FinalizeInitialization();
532 
533   // Check that the field trials are still associated.
534   FieldTrial* associated_trial1 =
535       feature_list2->GetAssociatedFieldTrial(kFeatureOnByDefault);
536   FieldTrial* associated_trial2 =
537       feature_list2->GetAssociatedFieldTrial(kFeatureOffByDefault);
538   EXPECT_EQ(associated_trial1, trial1);
539   EXPECT_EQ(associated_trial2, trial2);
540 }
541 
542 }  // namespace base
543