OLD | NEW |
---|---|
1 # Copyright 2016 the V8 project authors. All rights reserved. | 1 # Copyright 2016 the V8 project 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 """ | 5 """ |
6 Suppressions for V8 correctness fuzzer failures. | 6 Suppressions for V8 correctness fuzzer failures. |
7 | 7 |
8 We support three types of suppressions: | 8 We support three types of suppressions: |
9 1. Ignore test case by pattern. | 9 1. Ignore test case by pattern. |
10 Map a regular expression to a bug entry. A new failure will be reported | 10 Map a regular expression to a bug entry. A new failure will be reported |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 match2 = exp.match(line2) | 175 match2 = exp.match(line2) |
176 if match1 and match2: | 176 if match1 and match2: |
177 # If there are groups in the regexp, ensure the groups matched the same | 177 # If there are groups in the regexp, ensure the groups matched the same |
178 # things. | 178 # things. |
179 if match1.groups() == match2.groups(): # tuple comparison | 179 if match1.groups() == match2.groups(): # tuple comparison |
180 return True | 180 return True |
181 return False | 181 return False |
182 | 182 |
183 | 183 |
184 def diff_output(output1, output2, allowed, ignore1, ignore2): | 184 def diff_output(output1, output2, allowed, ignore1, ignore2): |
185 """Returns a tuple (difference, source_key). | 185 """Returns a tuple (difference, source, source_key). |
186 | 186 |
187 The difference is None if there's no difference, otherwise a string | 187 The difference is None if there's no difference, otherwise a string |
188 with a readable diff. | 188 with a readable diff. |
189 | 189 |
190 The source_key is a short hash of the last source output within the test | 190 The source is the last source output within the test case. It is the string |
191 case. It is the string 'none' if no such output existed. | 191 'none' if no such output existed. |
mmoroz
2017/01/16 12:39:58
nit: maybe it makes sense to put 'none' string int
Michael Achenbach
2017/01/16 12:58:41
Done.
| |
192 | |
193 The source_key is a short hash of source or 'none'. | |
192 """ | 194 """ |
193 def useful_line(ignore): | 195 def useful_line(ignore): |
194 def fun(line): | 196 def fun(line): |
195 return all(not e.match(line) for e in ignore) | 197 return all(not e.match(line) for e in ignore) |
196 return fun | 198 return fun |
197 | 199 |
198 lines1 = filter(useful_line(ignore1), output1) | 200 lines1 = filter(useful_line(ignore1), output1) |
199 lines2 = filter(useful_line(ignore2), output2) | 201 lines2 = filter(useful_line(ignore2), output2) |
200 | 202 |
201 # This keeps track where we are in the original source file of the fuzz | 203 # This keeps track where we are in the original source file of the fuzz |
202 # test case. | 204 # test case. |
205 source = 'none' | |
203 source_key = 'none' | 206 source_key = 'none' |
204 | 207 |
205 for ((line1, lookahead1), (line2, lookahead2)) in itertools.izip_longest( | 208 for ((line1, lookahead1), (line2, lookahead2)) in itertools.izip_longest( |
206 line_pairs(lines1), line_pairs(lines2), fillvalue=(None, None)): | 209 line_pairs(lines1), line_pairs(lines2), fillvalue=(None, None)): |
207 | 210 |
208 # Only one of the two iterators should run out. | 211 # Only one of the two iterators should run out. |
209 assert not (line1 is None and line2 is None) | 212 assert not (line1 is None and line2 is None) |
210 | 213 |
211 # One iterator ends earlier. | 214 # One iterator ends earlier. |
212 if line1 is None: | 215 if line1 is None: |
213 return '+ %s' % short_line_output(line2), source_key | 216 return '+ %s' % short_line_output(line2), source, source_key |
214 if line2 is None: | 217 if line2 is None: |
215 return '- %s' % short_line_output(line1), source_key | 218 return '- %s' % short_line_output(line1), source, source_key |
216 | 219 |
217 # If lines are equal, no further checks are necessary. | 220 # If lines are equal, no further checks are necessary. |
218 if line1 == line2: | 221 if line1 == line2: |
219 # Instrumented original-source-file output must be equal in both | 222 # Instrumented original-source-file output must be equal in both |
220 # versions. It only makes sense to update it here when both lines | 223 # versions. It only makes sense to update it here when both lines |
221 # are equal. | 224 # are equal. |
222 if line1.startswith(ORIGINAL_SOURCE_PREFIX): | 225 if line1.startswith(ORIGINAL_SOURCE_PREFIX): |
223 source = line1[len(ORIGINAL_SOURCE_PREFIX):] | 226 source = line1[len(ORIGINAL_SOURCE_PREFIX):] |
224 source_key = hashlib.sha1(source).hexdigest()[:SOURCE_HASH_LENGTH] | 227 source_key = hashlib.sha1(source).hexdigest()[:SOURCE_HASH_LENGTH] |
225 continue | 228 continue |
226 | 229 |
227 # Look ahead. If next line is a caret, ignore this line. | 230 # Look ahead. If next line is a caret, ignore this line. |
228 if caret_match(lookahead1, lookahead2): | 231 if caret_match(lookahead1, lookahead2): |
229 continue | 232 continue |
230 | 233 |
231 # Check if a regexp allows these lines to be different. | 234 # Check if a regexp allows these lines to be different. |
232 if ignore_by_regexp(line1, line2, allowed): | 235 if ignore_by_regexp(line1, line2, allowed): |
233 continue | 236 continue |
234 | 237 |
235 # Lines are different. | 238 # Lines are different. |
236 return ( | 239 return ( |
237 '- %s\n+ %s' % (short_line_output(line1), short_line_output(line2)), | 240 '- %s\n+ %s' % (short_line_output(line1), short_line_output(line2)), |
241 source, | |
238 source_key, | 242 source_key, |
239 ) | 243 ) |
240 | 244 |
241 # No difference found. | 245 # No difference found. |
242 return None, source_key | 246 return None, source, source_key |
243 | 247 |
244 | 248 |
245 def get_suppression(arch1, config1, arch2, config2): | 249 def get_suppression(arch1, config1, arch2, config2): |
246 return V8Suppression(arch1, config1, arch2, config2) | 250 return V8Suppression(arch1, config1, arch2, config2) |
247 | 251 |
248 | 252 |
249 class Suppression(object): | 253 class Suppression(object): |
250 def diff(self, output1, output2): | 254 def diff(self, output1, output2): |
251 return None | 255 return None |
252 | 256 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
309 bug = check(IGNORE_OUTPUT.get(arch, {})) | 313 bug = check(IGNORE_OUTPUT.get(arch, {})) |
310 if bug: | 314 if bug: |
311 return bug | 315 return bug |
312 bug = check(IGNORE_OUTPUT.get(config, {})) | 316 bug = check(IGNORE_OUTPUT.get(config, {})) |
313 if bug: | 317 if bug: |
314 return bug | 318 return bug |
315 bug = check(IGNORE_OUTPUT.get('%s,%s' % (arch, config), {})) | 319 bug = check(IGNORE_OUTPUT.get('%s,%s' % (arch, config), {})) |
316 if bug: | 320 if bug: |
317 return bug | 321 return bug |
318 return None | 322 return None |
OLD | NEW |