summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorAlp Toker <alp@nuanti.com>2013-12-29 05:09:05 +0000
committerAlp Toker <alp@nuanti.com>2013-12-29 05:09:05 +0000
commit9ad6e339c3235401eeeed9c3ec982ee1b02901f2 (patch)
tree28d791e02e0958b4ce1e19059b774e66dc0e44a1 /utils
parent0c6782545920d2d0cd3764f463ac352f5ff17ac4 (diff)
downloadllvm-9ad6e339c3235401eeeed9c3ec982ee1b02901f2.tar.gz
llvm-9ad6e339c3235401eeeed9c3ec982ee1b02901f2.tar.bz2
llvm-9ad6e339c3235401eeeed9c3ec982ee1b02901f2.tar.xz
lit: Incremental test scheduling
Add option -i to prioritize test runs by source file modification time and previous failure state. This optimal scheduling reduces typical test-and-fix iteration times to a matter of seconds by rapidly answering the questions: 1) Did my recent change fix tests that were previously failing? 2) Do the tests I just wrote / modified still work? The current implementation requires write permissions to the source tree because it uses mtimes to track failures. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198150 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/lit/lit/Test.py8
-rw-r--r--utils/lit/lit/formats/googletest.py2
-rwxr-xr-xutils/lit/lit/main.py28
3 files changed, 36 insertions, 2 deletions
diff --git a/utils/lit/lit/Test.py b/utils/lit/lit/Test.py
index b4988f530d..e51bf12977 100644
--- a/utils/lit/lit/Test.py
+++ b/utils/lit/lit/Test.py
@@ -128,10 +128,11 @@ class TestSuite:
class Test:
"""Test - Information on a single test instance."""
- def __init__(self, suite, path_in_suite, config):
+ def __init__(self, suite, path_in_suite, config, file_path = None):
self.suite = suite
self.path_in_suite = path_in_suite
self.config = config
+ self.file_path = file_path
# A list of conditions under which this test is expected to fail. These
# can optionally be provided by test format handlers, and will be
# honored when the test result is supplied.
@@ -157,6 +158,11 @@ class Test:
def getFullName(self):
return self.suite.config.name + ' :: ' + '/'.join(self.path_in_suite)
+ def getFilePath(self):
+ if self.file_path:
+ return self.file_path
+ return self.getSourcePath()
+
def getSourcePath(self):
return self.suite.getSourcePath(self.path_in_suite)
diff --git a/utils/lit/lit/formats/googletest.py b/utils/lit/lit/formats/googletest.py
index b77e184d2f..3d14b729ed 100644
--- a/utils/lit/lit/formats/googletest.py
+++ b/utils/lit/lit/formats/googletest.py
@@ -66,7 +66,7 @@ class GoogleTest(TestFormat):
# Discover the tests in this executable.
for testname in self.getGTestTests(execpath, litConfig, localConfig):
testPath = path_in_suite + (basename, testname)
- yield lit.Test.Test(testSuite, testPath, localConfig)
+ yield lit.Test.Test(testSuite, testPath, localConfig, file_path=execpath)
def getTestsInDirectory(self, testSuite, path_in_suite,
litConfig, localConfig):
diff --git a/utils/lit/lit/main.py b/utils/lit/lit/main.py
index 6f672a01eb..3c49e85406 100755
--- a/utils/lit/lit/main.py
+++ b/utils/lit/lit/main.py
@@ -34,6 +34,10 @@ class TestingProgressDisplay(object):
def update(self, test):
self.completed += 1
+
+ if self.opts.incremental:
+ update_incremental_cache(test)
+
if self.progressBar:
self.progressBar.update(float(self.completed)/self.numTests,
test.getFullName())
@@ -108,6 +112,24 @@ def write_test_results(run, lit_config, testing_time, output_path):
finally:
f.close()
+def update_incremental_cache(test):
+ if not test.result.code.isFailure:
+ return
+ fname = test.getFilePath()
+ os.utime(fname, None)
+
+def sort_by_incremental_cache(run, litConfig):
+ def sortIndex(test):
+ index = 0
+ fname = test.getFilePath()
+ try:
+ index = -os.path.getmtime(fname)
+ except os.error as e:
+ if litConfig.debug:
+ litConfig.note(e)
+ return index
+ run.tests.sort(key = lambda t: sortIndex(t))
+
def main(builtinParameters = {}):
# Use processes by default on Unix platforms.
isWindows = platform.system() == 'Windows'
@@ -179,6 +201,10 @@ def main(builtinParameters = {}):
group.add_option("", "--shuffle", dest="shuffle",
help="Run tests in random order",
action="store_true", default=False)
+ group.add_option("-i", "--incremental", dest="incremental",
+ help="Run modified and failing tests first (updates "
+ "mtimes)",
+ action="store_true", default=False)
group.add_option("", "--filter", dest="filter", metavar="REGEX",
help=("Only run tests with paths matching the given "
"regular expression"),
@@ -292,6 +318,8 @@ def main(builtinParameters = {}):
# Then select the order.
if opts.shuffle:
random.shuffle(run.tests)
+ elif opts.incremental:
+ sort_by_incremental_cache(run, litConfig)
else:
run.tests.sort(key = lambda t: t.getFullName())