mirror of
https://github.com/arsenetar/send2trash.git
synced 2025-05-08 09:49:52 +00:00
Add unit tests for multi-file calls
This commit is contained in:
parent
0d1d5ab40a
commit
41721642e2
@ -6,6 +6,7 @@ from os import path as op
|
|||||||
import send2trash.plat_other
|
import send2trash.plat_other
|
||||||
from send2trash.plat_other import send2trash as s2t
|
from send2trash.plat_other import send2trash as s2t
|
||||||
from send2trash.compat import PY3
|
from send2trash.compat import PY3
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -15,18 +16,22 @@ from tempfile import mkdtemp, NamedTemporaryFile, mktemp
|
|||||||
import shutil
|
import shutil
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# Could still use cleaning up. But no longer relies on ramfs.
|
# Could still use cleaning up. But no longer relies on ramfs.
|
||||||
|
|
||||||
HOMETRASH = send2trash.plat_other.HOMETRASH
|
HOMETRASH = send2trash.plat_other.HOMETRASH
|
||||||
|
|
||||||
|
|
||||||
def touch(path):
|
def touch(path):
|
||||||
with open(path, 'a'):
|
with open(path, "a"):
|
||||||
os.utime(path, None)
|
os.utime(path, None)
|
||||||
|
|
||||||
|
|
||||||
class TestHomeTrash(unittest.TestCase):
|
class TestHomeTrash(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.file = NamedTemporaryFile(
|
self.file = NamedTemporaryFile(
|
||||||
dir=op.expanduser("~"), prefix='send2trash_test', delete=False)
|
dir=op.expanduser("~"), prefix="send2trash_test", delete=False
|
||||||
|
)
|
||||||
|
|
||||||
def test_trash(self):
|
def test_trash(self):
|
||||||
s2t(self.file.name)
|
s2t(self.file.name)
|
||||||
@ -34,8 +39,35 @@ class TestHomeTrash(unittest.TestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
name = op.basename(self.file.name)
|
name = op.basename(self.file.name)
|
||||||
os.remove(op.join(HOMETRASH, 'files', name))
|
os.remove(op.join(HOMETRASH, "files", name))
|
||||||
os.remove(op.join(HOMETRASH, 'info', name+'.trashinfo'))
|
os.remove(op.join(HOMETRASH, "info", name + ".trashinfo"))
|
||||||
|
|
||||||
|
|
||||||
|
class TestHomeMultiTrash(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.files = list(
|
||||||
|
map(
|
||||||
|
lambda index: NamedTemporaryFile(
|
||||||
|
dir=op.expanduser("~"),
|
||||||
|
prefix="send2trash_test{}".format(index),
|
||||||
|
delete=False,
|
||||||
|
),
|
||||||
|
range(10),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_multitrash(self):
|
||||||
|
filenames = [file.name for file in self.files]
|
||||||
|
s2t(filenames)
|
||||||
|
self.assertFalse(any([op.exists(filename) for filename in filenames]))
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
filenames = [op.basename(file.name) for file in self.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 _filesys_enc():
|
def _filesys_enc():
|
||||||
@ -43,11 +75,12 @@ def _filesys_enc():
|
|||||||
# Get canonical name of codec
|
# Get canonical name of codec
|
||||||
return codecs.lookup(enc).name
|
return codecs.lookup(enc).name
|
||||||
|
|
||||||
@unittest.skipIf(_filesys_enc() == 'ascii', 'ASCII filesystem')
|
|
||||||
|
@unittest.skipIf(_filesys_enc() == "ascii", "ASCII filesystem")
|
||||||
class TestUnicodeTrash(unittest.TestCase):
|
class TestUnicodeTrash(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.name = u'send2trash_tést1'
|
self.name = u"send2trash_tést1"
|
||||||
self.file = op.join(op.expanduser(b'~'), self.name.encode('utf-8'))
|
self.file = op.join(op.expanduser(b"~"), self.name.encode("utf-8"))
|
||||||
touch(self.file)
|
touch(self.file)
|
||||||
|
|
||||||
def test_trash_bytes(self):
|
def test_trash_bytes(self):
|
||||||
@ -62,10 +95,11 @@ class TestUnicodeTrash(unittest.TestCase):
|
|||||||
if op.exists(self.file):
|
if op.exists(self.file):
|
||||||
os.remove(self.file)
|
os.remove(self.file)
|
||||||
|
|
||||||
trash_file = op.join(HOMETRASH, 'files', self.name)
|
trash_file = op.join(HOMETRASH, "files", self.name)
|
||||||
if op.exists(trash_file):
|
if op.exists(trash_file):
|
||||||
os.remove(trash_file)
|
os.remove(trash_file)
|
||||||
os.remove(op.join(HOMETRASH, 'info', self.name+'.trashinfo'))
|
os.remove(op.join(HOMETRASH, "info", self.name + ".trashinfo"))
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Tests for files on some other volume than the user's home directory.
|
# Tests for files on some other volume than the user's home directory.
|
||||||
@ -76,25 +110,31 @@ class TestUnicodeTrash(unittest.TestCase):
|
|||||||
#
|
#
|
||||||
class TestExtVol(unittest.TestCase):
|
class TestExtVol(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.trashTopdir = mkdtemp(prefix='s2t')
|
self.trashTopdir = mkdtemp(prefix="s2t")
|
||||||
if PY3:
|
if PY3:
|
||||||
trashTopdir_b = os.fsencode(self.trashTopdir)
|
trashTopdir_b = os.fsencode(self.trashTopdir)
|
||||||
else:
|
else:
|
||||||
trashTopdir_b = self.trashTopdir
|
trashTopdir_b = self.trashTopdir
|
||||||
self.fileName = 'test.txt'
|
self.fileName = "test.txt"
|
||||||
self.filePath = op.join(self.trashTopdir, self.fileName)
|
self.filePath = op.join(self.trashTopdir, self.fileName)
|
||||||
touch(self.filePath)
|
touch(self.filePath)
|
||||||
|
|
||||||
self.old_ismount = old_ismount = op.ismount
|
self.old_ismount = old_ismount = op.ismount
|
||||||
self.old_getdev = send2trash.plat_other.get_dev
|
self.old_getdev = send2trash.plat_other.get_dev
|
||||||
|
|
||||||
def s_getdev(path):
|
def s_getdev(path):
|
||||||
from send2trash.plat_other import is_parent
|
from send2trash.plat_other import is_parent
|
||||||
|
|
||||||
st = os.lstat(path)
|
st = os.lstat(path)
|
||||||
if is_parent(self.trashTopdir, path):
|
if is_parent(self.trashTopdir, path):
|
||||||
return 'dev'
|
return "dev"
|
||||||
return st.st_dev
|
return st.st_dev
|
||||||
|
|
||||||
def s_ismount(path):
|
def s_ismount(path):
|
||||||
if op.realpath(path) in (op.realpath(self.trashTopdir), op.realpath(trashTopdir_b)):
|
if op.realpath(path) in (
|
||||||
|
op.realpath(self.trashTopdir),
|
||||||
|
op.realpath(trashTopdir_b),
|
||||||
|
):
|
||||||
return True
|
return True
|
||||||
return old_ismount(path)
|
return old_ismount(path)
|
||||||
|
|
||||||
@ -106,23 +146,40 @@ class TestExtVol(unittest.TestCase):
|
|||||||
send2trash.plat_other.os.path.ismount = self.old_ismount
|
send2trash.plat_other.os.path.ismount = self.old_ismount
|
||||||
shutil.rmtree(self.trashTopdir)
|
shutil.rmtree(self.trashTopdir)
|
||||||
|
|
||||||
|
|
||||||
class TestTopdirTrash(TestExtVol):
|
class TestTopdirTrash(TestExtVol):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
TestExtVol.setUp(self)
|
TestExtVol.setUp(self)
|
||||||
# Create a .Trash dir w/ a sticky bit
|
# Create a .Trash dir w/ a sticky bit
|
||||||
self.trashDir = op.join(self.trashTopdir, '.Trash')
|
self.trashDir = op.join(self.trashTopdir, ".Trash")
|
||||||
os.mkdir(self.trashDir, 0o777|stat.S_ISVTX)
|
os.mkdir(self.trashDir, 0o777 | stat.S_ISVTX)
|
||||||
|
|
||||||
def test_trash(self):
|
def test_trash(self):
|
||||||
s2t(self.filePath)
|
s2t(self.filePath)
|
||||||
self.assertFalse(op.exists(self.filePath))
|
self.assertFalse(op.exists(self.filePath))
|
||||||
self.assertTrue(op.exists(op.join(self.trashDir, str(os.getuid()), 'files', self.fileName)))
|
self.assertTrue(
|
||||||
self.assertTrue(op.exists(op.join(self.trashDir, str(os.getuid()), 'info', self.fileName + '.trashinfo')))
|
op.exists(op.join(self.trashDir, str(os.getuid()), "files", self.fileName))
|
||||||
|
)
|
||||||
|
self.assertTrue(
|
||||||
|
op.exists(
|
||||||
|
op.join(
|
||||||
|
self.trashDir,
|
||||||
|
str(os.getuid()),
|
||||||
|
"info",
|
||||||
|
self.fileName + ".trashinfo",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
# info relative path (if another test is added, with the same fileName/Path,
|
# info relative path (if another test is added, with the same fileName/Path,
|
||||||
# then it gets renamed etc.)
|
# then it gets renamed etc.)
|
||||||
cfg = ConfigParser()
|
cfg = ConfigParser()
|
||||||
cfg.read(op.join(self.trashDir, str(os.getuid()), 'info', self.fileName + '.trashinfo'))
|
cfg.read(
|
||||||
self.assertEqual(self.fileName, cfg.get('Trash Info', 'Path', raw=True))
|
op.join(
|
||||||
|
self.trashDir, str(os.getuid()), "info", self.fileName + ".trashinfo"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertEqual(self.fileName, cfg.get("Trash Info", "Path", raw=True))
|
||||||
|
|
||||||
|
|
||||||
# Test .Trash-UID
|
# Test .Trash-UID
|
||||||
class TestTopdirTrashFallback(TestExtVol):
|
class TestTopdirTrashFallback(TestExtVol):
|
||||||
@ -130,7 +187,17 @@ class TestTopdirTrashFallback(TestExtVol):
|
|||||||
touch(self.filePath)
|
touch(self.filePath)
|
||||||
s2t(self.filePath)
|
s2t(self.filePath)
|
||||||
self.assertFalse(op.exists(self.filePath))
|
self.assertFalse(op.exists(self.filePath))
|
||||||
self.assertTrue(op.exists(op.join(self.trashTopdir, '.Trash-' + str(os.getuid()), 'files', self.fileName)))
|
self.assertTrue(
|
||||||
|
op.exists(
|
||||||
|
op.join(
|
||||||
|
self.trashTopdir,
|
||||||
|
".Trash-" + str(os.getuid()),
|
||||||
|
"files",
|
||||||
|
self.fileName,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Test failure
|
# Test failure
|
||||||
class TestTopdirFailure(TestExtVol):
|
class TestTopdirFailure(TestExtVol):
|
||||||
@ -147,6 +214,7 @@ class TestTopdirFailure(TestExtVol):
|
|||||||
os.chmod(self.trashTopdir, 0o700) # writable to allow deletion
|
os.chmod(self.trashTopdir, 0o700) # writable to allow deletion
|
||||||
TestExtVol.tearDown(self)
|
TestExtVol.tearDown(self)
|
||||||
|
|
||||||
|
|
||||||
# Make sure it will find the mount point properly for a file in a symlinked path
|
# Make sure it will find the mount point properly for a file in a symlinked path
|
||||||
class TestSymlink(TestExtVol):
|
class TestSymlink(TestExtVol):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -154,21 +222,31 @@ class TestSymlink(TestExtVol):
|
|||||||
# Use mktemp (race conditioney but no symlink equivalent)
|
# Use mktemp (race conditioney but no symlink equivalent)
|
||||||
# Since is_parent uses realpath(), and our getdev uses is_parent,
|
# Since is_parent uses realpath(), and our getdev uses is_parent,
|
||||||
# this should work
|
# this should work
|
||||||
self.slDir = mktemp(prefix='s2t', dir=op.expanduser('~'))
|
self.slDir = mktemp(prefix="s2t", dir=op.expanduser("~"))
|
||||||
|
|
||||||
os.mkdir(op.join(self.trashTopdir, 'subdir'), 0o700)
|
os.mkdir(op.join(self.trashTopdir, "subdir"), 0o700)
|
||||||
self.filePath = op.join(self.trashTopdir, 'subdir', self.fileName)
|
self.filePath = op.join(self.trashTopdir, "subdir", self.fileName)
|
||||||
touch(self.filePath)
|
touch(self.filePath)
|
||||||
os.symlink(op.join(self.trashTopdir, 'subdir'), self.slDir)
|
os.symlink(op.join(self.trashTopdir, "subdir"), self.slDir)
|
||||||
|
|
||||||
def test_trash(self):
|
def test_trash(self):
|
||||||
s2t(op.join(self.slDir, self.fileName))
|
s2t(op.join(self.slDir, self.fileName))
|
||||||
self.assertFalse(op.exists(self.filePath))
|
self.assertFalse(op.exists(self.filePath))
|
||||||
self.assertTrue(op.exists(op.join(self.trashTopdir, '.Trash-' + str(os.getuid()), 'files', self.fileName)))
|
self.assertTrue(
|
||||||
|
op.exists(
|
||||||
|
op.join(
|
||||||
|
self.trashTopdir,
|
||||||
|
".Trash-" + str(os.getuid()),
|
||||||
|
"files",
|
||||||
|
self.fileName,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.remove(self.slDir)
|
os.remove(self.slDir)
|
||||||
TestExtVol.tearDown(self)
|
TestExtVol.tearDown(self)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -9,12 +9,16 @@ from tempfile import gettempdir
|
|||||||
from send2trash import send2trash as s2t
|
from send2trash import send2trash as s2t
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform != 'win32', 'Windows only')
|
@unittest.skipIf(sys.platform != "win32", "Windows only")
|
||||||
class TestNormal(unittest.TestCase):
|
class TestNormal(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.dirname = '\\\\?\\' + op.join(gettempdir(), 'python.send2trash')
|
self.dirname = "\\\\?\\" + op.join(gettempdir(), "python.send2trash")
|
||||||
self.file = op.join(self.dirname, 'testfile.txt')
|
self.file = op.join(self.dirname, "testfile.txt")
|
||||||
self._create_tree(self.file)
|
self._create_tree(self.file)
|
||||||
|
self.files = [
|
||||||
|
op.join(self.dirname, "testfile{}.txt".format(index)) for index in range(10)
|
||||||
|
]
|
||||||
|
[self._create_tree(file) for file in self.files]
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
shutil.rmtree(self.dirname, ignore_errors=True)
|
shutil.rmtree(self.dirname, ignore_errors=True)
|
||||||
@ -23,29 +27,38 @@ class TestNormal(unittest.TestCase):
|
|||||||
dirname = op.dirname(path)
|
dirname = op.dirname(path)
|
||||||
if not op.isdir(dirname):
|
if not op.isdir(dirname):
|
||||||
os.makedirs(dirname)
|
os.makedirs(dirname)
|
||||||
with open(path, 'w') as writer:
|
with open(path, "w") as writer:
|
||||||
writer.write('send2trash test')
|
writer.write("send2trash test")
|
||||||
|
|
||||||
def test_trash_file(self):
|
def test_trash_file(self):
|
||||||
s2t(self.file)
|
s2t(self.file)
|
||||||
self.assertFalse(op.exists(self.file))
|
self.assertFalse(op.exists(self.file))
|
||||||
|
|
||||||
|
def test_trash_multifile(self):
|
||||||
|
s2t(self.files)
|
||||||
|
self.assertFalse(any([op.exists(file) for file in self.files]))
|
||||||
|
|
||||||
def test_file_not_found(self):
|
def test_file_not_found(self):
|
||||||
file = op.join(self.dirname, 'otherfile.txt')
|
file = op.join(self.dirname, "otherfile.txt")
|
||||||
self.assertRaises(WindowsError, s2t, file)
|
self.assertRaises(WindowsError, s2t, file)
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform != 'win32', 'Windows only')
|
|
||||||
|
@unittest.skipIf(sys.platform != "win32", "Windows only")
|
||||||
class TestLongPath(unittest.TestCase):
|
class TestLongPath(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
filename = 'A' * 100
|
filename = "A" * 100
|
||||||
self.dirname = '\\\\?\\' + op.join(gettempdir(), filename)
|
self.dirname = "\\\\?\\" + op.join(gettempdir(), filename)
|
||||||
self.file = op.join(
|
path = op.join(
|
||||||
self.dirname,
|
self.dirname,
|
||||||
filename,
|
filename,
|
||||||
filename, # From there, the path is not trashable from Explorer
|
filename, # From there, the path is not trashable from Explorer
|
||||||
filename,
|
filename,
|
||||||
filename + '.txt')
|
filename + "{}.txt",
|
||||||
|
)
|
||||||
|
self.file = path.format("")
|
||||||
self._create_tree(self.file)
|
self._create_tree(self.file)
|
||||||
|
self.files = [path.format(index) for index in range(10)]
|
||||||
|
[self._create_tree(file) for file in self.files]
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
shutil.rmtree(self.dirname, ignore_errors=True)
|
shutil.rmtree(self.dirname, ignore_errors=True)
|
||||||
@ -54,16 +67,21 @@ class TestLongPath(unittest.TestCase):
|
|||||||
dirname = op.dirname(path)
|
dirname = op.dirname(path)
|
||||||
if not op.isdir(dirname):
|
if not op.isdir(dirname):
|
||||||
os.makedirs(dirname)
|
os.makedirs(dirname)
|
||||||
with open(path, 'w') as writer:
|
with open(path, "w") as writer:
|
||||||
writer.write('Looong filename!')
|
writer.write("Looong filename!")
|
||||||
|
|
||||||
def test_trash_file(self):
|
def test_trash_file(self):
|
||||||
s2t(self.file)
|
s2t(self.file)
|
||||||
self.assertFalse(op.exists(self.file))
|
self.assertFalse(op.exists(self.file))
|
||||||
|
|
||||||
|
def test_trash_multifile(self):
|
||||||
|
s2t(self.files)
|
||||||
|
self.assertFalse(any([op.exists(file) for file in self.files]))
|
||||||
|
|
||||||
@unittest.skipIf(
|
@unittest.skipIf(
|
||||||
op.splitdrive(os.getcwd())[0] != op.splitdrive(gettempdir())[0],
|
op.splitdrive(os.getcwd())[0] != op.splitdrive(gettempdir())[0],
|
||||||
'Cannot trash long path from other drive')
|
"Cannot trash long path from other drive",
|
||||||
|
)
|
||||||
def test_trash_folder(self):
|
def test_trash_folder(self):
|
||||||
s2t(self.dirname)
|
s2t(self.dirname)
|
||||||
self.assertFalse(op.exists(self.dirname))
|
self.assertFalse(op.exists(self.dirname))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user