summaryrefslogtreecommitdiffstats
path: root/lldb/packages/Python/lldbsuite/test
diff options
context:
space:
mode:
authorTodd Fiala <todd.fiala@gmail.com>2016-05-13 21:36:26 +0000
committerTodd Fiala <todd.fiala@gmail.com>2016-05-13 21:36:26 +0000
commit7c5f7caa200da38a106c268d09c6a0657a66829e (patch)
tree25cf73696b388c0ba216ea091075dd8e2c0700b7 /lldb/packages/Python/lldbsuite/test
parentead771cb7ac8d8aacc71b2e6d62d465b1090ebd3 (diff)
downloadbcm5719-llvm-7c5f7caa200da38a106c268d09c6a0657a66829e.tar.gz
bcm5719-llvm-7c5f7caa200da38a106c268d09c6a0657a66829e.zip
test infra: catch bad decorators and import-time errors
Summary: This change enhances the LLDB test infrastructure to convert load-time exceptions in a given Python test module into errors. Before this change, specifying a non-existent test decorator, or otherwise having some load-time error in a python test module, would not get flagged as an error. With this change, typos and other load-time errors in a python test file get converted to errors and reported by the test runner. This change also includes test infrastructure tests that include covering the new work here. I'm going to wait until we have these infrastructure tests runnable on the main platforms before I try to work that into all the normal testing workflows. The test infrastructure tests can be run by using the standard python module testing practice of doing the following: cd packages/Python/lldbsuite/test_event python -m unittest discover -s test/src -p 'Test*.py' Those tests run the dotest inferior with a known broken test and verify that the errors are caught. These tests did not pass until I modified dotest.py to capture them properly. @zturner, if you have the chance, if you could try those steps above (the python -m unittest ... line) on Windows, that would be great if we can address any python2/3/Windows bits there. I don't think there's anything fancy, but I didn't want to hook it into test flow until I know it works there. I'll be slowly adding more tests that cover some of the other breakage I've occasionally seen that didn't get collected as part of the summarization. This is the biggest one I'm aware of. Reviewers: zturner, labath Subscribers: zturner, lldb-commits Differential Revision: http://reviews.llvm.org/D20193 llvm-svn: 269489
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test')
-rw-r--r--lldb/packages/Python/lldbsuite/test/dotest.py133
-rw-r--r--lldb/packages/Python/lldbsuite/test/issue_verification/TestInvalidDecorator.py.park13
2 files changed, 92 insertions, 54 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py
index 5f2e95fd084..4a38cdade5a 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest.py
@@ -676,73 +676,98 @@ def setupSysPath():
# This is to locate the lldb.py module. Insert it right after sys.path[0].
sys.path[1:1] = [lldbPythonDir]
+
+def visit_file(dir, name):
+ # Try to match the regexp pattern, if specified.
+ if configuration.regexp:
+ import re
+ if not re.search(configuration.regexp, name):
+ # We didn't match the regex, we're done.
+ return
+
+ # We found a match for our test. Add it to the suite.
+
+ # Update the sys.path first.
+ if not sys.path.count(dir):
+ sys.path.insert(0, dir)
+ base = os.path.splitext(name)[0]
+
+ # Thoroughly check the filterspec against the base module and admit
+ # the (base, filterspec) combination only when it makes sense.
+ filterspec = None
+ for filterspec in configuration.filters:
+ # Optimistically set the flag to True.
+ filtered = True
+ module = __import__(base)
+ parts = filterspec.split('.')
+ obj = module
+ for part in parts:
+ try:
+ parent, obj = obj, getattr(obj, part)
+ except AttributeError:
+ # The filterspec has failed.
+ filtered = False
+ break
+
+ # If filtered, we have a good filterspec. Add it.
+ if filtered:
+ # print("adding filter spec %s to module %s" % (filterspec, module))
+ configuration.suite.addTests(
+ unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
+ continue
+
+ # Forgo this module if the (base, filterspec) combo is invalid
+ if configuration.filters and not filtered:
+ return
+
+ if not filterspec or not filtered:
+ # Add the entire file's worth of tests since we're not filtered.
+ # Also the fail-over case when the filterspec branch
+ # (base, filterspec) combo doesn't make sense.
+ configuration.suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
+
+
def visit(prefix, dir, names):
"""Visitor function for os.path.walk(path, visit, arg)."""
dir_components = set(dir.split(os.sep))
excluded_components = set(['.svn', '.git'])
if dir_components.intersection(excluded_components):
- #print("Detected an excluded dir component: %s" % dir)
return
- for name in names:
- if '.py' == os.path.splitext(name)[1] and name.startswith(prefix):
+ # Gather all the Python test file names that follow the Test*.py pattern.
+ python_test_files = [
+ name
+ for name in names
+ if name.endswith('.py') and name.startswith(prefix)]
+ # Visit all the python test files.
+ for name in python_test_files:
+ try:
+ # Ensure we error out if we have multiple tests with the same
+ # base name.
+ # Future improvement: find all the places where we work with base
+ # names and convert to full paths. We have directory structure
+ # to disambiguate these, so we shouldn't need this constraint.
if name in configuration.all_tests:
raise Exception("Found multiple tests with the name %s" % name)
configuration.all_tests.add(name)
- # Try to match the regexp pattern, if specified.
- if configuration.regexp:
- import re
- if re.search(configuration.regexp, name):
- #print("Filename: '%s' matches pattern: '%s'" % (name, regexp))
- pass
- else:
- #print("Filename: '%s' does not match pattern: '%s'" % (name, regexp))
- continue
-
- # We found a match for our test. Add it to the suite.
-
- # Update the sys.path first.
- if not sys.path.count(dir):
- sys.path.insert(0, dir)
- base = os.path.splitext(name)[0]
-
- # Thoroughly check the filterspec against the base module and admit
- # the (base, filterspec) combination only when it makes sense.
- filterspec = None
- for filterspec in configuration.filters:
- # Optimistically set the flag to True.
- filtered = True
- module = __import__(base)
- parts = filterspec.split('.')
- obj = module
- for part in parts:
- try:
- parent, obj = obj, getattr(obj, part)
- except AttributeError:
- # The filterspec has failed.
- filtered = False
- break
-
- # If filtered, we have a good filterspec. Add it.
- if filtered:
- #print("adding filter spec %s to module %s" % (filterspec, module))
- configuration.suite.addTests(
- unittest2.defaultTestLoader.loadTestsFromName(filterspec, module))
- continue
-
- # Forgo this module if the (base, filterspec) combo is invalid
- if configuration.filters and not filtered:
- continue
-
- # Add either the filtered test case(s) (which is done before) or the entire test class.
- if not filterspec or not filtered:
- # A simple case of just the module name. Also the failover case
- # from the filterspec branch when the (base, filterspec) combo
- # doesn't make sense.
- configuration.suite.addTests(unittest2.defaultTestLoader.loadTestsFromName(base))
+ # Run the relevant tests in the python file.
+ visit_file(dir, name)
+ except Exception as ex:
+ # Convert this exception to a test event error for the file.
+ test_filename = os.path.abspath(os.path.join(dir, name))
+ if configuration.results_formatter_object is not None:
+ # Grab the backtrace for the exception.
+ import traceback
+ backtrace = traceback.format_exc()
+
+ # Generate the test event.
+ configuration.results_formatter_object.handle_event(
+ EventBuilder.event_for_job_test_add_error(
+ test_filename, ex, backtrace))
+ raise
def disabledynamics():
diff --git a/lldb/packages/Python/lldbsuite/test/issue_verification/TestInvalidDecorator.py.park b/lldb/packages/Python/lldbsuite/test/issue_verification/TestInvalidDecorator.py.park
new file mode 100644
index 00000000000..7f5c4cb79cf
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/issue_verification/TestInvalidDecorator.py.park
@@ -0,0 +1,13 @@
+from __future__ import print_function
+from lldbsuite.test import lldbtest
+from lldbsuite.test import decorators
+
+
+class NonExistentDecoratorTestCase(lldbtest.TestBase):
+
+ mydir = lldbtest.TestBase.compute_mydir(__file__)
+
+ @decorators.nonExistentDecorator(bugnumber="yt/1300")
+ def test(self):
+ """Verify non-existent decorators are picked up by test runner."""
+ pass
OpenPOWER on IntegriCloud