summaryrefslogtreecommitdiffstats
path: root/llvm/utils
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils')
-rw-r--r--llvm/utils/lit/lit/Test.py16
-rw-r--r--llvm/utils/lit/lit/TestRunner.py54
-rw-r--r--llvm/utils/lit/lit/run.py20
3 files changed, 51 insertions, 39 deletions
diff --git a/llvm/utils/lit/lit/Test.py b/llvm/utils/lit/lit/Test.py
index 1a9e3fe80fb..dc82670358a 100644
--- a/llvm/utils/lit/lit/Test.py
+++ b/llvm/utils/lit/lit/Test.py
@@ -172,7 +172,7 @@ class TestSuite:
return os.path.join(self.source_root, *components)
def getExecPath(self, components):
- return os.path.join(self.exec_root, *components)
+ return os.path.join(self.exec_root, "Output", *components)
class Test:
"""Test - Information on a single test instance."""
@@ -222,10 +222,13 @@ class Test:
# Syntax error in an XFAIL line.
self.result.code = UNRESOLVED
self.result.output = str(e)
-
+
def getFullName(self):
return self.suite.config.name + ' :: ' + '/'.join(self.path_in_suite)
+ def getTestBaseName(self):
+ return self.path_in_suite[-1]
+
def getFilePath(self):
if self.file_path:
return self.file_path
@@ -234,8 +237,11 @@ class Test:
def getSourcePath(self):
return self.suite.getSourcePath(self.path_in_suite)
- def getExecPath(self):
- return self.suite.getExecPath(self.path_in_suite)
+ def getTempFilePrefix(self):
+ return self.suite.getExecPath(self.path_in_suite) + ".tmp"
+
+ def getTempFileDir(self):
+ return os.path.dirname(self.getTempFilePrefix())
def isExpectedToFail(self):
"""
@@ -347,7 +353,7 @@ class Test:
safe_name = self.suite.name.replace(".","-")
if safe_test_path:
- class_name = safe_name + "." + "/".join(safe_test_path)
+ class_name = safe_name + "." + "/".join(safe_test_path)
else:
class_name = safe_name + "." + safe_name
diff --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py
index 37b03cc19f8..e72be025308 100644
--- a/llvm/utils/lit/lit/TestRunner.py
+++ b/llvm/utils/lit/lit/TestRunner.py
@@ -123,7 +123,7 @@ class ShellCommandResult(object):
self.exitCode = exitCode
self.timeoutReached = timeoutReached
self.outputFiles = list(outputFiles)
-
+
def executeShCmd(cmd, shenv, results, timeout=0):
"""
Wrapper around _executeShCmd that handles
@@ -501,7 +501,7 @@ def _executeShCmd(cmd, shenv, results, timeoutHelper):
data = None
if data is not None:
output_files.append((name, path, data))
-
+
results.append(ShellCommandResult(
cmd.commands[i], out, err, res, timeoutHelper.timeoutReached(),
output_files))
@@ -573,7 +573,7 @@ def executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
else:
out += data
out += "\n"
-
+
if result.stdout.strip():
out += '# command output:\n%s\n' % (result.stdout,)
if result.stderr.strip():
@@ -690,37 +690,28 @@ def parseIntegratedTestScriptCommands(source_path, keywords):
finally:
f.close()
-def getTempPaths(test):
- """Get the temporary location, this is always relative to the test suite
- root, not test source root."""
- execpath = test.getExecPath()
- execdir,execbase = os.path.split(execpath)
- tmpDir = os.path.join(execdir, 'Output')
- tmpBase = os.path.join(tmpDir, execbase)
- return tmpDir, tmpBase
-
-def getDefaultSubstitutions(test, tmpDir, tmpBase, normalize_slashes=False):
+def getDefaultSubstitutions(test, normalize_slashes=False):
sourcepath = test.getSourcePath()
sourcedir = os.path.dirname(sourcepath)
+ tmpDir = test.getTempFileDir()
+ tmpPrefix = test.getTempFilePrefix()
+ baseName = test.getTestBaseName()
# Normalize slashes, if requested.
if normalize_slashes:
sourcepath = sourcepath.replace('\\', '/')
sourcedir = sourcedir.replace('\\', '/')
tmpDir = tmpDir.replace('\\', '/')
- tmpBase = tmpBase.replace('\\', '/')
# We use #_MARKER_# to hide %% while we do the other substitutions.
substitutions = []
substitutions.extend([('%%', '#_MARKER_#')])
substitutions.extend(test.config.substitutions)
- tmpName = tmpBase + '.tmp'
- baseName = os.path.basename(tmpBase)
substitutions.extend([('%s', sourcepath),
('%S', sourcedir),
('%p', sourcedir),
('%{pathsep}', os.pathsep),
- ('%t', tmpName),
+ ('%t', tmpPrefix),
('%basename_t', baseName),
('%T', tmpDir),
('#_MARKER_#', '%')])
@@ -730,7 +721,7 @@ def getDefaultSubstitutions(test, tmpDir, tmpBase, normalize_slashes=False):
('%/s', sourcepath.replace('\\', '/')),
('%/S', sourcedir.replace('\\', '/')),
('%/p', sourcedir.replace('\\', '/')),
- ('%/t', tmpBase.replace('\\', '/') + '.tmp'),
+ ('%/t', tmpPrefix.replace('\\', '/')),
('%/T', tmpDir.replace('\\', '/')),
])
@@ -740,7 +731,7 @@ def getDefaultSubstitutions(test, tmpDir, tmpBase, normalize_slashes=False):
('%:s', re.sub(r'^(.):', r'\1', sourcepath)),
('%:S', re.sub(r'^(.):', r'\1', sourcedir)),
('%:p', re.sub(r'^(.):', r'\1', sourcedir)),
- ('%:t', re.sub(r'^(.):', r'\1', tmpBase) + '.tmp'),
+ ('%:t', re.sub(r'^(.):', r'\1', tmpPrefix)),
('%:T', re.sub(r'^(.):', r'\1', tmpDir)),
])
else:
@@ -748,7 +739,7 @@ def getDefaultSubstitutions(test, tmpDir, tmpBase, normalize_slashes=False):
('%:s', sourcepath),
('%:S', sourcedir),
('%:p', sourcedir),
- ('%:t', tmpBase + '.tmp'),
+ ('%:t', tmpPrefix),
('%:T', tmpDir),
])
return substitutions
@@ -779,7 +770,7 @@ class ParserKind(object):
TAG: A keyword taking no value. Ex 'END.'
COMMAND: A keyword taking a list of shell commands. Ex 'RUN:'
LIST: A keyword taking a comma-separated list of values.
- BOOLEAN_EXPR: A keyword taking a comma-separated list of
+ BOOLEAN_EXPR: A keyword taking a comma-separated list of
boolean expressions. Ex 'XFAIL:'
CUSTOM: A keyword with custom parsing semantics.
"""
@@ -951,14 +942,14 @@ def parseIntegratedTestScript(test, additional_parsers=[],
IntegratedTestKeywordParser('REQUIRES:', ParserKind.BOOLEAN_EXPR,
initial_value=test.requires),
IntegratedTestKeywordParser('REQUIRES-ANY:', ParserKind.CUSTOM,
- IntegratedTestKeywordParser._handleRequiresAny,
- initial_value=test.requires),
+ IntegratedTestKeywordParser._handleRequiresAny,
+ initial_value=test.requires),
IntegratedTestKeywordParser('UNSUPPORTED:', ParserKind.BOOLEAN_EXPR,
initial_value=test.unsupported),
IntegratedTestKeywordParser('END.', ParserKind.TAG)
]
keyword_parsers = {p.keyword: p for p in builtin_parsers}
-
+
# Install user-defined additional parsers.
for parser in additional_parsers:
if not isinstance(parser, IntegratedTestKeywordParser):
@@ -968,7 +959,7 @@ def parseIntegratedTestScript(test, additional_parsers=[],
raise ValueError("Parser for keyword '%s' already exists"
% parser.keyword)
keyword_parsers[parser.keyword] = parser
-
+
# Collect the test lines from the script.
sourcepath = test.getSourcePath()
for line_number, command_type, ln in \
@@ -1014,12 +1005,8 @@ def parseIntegratedTestScript(test, additional_parsers=[],
return script
-
def _runShTest(test, litConfig, useExternalSh, script, tmpBase):
- # Create the output directory if it does not already exist.
- lit.util.mkdir_p(os.path.dirname(tmpBase))
-
- execdir = os.path.dirname(test.getExecPath())
+ execdir = os.path.dirname(test.getTempFileDir())
if useExternalSh:
res = executeScript(test, litConfig, tmpBase, script, execdir)
else:
@@ -1063,10 +1050,8 @@ def executeShTest(test, litConfig, useExternalSh,
return script
if litConfig.noExecute:
return lit.Test.Result(Test.PASS)
-
- tmpDir, tmpBase = getTempPaths(test)
substitutions = list(extra_substitutions)
- substitutions += getDefaultSubstitutions(test, tmpDir, tmpBase,
+ substitutions += getDefaultSubstitutions(test,
normalize_slashes=useExternalSh)
script = applySubstitutions(script, substitutions)
@@ -1075,7 +1060,8 @@ def executeShTest(test, litConfig, useExternalSh,
if hasattr(test.config, 'test_retry_attempts'):
attempts += test.config.test_retry_attempts
for i in range(attempts):
- res = _runShTest(test, litConfig, useExternalSh, script, tmpBase)
+ res = _runShTest(test, litConfig, useExternalSh, script,
+ test.getTempFilePrefix())
if res.code != Test.FAIL:
break
# If we had to run the test more than once, count it as a flaky pass. These
diff --git a/llvm/utils/lit/lit/run.py b/llvm/utils/lit/lit/run.py
index 1290c142c83..bdaf1415a1c 100644
--- a/llvm/utils/lit/lit/run.py
+++ b/llvm/utils/lit/lit/run.py
@@ -1,4 +1,5 @@
import os
+import shutil
import sys
import threading
import time
@@ -74,6 +75,25 @@ class Run(object):
if not self.tests or jobs == 0:
return
+ # Create fresh output directories for each test we're going to run.
+ # This guarantees that test runs will not remnants of previous test
+ # runs' output.
+ clean_paths = set()
+ for test in self.tests:
+ clean_paths.add(os.path.normpath(test.getTempFileDir()))
+ clean_paths = list(clean_paths)
+ # Sort by number of path components, to ensure that parent directories
+ # get deleted and re-created before child directories.
+ clean_paths.sort(key=lambda x: len(x.split(os.sep)))
+ for base in clean_paths:
+ if os.path.exists(base):
+ if not os.path.islink(base) and os.path.isdir(base):
+ shutil.rmtree(base, True)
+ else:
+ os.unlink(os.path)
+ if not os.path.exists(base):
+ lit.util.mkdir_p(base)
+
# Set up semaphores to limit parallelism of certain classes of tests.
# For example, some ASan tests require lots of virtual memory and run
# faster with less parallelism on OS X.
OpenPOWER on IntegriCloud