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

Side by Side Diff: tools/foozzie/v8_suppressions.py

Issue 2578503003: [foozzie] Initial correctness fuzzer harness. (Closed)
Patch Set: updates Created 4 years 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 2016 the V8 project 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 """
6 Suppressions for V8 correctness fuzzer failures.
7
8 We support three types of suppressions:
9 1. Ignore test case by pattern.
10 Map a regular expression to a bug entry. A new failure will be reported
11 when the pattern matches a JS test case.
12 Subsequent matches will be recoreded under the first failure.
13
14 2. Ignore test run by output pattern:
15 Map a regular expression to a bug entry. A new failure will be reported
16 when the pattern matches the output of a particular run.
17 Subsequent matches will be recoreded under the first failure.
18
19 3. Relax line-to-line comparisons with expressions of lines to ignore and
20 lines to be normalized (i.e. ignore only portions of lines).
21 These are not tied to bugs, be careful to not silently switch off this tool!
22
23 Alternatively, think about adding a behavior change to v8_suppressions.js
24 to silence a particular class of problems.
25 """
26
27 import itertools
28 import re
29
30 # Max line length for regular experessions checking for lines to ignore.
31 MAX_LINE_LENGTH = 512
32
33 # For ignoring lines before carets and to ignore caret positions.
34 CARET_RE = re.compile(r'^\s*\^\s*$')
35
36 # Ignore by test case pattern. Map from bug->regexp.
37 # Regular expressions are assumed to be compiled. We use regexp.match.
38 IGNORE_TEST_CASES = {
39 'crbug.com/662907':
40 re.compile(r'.*new Array.*\[\d+\] =.*'
41 r'((Array)|(Object)).prototype.__defineSetter__.*', re.S),
42
43 'crbug.com/663340':
44 re.compile(r'.*\.shift\(\).*', re.S),
45
46 'crbug.com/666308':
47 re.compile(r'.*End stripped down and modified version.*'
48 r'\.prototype.*instanceof.*.*', re.S),
49 }
50
51 # Ignore by output pattern. Map from config->bug->regexp. Config '' is used
52 # to match all configurations. Otherwise use either a compiler configuration,
53 # e.g. fullcode or validate_asm or an architecture, e.g. x64 or ia32 or a
54 # comma-separated combination, e.g. x64,fullcode, for more specific
55 # suppressions.
56 # Bug is preferred to be a crbug.com/XYZ, but can be any short distinguishable
57 # label.
58 # Regular expressions are assumed to be compiled. We use regexp.search.
59 IGNORE_OUTPUT = {
60 '': {
61 'crbug.com/664068':
62 re.compile(r'RangeError', re.S),
63
64 'crbug.com/669017':
65 re.compile(r'SyntaxError', re.S),
66 },
67 'validate_asm': {
68 'validate_asm':
69 re.compile(r'TypeError'),
70 },
71 }
72
73 # Lines matching any of the following regular expressions will be ignored
74 # if appearing on both sides. The capturing groups need to match exactly.
75 # Use uncompiled regular expressions.
tandrii(chromium) 2016/12/19 08:43:33 why? ah, i guessed correctly; maybe: Use uncompile
Michael Achenbach 2016/12/19 09:42:19 Done.
76 ALLOWED_LINE_DIFFS = [
77 # Ignore caret position in stack traces.
78 r'^\s*\^\s*$',
79
80 # Ignore some stack trace headers as messages might not match.
81 r'^(.*)TypeError: .* is not a function$',
82 r'^(.*)TypeError: .* is not a constructor$',
83 r'^(.*)TypeError: (.*) is not .*$',
84 r'^(.*)ReferenceError: .* is not defined$',
85 r'^(.*):\d+: ReferenceError: .* is not defined$',
86
87 # These are rarely needed. It includes some cases above.
88 r'^\w*Error: .* is not .*$',
89 r'^(.*) \w*Error: .* is not .*$',
90 r'^(.*):\d+: \w*Error: .* is not .*$',
91
92 # Some test cases just print the message.
93 r'^.* is not a function(.*)$',
94 r'^(.*) is not a .*$',
95
96 # crbug.com/669017
97 r'^(.*)SyntaxError: .*$',
98
99 # Ignore lines of stack traces as character positions might not match.
100 r'^ at (?:new )?([^:]*):\d+:\d+(.*)$',
101 r'^(.*):\d+:(.*)$',
102
103 # crbug.com/662840
104 r"^.*(?:Trying to access ')?(\w*)(?:(?:' through proxy)|"
105 r"(?: is not defined))$",
106 ]
107
108 # Lines matching any of the following regular expressions will be ignored.
109 # Use uncompiled regular expressions.
110 IGNORE_LINES = [
111 r'^Validation of asm\.js module failed: .+$',
112 r'^.*:\d+: Invalid asm.js: .*$',
113 r'^Warning: unknown flag .*$',
114 r'^Warning: .+ is deprecated.*$',
115 r'^Try --help for options$',
116 ]
117
118
119 ###############################################################################
120 # Implementation - you should not need to change anything below this point.
121
122 # Compile regular expressions.
123 ALLOWED_LINE_DIFFS = [re.compile(exp) for exp in ALLOWED_LINE_DIFFS]
124 IGNORE_LINES = [re.compile(exp) for exp in IGNORE_LINES]
125
126
127 def line_pairs(lines):
128 for i in range(len(lines) - 1):
tandrii(chromium) 2016/12/19 08:43:32 xrange but i'd do this: for i, l in enumerate(li
Michael Achenbach 2016/12/19 09:42:19 Done, even nicer :)
129 yield lines[i], lines[i + 1]
130 if lines:
131 yield lines[-1], None
132
133
134 def filter_error_pos(lines):
135 for line, lookahead in line_pairs(lines):
136 # Look ahead. If next line is a caret, ignore this line.
137 try:
tandrii(chromium) 2016/12/19 08:43:33 # shorter, and no need to catch KeyboardInterrupt
Michael Achenbach 2016/12/19 09:42:19 Done. Removed the dead code :)
138 if CARET_RE.match(lookahead):
139 continue
140 except Exception:
141 # To ignore sentinel on last line.
142 pass
143 if CARET_RE.match(line):
144 # Ignore the caret too.
145 continue
146 yield line
147
148
149 def caret_match(line1, line2):
150 if (not line1 or
151 not line2 or
152 len(line1) > MAX_LINE_LENGTH or
153 len(line2) > MAX_LINE_LENGTH):
154 return False
155 return bool(CARET_RE.match(line1) and CARET_RE.match(line2))
156
157
158 def short_line_output(line):
159 if len(line) <= MAX_LINE_LENGTH:
160 # Avoid copying.
161 return line
162 return line[0:MAX_LINE_LENGTH] + '...'
163
164
165 def ignore_by_regexp(line1, line2, allowed):
166 if len(line1) > MAX_LINE_LENGTH or len(line2) > MAX_LINE_LENGTH:
167 return False
168 for exp in allowed:
169 match1 = exp.match(line1)
170 match2 = exp.match(line2)
171 if match1 and match2:
172 # If there are groups in the regexp, ensure the groups matched the same
173 # things.
174 for j, g in enumerate(match1.groups()):
tandrii(chromium) 2016/12/19 08:43:33 return match1.groups() == match2.groups() # tuple
Michael Achenbach 2016/12/19 09:42:19 Done. Except we can't just return - only in True c
175 if g != match2.groups()[j]:
176 break
177 else:
178 # Regexp matched and all groups are equal. Ignore these lines.
179 return True
180 return False
181
182
183 def diff_output(output1, output2, allowed, ignore1, ignore2):
184 def useful_line(ignore):
185 def fun(line):
186 for exp in ignore:
187 if exp.match(line):
188 return False
189 return True
tandrii(chromium) 2016/12/19 08:43:33 return all(not e.match(line) for e in ignore)
Michael Achenbach 2016/12/19 09:42:19 Done.
190 return fun
191
192 lines1 = filter(useful_line(ignore1), output1)
193 lines2 = filter(useful_line(ignore2), output2)
194
195 for ((line1, lookahead1), (line2, lookahead2)) in itertools.izip_longest(
196 line_pairs(lines1), line_pairs(lines2), fillvalue=(None, None)):
197
198 # Only one of the two iterators should run out.
199 assert not (line1 is None and line2 is None)
200
201 # One iterator ends earlier.
202 if line1 is None:
203 return '+ %s' % short_line_output(line2)
204 if line2 is None:
205 return '- %s' % short_line_output(line1)
206
207 # If lines are equal, no further checks are necessary.
208 if line1 == line2:
209 continue
210
211 # Look ahead. If next line is a caret, ignore this line.
212 if caret_match(lookahead1, lookahead2):
213 continue
214
215 # Check if a regexp allows these lines to be different.
216 if ignore_by_regexp(line1, line2, allowed):
217 continue
218
219 # Lines are different.
220 return '- %s\n+ %s' % (short_line_output(line1), short_line_output(line2))
221
222 # No difference found.
223 return None
224
225
226 def get_suppression(arch1, config1, arch2, config2):
227 return V8Suppression(arch1, config1, arch2, config2)
228
229
230 class Suppression(object):
231 def diff(self, output1, output2):
232 return None
233
234 def ignore(self, testcase):
235 return False
236
237 def ignore_by_output1(self, output):
238 return False
239
240 def ignore_by_output2(self, output):
241 return False
242
243
244 class V8Suppression(Suppression):
245 def __init__(self, arch1, config1, arch2, config2):
246 self.arch1 = arch1
247 self.config1 = config1
248 self.arch2 = arch2
249 self.config2 = config2
250
251 def diff(self, output1, output2):
252 return diff_output(
253 output1.splitlines(),
254 output2.splitlines(),
255 ALLOWED_LINE_DIFFS,
256 IGNORE_LINES,
257 IGNORE_LINES,
258 )
259
260 def ignore(self, testcase):
261 for bug, exp in IGNORE_TEST_CASES.iteritems():
262 if exp.match(testcase):
263 return bug
264 return False
265
266 def ignore_by_output1(self, output):
267 return self.ignore_by_output(output, self.arch1, self.config1)
268
269 def ignore_by_output2(self, output):
270 return self.ignore_by_output(output, self.arch2, self.config2)
271
272 def ignore_by_output(self, output, arch, config):
273 def check(mapping):
274 for bug, exp in mapping.iteritems():
275 if exp.search(output):
276 return bug
277 return None
278 bug = check(IGNORE_OUTPUT.get('', {}))
279 if bug:
280 return bug
281 bug = check(IGNORE_OUTPUT.get(arch, {}))
282 if bug:
283 return bug
284 bug = check(IGNORE_OUTPUT.get(config, {}))
285 if bug:
286 return bug
287 bug = check(IGNORE_OUTPUT.get('%s,%s' % (arch, config), {}))
288 if bug:
289 return bug
290 return None
291
OLDNEW
« tools/foozzie/v8_suppressions.js ('K') | « tools/foozzie/v8_suppressions.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698