OLD | NEW |
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 15 matching lines...) Expand all Loading... |
26 ignition_staging=['--ignition-staging'], | 26 ignition_staging=['--ignition-staging'], |
27 ignition_turbo=['--ignition-staging', '--turbo'], | 27 ignition_turbo=['--ignition-staging', '--turbo'], |
28 ignition_turbo_opt=['--ignition-staging', '--turbo', '--always-opt'], | 28 ignition_turbo_opt=['--ignition-staging', '--turbo', '--always-opt'], |
29 ) | 29 ) |
30 | 30 |
31 # Timeout in seconds for one d8 run. | 31 # Timeout in seconds for one d8 run. |
32 TIMEOUT = 3 | 32 TIMEOUT = 3 |
33 | 33 |
34 # Return codes. | 34 # Return codes. |
35 RETURN_PASS = 0 | 35 RETURN_PASS = 0 |
36 RETURN_FAILURE = 2 | 36 RETURN_FAIL = 2 |
37 | 37 |
38 BASE_PATH = os.path.dirname(os.path.abspath(__file__)) | 38 BASE_PATH = os.path.dirname(os.path.abspath(__file__)) |
39 PREAMBLE = [ | 39 PREAMBLE = [ |
40 os.path.join(BASE_PATH, 'v8_mock.js'), | 40 os.path.join(BASE_PATH, 'v8_mock.js'), |
41 os.path.join(BASE_PATH, 'v8_suppressions.js'), | 41 os.path.join(BASE_PATH, 'v8_suppressions.js'), |
42 ] | 42 ] |
43 | 43 |
44 FLAGS = ['--abort_on_stack_overflow', '--expose-gc', '--allow-natives-syntax', | 44 FLAGS = ['--abort_on_stack_overflow', '--expose-gc', '--allow-natives-syntax', |
45 '--invoke-weak-callbacks', '--omit-quit', '--es-staging'] | 45 '--invoke-weak-callbacks', '--omit-quit', '--es-staging'] |
46 | 46 |
47 SUPPORTED_ARCHS = ['ia32', 'x64', 'arm', 'arm64'] | 47 SUPPORTED_ARCHS = ['ia32', 'x64', 'arm', 'arm64'] |
48 | 48 |
49 # Output for suppressed failure case. | 49 # Output for suppressed failure case. |
50 FAILURE_HEADER_TEMPLATE = """ | 50 FAILURE_HEADER_TEMPLATE = """# |
51 # | |
52 # V8 correctness failure | 51 # V8 correctness failure |
53 # V8 correctness configs: %(configs)s | 52 # V8 correctness configs: %(configs)s |
54 # V8 correctness sources: %(sources)s | 53 # V8 correctness sources: %(sources)s |
55 # V8 correctness suppression: %(suppression)s""".strip() | 54 # V8 correctness suppression: %(suppression)s |
| 55 """ |
56 | 56 |
57 # Extended output for failure case. The 'CHECK' is for the minimizer. | 57 # Extended output for failure case. The 'CHECK' is for the minimizer. |
58 FAILURE_TEMPLATE = FAILURE_HEADER_TEMPLATE + """ | 58 FAILURE_TEMPLATE = FAILURE_HEADER_TEMPLATE + """# |
59 # | |
60 # CHECK | 59 # CHECK |
61 # | 60 # |
62 # Compared %(first_config_label)s with %(second_config_label)s | 61 # Compared %(first_config_label)s with %(second_config_label)s |
63 # | 62 # |
64 # Flags of %(first_config_label)s: | 63 # Flags of %(first_config_label)s: |
65 %(first_config_flags)s | 64 %(first_config_flags)s |
66 # Flags of %(second_config_label)s: | 65 # Flags of %(second_config_label)s: |
67 %(second_config_flags)s | 66 %(second_config_flags)s |
68 # | 67 # |
69 # Difference: | 68 # Difference: |
70 %(difference)s | 69 %(difference)s |
71 # | 70 # |
72 ### Start of configuration %(first_config_label)s: | 71 ### Start of configuration %(first_config_label)s: |
73 %(first_config_output)s | 72 %(first_config_output)s |
74 ### End of configuration %(first_config_label)s | 73 ### End of configuration %(first_config_label)s |
75 # | 74 # |
76 ### Start of configuration %(second_config_label)s: | 75 ### Start of configuration %(second_config_label)s: |
77 %(second_config_output)s | 76 %(second_config_output)s |
78 ### End of configuration %(second_config_label)s | 77 ### End of configuration %(second_config_label)s |
79 """.strip() | 78 """ |
80 | 79 |
81 | 80 |
82 def parse_args(): | 81 def parse_args(): |
83 parser = argparse.ArgumentParser() | 82 parser = argparse.ArgumentParser() |
84 parser.add_argument( | 83 parser.add_argument( |
85 '--random-seed', type=int, required=True, | 84 '--random-seed', type=int, required=True, |
86 help='random seed passed to both runs') | 85 help='random seed passed to both runs') |
87 parser.add_argument( | 86 parser.add_argument( |
88 '--first-arch', help='first architecture', default='x64') | 87 '--first-arch', help='first architecture', default='x64') |
89 parser.add_argument( | 88 parser.add_argument( |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 def main(): | 172 def main(): |
174 options = parse_args() | 173 options = parse_args() |
175 | 174 |
176 # Suppressions are architecture and configuration specific. | 175 # Suppressions are architecture and configuration specific. |
177 suppress = v8_suppressions.get_suppression( | 176 suppress = v8_suppressions.get_suppression( |
178 options.first_arch, options.first_config, | 177 options.first_arch, options.first_config, |
179 options.second_arch, options.second_config, | 178 options.second_arch, options.second_config, |
180 ) | 179 ) |
181 | 180 |
182 if test_pattern_bailout(options.testcase, suppress.ignore): | 181 if test_pattern_bailout(options.testcase, suppress.ignore): |
183 return RETURN_FAILURE | 182 return RETURN_FAIL |
184 | 183 |
185 common_flags = FLAGS + ['--random-seed', str(options.random_seed)] | 184 common_flags = FLAGS + ['--random-seed', str(options.random_seed)] |
186 first_config_flags = common_flags + CONFIGS[options.first_config] | 185 first_config_flags = common_flags + CONFIGS[options.first_config] |
187 second_config_flags = common_flags + CONFIGS[options.second_config] | 186 second_config_flags = common_flags + CONFIGS[options.second_config] |
188 | 187 |
189 def run_d8(d8, config_flags): | 188 def run_d8(d8, config_flags): |
| 189 args = [d8] + config_flags + PREAMBLE + [options.testcase] |
| 190 if d8.endswith('.py'): |
| 191 # Wrap with python in tests. |
| 192 args = [sys.executable] + args |
190 return v8_commands.Execute( | 193 return v8_commands.Execute( |
191 [d8] + config_flags + PREAMBLE + [options.testcase], | 194 args, |
192 cwd=os.path.dirname(options.testcase), | 195 cwd=os.path.dirname(options.testcase), |
193 timeout=TIMEOUT, | 196 timeout=TIMEOUT, |
194 ) | 197 ) |
195 | 198 |
196 first_config_output = run_d8(options.first_d8, first_config_flags) | 199 first_config_output = run_d8(options.first_d8, first_config_flags) |
197 | 200 |
198 # Early bailout based on first run's output. | 201 # Early bailout based on first run's output. |
199 if pass_bailout(first_config_output, 1): | 202 if pass_bailout(first_config_output, 1): |
200 return RETURN_PASS | 203 return RETURN_PASS |
201 if fail_bailout(first_config_output, suppress.ignore_by_output1): | 204 if fail_bailout(first_config_output, suppress.ignore_by_output1): |
202 return RETURN_FAILURE | 205 return RETURN_FAIL |
203 | 206 |
204 second_config_output = run_d8(options.second_d8, second_config_flags) | 207 second_config_output = run_d8(options.second_d8, second_config_flags) |
205 | 208 |
206 # Bailout based on second run's output. | 209 # Bailout based on second run's output. |
207 if pass_bailout(second_config_output, 2): | 210 if pass_bailout(second_config_output, 2): |
208 return RETURN_PASS | 211 return RETURN_PASS |
209 if fail_bailout(second_config_output, suppress.ignore_by_output2): | 212 if fail_bailout(second_config_output, suppress.ignore_by_output2): |
210 return RETURN_FAILURE | 213 return RETURN_FAIL |
211 | 214 |
212 difference = suppress.diff( | 215 difference = suppress.diff( |
213 first_config_output.stdout, second_config_output.stdout) | 216 first_config_output.stdout, second_config_output.stdout) |
214 if difference: | 217 if difference: |
215 # The first three entries will be parsed by clusterfuzz. Format changes | 218 # The first three entries will be parsed by clusterfuzz. Format changes |
216 # will require changes on the clusterfuzz side. | 219 # will require changes on the clusterfuzz side. |
217 first_config_label = '%s,%s' % (options.first_arch, options.first_config) | 220 first_config_label = '%s,%s' % (options.first_arch, options.first_config) |
218 second_config_label = '%s,%s' % (options.second_arch, options.second_config) | 221 second_config_label = '%s,%s' % (options.second_arch, options.second_config) |
219 print FAILURE_TEMPLATE % dict( | 222 print FAILURE_TEMPLATE % dict( |
220 configs='%s:%s' % (first_config_label, second_config_label), | 223 configs='%s:%s' % (first_config_label, second_config_label), |
221 sources='', # TODO | 224 sources='', # TODO |
222 suppression='', # We can't tie bugs to differences. | 225 suppression='', # We can't tie bugs to differences. |
223 first_config_label=first_config_label, | 226 first_config_label=first_config_label, |
224 second_config_label=second_config_label, | 227 second_config_label=second_config_label, |
225 first_config_flags=' '.join(first_config_flags), | 228 first_config_flags=' '.join(first_config_flags), |
226 second_config_flags=' '.join(second_config_flags), | 229 second_config_flags=' '.join(second_config_flags), |
227 first_config_output=first_config_output.stdout, | 230 first_config_output=first_config_output.stdout, |
228 second_config_output=second_config_output.stdout, | 231 second_config_output=second_config_output.stdout, |
229 difference=difference, | 232 difference=difference, |
230 ) | 233 ) |
231 return RETURN_FAILURE | 234 return RETURN_FAIL |
232 | 235 |
233 # TODO(machenbach): Figure out if we could also return a bug in case there's | 236 # TODO(machenbach): Figure out if we could also return a bug in case there's |
234 # no difference, but one of the line suppressions has matched - and without | 237 # no difference, but one of the line suppressions has matched - and without |
235 # the match there would be a difference. | 238 # the match there would be a difference. |
236 | 239 |
237 print '# V8 correctness - pass' | 240 print '# V8 correctness - pass' |
238 return RETURN_PASS | 241 return RETURN_PASS |
239 | 242 |
240 | 243 |
241 if __name__ == "__main__": | 244 if __name__ == "__main__": |
242 try: | 245 try: |
243 result = main() | 246 result = main() |
244 except SystemExit: | 247 except SystemExit: |
245 # Make sure clusterfuzz reports internal errors and wrong usage. | 248 # Make sure clusterfuzz reports internal errors and wrong usage. |
246 # Use one label for all internal and usage errors. | 249 # Use one label for all internal and usage errors. |
247 print FAILURE_HEADER_TEMPLATE % dict( | 250 print FAILURE_HEADER_TEMPLATE % dict( |
248 configs='', sources='', suppression='wrong_usage') | 251 configs='', sources='', suppression='wrong_usage') |
249 result = RETURN_FAILURE | 252 result = RETURN_FAIL |
250 except Exception as e: | 253 except Exception as e: |
251 print FAILURE_HEADER_TEMPLATE % dict( | 254 print FAILURE_HEADER_TEMPLATE % dict( |
252 configs='', sources='', suppression='internal_error') | 255 configs='', sources='', suppression='internal_error') |
253 print '# Internal error: %s' % e | 256 print '# Internal error: %s' % e |
254 traceback.print_exc(file=sys.stdout) | 257 traceback.print_exc(file=sys.stdout) |
255 result = RETURN_FAILURE | 258 result = RETURN_FAIL |
256 | 259 |
257 sys.exit(result) | 260 sys.exit(result) |
OLD | NEW |