summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-08-20 21:02:43 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-08-20 21:02:43 +0000
commit15c5c77fa04cd97e1057e8a585f669fc49da0d92 (patch)
tree9047e00a30ccb7b81dbe7227c8c883cbafb5d2dd /utils
parent4e20bb0468b8d0db13287e666b482eb93689be99 (diff)
Notes
Diffstat (limited to 'utils')
-rw-r--r--utils/lit/lit/LitConfig.py2
-rw-r--r--utils/lit/lit/TestRunner.py2
-rw-r--r--utils/lit/lit/formats/__init__.py7
-rw-r--r--utils/lit/lit/formats/base.py157
-rw-r--r--utils/lit/lit/formats/shtest.py33
-rw-r--r--utils/lit/lit/run.py13
-rw-r--r--utils/lit/tests/Inputs/max-failures/lit.cfg6
-rw-r--r--utils/lit/tests/max-failures.py8
-rw-r--r--utils/lit/tests/selecting.py2
-rwxr-xr-xutils/release/test-release.sh21
10 files changed, 155 insertions, 96 deletions
diff --git a/utils/lit/lit/LitConfig.py b/utils/lit/lit/LitConfig.py
index 2ef0a8f77ec9..3351ebed54bd 100644
--- a/utils/lit/lit/LitConfig.py
+++ b/utils/lit/lit/LitConfig.py
@@ -25,7 +25,7 @@ class LitConfig(object):
params, config_prefix = None,
maxIndividualTestTime = 0,
maxFailures = None,
- parallelism_groups = [],
+ parallelism_groups = {},
echo_all_commands = False):
# The name of the test runner.
self.progname = progname
diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py
index 46bcac4b306e..a60a0f854870 100644
--- a/utils/lit/lit/TestRunner.py
+++ b/utils/lit/lit/TestRunner.py
@@ -313,7 +313,7 @@ def processRedirects(cmd, stdin_source, cmd_shenv, opened_files):
elif op == ('<',):
redirects[0] = [filename, 'r', None]
else:
- raise InternalShellError(cmd, "Unsupported redirect: %r" % (r,))
+ raise InternalShellError(cmd, "Unsupported redirect: %r" % ((op, filename),))
# Open file descriptors in a second pass.
std_fds = [None, None, None]
diff --git a/utils/lit/lit/formats/__init__.py b/utils/lit/lit/formats/__init__.py
index 7d14ca4b535a..3ff46e93ead2 100644
--- a/utils/lit/lit/formats/__init__.py
+++ b/utils/lit/lit/formats/__init__.py
@@ -1,3 +1,8 @@
-from lit.formats.base import TestFormat # noqa: F401
+from lit.formats.base import ( # noqa: F401
+ TestFormat,
+ FileBasedTest,
+ OneCommandPerFileTest
+)
+
from lit.formats.googletest import GoogleTest # noqa: F401
from lit.formats.shtest import ShTest # noqa: F401
diff --git a/utils/lit/lit/formats/base.py b/utils/lit/lit/formats/base.py
index baa9ff1d3b7d..6721d17e334e 100644
--- a/utils/lit/lit/formats/base.py
+++ b/utils/lit/lit/formats/base.py
@@ -1,50 +1,117 @@
-import abc
+from __future__ import absolute_import
+import os
+
+import lit.Test
+import lit.util
class TestFormat(object):
- """Base class for test formats.
-
- A TestFormat encapsulates logic for finding and executing a certain type of
- test. For example, a subclass FooTestFormat would contain the logic for
- finding tests written in the 'Foo' format, and the logic for running a
- single one.
-
- TestFormat is an Abstract Base Class (ABC). It uses the Python abc.ABCMeta
- type and associated @abc.abstractmethod decorator. Together, these provide
- subclass behaviour which is notionally similar to C++ pure virtual classes:
- only subclasses which implement all abstract methods can be instantiated
- (the implementation may come from an intermediate base).
-
- For details on ABCs, see: https://docs.python.org/2/library/abc.html. Note
- that Python ABCs have extensive abilities beyond what is used here. For
- TestFormat, we only care about enforcing that abstract methods are
- implemented.
- """
-
- __metaclass__ = abc.ABCMeta
-
- @abc.abstractmethod
- def getTestsInDirectory(self, testSuite, path_in_suite, litConfig,
- localConfig):
- """Finds tests of this format in the given directory.
-
- Args:
- testSuite: a Test.TestSuite object.
- path_in_suite: the subpath under testSuite to look for tests.
- litConfig: the LitConfig for the test suite.
- localConfig: a LitConfig with local specializations.
-
- Returns:
- An iterable of Test.Test objects.
- """
-
- @abc.abstractmethod
+ pass
+
+###
+
+class FileBasedTest(TestFormat):
+ def getTestsInDirectory(self, testSuite, path_in_suite,
+ litConfig, localConfig):
+ source_path = testSuite.getSourcePath(path_in_suite)
+ for filename in os.listdir(source_path):
+ # Ignore dot files and excluded tests.
+ if (filename.startswith('.') or
+ filename in localConfig.excludes):
+ continue
+
+ filepath = os.path.join(source_path, filename)
+ if not os.path.isdir(filepath):
+ base,ext = os.path.splitext(filename)
+ if ext in localConfig.suffixes:
+ yield lit.Test.Test(testSuite, path_in_suite + (filename,),
+ localConfig)
+
+###
+
+import re
+import tempfile
+
+class OneCommandPerFileTest(TestFormat):
+ # FIXME: Refactor into generic test for running some command on a directory
+ # of inputs.
+
+ def __init__(self, command, dir, recursive=False,
+ pattern=".*", useTempInput=False):
+ if isinstance(command, str):
+ self.command = [command]
+ else:
+ self.command = list(command)
+ if dir is not None:
+ dir = str(dir)
+ self.dir = dir
+ self.recursive = bool(recursive)
+ self.pattern = re.compile(pattern)
+ self.useTempInput = useTempInput
+
+ def getTestsInDirectory(self, testSuite, path_in_suite,
+ litConfig, localConfig):
+ dir = self.dir
+ if dir is None:
+ dir = testSuite.getSourcePath(path_in_suite)
+
+ for dirname,subdirs,filenames in os.walk(dir):
+ if not self.recursive:
+ subdirs[:] = []
+
+ subdirs[:] = [d for d in subdirs
+ if (d != '.svn' and
+ d not in localConfig.excludes)]
+
+ for filename in filenames:
+ if (filename.startswith('.') or
+ not self.pattern.match(filename) or
+ filename in localConfig.excludes):
+ continue
+
+ path = os.path.join(dirname,filename)
+ suffix = path[len(dir):]
+ if suffix.startswith(os.sep):
+ suffix = suffix[1:]
+ test = lit.Test.Test(
+ testSuite, path_in_suite + tuple(suffix.split(os.sep)),
+ localConfig)
+ # FIXME: Hack?
+ test.source_path = path
+ yield test
+
+ def createTempInput(self, tmp, test):
+ raise NotImplementedError('This is an abstract method.')
+
def execute(self, test, litConfig):
- """Runs the given 'test', which is of this format.
+ if test.config.unsupported:
+ return (lit.Test.UNSUPPORTED, 'Test is unsupported')
+
+ cmd = list(self.command)
+
+ # If using temp input, create a temporary file and hand it to the
+ # subclass.
+ if self.useTempInput:
+ tmp = tempfile.NamedTemporaryFile(suffix='.cpp')
+ self.createTempInput(tmp, test)
+ tmp.flush()
+ cmd.append(tmp.name)
+ elif hasattr(test, 'source_path'):
+ cmd.append(test.source_path)
+ else:
+ cmd.append(test.getSourcePath())
+
+ out, err, exitCode = lit.util.executeCommand(cmd)
+
+ diags = out + err
+ if not exitCode and not diags.strip():
+ return lit.Test.PASS,''
- Args:
- test: a Test.Test object describing the test to run.
- litConfig: the LitConfig for the test suite.
+ # Try to include some useful information.
+ report = """Command: %s\n""" % ' '.join(["'%s'" % a
+ for a in cmd])
+ if self.useTempInput:
+ report += """Temporary File: %s\n""" % tmp.name
+ report += "--\n%s--\n""" % open(tmp.name).read()
+ report += """Output:\n--\n%s--""" % diags
- Returns:
- A tuple of (status:Test.ResultCode, message:str)
- """
+ return lit.Test.FAIL, report
diff --git a/utils/lit/lit/formats/shtest.py b/utils/lit/lit/formats/shtest.py
index 01ecd192092e..fdc9bd0241f3 100644
--- a/utils/lit/lit/formats/shtest.py
+++ b/utils/lit/lit/formats/shtest.py
@@ -1,13 +1,12 @@
from __future__ import absolute_import
-import os
-
-import lit.Test
import lit.TestRunner
import lit.util
-from .base import TestFormat
-class ShTest(TestFormat):
+from .base import FileBasedTest
+
+
+class ShTest(FileBasedTest):
"""ShTest is a format with one file per test.
This is the primary format for regression tests as described in the LLVM
@@ -18,31 +17,9 @@ class ShTest(TestFormat):
The ShTest files contain some number of shell-like command pipelines, along
with assertions about what should be in the output.
"""
-
- def __init__(self, execute_external = False):
- """Initializer.
-
- The 'execute_external' argument controls whether lit uses its internal
- logic for command pipelines, or passes the command to a shell
- subprocess.
-
- Args:
- execute_external: (optional) If true, use shell subprocesses instead
- of lit's internal pipeline logic.
- """
+ def __init__(self, execute_external=False):
self.execute_external = execute_external
- def getTestsInDirectory(self, testSuite, path_in_suite,
- litConfig, localConfig):
- """Yields test files matching 'suffixes' from the localConfig."""
- file_matches = lit.util.listdir_files(
- testSuite.getSourcePath(path_in_suite),
- localConfig.suffixes, localConfig.excludes)
- for filename in file_matches:
- yield lit.Test.Test(testSuite, path_in_suite + (filename,),
- localConfig)
-
def execute(self, test, litConfig):
- """Interprets and runs the given test file, and returns the result."""
return lit.TestRunner.executeShTest(test, litConfig,
self.execute_external)
diff --git a/utils/lit/lit/run.py b/utils/lit/lit/run.py
index 1290c142c834..3e39bdb92203 100644
--- a/utils/lit/lit/run.py
+++ b/utils/lit/lit/run.py
@@ -44,6 +44,12 @@ class Run(object):
def __init__(self, lit_config, tests):
self.lit_config = lit_config
self.tests = tests
+ # 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.
+ self.parallelism_semaphores = \
+ {k: multiprocessing.Semaphore(v) for k, v in
+ self.lit_config.parallelism_groups.items()}
def execute_test(self, test):
return _execute_test_impl(test, self.lit_config,
@@ -74,13 +80,6 @@ class Run(object):
if not self.tests or jobs == 0:
return
- # 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.
- self.parallelism_semaphores = \
- {k: multiprocessing.Semaphore(v) for k, v in
- self.lit_config.parallelism_groups.items()}
-
# Install a console-control signal handler on Windows.
if win32api is not None:
def console_ctrl_handler(type):
diff --git a/utils/lit/tests/Inputs/max-failures/lit.cfg b/utils/lit/tests/Inputs/max-failures/lit.cfg
new file mode 100644
index 000000000000..50d07566e1cc
--- /dev/null
+++ b/utils/lit/tests/Inputs/max-failures/lit.cfg
@@ -0,0 +1,6 @@
+import lit.formats
+config.name = 'shtest-shell'
+config.suffixes = ['.txt']
+config.test_format = lit.formats.ShTest()
+config.test_source_root = os.path.dirname(__file__) + '/../shtest-shell'
+config.test_exec_root = None
diff --git a/utils/lit/tests/max-failures.py b/utils/lit/tests/max-failures.py
index 5cc258dd08aa..bc58e9a4e47f 100644
--- a/utils/lit/tests/max-failures.py
+++ b/utils/lit/tests/max-failures.py
@@ -1,9 +1,9 @@
# 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: not %{lit} -j 1 -v %{inputs}/max-failures > %t.out
+# RUN: not %{lit} --max-failures=1 -j 1 -v %{inputs}/max-failures >> %t.out
+# RUN: not %{lit} --max-failures=2 -j 1 -v %{inputs}/max-failures >> %t.out
+# RUN: not %{lit} --max-failures=0 -j 1 -v %{inputs}/max-failures 2>> %t.out
# RUN: FileCheck < %t.out %s
#
# END.
diff --git a/utils/lit/tests/selecting.py b/utils/lit/tests/selecting.py
index 19ba240f9b0f..4a0d08b860b8 100644
--- a/utils/lit/tests/selecting.py
+++ b/utils/lit/tests/selecting.py
@@ -9,7 +9,7 @@
# Check that regex-filtering based on environment variables work.
#
-# RUN: LIT_FILTER='o[a-z]e' %{lit} %{inputs}/discovery | FileCheck --check-prefix=CHECK-FILTER-ENV %s
+# RUN: env LIT_FILTER='o[a-z]e' %{lit} %{inputs}/discovery | FileCheck --check-prefix=CHECK-FILTER-ENV %s
# CHECK-FILTER-ENV: Testing: 2 of 5 tests
diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh
index 02d8e7925f6e..66a2c578083e 100755
--- a/utils/release/test-release.sh
+++ b/utils/release/test-release.sh
@@ -403,14 +403,6 @@ function test_llvmCore() {
fi
if [ $do_test_suite = 'yes' ]; then
- SandboxDir="$BuildDir/sandbox"
- Lit=$SandboxDir/bin/lit
- TestSuiteBuildDir="$BuildDir/test-suite-build"
- TestSuiteSrcDir="$BuildDir/test-suite.src"
-
- virtualenv $SandboxDir
- $SandboxDir/bin/python $BuildDir/llvm.src/utils/lit/setup.py install
- mkdir -p $TestSuiteBuildDir
cd $TestSuiteBuildDir
env CC="$c_compiler" CXX="$cxx_compiler" \
cmake $TestSuiteSrcDir -DTEST_SUITE_LIT=$Lit
@@ -466,6 +458,19 @@ if [ "$do_checkout" = "yes" ]; then
export_sources
fi
+# Setup the test-suite. Do this early so we can catch failures before
+# we do the full 3 stage build.
+if [ $do_test_suite = "yes" ]; then
+ SandboxDir="$BuildDir/sandbox"
+ Lit=$SandboxDir/bin/lit
+ TestSuiteBuildDir="$BuildDir/test-suite-build"
+ TestSuiteSrcDir="$BuildDir/test-suite.src"
+
+ virtualenv $SandboxDir
+ $SandboxDir/bin/python $BuildDir/llvm.src/utils/lit/setup.py install
+ mkdir -p $TestSuiteBuildDir
+fi
+
(
Flavors="Release"
if [ "$do_debug" = "yes" ]; then