Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 4e549e7

Browse files
committed
Merging r309044, r309071, r309120, r309122, r309140 and r309227 (PR34157)
------------------------------------------------------------------------ r309044 | mgorny | 2017-07-25 15:38:31 -0700 (Tue, 25 Jul 2017) | 14 lines [lit] Fix UnboundLocalError for invalid shtest redirects Replace the incorrect variable reference when invalid redirect is used. This fixes the following issue: File "/usr/src/llvm/utils/lit/lit/TestRunner.py", line 316, in processRedirects raise InternalShellError(cmd, "Unsupported redirect: %r" % (r,)) UnboundLocalError: local variable 'r' referenced before assignment which in turn broke shtest-shell.py and max-failures.py lit tests. The breakage was introduced during refactoring in rL307310. Differential Revision: https://reviews.llvm.org/D35857 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r309071 | rnk | 2017-07-25 18:27:18 -0700 (Tue, 25 Jul 2017) | 1 line [lit] Attempt to fix Python unittest adaptor logic ------------------------------------------------------------------------ ------------------------------------------------------------------------ r309120 | modocache | 2017-07-26 07:59:36 -0700 (Wed, 26 Jul 2017) | 36 lines Revert "[lit] Remove dead code not referenced in the LLVM SVN repo." Summary: This reverts rL306623, which removed `FileBasedTest`, an abstract base class, but did not also remove the usages of that class in the lit unit tests. The revert fixes four test failures in the lit unit test suite. Test plan: As per the instructions in `utils/lit/README.txt`, run the lit unit test suite: ``` utils/lit/lit.py \ --path /path/to/your/llvm/build/bin \ utils/lit/tests ``` Verify that the following tests fail before applying this patch, and pass once the patch is applied: ``` lit :: test-data.py lit :: test-output.py lit :: xunit-output.py ``` In addition, run `check-llvm` to make sure the existing LLVM test suite executes normally. Reviewers: george.karpenkov, mgorny, dlj Reviewed By: mgorny Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D35877 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r309122 | modocache | 2017-07-26 08:02:05 -0700 (Wed, 26 Jul 2017) | 32 lines [lit] Fix type error for parallelism groups Summary: Whereas rL299560 and rL309071 call `parallelism_groups.items()`, under the assumption that `parallelism_groups` is a `dict` type, the default parameter for that attribute is a `list`. Change the default to a `dict` for type correctness. This regression in the unit tests would have been caught if the unit tests were being run continously. It also would have been caught if the lit project used a Python type checker such as `mypy`. Test Plan: As per the instructions in `utils/lit/README.txt`, run the lit unit test suite: ``` utils/lit/lit.py \ --path /path/to/your/llvm/build/bin \ utils/lit/tests ``` Verify that the test `lit :: unit/TestRunner.py` fails before applying this patch, but passes once this patch is applied. Reviewers: mgorny, rnk, rafael Reviewed By: mgorny Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D35878 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r309140 | george.karpenkov | 2017-07-26 10:19:36 -0700 (Wed, 26 Jul 2017) | 3 lines Fix LIT test breakage Differential Revision: https://reviews.llvm.org/D35867 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r309227 | rnk | 2017-07-26 15:57:32 -0700 (Wed, 26 Jul 2017) | 4 lines [lit] Fix race between shtest-shell and max-failures tests Previously these tests would use the same Output directory leading to flaky non-deterministic failures. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_50@310730 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 05ef777 commit 4e549e7

File tree

9 files changed

+142
-88
lines changed

9 files changed

+142
-88
lines changed

utils/lit/lit/LitConfig.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def __init__(self, progname, path, quiet,
2525
params, config_prefix = None,
2626
maxIndividualTestTime = 0,
2727
maxFailures = None,
28-
parallelism_groups = [],
28+
parallelism_groups = {},
2929
echo_all_commands = False):
3030
# The name of the test runner.
3131
self.progname = progname

utils/lit/lit/TestRunner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ def processRedirects(cmd, stdin_source, cmd_shenv, opened_files):
313313
elif op == ('<',):
314314
redirects[0] = [filename, 'r', None]
315315
else:
316-
raise InternalShellError(cmd, "Unsupported redirect: %r" % (r,))
316+
raise InternalShellError(cmd, "Unsupported redirect: %r" % ((op, filename),))
317317

318318
# Open file descriptors in a second pass.
319319
std_fds = [None, None, None]

utils/lit/lit/formats/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1-
from lit.formats.base import TestFormat # noqa: F401
1+
from lit.formats.base import ( # noqa: F401
2+
TestFormat,
3+
FileBasedTest,
4+
OneCommandPerFileTest
5+
)
6+
27
from lit.formats.googletest import GoogleTest # noqa: F401
38
from lit.formats.shtest import ShTest # noqa: F401

utils/lit/lit/formats/base.py

Lines changed: 112 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,117 @@
1-
import abc
1+
from __future__ import absolute_import
2+
import os
3+
4+
import lit.Test
5+
import lit.util
26

37
class TestFormat(object):
4-
"""Base class for test formats.
5-
6-
A TestFormat encapsulates logic for finding and executing a certain type of
7-
test. For example, a subclass FooTestFormat would contain the logic for
8-
finding tests written in the 'Foo' format, and the logic for running a
9-
single one.
10-
11-
TestFormat is an Abstract Base Class (ABC). It uses the Python abc.ABCMeta
12-
type and associated @abc.abstractmethod decorator. Together, these provide
13-
subclass behaviour which is notionally similar to C++ pure virtual classes:
14-
only subclasses which implement all abstract methods can be instantiated
15-
(the implementation may come from an intermediate base).
16-
17-
For details on ABCs, see: https://docs.python.org/2/library/abc.html. Note
18-
that Python ABCs have extensive abilities beyond what is used here. For
19-
TestFormat, we only care about enforcing that abstract methods are
20-
implemented.
21-
"""
22-
23-
__metaclass__ = abc.ABCMeta
24-
25-
@abc.abstractmethod
26-
def getTestsInDirectory(self, testSuite, path_in_suite, litConfig,
27-
localConfig):
28-
"""Finds tests of this format in the given directory.
29-
30-
Args:
31-
testSuite: a Test.TestSuite object.
32-
path_in_suite: the subpath under testSuite to look for tests.
33-
litConfig: the LitConfig for the test suite.
34-
localConfig: a LitConfig with local specializations.
35-
36-
Returns:
37-
An iterable of Test.Test objects.
38-
"""
39-
40-
@abc.abstractmethod
8+
pass
9+
10+
###
11+
12+
class FileBasedTest(TestFormat):
13+
def getTestsInDirectory(self, testSuite, path_in_suite,
14+
litConfig, localConfig):
15+
source_path = testSuite.getSourcePath(path_in_suite)
16+
for filename in os.listdir(source_path):
17+
# Ignore dot files and excluded tests.
18+
if (filename.startswith('.') or
19+
filename in localConfig.excludes):
20+
continue
21+
22+
filepath = os.path.join(source_path, filename)
23+
if not os.path.isdir(filepath):
24+
base,ext = os.path.splitext(filename)
25+
if ext in localConfig.suffixes:
26+
yield lit.Test.Test(testSuite, path_in_suite + (filename,),
27+
localConfig)
28+
29+
###
30+
31+
import re
32+
import tempfile
33+
34+
class OneCommandPerFileTest(TestFormat):
35+
# FIXME: Refactor into generic test for running some command on a directory
36+
# of inputs.
37+
38+
def __init__(self, command, dir, recursive=False,
39+
pattern=".*", useTempInput=False):
40+
if isinstance(command, str):
41+
self.command = [command]
42+
else:
43+
self.command = list(command)
44+
if dir is not None:
45+
dir = str(dir)
46+
self.dir = dir
47+
self.recursive = bool(recursive)
48+
self.pattern = re.compile(pattern)
49+
self.useTempInput = useTempInput
50+
51+
def getTestsInDirectory(self, testSuite, path_in_suite,
52+
litConfig, localConfig):
53+
dir = self.dir
54+
if dir is None:
55+
dir = testSuite.getSourcePath(path_in_suite)
56+
57+
for dirname,subdirs,filenames in os.walk(dir):
58+
if not self.recursive:
59+
subdirs[:] = []
60+
61+
subdirs[:] = [d for d in subdirs
62+
if (d != '.svn' and
63+
d not in localConfig.excludes)]
64+
65+
for filename in filenames:
66+
if (filename.startswith('.') or
67+
not self.pattern.match(filename) or
68+
filename in localConfig.excludes):
69+
continue
70+
71+
path = os.path.join(dirname,filename)
72+
suffix = path[len(dir):]
73+
if suffix.startswith(os.sep):
74+
suffix = suffix[1:]
75+
test = lit.Test.Test(
76+
testSuite, path_in_suite + tuple(suffix.split(os.sep)),
77+
localConfig)
78+
# FIXME: Hack?
79+
test.source_path = path
80+
yield test
81+
82+
def createTempInput(self, tmp, test):
83+
raise NotImplementedError('This is an abstract method.')
84+
4185
def execute(self, test, litConfig):
42-
"""Runs the given 'test', which is of this format.
86+
if test.config.unsupported:
87+
return (lit.Test.UNSUPPORTED, 'Test is unsupported')
88+
89+
cmd = list(self.command)
90+
91+
# If using temp input, create a temporary file and hand it to the
92+
# subclass.
93+
if self.useTempInput:
94+
tmp = tempfile.NamedTemporaryFile(suffix='.cpp')
95+
self.createTempInput(tmp, test)
96+
tmp.flush()
97+
cmd.append(tmp.name)
98+
elif hasattr(test, 'source_path'):
99+
cmd.append(test.source_path)
100+
else:
101+
cmd.append(test.getSourcePath())
102+
103+
out, err, exitCode = lit.util.executeCommand(cmd)
104+
105+
diags = out + err
106+
if not exitCode and not diags.strip():
107+
return lit.Test.PASS,''
43108

44-
Args:
45-
test: a Test.Test object describing the test to run.
46-
litConfig: the LitConfig for the test suite.
109+
# Try to include some useful information.
110+
report = """Command: %s\n""" % ' '.join(["'%s'" % a
111+
for a in cmd])
112+
if self.useTempInput:
113+
report += """Temporary File: %s\n""" % tmp.name
114+
report += "--\n%s--\n""" % open(tmp.name).read()
115+
report += """Output:\n--\n%s--""" % diags
47116

48-
Returns:
49-
A tuple of (status:Test.ResultCode, message:str)
50-
"""
117+
return lit.Test.FAIL, report

utils/lit/lit/formats/shtest.py

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
from __future__ import absolute_import
22

3-
import os
4-
5-
import lit.Test
63
import lit.TestRunner
74
import lit.util
8-
from .base import TestFormat
95

10-
class ShTest(TestFormat):
6+
from .base import FileBasedTest
7+
8+
9+
class ShTest(FileBasedTest):
1110
"""ShTest is a format with one file per test.
1211
1312
This is the primary format for regression tests as described in the LLVM
@@ -18,31 +17,9 @@ class ShTest(TestFormat):
1817
The ShTest files contain some number of shell-like command pipelines, along
1918
with assertions about what should be in the output.
2019
"""
21-
22-
def __init__(self, execute_external = False):
23-
"""Initializer.
24-
25-
The 'execute_external' argument controls whether lit uses its internal
26-
logic for command pipelines, or passes the command to a shell
27-
subprocess.
28-
29-
Args:
30-
execute_external: (optional) If true, use shell subprocesses instead
31-
of lit's internal pipeline logic.
32-
"""
20+
def __init__(self, execute_external=False):
3321
self.execute_external = execute_external
3422

35-
def getTestsInDirectory(self, testSuite, path_in_suite,
36-
litConfig, localConfig):
37-
"""Yields test files matching 'suffixes' from the localConfig."""
38-
file_matches = lit.util.listdir_files(
39-
testSuite.getSourcePath(path_in_suite),
40-
localConfig.suffixes, localConfig.excludes)
41-
for filename in file_matches:
42-
yield lit.Test.Test(testSuite, path_in_suite + (filename,),
43-
localConfig)
44-
4523
def execute(self, test, litConfig):
46-
"""Interprets and runs the given test file, and returns the result."""
4724
return lit.TestRunner.executeShTest(test, litConfig,
4825
self.execute_external)

utils/lit/lit/run.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ class Run(object):
4444
def __init__(self, lit_config, tests):
4545
self.lit_config = lit_config
4646
self.tests = tests
47+
# Set up semaphores to limit parallelism of certain classes of tests.
48+
# For example, some ASan tests require lots of virtual memory and run
49+
# faster with less parallelism on OS X.
50+
self.parallelism_semaphores = \
51+
{k: multiprocessing.Semaphore(v) for k, v in
52+
self.lit_config.parallelism_groups.items()}
4753

4854
def execute_test(self, test):
4955
return _execute_test_impl(test, self.lit_config,
@@ -74,13 +80,6 @@ def execute_tests(self, display, jobs, max_time=None):
7480
if not self.tests or jobs == 0:
7581
return
7682

77-
# Set up semaphores to limit parallelism of certain classes of tests.
78-
# For example, some ASan tests require lots of virtual memory and run
79-
# faster with less parallelism on OS X.
80-
self.parallelism_semaphores = \
81-
{k: multiprocessing.Semaphore(v) for k, v in
82-
self.lit_config.parallelism_groups.items()}
83-
8483
# Install a console-control signal handler on Windows.
8584
if win32api is not None:
8685
def console_ctrl_handler(type):
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import lit.formats
2+
config.name = 'shtest-shell'
3+
config.suffixes = ['.txt']
4+
config.test_format = lit.formats.ShTest()
5+
config.test_source_root = os.path.dirname(__file__) + '/../shtest-shell'
6+
config.test_exec_root = None

utils/lit/tests/max-failures.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Check the behavior of --max-failures option.
22
#
3-
# RUN: not %{lit} -j 1 -v %{inputs}/shtest-shell > %t.out
4-
# RUN: not %{lit} --max-failures=1 -j 1 -v %{inputs}/shtest-shell >> %t.out
5-
# RUN: not %{lit} --max-failures=2 -j 1 -v %{inputs}/shtest-shell >> %t.out
6-
# RUN: not %{lit} --max-failures=0 -j 1 -v %{inputs}/shtest-shell 2>> %t.out
3+
# RUN: not %{lit} -j 1 -v %{inputs}/max-failures > %t.out
4+
# RUN: not %{lit} --max-failures=1 -j 1 -v %{inputs}/max-failures >> %t.out
5+
# RUN: not %{lit} --max-failures=2 -j 1 -v %{inputs}/max-failures >> %t.out
6+
# RUN: not %{lit} --max-failures=0 -j 1 -v %{inputs}/max-failures 2>> %t.out
77
# RUN: FileCheck < %t.out %s
88
#
99
# END.

utils/lit/tests/selecting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
# Check that regex-filtering based on environment variables work.
1111
#
12-
# RUN: LIT_FILTER='o[a-z]e' %{lit} %{inputs}/discovery | FileCheck --check-prefix=CHECK-FILTER-ENV %s
12+
# RUN: env LIT_FILTER='o[a-z]e' %{lit} %{inputs}/discovery | FileCheck --check-prefix=CHECK-FILTER-ENV %s
1313
# CHECK-FILTER-ENV: Testing: 2 of 5 tests
1414

1515

0 commit comments

Comments
 (0)