Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(681)

Side by Side Diff: tools/metrics/histograms/verify_enum_custom_flags.py

Issue 344883002: Collect UMA statistics on which chrome://flags lead to chrome restart on ChromeOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Report hash(switch name). Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2014 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 """Check enum LoginCustomFlags ."""
6
7 class LoginCustomFlagsChecker(object):
8 """Verify that changes to enum LoginCustomFlags in histograms.xml are valid.
9
10 This class is used to check that LoginCustomFlags enum is never shrinked.
11
12 Note: this check would probably fail if enum is completely moved to
13 another part of histograms.xml, but it works for changes inside enum.
14 """
15 def __init__(self, input_api, output_api, path):
16 self.input_api = input_api
17 self.output_api = output_api
18 self.path = path
19 self.warnings_exist = False
20 self.enum_start = 0
21 self.enum_end = 0
22 self.results = []
23
24 def LogInfo(self, message):
25 self.input_api.logging.info(message)
26 return
27
28 def LogDebug(self, message):
29 self.input_api.logging.debug(message)
30 return
31
32 def GetLongMessage(self, local_path):
33 return str("The file \"%s\"\n"
34 "contains the definition of the enum LoginCustomFlags,\n"
35 "which should never be shrinked or removed.\n"
36 % (local_path))
37
38 def EmitWarning(self, message, line_number=None, line_text=None):
39 """Emits a presubmit prompt warning containing the short message
40 |message|. |item| is |LOCAL_PATH| with optional |line_number| and
41 |line_text|.
42
43 """
44 if line_number is not None and line_text is not None:
45 item = "%s(%d): %s" % (self.path, line_number, line_text)
46 elif line_number is not None:
47 item = "%s(%d)" % (self.path, line_number)
48 else:
49 item = self.path
50 if self.warnings_exist :
51 long_message = ''
52 else :
53 long_message = self.GetLongMessage(self.path)
54 self.warnings_exist = True
55
56 self.LogInfo(message)
57 self.results.append(
58 self.output_api.PresubmitPromptWarning(message, [item], long_message))
59
60 def ReportDeletedLabels(self, removed_labels, prefix=''):
61 message = prefix
62 message += str("It looks like you are deleting entries from the "
63 "enum definition. This should never happen.\n")
64 message += "The following labels have been deleted:\n"
65 for value in removed_labels :
66 message += "\t" + value + "\n"
67 self.EmitWarning(message)
68
69 def ExtractFistAndLasteLoginCustomFlagsLineNumberFromHistograms(self):
70 """Returns tuple (first line number, last line number) in the new version.
71 Line number starts with 1.
72 """
73 import os
74 with open(self.path, 'r') as file_handle:
75 line_number = 0
76 enum_start = 0
77 enum_end = 0
78 for line in file_handle:
79 line_number = line_number + 1
80 if self.input_api.re.match(r"^<enum name=\"LoginCustomFlags\"", line):
81 if enum_start > 0:
82 error = str("Bad '" + str(xml_file) + "' format: start of enum "
83 "LoginCustomFlags found twice: at lines "
84 + str(enum_start) + " and " + str(line_number)
85 + ".")
86 self.EmitWarning(error, line_number, line)
87 return
88 enum_start = line_number
89 elif enum_start > 0 and self.input_api.re.match(r"^ *<enum", line):
90 error = str("Bad '" + str(xml_file) + "' format: end of enum "
91 "LoginCustomFlags not found. Found new enum at line "
92 + str(line_number) + ":\n" + line)
93 self.EmitWarning(error, line_number, line)
94 return
95 elif enum_start > 0 and self.input_api.re.match(r"^</enum", line):
96 enum_end = line_number
97 break
98
99 if enum_start > 0 and enum_end > enum_start:
100 return (enum_start, enum_end)
101
102 if enum_start == 0:
103 error = str("Bad '" + str(xml_file) + "' format: start of enum "
104 "LoginCustomFlags is not found.")
105 self.EmitWarning(error, line_number, line)
106 return
107
108 if enum_end == 0:
109 error = str("Bad '" + str(xml_file) + "' format: end of enum "
110 "LoginCustomFlags is not found.")
111 self.EmitWarning(error, line_number, line)
112 return
113
114 if enum_start == enum_end:
115 error = str("Bad '" + str(xml_file) + "' format: end of enum "
116 "LoginCustomFlags is empty.")
117 self.EmitWarning(error, line_number, line)
118 return
119
120 raise Exception("Not reached.")
121
122 def CheckDiff(self, affected_file):
123 """Check diff is valid."""
124 added_labels = []
125 removed_labels = []
126 skip_chunk = True
127 line_num = 0
128 old_enum_start_found = False
129 old_enum_end_found = False
130 for line in affected_file.GenerateScmDiff().splitlines():
131 # Parse the unified diff chunk optional section heading, which looks like
132 # @@ -l,s +l,s @@ optional section heading
133 m = self.input_api.re.match(
134 r"^@@ \-([0-9]+)\,([0-9]+) \+([0-9]+)\,([0-9]+) @@", line)
135 if m:
136 old_line_num = int(m.group(1))
137 old_size = int(m.group(2))
138 new_line_num = int(m.group(3))
139 new_size = int(m.group(4))
140 line_num = new_line_num
141 skip_chunk = False
142 if line_num >= self.enum_end:
143 skip_chunk = True
144 elif line_num + new_size <= self.enum_start:
145 skip_chunk = True
146 # This line number applies for the next input line, so subtract 1.
147 line_num -= 1
148 continue
149
150 if skip_chunk:
151 continue
152
153 if not line.startswith("-"):
154 line_num += 1
155
156 if line_num >= self.enum_end:
157 break
158
159 self.LogDebug("Analysing line '" + line + "'")
160
161 if line_num == self.enum_start:
162 self.LogDebug("Found enum start.")
163
164 if line_num >= self.enum_start:
165 if not old_enum_start_found:
166 self.LogDebug("old_enum_start_found is true because "
167 "line_num >= self.enum_start")
168 old_enum_start_found = True
169 else:
170 m = self.input_api.re.match(
171 r"^([+ -])<enum name=\"LoginCustomFlags\"", line)
172 if m:
173 if m.group(1) == "-" :
174 old_enum_start_found = True
175 self.LogDebug("old_enum_start_found is true because "
176 "removal of old enum found.")
177 else:
178 # Raise exception if enum LoginCustomFlags found added (or not
179 # modified) at the line number before it was found in current
180 # histograms.xml version.
181 raise Exception("Error parsing changes to histograms.xml:\n"
182 "Diff line '" + line + "' unexpected.");
183
184 if not old_enum_start_found:
185 continue
186
187 m = self.input_api.re.match(r"^- *</enum", line)
188 if m:
189 old_enum_end_found = True
190 continue
191
192 # Ignore unchanged items here.
193 m = self.input_api.re.match(
194 r"^([+-]) *<int .*label *= *\"?([^\"]+)", line)
195
196 if not m:
197 continue
198
199 self.LogDebug("MATCHED '" + line + "'")
200
201 if m.group(1) == "+" and line_num > self.enum_start and \
202 line_num < self.enum_end:
203 added_labels.append(m.group(2))
204 elif m.group(1) == "-" and old_enum_start_found and \
205 not old_enum_end_found:
206 removed_labels.append(m.group(2))
207
208 self.LogDebug("removed_labels: " + str(removed_labels))
209 self.LogDebug("added_labels: " + str(added_labels))
210
211 removed_completely = []
212 for label in removed_labels:
213 if label not in added_labels:
214 removed_completely.append(label)
215 if len(removed_completely):
216 self.ReportDeletedLabels(removed_completely)
217
218 return False if len(removed_completely) else True
219
220 def PerformChecks(self, affected_file):
221 (self.enum_start, self.enum_end) = \
222 self.ExtractFistAndLasteLoginCustomFlagsLineNumberFromHistograms()
223 self.LogDebug("enum first-last lines are:"
224 + str((self.enum_start, self.enum_end)))
225
226 if len(self.results) == 0:
227 self.CheckDiff(affected_file)
228
229 def Run(self):
230 for file in self.input_api.AffectedFiles(include_deletes=True):
231 if self.input_api.basename(file.LocalPath()) == \
232 self.input_api.basename(self.path):
233 self.LogInfo("LoginCustomFlagsChecker: Start processing file.")
234 self.PerformChecks(file)
235 self.LogInfo("LoginCustomFlagsChecker: Done processing file.")
236 return self.results
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698