From 40c67b5832877935a555fc63bfaa735332c79700 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Sun, 15 Nov 2009 01:02:09 +0000 Subject: [PATCH] lit: Add --repeat=N option, for running each test N times. - Currently just useful for timing, although it could be extended as one (bad) way to deal with flaky tests. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@88827 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CommandGuide/lit.pod | 5 +++++ utils/lit/Test.py | 8 ++++++++ utils/lit/TestRunner.py | 2 ++ utils/lit/lit.py | 21 +++++++++++++++++---- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/docs/CommandGuide/lit.pod b/docs/CommandGuide/lit.pod index 1650742cea6..246fc66aa6d 100644 --- a/docs/CommandGuide/lit.pod +++ b/docs/CommandGuide/lit.pod @@ -149,6 +149,11 @@ List the discovered test suites as part of the standard output. Run Tcl scripts internally (instead of converting to shell scripts). +=item B<--repeat>=I + +Run each test I times. Currently this is primarily useful for timing tests, +other results are not collated in any reasonable fashion. + =back =head1 EXIT STATUS diff --git a/utils/lit/Test.py b/utils/lit/Test.py index d3f627456f8..1f6556ba859 100644 --- a/utils/lit/Test.py +++ b/utils/lit/Test.py @@ -54,6 +54,14 @@ class Test: self.output = None # The wall time to execute this test, if timing and once complete. self.elapsed = None + # The repeat index of this test, or None. + self.index = None + + def copyWithIndex(self, index): + import copy + res = copy.copy(self) + res.index = index + return res def setResult(self, result, output, elapsed): assert self.result is None, "Test result already set!" diff --git a/utils/lit/TestRunner.py b/utils/lit/TestRunner.py index 5b4538f7d29..20fbc6c13a9 100644 --- a/utils/lit/TestRunner.py +++ b/utils/lit/TestRunner.py @@ -367,6 +367,8 @@ def parseIntegratedTestScript(test): execpath = test.getExecPath() execdir,execbase = os.path.split(execpath) tmpBase = os.path.join(execdir, 'Output', execbase) + if test.index is not None: + tmpBase += '_%d' % test.index # We use #_MARKER_# to hide %% while we do the other substitutions. substitutions = [('%%', '#_MARKER_#')] diff --git a/utils/lit/lit.py b/utils/lit/lit.py index 70bd0605794..dcdce7d5c3c 100755 --- a/utils/lit/lit.py +++ b/utils/lit/lit.py @@ -388,6 +388,9 @@ def main(): group.add_option("", "--no-tcl-as-sh", dest="useTclAsSh", help="Don't run Tcl scripts using 'sh'", action="store_false", default=True) + group.add_option("", "--repeat", dest="repeatTests", metavar="N", + help="Repeat tests N times (for timing)", + action="store", default=None, type=int) parser.add_option_group(group) (opts, args) = parser.parse_args() @@ -472,6 +475,11 @@ def main(): header = '-- Testing: %d%s tests, %d threads --'%(len(tests),extra, opts.numThreads) + if opts.repeatTests: + tests = [t.copyWithIndex(i) + for t in tests + for i in range(opts.repeatTests)] + progressBar = None if not opts.quiet: if opts.succinct and opts.useProgressBar: @@ -524,11 +532,16 @@ def main(): print if opts.timeTests: - byTime = list(tests) - byTime.sort(key = lambda t: t.elapsed) + # Collate, in case we repeated tests. + times = {} + for t in tests: + key = t.getFullName() + times[key] = times.get(key, 0.) + t.elapsed + + byTime = list(times.items()) + byTime.sort(key = lambda (name,elapsed): elapsed) if byTime: - Util.printHistogram([(t.getFullName(), t.elapsed) for t in byTime], - title='Tests') + Util.printHistogram(byTime, title='Tests') for name,code in (('Expected Passes ', Test.PASS), ('Expected Failures ', Test.XFAIL),