10000 [WIP] bpo-37421: regrtest detects if a test leaks temporary files by vstinner · Pull Request #14415 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

[WIP] bpo-37421: regrtest detects if a test leaks temporary files #14415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 23 additions & 16 deletions Lib/test/libregrtest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def __init__(self):

# misc
self.win_load_tracker = None
self.tmp_dir = None
self.directory = None
self.worker_test_name = None

def get_executed(self):
Expand Down Expand Up @@ -191,7 +191,7 @@ def find_tests(self, tests):
self.tests = tests

if self.ns.single:
self.next_single_filename = os.path.join(self.tmp_dir, 'pynexttest')
self.next_single_filename = os.path.join(self.directory, 'pynexttest')
try:
with open(self.next_single_filename, 'r') as fp:
next_test = fp.read().strip()
Expand Down Expand Up @@ -551,28 +551,28 @@ def save_xml_result(self):

def set_temp_dir(self):
if self.ns.tempdir:
self.tmp_dir = self.ns.tempdir
self.directory = self.ns.tempdir

if not self.tmp_dir:
if not self.directory:
# When tests are run from the Python build directory, it is best practice
# to keep the test files in a subfolder. This eases the cleanup of leftover
# files using the "make distclean" command.
if sysconfig.is_python_build():
self.tmp_dir = sysconfig.get_config_var('abs_builddir')
if self.tmp_dir is None:
self.directory = sysconfig.get_config_var('abs_builddir')
if self.directory is None:
# bpo-30284: On Windows, only srcdir is available. Using
# abs_builddir mostly matters on UNIX when building Python
# out of the source tree, especially when the source tree
# is read only.
self.tmp_dir = sysconfig.get_config_var('srcdir')
self.tmp_dir = os.path.join(self.tmp_dir, 'build')
self.directory = sysconfig.get_config_var('srcdir')
self.directory = os.path.join(self.directory, 'build')
else:
self.tmp_dir = tempfile.gettempdir()
self.directory = tempfile.gettempdir()

self.tmp_dir = os.path.abspath(self.tmp_dir)
self.directory = os.path.abspath(self.directory)

def create_temp_dir(self):
os.makedirs(self.tmp_dir, exist_ok=True)
def create_test_dir(self):
os.makedirs(self.directory, exist_ok=True)

# Define a writable temp dir that will be used as cwd while running
# the tests. The name of the dir includes the pid to allow parallel
Expand All @@ -582,14 +582,14 @@ def create_temp_dir(self):
test_cwd = 'test_python_worker_{}'.format(pid)
else:
test_cwd = 'test_python_{}'.format(pid)
test_cwd = os.path.join(self.tmp_dir, test_cwd)
test_cwd = os.path.join(self.directory, test_cwd)
return test_cwd

def cleanup(self):
import glob

path = os.path.join(self.tmp_dir, 'test_python_*')
print("Cleanup %s directory" % self.tmp_dir)
path = os.path.join(self.directory, 'test_python_*')
print("Cleanup %s directory" % self.directory)
for name in glob.glob(path):
if os.path.isdir(name):
print("Remove directory: %s" % name)
Expand All @@ -607,13 +607,20 @@ def main(self, tests=None, **kwargs):
self.cleanup()
sys.exit(0)

test_cwd = self.create_temp_dir()
test_cwd = self.create_test_dir()

# Run the tests in a context manager that temporarily changes the CWD
# to a temporary and writable directory. If it's not possible to
# create or change the CWD, the original CWD will be used.
# The original CWD is available from support.SAVEDCWD.
with support.temp_cwd(test_cwd, quiet=True):
tmpdir = os.path.join(test_cwd, 'tmpdir')
os.mkdir(tmpdir)

os.environ['TMPDIR'] = tmpdir
os.environ['TEMPDIR'] = tmpdir
support.TMPDIR = tmpdir

# When using multiprocessing, worker processes will use test_cwd
# as their parent temporary directory. So when the main process
# exit, it removes also subdirectories of worker processes.
Expand Down
13 changes: 13 additions & 0 deletions Lib/test/libregrtest/save_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def __init__(self, testname, verbose=0, quiet=False, *, pgo=False):
self.verbose = verbose
self.quiet = quiet
self.pgo = pgo
self.tmpdir = support.TMPDIR

# To add things to save and restore, add a name XXX to the resources list
# and add corresponding get_XXX/restore_XXX functions. get_XXX should
Expand All @@ -70,6 +71,7 @@ def __init__(self, testname, verbose=0, quiet=False, *, pgo=False):
'shutil_archive_formats', 'shutil_unpack_formats',
'asyncio.events._event_loop_policy',
'urllib.requests._url_tempfiles', 'urllib.requests._opener',
'tmpdir',
)

def get_urllib_requests__url_tempfiles(self):
Expand Down Expand Up @@ -248,6 +250,17 @@ def restore_files(self, saved_value):
elif os.path.isdir(fn):
support.rmtree(fn)

def get_tmpdir(self):
return sorted(fn + ('/' if os.path.isdir(fn) else '')
for fn in os.listdir(self.tmpdir))
def restore_tmpdir(self, saved_value):
fn = support.TESTFN
if fn not in saved_value and (fn + '/') not in saved_value:
if os.path.isfile(fn):
support.unlink(fn)
elif os.path.isdir(fn):
support.rmtree(fn)

_lc = [getattr(locale, lc) for lc in dir(locale)
if lc.startswith('LC_')]
def get_locale(self):
Expand Down
0