OSDN Git Service

[lit] Add a --max-failures option.
authorDaniel Dunbar <daniel@zuster.org>
Mon, 26 Sep 2016 23:38:23 +0000 (23:38 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Mon, 26 Sep 2016 23:38:23 +0000 (23:38 +0000)
 - This is primarily useful as a "fail fast" mode for lit, where it will stop
   running tests after the first failure.

 - Patch by Max Moiseev.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282452 91177308-0d34-0410-b5e6-96231b3b80d8

utils/lit/lit/LitConfig.py
utils/lit/lit/main.py
utils/lit/lit/run.py
utils/lit/tests/max-failures.py [new file with mode: 0644]

index f5d41b1..c26c08e 100644 (file)
@@ -23,7 +23,8 @@ class LitConfig(object):
                  useValgrind, valgrindLeakCheck, valgrindArgs,
                  noExecute, debug, isWindows,
                  params, config_prefix = None,
-                 maxIndividualTestTime = 0):
+                 maxIndividualTestTime = 0,
+                 maxFailures = None):
         # The name of the test runner.
         self.progname = progname
         # The items to add to the PATH environment variable.
@@ -60,6 +61,7 @@ class LitConfig(object):
             self.valgrindArgs.extend(self.valgrindUserArgs)
 
         self.maxIndividualTestTime = maxIndividualTestTime
+        self.maxFailures = maxFailures
 
     @property
     def maxIndividualTestTime(self):
index ad5416e..53f026d 100755 (executable)
@@ -232,6 +232,9 @@ def main_with_tmp(builtinParameters):
                      help="Maximum time to spend running a single test (in seconds)."
                      "0 means no time limit. [Default: 0]",
                     type=int, default=None)
+    group.add_option("", "--max-failures", dest="maxFailures",
+                     help="Stop execution after the given number of failures.",
+                     action="store", type=int, default=None)
     parser.add_option_group(group)
 
     group = OptionGroup(parser, "Test Selection")
@@ -291,6 +294,9 @@ def main_with_tmp(builtinParameters):
        else:
                opts.numThreads = 1
 
+    if opts.maxFailures == 0:
+        parser.error("Setting --max-failures to 0 does not have any effect.")
+
     inputs = args
 
     # Create the user defined parameters.
@@ -324,7 +330,8 @@ def main_with_tmp(builtinParameters):
         isWindows = isWindows,
         params = userParams,
         config_prefix = opts.configPrefix,
-        maxIndividualTestTime = maxIndividualTestTime)
+        maxIndividualTestTime = maxIndividualTestTime,
+        maxFailures = opts.maxFailures)
 
     # Perform test discovery.
     run = lit.run.Run(litConfig,
@@ -477,7 +484,8 @@ def main_with_tmp(builtinParameters):
                        ('Expected Failing Tests', lit.Test.XFAIL),
                        ('Timed Out Tests', lit.Test.TIMEOUT)):
         if (lit.Test.XFAIL == code and not opts.show_xfail) or \
-           (lit.Test.UNSUPPORTED == code and not opts.show_unsupported):
+           (lit.Test.UNSUPPORTED == code and not opts.show_unsupported) or \
+           (lit.Test.UNRESOLVED == code and (opts.maxFailures is not None)):
             continue
         elts = byCode.get(code)
         if not elts:
index bbf644e..6bcca01 100644 (file)
@@ -152,6 +152,19 @@ def run_one_tester(run, provider, display):
 
 ###
 
+def handleFailures(provider, consumer, maxFailures):
+    class _Display(object):
+        def __init__(self, display):
+            self.display = display
+            self.maxFailures = maxFailures or object()
+            self.failedCount = 0
+        def update(self, test):
+            self.display.update(test)
+            self.failedCount += (test.result.code == lit.Test.FAIL)
+            if self.failedCount == self.maxFailures:
+                provider.cancel()
+    consumer.display = _Display(consumer.display)
+
 class Run(object):
     """
     This class represents a concrete, configured testing run.
@@ -232,6 +245,7 @@ class Run(object):
 
         # Create the test provider.
         provider = TestProvider(queue_impl, canceled_flag)
+        handleFailures(provider, consumer, self.lit_config.maxFailures)
 
         # Queue the tests outside the main thread because we can't guarantee
         # that we can put() all the tests without blocking:
diff --git a/utils/lit/tests/max-failures.py b/utils/lit/tests/max-failures.py
new file mode 100644 (file)
index 0000000..5cc258d
--- /dev/null
@@ -0,0 +1,14 @@
+# Check the behavior of --max-failures option.
+#
+# RUN: not %{lit} -j 1 -v %{inputs}/shtest-shell > %t.out
+# RUN: not %{lit} --max-failures=1 -j 1 -v %{inputs}/shtest-shell >> %t.out
+# RUN: not %{lit} --max-failures=2 -j 1 -v %{inputs}/shtest-shell >> %t.out
+# RUN: not %{lit} --max-failures=0 -j 1 -v %{inputs}/shtest-shell 2>> %t.out
+# RUN: FileCheck < %t.out %s
+#
+# END.
+
+# CHECK: Failing Tests (3)
+# CHECK: Failing Tests (1)
+# CHECK: Failing Tests (2)
+# CHECK: error: Setting --max-failures to 0 does not have any effect.