def setResult(self, result):
assert self.result is None, "result already set"
assert isinstance(result, Result), "unexpected result type"
+ try:
+ expected_to_fail = self.isExpectedToFail()
+ except ValueError as err:
+ # Syntax error in an XFAIL line.
+ result.code = UNRESOLVED
+ result.output = str(err)
+ else:
+ if expected_to_fail:
+ # pass -> unexpected pass
+ if result.code is PASS:
+ result.code = XPASS
+ # fail -> expected fail
+ elif result.code is FAIL:
+ result.code = XFAIL
self.result = result
def isFailure(self):
# TODO(yln): as the comment says.. this is racing with the main thread waiting
# for results
- def _process_result(self, test, result):
+ def _process_completed(self, test):
# Don't add any more test results after we've hit the maximum failure
# count. Otherwise we're racing with the main thread, which is going
# to terminate the process pool soon.
if self.hit_max_failures:
return
- test.setResult(result)
-
# Use test.isFailure() for correct XFAIL and XPASS handling
if test.isFailure():
self.failure_count += 1
# TODO(yln): ignores deadline
for test in self.tests:
result = lit.worker._execute(test, self.lit_config)
- self._process_result(test, result)
+ test.setResult(result)
+ self._process_completed(test)
if self.hit_max_failures:
break
self._install_win32_signal_handler(pool)
+ def process_completed(test, idx):
+ self.tests[idx] = test
+ self._process_completed(test)
+
async_results = [
pool.apply_async(lit.worker.execute, args=[test],
- callback=lambda r, t=test: self._process_result(t, r))
- for test in self.tests]
+ callback=lambda t, i=idx: process_completed(t, i))
+ for idx, test in enumerate(self.tests)]
pool.close()
for ar in async_results:
import lit.Test
import lit.util
+
_lit_config = None
_parallelism_semaphores = None
+
def initialize(lit_config, parallelism_semaphores):
"""Copy data shared by all test executions into worker processes"""
global _lit_config
_lit_config = lit_config
_parallelism_semaphores = parallelism_semaphores
+
def execute(test):
"""Run one test in a multiprocessing.Pool
to copy.
"""
try:
- return _execute_in_parallelism_group(test, _lit_config,
- _parallelism_semaphores)
+ result = _execute_in_parallelism_group(test, _lit_config,
+ _parallelism_semaphores)
+ test.setResult(result)
+ return test
except KeyboardInterrupt:
# If a worker process gets an interrupt, abort it immediately.
lit.util.abort_now()
except:
traceback.print_exc()
+
def _execute_in_parallelism_group(test, lit_config, parallelism_semaphores):
pg = test.config.parallelism_group
if callable(pg):
def _execute(test, lit_config):
- """Execute one test"""
start = time.time()
result = _execute_test_handle_errors(test, lit_config)
- end = time.time()
-
- result.elapsed = end - start
- resolve_result_code(result, test)
-
+ result.elapsed = time.time() - start
return result
-# TODO(yln): is this the right place to deal with this?
-# isExpectedToFail() only works after the test has been executed.
-def resolve_result_code(result, test):
- try:
- expected_to_fail = test.isExpectedToFail()
- except ValueError as e:
- # Syntax error in an XFAIL line.
- result.code = lit.Test.UNRESOLVED
- result.output = str(e)
- else:
- if expected_to_fail:
- # pass -> unexpected pass
- if result.code is lit.Test.PASS:
- result.code = lit.Test.XPASS
- # fail -> expected fail
- if result.code is lit.Test.FAIL:
- result.code = lit.Test.XFAIL
-
-
def _execute_test_handle_errors(test, lit_config):
try:
- return _adapt_result(test.config.test_format.execute(test, lit_config))
+ result = test.config.test_format.execute(test, lit_config)
+ return _adapt_result(result)
except KeyboardInterrupt:
raise
except: