scoped_feature_list_unittest.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. // Copyright 2017 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/test/scoped_feature_list.h"
  5. #include <map>
  6. #include <string>
  7. #include <utility>
  8. #include "base/metrics/field_trial.h"
  9. #include "base/metrics/field_trial_params.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. namespace base {
  12. namespace test {
  13. namespace {
  14. const Feature kTestFeature1{"TestFeature1", FEATURE_DISABLED_BY_DEFAULT};
  15. const Feature kTestFeature2{"TestFeature2", FEATURE_DISABLED_BY_DEFAULT};
  16. void ExpectFeatures(const std::string& enabled_features,
  17. const std::string& disabled_features) {
  18. FeatureList* list = FeatureList::GetInstance();
  19. std::string actual_enabled_features;
  20. std::string actual_disabled_features;
  21. list->GetFeatureOverrides(&actual_enabled_features,
  22. &actual_disabled_features);
  23. EXPECT_EQ(enabled_features, actual_enabled_features);
  24. EXPECT_EQ(disabled_features, actual_disabled_features);
  25. }
  26. std::string GetActiveFieldTrialGroupName(const std::string trial_name) {
  27. FieldTrial::ActiveGroups groups;
  28. FieldTrialList::GetActiveFieldTrialGroups(&groups);
  29. for (const auto& group : groups) {
  30. if (group.trial_name == trial_name)
  31. return group.group_name;
  32. }
  33. return std::string();
  34. }
  35. } // namespace
  36. class ScopedFeatureListTest : public testing::Test {
  37. public:
  38. ScopedFeatureListTest() {
  39. // Clear default feature list.
  40. std::unique_ptr<FeatureList> feature_list(new FeatureList);
  41. feature_list->InitializeFromCommandLine(std::string(), std::string());
  42. original_feature_list_ = FeatureList::ClearInstanceForTesting();
  43. FeatureList::SetInstance(std::move(feature_list));
  44. }
  45. ScopedFeatureListTest(const ScopedFeatureListTest&) = delete;
  46. ScopedFeatureListTest& operator=(const ScopedFeatureListTest&) = delete;
  47. ~ScopedFeatureListTest() override {
  48. // Restore feature list.
  49. if (original_feature_list_) {
  50. FeatureList::ClearInstanceForTesting();
  51. FeatureList::RestoreInstanceForTesting(std::move(original_feature_list_));
  52. }
  53. }
  54. private:
  55. // Save the present FeatureList and restore it after test finish.
  56. std::unique_ptr<FeatureList> original_feature_list_;
  57. };
  58. TEST_F(ScopedFeatureListTest, BasicScoped) {
  59. ExpectFeatures(std::string(), std::string());
  60. EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1));
  61. {
  62. test::ScopedFeatureList feature_list1;
  63. feature_list1.InitFromCommandLine("TestFeature1", std::string());
  64. ExpectFeatures("TestFeature1", std::string());
  65. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  66. }
  67. ExpectFeatures(std::string(), std::string());
  68. EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1));
  69. }
  70. TEST_F(ScopedFeatureListTest, InitFromCommandLineWithFeatureParams) {
  71. const std::map<std::string, std::string> feature_params1 = {{"x", "uma"},
  72. {"y", "ukm"}};
  73. const std::map<std::string, std::string> feature_params2 = {{"x", "ukm"},
  74. {"y", "uma"}};
  75. test::ScopedFeatureList feature_list1;
  76. feature_list1.InitFromCommandLine("TestFeature1<foo.bar:x/uma/y/ukm", "");
  77. // Check initial state. Field trial and parameters should be set correctly.
  78. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  79. FieldTrial::ActiveGroups active_groups;
  80. FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
  81. EXPECT_EQ(1u, active_groups.size());
  82. FieldTrial* original_field_trial =
  83. FieldTrialList::Find(active_groups[0].trial_name);
  84. std::map<std::string, std::string> actualParams;
  85. EXPECT_TRUE(GetFieldTrialParamsByFeature(kTestFeature1, &actualParams));
  86. EXPECT_EQ(feature_params1, actualParams);
  87. {
  88. // Override feature with existing field trial.
  89. test::ScopedFeatureList feature_list2;
  90. feature_list2.InitAndEnableFeatureWithParameters(kTestFeature1,
  91. feature_params2);
  92. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  93. EXPECT_NE(original_field_trial, FeatureList::GetFieldTrial(kTestFeature1));
  94. actualParams.clear();
  95. EXPECT_TRUE(GetFieldTrialParamsByFeature(kTestFeature1, &actualParams));
  96. EXPECT_EQ(feature_params2, actualParams);
  97. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
  98. }
  99. // Check that initial state is restored.
  100. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  101. active_groups.clear();
  102. FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
  103. EXPECT_EQ(1u, active_groups.size());
  104. EXPECT_EQ(original_field_trial, FeatureList::GetFieldTrial(kTestFeature1));
  105. actualParams.clear();
  106. EXPECT_TRUE(GetFieldTrialParamsByFeature(kTestFeature1, &actualParams));
  107. EXPECT_EQ(feature_params1, actualParams);
  108. }
  109. TEST_F(ScopedFeatureListTest, EnableWithFeatureParameters) {
  110. const char kParam1[] = "param_1";
  111. const char kParam2[] = "param_2";
  112. const char kValue1[] = "value_1";
  113. const char kValue2[] = "value_2";
  114. std::map<std::string, std::string> parameters;
  115. parameters[kParam1] = kValue1;
  116. parameters[kParam2] = kValue2;
  117. ExpectFeatures(std::string(), std::string());
  118. EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
  119. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
  120. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
  121. FieldTrial::ActiveGroups active_groups;
  122. FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
  123. EXPECT_EQ(0u, active_groups.size());
  124. {
  125. test::ScopedFeatureList feature_list;
  126. feature_list.InitAndEnableFeatureWithParameters(kTestFeature1, parameters);
  127. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  128. EXPECT_EQ(kValue1,
  129. GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
  130. EXPECT_EQ(kValue2,
  131. GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
  132. active_groups.clear();
  133. FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
  134. EXPECT_EQ(1u, active_groups.size());
  135. }
  136. ExpectFeatures(std::string(), std::string());
  137. EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
  138. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
  139. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
  140. active_groups.clear();
  141. FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
  142. EXPECT_EQ(0u, active_groups.size());
  143. }
  144. TEST_F(ScopedFeatureListTest, OverrideWithFeatureParameters) {
  145. scoped_refptr<FieldTrial> trial =
  146. FieldTrialList::CreateFieldTrial("foo", "bar");
  147. const char kParam[] = "param_1";
  148. const char kValue[] = "value_1";
  149. const char kValue0[] = "value_0";
  150. std::map<std::string, std::string> parameters;
  151. parameters[kParam] = kValue;
  152. test::ScopedFeatureList feature_list1;
  153. feature_list1.InitFromCommandLine(
  154. "TestFeature1<foo.bar:param_1/value_0,TestFeature2", std::string());
  155. // Check initial state.
  156. ExpectFeatures("TestFeature1<foo,TestFeature2", std::string());
  157. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  158. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  159. // ScopedFeatureList always scope features, field trials and their associated
  160. // parameters. So ScopedFeatureList::InitFromCommandLine() creates another
  161. // FieldTrial instance whose trial name, group name and associated parameters
  162. // are the same as |trial|, and changes |kTestFeature1|'s field trial to
  163. // be the newly created one.
  164. EXPECT_NE(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
  165. EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  166. EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  167. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  168. EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
  169. FieldTrial* trial_for_test_feature1 =
  170. FeatureList::GetFieldTrial(kTestFeature1);
  171. EXPECT_EQ("foo", trial_for_test_feature1->trial_name());
  172. EXPECT_EQ("bar", trial_for_test_feature1->group_name());
  173. {
  174. // Override feature with existing field trial.
  175. test::ScopedFeatureList feature_list2;
  176. feature_list2.InitAndEnableFeatureWithParameters(kTestFeature1, parameters);
  177. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  178. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  179. EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  180. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  181. EXPECT_NE(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
  182. EXPECT_NE(trial_for_test_feature1,
  183. FeatureList::GetFieldTrial(kTestFeature1));
  184. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
  185. EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  186. }
  187. {
  188. // Override feature with existing field trial.
  189. test::ScopedFeatureList feature_list2;
  190. feature_list2.InitFromCommandLine("TestFeature1<foo.bar2:param_1/value_1",
  191. std::string());
  192. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  193. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  194. EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  195. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  196. EXPECT_NE(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
  197. EXPECT_NE(trial_for_test_feature1,
  198. FeatureList::GetFieldTrial(kTestFeature1));
  199. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
  200. EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  201. // foo's active group is now bar2, not bar.
  202. EXPECT_TRUE(FieldTrialList::IsTrialActive("foo"));
  203. EXPECT_EQ("bar2", GetActiveFieldTrialGroupName("foo"));
  204. }
  205. // Check that initial state is restored.
  206. ExpectFeatures("TestFeature1<foo,TestFeature2", std::string());
  207. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  208. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  209. EXPECT_EQ(trial_for_test_feature1, FeatureList::GetFieldTrial(kTestFeature1));
  210. EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  211. EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  212. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  213. // foo's active group is bar, because initial state is restored.
  214. EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
  215. {
  216. // Override feature with no existing field trial.
  217. test::ScopedFeatureList feature_list2;
  218. feature_list2.InitAndEnableFeatureWithParameters(kTestFeature2, parameters);
  219. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  220. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  221. EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  222. EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  223. EXPECT_EQ(trial_for_test_feature1->trial_name(),
  224. FeatureList::GetFieldTrial(kTestFeature1)->trial_name());
  225. EXPECT_EQ(trial_for_test_feature1->group_name(),
  226. FeatureList::GetFieldTrial(kTestFeature1)->group_name());
  227. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  228. }
  229. // Check that initial state is restored.
  230. ExpectFeatures("TestFeature1<foo,TestFeature2", std::string());
  231. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  232. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  233. EXPECT_EQ(trial_for_test_feature1, FeatureList::GetFieldTrial(kTestFeature1));
  234. EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  235. EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  236. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  237. }
  238. TEST_F(ScopedFeatureListTest, OverrideWithFeatureMultipleParameters) {
  239. const char kParam1[] = "param_1";
  240. const char kValue1[] = "value_1";
  241. const char kParam2[] = "param_2";
  242. const char kValue2[] = "value_2";
  243. const char kValue3[] = "value_3";
  244. std::map<std::string, std::string> parameters;
  245. parameters[kParam1] = kValue3;
  246. test::ScopedFeatureList feature_list1;
  247. feature_list1.InitFromCommandLine(
  248. "TestFeature1<foo.bar:param_1/value_1/param_2/"
  249. "value_2,TestFeature2:param_1/value_2",
  250. std::string());
  251. // Check initial state.
  252. ExpectFeatures("TestFeature1<foo,TestFeature2<StudyTestFeature2",
  253. std::string());
  254. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  255. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  256. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
  257. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  258. EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
  259. EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
  260. EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
  261. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
  262. FieldTrial* trial = FieldTrialList::Find("foo");
  263. EXPECT_EQ("bar", trial->GetGroupNameWithoutActivation());
  264. EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
  265. FieldTrial* trial2 = FieldTrialList::Find("StudyTestFeature2");
  266. EXPECT_EQ("GroupTestFeature2", trial2->GetGroupNameWithoutActivation());
  267. EXPECT_EQ("GroupTestFeature2",
  268. GetActiveFieldTrialGroupName("StudyTestFeature2"));
  269. {
  270. // Override feature with existing field trial.
  271. test::ScopedFeatureList feature_list2;
  272. feature_list2.InitAndEnableFeatureWithParameters(kTestFeature1, parameters);
  273. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  274. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  275. EXPECT_EQ(kValue3,
  276. GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
  277. // param_2 is not set.
  278. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
  279. EXPECT_EQ(kValue2,
  280. GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
  281. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
  282. EXPECT_NE(trial, FeatureList::GetFieldTrial(kTestFeature1));
  283. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
  284. EXPECT_NE(trial2, FeatureList::GetFieldTrial(kTestFeature2));
  285. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  286. }
  287. // Check that initial state is restored.
  288. ExpectFeatures("TestFeature1<foo,TestFeature2<StudyTestFeature2",
  289. std::string());
  290. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  291. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  292. EXPECT_EQ(trial, FeatureList::GetFieldTrial(kTestFeature1));
  293. EXPECT_EQ(trial2, FeatureList::GetFieldTrial(kTestFeature2));
  294. EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
  295. EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
  296. EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
  297. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
  298. // foo's active group is bar, because initial state is restored.
  299. EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
  300. EXPECT_EQ("GroupTestFeature2",
  301. GetActiveFieldTrialGroupName("StudyTestFeature2"));
  302. {
  303. // Override feature with existing field trial.
  304. test::ScopedFeatureList feature_list2;
  305. feature_list2.InitFromCommandLine("TestFeature1<foo.bar2:param_2/value_3",
  306. std::string());
  307. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  308. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  309. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
  310. EXPECT_EQ(kValue3,
  311. GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
  312. EXPECT_EQ(kValue2,
  313. GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
  314. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
  315. EXPECT_NE(trial, FeatureList::GetFieldTrial(kTestFeature1));
  316. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
  317. EXPECT_EQ("foo", FeatureList::GetFieldTrial(kTestFeature1)->trial_name());
  318. EXPECT_EQ("bar2", FeatureList::GetFieldTrial(kTestFeature1)->group_name());
  319. EXPECT_NE(trial2, FeatureList::GetFieldTrial(kTestFeature2));
  320. EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  321. // foo's active group is now bar2, not bar.
  322. EXPECT_TRUE(FieldTrialList::IsTrialActive("foo"));
  323. EXPECT_EQ("bar2", GetActiveFieldTrialGroupName("foo"));
  324. }
  325. // Check that initial state is restored.
  326. ExpectFeatures("TestFeature1<foo,TestFeature2<StudyTestFeature2",
  327. std::string());
  328. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  329. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  330. EXPECT_EQ(trial, FeatureList::GetFieldTrial(kTestFeature1));
  331. EXPECT_EQ(trial2, FeatureList::GetFieldTrial(kTestFeature2));
  332. EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
  333. EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
  334. EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam1));
  335. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam2));
  336. EXPECT_EQ("bar", GetActiveFieldTrialGroupName("foo"));
  337. }
  338. TEST_F(ScopedFeatureListTest, OverrideMultipleFeaturesWithParameters) {
  339. scoped_refptr<FieldTrial> trial1 =
  340. FieldTrialList::CreateFieldTrial("foo1", "bar1");
  341. const char kParam[] = "param_1";
  342. const char kValue0[] = "value_0";
  343. const char kValue1[] = "value_1";
  344. const char kValue2[] = "value_2";
  345. std::map<std::string, std::string> parameters1;
  346. parameters1[kParam] = kValue1;
  347. std::map<std::string, std::string> parameters2;
  348. parameters2[kParam] = kValue2;
  349. test::ScopedFeatureList feature_list1;
  350. feature_list1.InitFromCommandLine(
  351. "TestFeature1<foo1:param_1/value_0,TestFeature2", std::string());
  352. // Check initial state.
  353. ExpectFeatures("TestFeature1<foo1,TestFeature2", std::string());
  354. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  355. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  356. EXPECT_EQ("foo1", FeatureList::GetFieldTrial(kTestFeature1)->trial_name());
  357. EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  358. EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  359. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  360. // InitFromCommandLine() scopes field trials.
  361. FieldTrial* trial = FieldTrialList::Find("foo1");
  362. // --enable-features will create a group whose name is "Group" + feature
  363. // name if no group name is specified. In this case, the feature name is
  364. // "TestFeature1". So the group name is "GroupTestFeature1".
  365. EXPECT_EQ("GroupTestFeature1", trial->GetGroupNameWithoutActivation());
  366. EXPECT_NE(trial1.get(), trial);
  367. // Because of "scoped", "bar1" disappears. Instead, "GroupTestFeature1"
  368. // is created and activated.
  369. EXPECT_NE("bar1", GetActiveFieldTrialGroupName("foo1"));
  370. EXPECT_EQ("GroupTestFeature1", GetActiveFieldTrialGroupName("foo1"));
  371. {
  372. // Override multiple features with parameters.
  373. test::ScopedFeatureList feature_list2;
  374. feature_list2.InitWithFeaturesAndParameters(
  375. {{kTestFeature1, parameters1}, {kTestFeature2, parameters2}}, {});
  376. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  377. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  378. EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  379. EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  380. }
  381. {
  382. // Override a feature with a parameter and disable another one.
  383. test::ScopedFeatureList feature_list2;
  384. feature_list2.InitWithFeaturesAndParameters({{kTestFeature1, parameters2}},
  385. {kTestFeature2});
  386. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  387. EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature2));
  388. EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  389. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  390. }
  391. // Check that initial state is restored.
  392. ExpectFeatures("TestFeature1<foo1,TestFeature2", std::string());
  393. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  394. EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
  395. EXPECT_EQ(trial, FeatureList::GetFieldTrial(kTestFeature1));
  396. EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
  397. EXPECT_EQ(kValue0, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  398. EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  399. }
  400. TEST_F(ScopedFeatureListTest, ParamsWithSpecialCharsPreserved) {
  401. // Check that special characters in param names and values are preserved.
  402. const char kParam[] = ";_\\<:>/_!?";
  403. const char kValue[] = ",;:/'!?";
  404. FieldTrialParams params0 = {{kParam, kValue}};
  405. test::ScopedFeatureList feature_list0;
  406. feature_list0.InitWithFeaturesAndParameters({{kTestFeature1, params0}}, {});
  407. EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  408. {
  409. const char kValue1[] = "normal";
  410. FieldTrialParams params1 = {{kParam, kValue1}};
  411. test::ScopedFeatureList feature_list1;
  412. feature_list1.InitWithFeaturesAndParameters({{kTestFeature1, params1}}, {});
  413. EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  414. }
  415. EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  416. {
  417. const char kValue2[] = "[<(2)>]";
  418. FieldTrialParams params2 = {{kParam, kValue2}};
  419. test::ScopedFeatureList feature_list2;
  420. feature_list2.InitWithFeaturesAndParameters({{kTestFeature2, params2}}, {});
  421. EXPECT_EQ(kValue2, GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
  422. EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  423. }
  424. EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  425. }
  426. TEST_F(ScopedFeatureListTest, ParamsWithEmptyValue) {
  427. const char kParam[] = "p";
  428. const char kEmptyValue[] = "";
  429. FieldTrialParams params = {{kParam, kEmptyValue}};
  430. test::ScopedFeatureList feature_list0;
  431. feature_list0.InitWithFeaturesAndParameters({{kTestFeature1, params}}, {});
  432. EXPECT_EQ(kEmptyValue,
  433. GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  434. {
  435. const char kValue1[] = "normal";
  436. FieldTrialParams params1 = {{kParam, kValue1}};
  437. test::ScopedFeatureList feature_list1;
  438. feature_list1.InitWithFeaturesAndParameters({{kTestFeature1, params1}}, {});
  439. EXPECT_EQ(kValue1, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  440. }
  441. EXPECT_EQ(kEmptyValue,
  442. GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
  443. }
  444. TEST_F(ScopedFeatureListTest, EnableFeatureOverrideDisable) {
  445. test::ScopedFeatureList feature_list1;
  446. feature_list1.InitWithFeatures({}, {kTestFeature1});
  447. {
  448. test::ScopedFeatureList feature_list2;
  449. feature_list2.InitWithFeatures({kTestFeature1}, {});
  450. ExpectFeatures("TestFeature1", std::string());
  451. }
  452. }
  453. TEST_F(ScopedFeatureListTest, FeatureOverrideNotMakeDuplicate) {
  454. test::ScopedFeatureList feature_list1;
  455. feature_list1.InitWithFeatures({}, {kTestFeature1});
  456. {
  457. test::ScopedFeatureList feature_list2;
  458. feature_list2.InitWithFeatures({}, {kTestFeature1});
  459. ExpectFeatures(std::string(), "TestFeature1");
  460. }
  461. }
  462. TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault) {
  463. test::ScopedFeatureList feature_list1;
  464. feature_list1.InitFromCommandLine("*TestFeature1", std::string());
  465. {
  466. test::ScopedFeatureList feature_list2;
  467. feature_list2.InitWithFeatures({kTestFeature1}, {});
  468. ExpectFeatures("TestFeature1", std::string());
  469. }
  470. }
  471. TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault2) {
  472. test::ScopedFeatureList feature_list1;
  473. feature_list1.InitFromCommandLine("*TestFeature1", std::string());
  474. {
  475. test::ScopedFeatureList feature_list2;
  476. feature_list2.InitWithFeatures({}, {kTestFeature1});
  477. ExpectFeatures(std::string(), "TestFeature1");
  478. }
  479. }
  480. TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithEnabledFieldTrial) {
  481. test::ScopedFeatureList feature_list1;
  482. std::unique_ptr<FeatureList> feature_list(new FeatureList);
  483. FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A");
  484. feature_list->RegisterFieldTrialOverride(
  485. kTestFeature1.name, FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
  486. feature_list1.InitWithFeatureList(std::move(feature_list));
  487. {
  488. test::ScopedFeatureList feature_list2;
  489. feature_list2.InitWithFeatures({kTestFeature1}, {});
  490. ExpectFeatures("TestFeature1", std::string());
  491. }
  492. }
  493. TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDisabledFieldTrial) {
  494. test::ScopedFeatureList feature_list1;
  495. std::unique_ptr<FeatureList> feature_list(new FeatureList);
  496. FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A");
  497. feature_list->RegisterFieldTrialOverride(
  498. kTestFeature1.name, FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
  499. feature_list1.InitWithFeatureList(std::move(feature_list));
  500. {
  501. test::ScopedFeatureList feature_list2;
  502. feature_list2.InitWithFeatures({kTestFeature1}, {});
  503. ExpectFeatures("TestFeature1", std::string());
  504. }
  505. }
  506. TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature) {
  507. test::ScopedFeatureList feature_list1;
  508. feature_list1.InitWithFeatures({}, {kTestFeature1});
  509. {
  510. test::ScopedFeatureList feature_list2;
  511. feature_list2.InitWithFeatures({}, {kTestFeature2});
  512. EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1));
  513. EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature2));
  514. }
  515. }
  516. TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature2) {
  517. test::ScopedFeatureList feature_list1;
  518. feature_list1.InitWithFeatures({}, {kTestFeature1});
  519. {
  520. test::ScopedFeatureList feature_list2;
  521. feature_list2.InitWithFeatures({kTestFeature2}, {});
  522. ExpectFeatures("TestFeature2", "TestFeature1");
  523. }
  524. }
  525. TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingDefaultFeature) {
  526. test::ScopedFeatureList feature_list1;
  527. feature_list1.InitFromCommandLine("*TestFeature1", std::string());
  528. {
  529. test::ScopedFeatureList feature_list2;
  530. feature_list2.InitWithFeatures({}, {kTestFeature2});
  531. ExpectFeatures("*TestFeature1", "TestFeature2");
  532. }
  533. }
  534. TEST_F(ScopedFeatureListTest, ScopedFeatureListIsNoopWhenNotInitialized) {
  535. test::ScopedFeatureList feature_list1;
  536. feature_list1.InitFromCommandLine("*TestFeature1", std::string());
  537. // A ScopedFeatureList on which Init() is not called should not reset things
  538. // when going out of scope.
  539. { test::ScopedFeatureList feature_list2; }
  540. ExpectFeatures("*TestFeature1", std::string());
  541. }
  542. TEST(ScopedFeatureListTestWithMemberList, ScopedFeatureListLocalOverride) {
  543. test::ScopedFeatureList initial_feature_list;
  544. initial_feature_list.InitAndDisableFeature(kTestFeature1);
  545. {
  546. base::test::ScopedFeatureList scoped_features;
  547. scoped_features.InitAndEnableFeatureWithParameters(kTestFeature1,
  548. {{"mode", "nobugs"}});
  549. ASSERT_TRUE(FeatureList::IsEnabled(kTestFeature1));
  550. }
  551. }
  552. } // namespace test
  553. } // namespace base