blob: 3e1afd41997aad40e9881da2dbdbd64e2a2575e7 [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
Serhiy Storchaka83910262016-11-11 11:46:44 +020010from test.libregrtest.refleak import dash_R, clear_caches
Victor Stinner3844fe52015-09-26 10:38:01 +020011from 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
mlouielua49c9352017-06-16 17:36:19 +080074def get_abs_module(ns, test):
75 if test.startswith('test.') or ns.testdir:
76 return test
77 else:
78 # Always import it from the test package
79 return 'test.' + test
80
81
Victor Stinner6f20a2e2015-09-30 02:32:11 +020082def runtest(ns, test):
Victor Stinner3844fe52015-09-26 10:38:01 +020083 """Run a single test.
84
Victor Stinnerab983672016-08-22 14:28:52 +020085 ns -- regrtest namespace of options
Victor Stinner3844fe52015-09-26 10:38:01 +020086 test -- the name of the test
Victor Stinner3844fe52015-09-26 10:38:01 +020087
Victor Stinnerab983672016-08-22 14:28:52 +020088 Returns the tuple (result, test_time), where result is one of the
89 constants:
90
Victor Stinner3844fe52015-09-26 10:38:01 +020091 INTERRUPTED KeyboardInterrupt when run under -j
92 RESOURCE_DENIED test skipped because resource denied
93 SKIPPED test skipped for some other reason
94 ENV_CHANGED test failed because it changed the execution environment
95 FAILED test failed
96 PASSED test passed
97 """
98
Victor Stinner6f20a2e2015-09-30 02:32:11 +020099 output_on_failure = ns.verbose3
Victor Stinner6f20a2e2015-09-30 02:32:11 +0200100
Victor Stinnerab983672016-08-22 14:28:52 +0200101 use_timeout = (ns.timeout is not None)
Victor Stinner3844fe52015-09-26 10:38:01 +0200102 if use_timeout:
Victor Stinnerab983672016-08-22 14:28:52 +0200103 faulthandler.dump_traceback_later(ns.timeout, exit=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200104 try:
Victor Stinner803ddd82017-11-21 15:34:02 -0800105 support.set_match_tests(ns.match_tests)
Victor Stinner21a0a6c2017-06-30 10:59:52 +0200106 # reset the environment_altered flag to detect if a test altered
107 # the environment
108 support.environment_altered = False
Victor Stinnerab983672016-08-22 14:28:52 +0200109 if ns.failfast:
Victor Stinner3844fe52015-09-26 10:38:01 +0200110 support.failfast = True
111 if output_on_failure:
112 support.verbose = True
113
114 # Reuse the same instance to all calls to runtest(). Some
115 # tests keep a reference to sys.stdout or sys.stderr
116 # (eg. test_argparse).
117 if runtest.stringio is None:
118 stream = io.StringIO()
119 runtest.stringio = stream
120 else:
121 stream = runtest.stringio
122 stream.seek(0)
123 stream.truncate()
124
125 orig_stdout = sys.stdout
126 orig_stderr = sys.stderr
127 try:
128 sys.stdout = stream
129 sys.stderr = stream
Victor Stinnerab983672016-08-22 14:28:52 +0200130 result = runtest_inner(ns, test, display_failure=False)
Victor Stinner21c8c922016-09-23 11:15:50 +0200131 if result[0] != PASSED:
Victor Stinner3844fe52015-09-26 10:38:01 +0200132 output = stream.getvalue()
133 orig_stderr.write(output)
134 orig_stderr.flush()
135 finally:
136 sys.stdout = orig_stdout
137 sys.stderr = orig_stderr
138 else:
Victor Stinnerab983672016-08-22 14:28:52 +0200139 support.verbose = ns.verbose # Tell tests to be moderately quiet
140 result = runtest_inner(ns, test, display_failure=not ns.verbose)
Victor Stinner3844fe52015-09-26 10:38:01 +0200141 return result
142 finally:
143 if use_timeout:
144 faulthandler.cancel_dump_traceback_later()
Victor Stinnerab983672016-08-22 14:28:52 +0200145 cleanup_test_droppings(test, ns.verbose)
Victor Stinner3844fe52015-09-26 10:38:01 +0200146runtest.stringio = None
147
148
Victor Stinnere3510d72017-08-09 17:44:33 +0200149def post_test_cleanup():
150 support.reap_children()
151
152
Victor Stinnerab983672016-08-22 14:28:52 +0200153def runtest_inner(ns, test, display_failure=True):
Victor Stinner3844fe52015-09-26 10:38:01 +0200154 support.unload(test)
155
156 test_time = 0.0
157 refleak = False # True if the test leaked references.
158 try:
mlouielua49c9352017-06-16 17:36:19 +0800159 abstest = get_abs_module(ns, test)
Serhiy Storchaka83910262016-11-11 11:46:44 +0200160 clear_caches()
Victor Stinnerab983672016-08-22 14:28:52 +0200161 with saved_test_environment(test, ns.verbose, ns.quiet, pgo=ns.pgo) as environment:
Victor Stinner3844fe52015-09-26 10:38:01 +0200162 start_time = time.time()
163 the_module = importlib.import_module(abstest)
164 # If the test has a test_main, that will run the appropriate
165 # tests. If not, use normal unittest test loading.
166 test_runner = getattr(the_module, "test_main", None)
167 if test_runner is None:
168 def test_runner():
169 loader = unittest.TestLoader()
170 tests = loader.loadTestsFromModule(the_module)
171 for error in loader.errors:
172 print(error, file=sys.stderr)
173 if loader.errors:
174 raise Exception("errors while loading tests")
175 support.run_unittest(tests)
Victor Stinnerab983672016-08-22 14:28:52 +0200176 if ns.huntrleaks:
177 refleak = dash_R(the_module, test, test_runner, ns.huntrleaks)
Pablo Galindo58ed7302018-06-26 15:17:26 +0100178 else:
179 test_runner()
Victor Stinner3844fe52015-09-26 10:38:01 +0200180 test_time = time.time() - start_time
Victor Stinnere3510d72017-08-09 17:44:33 +0200181 post_test_cleanup()
Victor Stinner3844fe52015-09-26 10:38:01 +0200182 except support.ResourceDenied as msg:
Victor Stinnerab983672016-08-22 14:28:52 +0200183 if not ns.quiet and not ns.pgo:
Victor Stinnerf33536c2015-09-30 00:48:27 +0200184 print(test, "skipped --", msg, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200185 return RESOURCE_DENIED, test_time
186 except unittest.SkipTest as msg:
Victor Stinnerab983672016-08-22 14:28:52 +0200187 if not ns.quiet and not ns.pgo:
Victor Stinnerf33536c2015-09-30 00:48:27 +0200188 print(test, "skipped --", msg, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200189 return SKIPPED, test_time
190 except KeyboardInterrupt:
191 raise
192 except support.TestFailed as msg:
Victor Stinnerab983672016-08-22 14:28:52 +0200193 if not ns.pgo:
Brett Cannon11faa212015-10-02 16:20:49 -0700194 if display_failure:
195 print("test", test, "failed --", msg, file=sys.stderr,
196 flush=True)
197 else:
198 print("test", test, "failed", file=sys.stderr, flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200199 return FAILED, test_time
200 except:
201 msg = traceback.format_exc()
Victor Stinnerab983672016-08-22 14:28:52 +0200202 if not ns.pgo:
Brett Cannon11faa212015-10-02 16:20:49 -0700203 print("test", test, "crashed --", msg, file=sys.stderr,
204 flush=True)
Victor Stinner3844fe52015-09-26 10:38:01 +0200205 return FAILED, test_time
206 else:
207 if refleak:
208 return FAILED, test_time
209 if environment.changed:
210 return ENV_CHANGED, test_time
211 return PASSED, test_time
212
213
214def cleanup_test_droppings(testname, verbose):
215 import shutil
216 import stat
217 import gc
218
219 # First kill any dangling references to open files etc.
220 # This can also issue some ResourceWarnings which would otherwise get
221 # triggered during the following test run, and possibly produce failures.
222 gc.collect()
223
224 # Try to clean up junk commonly left behind. While tests shouldn't leave
225 # any files or directories behind, when a test fails that can be tedious
226 # for it to arrange. The consequences can be especially nasty on Windows,
227 # since if a test leaves a file open, it cannot be deleted by name (while
228 # there's nothing we can do about that here either, we can display the
229 # name of the offending test, which is a real help).
230 for name in (support.TESTFN,
231 "db_home",
232 ):
233 if not os.path.exists(name):
234 continue
235
236 if os.path.isdir(name):
237 kind, nuker = "directory", shutil.rmtree
238 elif os.path.isfile(name):
239 kind, nuker = "file", os.unlink
240 else:
241 raise SystemError("os.path says %r exists but is neither "
242 "directory nor file" % name)
243
244 if verbose:
245 print("%r left behind %s %r" % (testname, kind, name))
246 try:
247 # if we have chmod, fix possible permissions problems
248 # that might prevent cleanup
249 if (hasattr(os, 'chmod')):
250 os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
251 nuker(name)
252 except Exception as msg:
253 print(("%r left behind %s %r and it couldn't be "
254 "removed: %s" % (testname, kind, name, msg)), file=sys.stderr)
255
256
257def findtestdir(path=None):
258 return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir