1
0
mirror of https://github.com/arsenetar/send2trash.git synced 2025-05-17 05:59:49 +00:00
send2trash/tests/test_plat_other.py
Andrew Senetar 356509120b
Add some checks to catch test failure
Really just checking that the setup is able to create test files so it
is known they were there then removed.
Windows tests really need verification of
recycle, which is not present.
2021-03-17 20:52:16 -05:00

236 lines
6.8 KiB
Python

# encoding: utf-8
import pytest
import codecs
import os
import sys
from os import path as op
from send2trash.compat import PY3
from send2trash import TrashPermissionError
try:
from configparser import ConfigParser
except ImportError:
# py2
from ConfigParser import ConfigParser # noqa: F401
from tempfile import mkdtemp, NamedTemporaryFile, mktemp
import shutil
import stat
if sys.platform != "win32":
import send2trash.plat_other
from send2trash.plat_other import send2trash as s2t
HOMETRASH = send2trash.plat_other.HOMETRASH
else:
pytest.skip("Skipping non-windows tests", allow_module_level=True)
@pytest.fixture
def testfile():
file = NamedTemporaryFile(
dir=op.expanduser("~"), prefix="send2trash_test", delete=False
)
file.close()
assert op.exists(file) is True
yield file
# Cleanup trash files on supported platforms
if sys.platform != "win32":
name = op.basename(file.name)
# Remove trash files if they exist
if op.exists(op.join(HOMETRASH, "files", name)):
os.remove(op.join(HOMETRASH, "files", name))
os.remove(op.join(HOMETRASH, "info", name + ".trashinfo"))
if op.exists(file.name):
os.remove(file.name)
@pytest.fixture
def testfiles():
files = list(
map(
lambda index: NamedTemporaryFile(
dir=op.expanduser("~"),
prefix="send2trash_test{}".format(index),
delete=False,
),
range(10),
)
)
[file.close() for file in files]
assert all([op.exists(file) for file in files]) is True
yield files
filenames = [op.basename(file.name) for file in files]
[os.remove(op.join(HOMETRASH, "files", filename)) for filename in filenames]
[
os.remove(op.join(HOMETRASH, "info", filename + ".trashinfo"))
for filename in filenames
]
def test_trash(testfile):
s2t(testfile.name)
assert op.exists(testfile.name) is False
def test_multitrash(testfiles):
filenames = [file.name for file in testfiles]
s2t(filenames)
assert any([op.exists(filename) for filename in filenames]) is False
def touch(path):
with open(path, "a"):
os.utime(path, None)
def _filesys_enc():
enc = sys.getfilesystemencoding()
# Get canonical name of codec
return codecs.lookup(enc).name
@pytest.fixture
def testUnicodefile():
name = u"send2trash_tést1"
file = op.join(op.expanduser(b"~"), name.encode("utf-8"))
touch(file)
assert op.exists(file) is True
yield file
# Cleanup trash files on supported platforms
if sys.platform != "win32":
# Remove trash files if they exist
if op.exists(op.join(HOMETRASH, "files", name)):
os.remove(op.join(HOMETRASH, "files", name))
os.remove(op.join(HOMETRASH, "info", name + ".trashinfo"))
if op.exists(file):
os.remove(file)
@pytest.mark.skipif(_filesys_enc() == "ascii", reason="Requires Unicode filesystem")
def test_trash_bytes(testUnicodefile):
s2t(testUnicodefile)
assert not op.exists(testUnicodefile)
@pytest.mark.skipif(_filesys_enc() == "ascii", reason="Requires Unicode filesystem")
def test_trash_unicode(testUnicodefile):
s2t(testUnicodefile.decode(sys.getfilesystemencoding()))
assert not op.exists(testUnicodefile)
class ExtVol:
def __init__(self, path):
self.trashTopdir = path
if PY3:
self.trashTopdir_b = os.fsencode(self.trashTopdir)
else:
self.trashTopdir_b = self.trashTopdir
def s_getdev(path):
from send2trash.plat_other import is_parent
st = os.lstat(path)
if is_parent(self.trashTopdir, path):
return "dev"
return st.st_dev
def s_ismount(path):
if op.realpath(path) in (
op.realpath(self.trashTopdir),
op.realpath(self.trashTopdir_b),
):
return True
return old_ismount(path)
self.old_ismount = old_ismount = op.ismount
self.old_getdev = send2trash.plat_other.get_dev
send2trash.plat_other.os.path.ismount = s_ismount
send2trash.plat_other.get_dev = s_getdev
def cleanup(self):
send2trash.plat_other.get_dev = self.old_getdev
send2trash.plat_other.os.path.ismount = self.old_ismount
shutil.rmtree(self.trashTopdir)
@pytest.fixture
def testExtVol():
trashTopdir = mkdtemp(prefix="s2t")
volume = ExtVol(trashTopdir)
fileName = "test.txt"
filePath = op.join(volume.trashTopdir, fileName)
touch(filePath)
assert op.exists(filePath) is True
yield volume, fileName, filePath
volume.cleanup()
def test_trash_topdir(testExtVol):
trashDir = op.join(testExtVol[0].trashTopdir, ".Trash")
os.mkdir(trashDir, 0o777 | stat.S_ISVTX)
s2t(testExtVol[2])
assert op.exists(testExtVol[2]) is False
assert (
op.exists(op.join(trashDir, str(os.getuid()), "files", testExtVol[1])) is True
)
assert (
op.exists(
op.join(trashDir, str(os.getuid()), "info", testExtVol[1] + ".trashinfo",)
)
is True
)
# info relative path (if another test is added, with the same fileName/Path,
# then it gets renamed etc.)
cfg = ConfigParser()
cfg.read(op.join(trashDir, str(os.getuid()), "info", testExtVol[1] + ".trashinfo"))
assert (testExtVol[1] == cfg.get("Trash Info", "Path", raw=True)) is True
def test_trash_topdir_fallback(testExtVol):
s2t(testExtVol[2])
assert op.exists(testExtVol[2]) is False
assert (
op.exists(
op.join(
testExtVol[0].trashTopdir,
".Trash-" + str(os.getuid()),
"files",
testExtVol[1],
)
)
is True
)
def test_trash_topdir_failure(testExtVol):
os.chmod(testExtVol[0].trashTopdir, 0o500) # not writable to induce the exception
pytest.raises(TrashPermissionError, s2t, [testExtVol[2]])
os.chmod(testExtVol[0].trashTopdir, 0o700) # writable to allow deletion
def test_trash_symlink(testExtVol):
# Use mktemp (race conditioney but no symlink equivalent)
# Since is_parent uses realpath(), and our getdev uses is_parent,
# this should work
slDir = mktemp(prefix="s2t", dir=op.expanduser("~"))
os.mkdir(op.join(testExtVol[0].trashTopdir, "subdir"), 0o700)
filePath = op.join(testExtVol[0].trashTopdir, "subdir", testExtVol[1])
touch(filePath)
os.symlink(op.join(testExtVol[0].trashTopdir, "subdir"), slDir)
s2t(op.join(slDir, testExtVol[1]))
assert op.exists(filePath) is False
assert (
op.exists(
op.join(
testExtVol[0].trashTopdir,
".Trash-" + str(os.getuid()),
"files",
testExtVol[1],
)
)
is True
)
os.remove(slDir)