OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2008 the V8 project authors. All rights reserved. | 3 # Copyright 2008 the V8 project authors. All rights reserved. |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 | 56 |
57 def __init__(self, cases): | 57 def __init__(self, cases): |
58 self.cases = cases | 58 self.cases = cases |
59 self.queue = Queue(len(cases)) | 59 self.queue = Queue(len(cases)) |
60 for case in cases: | 60 for case in cases: |
61 self.queue.put_nowait(case) | 61 self.queue.put_nowait(case) |
62 self.succeeded = 0 | 62 self.succeeded = 0 |
63 self.remaining = len(cases) | 63 self.remaining = len(cases) |
64 self.total = len(cases) | 64 self.total = len(cases) |
65 self.failed = [ ] | 65 self.failed = [ ] |
| 66 self.crashed = 0 |
66 self.terminate = False | 67 self.terminate = False |
67 self.lock = threading.Lock() | 68 self.lock = threading.Lock() |
68 | 69 |
69 def PrintFailureHeader(self, test): | 70 def PrintFailureHeader(self, test): |
70 if test.IsNegative(): | 71 if test.IsNegative(): |
71 negative_marker = '[negative] ' | 72 negative_marker = '[negative] ' |
72 else: | 73 else: |
73 negative_marker = '' | 74 negative_marker = '' |
74 print "=== %(label)s %(negative)s===" % { | 75 print "=== %(label)s %(negative)s===" % { |
75 'label': test.GetLabel(), | 76 'label': test.GetLabel(), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 output = case.Run() | 118 output = case.Run() |
118 case.duration = (time.time() - start) | 119 case.duration = (time.time() - start) |
119 except IOError, e: | 120 except IOError, e: |
120 assert self.terminate | 121 assert self.terminate |
121 return | 122 return |
122 if self.terminate: | 123 if self.terminate: |
123 return | 124 return |
124 self.lock.acquire() | 125 self.lock.acquire() |
125 if output.UnexpectedOutput(): | 126 if output.UnexpectedOutput(): |
126 self.failed.append(output) | 127 self.failed.append(output) |
| 128 if output.HasCrashed(): |
| 129 self.crashed += 1 |
127 else: | 130 else: |
128 self.succeeded += 1 | 131 self.succeeded += 1 |
129 self.remaining -= 1 | 132 self.remaining -= 1 |
130 self.HasRun(output) | 133 self.HasRun(output) |
131 self.lock.release() | 134 self.lock.release() |
132 | 135 |
133 | 136 |
134 def EscapeCommand(command): | 137 def EscapeCommand(command): |
135 parts = [] | 138 parts = [] |
136 for part in command: | 139 for part in command: |
(...skipping 15 matching lines...) Expand all Loading... |
152 print | 155 print |
153 for failed in self.failed: | 156 for failed in self.failed: |
154 self.PrintFailureHeader(failed.test) | 157 self.PrintFailureHeader(failed.test) |
155 if failed.output.stderr: | 158 if failed.output.stderr: |
156 print "--- stderr ---" | 159 print "--- stderr ---" |
157 print failed.output.stderr.strip() | 160 print failed.output.stderr.strip() |
158 if failed.output.stdout: | 161 if failed.output.stdout: |
159 print "--- stdout ---" | 162 print "--- stdout ---" |
160 print failed.output.stdout.strip() | 163 print failed.output.stdout.strip() |
161 print "Command: %s" % EscapeCommand(failed.command) | 164 print "Command: %s" % EscapeCommand(failed.command) |
| 165 if failed.HasCrashed(): |
| 166 print "--- CRASHED ---" |
162 if len(self.failed) == 0: | 167 if len(self.failed) == 0: |
163 print "===" | 168 print "===" |
164 print "=== All tests succeeded" | 169 print "=== All tests succeeded" |
165 print "===" | 170 print "===" |
166 else: | 171 else: |
167 print | 172 print |
168 print "===" | 173 print "===" |
169 print "=== %i tests failed" % len(self.failed) | 174 print "=== %i tests failed" % len(self.failed) |
| 175 if self.crashed > 0: |
| 176 print "=== %i tests CRASHED" % self.crashed |
170 print "===" | 177 print "===" |
171 | 178 |
172 | 179 |
173 class VerboseProgressIndicator(SimpleProgressIndicator): | 180 class VerboseProgressIndicator(SimpleProgressIndicator): |
174 | 181 |
175 def AboutToRun(self, case): | 182 def AboutToRun(self, case): |
176 print 'Starting %s...' % case.GetLabel() | 183 print 'Starting %s...' % case.GetLabel() |
177 sys.stdout.flush() | 184 sys.stdout.flush() |
178 | 185 |
179 def HasRun(self, output): | 186 def HasRun(self, output): |
180 if output.UnexpectedOutput(): | 187 if output.UnexpectedOutput(): |
181 outcome = 'FAIL' | 188 if output.HasCrashed(): |
| 189 outcome = 'CRASH' |
| 190 else: |
| 191 outcome = 'FAIL' |
182 else: | 192 else: |
183 outcome = 'pass' | 193 outcome = 'pass' |
184 print 'Done running %s: %s' % (output.test.GetLabel(), outcome) | 194 print 'Done running %s: %s' % (output.test.GetLabel(), outcome) |
185 | 195 |
186 | 196 |
187 class DotsProgressIndicator(SimpleProgressIndicator): | 197 class DotsProgressIndicator(SimpleProgressIndicator): |
188 | 198 |
189 def AboutToRun(self, case): | 199 def AboutToRun(self, case): |
190 pass | 200 pass |
191 | 201 |
192 def HasRun(self, output): | 202 def HasRun(self, output): |
193 total = self.succeeded + len(self.failed) | 203 total = self.succeeded + len(self.failed) |
194 if (total > 1) and (total % 50 == 1): | 204 if (total > 1) and (total % 50 == 1): |
195 sys.stdout.write('\n') | 205 sys.stdout.write('\n') |
196 if output.UnexpectedOutput(): | 206 if output.UnexpectedOutput(): |
197 sys.stdout.write('F') | 207 if output.HasCrashed(): |
198 sys.stdout.flush() | 208 sys.stdout.write('C') |
| 209 sys.stdout.flush() |
| 210 else: |
| 211 sys.stdout.write('F') |
| 212 sys.stdout.flush() |
199 else: | 213 else: |
200 sys.stdout.write('.') | 214 sys.stdout.write('.') |
201 sys.stdout.flush() | 215 sys.stdout.flush() |
202 | 216 |
203 | 217 |
204 class CompactProgressIndicator(ProgressIndicator): | 218 class CompactProgressIndicator(ProgressIndicator): |
205 | 219 |
206 def __init__(self, cases, templates): | 220 def __init__(self, cases, templates): |
207 super(CompactProgressIndicator, self).__init__(cases) | 221 super(CompactProgressIndicator, self).__init__(cases) |
208 self.templates = templates | 222 self.templates = templates |
(...skipping 13 matching lines...) Expand all Loading... |
222 if output.UnexpectedOutput(): | 236 if output.UnexpectedOutput(): |
223 self.ClearLine(self.last_status_length) | 237 self.ClearLine(self.last_status_length) |
224 self.PrintFailureHeader(output.test) | 238 self.PrintFailureHeader(output.test) |
225 stdout = output.output.stdout.strip() | 239 stdout = output.output.stdout.strip() |
226 if len(stdout): | 240 if len(stdout): |
227 print self.templates['stdout'] % stdout | 241 print self.templates['stdout'] % stdout |
228 stderr = output.output.stderr.strip() | 242 stderr = output.output.stderr.strip() |
229 if len(stderr): | 243 if len(stderr): |
230 print self.templates['stderr'] % stderr | 244 print self.templates['stderr'] % stderr |
231 print "Command: %s" % EscapeCommand(output.command) | 245 print "Command: %s" % EscapeCommand(output.command) |
| 246 if output.HasCrashed(): |
| 247 print "--- CRASHED ---" |
232 | 248 |
233 def Truncate(self, str, length): | 249 def Truncate(self, str, length): |
234 if length and (len(str) > (length - 3)): | 250 if length and (len(str) > (length - 3)): |
235 return str[:(length-3)] + "..." | 251 return str[:(length-3)] + "..." |
236 else: | 252 else: |
237 return str | 253 return str |
238 | 254 |
239 def PrintProgress(self, name): | 255 def PrintProgress(self, name): |
240 self.ClearLine(self.last_status_length) | 256 self.ClearLine(self.last_status_length) |
241 elapsed = time.time() - self.start_time | 257 elapsed = time.time() - self.start_time |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 | 353 |
338 | 354 |
339 class TestOutput(object): | 355 class TestOutput(object): |
340 | 356 |
341 def __init__(self, test, command, output): | 357 def __init__(self, test, command, output): |
342 self.test = test | 358 self.test = test |
343 self.command = command | 359 self.command = command |
344 self.output = output | 360 self.output = output |
345 | 361 |
346 def UnexpectedOutput(self): | 362 def UnexpectedOutput(self): |
347 if self.HasFailed(): | 363 if self.HasCrashed(): |
| 364 outcome = CRASH |
| 365 elif self.HasFailed(): |
348 outcome = FAIL | 366 outcome = FAIL |
349 else: | 367 else: |
350 outcome = PASS | 368 outcome = PASS |
351 return not outcome in self.test.outcomes | 369 return not outcome in self.test.outcomes |
352 | 370 |
| 371 def HasCrashed(self): |
| 372 if platform.system() == 'Windows': |
| 373 return 0x80000000 & self.output.exit_code and not (0x3FFFFF00 & self.outpu
t.exit_code) |
| 374 else: |
| 375 return False |
| 376 |
353 def HasFailed(self): | 377 def HasFailed(self): |
354 execution_failed = self.test.DidFail(self.output) | 378 execution_failed = self.test.DidFail(self.output) |
355 if self.test.IsNegative(): | 379 if self.test.IsNegative(): |
356 return not execution_failed | 380 return not execution_failed |
357 else: | 381 else: |
358 return execution_failed | 382 return execution_failed |
359 | 383 |
360 | 384 |
361 def KillProcessWithID(pid): | 385 def KillProcessWithID(pid): |
362 if platform.system() == 'Windows': | 386 if platform.system() == 'Windows': |
363 os.popen('taskkill /T /F /PID %d' % pid) | 387 os.popen('taskkill /T /F /PID %d' % pid) |
364 else: | 388 else: |
365 os.kill(pid, signal.SIGTERM) | 389 os.kill(pid, signal.SIGTERM) |
366 | 390 |
367 | 391 |
368 MAX_SLEEP_TIME = 0.1 | 392 MAX_SLEEP_TIME = 0.1 |
369 INITIAL_SLEEP_TIME = 0.0001 | 393 INITIAL_SLEEP_TIME = 0.0001 |
370 SLEEP_TIME_FACTOR = 1.25 | 394 SLEEP_TIME_FACTOR = 1.25 |
371 | 395 |
| 396 SEM_INVALID_VALUE = -1 |
| 397 SEM_NOGPFAULTERRORBOX = 0x0002 # Microsoft Platform SDK WinBase.h |
372 | 398 |
| 399 def Win32SetErrorMode(mode): |
| 400 prev_error_mode = SEM_INVALID_VALUE |
| 401 try: |
| 402 import ctypes |
| 403 prev_error_mode = ctypes.windll.kernel32.SetErrorMode(mode); |
| 404 except ImportError: |
| 405 pass |
| 406 return prev_error_mode |
| 407 |
373 def RunProcess(context, timeout, args, **rest): | 408 def RunProcess(context, timeout, args, **rest): |
374 if context.verbose: print "#", " ".join(args) | 409 if context.verbose: print "#", " ".join(args) |
375 popen_args = args | 410 popen_args = args |
| 411 prev_error_mode = SEM_INVALID_VALUE; |
376 if platform.system() == 'Windows': | 412 if platform.system() == 'Windows': |
377 popen_args = '"' + subprocess.list2cmdline(args) + '"' | 413 popen_args = '"' + subprocess.list2cmdline(args) + '"' |
| 414 if context.supress_dialogs: |
| 415 # Try to change the error mode to avoid dialogs on fatal errors. |
| 416 Win32SetErrorMode(SEM_NOGPFAULTERRORBOX) |
378 process = subprocess.Popen( | 417 process = subprocess.Popen( |
379 shell = (platform.system() == 'Windows'), | 418 shell = (platform.system() == 'Windows'), |
380 args = popen_args, | 419 args = popen_args, |
381 **rest | 420 **rest |
382 ) | 421 ) |
| 422 if platform.system() == 'Windows' and context.supress_dialogs and prev_error_m
ode != SEM_INVALID_VALUE: |
| 423 Win32SetErrorMode(prev_error_mode) |
383 # Compute the end time - if the process crosses this limit we | 424 # Compute the end time - if the process crosses this limit we |
384 # consider it timed out. | 425 # consider it timed out. |
385 if timeout is None: end_time = None | 426 if timeout is None: end_time = None |
386 else: end_time = time.time() + timeout | 427 else: end_time = time.time() + timeout |
387 timed_out = False | 428 timed_out = False |
388 # Repeatedly check the exit code from the process in a | 429 # Repeatedly check the exit code from the process in a |
389 # loop and keep track of whether or not it times out. | 430 # loop and keep track of whether or not it times out. |
390 exit_code = None | 431 exit_code = None |
391 sleep_time = INITIAL_SLEEP_TIME | 432 sleep_time = INITIAL_SLEEP_TIME |
392 while exit_code is None: | 433 while exit_code is None: |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 def GetTestStatus(self, context, sections, defs): | 577 def GetTestStatus(self, context, sections, defs): |
537 for test in self.tests: | 578 for test in self.tests: |
538 test.GetTestStatus(context, sections, defs) | 579 test.GetTestStatus(context, sections, defs) |
539 | 580 |
540 | 581 |
541 PREFIX = {'debug': '_g', 'release': ''} | 582 PREFIX = {'debug': '_g', 'release': ''} |
542 | 583 |
543 | 584 |
544 class Context(object): | 585 class Context(object): |
545 | 586 |
546 def __init__(self, workspace, buildspace, verbose, vm, timeout, processor): | 587 def __init__(self, workspace, buildspace, verbose, vm, timeout, processor, sup
ress_dialogs): |
547 self.workspace = workspace | 588 self.workspace = workspace |
548 self.buildspace = buildspace | 589 self.buildspace = buildspace |
549 self.verbose = verbose | 590 self.verbose = verbose |
550 self.vm_root = vm | 591 self.vm_root = vm |
551 self.timeout = timeout | 592 self.timeout = timeout |
552 self.processor = processor | 593 self.processor = processor |
| 594 self.supress_dialogs = supress_dialogs |
553 | 595 |
554 def GetVm(self, mode): | 596 def GetVm(self, mode): |
555 name = self.vm_root + PREFIX[mode] | 597 name = self.vm_root + PREFIX[mode] |
556 if platform.system() == 'Windows': | 598 if platform.system() == 'Windows': |
557 return name + '.exe' | 599 return name + '.exe' |
558 else: | 600 else: |
559 return name | 601 return name |
560 | 602 |
561 def RunTestCases(all_cases, progress, tasks): | 603 def RunTestCases(all_cases, progress, tasks): |
562 def DoSkip(case): | 604 def DoSkip(case): |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1023 default='none') | 1065 default='none') |
1024 result.add_option("--special-command", default=None) | 1066 result.add_option("--special-command", default=None) |
1025 result.add_option("--cat", help="Print the source of the tests", | 1067 result.add_option("--cat", help="Print the source of the tests", |
1026 default=False, action="store_true") | 1068 default=False, action="store_true") |
1027 result.add_option("--warn-unused", help="Report unused rules", | 1069 result.add_option("--warn-unused", help="Report unused rules", |
1028 default=False, action="store_true") | 1070 default=False, action="store_true") |
1029 result.add_option("-j", help="The number of parallel tasks to run", | 1071 result.add_option("-j", help="The number of parallel tasks to run", |
1030 default=1, type="int") | 1072 default=1, type="int") |
1031 result.add_option("--time", help="Print timing information after running", | 1073 result.add_option("--time", help="Print timing information after running", |
1032 default=False, action="store_true") | 1074 default=False, action="store_true") |
| 1075 if platform.system() == 'Windows': |
| 1076 result.add_option("--supress-dialogs", help="Supress Windows dialogs for cra
shing tests", |
| 1077 dest="supress_dialogs", default=True, action="store_true") |
| 1078 result.add_option("--no-supress-dialogs", help="Display Windows dialogs for
crashing tests", |
| 1079 dest="supress_dialogs", action="store_false") |
1033 return result | 1080 return result |
1034 | 1081 |
1035 | 1082 |
1036 def ProcessOptions(options): | 1083 def ProcessOptions(options): |
1037 global VERBOSE | 1084 global VERBOSE |
1038 VERBOSE = options.verbose | 1085 VERBOSE = options.verbose |
1039 options.mode = options.mode.split(',') | 1086 options.mode = options.mode.split(',') |
1040 for mode in options.mode: | 1087 for mode in options.mode: |
1041 if not mode in ['debug', 'release']: | 1088 if not mode in ['debug', 'release']: |
1042 print "Unknown mode %s" % mode | 1089 print "Unknown mode %s" % mode |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 paths = [ ] | 1199 paths = [ ] |
1153 for arg in args: | 1200 for arg in args: |
1154 path = SplitPath(arg) | 1201 path = SplitPath(arg) |
1155 paths.append(path) | 1202 paths.append(path) |
1156 | 1203 |
1157 # First build the required targets | 1204 # First build the required targets |
1158 buildspace = abspath('.') | 1205 buildspace = abspath('.') |
1159 context = Context(workspace, buildspace, VERBOSE, | 1206 context = Context(workspace, buildspace, VERBOSE, |
1160 join(buildspace, 'shell'), | 1207 join(buildspace, 'shell'), |
1161 options.timeout, | 1208 options.timeout, |
1162 GetSpecialCommandProcessor(options.special_command)) | 1209 GetSpecialCommandProcessor(options.special_command), |
| 1210 options.supress_dialogs) |
1163 if options.j != 1: | 1211 if options.j != 1: |
1164 options.scons_flags += ['-j', str(options.j)] | 1212 options.scons_flags += ['-j', str(options.j)] |
1165 if not options.no_build: | 1213 if not options.no_build: |
1166 reqs = [ ] | 1214 reqs = [ ] |
1167 for path in paths: | 1215 for path in paths: |
1168 reqs += root.GetBuildRequirements(path, context) | 1216 reqs += root.GetBuildRequirements(path, context) |
1169 reqs = list(set(reqs)) | 1217 reqs = list(set(reqs)) |
1170 if len(reqs) > 0: | 1218 if len(reqs) > 0: |
1171 if not BuildRequirements(context, reqs, options.mode, options.scons_flags)
: | 1219 if not BuildRequirements(context, reqs, options.mode, options.scons_flags)
: |
1172 return 1 | 1220 return 1 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1246 for entry in timed_tests[:20]: | 1294 for entry in timed_tests[:20]: |
1247 t = FormatTime(entry.duration) | 1295 t = FormatTime(entry.duration) |
1248 sys.stderr.write("%4i (%s) %s\n" % (index, t, entry.GetLabel())) | 1296 sys.stderr.write("%4i (%s) %s\n" % (index, t, entry.GetLabel())) |
1249 index += 1 | 1297 index += 1 |
1250 | 1298 |
1251 return result | 1299 return result |
1252 | 1300 |
1253 | 1301 |
1254 if __name__ == '__main__': | 1302 if __name__ == '__main__': |
1255 sys.exit(Main()) | 1303 sys.exit(Main()) |
OLD | NEW |