testing/mozbase/mozfile/tests/test_remove.py

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 #!/usr/bin/env python
michael@0 2
michael@0 3 import os
michael@0 4 import stat
michael@0 5 import shutil
michael@0 6 import tempfile
michael@0 7 import threading
michael@0 8 import time
michael@0 9 import unittest
michael@0 10
michael@0 11 import mozfile
michael@0 12 import mozinfo
michael@0 13
michael@0 14 import stubs
michael@0 15
michael@0 16
michael@0 17 def mark_readonly(path):
michael@0 18 """Removes all write permissions from given file/directory.
michael@0 19
michael@0 20 :param path: path of directory/file of which modes must be changed
michael@0 21 """
michael@0 22 mode = os.stat(path)[stat.ST_MODE]
michael@0 23 os.chmod(path, mode & ~stat.S_IWUSR & ~stat.S_IWGRP & ~stat.S_IWOTH)
michael@0 24
michael@0 25
michael@0 26 class FileOpenCloseThread(threading.Thread):
michael@0 27 """Helper thread for asynchronous file handling"""
michael@0 28 def __init__(self, path, delay, delete=False):
michael@0 29 threading.Thread.__init__(self)
michael@0 30 self.delay = delay
michael@0 31 self.path = path
michael@0 32 self.delete = delete
michael@0 33
michael@0 34 def run(self):
michael@0 35 with open(self.path) as f:
michael@0 36 time.sleep(self.delay)
michael@0 37 if self.delete:
michael@0 38 try:
michael@0 39 os.remove(self.path)
michael@0 40 except:
michael@0 41 pass
michael@0 42
michael@0 43
michael@0 44 class MozfileRemoveTestCase(unittest.TestCase):
michael@0 45 """Test our ability to remove directories and files"""
michael@0 46
michael@0 47 def setUp(self):
michael@0 48 # Generate a stub
michael@0 49 self.tempdir = stubs.create_stub()
michael@0 50
michael@0 51 def tearDown(self):
michael@0 52 if os.path.isdir(self.tempdir):
michael@0 53 shutil.rmtree(self.tempdir)
michael@0 54
michael@0 55 def test_remove_directory(self):
michael@0 56 """Test the removal of a directory"""
michael@0 57 self.assertTrue(os.path.isdir(self.tempdir))
michael@0 58 mozfile.remove(self.tempdir)
michael@0 59 self.assertFalse(os.path.exists(self.tempdir))
michael@0 60
michael@0 61 def test_remove_directory_with_open_file(self):
michael@0 62 """Test removing a directory with an open file"""
michael@0 63 # Open a file in the generated stub
michael@0 64 filepath = os.path.join(self.tempdir, *stubs.files[1])
michael@0 65 f = file(filepath, 'w')
michael@0 66 f.write('foo-bar')
michael@0 67
michael@0 68 # keep file open and then try removing the dir-tree
michael@0 69 if mozinfo.isWin:
michael@0 70 # On the Windows family WindowsError should be raised.
michael@0 71 self.assertRaises(OSError, mozfile.remove, self.tempdir)
michael@0 72 self.assertTrue(os.path.exists(self.tempdir))
michael@0 73 else:
michael@0 74 # Folder should be deleted on all other platforms
michael@0 75 mozfile.remove(self.tempdir)
michael@0 76 self.assertFalse(os.path.exists(self.tempdir))
michael@0 77
michael@0 78 def test_remove_closed_file(self):
michael@0 79 """Test removing a closed file"""
michael@0 80 # Open a file in the generated stub
michael@0 81 filepath = os.path.join(self.tempdir, *stubs.files[1])
michael@0 82 with open(filepath, 'w') as f:
michael@0 83 f.write('foo-bar')
michael@0 84
michael@0 85 # Folder should be deleted on all platforms
michael@0 86 mozfile.remove(self.tempdir)
michael@0 87 self.assertFalse(os.path.exists(self.tempdir))
michael@0 88
michael@0 89 def test_removing_open_file_with_retry(self):
michael@0 90 """Test removing a file in use with retry"""
michael@0 91 filepath = os.path.join(self.tempdir, *stubs.files[1])
michael@0 92
michael@0 93 thread = FileOpenCloseThread(filepath, 1)
michael@0 94 thread.start()
michael@0 95
michael@0 96 # Wait a bit so we can be sure the file has been opened
michael@0 97 time.sleep(.5)
michael@0 98 mozfile.remove(filepath)
michael@0 99 thread.join()
michael@0 100
michael@0 101 # Check deletion was successful
michael@0 102 self.assertFalse(os.path.exists(filepath))
michael@0 103
michael@0 104 def test_removing_already_deleted_file_with_retry(self):
michael@0 105 """Test removing a meanwhile removed file with retry"""
michael@0 106 filepath = os.path.join(self.tempdir, *stubs.files[1])
michael@0 107
michael@0 108 thread = FileOpenCloseThread(filepath, .8, True)
michael@0 109 thread.start()
michael@0 110
michael@0 111 # Wait a bit so we can be sure the file has been opened and gets deleted
michael@0 112 # while remove() waits for the next retry
michael@0 113 time.sleep(.5)
michael@0 114 mozfile.remove(filepath)
michael@0 115 thread.join()
michael@0 116
michael@0 117 # Check deletion was successful
michael@0 118 self.assertFalse(os.path.exists(filepath))
michael@0 119
michael@0 120 def test_remove_readonly_tree(self):
michael@0 121 """Test removing a read-only directory"""
michael@0 122
michael@0 123 dirpath = os.path.join(self.tempdir, "nested_tree")
michael@0 124 mark_readonly(dirpath)
michael@0 125
michael@0 126 # However, mozfile should change write permissions and remove dir.
michael@0 127 mozfile.remove(dirpath)
michael@0 128
michael@0 129 self.assertFalse(os.path.exists(dirpath))
michael@0 130
michael@0 131 def test_remove_readonly_file(self):
michael@0 132 """Test removing read-only files"""
michael@0 133 filepath = os.path.join(self.tempdir, *stubs.files[1])
michael@0 134 mark_readonly(filepath)
michael@0 135
michael@0 136 # However, mozfile should change write permission and then remove file.
michael@0 137 mozfile.remove(filepath)
michael@0 138
michael@0 139 self.assertFalse(os.path.exists(filepath))
michael@0 140
michael@0 141 @unittest.skipIf(mozinfo.isWin, "Symlinks are not supported on Windows")
michael@0 142 def test_remove_symlink(self):
michael@0 143 """Test removing a symlink"""
michael@0 144 file_path = os.path.join(self.tempdir, *stubs.files[1])
michael@0 145 symlink_path = os.path.join(self.tempdir, 'symlink')
michael@0 146
michael@0 147 os.symlink(file_path, symlink_path)
michael@0 148 self.assertTrue(os.path.islink(symlink_path))
michael@0 149
michael@0 150 # The linked folder and files should not be deleted
michael@0 151 mozfile.remove(symlink_path)
michael@0 152 self.assertFalse(os.path.exists(symlink_path))
michael@0 153 self.assertTrue(os.path.exists(file_path))
michael@0 154
michael@0 155 @unittest.skipIf(mozinfo.isWin, "Symlinks are not supported on Windows")
michael@0 156 def test_remove_symlink_in_subfolder(self):
michael@0 157 """Test removing a folder with an contained symlink"""
michael@0 158 file_path = os.path.join(self.tempdir, *stubs.files[0])
michael@0 159 dir_path = os.path.dirname(os.path.join(self.tempdir, *stubs.files[1]))
michael@0 160 symlink_path = os.path.join(dir_path, 'symlink')
michael@0 161
michael@0 162 os.symlink(file_path, symlink_path)
michael@0 163 self.assertTrue(os.path.islink(symlink_path))
michael@0 164
michael@0 165 # The folder with the contained symlink will be deleted but not the
michael@0 166 # original linked file
michael@0 167 mozfile.remove(dir_path)
michael@0 168 self.assertFalse(os.path.exists(dir_path))
michael@0 169 self.assertFalse(os.path.exists(symlink_path))
michael@0 170 self.assertTrue(os.path.exists(file_path))
michael@0 171
michael@0 172 @unittest.skipIf(mozinfo.isWin or not os.geteuid(),
michael@0 173 "Symlinks are not supported on Windows and cannot run test as root")
michael@0 174 def test_remove_symlink_for_system_path(self):
michael@0 175 """Test removing a symlink which points to a system folder"""
michael@0 176 symlink_path = os.path.join(self.tempdir, 'symlink')
michael@0 177
michael@0 178 os.symlink(os.path.dirname(self.tempdir), symlink_path)
michael@0 179 self.assertTrue(os.path.islink(symlink_path))
michael@0 180
michael@0 181 # The folder with the contained symlink will be deleted but not the
michael@0 182 # original linked file
michael@0 183 mozfile.remove(symlink_path)
michael@0 184 self.assertFalse(os.path.exists(symlink_path))

mercurial