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