feature_list_unittest.cc 35 KB

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