12fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#!/usr/bin/env python 22fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# Copyright (C) 2011 Google Inc. All rights reserved. 32fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# 42fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# Redistribution and use in source and binary forms, with or without 52fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# modification, are permitted provided that the following conditions are 62fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# met: 72fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# 82fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# * Redistributions of source code must retain the above copyright 92fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# notice, this list of conditions and the following disclaimer. 102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# * Redistributions in binary form must reproduce the above 112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# copyright notice, this list of conditions and the following disclaimer 122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# in the documentation and/or other materials provided with the 132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# distribution. 142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# * Neither the name of Google Inc. nor the names of its 152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# contributors may be used to endorse or promote products derived from 162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# this software without specific prior written permission. 172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# 182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block""" 312fc2651226baac27029e38c9d6ef883fa32084dbSteve BlockThe TestRunner2 package is an alternate implementation of the TestRunner 322fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass that uses the manager_worker_broker module to send sets of tests to 332fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockworkers and receive their completion messages accordingly. 342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block""" 352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 362fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockimport logging 3781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochimport time 382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 3981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochfrom webkitpy.tool import grammar 402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 412fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockfrom webkitpy.layout_tests.layout_package import manager_worker_broker 422fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockfrom webkitpy.layout_tests.layout_package import test_runner 432fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockfrom webkitpy.layout_tests.layout_package import worker 442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 4581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block_log = logging.getLogger(__name__) 472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 4981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochclass _WorkerState(object): 5081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch """A class for the TestRunner/manager to use to track the current state 5181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch of the workers.""" 5281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch def __init__(self, number, worker_connection): 5381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.worker_connection = worker_connection 5481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.number = number 5581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.done = False 5681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.current_test_name = None 5781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.next_timeout = None 5881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.wedged = False 5981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.stats = {} 6081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.stats['name'] = worker_connection.name 6181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.stats['num_tests'] = 0 6281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.stats['total_time'] = 0 6381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 6481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch def __repr__(self): 6581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return "_WorkerState(" + str(self.__dict__) + ")" 6681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 6781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 682fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockclass TestRunner2(test_runner.TestRunner): 692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def __init__(self, port, options, printer): 702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block test_runner.TestRunner.__init__(self, port, options, printer) 712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._all_results = [] 722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._group_stats = {} 732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._current_result_summary = None 7481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 7581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # This maps worker names to the state we are tracking for each of them. 7681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._worker_states = {} 772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 782fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def is_done(self): 7981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_states = self._worker_states.values() 8081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return worker_states and all(self._worker_is_done(worker_state) for worker_state in worker_states) 8181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 8281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch def _worker_is_done(self, worker_state): 8381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch t = time.time() 8481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if worker_state.done or worker_state.wedged: 8581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return True 8681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 8781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch next_timeout = worker_state.next_timeout 8881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch WEDGE_PADDING = 40.0 8981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if next_timeout and t > next_timeout + WEDGE_PADDING: 9081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch _log.error('') 9181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.worker_connection.log_wedged_worker(worker_state.current_test_name) 9281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch _log.error('') 9381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.wedged = True 9481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return True 9581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return False 962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def name(self): 982fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return 'TestRunner2' 992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block def _run_tests(self, file_list, result_summary): 1012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """Runs the tests in the file_list. 1022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 10381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch Return: A tuple (interrupted, keyboard_interrupted, thread_timings, 10481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch test_timings, individual_test_timings) 10581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch interrupted is whether the run was interrupted 1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block keyboard_interrupted is whether someone typed Ctrl^C 1072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block thread_timings is a list of dicts with the total runtime 1082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block of each thread with 'name', 'num_tests', 'total_time' properties 1092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block test_timings is a list of timings for each sharded subdirectory 1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block of the form [time, directory_name, num_tests] 1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block individual_test_timings is a list of run times for each test 1122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block in the form {filename:filename, test_run_time:test_run_time} 1132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block result_summary: summary object to populate with the results 1142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block """ 1152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._current_result_summary = result_summary 11681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._all_results = [] 11781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._group_stats = {} 11881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._worker_states = {} 11981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 12081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch keyboard_interrupted = False 12181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch interrupted = False 12281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch thread_timings = [] 12381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 12481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._printer.print_update('Sharding tests ...') 12581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch test_lists = self._shard_tests(file_list, 1262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch (int(self._options.child_processes) > 1) and not self._options.experimental_fully_parallel) 1272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch num_workers = self._num_workers(len(test_lists)) 1292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 13081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch manager_connection = manager_worker_broker.get(self._port, self._options, 13181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self, worker.Worker) 1322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 13381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if self._options.dry_run: 13481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return (keyboard_interrupted, interrupted, thread_timings, 13581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._group_stats, self._all_results) 1362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 13781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._printer.print_update('Starting %s ...' % 13881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch grammar.pluralize('worker', num_workers)) 13981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch for worker_number in xrange(num_workers): 14081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_connection = manager_connection.start_worker(worker_number) 14181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state = _WorkerState(worker_number, worker_connection) 14281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._worker_states[worker_connection.name] = worker_state 1432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 14481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # FIXME: If we start workers up too quickly, DumpRenderTree appears 14581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # to thrash on something and time out its first few tests. Until 14681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # we can figure out what's going on, sleep a bit in between 14781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # workers. 14881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch time.sleep(0.1) 1492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 15081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._printer.print_update("Starting testing ...") 1512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block for test_list in test_lists: 1522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block manager_connection.post_message('test_list', test_list[0], test_list[1]) 1532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 15481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # We post one 'stop' message for each worker. Because the stop message 15581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # are sent after all of the tests, and because each worker will stop 15681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # reading messsages after receiving a stop, we can be sure each 15781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # worker will get a stop message and hence they will all shut down. 15881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch for i in xrange(num_workers): 15981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch manager_connection.post_message('stop') 1602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 16181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch try: 16281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch while not self.is_done(): 16381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # We loop with a timeout in order to be able to detect wedged threads. 1642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block manager_connection.run_message_loop(delay_secs=1.0) 1652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 16681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if any(worker_state.wedged for worker_state in self._worker_states.values()): 16781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch _log.error('') 16881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch _log.error('Remaining workers are wedged, bailing out.') 16981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch _log.error('') 17081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch else: 17181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch _log.debug('No wedged threads') 17281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 17381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # Make sure all of the workers have shut down (if possible). 17481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch for worker_state in self._worker_states.values(): 17581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if not worker_state.wedged and worker_state.worker_connection.is_alive(): 17681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.worker_connection.join(0.5) 17781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch assert not worker_state.worker_connection.is_alive() 17881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 17981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch except KeyboardInterrupt: 18081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch _log.info("Interrupted, exiting") 18181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.cancel_workers() 18281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch keyboard_interrupted = True 18381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch except test_runner.TestRunInterruptedException, e: 18481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch _log.info(e.reason) 18581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self.cancel_workers() 18681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch interrupted = True 18781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch except: 18881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # Unexpected exception; don't try to clean up workers. 18981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch _log.info("Exception raised, exiting") 19081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch raise 19181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 19281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch thread_timings = [worker_state.stats for worker_state in self._worker_states.values()] 1932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 1942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block # FIXME: should this be a class instead of a tuple? 19581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch return (interrupted, keyboard_interrupted, thread_timings, 1962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._group_stats, self._all_results) 1972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 19881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch def cancel_workers(self): 19981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch for worker_state in self._worker_states.values(): 20081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.worker_connection.cancel() 2012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 20281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch def handle_started_test(self, source, test_info, hang_timeout): 20381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state = self._worker_states[source] 20481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.current_test_name = self._port.relative_test_filename(test_info.filename) 20581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.next_timeout = time.time() + hang_timeout 2062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 20781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch def handle_done(self, source): 20881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state = self._worker_states[source] 20981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.done = True 2102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 21181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch def handle_exception(self, source, exception_info): 21281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch exception_type, exception_value, exception_traceback = exception_info 21381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch raise exception_type, exception_value, exception_traceback 2142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 21581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch def handle_finished_list(self, source, list_name, num_tests, elapsed_time): 21681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._group_stats[list_name] = (num_tests, elapsed_time) 2172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 21881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch def handle_finished_test(self, source, result, elapsed_time): 21981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state = self._worker_states[source] 22081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.next_timeout = None 22181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.current_test_name = None 22281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.stats['total_time'] += elapsed_time 22381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch worker_state.stats['num_tests'] += 1 22481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch 22581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch if worker_state.wedged: 22681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch # This shouldn't happen if we have our timeouts tuned properly. 2272bde8e466a4451c7319e3a072d118917957d6554Steve Block _log.error("%s unwedged", source) 2282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block self._all_results.append(result) 23081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch self._update_summary_with_result(self._current_result_summary, result) 231