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

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

Issue 2634743004: [foozzie] Stop using extra metadata files. (Closed)
Patch Set: Review Created 3 years, 11 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
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2016 the V8 project authors. All rights reserved. 2 # Copyright 2016 the V8 project authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """ 6 """
7 V8 correctness fuzzer launcher script. 7 V8 correctness fuzzer launcher script.
8 """ 8 """
9 9
10 import argparse 10 import argparse
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 44
45 FLAGS = ['--abort_on_stack_overflow', '--expose-gc', '--allow-natives-syntax', 45 FLAGS = ['--abort_on_stack_overflow', '--expose-gc', '--allow-natives-syntax',
46 '--invoke-weak-callbacks', '--omit-quit', '--es-staging'] 46 '--invoke-weak-callbacks', '--omit-quit', '--es-staging']
47 47
48 SUPPORTED_ARCHS = ['ia32', 'x64', 'arm', 'arm64'] 48 SUPPORTED_ARCHS = ['ia32', 'x64', 'arm', 'arm64']
49 49
50 # Output for suppressed failure case. 50 # Output for suppressed failure case.
51 FAILURE_HEADER_TEMPLATE = """# 51 FAILURE_HEADER_TEMPLATE = """#
52 # V8 correctness failure 52 # V8 correctness failure
53 # V8 correctness configs: %(configs)s 53 # V8 correctness configs: %(configs)s
54 # V8 correctness sources: %(sources)s 54 # V8 correctness sources: %(source_key)s
55 # V8 correctness suppression: %(suppression)s 55 # V8 correctness suppression: %(suppression)s
56 """ 56 """
57 57
58 # Extended output for failure case. The 'CHECK' is for the minimizer. 58 # Extended output for failure case. The 'CHECK' is for the minimizer.
59 FAILURE_TEMPLATE = FAILURE_HEADER_TEMPLATE + """# 59 FAILURE_TEMPLATE = FAILURE_HEADER_TEMPLATE + """#
60 # CHECK 60 # CHECK
61 # 61 #
62 # Compared %(first_config_label)s with %(second_config_label)s 62 # Compared %(first_config_label)s with %(second_config_label)s
63 # 63 #
64 # Flags of %(first_config_label)s: 64 # Flags of %(first_config_label)s:
65 %(first_config_flags)s 65 %(first_config_flags)s
66 # Flags of %(second_config_label)s: 66 # Flags of %(second_config_label)s:
67 %(second_config_flags)s 67 %(second_config_flags)s
68 # 68 #
69 # Difference: 69 # Difference:
70 %(difference)s 70 %(difference)s
71 # 71 #
72 # Source file:
73 %(source)s
74 #
72 ### Start of configuration %(first_config_label)s: 75 ### Start of configuration %(first_config_label)s:
73 %(first_config_output)s 76 %(first_config_output)s
74 ### End of configuration %(first_config_label)s 77 ### End of configuration %(first_config_label)s
75 # 78 #
76 ### Start of configuration %(second_config_label)s: 79 ### Start of configuration %(second_config_label)s:
77 %(second_config_output)s 80 %(second_config_output)s
78 ### End of configuration %(second_config_label)s 81 ### End of configuration %(second_config_label)s
79 """ 82 """
80 83
81 FUZZ_TEST_RE = re.compile(r'.*fuzz(-\d+\.js)') 84 FUZZ_TEST_RE = re.compile(r'.*fuzz(-\d+\.js)')
85 SOURCE_RE = re.compile(r'print\("v8-foozzie source: (.*)"\);')
82 86
83 def parse_args(): 87 def parse_args():
84 parser = argparse.ArgumentParser() 88 parser = argparse.ArgumentParser()
85 parser.add_argument( 89 parser.add_argument(
86 '--random-seed', type=int, required=True, 90 '--random-seed', type=int, required=True,
87 help='random seed passed to both runs') 91 help='random seed passed to both runs')
88 parser.add_argument( 92 parser.add_argument(
89 '--first-arch', help='first architecture', default='x64') 93 '--first-arch', help='first architecture', default='x64')
90 parser.add_argument( 94 parser.add_argument(
91 '--second-arch', help='second architecture', default='x64') 95 '--second-arch', help='second architecture', default='x64')
(...skipping 18 matching lines...) Expand all
110 assert options.first_arch in SUPPORTED_ARCHS 114 assert options.first_arch in SUPPORTED_ARCHS
111 assert options.second_arch in SUPPORTED_ARCHS 115 assert options.second_arch in SUPPORTED_ARCHS
112 assert options.first_config in CONFIGS 116 assert options.first_config in CONFIGS
113 assert options.second_config in CONFIGS 117 assert options.second_config in CONFIGS
114 118
115 # Ensure we have a test case. 119 # Ensure we have a test case.
116 assert (os.path.exists(options.testcase) and 120 assert (os.path.exists(options.testcase) and
117 os.path.isfile(options.testcase)), ( 121 os.path.isfile(options.testcase)), (
118 'Test case %s doesn\'t exist' % options.testcase) 122 'Test case %s doesn\'t exist' % options.testcase)
119 123
120 # Deduce metadata file name from test case. This also removes
121 # the prefix the test case might get during minimization.
122 suffix = FUZZ_TEST_RE.match(os.path.basename(options.testcase)).group(1)
123 options.meta_data_path = os.path.join(
124 os.path.dirname(options.testcase), 'meta' + suffix)
125 assert os.path.exists(options.meta_data_path), (
126 'Metadata %s doesn\'t exist' % options.meta_data_path)
127
128 # Use first d8 as default for second d8. 124 # Use first d8 as default for second d8.
129 options.second_d8 = options.second_d8 or options.first_d8 125 options.second_d8 = options.second_d8 or options.first_d8
130 126
131 # Ensure absolute paths. 127 # Ensure absolute paths.
132 if not os.path.isabs(options.first_d8): 128 if not os.path.isabs(options.first_d8):
133 options.first_d8 = os.path.join(BASE_PATH, options.first_d8) 129 options.first_d8 = os.path.join(BASE_PATH, options.first_d8)
134 if not os.path.isabs(options.second_d8): 130 if not os.path.isabs(options.second_d8):
135 options.second_d8 = os.path.join(BASE_PATH, options.second_d8) 131 options.second_d8 = os.path.join(BASE_PATH, options.second_d8)
136 132
137 # Ensure executables exist. 133 # Ensure executables exist.
138 assert os.path.exists(options.first_d8) 134 assert os.path.exists(options.first_d8)
139 assert os.path.exists(options.second_d8) 135 assert os.path.exists(options.second_d8)
140 136
141 # Ensure we use different executables when we claim we compare 137 # Ensure we use different executables when we claim we compare
142 # different architectures. 138 # different architectures.
143 # TODO(machenbach): Infer arch from gn's build output. 139 # TODO(machenbach): Infer arch from gn's build output.
144 if options.first_arch != options.second_arch: 140 if options.first_arch != options.second_arch:
145 assert options.first_d8 != options.second_d8 141 assert options.first_d8 != options.second_d8
146 142
147 return options 143 return options
148 144
149 145
150 def metadata_bailout(metadata, ignore_fun): 146 def get_meta_data(content):
151 """Print failure state and return if ignore_fun matches metadata.""" 147 """Extracts original-source-file paths from test case content."""
152 bug = (ignore_fun(metadata) or '').strip() 148 sources = []
149 for line in content.splitlines():
150 match = SOURCE_RE.match(line)
151 if match:
152 sources.append(match.group(1))
153 return {'sources': sources}
154
155
156 def content_bailout(content, ignore_fun):
157 """Print failure state and return if ignore_fun matches content."""
158 bug = (ignore_fun(content) or '').strip()
153 if bug: 159 if bug:
154 print FAILURE_HEADER_TEMPLATE % dict( 160 print FAILURE_HEADER_TEMPLATE % dict(
155 configs='', sources='', suppression=bug) 161 configs='', source_key='', suppression=bug)
156 return True 162 return True
157 return False 163 return False
158 164
159 165
160 def test_pattern_bailout(testcase, ignore_fun):
161 """Print failure state and return if ignore_fun matches testcase."""
162 with open(testcase) as f:
163 bug = (ignore_fun(f.read()) or '').strip()
164 if bug:
165 print FAILURE_HEADER_TEMPLATE % dict(
166 configs='', sources='', suppression=bug)
167 return True
168 return False
169
170
171 def pass_bailout(output, step_number): 166 def pass_bailout(output, step_number):
172 """Print info and return if in timeout or crash pass states.""" 167 """Print info and return if in timeout or crash pass states."""
173 if output.HasTimedOut(): 168 if output.HasTimedOut():
174 # Dashed output, so that no other clusterfuzz tools can match the 169 # Dashed output, so that no other clusterfuzz tools can match the
175 # words timeout or crash. 170 # words timeout or crash.
176 print '# V8 correctness - T-I-M-E-O-U-T %d' % step_number 171 print '# V8 correctness - T-I-M-E-O-U-T %d' % step_number
177 return True 172 return True
178 if output.HasCrashed(): 173 if output.HasCrashed():
179 print '# V8 correctness - C-R-A-S-H %d' % step_number 174 print '# V8 correctness - C-R-A-S-H %d' % step_number
180 return True 175 return True
181 return False 176 return False
182 177
183 178
184 def fail_bailout(output, ignore_by_output_fun): 179 def fail_bailout(output, ignore_by_output_fun):
185 """Print failure state and return if ignore_by_output_fun matches output.""" 180 """Print failure state and return if ignore_by_output_fun matches output."""
186 bug = (ignore_by_output_fun(output.stdout) or '').strip() 181 bug = (ignore_by_output_fun(output.stdout) or '').strip()
187 if bug: 182 if bug:
188 print FAILURE_HEADER_TEMPLATE % dict( 183 print FAILURE_HEADER_TEMPLATE % dict(
189 configs='', sources='', suppression=bug) 184 configs='', source_key='', suppression=bug)
190 return True 185 return True
191 return False 186 return False
192 187
193 188
194 def main(): 189 def main():
195 options = parse_args() 190 options = parse_args()
196 191
197 # Suppressions are architecture and configuration specific. 192 # Suppressions are architecture and configuration specific.
198 suppress = v8_suppressions.get_suppression( 193 suppress = v8_suppressions.get_suppression(
199 options.first_arch, options.first_config, 194 options.first_arch, options.first_config,
200 options.second_arch, options.second_config, 195 options.second_arch, options.second_config,
201 ) 196 )
202 197
203 # Get metadata. 198 # Static bailout based on test case content or metadata.
204 # TODO(machenbach): We probably don't need the metadata file anymore 199 with open(options.testcase) as f:
205 # now that the metadata is printed in the test cases. 200 content = f.read()
206 with open(options.meta_data_path) as f: 201 if content_bailout(get_meta_data(content), suppress.ignore_by_metadata):
207 metadata = json.load(f) 202 return RETURN_FAIL
208 203 if content_bailout(content, suppress.ignore_by_content):
209 if metadata_bailout(metadata, suppress.ignore_by_metadata):
210 return RETURN_FAIL 204 return RETURN_FAIL
211 205
212 if test_pattern_bailout(options.testcase, suppress.ignore_by_content): 206 # Set up runtime arguments.
213 return RETURN_FAIL
214
215 common_flags = FLAGS + ['--random-seed', str(options.random_seed)] 207 common_flags = FLAGS + ['--random-seed', str(options.random_seed)]
216 first_config_flags = common_flags + CONFIGS[options.first_config] 208 first_config_flags = common_flags + CONFIGS[options.first_config]
217 second_config_flags = common_flags + CONFIGS[options.second_config] 209 second_config_flags = common_flags + CONFIGS[options.second_config]
218 210
219 def run_d8(d8, config_flags): 211 def run_d8(d8, config_flags):
220 args = [d8] + config_flags + PREAMBLE + [options.testcase] 212 args = [d8] + config_flags + PREAMBLE + [options.testcase]
221 if d8.endswith('.py'): 213 if d8.endswith('.py'):
222 # Wrap with python in tests. 214 # Wrap with python in tests.
223 args = [sys.executable] + args 215 args = [sys.executable] + args
224 return v8_commands.Execute( 216 return v8_commands.Execute(
(...skipping 11 matching lines...) Expand all
236 return RETURN_FAIL 228 return RETURN_FAIL
237 229
238 second_config_output = run_d8(options.second_d8, second_config_flags) 230 second_config_output = run_d8(options.second_d8, second_config_flags)
239 231
240 # Bailout based on second run's output. 232 # Bailout based on second run's output.
241 if pass_bailout(second_config_output, 2): 233 if pass_bailout(second_config_output, 2):
242 return RETURN_PASS 234 return RETURN_PASS
243 if fail_bailout(second_config_output, suppress.ignore_by_output2): 235 if fail_bailout(second_config_output, suppress.ignore_by_output2):
244 return RETURN_FAIL 236 return RETURN_FAIL
245 237
246 difference, source_key = suppress.diff( 238 difference, source, source_key = suppress.diff(
247 first_config_output.stdout, second_config_output.stdout) 239 first_config_output.stdout, second_config_output.stdout)
248 if difference: 240 if difference:
249 # The first three entries will be parsed by clusterfuzz. Format changes 241 # The first three entries will be parsed by clusterfuzz. Format changes
250 # will require changes on the clusterfuzz side. 242 # will require changes on the clusterfuzz side.
251 first_config_label = '%s,%s' % (options.first_arch, options.first_config) 243 first_config_label = '%s,%s' % (options.first_arch, options.first_config)
252 second_config_label = '%s,%s' % (options.second_arch, options.second_config) 244 second_config_label = '%s,%s' % (options.second_arch, options.second_config)
253 print FAILURE_TEMPLATE % dict( 245 print FAILURE_TEMPLATE % dict(
254 configs='%s:%s' % (first_config_label, second_config_label), 246 configs='%s:%s' % (first_config_label, second_config_label),
255 sources=source_key, 247 source_key=source_key,
256 suppression='', # We can't tie bugs to differences. 248 suppression='', # We can't tie bugs to differences.
257 first_config_label=first_config_label, 249 first_config_label=first_config_label,
258 second_config_label=second_config_label, 250 second_config_label=second_config_label,
259 first_config_flags=' '.join(first_config_flags), 251 first_config_flags=' '.join(first_config_flags),
260 second_config_flags=' '.join(second_config_flags), 252 second_config_flags=' '.join(second_config_flags),
261 first_config_output=first_config_output.stdout, 253 first_config_output=first_config_output.stdout,
262 second_config_output=second_config_output.stdout, 254 second_config_output=second_config_output.stdout,
255 source=source,
263 difference=difference, 256 difference=difference,
264 ) 257 )
265 return RETURN_FAIL 258 return RETURN_FAIL
266 259
267 # TODO(machenbach): Figure out if we could also return a bug in case there's 260 # TODO(machenbach): Figure out if we could also return a bug in case there's
268 # no difference, but one of the line suppressions has matched - and without 261 # no difference, but one of the line suppressions has matched - and without
269 # the match there would be a difference. 262 # the match there would be a difference.
270 263
271 print '# V8 correctness - pass' 264 print '# V8 correctness - pass'
272 return RETURN_PASS 265 return RETURN_PASS
273 266
274 267
275 if __name__ == "__main__": 268 if __name__ == "__main__":
276 try: 269 try:
277 result = main() 270 result = main()
278 except SystemExit: 271 except SystemExit:
279 # Make sure clusterfuzz reports internal errors and wrong usage. 272 # Make sure clusterfuzz reports internal errors and wrong usage.
280 # Use one label for all internal and usage errors. 273 # Use one label for all internal and usage errors.
281 print FAILURE_HEADER_TEMPLATE % dict( 274 print FAILURE_HEADER_TEMPLATE % dict(
282 configs='', sources='', suppression='wrong_usage') 275 configs='', source_key='', suppression='wrong_usage')
283 result = RETURN_FAIL 276 result = RETURN_FAIL
284 except Exception as e: 277 except Exception as e:
285 print FAILURE_HEADER_TEMPLATE % dict( 278 print FAILURE_HEADER_TEMPLATE % dict(
286 configs='', sources='', suppression='internal_error') 279 configs='', source_key='', suppression='internal_error')
287 print '# Internal error: %s' % e 280 print '# Internal error: %s' % e
288 traceback.print_exc(file=sys.stdout) 281 traceback.print_exc(file=sys.stdout)
289 result = RETURN_FAIL 282 result = RETURN_FAIL
290 283
291 sys.exit(result) 284 sys.exit(result)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698