blob: 17a8a9ed7f4894c4d4fb50028e6c114028651615 [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"
15#include "base/feature_list.h"
16#include "base/format_macros.h"
avibc5337b2015-12-25 23:16:3317#include "base/macros.h"
jkrcal1383d1d2016-06-17 12:40:5618#include "base/metrics/field_trial.h"
sdefresne0e566342015-11-24 08:55:4619#include "base/stl_util.h"
20#include "base/strings/stringprintf.h"
21#include "base/strings/utf_string_conversions.h"
asvitkine9499b8d2016-08-09 05:37:0722#include "base/test/scoped_feature_list.h"
sdefresne0e566342015-11-24 08:55:4623#include "base/values.h"
avibc5337b2015-12-25 23:16:3324#include "build/build_config.h"
sdefresne0e566342015-11-24 08:55:4625#include "components/flags_ui/feature_entry.h"
26#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";
sdefresne0e566342015-11-24 08:55:4650
51const char kSwitch1[] = "switch";
52const char kSwitch2[] = "switch2";
53const char kSwitch3[] = "switch3";
54const char kSwitch6[] = "switch6";
55const char kValueForSwitch2[] = "value_for_switch2";
56
Mustafa Emre Acerb3aa36a82018-05-22 21:44:0557const char kStringSwitch[] = "string_switch";
58const char kValueForStringSwitch[] = "value_for_string_switch";
59
sdefresne0e566342015-11-24 08:55:4660const char kMultiSwitch1[] = "multi_switch1";
61const char kMultiSwitch2[] = "multi_switch2";
62const char kValueForMultiSwitch2[] = "value_for_multi_switch2";
63
64const char kEnableDisableValue1[] = "value1";
65const char kEnableDisableValue2[] = "value2";
66
67const char kEnableFeatures[] = "dummy-enable-features";
68const char kDisableFeatures[] = "dummy-disable-features";
69
Maksim Ivanov6fba75b2018-01-18 23:46:0570const char kDummySentinelBeginSwitch[] = "dummy-begin";
71const char kDummySentinelEndSwitch[] = "dummy-end";
72
jkrcal1383d1d2016-06-17 12:40:5673const char kTestTrial[] = "TestTrial";
jkrcal7a3554e2017-03-02 09:01:3574const char kTestParam1[] = "param1";
75const char kTestParam2[] = "param2";
jkrcal05f7ce32016-07-13 16:42:0976const char kTestParamValue[] = "value";
jkrcal1383d1d2016-06-17 12:40:5677
78const base::Feature kTestFeature1{"FeatureName1",
79 base::FEATURE_ENABLED_BY_DEFAULT};
80const base::Feature kTestFeature2{"FeatureName2",
81 base::FEATURE_ENABLED_BY_DEFAULT};
82
jkrcal7a3554e2017-03-02 09:01:3583const FeatureEntry::FeatureParam kTestVariationOther1[] = {
84 {kTestParam1, kTestParamValue}};
85const FeatureEntry::FeatureParam kTestVariationOther2[] = {
86 {kTestParam2, kTestParamValue}};
jkrcal1383d1d2016-06-17 12:40:5687
jkrcal7a3554e2017-03-02 09:01:3588const FeatureEntry::FeatureVariation kTestVariations1[] = {
89 {"dummy description 1", kTestVariationOther1, 1, nullptr}};
90const FeatureEntry::FeatureVariation kTestVariations2[] = {
91 {"dummy description 2", kTestVariationOther2, 1, nullptr}};
jkrcal1383d1d2016-06-17 12:40:5692
vabr0215a8e2017-03-28 12:47:3493const char* kDummyName = nullptr;
94const char* kDummyDescription = nullptr;
sdefresne0e566342015-11-24 08:55:4695
96bool SkipFeatureEntry(const FeatureEntry& feature_entry) {
97 return false;
98}
99
100} // namespace
101
102const FeatureEntry::Choice kMultiChoices[] = {
vabr0215a8e2017-03-28 12:47:34103 {kDummyDescription, "", ""},
104 {kDummyDescription, kMultiSwitch1, ""},
105 {kDummyDescription, kMultiSwitch2, kValueForMultiSwitch2},
sdefresne0e566342015-11-24 08:55:46106};
107
sdefresne0e566342015-11-24 08:55:46108// The entries that are set for these tests. The 3rd entry is not supported on
109// the current platform, all others are.
110static FeatureEntry kEntries[] = {
vabr0215a8e2017-03-28 12:47:34111 {kFlags1, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46112 0, // Ends up being mapped to the current platform.
jkrcal1383d1d2016-06-17 12:40:56113 FeatureEntry::SINGLE_VALUE, kSwitch1, "", nullptr, nullptr, nullptr, 0,
114 nullptr, nullptr, nullptr},
vabr0215a8e2017-03-28 12:47:34115 {kFlags2, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46116 0, // Ends up being mapped to the current platform.
117 FeatureEntry::SINGLE_VALUE, kSwitch2, kValueForSwitch2, nullptr, nullptr,
jkrcal1383d1d2016-06-17 12:40:56118 nullptr, 0, nullptr, nullptr, nullptr},
vabr0215a8e2017-03-28 12:47:34119 {kFlags3, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46120 0, // This ends up enabling for an OS other than the current.
jkrcal1383d1d2016-06-17 12:40:56121 FeatureEntry::SINGLE_VALUE, kSwitch3, "", nullptr, nullptr, nullptr, 0,
122 nullptr, nullptr, nullptr},
vabr0215a8e2017-03-28 12:47:34123 {kFlags4, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46124 0, // Ends up being mapped to the current platform.
jkrcal1383d1d2016-06-17 12:40:56125 FeatureEntry::MULTI_VALUE, "", "", "", "", nullptr,
126 arraysize(kMultiChoices), kMultiChoices, nullptr, nullptr},
vabr0215a8e2017-03-28 12:47:34127 {kFlags5, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46128 0, // Ends up being mapped to the current platform.
129 FeatureEntry::ENABLE_DISABLE_VALUE, kSwitch1, kEnableDisableValue1,
jkrcal1383d1d2016-06-17 12:40:56130 kSwitch2, kEnableDisableValue2, nullptr, 3, nullptr, nullptr, nullptr},
vabr0215a8e2017-03-28 12:47:34131 {kFlags6, kDummyName, kDummyDescription, 0,
sdefresne0e566342015-11-24 08:55:46132 FeatureEntry::SINGLE_DISABLE_VALUE, kSwitch6, "", nullptr, nullptr,
jkrcal1383d1d2016-06-17 12:40:56133 nullptr, 0, nullptr, nullptr, nullptr},
vabr0215a8e2017-03-28 12:47:34134 {kFlags7, kDummyName, kDummyDescription,
sdefresne0e566342015-11-24 08:55:46135 0, // Ends up being mapped to the current platform.
136 FeatureEntry::FEATURE_VALUE, nullptr, nullptr, nullptr, nullptr,
jkrcal1383d1d2016-06-17 12:40:56137 &kTestFeature1, 3, nullptr, nullptr, nullptr},
vabr0215a8e2017-03-28 12:47:34138 {kFlags8, kDummyName, kDummyDescription,
jkrcal1383d1d2016-06-17 12:40:56139 0, // Ends up being mapped to the current platform.
jkrcal531f36752017-03-22 13:44:25140 FeatureEntry::FEATURE_WITH_PARAMS_VALUE, nullptr, nullptr, nullptr,
jkrcal7a3554e2017-03-02 09:01:35141 nullptr, &kTestFeature1, 4, nullptr, kTestVariations1, kTestTrial},
vabr0215a8e2017-03-28 12:47:34142 {kFlags9, kDummyName, kDummyDescription,
jkrcal7a3554e2017-03-02 09:01:35143 0, // Ends up being mapped to the current platform.
jkrcal531f36752017-03-22 13:44:25144 FeatureEntry::FEATURE_WITH_PARAMS_VALUE, nullptr, nullptr, nullptr,
jkrcal7a3554e2017-03-02 09:01:35145 nullptr, &kTestFeature1, 4, nullptr, kTestVariations1, kTestTrial},
vabr0215a8e2017-03-28 12:47:34146 {kFlags10, kDummyName, kDummyDescription,
jkrcal7a3554e2017-03-02 09:01:35147 0, // Ends up being mapped to the current platform.
jkrcal531f36752017-03-22 13:44:25148 FeatureEntry::FEATURE_WITH_PARAMS_VALUE, nullptr, nullptr, nullptr,
jkrcal7a3554e2017-03-02 09:01:35149 nullptr, &kTestFeature2, 4, nullptr, kTestVariations2, kTestTrial},
Mustafa Emre Acerb3aa36a82018-05-22 21:44:05150 {kFlags11, kDummyName, kDummyDescription,
151 0, // Ends up being mapped to the current platform.
152 FeatureEntry::ORIGIN_LIST_VALUE, kStringSwitch, kValueForStringSwitch,
153 nullptr, nullptr, nullptr /* feature */, 0, nullptr, nullptr, nullptr}};
sdefresne0e566342015-11-24 08:55:46154
155class FlagsStateTest : public ::testing::Test {
156 protected:
jkrcal1383d1d2016-06-17 12:40:56157 FlagsStateTest() : flags_storage_(&prefs_), trial_list_(nullptr) {
sdefresne0e566342015-11-24 08:55:46158 prefs_.registry()->RegisterListPref(prefs::kEnabledLabsExperiments);
159
160 for (size_t i = 0; i < arraysize(kEntries); ++i)
161 kEntries[i].supported_platforms = FlagsState::GetCurrentPlatform();
162
163 int os_other_than_current = 1;
164 while (os_other_than_current == FlagsState::GetCurrentPlatform())
165 os_other_than_current <<= 1;
166 kEntries[2].supported_platforms = os_other_than_current;
167 flags_state_.reset(new FlagsState(kEntries, arraysize(kEntries)));
168 }
169
jkrcal05f7ce32016-07-13 16:42:09170 ~FlagsStateTest() override {
171 variations::testing::ClearAllVariationParams();
172 }
173
sdefresne0e566342015-11-24 08:55:46174 TestingPrefServiceSimple prefs_;
175 PrefServiceFlagsStorage flags_storage_;
dcheng84c358e2016-04-26 07:05:53176 std::unique_ptr<FlagsState> flags_state_;
jkrcal1383d1d2016-06-17 12:40:56177 base::FieldTrialList trial_list_;
sdefresne0e566342015-11-24 08:55:46178};
179
180TEST_F(FlagsStateTest, NoChangeNoRestart) {
181 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
182 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, false);
183 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
184
185 // kFlags6 is enabled by default, so enabling should not require a restart.
186 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, true);
187 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
188}
189
190TEST_F(FlagsStateTest, ChangeNeedsRestart) {
191 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
192 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
193 EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges());
194}
195
196// Tests that disabling a default enabled entry requires a restart.
197TEST_F(FlagsStateTest, DisableChangeNeedsRestart) {
198 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
199 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, false);
200 EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges());
201}
202
203TEST_F(FlagsStateTest, MultiFlagChangeNeedsRestart) {
204 const FeatureEntry& entry = kEntries[3];
205 ASSERT_EQ(kFlags4, entry.internal_name);
206 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
207 // Enable the 2nd choice of the multi-value.
jkrcal1383d1d2016-06-17 12:40:56208 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
sdefresne0e566342015-11-24 08:55:46209 true);
210 EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges());
211 flags_state_->Reset();
212 EXPECT_FALSE(flags_state_->IsRestartNeededToCommitChanges());
213 // Enable the default choice now.
jkrcal1383d1d2016-06-17 12:40:56214 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0),
sdefresne0e566342015-11-24 08:55:46215 true);
216 EXPECT_TRUE(flags_state_->IsRestartNeededToCommitChanges());
217}
218
219TEST_F(FlagsStateTest, AddTwoFlagsRemoveOne) {
220 // Add two entries, check they're there.
221 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
222 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true);
223
224 const base::ListValue* entries_list =
225 prefs_.GetList(prefs::kEnabledLabsExperiments);
226 ASSERT_TRUE(entries_list != nullptr);
227
228 ASSERT_EQ(2u, entries_list->GetSize());
229
230 std::string s0;
231 ASSERT_TRUE(entries_list->GetString(0, &s0));
232 std::string s1;
233 ASSERT_TRUE(entries_list->GetString(1, &s1));
234
235 EXPECT_TRUE(s0 == kFlags1 || s1 == kFlags1);
236 EXPECT_TRUE(s0 == kFlags2 || s1 == kFlags2);
237
238 // Remove one entry, check the other's still around.
239 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, false);
240
241 entries_list = prefs_.GetList(prefs::kEnabledLabsExperiments);
242 ASSERT_TRUE(entries_list != nullptr);
243 ASSERT_EQ(1u, entries_list->GetSize());
244 ASSERT_TRUE(entries_list->GetString(0, &s0));
245 EXPECT_TRUE(s0 == kFlags1);
246}
247
248TEST_F(FlagsStateTest, AddTwoFlagsRemoveBoth) {
249 // Add two entries, check the pref exists.
250 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
251 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true);
252 const base::ListValue* entries_list =
253 prefs_.GetList(prefs::kEnabledLabsExperiments);
254 ASSERT_TRUE(entries_list != nullptr);
255
256 // Remove both, the pref should have been removed completely.
257 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, false);
258 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, false);
259 entries_list = prefs_.GetList(prefs::kEnabledLabsExperiments);
260 EXPECT_TRUE(entries_list == nullptr || entries_list->GetSize() == 0);
261}
262
263TEST_F(FlagsStateTest, ConvertFlagsToSwitches) {
264 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
265
266 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
267 command_line.AppendSwitch("foo");
268
269 EXPECT_TRUE(command_line.HasSwitch("foo"));
270 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
271
272 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
273 kAddSentinels, kEnableFeatures,
274 kDisableFeatures);
275
276 EXPECT_TRUE(command_line.HasSwitch("foo"));
277 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
278 EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesBegin));
279 EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesEnd));
280
281 base::CommandLine command_line2(base::CommandLine::NO_PROGRAM);
282
283 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line2,
284 kNoSentinels, kEnableFeatures,
285 kDisableFeatures);
286
287 EXPECT_TRUE(command_line2.HasSwitch(kSwitch1));
288 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesBegin));
289 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesEnd));
290}
291
jkrcal1383d1d2016-06-17 12:40:56292TEST_F(FlagsStateTest, RegisterAllFeatureVariationParameters) {
293 const FeatureEntry& entry = kEntries[7];
jkrcald1d20082016-07-14 15:04:24294 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
295
jkrcal05f7ce32016-07-13 16:42:09296 // Select the "Default" variation.
jkrcal1383d1d2016-06-17 12:40:56297 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0),
298 true);
jkrcald1d20082016-07-14 15:04:24299 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
300 feature_list.get());
jkrcal1383d1d2016-06-17 12:40:56301 // No value should be associated.
jkrcal7a3554e2017-03-02 09:01:35302 EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam1));
jkrcal1383d1d2016-06-17 12:40:56303 // The trial should not be created.
304 base::FieldTrial* trial = base::FieldTrialList::Find(kTestTrial);
305 EXPECT_EQ(nullptr, trial);
306
jkrcal05f7ce32016-07-13 16:42:09307 // Select the default "Enabled" variation.
jkrcal1383d1d2016-06-17 12:40:56308 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(1),
309 true);
310
jkrcald1d20082016-07-14 15:04:24311 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
312 feature_list.get());
jkrcal05f7ce32016-07-13 16:42:09313 // No value should be associated as this is the default option.
jkrcal7a3554e2017-03-02 09:01:35314 EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam1));
jkrcal1383d1d2016-06-17 12:40:56315
316 // The trial should be created.
317 trial = base::FieldTrialList::Find(kTestTrial);
318 EXPECT_NE(nullptr, trial);
319 // The about:flags group should be selected for the trial.
320 EXPECT_EQ(internal::kTrialGroupAboutFlags, trial->group_name());
321
jkrcal05f7ce32016-07-13 16:42:09322 // Select the only one variation.
jkrcal1383d1d2016-06-17 12:40:56323 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
324 true);
jkrcald1d20082016-07-14 15:04:24325 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
326 feature_list.get());
jkrcal1383d1d2016-06-17 12:40:56327 // Associating for the second time should not change the value.
jkrcal7a3554e2017-03-02 09:01:35328 EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam1));
jkrcal05f7ce32016-07-13 16:42:09329}
330
331TEST_F(FlagsStateTest, RegisterAllFeatureVariationParametersNonDefault) {
332 const FeatureEntry& entry = kEntries[7];
jkrcald1d20082016-07-14 15:04:24333 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
334
jkrcal05f7ce32016-07-13 16:42:09335 // Select the only one variation.
336 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
337 true);
jkrcald1d20082016-07-14 15:04:24338 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
339 feature_list.get());
340
341 // Set the feature_list as the main instance so that
342 // variations::GetVariationParamValueByFeature below works.
asvitkine9499b8d2016-08-09 05:37:07343 base::test::ScopedFeatureList scoped_feature_list;
344 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
jkrcald1d20082016-07-14 15:04:24345
jkrcal05f7ce32016-07-13 16:42:09346 // The param should have the value predefined in this variation.
347 EXPECT_EQ(kTestParamValue,
jkrcal7a3554e2017-03-02 09:01:35348 variations::GetVariationParamValue(kTestTrial, kTestParam1));
jkrcald1d20082016-07-14 15:04:24349
350 // The value should be associated also via the name of the feature.
351 EXPECT_EQ(kTestParamValue, variations::GetVariationParamValueByFeature(
jkrcal7a3554e2017-03-02 09:01:35352 kTestFeature1, kTestParam1));
353}
354
355TEST_F(FlagsStateTest, RegisterAllFeatureVariationParametersWithDefaultTrials) {
356 const FeatureEntry& entry1 = kEntries[8];
357 const FeatureEntry& entry2 = kEntries[9];
358 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
359
360 // Select the only one variation for each FeatureEntry.
361 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry1.NameForOption(2),
362 true);
363 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry2.NameForOption(2),
364 true);
365 flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_,
366 feature_list.get());
367
368 // Set the feature_list as the main instance so that
369 // variations::GetVariationParamValueByFeature below works.
370 base::test::ScopedFeatureList scoped_feature_list;
371 scoped_feature_list.InitWithFeatureList(std::move(feature_list));
372
373 // The params should have the values predefined in these variations
374 // (accessible via the names of the features).
375 EXPECT_EQ(kTestParamValue, variations::GetVariationParamValueByFeature(
376 kTestFeature1, kTestParam1));
377 EXPECT_EQ(kTestParamValue, variations::GetVariationParamValueByFeature(
378 kTestFeature2, kTestParam2));
379 // The params are registered in the same trial.
380 EXPECT_EQ(kTestParamValue,
381 variations::GetVariationParamValue(kTestTrial, kTestParam1));
382 EXPECT_EQ(kTestParamValue,
383 variations::GetVariationParamValue(kTestTrial, kTestParam2));
jkrcal1383d1d2016-06-17 12:40:56384}
385
sdefresne0e566342015-11-24 08:55:46386base::CommandLine::StringType CreateSwitch(const std::string& value) {
387#if defined(OS_WIN)
388 return base::ASCIIToUTF16(value);
389#else
390 return value;
391#endif
392}
393
394TEST_F(FlagsStateTest, CompareSwitchesToCurrentCommandLine) {
Maksim Ivanov6fba75b2018-01-18 23:46:05395 // Start with the active command line containing no flags, and the new command
396 // line having the |kFlags1| flag.
397
sdefresne0e566342015-11-24 08:55:46398 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
399
400 const std::string kDoubleDash("--");
401
402 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
403 command_line.AppendSwitch("foo");
404
405 base::CommandLine new_command_line(base::CommandLine::NO_PROGRAM);
406 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &new_command_line,
407 kAddSentinels, kEnableFeatures,
408 kDisableFeatures);
409
410 EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
411 new_command_line, command_line, nullptr, nullptr, nullptr));
412 {
413 std::set<base::CommandLine::StringType> difference;
414 EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
415 new_command_line, command_line, &difference, nullptr, nullptr));
416 EXPECT_EQ(1U, difference.size());
417 EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1)));
418 }
419
Maksim Ivanov6fba75b2018-01-18 23:46:05420 // Now both command lines have the |kFlags1| flag.
421
sdefresne0e566342015-11-24 08:55:46422 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
423 kAddSentinels, kEnableFeatures,
424 kDisableFeatures);
425
426 EXPECT_TRUE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
427 new_command_line, command_line, nullptr, nullptr, nullptr));
428 {
429 std::set<base::CommandLine::StringType> difference;
430 EXPECT_TRUE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
431 new_command_line, command_line, &difference, nullptr, nullptr));
432 EXPECT_TRUE(difference.empty());
433 }
434
Maksim Ivanov6fba75b2018-01-18 23:46:05435 // Now the active command line has the |kFlags2| flag, and the new command
436 // line has the |kFlags1| flag.
437
sdefresne0e566342015-11-24 08:55:46438 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, false);
439 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true);
440
441 base::CommandLine another_command_line(base::CommandLine::NO_PROGRAM);
442 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &another_command_line,
443 kAddSentinels, kEnableFeatures,
444 kDisableFeatures);
445
446 EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
447 new_command_line, another_command_line, nullptr, nullptr, nullptr));
448 {
449 std::set<base::CommandLine::StringType> difference;
450 EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
451 new_command_line, another_command_line, &difference, nullptr, nullptr));
452 EXPECT_EQ(2U, difference.size());
453 EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1)));
454 EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch2 + "=" +
455 kValueForSwitch2)));
456 }
Maksim Ivanov6fba75b2018-01-18 23:46:05457
458 // Now both command lines have both flags |kFlags1| and |kFlags2|, but each
459 // flag is surrounded by dummy sentinels in one of the command lines.
460
461 new_command_line.AppendSwitch(kDummySentinelBeginSwitch);
462 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &new_command_line,
463 kNoSentinels, kEnableFeatures,
464 kDisableFeatures);
465 new_command_line.AppendSwitch(kDummySentinelEndSwitch);
466
467 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
468 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, false);
469
470 another_command_line.AppendSwitch(kDummySentinelBeginSwitch);
471 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &another_command_line,
472 kNoSentinels, kEnableFeatures,
473 kDisableFeatures);
474 another_command_line.AppendSwitch(kDummySentinelEndSwitch);
475
476 EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
477 new_command_line, another_command_line, nullptr, nullptr, nullptr));
478 EXPECT_TRUE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
479 new_command_line, another_command_line, nullptr,
480 kDummySentinelBeginSwitch, kDummySentinelEndSwitch));
481
482 // Now the new command line additionally contains |kFlags3|, which is
483 // followed by another dummy end sentinel.
484
485 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, false);
486 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags3, true);
487
488 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &new_command_line,
489 kNoSentinels, kEnableFeatures,
490 kDisableFeatures);
491 new_command_line.AppendSwitch(kDummySentinelEndSwitch);
492
493 EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
494 new_command_line, another_command_line, nullptr,
495 kDummySentinelBeginSwitch, kDummySentinelEndSwitch));
496
497 // Now both command lines contain the |kFlags3| flag followed by the second
498 // dummy end sentinel.
499
500 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &another_command_line,
501 kNoSentinels, kEnableFeatures,
502 kDisableFeatures);
503 another_command_line.AppendSwitch(kDummySentinelEndSwitch);
504
505 EXPECT_FALSE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
506 new_command_line, another_command_line, nullptr, nullptr, nullptr));
507 EXPECT_TRUE(FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
508 new_command_line, another_command_line, nullptr,
509 kDummySentinelBeginSwitch, kDummySentinelEndSwitch));
sdefresne0e566342015-11-24 08:55:46510}
511
512TEST_F(FlagsStateTest, RemoveFlagSwitches) {
Jeremy Roman863386d2017-10-31 19:25:38513 base::CommandLine::SwitchMap switch_list;
sdefresne0e566342015-11-24 08:55:46514 switch_list[kSwitch1] = base::CommandLine::StringType();
515 switch_list[switches::kFlagSwitchesBegin] = base::CommandLine::StringType();
516 switch_list[switches::kFlagSwitchesEnd] = base::CommandLine::StringType();
517 switch_list["foo"] = base::CommandLine::StringType();
518
519 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
520
521 // This shouldn't do anything before ConvertFlagsToSwitches() wasn't called.
522 flags_state_->RemoveFlagsSwitches(&switch_list);
523 ASSERT_EQ(4u, switch_list.size());
skyostil46384412016-08-12 14:33:39524 EXPECT_TRUE(base::ContainsKey(switch_list, kSwitch1));
525 EXPECT_TRUE(base::ContainsKey(switch_list, switches::kFlagSwitchesBegin));
526 EXPECT_TRUE(base::ContainsKey(switch_list, switches::kFlagSwitchesEnd));
527 EXPECT_TRUE(base::ContainsKey(switch_list, "foo"));
sdefresne0e566342015-11-24 08:55:46528
529 // Call ConvertFlagsToSwitches(), then RemoveFlagsSwitches() again.
530 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
531 command_line.AppendSwitch("foo");
532 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
533 kAddSentinels, kEnableFeatures,
534 kDisableFeatures);
535 flags_state_->RemoveFlagsSwitches(&switch_list);
536
537 // Now the about:flags-related switch should have been removed.
538 ASSERT_EQ(1u, switch_list.size());
skyostil46384412016-08-12 14:33:39539 EXPECT_TRUE(base::ContainsKey(switch_list, "foo"));
sdefresne0e566342015-11-24 08:55:46540}
541
542TEST_F(FlagsStateTest, RemoveFlagSwitches_Features) {
543 struct {
544 int enabled_choice; // 0: default, 1: enabled, 2: disabled.
545 const char* existing_enable_features;
546 const char* existing_disable_features;
547 const char* expected_enable_features;
548 const char* expected_disable_features;
549 } cases[] = {
550 // Default value: Should not affect existing flags.
551 {0, nullptr, nullptr, nullptr, nullptr},
552 {0, "A,B", "C", "A,B", "C"},
553 // "Enable" option: should only affect enabled list.
jkrcal1383d1d2016-06-17 12:40:56554 {1, nullptr, nullptr, "FeatureName1", nullptr},
555 {1, "A,B", "C", "A,B,FeatureName1", "C"},
sdefresne0e566342015-11-24 08:55:46556 // "Disable" option: should only affect disabled list.
jkrcal1383d1d2016-06-17 12:40:56557 {2, nullptr, nullptr, nullptr, "FeatureName1"},
558 {2, "A,B", "C", "A,B", "C,FeatureName1"},
sdefresne0e566342015-11-24 08:55:46559 };
560
561 for (size_t i = 0; i < arraysize(cases); ++i) {
562 SCOPED_TRACE(base::StringPrintf(
563 "Test[%" PRIuS "]: %d [%s] [%s]", i, cases[i].enabled_choice,
564 cases[i].existing_enable_features ? cases[i].existing_enable_features
565 : "null",
566 cases[i].existing_disable_features ? cases[i].existing_disable_features
567 : "null"));
568
569 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
570 if (cases[i].existing_enable_features) {
571 command_line.AppendSwitchASCII(kEnableFeatures,
572 cases[i].existing_enable_features);
573 }
574 if (cases[i].existing_disable_features) {
575 command_line.AppendSwitchASCII(kDisableFeatures,
576 cases[i].existing_disable_features);
577 }
578
579 flags_state_->Reset();
580
581 const std::string entry_name = base::StringPrintf(
582 "%s%s%d", kFlags7, testing::kMultiSeparator, cases[i].enabled_choice);
583 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry_name, true);
584
585 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
586 kAddSentinels, kEnableFeatures,
587 kDisableFeatures);
588 auto switch_list = command_line.GetSwitches();
589 EXPECT_EQ(cases[i].expected_enable_features != nullptr,
skyostil46384412016-08-12 14:33:39590 base::ContainsKey(switch_list, kEnableFeatures));
sdefresne0e566342015-11-24 08:55:46591 if (cases[i].expected_enable_features)
592 EXPECT_EQ(CreateSwitch(cases[i].expected_enable_features),
593 switch_list[kEnableFeatures]);
594
595 EXPECT_EQ(cases[i].expected_disable_features != nullptr,
skyostil46384412016-08-12 14:33:39596 base::ContainsKey(switch_list, kDisableFeatures));
sdefresne0e566342015-11-24 08:55:46597 if (cases[i].expected_disable_features)
598 EXPECT_EQ(CreateSwitch(cases[i].expected_disable_features),
599 switch_list[kDisableFeatures]);
600
601 // RemoveFlagsSwitches() should result in the original values for these
602 // switches.
603 switch_list = command_line.GetSwitches();
604 flags_state_->RemoveFlagsSwitches(&switch_list);
605 EXPECT_EQ(cases[i].existing_enable_features != nullptr,
skyostil46384412016-08-12 14:33:39606 base::ContainsKey(switch_list, kEnableFeatures));
sdefresne0e566342015-11-24 08:55:46607 if (cases[i].existing_enable_features)
608 EXPECT_EQ(CreateSwitch(cases[i].existing_enable_features),
609 switch_list[kEnableFeatures]);
610 EXPECT_EQ(cases[i].existing_disable_features != nullptr,
skyostil46384412016-08-12 14:33:39611 base::ContainsKey(switch_list, kEnableFeatures));
sdefresne0e566342015-11-24 08:55:46612 if (cases[i].existing_disable_features)
613 EXPECT_EQ(CreateSwitch(cases[i].existing_disable_features),
614 switch_list[kDisableFeatures]);
615 }
616}
617
618// Tests enabling entries that aren't supported on the current platform.
619TEST_F(FlagsStateTest, PersistAndPrune) {
620 // Enable entries 1 and 3.
621 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
622 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags3, true);
623 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
624 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
625 EXPECT_FALSE(command_line.HasSwitch(kSwitch3));
626
627 // Convert the flags to switches. Entry 3 shouldn't be among the switches
628 // as it is not applicable to the current platform.
629 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
630 kAddSentinels, kEnableFeatures,
631 kDisableFeatures);
632 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
633 EXPECT_FALSE(command_line.HasSwitch(kSwitch3));
634
635 // FeatureEntry 3 should show still be persisted in preferences though.
636 const base::ListValue* entries_list =
637 prefs_.GetList(prefs::kEnabledLabsExperiments);
638 ASSERT_TRUE(entries_list);
639 EXPECT_EQ(2U, entries_list->GetSize());
640 std::string s0;
641 ASSERT_TRUE(entries_list->GetString(0, &s0));
642 EXPECT_EQ(kFlags1, s0);
643 std::string s1;
644 ASSERT_TRUE(entries_list->GetString(1, &s1));
645 EXPECT_EQ(kFlags3, s1);
646}
647
648// Tests that switches which should have values get them in the command
649// line.
650TEST_F(FlagsStateTest, CheckValues) {
651 // Enable entries 1 and 2.
652 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags1, true);
653 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags2, true);
654 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
655 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
656 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
657
658 // Convert the flags to switches.
659 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
660 kAddSentinels, kEnableFeatures,
661 kDisableFeatures);
662 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
663 EXPECT_EQ(std::string(), command_line.GetSwitchValueASCII(kSwitch1));
664 EXPECT_TRUE(command_line.HasSwitch(kSwitch2));
665 EXPECT_EQ(std::string(kValueForSwitch2),
666 command_line.GetSwitchValueASCII(kSwitch2));
667
668 // Confirm that there is no '=' in the command line for simple switches.
669 std::string switch1_with_equals =
670 std::string("--") + std::string(kSwitch1) + std::string("=");
671#if defined(OS_WIN)
672 EXPECT_EQ(base::string16::npos, command_line.GetCommandLineString().find(
673 base::ASCIIToUTF16(switch1_with_equals)));
674#else
675 EXPECT_EQ(std::string::npos,
676 command_line.GetCommandLineString().find(switch1_with_equals));
677#endif
678
679 // And confirm there is a '=' for switches with values.
680 std::string switch2_with_equals =
681 std::string("--") + std::string(kSwitch2) + std::string("=");
682#if defined(OS_WIN)
683 EXPECT_NE(base::string16::npos, command_line.GetCommandLineString().find(
684 base::ASCIIToUTF16(switch2_with_equals)));
685#else
686 EXPECT_NE(std::string::npos,
687 command_line.GetCommandLineString().find(switch2_with_equals));
688#endif
689
690 // And it should persist.
691 const base::ListValue* entries_list =
692 prefs_.GetList(prefs::kEnabledLabsExperiments);
693 ASSERT_TRUE(entries_list);
694 EXPECT_EQ(2U, entries_list->GetSize());
695 std::string s0;
696 ASSERT_TRUE(entries_list->GetString(0, &s0));
697 EXPECT_EQ(kFlags1, s0);
698 std::string s1;
699 ASSERT_TRUE(entries_list->GetString(1, &s1));
700 EXPECT_EQ(kFlags2, s1);
701}
702
703// Tests multi-value type entries.
704TEST_F(FlagsStateTest, MultiValues) {
705 const FeatureEntry& entry = kEntries[3];
706 ASSERT_EQ(kFlags4, entry.internal_name);
707
708 // Initially, the first "deactivated" option of the multi entry should
709 // be set.
710 {
711 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
712 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
713 kAddSentinels, kEnableFeatures,
714 kDisableFeatures);
715 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
716 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
717 }
718
719 // Enable the 2nd choice of the multi-value.
jkrcal1383d1d2016-06-17 12:40:56720 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
sdefresne0e566342015-11-24 08:55:46721 true);
722 {
723 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
724 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
725 kAddSentinels, kEnableFeatures,
726 kDisableFeatures);
727 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
728 EXPECT_TRUE(command_line.HasSwitch(kMultiSwitch2));
729 EXPECT_EQ(std::string(kValueForMultiSwitch2),
730 command_line.GetSwitchValueASCII(kMultiSwitch2));
731 }
732
733 // Disable the multi-value entry.
jkrcal1383d1d2016-06-17 12:40:56734 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0),
sdefresne0e566342015-11-24 08:55:46735 true);
736 {
737 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
738 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
739 kAddSentinels, kEnableFeatures,
740 kDisableFeatures);
741 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
742 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
743 }
744}
745
746// Tests that disable flags are added when an entry is disabled.
747TEST_F(FlagsStateTest, DisableFlagCommandLine) {
748 // Nothing selected.
749 {
750 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
751 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
752 kAddSentinels, kEnableFeatures,
753 kDisableFeatures);
754 EXPECT_FALSE(command_line.HasSwitch(kSwitch6));
755 }
756
757 // Disable the entry 6.
758 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, false);
759 {
760 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
761 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
762 kAddSentinels, kEnableFeatures,
763 kDisableFeatures);
764 EXPECT_TRUE(command_line.HasSwitch(kSwitch6));
765 }
766
767 // Enable entry 6.
768 flags_state_->SetFeatureEntryEnabled(&flags_storage_, kFlags6, true);
769 {
770 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
771 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
772 kAddSentinels, kEnableFeatures,
773 kDisableFeatures);
774 EXPECT_FALSE(command_line.HasSwitch(kSwitch6));
775 }
776}
777
778TEST_F(FlagsStateTest, EnableDisableValues) {
779 const FeatureEntry& entry = kEntries[4];
780 ASSERT_EQ(kFlags5, entry.internal_name);
781
782 // Nothing selected.
783 {
784 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
785 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
786 kAddSentinels, kEnableFeatures,
787 kDisableFeatures);
788 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
789 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
790 }
791
792 // "Enable" option selected.
jkrcal1383d1d2016-06-17 12:40:56793 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(1),
sdefresne0e566342015-11-24 08:55:46794 true);
795 {
796 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
797 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
798 kAddSentinels, kEnableFeatures,
799 kDisableFeatures);
800 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
801 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
802 EXPECT_EQ(kEnableDisableValue1, command_line.GetSwitchValueASCII(kSwitch1));
803 }
804
805 // "Disable" option selected.
jkrcal1383d1d2016-06-17 12:40:56806 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2),
sdefresne0e566342015-11-24 08:55:46807 true);
808 {
809 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
810 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
811 kAddSentinels, kEnableFeatures,
812 kDisableFeatures);
813 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
814 EXPECT_TRUE(command_line.HasSwitch(kSwitch2));
815 EXPECT_EQ(kEnableDisableValue2, command_line.GetSwitchValueASCII(kSwitch2));
816 }
817
818 // "Default" option selected, same as nothing selected.
jkrcal1383d1d2016-06-17 12:40:56819 flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0),
sdefresne0e566342015-11-24 08:55:46820 true);
821 {
822 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
823 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
824 kAddSentinels, kEnableFeatures,
825 kDisableFeatures);
826 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
827 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
828 }
829}
830
831TEST_F(FlagsStateTest, FeatureValues) {
832 const FeatureEntry& entry = kEntries[6];
833 ASSERT_EQ(kFlags7, entry.internal_name);
834
835 struct {
836 int enabled_choice;
837 const char* existing_enable_features;
838 const char* existing_disable_features;
839 const char* expected_enable_features;
840 const char* expected_disable_features;
841 } cases[] = {
842 // Nothing selected.
843 {-1, nullptr, nullptr, "", ""},
844 // "Default" option selected, same as nothing selected.
845 {0, nullptr, nullptr, "", ""},
846 // "Enable" option selected.
jkrcal1383d1d2016-06-17 12:40:56847 {1, nullptr, nullptr, "FeatureName1", ""},
sdefresne0e566342015-11-24 08:55:46848 // "Disable" option selected.
jkrcal1383d1d2016-06-17 12:40:56849 {2, nullptr, nullptr, "", "FeatureName1"},
sdefresne0e566342015-11-24 08:55:46850 // "Enable" option should get added to the existing list.
jkrcal1383d1d2016-06-17 12:40:56851 {1, "Foo,Bar", nullptr, "Foo,Bar,FeatureName1", ""},
sdefresne0e566342015-11-24 08:55:46852 // "Disable" option should get added to the existing list.
jkrcal1383d1d2016-06-17 12:40:56853 {2, nullptr, "Foo,Bar", "", "Foo,Bar,FeatureName1"},
sdefresne0e566342015-11-24 08:55:46854 };
855
856 for (size_t i = 0; i < arraysize(cases); ++i) {
857 SCOPED_TRACE(base::StringPrintf(
858 "Test[%" PRIuS "]: %d [%s] [%s]", i, cases[i].enabled_choice,
859 cases[i].existing_enable_features ? cases[i].existing_enable_features
860 : "null",
861 cases[i].existing_disable_features ? cases[i].existing_disable_features
862 : "null"));
863
864 if (cases[i].enabled_choice != -1) {
865 flags_state_->SetFeatureEntryEnabled(
jkrcal1383d1d2016-06-17 12:40:56866 &flags_storage_, entry.NameForOption(cases[i].enabled_choice), true);
sdefresne0e566342015-11-24 08:55:46867 }
868
869 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
870 if (cases[i].existing_enable_features) {
871 command_line.AppendSwitchASCII(kEnableFeatures,
872 cases[i].existing_enable_features);
873 }
874 if (cases[i].existing_disable_features) {
875 command_line.AppendSwitchASCII(kDisableFeatures,
876 cases[i].existing_disable_features);
877 }
878
879 flags_state_->ConvertFlagsToSwitches(&flags_storage_, &command_line,
880 kAddSentinels, kEnableFeatures,
881 kDisableFeatures);
882 EXPECT_EQ(cases[i].expected_enable_features,
883 command_line.GetSwitchValueASCII(kEnableFeatures));
884 EXPECT_EQ(cases[i].expected_disable_features,
885 command_line.GetSwitchValueASCII(kDisableFeatures));
886 }
887}
888
889TEST_F(FlagsStateTest, GetFlagFeatureEntries) {
890 base::ListValue supported_entries;
891 base::ListValue unsupported_entries;
892 flags_state_->GetFlagFeatureEntries(&flags_storage_, kGeneralAccessFlagsOnly,
893 &supported_entries, &unsupported_entries,
894 base::Bind(&SkipFeatureEntry));
895 // All |kEntries| except for |kFlags3| should be supported.
Mustafa Emre Acerb3aa36a82018-05-22 21:44:05896 EXPECT_EQ(10u, supported_entries.GetSize());
sdefresne0e566342015-11-24 08:55:46897 EXPECT_EQ(1u, unsupported_entries.GetSize());
898 EXPECT_EQ(arraysize(kEntries),
899 supported_entries.GetSize() + unsupported_entries.GetSize());
900}
901
902} // namespace flags_ui