handle test folder cleanup being unable to create a cleanup lock

This commit is contained in:
Ronny Pfannschmidt 2018-10-24 07:45:53 +02:00
parent c94b2b227e
commit ae2fc27799
3 changed files with 19 additions and 5 deletions

View File

@ -0,0 +1 @@
Handle race condition between creation and deletion of temporary folders.

View File

@ -182,9 +182,15 @@ def register_cleanup_lock_removal(lock_path, register=atexit.register):
return register(cleanup_on_exit)
def delete_a_numbered_dir(path):
"""removes a numbered directory"""
create_cleanup_lock(path)
def maybe_delete_a_numbered_dir(path):
"""removes a numbered directory if its lock can be obtained"""
try:
create_cleanup_lock(path)
except (OSError, EnvironmentError):
# known races:
# * other process did a cleanup at the same time
# * deletable folder was found
return
parent = path.parent
garbage = parent.joinpath("garbage-{}".format(uuid.uuid4()))
@ -214,7 +220,7 @@ def ensure_deletable(path, consider_lock_dead_if_created_before):
def try_cleanup(path, consider_lock_dead_if_created_before):
"""tries to cleanup a folder if we can ensure its deletable"""
if ensure_deletable(path, consider_lock_dead_if_created_before):
delete_a_numbered_dir(path)
maybe_delete_a_numbered_dir(path)
def cleanup_candidates(root, prefix, keep):

View File

@ -4,6 +4,7 @@ import sys
import six
import pytest
from _pytest import pathlib
from _pytest.pathlib import Path
@ -284,11 +285,17 @@ class TestNumberedDir(object):
rmtree(adir, force=True)
assert not adir.exists()
def test_cleanup_symlink(self, tmp_path):
def test_cleanup_ignores_symlink(self, tmp_path):
the_symlink = tmp_path / (self.PREFIX + "current")
attempt_symlink_to(the_symlink, tmp_path / (self.PREFIX + "5"))
self._do_cleanup(tmp_path)
def test_removal_accepts_lock(self, tmp_path):
folder = pathlib.make_numbered_dir(root=tmp_path, prefix=self.PREFIX)
pathlib.create_cleanup_lock(folder)
pathlib.maybe_delete_a_numbered_dir(folder)
assert folder.is_dir()
def attempt_symlink_to(path, to_path):
"""Try to make a symlink from "path" to "to_path", skipping in case this platform