Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # | 2 # |
| 3 # Copyright 2012 the V8 project authors. All rights reserved. | 3 # Copyright 2012 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 25 matching lines...) Expand all Loading... | |
| 36 import re | 36 import re |
| 37 import signal | 37 import signal |
| 38 import subprocess | 38 import subprocess |
| 39 import sys | 39 import sys |
| 40 import tempfile | 40 import tempfile |
| 41 import time | 41 import time |
| 42 import threading | 42 import threading |
| 43 import utils | 43 import utils |
| 44 from Queue import Queue, Empty | 44 from Queue import Queue, Empty |
| 45 | 45 |
| 46 from unittest_output import UnitTestOutput | |
| 46 | 47 |
| 47 VERBOSE = False | 48 VERBOSE = False |
| 49 XMLOUT = None | |
|
Jakob Kummerow
2012/09/28 17:38:52
No global variables. Please.
| |
| 50 XMLTESTSUITE = None | |
| 48 | 51 |
| 49 | 52 |
| 50 # --------------------------------------------- | 53 # --------------------------------------------- |
| 51 # --- P r o g r e s s I n d i c a t o r s --- | 54 # --- P r o g r e s s I n d i c a t o r s --- |
| 52 # --------------------------------------------- | 55 # --------------------------------------------- |
| 53 | 56 |
| 54 | 57 |
| 55 class ProgressIndicator(object): | 58 class ProgressIndicator(object): |
| 56 | 59 |
| 57 def __init__(self, cases): | 60 def __init__(self, cases): |
| 58 self.cases = cases | 61 self.cases = cases |
| 59 self.queue = Queue(len(cases)) | 62 self.queue = Queue(len(cases)) |
| 60 for case in cases: | 63 for case in cases: |
| 61 self.queue.put_nowait(case) | 64 self.queue.put_nowait(case) |
| 62 self.succeeded = 0 | 65 self.succeeded = 0 |
| 63 self.remaining = len(cases) | 66 self.remaining = len(cases) |
| 64 self.total = len(cases) | 67 self.total = len(cases) |
| 65 self.failed = [ ] | 68 self.failed = [ ] |
| 66 self.crashed = 0 | 69 self.crashed = 0 |
| 67 self.terminate = False | 70 self.terminate = False |
| 68 self.lock = threading.Lock() | 71 self.lock = threading.Lock() |
| 72 if XMLOUT: | |
|
Jakob Kummerow
2012/09/28 17:38:52
This looks weird. The UnitTestProgressIndicator is
| |
| 73 self.xmlOutputter = UnitTestProgressIndicator() | |
| 69 | 74 |
| 70 def PrintFailureHeader(self, test): | 75 def PrintFailureHeader(self, test): |
| 71 if test.IsNegative(): | 76 if test.IsNegative(): |
| 72 negative_marker = '[negative] ' | 77 negative_marker = '[negative] ' |
| 73 else: | 78 else: |
| 74 negative_marker = '' | 79 negative_marker = '' |
| 75 print "=== %(label)s %(negative)s===" % { | 80 print "=== %(label)s %(negative)s===" % { |
| 76 'label': test.GetLabel(), | 81 'label': test.GetLabel(), |
| 77 'negative': negative_marker | 82 'negative': negative_marker |
| 78 } | 83 } |
| 79 print "Path: %s" % "/".join(test.path) | 84 print "Path: %s" % "/".join(test.path) |
| 80 | 85 |
| 81 def Run(self, tasks): | 86 def Run(self, tasks): |
| 82 self.Starting() | 87 self.Starting() |
| 88 if XMLOUT: | |
| 89 self.xmlOutputter.Starting() | |
| 83 threads = [] | 90 threads = [] |
| 84 # Spawn N-1 threads and then use this thread as the last one. | 91 # Spawn N-1 threads and then use this thread as the last one. |
| 85 # That way -j1 avoids threading altogether which is a nice fallback | 92 # That way -j1 avoids threading altogether which is a nice fallback |
| 86 # in case of threading problems. | 93 # in case of threading problems. |
| 87 for i in xrange(tasks - 1): | 94 for i in xrange(tasks - 1): |
| 88 thread = threading.Thread(target=self.RunSingle, args=[]) | 95 thread = threading.Thread(target=self.RunSingle, args=[]) |
| 89 threads.append(thread) | 96 threads.append(thread) |
| 90 thread.start() | 97 thread.start() |
| 91 try: | 98 try: |
| 92 self.RunSingle() | 99 self.RunSingle() |
| 93 # Wait for the remaining threads | 100 # Wait for the remaining threads |
| 94 for thread in threads: | 101 for thread in threads: |
| 95 # Use a timeout so that signals (ctrl-c) will be processed. | 102 # Use a timeout so that signals (ctrl-c) will be processed. |
| 96 thread.join(timeout=10000000) | 103 thread.join(timeout=10000000) |
| 97 except Exception, e: | 104 except Exception, e: |
| 98 # If there's an exception we schedule an interruption for any | 105 # If there's an exception we schedule an interruption for any |
| 99 # remaining threads. | 106 # remaining threads. |
| 100 self.terminate = True | 107 self.terminate = True |
| 101 # ...and then reraise the exception to bail out | 108 # ...and then reraise the exception to bail out |
| 102 raise | 109 raise |
| 103 self.Done() | 110 self.Done() |
| 111 if XMLOUT: | |
| 112 self.xmlOutputter.Done() | |
| 104 return not self.failed | 113 return not self.failed |
| 105 | 114 |
| 106 def RunSingle(self): | 115 def RunSingle(self): |
| 107 while not self.terminate: | 116 while not self.terminate: |
| 108 try: | 117 try: |
| 109 test = self.queue.get_nowait() | 118 test = self.queue.get_nowait() |
| 110 except Empty: | 119 except Empty: |
| 111 return | 120 return |
| 112 case = test.case | 121 case = test.case |
| 113 self.lock.acquire() | 122 self.lock.acquire() |
| 114 self.AboutToRun(case) | 123 self.AboutToRun(case) |
| 124 if XMLOUT: | |
| 125 self.xmlOutputter.AboutToRun(case) | |
| 115 self.lock.release() | 126 self.lock.release() |
| 116 try: | 127 try: |
| 117 start = time.time() | 128 start = time.time() |
| 118 output = case.Run() | 129 output = case.Run() |
| 119 case.duration = (time.time() - start) | 130 case.duration = (time.time() - start) |
| 120 except BreakNowException: | 131 except BreakNowException: |
| 121 self.terminate = True | 132 self.terminate = True |
| 122 except IOError, e: | 133 except IOError, e: |
| 123 assert self.terminate | 134 assert self.terminate |
| 124 return | 135 return |
| 125 if self.terminate: | 136 if self.terminate: |
| 126 return | 137 return |
| 127 self.lock.acquire() | 138 self.lock.acquire() |
| 128 if output.UnexpectedOutput(): | 139 if output.UnexpectedOutput(): |
| 129 self.failed.append(output) | 140 self.failed.append(output) |
| 130 if output.HasCrashed(): | 141 if output.HasCrashed(): |
| 131 self.crashed += 1 | 142 self.crashed += 1 |
| 132 else: | 143 else: |
| 133 self.succeeded += 1 | 144 self.succeeded += 1 |
| 134 self.remaining -= 1 | 145 self.remaining -= 1 |
| 135 self.HasRun(output) | 146 self.HasRun(output) |
| 147 if XMLOUT: | |
| 148 self.xmlOutputter.HasRun(output) | |
| 136 self.lock.release() | 149 self.lock.release() |
| 137 | 150 |
| 138 | 151 |
| 139 def EscapeCommand(command): | 152 def EscapeCommand(command): |
| 140 parts = [] | 153 parts = [] |
| 141 for part in command: | 154 for part in command: |
| 142 if ' ' in part: | 155 if ' ' in part: |
| 143 # Escape spaces and double quotes. We may need to escape more characters | 156 # Escape spaces and double quotes. We may need to escape more characters |
| 144 # for this to work properly. | 157 # for this to work properly. |
| 145 parts.append('"%s"' % part.replace('"', '\\"')) | 158 parts.append('"%s"' % part.replace('"', '\\"')) |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 def __init__(self, cases): | 310 def __init__(self, cases): |
| 298 templates = { | 311 templates = { |
| 299 'status_line': "[%(mins)02i:%(secs)02i|%%%(remaining) 4d|+%(passed) 4d|-%( failed) 4d]: %(test)s", | 312 'status_line': "[%(mins)02i:%(secs)02i|%%%(remaining) 4d|+%(passed) 4d|-%( failed) 4d]: %(test)s", |
| 300 'stdout': '%s', | 313 'stdout': '%s', |
| 301 'stderr': '%s', | 314 'stderr': '%s', |
| 302 } | 315 } |
| 303 super(MonochromeProgressIndicator, self).__init__(cases, templates) | 316 super(MonochromeProgressIndicator, self).__init__(cases, templates) |
| 304 | 317 |
| 305 def ClearLine(self, last_line_length): | 318 def ClearLine(self, last_line_length): |
| 306 print ("\r" + (" " * last_line_length) + "\r"), | 319 print ("\r" + (" " * last_line_length) + "\r"), |
| 307 | 320 |
|
Jakob Kummerow
2012/09/28 17:38:52
nit: two newlines between top-level definitions
| |
| 321 class UnitTestProgressIndicator(ProgressIndicator): | |
| 322 | |
| 323 def __init__(self): | |
| 324 self.outputter = UnitTestOutput(XMLTESTSUITE) | |
| 325 if XMLOUT: | |
| 326 self.outfile = open(XMLOUT, "w") | |
| 327 else: | |
| 328 self.outfile = sys.stdout | |
| 329 | |
| 330 def Starting(self): | |
| 331 pass | |
| 332 | |
| 333 def AboutToRun(self, case): | |
| 334 self.outputter.startNewTest(case.GetName()) | |
| 335 | |
| 336 def Done(self): | |
| 337 self.outputter.finishAndWrite(self.outfile) | |
| 338 if self.outfile != sys.stdout: | |
| 339 self.outfile.close() | |
| 340 | |
| 341 def HasRun(self, output): | |
| 342 if output.UnexpectedOutput(): | |
| 343 failtext = "" | |
| 344 stdout = output.output.stdout.strip() | |
| 345 if len(stdout): | |
| 346 failtext += "stdout:\n" | |
| 347 failtext += stdout | |
| 348 failtext += "\n" | |
| 349 stderr = output.output.stderr.strip() | |
| 350 if len(stderr): | |
| 351 failtext += "stderr:\n" | |
| 352 failtext += stderr | |
| 353 failtext += "\n" | |
| 354 if output.HasCrashed(): | |
| 355 failtext += "--- CRASHED ---" | |
| 356 if output.HasTimedOut(): | |
| 357 failtext += "--- TIMEOUT ---" | |
| 358 self.outputter.finishCurrentTest(output.command, True, failtext) | |
| 359 else: | |
| 360 self.outputter.finishCurrentTest(output.command, False) | |
| 361 | |
| 308 | 362 |
| 309 PROGRESS_INDICATORS = { | 363 PROGRESS_INDICATORS = { |
| 310 'verbose': VerboseProgressIndicator, | 364 'verbose': VerboseProgressIndicator, |
| 311 'dots': DotsProgressIndicator, | 365 'dots': DotsProgressIndicator, |
| 312 'color': ColorProgressIndicator, | 366 'color': ColorProgressIndicator, |
| 313 'mono': MonochromeProgressIndicator | 367 'mono': MonochromeProgressIndicator |
| 314 } | 368 } |
| 315 | 369 |
| 316 | 370 |
| 317 # ------------------------- | 371 # ------------------------- |
| (...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1231 dest="suppress_dialogs", action="store_false") | 1285 dest="suppress_dialogs", action="store_false") |
| 1232 result.add_option("--mips-arch-variant", help="mips architecture variant: mips 32r1/mips32r2", default="mips32r2"); | 1286 result.add_option("--mips-arch-variant", help="mips architecture variant: mips 32r1/mips32r2", default="mips32r2"); |
| 1233 result.add_option("--shell", help="Path to V8 shell", default="d8") | 1287 result.add_option("--shell", help="Path to V8 shell", default="d8") |
| 1234 result.add_option("--isolates", help="Whether to test isolates", default=False , action="store_true") | 1288 result.add_option("--isolates", help="Whether to test isolates", default=False , action="store_true") |
| 1235 result.add_option("--store-unexpected-output", | 1289 result.add_option("--store-unexpected-output", |
| 1236 help="Store the temporary JS files from tests that fails", | 1290 help="Store the temporary JS files from tests that fails", |
| 1237 dest="store_unexpected_output", default=True, action="store_true") | 1291 dest="store_unexpected_output", default=True, action="store_true") |
| 1238 result.add_option("--no-store-unexpected-output", | 1292 result.add_option("--no-store-unexpected-output", |
| 1239 help="Deletes the temporary JS files from tests that fails", | 1293 help="Deletes the temporary JS files from tests that fails", |
| 1240 dest="store_unexpected_output", action="store_false") | 1294 dest="store_unexpected_output", action="store_false") |
| 1295 result.add_option("--xmlout", help="File name of the UnitTest output") | |
| 1296 result.add_option("--xmltestsuite", help="Name of the testsuite in the UnitTes t XML output", default="v8tests") | |
| 1241 result.add_option("--stress-only", | 1297 result.add_option("--stress-only", |
| 1242 help="Only run tests with --always-opt --stress-opt", | 1298 help="Only run tests with --always-opt --stress-opt", |
| 1243 default=False, action="store_true") | 1299 default=False, action="store_true") |
| 1244 result.add_option("--nostress", | 1300 result.add_option("--nostress", |
| 1245 help="Don't run crankshaft --always-opt --stress-op test", | 1301 help="Don't run crankshaft --always-opt --stress-op test", |
| 1246 default=False, action="store_true") | 1302 default=False, action="store_true") |
| 1247 result.add_option("--shard-count", | 1303 result.add_option("--shard-count", |
| 1248 help="Split testsuites into this number of shards", | 1304 help="Split testsuites into this number of shards", |
| 1249 default=1, type="int") | 1305 default=1, type="int") |
| 1250 result.add_option("--shard-run", | 1306 result.add_option("--shard-run", |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1284 if options.arch in ['android', 'arm', 'mipsel']: | 1340 if options.arch in ['android', 'arm', 'mipsel']: |
| 1285 options.timeout = 2 * TIMEOUT_DEFAULT; | 1341 options.timeout = 2 * TIMEOUT_DEFAULT; |
| 1286 else: | 1342 else: |
| 1287 options.timeout = TIMEOUT_DEFAULT; | 1343 options.timeout = TIMEOUT_DEFAULT; |
| 1288 if options.snapshot: | 1344 if options.snapshot: |
| 1289 options.scons_flags.append("snapshot=on") | 1345 options.scons_flags.append("snapshot=on") |
| 1290 global VARIANT_FLAGS | 1346 global VARIANT_FLAGS |
| 1291 if options.mips_arch_variant: | 1347 if options.mips_arch_variant: |
| 1292 options.scons_flags.append("mips_arch_variant=" + options.mips_arch_variant) | 1348 options.scons_flags.append("mips_arch_variant=" + options.mips_arch_variant) |
| 1293 | 1349 |
| 1350 global XMLOUT | |
| 1351 XMLOUT = options.xmlout | |
| 1352 global XMLTESTSUITE | |
| 1353 XMLTESTSUITE = options.xmltestsuite | |
| 1354 | |
| 1294 if options.stress_only: | 1355 if options.stress_only: |
| 1295 VARIANT_FLAGS = [['--stress-opt', '--always-opt']] | 1356 VARIANT_FLAGS = [['--stress-opt', '--always-opt']] |
| 1296 if options.nostress: | 1357 if options.nostress: |
| 1297 VARIANT_FLAGS = [[],['--nocrankshaft']] | 1358 VARIANT_FLAGS = [[],['--nocrankshaft']] |
| 1298 if options.shell.endswith("d8"): | 1359 if options.shell.endswith("d8"): |
| 1299 if options.special_command: | 1360 if options.special_command: |
| 1300 options.special_command += " --test" | 1361 options.special_command += " --test" |
| 1301 else: | 1362 else: |
| 1302 options.special_command = "@ --test" | 1363 options.special_command = "@ --test" |
| 1303 if options.noprof: | 1364 if options.noprof: |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1545 index = 1 | 1606 index = 1 |
| 1546 for entry in timed_tests[:20]: | 1607 for entry in timed_tests[:20]: |
| 1547 t = FormatTime(entry.duration) | 1608 t = FormatTime(entry.duration) |
| 1548 sys.stderr.write("%4i (%s) %s\n" % (index, t, entry.GetLabel())) | 1609 sys.stderr.write("%4i (%s) %s\n" % (index, t, entry.GetLabel())) |
| 1549 index += 1 | 1610 index += 1 |
| 1550 | 1611 |
| 1551 return result | 1612 return result |
| 1552 | 1613 |
| 1553 | 1614 |
| 1554 if __name__ == '__main__': | 1615 if __name__ == '__main__': |
| 1555 sys.exit(Main()) | 1616 if XMLOUT: |
| 1617 Main() | |
| 1618 sys.exit(0) | |
| 1619 else: | |
| 1620 sys.exit(Main()) | |
| OLD | NEW |