blob: ef1feb738a0ac6e743b58cc8b9e8ff0a7bd32dfc [file] [log] [blame]
Victor Stinner3844fe52015-09-26 10:38:01 +02001import faulthandler
2import importlib
3import io
Victor Stinner3844fe52015-09-26 10:38:01 +02004import os
5import sys
6import time
7import traceback
8import unittest
9from test import support
10from test.libregrtest.refleak import dash_R
11from test.libregrtest.save_env import saved_test_environment
12
13
14# Test result constants.
15PASSED = 1
16FAILED = 0
17ENV_CHANGED = -1
18SKIPPED = -2
19RESOURCE_DENIED = -3
20INTERRUPTED = -4
21CHILD_ERROR = -5 # error in a child process
22
Victor Stinner1b8b4232016-05-20 13:37:40 +020023_FORMAT_TEST_RESULT = {
24 PASSED: '%s passed',
25 FAILED: '%s failed',
26 ENV_CHANGED: '%s failed (env changed)',
27 SKIPPED: '%s skipped',
28 RESOURCE_DENIED: '%s skipped (resource denied)',
29 INTERRUPTED: '%s interrupted',
30 CHILD_ERROR: '%s crashed',
31}
32
Victor Stinner69649f22016-03-23 12:14:10 +010033# Minimum duration of a test to display its duration or to mention that
34# the test is running in background
35PROGRESS_MIN_TIME = 30.0 # seconds
36
Victor Stinner3844fe52015-09-26 10:38:01 +020037# small set of tests to determine if we have a basically functioning interpreter
38# (i.e. if any of these fail, then anything else is likely to follow)
39STDTESTS = [
40 'test_grammar',
41 'test_opcodes',
42 'test_dict',
43 'test_builtin',
44 'test_exceptions',
45 'test_types',
46 'test_unittest',
47 'test_doctest',
48 'test_doctest2',
49 'test_support'
50]
51
52# set of tests that we don't want to be executed when using regrtest
53NOTTESTS = set()
54
55
Victor Stinner1b8b4232016-05-20 13:37:40 +020056def format_test_result(test_name, result):
57 fmt = _FORMAT_TEST_RESULT.get(result, "%s")
58 return fmt % test_name
59
60
Victor Stinner3844fe52015-09-26 10:38:01 +020061def findtests(testdir=None, stdtests=STDTESTS, nottests=NOTTESTS):
62 """Return a list of all applicable test modules."""
63 testdir = findtestdir(testdir)
64 names = os.listdir(testdir)
65 tests = []
66 others = set(stdtests) | nottests
67 for name in names:
68 mod, ext = os.path.splitext(name)
69 if mod[:5] == "test_" and ext in (".py", "") and mod not in others:
70 tests.append(mod)
71 return stdtests + sorted(tests)
72
73
Victor Stinner6f20a2e2015-09-30 02:32:11 +020074def runtest(ns, test):
Victor Stinner3844fe52015-09-26 10:38:01 +020075 """Run a single test.
76
77 test -- the name of the test
78 verbose -- if true, print more messages
79 quiet -- if true, don't print 'skipped' messages (probably redundant)
80 huntrleaks -- run multiple times to test for leaks; requires a debug
81 build; a triple corresponding to -R's three arguments
Victor Stinner3844fe52015-09-26 10:38:01 +020082 output_on_failure -- if true, display test output on failure
83 timeout -- dump the traceback and exit if a test takes more than
84 timeout seconds
85 failfast, match_tests -- See regrtest command-line flags for these.
Brett Cannon11faa212015-10-02 16:20:49 -070086 pgo -- if true, suppress any info irrelevant to a generating a PGO build
Victor Stinner3844fe52015-09-26 10:38:01 +020087
88 Returns the tuple result, test_time, where result is one of the constants:
89 INTERRUPTED KeyboardInterrupt when run under -j
90 RESOURCE_DENIED test skipped because resource denied
91 SKIPPED test skipped for some other reason
92 ENV_CHANGED test failed because it changed the execution environment
93 FAILED test failed
94 PASSED test passed
95 """
96
Victor Stinner6f20a2e2015-09-30 02:32:11 +020097 verbose = ns.verbose
98 quiet = ns.quiet
99 huntrleaks = ns.huntrleaks
100 output_on_failure = ns.verbose3
101 failfast = ns.failfast
102 match_tests = ns.match_tests
103 timeout = ns.timeout
Brett Cannon11faa212015-10-02 16:20:49 -0700104 pgo = ns.pgo
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200105
Victor Stinner3844fe52015-09-26 10:38:01 +0200106 use_timeout = (timeout is not None)
107 if use_timeout:
108 faulthandler.dump_traceback_later(timeout, exit=True)
109 try:
110 support.match_tests = match_tests
111 if failfast:
112 support.failfast = True
113 if output_on_failure:
114 support.verbose = True
115
116 # Reuse the same instance to all calls to runtest(). Some
117 # tests keep a reference to sys.stdout or sys.stderr
118 # (eg. test_argparse).
119 if runtest.stringio is None:
120 stream = io.StringIO()
121 runtest.stringio = stream
122 else:
123 stream = runtest.stringio
124 stream.seek(0)
125 stream.truncate()
126
127 orig_stdout = sys.stdout
128 orig_stderr = sys.stderr
129 try:
130 sys.stdout = stream
131 sys.stderr = stream
Victor Stinner9759dd32016-03-30 02:32:52 +0200132 result = runtest_inner(ns, test, verbose, quiet, huntrleaks,
Brett Cannon11faa212015-10-02 16:20:49 -0700133 display_failure=False, pgo=pgo)
Victor Stinner3844fe52015-09-26 10:38:01 +0200134 if result[0] == FAILED:
135 output = stream.getvalue()
136 orig_stderr.write(output)
137 orig_stderr.flush()
138 finally:
139 sys.stdout = orig_stdout
140 sys.stderr = orig_stderr
141 else:
142 support.verbose = verbose # Tell tests to be moderately quiet
Victor Stinner9759dd32016-03-30 02:32:52 +0200143 result = runtest_inner(ns, test, verbose, quiet, huntrleaks,
Brett Cannon11faa212015-10-02 16:20:49 -0700144 display_failure=not verbose, pgo=pgo)
Victor Stinner3844fe52015-09-26 10:38:01 +0200145 return result
146 finally:
147 if use_timeout:
148 faulthandler.cancel_dump_traceback_later()
149 cleanup_test_droppings(test, verbose)
150runtest.stringio = None
151
152
Victor Stinner9759dd32016-03-30 02:32:52 +0200153def runtest_inner(ns, test, verbose, quiet,
Brett Cannon11faa212015-10-02 16:20:49 -0700154 huntrleaks=False, display_failure=True, *, pgo=False):
Victor Stinner3844fe52015-09-26 10:38:01 +0200155 support.unload(test)
156
157 test_time = 0.0
158 refleak = False # True if the test leaked references.
159 try:
Victor Stinner9759dd32016-03-30 02:32:52 +0200160 if test.startswith('test.') or ns.testdir:
Victor Stinner3844fe52015-09-26 10:38:01 +0200161 abstest = test
162 else:
163 # Always import it from the test package
164 abstest = 'test.' + test
Brett Cannon11faa212015-10-02 16:20:49 -0700165 with saved_test_environment(test, verbose, quiet, pgo=pgo) as environment:
Victor Stinner3844fe52015-09-26 10:38:01 +0200166 start_time = time.time()
167 the_module = importlib.import_module(abstest)
168 # If the test has a test_main, that will run the appropriate
169 # tests. If not, use normal unittest test loading.
170 test_runner = getattr(the_module, "test_main", None)
171 if test_runner is None:
172 def test_runner():
173 loader = unittest.TestLoader()
174 tests = loader.loadTestsFromModule(the_module)
175 for error in loader.errors:
176 print(error, file=sys.stderr)
177 if loader.errors:
178 raise Exception("errors while loading tests")
179 support.run_unittest(tests)
180 test_runner()
181 if huntrleaks:
182 refleak = dash_R(the_module, test, test_runner, huntrleaks)
183 test_time = time.time() - start_time
184 except support.ResourceDenied as msg:
Brett Cannon11faa212015-10-02 16:20:49 -0700185 if not quiet and not pgo:
Victor Stinnerf33536c2015-09-30 00:48:27 +0200186 print(test, "skipped --", msg, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200187 return RESOURCE_DENIED, test_time
188 except unittest.SkipTest as msg:
Brett Cannon11faa212015-10-02 16:20:49 -0700189 if not quiet and not pgo:
Victor Stinnerf33536c2015-09-30 00:48:27 +0200190 print(test, "skipped --", msg, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200191 return SKIPPED, test_time
192 except KeyboardInterrupt:
193 raise
194 except support.TestFailed as msg:
Brett Cannon11faa212015-10-02 16:20:49 -0700195 if not pgo:
196 if display_failure:
197 print("test", test, "failed --", msg, file=sys.stderr,
198 flush=True)
199 else:
200 print("test", test, "failed", file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200201 return FAILED, test_time
202 except:
203 msg = traceback.format_exc()
Brett Cannon11faa212015-10-02 16:20:49 -0700204 if not pgo:
205 print("test", test, "crashed --", msg, file=sys.stderr,
206 flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200207 return FAILED, test_time
208 else:
209 if refleak:
210 return FAILED, test_time
211 if environment.changed:
212 return ENV_CHANGED, test_time
213 return PASSED, test_time
214
215
216def cleanup_test_droppings(testname, verbose):
217 import shutil
218 import stat
219 import gc
220
221 # First kill any dangling references to open files etc.
222 # This can also issue some ResourceWarnings which would otherwise get
223 # triggered during the following test run, and possibly produce failures.
224 gc.collect()
225
226 # Try to clean up junk commonly left behind. While tests shouldn't leave
227 # any files or directories behind, when a test fails that can be tedious
228 # for it to arrange. The consequences can be especially nasty on Windows,
229 # since if a test leaves a file open, it cannot be deleted by name (while
230 # there's nothing we can do about that here either, we can display the
231 # name of the offending test, which is a real help).
232 for name in (support.TESTFN,
233 "db_home",
234 ):
235 if not os.path.exists(name):
236 continue
237
238 if os.path.isdir(name):
239 kind, nuker = "directory", shutil.rmtree
240 elif os.path.isfile(name):
241 kind, nuker = "file", os.unlink
242 else:
243 raise SystemError("os.path says %r exists but is neither "
244 "directory nor file" % name)
245
246 if verbose:
247 print("%r left behind %s %r" % (testname, kind, name))
248 try:
249 # if we have chmod, fix possible permissions problems
250 # that might prevent cleanup
251 if (hasattr(os, 'chmod')):
252 os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
253 nuker(name)
254 except Exception as msg:
255 print(("%r left behind %s %r and it couldn't be "
256 "removed: %s" % (testname, kind, name, msg)), file=sys.stderr)
257
258
259def findtestdir(path=None):
260 return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir