Use pipefail when available.

This change makes test with RUN lines like
RUN: opt ... | FileCheck

fail if opt fails, even if it prints what FileCheck wants. Enabling this
found some interesting cases of broken tests that were not being noticed
because opt (or some other tool) was crashing late.

Pipefail is used when the shell supports it or when using the internal
python based tester.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187261 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2013-07-26 22:32:58 +00:00
parent e7e612f22f
commit c1bb2d4325
6 changed files with 18 additions and 3 deletions

View File

@ -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
~~~~~~~~~~~~~~

View File

@ -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.

2
test/Other/pipefail.txt Normal file
View File

@ -0,0 +1,2 @@
REQUIRES: shell
RUN: ((false | true) && echo true || echo false) | grep false

View File

@ -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()

View File

@ -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()

View File

@ -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?