OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/files/file_path.h" | |
6 #include "base/memory/scoped_vector.h" | |
7 #include "base/path_service.h" | |
5 #include "base/prefs/pref_registry_simple.h" | 8 #include "base/prefs/pref_registry_simple.h" |
6 #include "base/prefs/testing_pref_service.h" | 9 #include "base/prefs/testing_pref_service.h" |
7 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/stringprintf.h" | |
8 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
9 #include "base/values.h" | 13 #include "base/values.h" |
10 #include "chrome/browser/about_flags.h" | 14 #include "chrome/browser/about_flags.h" |
11 #include "chrome/browser/pref_service_flags_storage.h" | 15 #include "chrome/browser/pref_service_flags_storage.h" |
12 #include "chrome/common/chrome_switches.h" | 16 #include "chrome/common/chrome_switches.h" |
13 #include "chrome/common/pref_names.h" | 17 #include "chrome/common/pref_names.h" |
14 #include "grit/chromium_strings.h" | 18 #include "grit/chromium_strings.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
20 #include "third_party/libxml/chromium/libxml_utils.h" | |
21 | |
22 namespace { | |
16 | 23 |
17 const char kFlags1[] = "flag1"; | 24 const char kFlags1[] = "flag1"; |
18 const char kFlags2[] = "flag2"; | 25 const char kFlags2[] = "flag2"; |
19 const char kFlags3[] = "flag3"; | 26 const char kFlags3[] = "flag3"; |
20 const char kFlags4[] = "flag4"; | 27 const char kFlags4[] = "flag4"; |
21 const char kFlags5[] = "flag5"; | 28 const char kFlags5[] = "flag5"; |
22 | 29 |
23 const char kSwitch1[] = "switch"; | 30 const char kSwitch1[] = "switch"; |
24 const char kSwitch2[] = "switch2"; | 31 const char kSwitch2[] = "switch2"; |
25 const char kSwitch3[] = "switch3"; | 32 const char kSwitch3[] = "switch3"; |
26 const char kValueForSwitch2[] = "value_for_switch2"; | 33 const char kValueForSwitch2[] = "value_for_switch2"; |
27 | 34 |
28 const char kMultiSwitch1[] = "multi_switch1"; | 35 const char kMultiSwitch1[] = "multi_switch1"; |
29 const char kMultiSwitch2[] = "multi_switch2"; | 36 const char kMultiSwitch2[] = "multi_switch2"; |
30 const char kValueForMultiSwitch2[] = "value_for_multi_switch2"; | 37 const char kValueForMultiSwitch2[] = "value_for_multi_switch2"; |
31 | 38 |
32 const char kEnableDisableValue1[] = "value1"; | 39 const char kEnableDisableValue1[] = "value1"; |
33 const char kEnableDisableValue2[] = "value2"; | 40 const char kEnableDisableValue2[] = "value2"; |
34 | 41 |
42 typedef std::map<std::string, uint32> Switch2IdMap; | |
Ilya Sherman
2014/08/05 20:14:46
Please spell out "To", rather than using "2".
Alexander Alekseev
2014/08/07 23:24:56
Done.
| |
43 | |
44 // This is a helper function to the next one. | |
45 // Extracts single enum (with integer values) from histograms.xml. | |
46 // Expects |reader| to point at given enum. | |
47 // Returns map { value => label }. | |
48 // Returns empty map on error. | |
49 std::map<uint32, std::string> ParseEnumFromHistogramsXml( | |
50 const std::string& enum_name, | |
51 XmlReader* reader) { | |
52 int entries_index = -1; | |
53 | |
54 std::map<uint32, std::string> result; | |
55 bool success = true; | |
56 | |
57 while (true) { | |
58 const std::string node_name = reader->NodeName(); | |
59 if (node_name == "enum" && reader->IsClosingElement()) | |
60 break; | |
61 | |
62 if (node_name == "int") { | |
63 ++entries_index; | |
64 std::string value_str; | |
65 std::string label; | |
66 const bool has_value = reader->NodeAttribute("value", &value_str); | |
67 const bool has_label = reader->NodeAttribute("label", &label); | |
68 if (!has_value) { | |
69 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " | |
70 << entries_index << ", label='" << label | |
71 << "'): No 'value' attribute."; | |
72 success = false; | |
73 } | |
74 if (!has_label) { | |
75 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " | |
76 << entries_index << ", value_str='" << value_str | |
77 << "'): No 'label' attribute."; | |
78 success = false; | |
79 } | |
80 | |
81 uint32 value; | |
82 if (has_value && !base::StringToUint(value_str, &value)) { | |
83 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " | |
84 << entries_index << ", label='" << label | |
85 << "', value_str='" << value_str | |
86 << "'): 'value' attribute is not integer."; | |
87 success = false; | |
88 } | |
89 if (result.count(value)) { | |
90 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " | |
91 << entries_index << ", label='" << label | |
92 << "', value_str='" << value_str | |
93 << "'): duplicate value '" << value_str | |
94 << "' found in enum. The previous one has label='" | |
95 << result[value] << "'."; | |
96 success = false; | |
97 } | |
98 if (success) { | |
99 result[value] = label; | |
100 } | |
101 } | |
102 // All enum entries are on the same level, so it is enough to iterate | |
103 // until possible. | |
104 reader->Next(); | |
105 } | |
106 return (success ? result : std::map<uint32, std::string>()); | |
107 } | |
108 | |
109 // Find and read given enum (with integer values) from histograms.xml. | |
110 // |enum_name| - enum name. | |
111 // |histograms_xml| - must be loaded histograms.xml file. | |
112 // | |
113 // Returns map { value => label } so that: | |
114 // <int value="9" label="enable-pinch-virtual-viewport"/> | |
115 // becomes: | |
116 // { 9 => "enable-pinch-virtual-viewport" } | |
117 // Returns empty map on error. | |
118 std::map<uint32, std::string> ReadEnumFromHistogramsXml( | |
119 const std::string& enum_name, | |
120 XmlReader* histograms_xml) { | |
121 std::map<uint32, std::string> login_custom_flags; | |
122 | |
123 // Implement simple depth first search. | |
124 while (true) { | |
125 const std::string node_name = histograms_xml->NodeName(); | |
126 if (node_name == "enum") { | |
127 std::string name; | |
128 if (histograms_xml->NodeAttribute("name", &name) && name == enum_name) { | |
129 if (!login_custom_flags.empty()) { | |
130 EXPECT_TRUE(login_custom_flags.empty()) | |
131 << "Duplicate enum '" << enum_name << "' found in histograms.xml"; | |
132 return std::map<uint32, std::string>(); | |
133 } | |
134 | |
135 const bool got_into_enum = histograms_xml->Read(); | |
136 if (got_into_enum) { | |
137 login_custom_flags = | |
138 ParseEnumFromHistogramsXml(enum_name, histograms_xml); | |
139 EXPECT_FALSE(login_custom_flags.empty()) | |
140 << "Bad enum '" << enum_name | |
141 << "' found in histograms.xml (format error)."; | |
142 } else { | |
143 EXPECT_TRUE(got_into_enum) | |
144 << "Bad enum '" << enum_name | |
145 << "' (looks empty) found in histograms.xml."; | |
146 } | |
147 if (login_custom_flags.empty()) | |
148 return std::map<uint32, std::string>(); | |
149 } | |
150 } | |
151 // Go deeper if possible (stops at the closing tag of the deepest node). | |
152 if (histograms_xml->Read()) | |
153 continue; | |
154 | |
155 // Try next node on the same level (skips closing tag). | |
156 if (histograms_xml->Next()) | |
157 continue; | |
158 | |
159 // Go up until next node on the same level exists. | |
160 while (histograms_xml->Depth() && !histograms_xml->SkipToElement()) { | |
161 } | |
162 | |
163 // Reached top. histograms.xml consists of the single top level node | |
164 // 'histogram-configuration', so this is the end. | |
165 if (!histograms_xml->Depth()) | |
166 break; | |
167 } | |
168 EXPECT_FALSE(login_custom_flags.empty()) | |
169 << "Enum '" << enum_name << "' is not found in histograms.xml."; | |
170 return login_custom_flags; | |
171 } | |
172 | |
173 std::string FilePathStringTypeToString(const base::FilePath::StringType& path) { | |
174 #if defined(OS_WIN) | |
175 return UTF16ToUTF8(path); | |
176 #else | |
177 return path; | |
178 #endif | |
179 } | |
180 | |
181 } // anonymous namespace | |
182 | |
35 namespace about_flags { | 183 namespace about_flags { |
36 | 184 |
37 const Experiment::Choice kMultiChoices[] = { | 185 const Experiment::Choice kMultiChoices[] = { |
38 { IDS_PRODUCT_NAME, "", "" }, | 186 { IDS_PRODUCT_NAME, "", "" }, |
39 { IDS_PRODUCT_NAME, kMultiSwitch1, "" }, | 187 { IDS_PRODUCT_NAME, kMultiSwitch1, "" }, |
40 { IDS_PRODUCT_NAME, kMultiSwitch2, kValueForMultiSwitch2 }, | 188 { IDS_PRODUCT_NAME, kMultiSwitch2, kValueForMultiSwitch2 }, |
41 }; | 189 }; |
42 | 190 |
43 // The experiments that are set for these tests. The 3rd experiment is not | 191 // The experiments that are set for these tests. The 3rd experiment is not |
44 // supported on the current platform, all others are. | 192 // supported on the current platform, all others are. |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 }; | 259 }; |
112 | 260 |
113 class AboutFlagsTest : public ::testing::Test { | 261 class AboutFlagsTest : public ::testing::Test { |
114 protected: | 262 protected: |
115 AboutFlagsTest() : flags_storage_(&prefs_) { | 263 AboutFlagsTest() : flags_storage_(&prefs_) { |
116 prefs_.registry()->RegisterListPref(prefs::kEnabledLabsExperiments); | 264 prefs_.registry()->RegisterListPref(prefs::kEnabledLabsExperiments); |
117 testing::ClearState(); | 265 testing::ClearState(); |
118 } | 266 } |
119 | 267 |
120 virtual void SetUp() OVERRIDE { | 268 virtual void SetUp() OVERRIDE { |
269 std::set<std::string> all_switches = GetAllSwitchesForTesting(); | |
121 for (size_t i = 0; i < arraysize(kExperiments); ++i) | 270 for (size_t i = 0; i < arraysize(kExperiments); ++i) |
122 kExperiments[i].supported_platforms = GetCurrentPlatform(); | 271 kExperiments[i].supported_platforms = GetCurrentPlatform(); |
123 | 272 |
124 int os_other_than_current = 1; | 273 int os_other_than_current = 1; |
125 while (os_other_than_current == GetCurrentPlatform()) | 274 while (os_other_than_current == GetCurrentPlatform()) |
126 os_other_than_current <<= 1; | 275 os_other_than_current <<= 1; |
127 kExperiments[2].supported_platforms = os_other_than_current; | 276 kExperiments[2].supported_platforms = os_other_than_current; |
128 | 277 |
129 testing::SetExperiments(kExperiments, arraysize(kExperiments)); | 278 testing::SetExperiments(kExperiments, arraysize(kExperiments)); |
130 } | 279 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 | 375 |
227 CommandLine command_line2(CommandLine::NO_PROGRAM); | 376 CommandLine command_line2(CommandLine::NO_PROGRAM); |
228 | 377 |
229 ConvertFlagsToSwitches(&flags_storage_, &command_line2, kNoSentinels); | 378 ConvertFlagsToSwitches(&flags_storage_, &command_line2, kNoSentinels); |
230 | 379 |
231 EXPECT_TRUE(command_line2.HasSwitch(kSwitch1)); | 380 EXPECT_TRUE(command_line2.HasSwitch(kSwitch1)); |
232 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesBegin)); | 381 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesBegin)); |
233 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesEnd)); | 382 EXPECT_FALSE(command_line2.HasSwitch(switches::kFlagSwitchesEnd)); |
234 } | 383 } |
235 | 384 |
385 CommandLine::StringType CreateSwitch(const std::string& value) { | |
386 #if defined(OS_WIN) | |
387 return ASCIIToUTF16(value); | |
388 #else | |
389 return value; | |
390 #endif | |
391 } | |
392 | |
236 TEST_F(AboutFlagsTest, CompareSwitchesToCurrentCommandLine) { | 393 TEST_F(AboutFlagsTest, CompareSwitchesToCurrentCommandLine) { |
237 SetExperimentEnabled(&flags_storage_, kFlags1, true); | 394 SetExperimentEnabled(&flags_storage_, kFlags1, true); |
238 | 395 |
396 const std::string kDoubleDash("--"); | |
397 | |
239 CommandLine command_line(CommandLine::NO_PROGRAM); | 398 CommandLine command_line(CommandLine::NO_PROGRAM); |
240 command_line.AppendSwitch("foo"); | 399 command_line.AppendSwitch("foo"); |
241 | 400 |
242 CommandLine new_command_line(CommandLine::NO_PROGRAM); | 401 CommandLine new_command_line(CommandLine::NO_PROGRAM); |
243 ConvertFlagsToSwitches(&flags_storage_, &new_command_line, kAddSentinels); | 402 ConvertFlagsToSwitches(&flags_storage_, &new_command_line, kAddSentinels); |
244 | 403 |
245 EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line, | 404 EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine( |
246 command_line)); | 405 new_command_line, command_line, NULL)); |
406 { | |
407 std::set<CommandLine::StringType> difference; | |
408 EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine( | |
409 new_command_line, command_line, &difference)); | |
410 EXPECT_EQ(1U, difference.size()); | |
411 EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1))); | |
412 } | |
247 | 413 |
248 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); | 414 ConvertFlagsToSwitches(&flags_storage_, &command_line, kAddSentinels); |
249 | 415 |
250 EXPECT_TRUE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line, | 416 EXPECT_TRUE(AreSwitchesIdenticalToCurrentCommandLine( |
251 command_line)); | 417 new_command_line, command_line, NULL)); |
418 { | |
419 std::set<CommandLine::StringType> difference; | |
420 EXPECT_TRUE(AreSwitchesIdenticalToCurrentCommandLine( | |
421 new_command_line, command_line, &difference)); | |
422 EXPECT_TRUE(difference.empty()); | |
423 } | |
252 | 424 |
253 // Now both have flags but different. | 425 // Now both have flags but different. |
254 SetExperimentEnabled(&flags_storage_, kFlags1, false); | 426 SetExperimentEnabled(&flags_storage_, kFlags1, false); |
255 SetExperimentEnabled(&flags_storage_, kFlags2, true); | 427 SetExperimentEnabled(&flags_storage_, kFlags2, true); |
256 | 428 |
257 CommandLine another_command_line(CommandLine::NO_PROGRAM); | 429 CommandLine another_command_line(CommandLine::NO_PROGRAM); |
258 ConvertFlagsToSwitches(&flags_storage_, &another_command_line, kAddSentinels); | 430 ConvertFlagsToSwitches(&flags_storage_, &another_command_line, kAddSentinels); |
259 | 431 |
260 EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine(new_command_line, | 432 EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine( |
261 another_command_line)); | 433 new_command_line, another_command_line, NULL)); |
434 { | |
435 std::set<CommandLine::StringType> difference; | |
436 EXPECT_FALSE(AreSwitchesIdenticalToCurrentCommandLine( | |
437 new_command_line, another_command_line, &difference)); | |
438 EXPECT_EQ(2U, difference.size()); | |
439 EXPECT_EQ(1U, difference.count(CreateSwitch(kDoubleDash + kSwitch1))); | |
440 EXPECT_EQ(1U, | |
441 difference.count(CreateSwitch(kDoubleDash + kSwitch2 + "=" + | |
442 kValueForSwitch2))); | |
443 } | |
262 } | 444 } |
263 | 445 |
264 TEST_F(AboutFlagsTest, RemoveFlagSwitches) { | 446 TEST_F(AboutFlagsTest, RemoveFlagSwitches) { |
265 std::map<std::string, CommandLine::StringType> switch_list; | 447 std::map<std::string, CommandLine::StringType> switch_list; |
266 switch_list[kSwitch1] = CommandLine::StringType(); | 448 switch_list[kSwitch1] = CommandLine::StringType(); |
267 switch_list[switches::kFlagSwitchesBegin] = CommandLine::StringType(); | 449 switch_list[switches::kFlagSwitchesBegin] = CommandLine::StringType(); |
268 switch_list[switches::kFlagSwitchesEnd] = CommandLine::StringType(); | 450 switch_list[switches::kFlagSwitchesEnd] = CommandLine::StringType(); |
269 switch_list["foo"] = CommandLine::StringType(); | 451 switch_list["foo"] = CommandLine::StringType(); |
270 | 452 |
271 SetExperimentEnabled(&flags_storage_, kFlags1, true); | 453 SetExperimentEnabled(&flags_storage_, kFlags1, true); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
457 TEST_F(AboutFlagsTest, NoSeparators) { | 639 TEST_F(AboutFlagsTest, NoSeparators) { |
458 testing::SetExperiments(NULL, 0); | 640 testing::SetExperiments(NULL, 0); |
459 size_t count; | 641 size_t count; |
460 const Experiment* experiments = testing::GetExperiments(&count); | 642 const Experiment* experiments = testing::GetExperiments(&count); |
461 for (size_t i = 0; i < count; ++i) { | 643 for (size_t i = 0; i < count; ++i) { |
462 std::string name = experiments->internal_name; | 644 std::string name = experiments->internal_name; |
463 EXPECT_EQ(std::string::npos, name.find(testing::kMultiSeparator)) << i; | 645 EXPECT_EQ(std::string::npos, name.find(testing::kMultiSeparator)) << i; |
464 } | 646 } |
465 } | 647 } |
466 | 648 |
649 class AboutFlagsHistogramTest : public ::testing::Test { | |
Ilya Sherman
2014/08/05 20:14:46
I'm not an owner for this file, but I think it's g
Alexander Alekseev
2014/08/07 23:24:56
Done.
There is no explicit OWNER for this file.
| |
650 protected: | |
651 void SetSwitchToHistogramIdMapping(const std::string& switch_name, | |
652 const uint32 switch_histogram_id, | |
653 std::map<std::string, uint32>* out_map) { | |
Ilya Sherman
2014/08/05 20:14:46
nit: Docs.
Alexander Alekseev
2014/08/07 23:24:56
Done.
| |
654 const std::pair<std::map<std::string, uint32>::iterator, bool> status = | |
655 out_map->insert(std::make_pair(switch_name, switch_histogram_id)); | |
656 if (!status.second) { | |
657 EXPECT_TRUE(status.first->second == switch_histogram_id) | |
658 << "Duplicate switch '" << switch_name | |
659 << "' found in enum 'LoginCustomFlags' in histograms.xml."; | |
660 } | |
661 } | |
662 | |
663 std::string GetHistogramEnumEntryText(const std::string& switch_name, | |
664 uint32 value) { | |
Ilya Sherman
2014/08/05 20:14:46
nit: Docs.
Alexander Alekseev
2014/08/07 23:24:56
Done.
| |
665 return base::StringPrintf( | |
666 "<int value=\"%u\" label=\"%s\"/>", value, switch_name.c_str()); | |
667 } | |
668 }; | |
669 | |
670 TEST_F(AboutFlagsHistogramTest, CheckHistograms) { | |
671 base::FilePath histograms_xml_file_path; | |
672 ASSERT_TRUE( | |
673 PathService::Get(base::DIR_SOURCE_ROOT, &histograms_xml_file_path)); | |
674 histograms_xml_file_path = histograms_xml_file_path.AppendASCII("tools") | |
675 .AppendASCII("metrics") | |
676 .AppendASCII("histograms") | |
677 .AppendASCII("histograms.xml"); | |
678 | |
679 XmlReader histograms_xml; | |
680 ASSERT_TRUE(histograms_xml.LoadFile( | |
681 FilePathStringTypeToString(histograms_xml_file_path.value()))); | |
682 std::map<uint32, std::string> login_custom_flags = | |
683 ReadEnumFromHistogramsXml("LoginCustomFlags", &histograms_xml); | |
684 ASSERT_TRUE(login_custom_flags.size()) | |
685 << "Error reading enum 'LoginCustomFlags' from histograms.xml."; | |
686 | |
687 // Build reverse map {switch_name => id} from login_custom_flags. | |
688 Switch2IdMap histograms_xml_switches_ids; | |
689 | |
690 EXPECT_TRUE(login_custom_flags.count(kBadSwitchFormatHistogramId)) | |
691 << "Entry for UMA ID of incorrect command-line flag is not found in " | |
692 "histograms.xml enum LoginCustomFlags. " | |
693 "Consider adding entry:\n" | |
694 << " " << GetHistogramEnumEntryText("BAD_FLAG_FORMAT", 0); | |
695 // Check that all LoginCustomFlags entries have correct values. | |
696 for (std::map<uint32, std::string>::const_iterator it = | |
697 login_custom_flags.begin(); | |
698 it != login_custom_flags.end(); | |
699 ++it) { | |
700 if (it->first == kBadSwitchFormatHistogramId) { | |
701 // Add eror value with empty name. | |
702 SetSwitchToHistogramIdMapping( | |
703 "", it->first, &histograms_xml_switches_ids); | |
704 continue; | |
705 } | |
706 const uint32 uma_id = GetSwitchUMAId(it->second); | |
707 EXPECT_EQ(uma_id, it->first) | |
708 << "histograms.xml enum LoginCustomFlags " | |
709 "entry '" << it->second << "' has incorrect value=" << it->first | |
710 << ", but " << uma_id << " is expected. Consider changing entry to:\n" | |
711 << " " << GetHistogramEnumEntryText(it->second, uma_id); | |
712 SetSwitchToHistogramIdMapping( | |
713 it->second, it->first, &histograms_xml_switches_ids); | |
714 } | |
715 | |
716 // Check that all flags in about_flags.cc have entries in login_custom_flags. | |
717 std::set<std::string> all_switches = GetAllSwitchesForTesting(); | |
718 for (std::set<std::string>::const_iterator it = all_switches.begin(); | |
719 it != all_switches.end(); | |
720 ++it) { | |
721 // Skip empty placeholders. | |
722 if (it->empty()) | |
723 continue; | |
724 const uint32 uma_id = GetSwitchUMAId(*it); | |
725 EXPECT_NE(kBadSwitchFormatHistogramId, uma_id) | |
726 << "Command-line switch '" << *it | |
727 << "' from about_flags.cc has UMA ID equal to reserved value " | |
728 "kBadSwitchFormatHistogramId=" << kBadSwitchFormatHistogramId | |
729 << ". Please modify switch name."; | |
730 Switch2IdMap::iterator enum_entry = | |
731 histograms_xml_switches_ids.lower_bound(*it); | |
732 | |
733 // Ignore case here when switch ID is incorrect - it has already been | |
734 // reported in the previous loop. | |
735 EXPECT_TRUE(enum_entry != histograms_xml_switches_ids.end() && | |
736 enum_entry->first == *it) | |
737 << "histograms.xml enum LoginCustomFlags doesn't contain switch '" | |
738 << *it << "' (value=" << uma_id | |
739 << " expected). Consider adding entry:\n" | |
740 << " " << GetHistogramEnumEntryText(*it, uma_id); | |
741 } | |
742 } | |
743 | |
467 } // namespace about_flags | 744 } // namespace about_flags |
OLD | NEW |