| 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 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 def __init__(self, exit_code, timed_out, stdout, stderr): | 324 def __init__(self, exit_code, timed_out, stdout, stderr): |
| 325 self.exit_code = exit_code | 325 self.exit_code = exit_code |
| 326 self.timed_out = timed_out | 326 self.timed_out = timed_out |
| 327 self.stdout = stdout | 327 self.stdout = stdout |
| 328 self.stderr = stderr | 328 self.stderr = stderr |
| 329 self.failed = None | 329 self.failed = None |
| 330 | 330 |
| 331 | 331 |
| 332 class TestCase(object): | 332 class TestCase(object): |
| 333 | 333 |
| 334 def __init__(self, context, path): | 334 def __init__(self, context, path, mode): |
| 335 self.path = path | 335 self.path = path |
| 336 self.context = context | 336 self.context = context |
| 337 self.duration = None | 337 self.duration = None |
| 338 self.mode = mode |
| 338 | 339 |
| 339 def IsNegative(self): | 340 def IsNegative(self): |
| 340 return False | 341 return False |
| 341 | 342 |
| 342 def CompareTime(self, other): | 343 def CompareTime(self, other): |
| 343 return cmp(other.duration, self.duration) | 344 return cmp(other.duration, self.duration) |
| 344 | 345 |
| 345 def DidFail(self, output): | 346 def DidFail(self, output): |
| 346 if output.failed is None: | 347 if output.failed is None: |
| 347 output.failed = self.IsFailureOutput(output) | 348 output.failed = self.IsFailureOutput(output) |
| 348 return output.failed | 349 return output.failed |
| 349 | 350 |
| 350 def IsFailureOutput(self, output): | 351 def IsFailureOutput(self, output): |
| 351 return output.exit_code != 0 | 352 return output.exit_code != 0 |
| 352 | 353 |
| 353 def GetSource(self): | 354 def GetSource(self): |
| 354 return "(no source available)" | 355 return "(no source available)" |
| 355 | 356 |
| 356 def RunCommand(self, command): | 357 def RunCommand(self, command): |
| 357 full_command = self.context.processor(command) | 358 full_command = self.context.processor(command) |
| 358 output = Execute(full_command, self.context, self.context.timeout) | 359 output = Execute(full_command, |
| 360 self.context, |
| 361 self.context.GetTimeout(self.mode)) |
| 359 self.Cleanup() | 362 self.Cleanup() |
| 360 return TestOutput(self, full_command, output) | 363 return TestOutput(self, |
| 364 full_command, |
| 365 output, |
| 366 self.context.store_unexpected_output) |
| 361 | 367 |
| 362 def BeforeRun(self): | 368 def BeforeRun(self): |
| 363 pass | 369 pass |
| 364 | 370 |
| 365 def AfterRun(self): | 371 def AfterRun(self, result): |
| 366 pass | 372 pass |
| 367 | 373 |
| 368 def Run(self): | 374 def Run(self): |
| 369 self.BeforeRun() | 375 self.BeforeRun() |
| 370 try: | 376 try: |
| 371 result = self.RunCommand(self.GetCommand()) | 377 result = self.RunCommand(self.GetCommand()) |
| 372 finally: | 378 finally: |
| 373 self.AfterRun() | 379 self.AfterRun(result) |
| 374 return result | 380 return result |
| 375 | 381 |
| 376 def Cleanup(self): | 382 def Cleanup(self): |
| 377 return | 383 return |
| 378 | 384 |
| 379 | 385 |
| 380 class TestOutput(object): | 386 class TestOutput(object): |
| 381 | 387 |
| 382 def __init__(self, test, command, output): | 388 def __init__(self, test, command, output, store_unexpected_output): |
| 383 self.test = test | 389 self.test = test |
| 384 self.command = command | 390 self.command = command |
| 385 self.output = output | 391 self.output = output |
| 392 self.store_unexpected_output = store_unexpected_output |
| 386 | 393 |
| 387 def UnexpectedOutput(self): | 394 def UnexpectedOutput(self): |
| 388 if self.HasCrashed(): | 395 if self.HasCrashed(): |
| 389 outcome = CRASH | 396 outcome = CRASH |
| 390 elif self.HasTimedOut(): | 397 elif self.HasTimedOut(): |
| 391 outcome = TIMEOUT | 398 outcome = TIMEOUT |
| 392 elif self.HasFailed(): | 399 elif self.HasFailed(): |
| 393 outcome = FAIL | 400 outcome = FAIL |
| 394 else: | 401 else: |
| 395 outcome = PASS | 402 outcome = PASS |
| 396 return not outcome in self.test.outcomes | 403 return not outcome in self.test.outcomes |
| 397 | 404 |
| 405 def HasPreciousOutput(self): |
| 406 return self.UnexpectedOutput() and self.store_unexpected_output |
| 407 |
| 398 def HasCrashed(self): | 408 def HasCrashed(self): |
| 399 if utils.IsWindows(): | 409 if utils.IsWindows(): |
| 400 return 0x80000000 & self.output.exit_code and not (0x3FFFFF00 & self.outpu
t.exit_code) | 410 return 0x80000000 & self.output.exit_code and not (0x3FFFFF00 & self.outpu
t.exit_code) |
| 401 else: | 411 else: |
| 402 # Timed out tests will have exit_code -signal.SIGTERM. | 412 # Timed out tests will have exit_code -signal.SIGTERM. |
| 403 if self.output.timed_out: | 413 if self.output.timed_out: |
| 404 return False | 414 return False |
| 405 return self.output.exit_code < 0 and \ | 415 return self.output.exit_code < 0 and \ |
| 406 self.output.exit_code != -signal.SIGABRT | 416 self.output.exit_code != -signal.SIGABRT |
| 407 | 417 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 | 560 |
| 551 class TestSuite(object): | 561 class TestSuite(object): |
| 552 | 562 |
| 553 def __init__(self, name): | 563 def __init__(self, name): |
| 554 self.name = name | 564 self.name = name |
| 555 | 565 |
| 556 def GetName(self): | 566 def GetName(self): |
| 557 return self.name | 567 return self.name |
| 558 | 568 |
| 559 | 569 |
| 570 # Use this to run several variants of the tests, e.g.: |
| 571 # VARIANT_FLAGS = [[], ['--always_compact', '--noflush_code']] |
| 572 VARIANT_FLAGS = [[]] |
| 573 |
| 574 |
| 560 class TestRepository(TestSuite): | 575 class TestRepository(TestSuite): |
| 561 | 576 |
| 562 def __init__(self, path): | 577 def __init__(self, path): |
| 563 normalized_path = abspath(path) | 578 normalized_path = abspath(path) |
| 564 super(TestRepository, self).__init__(basename(normalized_path)) | 579 super(TestRepository, self).__init__(basename(normalized_path)) |
| 565 self.path = normalized_path | 580 self.path = normalized_path |
| 566 self.is_loaded = False | 581 self.is_loaded = False |
| 567 self.config = None | 582 self.config = None |
| 568 | 583 |
| 569 def GetConfiguration(self, context): | 584 def GetConfiguration(self, context): |
| 570 if self.is_loaded: | 585 if self.is_loaded: |
| 571 return self.config | 586 return self.config |
| 572 self.is_loaded = True | 587 self.is_loaded = True |
| 573 file = None | 588 file = None |
| 574 try: | 589 try: |
| 575 (file, pathname, description) = imp.find_module('testcfg', [ self.path ]) | 590 (file, pathname, description) = imp.find_module('testcfg', [ self.path ]) |
| 576 module = imp.load_module('testcfg', file, pathname, description) | 591 module = imp.load_module('testcfg', file, pathname, description) |
| 577 self.config = module.GetConfiguration(context, self.path) | 592 self.config = module.GetConfiguration(context, self.path) |
| 578 finally: | 593 finally: |
| 579 if file: | 594 if file: |
| 580 file.close() | 595 file.close() |
| 581 return self.config | 596 return self.config |
| 582 | 597 |
| 583 def GetBuildRequirements(self, path, context): | 598 def GetBuildRequirements(self, path, context): |
| 584 return self.GetConfiguration(context).GetBuildRequirements() | 599 return self.GetConfiguration(context).GetBuildRequirements() |
| 585 | 600 |
| 586 def ListTests(self, current_path, path, context, mode): | 601 def AddTestsToList(self, result, current_path, path, context, mode): |
| 587 return self.GetConfiguration(context).ListTests(current_path, path, mode) | 602 for v in VARIANT_FLAGS: |
| 603 tests = self.GetConfiguration(context).ListTests(current_path, path, mode) |
| 604 for t in tests: t.variant_flags = v |
| 605 result += tests |
| 606 |
| 588 | 607 |
| 589 def GetTestStatus(self, context, sections, defs): | 608 def GetTestStatus(self, context, sections, defs): |
| 590 self.GetConfiguration(context).GetTestStatus(sections, defs) | 609 self.GetConfiguration(context).GetTestStatus(sections, defs) |
| 591 | 610 |
| 592 | 611 |
| 593 class LiteralTestSuite(TestSuite): | 612 class LiteralTestSuite(TestSuite): |
| 594 | 613 |
| 595 def __init__(self, tests): | 614 def __init__(self, tests): |
| 596 super(LiteralTestSuite, self).__init__('root') | 615 super(LiteralTestSuite, self).__init__('root') |
| 597 self.tests = tests | 616 self.tests = tests |
| 598 | 617 |
| 599 def GetBuildRequirements(self, path, context): | 618 def GetBuildRequirements(self, path, context): |
| 600 (name, rest) = CarCdr(path) | 619 (name, rest) = CarCdr(path) |
| 601 result = [ ] | 620 result = [ ] |
| 602 for test in self.tests: | 621 for test in self.tests: |
| 603 if not name or name.match(test.GetName()): | 622 if not name or name.match(test.GetName()): |
| 604 result += test.GetBuildRequirements(rest, context) | 623 result += test.GetBuildRequirements(rest, context) |
| 605 return result | 624 return result |
| 606 | 625 |
| 607 def ListTests(self, current_path, path, context, mode): | 626 def ListTests(self, current_path, path, context, mode): |
| 608 (name, rest) = CarCdr(path) | 627 (name, rest) = CarCdr(path) |
| 609 result = [ ] | 628 result = [ ] |
| 610 for test in self.tests: | 629 for test in self.tests: |
| 611 test_name = test.GetName() | 630 test_name = test.GetName() |
| 612 if not name or name.match(test_name): | 631 if not name or name.match(test_name): |
| 613 full_path = current_path + [test_name] | 632 full_path = current_path + [test_name] |
| 614 result += test.ListTests(full_path, path, context, mode) | 633 test.AddTestsToList(result, full_path, path, context, mode) |
| 615 return result | 634 return result |
| 616 | 635 |
| 617 def GetTestStatus(self, context, sections, defs): | 636 def GetTestStatus(self, context, sections, defs): |
| 618 for test in self.tests: | 637 for test in self.tests: |
| 619 test.GetTestStatus(context, sections, defs) | 638 test.GetTestStatus(context, sections, defs) |
| 620 | 639 |
| 621 | 640 |
| 622 SUFFIX = {'debug': '_g', 'release': ''} | 641 SUFFIX = { |
| 642 'debug' : '_g', |
| 643 'release' : '' } |
| 644 FLAGS = { |
| 645 'debug' : ['--enable-slow-asserts', '--debug-code', '--verify-heap'], |
| 646 'release' : []} |
| 647 TIMEOUT_SCALEFACTOR = { |
| 648 'debug' : 4, |
| 649 'release' : 1 } |
| 623 | 650 |
| 624 | 651 |
| 625 class Context(object): | 652 class Context(object): |
| 626 | 653 |
| 627 def __init__(self, workspace, buildspace, verbose, vm, timeout, processor, sup
press_dialogs): | 654 def __init__(self, workspace, buildspace, verbose, vm, timeout, processor, sup
press_dialogs, store_unexpected_output): |
| 628 self.workspace = workspace | 655 self.workspace = workspace |
| 629 self.buildspace = buildspace | 656 self.buildspace = buildspace |
| 630 self.verbose = verbose | 657 self.verbose = verbose |
| 631 self.vm_root = vm | 658 self.vm_root = vm |
| 632 self.timeout = timeout | 659 self.timeout = timeout |
| 633 self.processor = processor | 660 self.processor = processor |
| 634 self.suppress_dialogs = suppress_dialogs | 661 self.suppress_dialogs = suppress_dialogs |
| 662 self.store_unexpected_output = store_unexpected_output |
| 635 | 663 |
| 636 def GetVm(self, mode): | 664 def GetVm(self, mode): |
| 637 name = self.vm_root + SUFFIX[mode] | 665 name = self.vm_root + SUFFIX[mode] |
| 638 if utils.IsWindows() and not name.endswith('.exe'): | 666 if utils.IsWindows() and not name.endswith('.exe'): |
| 639 name = name + '.exe' | 667 name = name + '.exe' |
| 640 return name | 668 return name |
| 641 | 669 |
| 670 def GetVmCommand(self, testcase, mode): |
| 671 return [self.GetVm(mode)] + self.GetVmFlags(testcase, mode) |
| 672 |
| 673 def GetVmFlags(self, testcase, mode): |
| 674 return testcase.variant_flags + FLAGS[mode] |
| 675 |
| 676 def GetTimeout(self, mode): |
| 677 return self.timeout * TIMEOUT_SCALEFACTOR[mode] |
| 678 |
| 642 def RunTestCases(cases_to_run, progress, tasks): | 679 def RunTestCases(cases_to_run, progress, tasks): |
| 643 progress = PROGRESS_INDICATORS[progress](cases_to_run) | 680 progress = PROGRESS_INDICATORS[progress](cases_to_run) |
| 644 return progress.Run(tasks) | 681 return progress.Run(tasks) |
| 645 | 682 |
| 646 | 683 |
| 647 def BuildRequirements(context, requirements, mode, scons_flags): | 684 def BuildRequirements(context, requirements, mode, scons_flags): |
| 648 command_line = (['scons', '-Y', context.workspace, 'mode=' + ",".join(mode)] | 685 command_line = (['scons', '-Y', context.workspace, 'mode=' + ",".join(mode)] |
| 649 + requirements | 686 + requirements |
| 650 + scons_flags) | 687 + scons_flags) |
| 651 output = ExecuteNoCapture(command_line, context) | 688 output = ExecuteNoCapture(command_line, context) |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 result.add_option("--warn-unused", help="Report unused rules", | 1151 result.add_option("--warn-unused", help="Report unused rules", |
| 1115 default=False, action="store_true") | 1152 default=False, action="store_true") |
| 1116 result.add_option("-j", help="The number of parallel tasks to run", | 1153 result.add_option("-j", help="The number of parallel tasks to run", |
| 1117 default=1, type="int") | 1154 default=1, type="int") |
| 1118 result.add_option("--time", help="Print timing information after running", | 1155 result.add_option("--time", help="Print timing information after running", |
| 1119 default=False, action="store_true") | 1156 default=False, action="store_true") |
| 1120 result.add_option("--suppress-dialogs", help="Suppress Windows dialogs for cra
shing tests", | 1157 result.add_option("--suppress-dialogs", help="Suppress Windows dialogs for cra
shing tests", |
| 1121 dest="suppress_dialogs", default=True, action="store_true") | 1158 dest="suppress_dialogs", default=True, action="store_true") |
| 1122 result.add_option("--no-suppress-dialogs", help="Display Windows dialogs for c
rashing tests", | 1159 result.add_option("--no-suppress-dialogs", help="Display Windows dialogs for c
rashing tests", |
| 1123 dest="suppress_dialogs", action="store_false") | 1160 dest="suppress_dialogs", action="store_false") |
| 1124 result.add_option("--shell", help="Path to V8 shell", default="shell"); | 1161 result.add_option("--shell", help="Path to V8 shell", default="shell") |
| 1162 result.add_option("--store-unexpected-output", |
| 1163 help="Store the temporary JS files from tests that fails", |
| 1164 dest="store_unexpected_output", default=True, action="store_true") |
| 1165 result.add_option("--no-store-unexpected-output", |
| 1166 help="Deletes the temporary JS files from tests that fails", |
| 1167 dest="store_unexpected_output", action="store_false") |
| 1125 return result | 1168 return result |
| 1126 | 1169 |
| 1127 | 1170 |
| 1128 def ProcessOptions(options): | 1171 def ProcessOptions(options): |
| 1129 global VERBOSE | 1172 global VERBOSE |
| 1130 VERBOSE = options.verbose | 1173 VERBOSE = options.verbose |
| 1131 options.mode = options.mode.split(',') | 1174 options.mode = options.mode.split(',') |
| 1132 for mode in options.mode: | 1175 for mode in options.mode: |
| 1133 if not mode in ['debug', 'release']: | 1176 if not mode in ['debug', 'release']: |
| 1134 print "Unknown mode %s" % mode | 1177 print "Unknown mode %s" % mode |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1251 paths.append(path) | 1294 paths.append(path) |
| 1252 | 1295 |
| 1253 # Check for --valgrind option. If enabled, we overwrite the special | 1296 # Check for --valgrind option. If enabled, we overwrite the special |
| 1254 # command flag with a command that uses the run-valgrind.py script. | 1297 # command flag with a command that uses the run-valgrind.py script. |
| 1255 if options.valgrind: | 1298 if options.valgrind: |
| 1256 run_valgrind = join(workspace, "tools", "run-valgrind.py") | 1299 run_valgrind = join(workspace, "tools", "run-valgrind.py") |
| 1257 options.special_command = "python -u " + run_valgrind + " @" | 1300 options.special_command = "python -u " + run_valgrind + " @" |
| 1258 | 1301 |
| 1259 shell = abspath(options.shell) | 1302 shell = abspath(options.shell) |
| 1260 buildspace = dirname(shell) | 1303 buildspace = dirname(shell) |
| 1304 |
| 1261 context = Context(workspace, buildspace, VERBOSE, | 1305 context = Context(workspace, buildspace, VERBOSE, |
| 1262 shell, | 1306 shell, |
| 1263 options.timeout, | 1307 options.timeout, |
| 1264 GetSpecialCommandProcessor(options.special_command), | 1308 GetSpecialCommandProcessor(options.special_command), |
| 1265 options.suppress_dialogs) | 1309 options.suppress_dialogs, |
| 1310 options.store_unexpected_output) |
| 1266 # First build the required targets | 1311 # First build the required targets |
| 1267 if not options.no_build: | 1312 if not options.no_build: |
| 1268 reqs = [ ] | 1313 reqs = [ ] |
| 1269 for path in paths: | 1314 for path in paths: |
| 1270 reqs += root.GetBuildRequirements(path, context) | 1315 reqs += root.GetBuildRequirements(path, context) |
| 1271 reqs = list(set(reqs)) | 1316 reqs = list(set(reqs)) |
| 1272 if len(reqs) > 0: | 1317 if len(reqs) > 0: |
| 1273 if options.j != 1: | 1318 if options.j != 1: |
| 1274 options.scons_flags += ['-j', str(options.j)] | 1319 options.scons_flags += ['-j', str(options.j)] |
| 1275 if not BuildRequirements(context, reqs, options.mode, options.scons_flags)
: | 1320 if not BuildRequirements(context, reqs, options.mode, options.scons_flags)
: |
| 1276 return 1 | 1321 return 1 |
| 1277 | 1322 |
| 1278 # Just return if we are only building the targets for running the tests. | 1323 # Just return if we are only building the targets for running the tests. |
| 1279 if options.build_only: | 1324 if options.build_only: |
| 1280 return 0 | 1325 return 0 |
| 1281 | 1326 |
| 1282 # Get status for tests | 1327 # Get status for tests |
| 1283 sections = [ ] | 1328 sections = [ ] |
| 1284 defs = { } | 1329 defs = { } |
| 1285 root.GetTestStatus(context, sections, defs) | 1330 root.GetTestStatus(context, sections, defs) |
| 1286 config = Configuration(sections, defs) | 1331 config = Configuration(sections, defs) |
| 1287 | 1332 |
| 1288 # List the tests | 1333 # List the tests |
| 1289 all_cases = [ ] | 1334 all_cases = [ ] |
| 1290 all_unused = [ ] | 1335 all_unused = [ ] |
| 1291 unclassified_tests = [ ] | 1336 unclassified_tests = [ ] |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 for entry in timed_tests[:20]: | 1406 for entry in timed_tests[:20]: |
| 1362 t = FormatTime(entry.duration) | 1407 t = FormatTime(entry.duration) |
| 1363 sys.stderr.write("%4i (%s) %s\n" % (index, t, entry.GetLabel())) | 1408 sys.stderr.write("%4i (%s) %s\n" % (index, t, entry.GetLabel())) |
| 1364 index += 1 | 1409 index += 1 |
| 1365 | 1410 |
| 1366 return result | 1411 return result |
| 1367 | 1412 |
| 1368 | 1413 |
| 1369 if __name__ == '__main__': | 1414 if __name__ == '__main__': |
| 1370 sys.exit(Main()) | 1415 sys.exit(Main()) |
| OLD | NEW |