[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 os
import platform import platform
import sys import sys
import time
import lit.cl_arguments import lit.cl_arguments
import lit.discovery import lit.discovery
@ -209,8 +208,6 @@ def increase_process_limit(litConfig, opts):
def run_tests(tests, litConfig, opts, numTotalTests): def run_tests(tests, litConfig, opts, numTotalTests):
increase_process_limit(litConfig, opts) increase_process_limit(litConfig, opts)
run = lit.run.Run(litConfig, tests)
display = lit.display.create_display(opts, len(tests), numTotalTests, display = lit.display.create_display(opts, len(tests), numTotalTests,
opts.numWorkers) opts.numWorkers)
def progress_callback(test): def progress_callback(test):
@ -218,18 +215,22 @@ def run_tests(tests, litConfig, opts, numTotalTests):
if opts.incremental: if opts.incremental:
update_incremental_cache(test) update_incremental_cache(test)
run_callback = lambda: run.execute_tests(progress_callback, opts.numWorkers, run = lit.run.Run(tests, litConfig, progress_callback, opts.maxTime,
opts.maxTime) opts.numWorkers)
startTime = time.time()
try: try:
run_tests_in_tmp_dir(run_callback, litConfig) elapsed = run_tests_in_tmp_dir(run.execute_tests, litConfig)
except KeyboardInterrupt: except KeyboardInterrupt:
#TODO(yln): should we attempt to cleanup the progress bar here?
sys.exit(2) 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() display.finish()
return testing_time return elapsed
def run_tests_in_tmp_dir(run_callback, litConfig): def run_tests_in_tmp_dir(run_callback, litConfig):
# Create a temp directory inside the normal temp directory so that we can # 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 # scanning for stale temp directories, and deleting temp directories whose
# lit process has died. # lit process has died.
try: try:
run_callback() return run_callback()
finally: finally:
if tmp_dir: if tmp_dir:
try: try:

View File

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