Changeset 84595 in webkit
- Timestamp:
- Apr 21, 2011 8:28:23 PM (13 years ago)
- Location:
- trunk/Tools
- Files:
-
- 1 deleted
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r84594 r84595 1 2011-04-21 Dirk Pranke <dpranke@chromium.org> 2 3 Reviewed by Tony Chang. 4 5 new-run-webkit-tests: obsolete old code, part 4: merge worker_mixin into worker 6 https://bugs.webkit.org/show_bug.cgi?id=58756 7 8 Since worker_mixin is now only used by worker, there's no point 9 in having it split across two files. 10 11 * Scripts/webkitpy/layout_tests/layout_package/worker.py: 12 * Scripts/webkitpy/layout_tests/layout_package/worker_mixin.py: Removed. 13 1 14 2011-04-21 Dirk Pranke <dpranke@chromium.org> 2 15 -
trunk/Tools/Scripts/webkitpy/layout_tests/layout_package/worker.py
r84467 r84595 27 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 28 29 """Handle messages from the TestRunner and executeactual tests."""29 """Handle messages from the Manager and executes actual tests.""" 30 30 31 31 import logging 32 32 import sys 33 import threading 33 34 import time 34 35 35 36 from webkitpy.common.system import stack_utils 36 37 37 from webkitpy.layout_tests.layout_package import manager_worker_broker 38 from webkitpy.layout_tests.layout_package import worker_mixin39 38 from webkitpy.layout_tests.layout_package import single_test_runner 39 from webkitpy.layout_tests.layout_package import test_results 40 40 41 41 _log = logging.getLogger(__name__) 42 42 43 43 44 class Worker(manager_worker_broker.AbstractWorker , worker_mixin.WorkerMixin):44 class Worker(manager_worker_broker.AbstractWorker): 45 45 def __init__(self, worker_connection, worker_number, options): 46 46 self._worker_connection = worker_connection … … 54 54 def __del__(self): 55 55 self.cleanup() 56 57 def safe_init(self, port): 58 """This method should only be called when it is is safe for the mixin 59 to create state that can't be Pickled. 60 61 This routine exists so that the mixin can be created and then marshaled 62 across into a child process.""" 63 self._port = port 64 self._filesystem = port._filesystem 65 self._batch_count = 0 66 self._batch_size = self._options.batch_size 67 self._driver = None 68 tests_run_filename = self._filesystem.join(port.results_directory(), 69 "tests_run%d.txt" % self._worker_number) 70 self._tests_run_file = self._filesystem.open_text_file_for_writing(tests_run_filename) 71 72 # FIXME: it's goofy that we have to track this at all, but it's due to 73 # the awkward logic in TestShellThread._run(). When we remove that 74 # file, we should rewrite this code so that caller keeps track of whether 75 # the lock is held. 76 self._has_http_lock = False 56 77 57 78 def cancel(self): … … 121 142 122 143 self.clean_up_after_test(test_input, result) 144 145 def cleanup(self): 146 if self._driver: 147 self.kill_driver() 148 if self._has_http_lock: 149 self.stop_servers_with_lock() 150 if self._tests_run_file: 151 self._tests_run_file.close() 152 self._tests_run_file = None 153 154 def timeout(self, test_input): 155 """Compute the appropriate timeout value for a test.""" 156 # The DumpRenderTree watchdog uses 2.5x the timeout; we want to be 157 # larger than that. We also add a little more padding if we're 158 # running tests in a separate thread. 159 # 160 # Note that we need to convert the test timeout from a 161 # string value in milliseconds to a float for Python. 162 driver_timeout_sec = 3.0 * float(test_input.timeout) / 1000.0 163 if not self._options.run_singly: 164 return driver_timeout_sec 165 166 thread_padding_sec = 1.0 167 thread_timeout_sec = driver_timeout_sec + thread_padding_sec 168 return thread_timeout_sec 169 170 def start_servers_with_lock(self): 171 _log.debug('Acquiring http lock ...') 172 self._port.acquire_http_lock() 173 _log.debug('Starting HTTP server ...') 174 self._port.start_http_server() 175 _log.debug('Starting WebSocket server ...') 176 self._port.start_websocket_server() 177 self._has_http_lock = True 178 179 def stop_servers_with_lock(self): 180 if self._has_http_lock: 181 _log.debug('Stopping HTTP server ...') 182 self._port.stop_http_server() 183 _log.debug('Stopping WebSocket server ...') 184 self._port.stop_websocket_server() 185 _log.debug('Releasing server lock ...') 186 self._port.release_http_lock() 187 self._has_http_lock = False 188 189 def kill_driver(self): 190 if self._driver: 191 self._driver.stop() 192 self._driver = None 193 194 def run_test_with_timeout(self, test_input, timeout): 195 if self._options.run_singly: 196 return self._run_test_in_another_thread(test_input, timeout) 197 else: 198 return self._run_test_in_this_thread(test_input) 199 return result 200 201 def clean_up_after_test(self, test_input, result): 202 self._batch_count += 1 203 self._tests_run_file.write(test_input.filename + "\n") 204 test_name = self._port.relative_test_filename(test_input.filename) 205 206 if result.failures: 207 # Check and kill DumpRenderTree if we need to. 208 if any([f.should_kill_dump_render_tree() for f in result.failures]): 209 self.kill_driver() 210 # Reset the batch count since the shell just bounced. 211 self._batch_count = 0 212 213 # Print the error message(s). 214 _log.debug("%s %s failed:" % (self._name, test_name)) 215 for f in result.failures: 216 _log.debug("%s %s" % (self._name, f.message())) 217 else: 218 _log.debug("%s %s passed" % (self._name, test_name)) 219 220 if self._batch_size > 0 and self._batch_count >= self._batch_size: 221 # Bounce the shell and reset count. 222 self.kill_driver() 223 self._batch_count = 0 224 225 def _run_test_in_another_thread(self, test_input, thread_timeout_sec): 226 """Run a test in a separate thread, enforcing a hard time limit. 227 228 Since we can only detect the termination of a thread, not any internal 229 state or progress, we can only run per-test timeouts when running test 230 files singly. 231 232 Args: 233 test_input: Object containing the test filename and timeout 234 thread_timeout_sec: time to wait before killing the driver process. 235 Returns: 236 A TestResult 237 """ 238 worker = self 239 240 driver = worker._port.create_driver(worker._worker_number) 241 driver.start() 242 243 class SingleTestThread(threading.Thread): 244 def run(self): 245 self.result = worker._run_single_test(driver, test_input) 246 247 thread = SingleTestThread() 248 thread.start() 249 thread.join(thread_timeout_sec) 250 result = getattr(thread, 'result', None) 251 if thread.isAlive(): 252 # If join() returned with the thread still running, the 253 # DumpRenderTree is completely hung and there's nothing 254 # more we can do with it. We have to kill all the 255 # DumpRenderTrees to free it up. If we're running more than 256 # one DumpRenderTree thread, we'll end up killing the other 257 # DumpRenderTrees too, introducing spurious crashes. We accept 258 # that tradeoff in order to avoid losing the rest of this 259 # thread's results. 260 _log.error('Test thread hung: killing all DumpRenderTrees') 261 262 driver.stop() 263 264 if not result: 265 result = test_results.TestResult(test_input.filename, failures=[], test_run_time=0) 266 return result 267 268 def _run_test_in_this_thread(self, test_input): 269 """Run a single test file using a shared DumpRenderTree process. 270 271 Args: 272 test_input: Object containing the test filename, uri and timeout 273 274 Returns: a TestResult object. 275 """ 276 # poll() is not threadsafe and can throw OSError due to: 277 # http://bugs.python.org/issue1731717 278 if not self._driver or self._driver.poll() is not None: 279 self._driver = self._port.create_driver(self._worker_number) 280 self._driver.start() 281 return self._run_single_test(self._driver, test_input) 282 283 def _run_single_test(self, driver, test_input): 284 return single_test_runner.run_single_test(self._port, self._options, 285 test_input, driver, self._name)
Note: See TracChangeset
for help on using the changeset viewer.