[lit] Improve lit.Run class

* Push timing of overall test time into run module
* Make lit.Run a proper class
* Add a few TODO comments

llvm-svn: 375065
This commit is contained in:
Julian Lettner 2019-10-17 00:29:59 +00:00
parent f80f15e38a
commit f35cebe71d
2 changed files with 37 additions and 31 deletions

View File

@ -9,7 +9,6 @@ See lit.pod for more information.
import os
import platform
import sys
import time
import lit.cl_arguments
import lit.discovery
@ -209,8 +208,6 @@ def increase_process_limit(litConfig, opts):
def run_tests(tests, litConfig, opts, numTotalTests):
increase_process_limit(litConfig, opts)
run = lit.run.Run(litConfig, tests)
display = lit.display.create_display(opts, len(tests), numTotalTests,
opts.numWorkers)
def progress_callback(test):
@ -218,18 +215,22 @@ def run_tests(tests, litConfig, opts, numTotalTests):
if opts.incremental:
update_incremental_cache(test)
run_callback = lambda: run.execute_tests(progress_callback, opts.numWorkers,
opts.maxTime)
run = lit.run.Run(tests, litConfig, progress_callback, opts.maxTime,
opts.numWorkers)
startTime = time.time()
try:
run_tests_in_tmp_dir(run_callback, litConfig)
elapsed = run_tests_in_tmp_dir(run.execute_tests, litConfig)
except KeyboardInterrupt:
#TODO(yln): should we attempt to cleanup the progress bar here?
sys.exit(2)
testing_time = time.time() - startTime
# TODO(yln): display.finish_interrupted(), which shows the most recently started test
# TODO(yln): change display to update when test starts, not when test completes
# Ensure everything still works with SimpleProgressBar as well
# finally:
# display.finish()
display.finish()
return testing_time
return elapsed
def run_tests_in_tmp_dir(run_callback, litConfig):
# Create a temp directory inside the normal temp directory so that we can
@ -252,7 +253,7 @@ def run_tests_in_tmp_dir(run_callback, litConfig):
# scanning for stale temp directories, and deleting temp directories whose
# lit process has died.
try:
run_callback()
return run_callback()
finally:
if tmp_dir:
try:

View File

@ -12,18 +12,17 @@ class NopSemaphore(object):
def release(self): pass
class Run(object):
"""
This class represents a concrete, configured testing run.
"""
"""A concrete, configured testing run."""
def __init__(self, lit_config, tests):
self.lit_config = lit_config
def __init__(self, tests, lit_config, progress_callback, max_time, workers):
self.tests = tests
self.lit_config = lit_config
self.progress_callback = progress_callback
self.max_time = max_time
self.workers = workers
def execute_tests(self, progress_callback, workers, max_time):
def execute_tests(self):
"""
execute_tests(progress_callback, workers, max_time)
Execute the tests in the run using up to the specified number of
parallel tasks, and inform the caller of each individual result. The
provided tests should be a subset of the tests available in this run
@ -34,42 +33,48 @@ class Run(object):
If max_time is non-None, it should be a time in seconds after which to
stop executing tests.
Returns the elapsed testing time.
Upon completion, each test in the run will have its result
computed. Tests which were not actually executed (for any reason) will
be given an UNRESOLVED result.
"""
# Don't do anything if we aren't going to run any tests.
if not self.tests:
return
self.progress_callback = progress_callback
return 0.0
self.failure_count = 0
self.hit_max_failures = False
if workers == 1:
self._execute_in_serial(max_time)
start = time.time()
if self.workers == 1:
self._execute_in_serial()
else:
self._execute_in_parallel(workers, max_time)
self._execute_in_parallel()
end = time.time()
# Mark any tests that weren't run as UNRESOLVED.
for test in self.tests:
if test.result is None:
test.setResult(lit.Test.Result(lit.Test.UNRESOLVED, '', 0.0))
def _execute_in_serial(self, max_time):
return end - start
def _execute_in_serial(self):
# TODO(yln): ignores max_time
for test_index, test in enumerate(self.tests):
lit.worker._execute_test(test, self.lit_config)
self._consume_test_result((test_index, test))
if self.hit_max_failures:
break
def _execute_in_parallel(self, workers, max_time):
assert workers > 1
def _execute_in_parallel(self):
# We need to issue many wait calls, so compute the final deadline and
# subtract time.time() from that as we go along.
deadline = None
if max_time:
deadline = time.time() + max_time
if self.max_time:
deadline = time.time() + self.max_time
semaphores = {
k: NopSemaphore() if v is None else
@ -81,7 +86,7 @@ class Run(object):
# interrupts the workers before we make it into our task callback, they
# will each raise a KeyboardInterrupt exception and print to stderr at
# the same time.
pool = multiprocessing.Pool(workers, lit.worker.initializer,
pool = multiprocessing.Pool(self.workers, lit.worker.initializer,
(self.lit_config, semaphores))
# Install a console-control signal handler on Windows.