| OLD | NEW |
| (Empty) |
| 1 # Copyright 2012 the V8 project authors. All rights reserved. | |
| 2 # Redistribution and use in source and binary forms, with or without | |
| 3 # modification, are permitted provided that the following conditions are | |
| 4 # met: | |
| 5 # | |
| 6 # * Redistributions of source code must retain the above copyright | |
| 7 # notice, this list of conditions and the following disclaimer. | |
| 8 # * Redistributions in binary form must reproduce the above | |
| 9 # copyright notice, this list of conditions and the following | |
| 10 # disclaimer in the documentation and/or other materials provided | |
| 11 # with the distribution. | |
| 12 # * Neither the name of Google Inc. nor the names of its | |
| 13 # contributors may be used to endorse or promote products derived | |
| 14 # from this software without specific prior written permission. | |
| 15 # | |
| 16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 27 | |
| 28 | |
| 29 import multiprocessing | |
| 30 import os | |
| 31 import threading | |
| 32 import time | |
| 33 | |
| 34 from . import commands | |
| 35 from . import utils | |
| 36 | |
| 37 | |
| 38 class Job(object): | |
| 39 def __init__(self, command, dep_command, test_id, timeout, verbose): | |
| 40 self.command = command | |
| 41 self.dep_command = dep_command | |
| 42 self.id = test_id | |
| 43 self.timeout = timeout | |
| 44 self.verbose = verbose | |
| 45 | |
| 46 | |
| 47 def RunTest(job): | |
| 48 try: | |
| 49 start_time = time.time() | |
| 50 if job.dep_command is not None: | |
| 51 dep_output = commands.Execute(job.dep_command, job.verbose, job.timeout) | |
| 52 # TODO(jkummerow): We approximate the test suite specific function | |
| 53 # IsFailureOutput() by just checking the exit code here. Currently | |
| 54 # only cctests define dependencies, for which this simplification is | |
| 55 # correct. | |
| 56 if dep_output.exit_code != 0: | |
| 57 return (job.id, dep_output, time.time() - start_time) | |
| 58 output = commands.Execute(job.command, job.verbose, job.timeout) | |
| 59 return (job.id, output, time.time() - start_time) | |
| 60 except Exception, e: | |
| 61 print(">>> EXCEPTION: %s" % e) | |
| 62 return (-1, -1, 0) | |
| 63 | |
| 64 | |
| 65 class Runner(object): | |
| 66 | |
| 67 def __init__(self, suites, progress_indicator, context): | |
| 68 self.tests = [ t for s in suites for t in s.tests ] | |
| 69 self._CommonInit(len(self.tests), progress_indicator, context) | |
| 70 | |
| 71 def _CommonInit(self, num_tests, progress_indicator, context): | |
| 72 self.indicator = progress_indicator | |
| 73 progress_indicator.runner = self | |
| 74 self.context = context | |
| 75 self.succeeded = 0 | |
| 76 self.total = num_tests | |
| 77 self.remaining = num_tests | |
| 78 self.failed = [] | |
| 79 self.crashed = 0 | |
| 80 self.terminate = False | |
| 81 self.lock = threading.Lock() | |
| 82 | |
| 83 def Run(self, jobs): | |
| 84 self.indicator.Starting() | |
| 85 self._RunInternal(jobs) | |
| 86 self.indicator.Done() | |
| 87 return not self.failed | |
| 88 | |
| 89 def _RunInternal(self, jobs): | |
| 90 pool = multiprocessing.Pool(processes=jobs) | |
| 91 test_map = {} | |
| 92 queue = [] | |
| 93 for test in self.tests: | |
| 94 assert test.id >= 0 | |
| 95 test_map[test.id] = test | |
| 96 command = self.GetCommand(test) | |
| 97 timeout = self.context.timeout | |
| 98 if ("--stress-opt" in test.flags or | |
| 99 "--stress-opt" in self.context.mode_flags or | |
| 100 "--stress-opt" in self.context.extra_flags): | |
| 101 timeout *= 4 | |
| 102 if test.dependency is not None: | |
| 103 dep_command = [ c.replace(test.path, test.dependency) for c in command ] | |
| 104 else: | |
| 105 dep_command = None | |
| 106 job = Job(command, dep_command, test.id, timeout, self.context.verbose) | |
| 107 queue.append(job) | |
| 108 try: | |
| 109 kChunkSize = 1 | |
| 110 it = pool.imap_unordered(RunTest, queue, kChunkSize) | |
| 111 for result in it: | |
| 112 test_id = result[0] | |
| 113 if test_id < 0: | |
| 114 raise BreakNowException("User pressed Ctrl+C or IO went wrong") | |
| 115 test = test_map[test_id] | |
| 116 self.indicator.AboutToRun(test) | |
| 117 test.output = result[1] | |
| 118 test.duration = result[2] | |
| 119 if test.suite.HasUnexpectedOutput(test): | |
| 120 self.failed.append(test) | |
| 121 if test.output.HasCrashed(): | |
| 122 self.crashed += 1 | |
| 123 else: | |
| 124 self.succeeded += 1 | |
| 125 self.remaining -= 1 | |
| 126 self.indicator.HasRun(test) | |
| 127 except: | |
| 128 pool.terminate() | |
| 129 pool.join() | |
| 130 raise | |
| 131 return | |
| 132 | |
| 133 | |
| 134 def GetCommand(self, test): | |
| 135 d8testflag = [] | |
| 136 shell = test.suite.shell() | |
| 137 if shell == "d8": | |
| 138 d8testflag = ["--test"] | |
| 139 if utils.IsWindows(): | |
| 140 shell += ".exe" | |
| 141 cmd = ([self.context.command_prefix] + | |
| 142 [os.path.join(self.context.shell_dir, shell)] + | |
| 143 d8testflag + | |
| 144 test.suite.GetFlagsForTestCase(test, self.context) + | |
| 145 [self.context.extra_flags]) | |
| 146 cmd = [ c for c in cmd if c != "" ] | |
| 147 return cmd | |
| 148 | |
| 149 | |
| 150 class BreakNowException(Exception): | |
| 151 def __init__(self, value): | |
| 152 self.value = value | |
| 153 def __str__(self): | |
| 154 return repr(self.value) | |
| OLD | NEW |