llvm.org GIT mirror llvm / 9ad6e33
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 Alp Toker 5 years ago
3 changed file(s) with 36 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
127127 class Test:
128128 """Test - Information on a single test instance."""
129129
130 def __init__(self, suite, path_in_suite, config):
130 def __init__(self, suite, path_in_suite, config, file_path = None):
131131 self.suite = suite
132132 self.path_in_suite = path_in_suite
133133 self.config = config
134 self.file_path = file_path
134135 # A list of conditions under which this test is expected to fail. These
135136 # can optionally be provided by test format handlers, and will be
136137 # honored when the test result is supplied.
155156
156157 def getFullName(self):
157158 return self.suite.config.name + ' :: ' + '/'.join(self.path_in_suite)
159
160 def getFilePath(self):
161 if self.file_path:
162 return self.file_path
163 return self.getSourcePath()
158164
159165 def getSourcePath(self):
160166 return self.suite.getSourcePath(self.path_in_suite)
6565 # Discover the tests in this executable.
6666 for testname in self.getGTestTests(execpath, litConfig, localConfig):
6767 testPath = path_in_suite + (basename, testname)
68 yield lit.Test.Test(testSuite, testPath, localConfig)
68 yield lit.Test.Test(testSuite, testPath, localConfig, file_path=execpath)
6969
7070 def getTestsInDirectory(self, testSuite, path_in_suite,
7171 litConfig, localConfig):
3333
3434 def update(self, test):
3535 self.completed += 1
36
37 if self.opts.incremental:
38 update_incremental_cache(test)
39
3640 if self.progressBar:
3741 self.progressBar.update(float(self.completed)/self.numTests,
3842 test.getFullName())
106110 f.write('\n')
107111 finally:
108112 f.close()
113
114 def update_incremental_cache(test):
115 if not test.result.code.isFailure:
116 return
117 fname = test.getFilePath()
118 os.utime(fname, None)
119
120 def sort_by_incremental_cache(run, litConfig):
121 def sortIndex(test):
122 index = 0
123 fname = test.getFilePath()
124 try:
125 index = -os.path.getmtime(fname)
126 except os.error as e:
127 if litConfig.debug:
128 litConfig.note(e)
129 return index
130 run.tests.sort(key = lambda t: sortIndex(t))
109131
110132 def main(builtinParameters = {}):
111133 # Use processes by default on Unix platforms.
177199 action="store", type=float, default=None)
178200 group.add_option("", "--shuffle", dest="shuffle",
179201 help="Run tests in random order",
202 action="store_true", default=False)
203 group.add_option("-i", "--incremental", dest="incremental",
204 help="Run modified and failing tests first (updates "
205 "mtimes)",
180206 action="store_true", default=False)
181207 group.add_option("", "--filter", dest="filter", metavar="REGEX",
182208 help=("Only run tests with paths matching the given "
291317 # Then select the order.
292318 if opts.shuffle:
293319 random.shuffle(run.tests)
320 elif opts.incremental:
321 sort_by_incremental_cache(run, litConfig)
294322 else:
295323 run.tests.sort(key = lambda t: t.getFullName())
296324