blob: 0dd72c150df9a1b7656f1243032c455b274eafdb [file] [log] [blame]
sdefresne0e566342015-11-24 08:55:461// 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 "components/flags_ui/flags_state.h"
6
avibc5337b2015-12-25 23:16:337#include <stddef.h>
8
sdefresne0e566342015-11-24 08:55:469#include <map>
dcheng84c358e2016-04-26 07:05:5310#include <memory>
sdefresne0e566342015-11-24 08:55:4611#include <set>
12#include <string>
13
14#include "base/bind.h"
Jan Wilken Dörrie986f0a62020-12-09 23:29:1215#include "base/containers/contains.h"
sdefresne0e566342015-11-24 08:55:4616#include "base/feature_list.h"
17#include "base/format_macros.h"
jkrcal1383d1d2016-06-17 12:40:5618#include "base/metrics/field_trial.h"
sdefresne0e566342015-11-24 08:55:4619#include "base/strings/stringprintf.h"
20#include "base/strings/utf_string_conversions.h"
asvitkine9499b8d2016-08-09 05:37:0721#include "base/test/scoped_feature_list.h"
sdefresne0e566342015-11-24 08:55:4622#include "base/values.h"
avibc5337b2015-12-25 23:16:3323#include "build/build_config.h"
sdefresne0e566342015-11-24 08:55:4624#include "components/flags_ui/feature_entry.h"
Jeremy Roman39086972020-06-15 17:55:4325#include "components/flags_ui/feature_entry_macros.h"
sdefresne0e566342015-11-24 08:55:4626#include "components/flags_ui/flags_ui_pref_names.h"
27#include "components/flags_ui/flags_ui_switches.h"
28#include "components/flags_ui/pref_service_flags_storage.h"
brettw066508682016-02-03 08:22:0229#include "components/prefs/pref_registry_simple.h"
30#include "components/prefs/testing_pref_service.h"
thakisfe8fa0a2017-02-23 19:46:3631#include "components/strings/grit/components_strings.h"
jkrcal1383d1d2016-06-17 12:40:5632#include "components/variations/variations_associated_data.h"
sdefresne0e566342015-11-24 08:55:4633#include "testing/gtest/include/gtest/gtest.h"
34
35namespace flags_ui {
36
37namespace {
38
39const char kFlags1[] = "flag1";
40const char kFlags2[] = "flag2";
41const char kFlags3[] = "flag3";
42const char kFlags4[] = "flag4";
43const char kFlags5[] = "flag5";
44const char kFlags6[] = "flag6";
45const char kFlags7[] = "flag7";
jkrcal1383d1d2016-06-17 12:40:5646const char kFlags8[] = "flag8";
jkrcal7a3554e2017-03-02 09:01:3547const char kFlags9[] = "flag9";
48const char kFlags10[] = "flag10";
Mustafa Emre Acerb3aa36a82018-05-22 21:44:0549const char kFlags11[] = "flag11";
Joon Ahn79fe0a22020-09-21 18:44:5150const char kFlags12[] = "flag12";
sdefresne0e566342015-11-24 08:55:4651
52const char kSwitch1[] = "switch";
53const char kSwitch2[] = "switch2";
54const char kSwitch3[] = "switch3";
55const char kSwitch6[] = "switch6";
56const char kValueForSwitch2[] = "value_for_switch2";
57
Mustafa Emre Acerb3aa36a82018-05-22 21:44:0558const char kStringSwitch[] = "string_switch";
59const char kValueForStringSwitch[] = "value_for_string_switch";
60
sdefresne0e566342015-11-24 08:55:4661const char kMultiSwitch1[] = "multi_switch1";
62const char kMultiSwitch2[] = "multi_switch2";
63const char kValueForMultiSwitch2[] = "value_for_multi_switch2";
64
65const char kEnableDisableValue1[] = "value1";
66const char kEnableDisableValue2[] = "value2";
67
68const char kEnableFeatures[] = "dummy-enable-features";
69const char kDisableFeatures[] = "dummy-disable-features";
70
jkrcal1383d1d2016-06-17 12:40:5671const char kTestTrial[] = "TestTrial";
jkrcal7a3554e2017-03-02 09:01:3572const char kTestParam1[] = "param1";
73const char kTestParam2[] = "param2";
Joon Ahn79fe0a22020-09-21 18:44:5174const char kTestParam3[] = "param:/3";
jkrcal05f7ce32016-07-13 16:42:0975const char kTestParamValue[] = "value";
jkrcal1383d1d2016-06-17 12:40:5676
77const base::Feature kTestFeature1{"FeatureName1",
78 base::FEATURE_ENABLED_BY_DEFAULT};
79const base::Feature kTestFeature2{"FeatureName2",
80 base::FEATURE_ENABLED_BY_DEFAULT};
Joon Ahn79fe0a22020-09-21 18:44:5181const base::Feature kTestFeature3{"FeatureName3",
82 base::FEATURE_DISABLED_BY_DEFAULT};
jkrcal1383d1d2016-06-17 12:40:5683
jkrcal7a3554e2017-03-02 09:01:3584const FeatureEntry::FeatureParam kTestVariationOther1[] = {
85 {kTestParam1, kTestParamValue}};
86const FeatureEntry::FeatureParam kTestVariationOther2[] = {
87 {kTestParam2, kTestParamValue}};
Joon Ahn79fe0a22020-09-21 18:44:5188const FeatureEntry::FeatureParam kTestVariationOther3[] = {
89 {kTestParam1, kTestParamValue},
90 {kTestParam3, kTestParamValue},
91};
jkrcal1383d1d2016-06-17 12:40:5692
jkrcal7a3554e2017-03-02 09:01:3593const FeatureEntry::FeatureVariation kTestVariations1[] = {
94 {"dummy description 1", kTestVariationOther1, 1, nullptr}};
95const FeatureEntry::FeatureVariation kTestVariations2[] = {
96 {"dummy description 2", kTestVariationOther2, 1, nullptr}};
Joon Ahn79fe0a22020-09-21 18:44:5197const FeatureEntry::FeatureVariation kTestVariations3[] = {
98 {"dummy description 1", kTestVariationOther1, 1, nullptr},
99 {"dummy description 2", kTestVariationOther2, 1, nullptr},
100 {"dummy description 3", kTestVariationOther3, 2, nullptr}};
101
102const char kTestVariation3Cmdline[] =
103 "FeatureName3:param1/value/param%3A%2F3/value";
jkrcal1383d1d2016-06-17 12:40:56104
Jan Wilken Dörrie57a23ec2020-09-12 12:20:29105const char kDummyName[] = "";
106const char kDummyDescription[] = "";
sdefresne0e566342015-11-24 08:55:46107
108bool SkipFeatureEntry(const FeatureEntry& feature_entry) {
109 return false;
110}
111
112} // namespace
113
114const FeatureEntry::Choice kMultiChoices[] = {
vabr0215a8e2017-03-28 12:47:34115 {kDummyDescription, "", ""},
116 {kDummyDescription, kMultiSwitch1, ""},
117 {kDummyDescription, kMultiSwitch2, kValueForMultiSwitch2},
sdefresne0e566342015-11-24 08:55:46118};
119
sdefresne0e566342015-11-24 08:55:46120// The entries that are set for these tests. The 3rd entry is not supported on
121// the current platform, all others are.
122static FeatureEntry kEntries[] = {
vabr0215a8e2017-03-28 12:47:34123 {kFlags1, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46124 0, // Ends up being mapped to the current platform.
Jeremy Roman39086972020-06-15 17:55:43125 SINGLE_VALUE_TYPE(kSwitch1)},
vabr0215a8e2017-03-28 12:47:34126 {kFlags2, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46127 0, // Ends up being mapped to the current platform.
Jeremy Roman39086972020-06-15 17:55:43128 SINGLE_VALUE_TYPE_AND_VALUE(kSwitch2, kValueForSwitch2)},
vabr0215a8e2017-03-28 12:47:34129 {kFlags3, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46130 0, // This ends up enabling for an OS other than the current.
Jeremy Roman39086972020-06-15 17:55:43131 SINGLE_VALUE_TYPE(kSwitch3)},
vabr0215a8e2017-03-28 12:47:34132 {kFlags4, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46133 0, // Ends up being mapped to the current platform.
Jeremy Roman39086972020-06-15 17:55:43134 MULTI_VALUE_TYPE(kMultiChoices)},
vabr0215a8e2017-03-28 12:47:34135 {kFlags5, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46136 0, // Ends up being mapped to the current platform.
Jeremy Roman39086972020-06-15 17:55:43137 ENABLE_DISABLE_VALUE_TYPE_AND_VALUE(kSwitch1,
138 kEnableDisableValue1,
139 kSwitch2,
140 kEnableDisableValue2)},
vabr0215a8e2017-03-28 12:47:34141 {kFlags6, kDummyName, kDummyDescription, 0,
Jeremy Roman39086972020-06-15 17:55:43142 SINGLE_DISABLE_VALUE_TYPE(kSwitch6)},
vabr0215a8e2017-03-28 12:47:34143 {kFlags7, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46144 0, // Ends up being mapped to the current platform.
Jeremy Roman39086972020-06-15 17:55:43145 FEATURE_VALUE_TYPE(kTestFeature1)},
vabr0215a8e2017-03-28 12:47:34146 {kFlags8, kDummyName, kDummyDescription,
jkrcal1383d1d2016-06-17 12:40:56147 0, // Ends up being mapped to the current platform.
Jeremy Roman39086972020-06-15 17:55:43148 FEATURE_WITH_PARAMS_VALUE_TYPE(kTestFeature1,
149 kTestVariations1,
150 kTestTrial)},
vabr0215a8e2017-03-28 12:47:34151 {kFlags9, kDummyName, kDummyDescription,
jkrcal7a3554e2017-03-02 09:01:35152 0, // Ends up being mapped to the current platform.
Jeremy Roman39086972020-06-15 17:55:43153 FEATURE_WITH_PARAMS_VALUE_TYPE(kTestFeature1,
154 kTestVariations1,
155 kTestTrial)},
vabr0215a8e2017-03-28 12:47:34156 {kFlags10, kDummyName, kDummyDescription,
jkrcal7a3554e2017-03-02 09:01:35157 0, // Ends up being mapped to the current platform.
Jeremy Roman39086972020-06-15 17:55:43158 FEATURE_WITH_PARAMS_VALUE_TYPE(kTestFeature2,
159 kTestVariations2,
160 kTestTrial)},
Mustafa Emre Acerb3aa36a82018-05-22 21:44:05161 {kFlags11, kDummyName, kDummyDescription,
162 0, // Ends up being mapped to the current platform.
Joon Ahn79fe0a22020-09-21 18:44:51163 ORIGIN_LIST_VALUE_TYPE(kStringSwitch, kValueForStringSwitch)},
164 {kFlags12, kDummyName, kDummyDescription,
165 0, // Ends up being mapped to the current platform.
166 FEATURE_WITH_PARAMS_VALUE_TYPE(kTestFeature3,
167 kTestVariations3,
168 kTestTrial)}};
sdefresne0e566342015-11-24 08:55:46169
Elly Fong-Jones3cd75282019-11-12 20:26:50170class FlagsStateTest : public ::testing::Test,
171 public flags_ui::FlagsState::Delegate {
sdefresne0e566342015-11-24 08:55:46172 protected:
Mikel Astizf9f1f7c2019-11-18 18:13:49173 FlagsStateTest() : flags_storage_(&prefs_) {
Mustafa Emre Acera1a7fb12019-07-24 17:36:50174 prefs_.registry()->RegisterListPref(prefs::kAboutFlagsEntries);
175 prefs_.registry()->RegisterDictionaryPref(prefs::kAboutFlagsOriginLists);
sdefresne0e566342015-11-24 08:55:46176
Daniel Cheng7b7aaecc2022-02-26 17:57:25177 for (size_t i = 0; i < std::size(kEntries); ++i)
sdefresne0e566342015-11-24 08:55:46178 kEntries[i].supported_platforms = FlagsState::GetCurrentPlatform();
179
180 int os_other_than_current = 1;
181 while (os_other_than_current == FlagsState::GetCurrentPlatform())
182 os_other_than_current <<= 1;
183 kEntries[2].supported_platforms = os_other_than_current;
Peter Boström665b49d2021-04-05 19:29:58184 flags_state_ = std::make_unique<FlagsState>(kEntries, this);
sdefresne0e566342015-11-24 08:55:46185 }
186
jkrcal05f7ce32016-07-13 16:42:09187 ~FlagsStateTest() override {
188 variations::testing::ClearAllVariationParams();
189 }
190
Elly Fong-Jones3cd75282019-11-12 20:26:50191 // FlagsState::Delegate:
Elly Fong-Jonesf8a4aa42020-08-04 15:53:30192 bool ShouldExcludeFlag(const FlagsStorage* storage,
193 const FeatureEntry& entry) override {
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19194 return exclude_flags_.count(entry.internal_name) != 0;
195 }
196
sdefresne0e566342015-11-24 08:55:46197 TestingPrefServiceSimple prefs_;
198 PrefServiceFlagsStorage flags_storage_;
dcheng84c358e2016-04-26 07:05:53199 std::unique_ptr<FlagsState> flags_state_;
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19200 std::set<std::string> exclude_flags_;
sdefresne0e566342015-11-24 08:55:46201};
202
203TEST_F(FlagsStateTest, NoChangeNoRestart) {
204 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
205 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, false);
206 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
207
208 // kFlags6 is enabled by default, so enabling should not require a restart.
209 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, true);
210 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
211}
212
213TEST_F(FlagsStateTest, ChangeNeedsRestart) {
214 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
215 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
216 EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges());
217}
218
219// Tests that disabling a default enabled entry requires a restart.
220TEST_F(FlagsStateTest, DisableChangeNeedsRestart) {
221 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
222 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, false);
223 EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges());
224}
225
226TEST_F(FlagsStateTest, MultiFlagChangeNeedsRestart) {
227 const FeatureEntry& entry = kEntries[3];
228 ASSERT_EQ(kFlags4, entry.internal_name);
229 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
230 // Enable the 2nd choice of the multi-value.
jkrcal1383d1d2016-06-17 12:40:56231 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
sdefresne0e566342015-11-24 08:55:46232 true);
233 EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges());
234 flags_state_->Reset();
235 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
236 // Enable the default choice now.
jkrcal1383d1d2016-06-17 12:40:56237 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0),
sdefresne0e566342015-11-24 08:55:46238 true);
239 EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges());
240}
241
242TEST_F(FlagsStateTest, AddTwoFlagsRemoveOne) {
243 // Add two entries, check they're there.
244 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
245 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true);
246
Morten Stenshorne7afa5802021-07-15 10:04:43247 const base::Value* entries_list = prefs_.GetList(prefs::kAboutFlagsEntries);
sdefresne0e566342015-11-24 08:55:46248 ASSERT_TRUE(entries_list != nullptr);
249
Daniel Cheng354945d2022-02-02 23:39:17250 ASSERT_EQ(2u, entries_list->GetListDeprecated().size());
sdefresne0e566342015-11-24 08:55:46251
Daniel Cheng354945d2022-02-02 23:39:17252 std::string s0 = entries_list->GetListDeprecated()[0].GetString();
253 std::string s1 = entries_list->GetListDeprecated()[1].GetString();
sdefresne0e566342015-11-24 08:55:46254
255 EXPECT_TRUE(s0 == kFlags1 || s1 == kFlags1);
256 EXPECT_TRUE(s0 == kFlags2 || s1 == kFlags2);
257
258 // Remove one entry, check the other's still around.
259 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, false);
260
Mustafa Emre Acera1a7fb12019-07-24 17:36:50261 entries_list = prefs_.GetList(prefs::kAboutFlagsEntries);
sdefresne0e566342015-11-24 08:55:46262 ASSERT_TRUE(entries_list != nullptr);
Daniel Cheng354945d2022-02-02 23:39:17263 ASSERT_EQ(1u, entries_list->GetListDeprecated().size());
264 s0 = entries_list->GetListDeprecated()[0].GetString();
sdefresne0e566342015-11-24 08:55:46265 EXPECT_TRUE(s0 == kFlags1);
266}
267
268TEST_F(FlagsStateTest, AddTwoFlagsRemoveBoth) {
269 // Add two entries, check the pref exists.
270 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
271 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true);
Morten Stenshorne7afa5802021-07-15 10:04:43272 const base::Value* entries_list = prefs_.GetList(prefs::kAboutFlagsEntries);
sdefresne0e566342015-11-24 08:55:46273 ASSERT_TRUE(entries_list != nullptr);
274
275 // Remove both, the pref should have been removed completely.
276 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, false);
277 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, false);
Mustafa Emre Acera1a7fb12019-07-24 17:36:50278 entries_list = prefs_.GetList(prefs::kAboutFlagsEntries);
Daniel Cheng354945d2022-02-02 23:39:17279 EXPECT_TRUE(entries_list == nullptr ||
280 entries_list->GetListDeprecated().size() == 0);
sdefresne0e566342015-11-24 08:55:46281}
282
cfredricfaee9972021-10-08 19:24:11283TEST_F(FlagsStateTest, CombineOriginListValues) {
284 // Add a value in prefs, and on command line.
285 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags11, true);
286 const std::string prefs_value =
287 "http://a.test,http://c.test,http://dupe.test";
288 flags_state_->SetOriginListFlag(kFlags11, prefs_value, &flags_storage_);
289 ASSERT_EQ(flags_storage_.GetOriginListFlag(kFlags11), prefs_value);
290
291 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
292 const std::string cli_value = "http://dupe.test,http://b.test";
293 command_line.AppendSwitchASCII(kStringSwitch, cli_value);
294 ASSERT_EQ(command_line.GetSwitchValueASCII(kStringSwitch), cli_value);
295
296 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
297 kNoSentinels, kEnableFeatures,
298 kDisableFeatures);
299
300 // Lists are concatenated together with duplicates removed, but are not
301 // sorted.
302 EXPECT_EQ(command_line.GetSwitchValueASCII(kStringSwitch),
303 "http://dupe.test,http://b.test,http://a.test,http://c.test");
304}
305
sdefresne0e566342015-11-24 08:55:46306TEST_F(FlagsStateTest, ConvertFlagsToSwitches) {
307 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
308
309 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
310 command_line.AppendSwitch("foo");
311
312 EXPECT_TRUE(command_line.HasSwitch("foo"));
313 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
314
315 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
316 kAddSentinels, kEnableFeatures,
317 kDisableFeatures);
318
319 EXPECT_TRUE(command_line.HasSwitch("foo"));
320 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
321 EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesBegin));
322 EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesEnd));
323
324 base::CommandLine command_line2(base::CommandLine::NO_PROGRAM);
325
326 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line2,
327 kNoSentinels, kEnableFeatures,
328 kDisableFeatures);
329
330 EXPECT_TRUE(command_line2.HasSwitch(kSwitch1));
331 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesBegin));
332 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesEnd));
Joon Ahn79fe0a22020-09-21 18:44:51333
334 base::CommandLine command_line3(base::CommandLine::NO_PROGRAM);
335 // Enable 3rd variation (@4 since 0 is enable).
336 flags_state_->SetFeatureEntryEnabled(
337 &flags_storage_, std::string(kFlags12).append("@4"), true);
338
339 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line3,
340 kNoSentinels, kEnableFeatures,
341 kDisableFeatures);
342
343 EXPECT_TRUE(command_line3.HasSwitch(kEnableFeatures));
344 EXPECT_EQ(command_line3.GetSwitchValueASCII(kEnableFeatures),
345 kTestVariation3Cmdline);
sdefresne0e566342015-11-24 08:55:46346}
347
jkrcal1383d1d2016-06-17 12:40:56348TEST_F(FlagsStateTest, RegisterAllFeatureVariationParameters) {
349 const FeatureEntry& entry = kEntries[7];
jkrcald1d20082016-07-14 15:04:24350 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
351
jkrcal05f7ce32016-07-13 16:42:09352 // Select the "Default" variation.
jkrcal1383d1d2016-06-17 12:40:56353 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0),
354 true);
jkrcald1d20082016-07-14 15:04:24355 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
356 feature_list.get());
jkrcal1383d1d2016-06-17 12:40:56357 // No value should be associated.
jkrcal7a3554e2017-03-02 09:01:35358 EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam1));
jkrcal1383d1d2016-06-17 12:40:56359 // The trial should not be created.
360 base::FieldTrial* trial = base::FieldTrialList::Find(kTestTrial);
361 EXPECT_EQ(nullptr, trial);
362
jkrcal05f7ce32016-07-13 16:42:09363 // Select the default "Enabled" variation.
jkrcal1383d1d2016-06-17 12:40:56364 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(1),
365 true);
366
jkrcald1d20082016-07-14 15:04:24367 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
368 feature_list.get());
jkrcal05f7ce32016-07-13 16:42:09369 // No value should be associated as this is the default option.
jkrcal7a3554e2017-03-02 09:01:35370 EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam1));
jkrcal1383d1d2016-06-17 12:40:56371
372 // The trial should be created.
373 trial = base::FieldTrialList::Find(kTestTrial);
374 EXPECT_NE(nullptr, trial);
375 // The about:flags group should be selected for the trial.
376 EXPECT_EQ(internal::kTrialGroupAboutFlags, trial->group_name());
377
jkrcal05f7ce32016-07-13 16:42:09378 // Select the only one variation.
jkrcal1383d1d2016-06-17 12:40:56379 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
380 true);
jkrcald1d20082016-07-14 15:04:24381 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
382 feature_list.get());
jkrcal1383d1d2016-06-17 12:40:56383 // Associating for the second time should not change the value.
jkrcal7a3554e2017-03-02 09:01:35384 EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam1));
jkrcal05f7ce32016-07-13 16:42:09385}
386
387TEST_F(FlagsStateTest, RegisterAllFeatureVariationParametersNonDefault) {
388 const FeatureEntry& entry = kEntries[7];
jkrcald1d20082016-07-14 15:04:24389 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
390
jkrcal05f7ce32016-07-13 16:42:09391 // Select the only one variation.
392 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
393 true);
jkrcald1d20082016-07-14 15:04:24394 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
395 feature_list.get());
396
397 // Set the feature_list as the main instance so that
398 // variations::GetVariationParamValueByFeature below works.
asvitkine9499b8d2016-08-09 05:37:07399 base::test::ScopedFeatureList scoped_feature_list;
400 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
jkrcald1d20082016-07-14 15:04:24401
jkrcal05f7ce32016-07-13 16:42:09402 // The param should have the value predefined in this variation.
403 EXPECT_EQ(kTestParamValue,
jkrcal7a3554e2017-03-02 09:01:35404 variations::GetVariationParamValue(kTestTrial, kTestParam1));
jkrcald1d20082016-07-14 15:04:24405
406 // The value should be associated also via the name of the feature.
407 EXPECT_EQ(kTestParamValue, variations::GetVariationParamValueByFeature(
jkrcal7a3554e2017-03-02 09:01:35408 kTestFeature1, kTestParam1));
409}
410
411TEST_F(FlagsStateTest, RegisterAllFeatureVariationParametersWithDefaultTrials) {
412 const FeatureEntry& entry1 = kEntries[8];
413 const FeatureEntry& entry2 = kEntries[9];
414 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
415
416 // Select the only one variation for each FeatureEntry.
417 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry1.NameForOption(2),
418 true);
419 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry2.NameForOption(2),
420 true);
421 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
422 feature_list.get());
423
424 // Set the feature_list as the main instance so that
425 // variations::GetVariationParamValueByFeature below works.
426 base::test::ScopedFeatureList scoped_feature_list;
427 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
428
429 // The params should have the values predefined in these variations
430 // (accessible via the names of the features).
431 EXPECT_EQ(kTestParamValue, variations::GetVariationParamValueByFeature(
432 kTestFeature1, kTestParam1));
433 EXPECT_EQ(kTestParamValue, variations::GetVariationParamValueByFeature(
434 kTestFeature2, kTestParam2));
435 // The params are registered in the same trial.
436 EXPECT_EQ(kTestParamValue,
437 variations::GetVariationParamValue(kTestTrial, kTestParam1));
438 EXPECT_EQ(kTestParamValue,
439 variations::GetVariationParamValue(kTestTrial, kTestParam2));
jkrcal1383d1d2016-06-17 12:40:56440}
441
sdefresne0e566342015-11-24 08:55:46442base::CommandLine::StringType CreateSwitch(const std::string& value) {
Xiaohan Wangbca91f92022-01-15 19:56:21443#if BUILDFLAG(IS_WIN)
Peter Kastinga8451362021-02-01 14:18:04444 return base::ASCIIToWide(value);
sdefresne0e566342015-11-24 08:55:46445#else
446 return value;
447#endif
448}
449
sdefresne0e566342015-11-24 08:55:46450TEST_F(FlagsStateTest, RemoveFlagSwitches) {
Jeremy Roman863386d2017-10-31 19:25:38451 base::CommandLine::SwitchMap switch_list;
sdefresne0e566342015-11-24 08:55:46452 switch_list[kSwitch1] = base::CommandLine::StringType();
453 switch_list[switches::kFlagSwitchesBegin] = base::CommandLine::StringType();
454 switch_list[switches::kFlagSwitchesEnd] = base::CommandLine::StringType();
455 switch_list["foo"] = base::CommandLine::StringType();
456
457 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
458
459 // This shouldn't do anything before ConvertFlagsToSwitches() wasn't called.
460 flags_state_->RemoveFlagsSwitches(&switch_list);
461 ASSERT_EQ(4u, switch_list.size());
Jan Wilken Dörrie45d34f42019-06-08 09:40:54462 EXPECT_TRUE(base::Contains(switch_list, kSwitch1));
463 EXPECT_TRUE(base::Contains(switch_list, switches::kFlagSwitchesBegin));
464 EXPECT_TRUE(base::Contains(switch_list, switches::kFlagSwitchesEnd));
465 EXPECT_TRUE(base::Contains(switch_list, "foo"));
sdefresne0e566342015-11-24 08:55:46466
467 // Call ConvertFlagsToSwitches(), then RemoveFlagsSwitches() again.
468 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
469 command_line.AppendSwitch("foo");
470 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
471 kAddSentinels, kEnableFeatures,
472 kDisableFeatures);
473 flags_state_->RemoveFlagsSwitches(&switch_list);
474
475 // Now the about:flags-related switch should have been removed.
476 ASSERT_EQ(1u, switch_list.size());
Jan Wilken Dörrie45d34f42019-06-08 09:40:54477 EXPECT_TRUE(base::Contains(switch_list, "foo"));
sdefresne0e566342015-11-24 08:55:46478}
479
480TEST_F(FlagsStateTest, RemoveFlagSwitches_Features) {
481 struct {
482 int enabled_choice; // 0: default, 1: enabled, 2: disabled.
483 const char* existing_enable_features;
484 const char* existing_disable_features;
485 const char* expected_enable_features;
486 const char* expected_disable_features;
487 } cases[] = {
488 // Default value: Should not affect existing flags.
489 {0, nullptr, nullptr, nullptr, nullptr},
490 {0, "A,B", "C", "A,B", "C"},
491 // "Enable" option: should only affect enabled list.
jkrcal1383d1d2016-06-17 12:40:56492 {1, nullptr, nullptr, "FeatureName1", nullptr},
493 {1, "A,B", "C", "A,B,FeatureName1", "C"},
sdefresne0e566342015-11-24 08:55:46494 // "Disable" option: should only affect disabled list.
jkrcal1383d1d2016-06-17 12:40:56495 {2, nullptr, nullptr, nullptr, "FeatureName1"},
496 {2, "A,B", "C", "A,B", "C,FeatureName1"},
sdefresne0e566342015-11-24 08:55:46497 };
498
Daniel Cheng7b7aaecc2022-02-26 17:57:25499 for (size_t i = 0; i < std::size(cases); ++i) {
sdefresne0e566342015-11-24 08:55:46500 SCOPED_TRACE(base::StringPrintf(
501 "Test[%" PRIuS "]: %d [%s] [%s]", i, cases[i].enabled_choice,
502 cases[i].existing_enable_features ? cases[i].existing_enable_features
503 : "null",
504 cases[i].existing_disable_features ? cases[i].existing_disable_features
505 : "null"));
506
507 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
508 if (cases[i].existing_enable_features) {
509 command_line.AppendSwitchASCII(kEnableFeatures,
510 cases[i].existing_enable_features);
511 }
512 if (cases[i].existing_disable_features) {
513 command_line.AppendSwitchASCII(kDisableFeatures,
514 cases[i].existing_disable_features);
515 }
516
517 flags_state_->Reset();
518
519 const std::string entry_name = base::StringPrintf(
520 "%s%s%d", kFlags7, testing::kMultiSeparator, cases[i].enabled_choice);
521 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry_name, true);
522
523 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
524 kAddSentinels, kEnableFeatures,
525 kDisableFeatures);
526 auto switch_list = command_line.GetSwitches();
527 EXPECT_EQ(cases[i].expected_enable_features != nullptr,
Jan Wilken Dörrie45d34f42019-06-08 09:40:54528 base::Contains(switch_list, kEnableFeatures));
sdefresne0e566342015-11-24 08:55:46529 if (cases[i].expected_enable_features)
530 EXPECT_EQ(CreateSwitch(cases[i].expected_enable_features),
531 switch_list[kEnableFeatures]);
532
533 EXPECT_EQ(cases[i].expected_disable_features != nullptr,
Jan Wilken Dörrie45d34f42019-06-08 09:40:54534 base::Contains(switch_list, kDisableFeatures));
sdefresne0e566342015-11-24 08:55:46535 if (cases[i].expected_disable_features)
536 EXPECT_EQ(CreateSwitch(cases[i].expected_disable_features),
537 switch_list[kDisableFeatures]);
538
539 // RemoveFlagsSwitches() should result in the original values for these
540 // switches.
541 switch_list = command_line.GetSwitches();
542 flags_state_->RemoveFlagsSwitches(&switch_list);
543 EXPECT_EQ(cases[i].existing_enable_features != nullptr,
Jan Wilken Dörrie45d34f42019-06-08 09:40:54544 base::Contains(switch_list, kEnableFeatures));
sdefresne0e566342015-11-24 08:55:46545 if (cases[i].existing_enable_features)
546 EXPECT_EQ(CreateSwitch(cases[i].existing_enable_features),
547 switch_list[kEnableFeatures]);
548 EXPECT_EQ(cases[i].existing_disable_features != nullptr,
Jan Wilken Dörrie45d34f42019-06-08 09:40:54549 base::Contains(switch_list, kEnableFeatures));
sdefresne0e566342015-11-24 08:55:46550 if (cases[i].existing_disable_features)
551 EXPECT_EQ(CreateSwitch(cases[i].existing_disable_features),
552 switch_list[kDisableFeatures]);
553 }
554}
555
556// Tests enabling entries that aren't supported on the current platform.
557TEST_F(FlagsStateTest, PersistAndPrune) {
558 // Enable entries 1 and 3.
559 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
560 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags3, true);
561 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
562 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
563 EXPECT_FALSE(command_line.HasSwitch(kSwitch3));
564
565 // Convert the flags to switches. Entry 3 shouldn't be among the switches
566 // as it is not applicable to the current platform.
567 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
568 kAddSentinels, kEnableFeatures,
569 kDisableFeatures);
570 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
571 EXPECT_FALSE(command_line.HasSwitch(kSwitch3));
572
573 // FeatureEntry 3 should show still be persisted in preferences though.
Morten Stenshorne7afa5802021-07-15 10:04:43574 const base::Value* entries_list = prefs_.GetList(prefs::kAboutFlagsEntries);
sdefresne0e566342015-11-24 08:55:46575 ASSERT_TRUE(entries_list);
Daniel Cheng354945d2022-02-02 23:39:17576 EXPECT_EQ(2U, entries_list->GetListDeprecated().size());
577 std::string s0 = entries_list->GetListDeprecated()[0].GetString();
sdefresne0e566342015-11-24 08:55:46578 EXPECT_EQ(kFlags1, s0);
Daniel Cheng354945d2022-02-02 23:39:17579 std::string s1 = entries_list->GetListDeprecated()[1].GetString();
sdefresne0e566342015-11-24 08:55:46580 EXPECT_EQ(kFlags3, s1);
581}
582
583// Tests that switches which should have values get them in the command
584// line.
585TEST_F(FlagsStateTest, CheckValues) {
586 // Enable entries 1 and 2.
587 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
588 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true);
589 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
590 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
591 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
592
593 // Convert the flags to switches.
594 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
595 kAddSentinels, kEnableFeatures,
596 kDisableFeatures);
597 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
598 EXPECT_EQ(std::string(), command_line.GetSwitchValueASCII(kSwitch1));
599 EXPECT_TRUE(command_line.HasSwitch(kSwitch2));
600 EXPECT_EQ(std::string(kValueForSwitch2),
601 command_line.GetSwitchValueASCII(kSwitch2));
602
603 // Confirm that there is no '=' in the command line for simple switches.
604 std::string switch1_with_equals =
605 std::string("--") + std::string(kSwitch1) + std::string("=");
Xiaohan Wangbca91f92022-01-15 19:56:21606#if BUILDFLAG(IS_WIN)
Peter Kastinga8451362021-02-01 14:18:04607 EXPECT_EQ(std::wstring::npos, command_line.GetCommandLineString().find(
608 base::ASCIIToWide(switch1_with_equals)));
sdefresne0e566342015-11-24 08:55:46609#else
610 EXPECT_EQ(std::string::npos,
611 command_line.GetCommandLineString().find(switch1_with_equals));
612#endif
613
614 // And confirm there is a '=' for switches with values.
615 std::string switch2_with_equals =
616 std::string("--") + std::string(kSwitch2) + std::string("=");
Xiaohan Wangbca91f92022-01-15 19:56:21617#if BUILDFLAG(IS_WIN)
Peter Kastinga8451362021-02-01 14:18:04618 EXPECT_NE(std::wstring::npos, command_line.GetCommandLineString().find(
619 base::ASCIIToWide(switch2_with_equals)));
sdefresne0e566342015-11-24 08:55:46620#else
621 EXPECT_NE(std::string::npos,
622 command_line.GetCommandLineString().find(switch2_with_equals));
623#endif
624
625 // And it should persist.
Morten Stenshorne7afa5802021-07-15 10:04:43626 const base::Value* entries_list = prefs_.GetList(prefs::kAboutFlagsEntries);
sdefresne0e566342015-11-24 08:55:46627 ASSERT_TRUE(entries_list);
Daniel Cheng354945d2022-02-02 23:39:17628 EXPECT_EQ(2U, entries_list->GetListDeprecated().size());
629 std::string s0 = entries_list->GetListDeprecated()[0].GetString();
sdefresne0e566342015-11-24 08:55:46630 EXPECT_EQ(kFlags1, s0);
Daniel Cheng354945d2022-02-02 23:39:17631 std::string s1 = entries_list->GetListDeprecated()[1].GetString();
sdefresne0e566342015-11-24 08:55:46632 EXPECT_EQ(kFlags2, s1);
633}
634
635// Tests multi-value type entries.
636TEST_F(FlagsStateTest, MultiValues) {
637 const FeatureEntry& entry = kEntries[3];
638 ASSERT_EQ(kFlags4, entry.internal_name);
639
640 // Initially, the first "deactivated" option of the multi entry should
641 // be set.
642 {
643 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
644 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
645 kAddSentinels, kEnableFeatures,
646 kDisableFeatures);
647 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
648 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
649 }
650
651 // Enable the 2nd choice of the multi-value.
jkrcal1383d1d2016-06-17 12:40:56652 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
sdefresne0e566342015-11-24 08:55:46653 true);
654 {
655 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
656 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
657 kAddSentinels, kEnableFeatures,
658 kDisableFeatures);
659 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
660 EXPECT_TRUE(command_line.HasSwitch(kMultiSwitch2));
661 EXPECT_EQ(std::string(kValueForMultiSwitch2),
662 command_line.GetSwitchValueASCII(kMultiSwitch2));
663 }
664
665 // Disable the multi-value entry.
jkrcal1383d1d2016-06-17 12:40:56666 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0),
sdefresne0e566342015-11-24 08:55:46667 true);
668 {
669 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
670 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
671 kAddSentinels, kEnableFeatures,
672 kDisableFeatures);
673 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
674 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
675 }
676}
677
678// Tests that disable flags are added when an entry is disabled.
679TEST_F(FlagsStateTest, DisableFlagCommandLine) {
680 // Nothing selected.
681 {
682 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
683 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
684 kAddSentinels, kEnableFeatures,
685 kDisableFeatures);
686 EXPECT_FALSE(command_line.HasSwitch(kSwitch6));
687 }
688
689 // Disable the entry 6.
690 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, false);
691 {
692 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
693 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
694 kAddSentinels, kEnableFeatures,
695 kDisableFeatures);
696 EXPECT_TRUE(command_line.HasSwitch(kSwitch6));
697 }
698
699 // Enable entry 6.
700 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, true);
701 {
702 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
703 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
704 kAddSentinels, kEnableFeatures,
705 kDisableFeatures);
706 EXPECT_FALSE(command_line.HasSwitch(kSwitch6));
707 }
708}
709
710TEST_F(FlagsStateTest, EnableDisableValues) {
711 const FeatureEntry& entry = kEntries[4];
712 ASSERT_EQ(kFlags5, entry.internal_name);
713
714 // Nothing selected.
715 {
716 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
717 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
718 kAddSentinels, kEnableFeatures,
719 kDisableFeatures);
720 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
721 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
722 }
723
724 // "Enable" option selected.
jkrcal1383d1d2016-06-17 12:40:56725 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(1),
sdefresne0e566342015-11-24 08:55:46726 true);
727 {
728 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
729 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
730 kAddSentinels, kEnableFeatures,
731 kDisableFeatures);
732 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
733 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
734 EXPECT_EQ(kEnableDisableValue1, command_line.GetSwitchValueASCII(kSwitch1));
735 }
736
737 // "Disable" option selected.
jkrcal1383d1d2016-06-17 12:40:56738 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
sdefresne0e566342015-11-24 08:55:46739 true);
740 {
741 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
742 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
743 kAddSentinels, kEnableFeatures,
744 kDisableFeatures);
745 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
746 EXPECT_TRUE(command_line.HasSwitch(kSwitch2));
747 EXPECT_EQ(kEnableDisableValue2, command_line.GetSwitchValueASCII(kSwitch2));
748 }
749
750 // "Default" option selected, same as nothing selected.
jkrcal1383d1d2016-06-17 12:40:56751 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0),
sdefresne0e566342015-11-24 08:55:46752 true);
753 {
754 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
755 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
756 kAddSentinels, kEnableFeatures,
757 kDisableFeatures);
758 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
759 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
760 }
Elly Fong-Jonesc3e9aea2019-10-24 19:44:19761
762 // "Disable" option selected, but flag filtered out by exclude predicate.
763 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
764 true);
765 exclude_flags_.insert(entry.internal_name);
766 {
767 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
768 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
769 kAddSentinels, kEnableFeatures,
770 kDisableFeatures);
771 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
772 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
773 }
774 exclude_flags_.clear();
sdefresne0e566342015-11-24 08:55:46775}
776
777TEST_F(FlagsStateTest, FeatureValues) {
778 const FeatureEntry& entry = kEntries[6];
779 ASSERT_EQ(kFlags7, entry.internal_name);
780
781 struct {
782 int enabled_choice;
783 const char* existing_enable_features;
784 const char* existing_disable_features;
785 const char* expected_enable_features;
786 const char* expected_disable_features;
787 } cases[] = {
788 // Nothing selected.
789 {-1, nullptr, nullptr, "", ""},
790 // "Default" option selected, same as nothing selected.
791 {0, nullptr, nullptr, "", ""},
792 // "Enable" option selected.
jkrcal1383d1d2016-06-17 12:40:56793 {1, nullptr, nullptr, "FeatureName1", ""},
sdefresne0e566342015-11-24 08:55:46794 // "Disable" option selected.
jkrcal1383d1d2016-06-17 12:40:56795 {2, nullptr, nullptr, "", "FeatureName1"},
sdefresne0e566342015-11-24 08:55:46796 // "Enable" option should get added to the existing list.
jkrcal1383d1d2016-06-17 12:40:56797 {1, "Foo,Bar", nullptr, "Foo,Bar,FeatureName1", ""},
sdefresne0e566342015-11-24 08:55:46798 // "Disable" option should get added to the existing list.
jkrcal1383d1d2016-06-17 12:40:56799 {2, nullptr, "Foo,Bar", "", "Foo,Bar,FeatureName1"},
sdefresne0e566342015-11-24 08:55:46800 };
801
Daniel Cheng7b7aaecc2022-02-26 17:57:25802 for (size_t i = 0; i < std::size(cases); ++i) {
sdefresne0e566342015-11-24 08:55:46803 SCOPED_TRACE(base::StringPrintf(
804 "Test[%" PRIuS "]: %d [%s] [%s]", i, cases[i].enabled_choice,
805 cases[i].existing_enable_features ? cases[i].existing_enable_features
806 : "null",
807 cases[i].existing_disable_features ? cases[i].existing_disable_features
808 : "null"));
809
810 if (cases[i].enabled_choice != -1) {
811 flags_state_->SetFeatureEntryEnabled(
jkrcal1383d1d2016-06-17 12:40:56812 &flags_storage_, entry.NameForOption(cases[i].enabled_choice), true);
sdefresne0e566342015-11-24 08:55:46813 }
814
815 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
816 if (cases[i].existing_enable_features) {
817 command_line.AppendSwitchASCII(kEnableFeatures,
818 cases[i].existing_enable_features);
819 }
820 if (cases[i].existing_disable_features) {
821 command_line.AppendSwitchASCII(kDisableFeatures,
822 cases[i].existing_disable_features);
823 }
824
825 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
826 kAddSentinels, kEnableFeatures,
827 kDisableFeatures);
828 EXPECT_EQ(cases[i].expected_enable_features,
829 command_line.GetSwitchValueASCII(kEnableFeatures));
830 EXPECT_EQ(cases[i].expected_disable_features,
831 command_line.GetSwitchValueASCII(kDisableFeatures));
832 }
833}
834
835TEST_F(FlagsStateTest, GetFlagFeatureEntries) {
Morten Stenshorne7afa5802021-07-15 10:04:43836 base::Value::ListStorage supported_entries;
837 base::Value::ListStorage unsupported_entries;
sdefresne0e566342015-11-24 08:55:46838 flags_state_->GetFlagFeatureEntries(&flags_storage_, kGeneralAccessFlagsOnly,
Morten Stenshorne7afa5802021-07-15 10:04:43839 supported_entries, unsupported_entries,
Ken Rockot6fc4e282019-12-20 21:07:16840 base::BindRepeating(&SkipFeatureEntry));
sdefresne0e566342015-11-24 08:55:46841 // All |kEntries| except for |kFlags3| should be supported.
Morten Stenshorne7afa5802021-07-15 10:04:43842 auto supported_count = supported_entries.size();
843 auto unsupported_count = unsupported_entries.size();
844 EXPECT_EQ(11u, supported_count);
845 EXPECT_EQ(1u, unsupported_count);
Daniel Cheng7b7aaecc2022-02-26 17:57:25846 EXPECT_EQ(std::size(kEntries), supported_count + unsupported_count);
sdefresne0e566342015-11-24 08:55:46847}
848
849} // namespace flags_ui