| 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 |