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 <stdint.h> | 5 #include <stdint.h> |
6 | 6 |
7 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
8 #include "base/memory/scoped_vector.h" | 8 #include "base/memory/scoped_vector.h" |
9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
10 #include "base/prefs/pref_registry_simple.h" | 10 #include "base/prefs/pref_registry_simple.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 const char kSwitch3[] = "switch3"; | 34 const char kSwitch3[] = "switch3"; |
35 const char kValueForSwitch2[] = "value_for_switch2"; | 35 const char kValueForSwitch2[] = "value_for_switch2"; |
36 | 36 |
37 const char kMultiSwitch1[] = "multi_switch1"; | 37 const char kMultiSwitch1[] = "multi_switch1"; |
38 const char kMultiSwitch2[] = "multi_switch2"; | 38 const char kMultiSwitch2[] = "multi_switch2"; |
39 const char kValueForMultiSwitch2[] = "value_for_multi_switch2"; | 39 const char kValueForMultiSwitch2[] = "value_for_multi_switch2"; |
40 | 40 |
41 const char kEnableDisableValue1[] = "value1"; | 41 const char kEnableDisableValue1[] = "value1"; |
42 const char kEnableDisableValue2[] = "value2"; | 42 const char kEnableDisableValue2[] = "value2"; |
43 | 43 |
44 typedef std::map<std::string, uint32_t> SwitchToIdMap; | 44 typedef std::map<std::string, int32_t> SwitchToIdMap; |
45 | 45 |
46 // This is a helper function to the ReadEnumFromHistogramsXml(). | 46 // This is a helper function to the ReadEnumFromHistogramsXml(). |
47 // Extracts single enum (with integer values) from histograms.xml. | 47 // Extracts single enum (with integer values) from histograms.xml. |
48 // Expects |reader| to point at given enum. | 48 // Expects |reader| to point at given enum. |
49 // Returns map { value => label }. | 49 // Returns map { value => label }. |
50 // Returns empty map on error. | 50 // Returns empty map on error. |
51 std::map<uint32_t, std::string> ParseEnumFromHistogramsXml( | 51 std::map<int32_t, std::string> ParseEnumFromHistogramsXml( |
52 const std::string& enum_name, | 52 const std::string& enum_name, |
53 XmlReader* reader) { | 53 XmlReader* reader) { |
54 int entries_index = -1; | 54 int entries_index = -1; |
55 | 55 |
56 std::map<uint32_t, std::string> result; | 56 std::map<int32_t, std::string> result; |
57 bool success = true; | 57 bool success = true; |
58 | 58 |
59 while (true) { | 59 while (true) { |
60 const std::string node_name = reader->NodeName(); | 60 const std::string node_name = reader->NodeName(); |
61 if (node_name == "enum" && reader->IsClosingElement()) | 61 if (node_name == "enum" && reader->IsClosingElement()) |
62 break; | 62 break; |
63 | 63 |
64 if (node_name == "int") { | 64 if (node_name == "int") { |
65 ++entries_index; | 65 ++entries_index; |
66 std::string value_str; | 66 std::string value_str; |
67 std::string label; | 67 std::string label; |
68 const bool has_value = reader->NodeAttribute("value", &value_str); | 68 const bool has_value = reader->NodeAttribute("value", &value_str); |
69 const bool has_label = reader->NodeAttribute("label", &label); | 69 const bool has_label = reader->NodeAttribute("label", &label); |
70 if (!has_value) { | 70 if (!has_value) { |
71 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " | 71 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " |
72 << entries_index << ", label='" << label | 72 << entries_index << ", label='" << label |
73 << "'): No 'value' attribute."; | 73 << "'): No 'value' attribute."; |
74 success = false; | 74 success = false; |
75 } | 75 } |
76 if (!has_label) { | 76 if (!has_label) { |
77 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " | 77 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " |
78 << entries_index << ", value_str='" << value_str | 78 << entries_index << ", value_str='" << value_str |
79 << "'): No 'label' attribute."; | 79 << "'): No 'label' attribute."; |
80 success = false; | 80 success = false; |
81 } | 81 } |
82 | 82 |
83 uint32_t value; | 83 int32_t value; |
84 if (has_value && !base::StringToUint(value_str, &value)) { | 84 if (has_value && !base::StringToInt(value_str, &value)) { |
85 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " | 85 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " |
86 << entries_index << ", label='" << label | 86 << entries_index << ", label='" << label |
87 << "', value_str='" << value_str | 87 << "', value_str='" << value_str |
88 << "'): 'value' attribute is not integer."; | 88 << "'): 'value' attribute is not integer."; |
89 success = false; | 89 success = false; |
90 } | 90 } |
91 if (result.count(value)) { | 91 if (result.count(value)) { |
92 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " | 92 ADD_FAILURE() << "Bad " << enum_name << " enum entry (at index " |
93 << entries_index << ", label='" << label | 93 << entries_index << ", label='" << label |
94 << "', value_str='" << value_str | 94 << "', value_str='" << value_str |
95 << "'): duplicate value '" << value_str | 95 << "'): duplicate value '" << value_str |
96 << "' found in enum. The previous one has label='" | 96 << "' found in enum. The previous one has label='" |
97 << result[value] << "'."; | 97 << result[value] << "'."; |
98 success = false; | 98 success = false; |
99 } | 99 } |
100 if (success) { | 100 if (success) { |
101 result[value] = label; | 101 result[value] = label; |
102 } | 102 } |
103 } | 103 } |
104 // All enum entries are on the same level, so it is enough to iterate | 104 // All enum entries are on the same level, so it is enough to iterate |
105 // until possible. | 105 // until possible. |
106 reader->Next(); | 106 reader->Next(); |
107 } | 107 } |
108 return (success ? result : std::map<uint32_t, std::string>()); | 108 return (success ? result : std::map<int32_t, std::string>()); |
109 } | 109 } |
110 | 110 |
111 // Find and read given enum (with integer values) from histograms.xml. | 111 // Find and read given enum (with integer values) from histograms.xml. |
112 // |enum_name| - enum name. | 112 // |enum_name| - enum name. |
113 // |histograms_xml| - must be loaded histograms.xml file. | 113 // |histograms_xml| - must be loaded histograms.xml file. |
114 // | 114 // |
115 // Returns map { value => label } so that: | 115 // Returns map { value => label } so that: |
116 // <int value="9" label="enable-pinch-virtual-viewport"/> | 116 // <int value="9" label="enable-pinch-virtual-viewport"/> |
117 // becomes: | 117 // becomes: |
118 // { 9 => "enable-pinch-virtual-viewport" } | 118 // { 9 => "enable-pinch-virtual-viewport" } |
119 // Returns empty map on error. | 119 // Returns empty map on error. |
120 std::map<uint32_t, std::string> ReadEnumFromHistogramsXml( | 120 std::map<int32_t, std::string> ReadEnumFromHistogramsXml( |
121 const std::string& enum_name, | 121 const std::string& enum_name, |
122 XmlReader* histograms_xml) { | 122 XmlReader* histograms_xml) { |
123 std::map<uint32_t, std::string> login_custom_flags; | 123 std::map<int32_t, std::string> login_custom_flags; |
124 | 124 |
125 // Implement simple depth first search. | 125 // Implement simple depth first search. |
126 while (true) { | 126 while (true) { |
127 const std::string node_name = histograms_xml->NodeName(); | 127 const std::string node_name = histograms_xml->NodeName(); |
128 if (node_name == "enum") { | 128 if (node_name == "enum") { |
129 std::string name; | 129 std::string name; |
130 if (histograms_xml->NodeAttribute("name", &name) && name == enum_name) { | 130 if (histograms_xml->NodeAttribute("name", &name) && name == enum_name) { |
131 if (!login_custom_flags.empty()) { | 131 if (!login_custom_flags.empty()) { |
132 EXPECT_TRUE(login_custom_flags.empty()) | 132 EXPECT_TRUE(login_custom_flags.empty()) |
133 << "Duplicate enum '" << enum_name << "' found in histograms.xml"; | 133 << "Duplicate enum '" << enum_name << "' found in histograms.xml"; |
134 return std::map<uint32_t, std::string>(); | 134 return std::map<int32_t, std::string>(); |
135 } | 135 } |
136 | 136 |
137 const bool got_into_enum = histograms_xml->Read(); | 137 const bool got_into_enum = histograms_xml->Read(); |
138 if (got_into_enum) { | 138 if (got_into_enum) { |
139 login_custom_flags = | 139 login_custom_flags = |
140 ParseEnumFromHistogramsXml(enum_name, histograms_xml); | 140 ParseEnumFromHistogramsXml(enum_name, histograms_xml); |
141 EXPECT_FALSE(login_custom_flags.empty()) | 141 EXPECT_FALSE(login_custom_flags.empty()) |
142 << "Bad enum '" << enum_name | 142 << "Bad enum '" << enum_name |
143 << "' found in histograms.xml (format error)."; | 143 << "' found in histograms.xml (format error)."; |
144 } else { | 144 } else { |
145 EXPECT_TRUE(got_into_enum) | 145 EXPECT_TRUE(got_into_enum) |
146 << "Bad enum '" << enum_name | 146 << "Bad enum '" << enum_name |
147 << "' (looks empty) found in histograms.xml."; | 147 << "' (looks empty) found in histograms.xml."; |
148 } | 148 } |
149 if (login_custom_flags.empty()) | 149 if (login_custom_flags.empty()) |
150 return std::map<uint32_t, std::string>(); | 150 return std::map<int32_t, std::string>(); |
151 } | 151 } |
152 } | 152 } |
153 // Go deeper if possible (stops at the closing tag of the deepest node). | 153 // Go deeper if possible (stops at the closing tag of the deepest node). |
154 if (histograms_xml->Read()) | 154 if (histograms_xml->Read()) |
155 continue; | 155 continue; |
156 | 156 |
157 // Try next node on the same level (skips closing tag). | 157 // Try next node on the same level (skips closing tag). |
158 if (histograms_xml->Next()) | 158 if (histograms_xml->Next()) |
159 continue; | 159 continue; |
160 | 160 |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 std::string name = experiments->internal_name; | 669 std::string name = experiments->internal_name; |
670 EXPECT_EQ(std::string::npos, name.find(testing::kMultiSeparator)) << i; | 670 EXPECT_EQ(std::string::npos, name.find(testing::kMultiSeparator)) << i; |
671 } | 671 } |
672 } | 672 } |
673 | 673 |
674 class AboutFlagsHistogramTest : public ::testing::Test { | 674 class AboutFlagsHistogramTest : public ::testing::Test { |
675 protected: | 675 protected: |
676 // This is a helper function to check that all IDs in enum LoginCustomFlags in | 676 // This is a helper function to check that all IDs in enum LoginCustomFlags in |
677 // histograms.xml are unique. | 677 // histograms.xml are unique. |
678 void SetSwitchToHistogramIdMapping(const std::string& switch_name, | 678 void SetSwitchToHistogramIdMapping(const std::string& switch_name, |
679 const uint32_t switch_histogram_id, | 679 const int32_t switch_histogram_id, |
680 std::map<std::string, uint32_t>* out_map) { | 680 std::map<std::string, int32_t>* out_map) { |
681 const std::pair<std::map<std::string, uint32_t>::iterator, bool> status = | 681 const std::pair<std::map<std::string, int32_t>::iterator, bool> status = |
682 out_map->insert(std::make_pair(switch_name, switch_histogram_id)); | 682 out_map->insert(std::make_pair(switch_name, switch_histogram_id)); |
683 if (!status.second) { | 683 if (!status.second) { |
684 EXPECT_TRUE(status.first->second == switch_histogram_id) | 684 EXPECT_TRUE(status.first->second == switch_histogram_id) |
685 << "Duplicate switch '" << switch_name | 685 << "Duplicate switch '" << switch_name |
686 << "' found in enum 'LoginCustomFlags' in histograms.xml."; | 686 << "' found in enum 'LoginCustomFlags' in histograms.xml."; |
687 } | 687 } |
688 } | 688 } |
689 | 689 |
690 // This method generates a hint for the user for what string should be added | 690 // This method generates a hint for the user for what string should be added |
691 // to the enum LoginCustomFlags to make in consistent. | 691 // to the enum LoginCustomFlags to make in consistent. |
692 std::string GetHistogramEnumEntryText(const std::string& switch_name, | 692 std::string GetHistogramEnumEntryText(const std::string& switch_name, |
693 uint32_t value) { | 693 int32_t value) { |
694 return base::StringPrintf( | 694 return base::StringPrintf( |
695 "<int value=\"%u\" label=\"%s\"/>", value, switch_name.c_str()); | 695 "<int value=\"%d\" label=\"%s\"/>", value, switch_name.c_str()); |
696 } | 696 } |
697 }; | 697 }; |
698 | 698 |
699 TEST_F(AboutFlagsHistogramTest, CheckHistograms) { | 699 TEST_F(AboutFlagsHistogramTest, CheckHistograms) { |
700 base::FilePath histograms_xml_file_path; | 700 base::FilePath histograms_xml_file_path; |
701 ASSERT_TRUE( | 701 ASSERT_TRUE( |
702 PathService::Get(base::DIR_SOURCE_ROOT, &histograms_xml_file_path)); | 702 PathService::Get(base::DIR_SOURCE_ROOT, &histograms_xml_file_path)); |
703 histograms_xml_file_path = histograms_xml_file_path.AppendASCII("tools") | 703 histograms_xml_file_path = histograms_xml_file_path.AppendASCII("tools") |
704 .AppendASCII("metrics") | 704 .AppendASCII("metrics") |
705 .AppendASCII("histograms") | 705 .AppendASCII("histograms") |
706 .AppendASCII("histograms.xml"); | 706 .AppendASCII("histograms.xml"); |
707 | 707 |
708 XmlReader histograms_xml; | 708 XmlReader histograms_xml; |
709 ASSERT_TRUE(histograms_xml.LoadFile( | 709 ASSERT_TRUE(histograms_xml.LoadFile( |
710 FilePathStringTypeToString(histograms_xml_file_path.value()))); | 710 FilePathStringTypeToString(histograms_xml_file_path.value()))); |
711 std::map<uint32_t, std::string> login_custom_flags = | 711 std::map<int32_t, std::string> login_custom_flags = |
712 ReadEnumFromHistogramsXml("LoginCustomFlags", &histograms_xml); | 712 ReadEnumFromHistogramsXml("LoginCustomFlags", &histograms_xml); |
713 ASSERT_TRUE(login_custom_flags.size()) | 713 ASSERT_TRUE(login_custom_flags.size()) |
714 << "Error reading enum 'LoginCustomFlags' from histograms.xml."; | 714 << "Error reading enum 'LoginCustomFlags' from histograms.xml."; |
715 | 715 |
716 // Build reverse map {switch_name => id} from login_custom_flags. | 716 // Build reverse map {switch_name => id} from login_custom_flags. |
717 SwitchToIdMap histograms_xml_switches_ids; | 717 SwitchToIdMap histograms_xml_switches_ids; |
718 | 718 |
719 EXPECT_TRUE(login_custom_flags.count(kBadSwitchFormatHistogramId)) | 719 EXPECT_TRUE(login_custom_flags.count(kBadSwitchFormatHistogramId)) |
720 << "Entry for UMA ID of incorrect command-line flag is not found in " | 720 << "Entry for UMA ID of incorrect command-line flag is not found in " |
721 "histograms.xml enum LoginCustomFlags. " | 721 "histograms.xml enum LoginCustomFlags. " |
722 "Consider adding entry:\n" | 722 "Consider adding entry:\n" |
723 << " " << GetHistogramEnumEntryText("BAD_FLAG_FORMAT", 0); | 723 << " " << GetHistogramEnumEntryText("BAD_FLAG_FORMAT", 0); |
724 // Check that all LoginCustomFlags entries have correct values. | 724 // Check that all LoginCustomFlags entries have correct values. |
725 for (std::map<uint32_t, std::string>::const_iterator it = | 725 for (std::map<int32_t, std::string>::const_iterator it = |
726 login_custom_flags.begin(); | 726 login_custom_flags.begin(); |
727 it != login_custom_flags.end(); | 727 it != login_custom_flags.end(); |
728 ++it) { | 728 ++it) { |
729 if (it->first == kBadSwitchFormatHistogramId) { | 729 if (it->first == kBadSwitchFormatHistogramId) { |
730 // Add eror value with empty name. | 730 // Add eror value with empty name. |
731 SetSwitchToHistogramIdMapping( | 731 SetSwitchToHistogramIdMapping( |
732 "", it->first, &histograms_xml_switches_ids); | 732 "", it->first, &histograms_xml_switches_ids); |
733 continue; | 733 continue; |
734 } | 734 } |
735 const uint32_t uma_id = GetSwitchUMAId(it->second); | 735 const int32_t uma_id = GetSwitchUMAId(it->second); |
736 EXPECT_EQ(uma_id, it->first) | 736 EXPECT_EQ(uma_id, it->first) |
737 << "histograms.xml enum LoginCustomFlags " | 737 << "histograms.xml enum LoginCustomFlags " |
738 "entry '" << it->second << "' has incorrect value=" << it->first | 738 "entry '" << it->second << "' has incorrect value=" << it->first |
739 << ", but " << uma_id << " is expected. Consider changing entry to:\n" | 739 << ", but " << uma_id << " is expected. Consider changing entry to:\n" |
740 << " " << GetHistogramEnumEntryText(it->second, uma_id); | 740 << " " << GetHistogramEnumEntryText(it->second, uma_id); |
741 SetSwitchToHistogramIdMapping( | 741 SetSwitchToHistogramIdMapping( |
742 it->second, it->first, &histograms_xml_switches_ids); | 742 it->second, it->first, &histograms_xml_switches_ids); |
743 } | 743 } |
744 | 744 |
745 // Check that all flags in about_flags.cc have entries in login_custom_flags. | 745 // Check that all flags in about_flags.cc have entries in login_custom_flags. |
746 std::set<std::string> all_switches = GetAllSwitchesForTesting(); | 746 std::set<std::string> all_switches = GetAllSwitchesForTesting(); |
747 for (std::set<std::string>::const_iterator it = all_switches.begin(); | 747 for (std::set<std::string>::const_iterator it = all_switches.begin(); |
748 it != all_switches.end(); | 748 it != all_switches.end(); |
749 ++it) { | 749 ++it) { |
750 // Skip empty placeholders. | 750 // Skip empty placeholders. |
751 if (it->empty()) | 751 if (it->empty()) |
752 continue; | 752 continue; |
753 const uint32_t uma_id = GetSwitchUMAId(*it); | 753 const int32_t uma_id = GetSwitchUMAId(*it); |
754 EXPECT_NE(kBadSwitchFormatHistogramId, uma_id) | 754 EXPECT_NE(kBadSwitchFormatHistogramId, uma_id) |
755 << "Command-line switch '" << *it | 755 << "Command-line switch '" << *it |
756 << "' from about_flags.cc has UMA ID equal to reserved value " | 756 << "' from about_flags.cc has UMA ID equal to reserved value " |
757 "kBadSwitchFormatHistogramId=" << kBadSwitchFormatHistogramId | 757 "kBadSwitchFormatHistogramId=" << kBadSwitchFormatHistogramId |
758 << ". Please modify switch name."; | 758 << ". Please modify switch name."; |
759 SwitchToIdMap::iterator enum_entry = | 759 SwitchToIdMap::iterator enum_entry = |
760 histograms_xml_switches_ids.lower_bound(*it); | 760 histograms_xml_switches_ids.lower_bound(*it); |
761 | 761 |
762 // Ignore case here when switch ID is incorrect - it has already been | 762 // Ignore case here when switch ID is incorrect - it has already been |
763 // reported in the previous loop. | 763 // reported in the previous loop. |
764 EXPECT_TRUE(enum_entry != histograms_xml_switches_ids.end() && | 764 EXPECT_TRUE(enum_entry != histograms_xml_switches_ids.end() && |
765 enum_entry->first == *it) | 765 enum_entry->first == *it) |
766 << "histograms.xml enum LoginCustomFlags doesn't contain switch '" | 766 << "histograms.xml enum LoginCustomFlags doesn't contain switch '" |
767 << *it << "' (value=" << uma_id | 767 << *it << "' (value=" << uma_id |
768 << " expected). Consider adding entry:\n" | 768 << " expected). Consider adding entry:\n" |
769 << " " << GetHistogramEnumEntryText(*it, uma_id); | 769 << " " << GetHistogramEnumEntryText(*it, uma_id); |
770 } | 770 } |
771 } | 771 } |
772 | 772 |
773 } // namespace about_flags | 773 } // namespace about_flags |
OLD | NEW |