summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/CommandGuide/lit.rst4
-rw-r--r--docs/ReleaseNotes.rst4
-rw-r--r--test/Other/pipefail.txt2
-rw-r--r--utils/lit/lit/ShUtil.py5
-rw-r--r--utils/lit/lit/TestRunner.py5
-rw-r--r--utils/lit/lit/TestingConfig.py1
6 files changed, 18 insertions, 3 deletions
diff --git a/docs/CommandGuide/lit.rst b/docs/CommandGuide/lit.rst
index 2f6d9a1556..a4681fb34c 100644
--- a/docs/CommandGuide/lit.rst
+++ b/docs/CommandGuide/lit.rst
@@ -316,6 +316,10 @@ executed, two important global variables are predefined:
*on_clone* function will generally modify), and (3) the test path to the new
directory being scanned.
+ **pipefail** Normally a test using a shell pipe fails if any of the commands
+ on the pipe fail. If this is not desired, setting this variable to false
+ makes the test fail only if the last command in the pipe fails.
+
TEST DISCOVERY
~~~~~~~~~~~~~~
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 93f12e5974..e776dce29a 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -41,6 +41,10 @@ Non-comprehensive list of changes in this release
functionality, or simply have a lot to talk about), see the `NOTE` below
for adding a new subsection.
+* The regression tests now fail if any command in a pipe fails. To disable it in
+ a directory, just add ``config.pipefail = False`` to its ``lit.local.cfg``.
+ See :doc:`Lit <CommandGuide/lit>` for the details.
+
* Support for exception handling has been removed from the old JIT. Use MCJIT
if you need EH support.
diff --git a/test/Other/pipefail.txt b/test/Other/pipefail.txt
new file mode 100644
index 0000000000..241080aab6
--- /dev/null
+++ b/test/Other/pipefail.txt
@@ -0,0 +1,2 @@
+REQUIRES: shell
+RUN: ((false | true) && echo true || echo false) | grep false
diff --git a/utils/lit/lit/ShUtil.py b/utils/lit/lit/ShUtil.py
index 50f7910319..00bb40255c 100644
--- a/utils/lit/lit/ShUtil.py
+++ b/utils/lit/lit/ShUtil.py
@@ -166,8 +166,9 @@ class ShLexer:
###
class ShParser:
- def __init__(self, data, win32Escapes = False):
+ def __init__(self, data, win32Escapes = False, pipefail = False):
self.data = data
+ self.pipefail = pipefail
self.tokens = ShLexer(data, win32Escapes = win32Escapes).lex()
def lex(self):
@@ -224,7 +225,7 @@ class ShParser:
while self.look() == ('|',):
self.lex()
commands.append(self.parse_command())
- return Pipeline(commands, negate)
+ return Pipeline(commands, negate, self.pipefail)
def parse(self):
lhs = self.parse_pipeline()
diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py
index 84176996a8..daa9b7dfbb 100644
--- a/utils/lit/lit/TestRunner.py
+++ b/utils/lit/lit/TestRunner.py
@@ -245,7 +245,8 @@ def executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
cmds = []
for ln in commands:
try:
- cmds.append(ShUtil.ShParser(ln, litConfig.isWindows).parse())
+ cmds.append(ShUtil.ShParser(ln, litConfig.isWindows,
+ test.config.pipefail).parse())
except:
return (Test.FAIL, "shell parser error on: %r" % ln)
@@ -284,6 +285,8 @@ def executeScript(test, litConfig, tmpBase, commands, cwd):
if isWin32CMDEXE:
f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
else:
+ if test.config.pipefail:
+ f.write('set -o pipefail;')
f.write('{ ' + '; } &&\n{ '.join(commands) + '; }')
f.write('\n')
f.close()
diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py
index a1f79a3bfc..5d5832e9bb 100644
--- a/utils/lit/lit/TestingConfig.py
+++ b/utils/lit/lit/TestingConfig.py
@@ -92,6 +92,7 @@ class TestingConfig:
self.test_source_root = test_source_root
self.excludes = set(excludes)
self.available_features = set(available_features)
+ self.pipefail = True
def clone(self, path):
# FIXME: Chain implementations?