[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / about_flags_unittest.cc
blob0cb9fa78835f36a552cf7fe0ffe1ed07170e7871
1 // Copyright (c) 2011 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.
5 #include "base/prefs/pref_registry_simple.h"
6 #include "base/prefs/testing_pref_service.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/values.h"
10 #include "chrome/browser/about_flags.h"
11 #include "chrome/browser/pref_service_flags_storage.h"
12 #include "chrome/common/chrome_switches.h"
13 #include "chrome/common/pref_names.h"
14 #include "grit/chromium_strings.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 const char kFlags1[] = "flag1";
18 const char kFlags2[] = "flag2";
19 const char kFlags3[] = "flag3";
20 const char kFlags4[] = "flag4";
21 const char kFlags5[] = "flag5";
23 const char kSwitch1[] = "switch";
24 const char kSwitch2[] = "switch2";
25 const char kSwitch3[] = "switch3";
26 const char kValueForSwitch2[] = "value_for_switch2";
28 const char kMultiSwitch1[] = "multi_switch1";
29 const char kMultiSwitch2[] = "multi_switch2";
30 const char kValueForMultiSwitch2[] = "value_for_multi_switch2";
32 const char kEnableDisableValue1[] = "value1";
33 const char kEnableDisableValue2[] = "value2";
35 namespace about_flags {
37 const Experiment::Choice kMultiChoices[] = {
38 { IDS_PRODUCT_NAME, "", "" },
39 { IDS_PRODUCT_NAME, kMultiSwitch1, "" },
40 { IDS_PRODUCT_NAME, kMultiSwitch2, kValueForMultiSwitch2 },
43 // The experiments that are set for these tests. The 3rd experiment is not
44 // supported on the current platform, all others are.
45 static Experiment kExperiments[] = {
47 kFlags1,
48 IDS_PRODUCT_NAME,
49 IDS_PRODUCT_NAME,
50 0, // Ends up being mapped to the current platform.
51 Experiment::SINGLE_VALUE,
52 kSwitch1,
53 "",
54 NULL,
55 NULL,
56 NULL,
60 kFlags2,
61 IDS_PRODUCT_NAME,
62 IDS_PRODUCT_NAME,
63 0, // Ends up being mapped to the current platform.
64 Experiment::SINGLE_VALUE,
65 kSwitch2,
66 kValueForSwitch2,
67 NULL,
68 NULL,
69 NULL,
73 kFlags3,
74 IDS_PRODUCT_NAME,
75 IDS_PRODUCT_NAME,
76 0, // This ends up enabling for an OS other than the current.
77 Experiment::SINGLE_VALUE,
78 kSwitch3,
79 "",
80 NULL,
81 NULL,
82 NULL,
86 kFlags4,
87 IDS_PRODUCT_NAME,
88 IDS_PRODUCT_NAME,
89 0, // Ends up being mapped to the current platform.
90 Experiment::MULTI_VALUE,
91 "",
92 "",
93 "",
94 "",
95 kMultiChoices,
96 arraysize(kMultiChoices)
99 kFlags5,
100 IDS_PRODUCT_NAME,
101 IDS_PRODUCT_NAME,
102 0, // Ends up being mapped to the current platform.
103 Experiment::ENABLE_DISABLE_VALUE,
104 kSwitch1,
105 kEnableDisableValue1,
106 kSwitch2,
107 kEnableDisableValue2,
108 NULL,
113 class AboutFlagsTest : public ::testing::Test {
114 protected:
115 AboutFlagsTest() : flags_storage_(&prefs_) {
116 prefs_.registry()->RegisterListPref(prefs::kEnabledLabsExperiments);
117 testing::ClearState();
120 virtual void SetUp() OVERRIDE {
121 for (size_t i = 0; i < arraysize(kExperiments); ++i)
122 kExperiments[i].supported_platforms = GetCurrentPlatform();
124 int os_other_than_current = 1;
125 while (os_other_than_current == GetCurrentPlatform())
126 os_other_than_current <<= 1;
127 kExperiments[2].supported_platforms = os_other_than_current;
129 testing::SetExperiments(kExperiments, arraysize(kExperiments));
132 virtual void TearDown() OVERRIDE {
133 testing::SetExperiments(NULL, 0);
136 TestingPrefServiceSimple prefs_;
137 PrefServiceFlagsStorage flags_storage_;
141 TEST_F(AboutFlagsTest, NoChangeNoRestart) {
142 EXPECT_FALSE(IsRestartNeededToCommitChanges());
143 SetExperimentEnabled(&flags_storage_, kFlags1, false);
144 EXPECT_FALSE(IsRestartNeededToCommitChanges());
147 TEST_F(AboutFlagsTest, ChangeNeedsRestart) {
148 EXPECT_FALSE(IsRestartNeededToCommitChanges());
149 SetExperimentEnabled(&flags_storage_, kFlags1, true);
150 EXPECT_TRUE(IsRestartNeededToCommitChanges());
153 TEST_F(AboutFlagsTest, MultiFlagChangeNeedsRestart) {
154 const Experiment& experiment = kExperiments[3];
155 ASSERT_EQ(kFlags4, experiment.internal_name);
156 EXPECT_FALSE(IsRestartNeededToCommitChanges());
157 // Enable the 2nd choice of the multi-value.
158 SetExperimentEnabled(&flags_storage_, experiment.NameForChoice(2), true);
159 EXPECT_TRUE(IsRestartNeededToCommitChanges());
160 testing::ClearState();
161 EXPECT_FALSE(IsRestartNeededToCommitChanges());
162 // Enable the default choice now.
163 SetExperimentEnabled(&flags_storage_, experiment.NameForChoice(0), true);
164 EXPECT_TRUE(IsRestartNeededToCommitChanges());
167 TEST_F(AboutFlagsTest, AddTwoFlagsRemoveOne) {
168 // Add two experiments, check they're there.
169 SetExperimentEnabled(&flags_storage_, kFlags1, true);
170 SetExperimentEnabled(&flags_storage_, kFlags2, true);
172 const base::ListValue* experiments_list = prefs_.GetList(
173 prefs::kEnabledLabsExperiments);
174 ASSERT_TRUE(experiments_list != NULL);
176 ASSERT_EQ(2u, experiments_list->GetSize());
178 std::string s0;
179 ASSERT_TRUE(experiments_list->GetString(0, &s0));
180 std::string s1;
181 ASSERT_TRUE(experiments_list->GetString(1, &s1));
183 EXPECT_TRUE(s0 == kFlags1 || s1 == kFlags1);
184 EXPECT_TRUE(s0 == kFlags2 || s1 == kFlags2);
186 // Remove one experiment, check the other's still around.
187 SetExperimentEnabled(&flags_storage_, kFlags2, false);
189 experiments_list = prefs_.GetList(prefs::kEnabledLabsExperiments);
190 ASSERT_TRUE(experiments_list != NULL);
191 ASSERT_EQ(1u, experiments_list->GetSize());
192 ASSERT_TRUE(experiments_list->GetString(0, &s0));
193 EXPECT_TRUE(s0 == kFlags1);
196 TEST_F(AboutFlagsTest, AddTwoFlagsRemoveBoth) {
197 // Add two experiments, check the pref exists.
198 SetExperimentEnabled(&flags_storage_, kFlags1, true);
199 SetExperimentEnabled(&flags_storage_, kFlags2, true);
200 const base::ListValue* experiments_list = prefs_.GetList(
201 prefs::kEnabledLabsExperiments);
202 ASSERT_TRUE(experiments_list != NULL);
204 // Remove both, the pref should have been removed completely.
205 SetExperimentEnabled(&flags_storage_, kFlags1, false);
206 SetExperimentEnabled(&flags_storage_, kFlags2, false);
207 experiments_list = prefs_.GetList(prefs::kEnabledLabsExperiments);
208 EXPECT_TRUE(experiments_list == NULL || experiments_list->GetSize() == 0);
211 TEST_F(AboutFlagsTest, ConvertFlagsToSwitches) {
212 SetExperimentEnabled(&flags_storage_, kFlags1, true);
214 CommandLine command_line(CommandLine::NO_PROGRAM);
215 command_line.AppendSwitch("foo");
217 EXPECT_TRUE(command_line.HasSwitch("foo"));
218 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
220 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
222 EXPECT_TRUE(command_line.HasSwitch("foo"));
223 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
224 EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesBegin));
225 EXPECT_TRUE(command_line.HasSwitch(switches::kFlagSwitchesEnd));
227 CommandLine command_line2(CommandLine::NO_PROGRAM);
229 ConvertFlagsToSwitches(&flags_storage_, &command_line2, kNoSentinels);
231 EXPECT_TRUE(command_line2.HasSwitch(kSwitch1));
232 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesBegin));
233 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesEnd));
236 TEST_F(AboutFlagsTest, CompareSwitchesToCurrentCommandLine) {
237 SetExperimentEnabled(&flags_storage_, kFlags1, true);
239 CommandLine command_line(CommandLine::NO_PROGRAM);
240 command_line.AppendSwitch("foo");
242 CommandLine new_command_line(CommandLine::NO_PROGRAM);
243 ConvertFlagsToSwitches(&flags_storage_, &new_command_line, kAddSentinels);
245 EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line,
246 command_line));
248 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
250 EXPECT_TRUE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line,
251 command_line));
253 // Now both have flags but different.
254 SetExperimentEnabled(&flags_storage_, kFlags1, false);
255 SetExperimentEnabled(&flags_storage_, kFlags2, true);
257 CommandLine another_command_line(CommandLine::NO_PROGRAM);
258 ConvertFlagsToSwitches(&flags_storage_, &another_command_line, kAddSentinels);
260 EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line,
261 another_command_line));
264 TEST_F(AboutFlagsTest, RemoveFlagSwitches) {
265 std::map<std::string, CommandLine::StringType> switch_list;
266 switch_list[kSwitch1] = CommandLine::StringType();
267 switch_list[switches::kFlagSwitchesBegin] = CommandLine::StringType();
268 switch_list[switches::kFlagSwitchesEnd] = CommandLine::StringType();
269 switch_list["foo"] = CommandLine::StringType();
271 SetExperimentEnabled(&flags_storage_, kFlags1, true);
273 // This shouldn't do anything before ConvertFlagsToSwitches() wasn't called.
274 RemoveFlagsSwitches(&switch_list);
275 ASSERT_EQ(4u, switch_list.size());
276 EXPECT_TRUE(switch_list.find(kSwitch1) != switch_list.end());
277 EXPECT_TRUE(switch_list.find(switches::kFlagSwitchesBegin) !=
278 switch_list.end());
279 EXPECT_TRUE(switch_list.find(switches::kFlagSwitchesEnd) !=
280 switch_list.end());
281 EXPECT_TRUE(switch_list.find("foo") != switch_list.end());
283 // Call ConvertFlagsToSwitches(), then RemoveFlagsSwitches() again.
284 CommandLine command_line(CommandLine::NO_PROGRAM);
285 command_line.AppendSwitch("foo");
286 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
287 RemoveFlagsSwitches(&switch_list);
289 // Now the about:flags-related switch should have been removed.
290 ASSERT_EQ(1u, switch_list.size());
291 EXPECT_TRUE(switch_list.find("foo") != switch_list.end());
294 // Tests enabling experiments that aren't supported on the current platform.
295 TEST_F(AboutFlagsTest, PersistAndPrune) {
296 // Enable experiments 1 and 3.
297 SetExperimentEnabled(&flags_storage_, kFlags1, true);
298 SetExperimentEnabled(&flags_storage_, kFlags3, true);
299 CommandLine command_line(CommandLine::NO_PROGRAM);
300 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
301 EXPECT_FALSE(command_line.HasSwitch(kSwitch3));
303 // Convert the flags to switches. Experiment 3 shouldn't be among the switches
304 // as it is not applicable to the current platform.
305 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
306 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
307 EXPECT_FALSE(command_line.HasSwitch(kSwitch3));
309 // Experiment 3 should show still be persisted in preferences though.
310 const base::ListValue* experiments_list =
311 prefs_.GetList(prefs::kEnabledLabsExperiments);
312 ASSERT_TRUE(experiments_list);
313 EXPECT_EQ(2U, experiments_list->GetSize());
314 std::string s0;
315 ASSERT_TRUE(experiments_list->GetString(0, &s0));
316 EXPECT_EQ(kFlags1, s0);
317 std::string s1;
318 ASSERT_TRUE(experiments_list->GetString(1, &s1));
319 EXPECT_EQ(kFlags3, s1);
322 // Tests that switches which should have values get them in the command
323 // line.
324 TEST_F(AboutFlagsTest, CheckValues) {
325 // Enable experiments 1 and 2.
326 SetExperimentEnabled(&flags_storage_, kFlags1, true);
327 SetExperimentEnabled(&flags_storage_, kFlags2, true);
328 CommandLine command_line(CommandLine::NO_PROGRAM);
329 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
330 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
332 // Convert the flags to switches.
333 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
334 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
335 EXPECT_EQ(std::string(), command_line.GetSwitchValueASCII(kSwitch1));
336 EXPECT_TRUE(command_line.HasSwitch(kSwitch2));
337 EXPECT_EQ(std::string(kValueForSwitch2),
338 command_line.GetSwitchValueASCII(kSwitch2));
340 // Confirm that there is no '=' in the command line for simple switches.
341 std::string switch1_with_equals = std::string("--") +
342 std::string(kSwitch1) +
343 std::string("=");
344 #if defined(OS_WIN)
345 EXPECT_EQ(std::wstring::npos,
346 command_line.GetCommandLineString().find(
347 base::ASCIIToWide(switch1_with_equals)));
348 #else
349 EXPECT_EQ(std::string::npos,
350 command_line.GetCommandLineString().find(switch1_with_equals));
351 #endif
353 // And confirm there is a '=' for switches with values.
354 std::string switch2_with_equals = std::string("--") +
355 std::string(kSwitch2) +
356 std::string("=");
357 #if defined(OS_WIN)
358 EXPECT_NE(std::wstring::npos,
359 command_line.GetCommandLineString().find(
360 base::ASCIIToWide(switch2_with_equals)));
361 #else
362 EXPECT_NE(std::string::npos,
363 command_line.GetCommandLineString().find(switch2_with_equals));
364 #endif
366 // And it should persist.
367 const base::ListValue* experiments_list =
368 prefs_.GetList(prefs::kEnabledLabsExperiments);
369 ASSERT_TRUE(experiments_list);
370 EXPECT_EQ(2U, experiments_list->GetSize());
371 std::string s0;
372 ASSERT_TRUE(experiments_list->GetString(0, &s0));
373 EXPECT_EQ(kFlags1, s0);
374 std::string s1;
375 ASSERT_TRUE(experiments_list->GetString(1, &s1));
376 EXPECT_EQ(kFlags2, s1);
379 // Tests multi-value type experiments.
380 TEST_F(AboutFlagsTest, MultiValues) {
381 const Experiment& experiment = kExperiments[3];
382 ASSERT_EQ(kFlags4, experiment.internal_name);
384 // Initially, the first "deactivated" option of the multi experiment should
385 // be set.
387 CommandLine command_line(CommandLine::NO_PROGRAM);
388 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
389 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
390 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
393 // Enable the 2nd choice of the multi-value.
394 SetExperimentEnabled(&flags_storage_, experiment.NameForChoice(2), true);
396 CommandLine command_line(CommandLine::NO_PROGRAM);
397 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
398 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
399 EXPECT_TRUE(command_line.HasSwitch(kMultiSwitch2));
400 EXPECT_EQ(std::string(kValueForMultiSwitch2),
401 command_line.GetSwitchValueASCII(kMultiSwitch2));
404 // Disable the multi-value experiment.
405 SetExperimentEnabled(&flags_storage_, experiment.NameForChoice(0), true);
407 CommandLine command_line(CommandLine::NO_PROGRAM);
408 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
409 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
410 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
414 TEST_F(AboutFlagsTest, EnableDisableValues) {
415 const Experiment& experiment = kExperiments[4];
416 ASSERT_EQ(kFlags5, experiment.internal_name);
418 // Nothing selected.
420 CommandLine command_line(CommandLine::NO_PROGRAM);
421 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
422 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
423 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
426 // "Enable" option selected.
427 SetExperimentEnabled(&flags_storage_, experiment.NameForChoice(1), true);
429 CommandLine command_line(CommandLine::NO_PROGRAM);
430 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
431 EXPECT_TRUE(command_line.HasSwitch(kSwitch1));
432 EXPECT_FALSE(command_line.HasSwitch(kSwitch2));
433 EXPECT_EQ(kEnableDisableValue1, command_line.GetSwitchValueASCII(kSwitch1));
436 // "Disable" option selected.
437 SetExperimentEnabled(&flags_storage_, experiment.NameForChoice(2), true);
439 CommandLine command_line(CommandLine::NO_PROGRAM);
440 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
441 EXPECT_FALSE(command_line.HasSwitch(kSwitch1));
442 EXPECT_TRUE(command_line.HasSwitch(kSwitch2));
443 EXPECT_EQ(kEnableDisableValue2, command_line.GetSwitchValueASCII(kSwitch2));
446 // "Default" option selected, same as nothing selected.
447 SetExperimentEnabled(&flags_storage_, experiment.NameForChoice(0), true);
449 CommandLine command_line(CommandLine::NO_PROGRAM);
450 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels);
451 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch1));
452 EXPECT_FALSE(command_line.HasSwitch(kMultiSwitch2));
456 // Makes sure there are no separators in any of the experiment names.
457 TEST_F(AboutFlagsTest, NoSeparators) {
458 testing::SetExperiments(NULL, 0);
459 size_t count;
460 const Experiment* experiments = testing::GetExperiments(&count);
461 for (size_t i = 0; i < count; ++i) {
462 std::string name = experiments->internal_name;
463 EXPECT_EQ(std::string::npos, name.find(testing::kMultiSeparator)) << i;
467 } // namespace about_flags