1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/testing/mozbase/mozfile/tests/test_remove.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,184 @@ 1.4 +#!/usr/bin/env python 1.5 + 1.6 +import os 1.7 +import stat 1.8 +import shutil 1.9 +import tempfile 1.10 +import threading 1.11 +import time 1.12 +import unittest 1.13 + 1.14 +import mozfile 1.15 +import mozinfo 1.16 + 1.17 +import stubs 1.18 + 1.19 + 1.20 +def mark_readonly(path): 1.21 + """Removes all write permissions from given file/directory. 1.22 + 1.23 + :param path: path of directory/file of which modes must be changed 1.24 + """ 1.25 + mode = os.stat(path)[stat.ST_MODE] 1.26 + os.chmod(path, mode & ~stat.S_IWUSR & ~stat.S_IWGRP & ~stat.S_IWOTH) 1.27 + 1.28 + 1.29 +class FileOpenCloseThread(threading.Thread): 1.30 + """Helper thread for asynchronous file handling""" 1.31 + def __init__(self, path, delay, delete=False): 1.32 + threading.Thread.__init__(self) 1.33 + self.delay = delay 1.34 + self.path = path 1.35 + self.delete = delete 1.36 + 1.37 + def run(self): 1.38 + with open(self.path) as f: 1.39 + time.sleep(self.delay) 1.40 + if self.delete: 1.41 + try: 1.42 + os.remove(self.path) 1.43 + except: 1.44 + pass 1.45 + 1.46 + 1.47 +class MozfileRemoveTestCase(unittest.TestCase): 1.48 + """Test our ability to remove directories and files""" 1.49 + 1.50 + def setUp(self): 1.51 + # Generate a stub 1.52 + self.tempdir = stubs.create_stub() 1.53 + 1.54 + def tearDown(self): 1.55 + if os.path.isdir(self.tempdir): 1.56 + shutil.rmtree(self.tempdir) 1.57 + 1.58 + def test_remove_directory(self): 1.59 + """Test the removal of a directory""" 1.60 + self.assertTrue(os.path.isdir(self.tempdir)) 1.61 + mozfile.remove(self.tempdir) 1.62 + self.assertFalse(os.path.exists(self.tempdir)) 1.63 + 1.64 + def test_remove_directory_with_open_file(self): 1.65 + """Test removing a directory with an open file""" 1.66 + # Open a file in the generated stub 1.67 + filepath = os.path.join(self.tempdir, *stubs.files[1]) 1.68 + f = file(filepath, 'w') 1.69 + f.write('foo-bar') 1.70 + 1.71 + # keep file open and then try removing the dir-tree 1.72 + if mozinfo.isWin: 1.73 + # On the Windows family WindowsError should be raised. 1.74 + self.assertRaises(OSError, mozfile.remove, self.tempdir) 1.75 + self.assertTrue(os.path.exists(self.tempdir)) 1.76 + else: 1.77 + # Folder should be deleted on all other platforms 1.78 + mozfile.remove(self.tempdir) 1.79 + self.assertFalse(os.path.exists(self.tempdir)) 1.80 + 1.81 + def test_remove_closed_file(self): 1.82 + """Test removing a closed file""" 1.83 + # Open a file in the generated stub 1.84 + filepath = os.path.join(self.tempdir, *stubs.files[1]) 1.85 + with open(filepath, 'w') as f: 1.86 + f.write('foo-bar') 1.87 + 1.88 + # Folder should be deleted on all platforms 1.89 + mozfile.remove(self.tempdir) 1.90 + self.assertFalse(os.path.exists(self.tempdir)) 1.91 + 1.92 + def test_removing_open_file_with_retry(self): 1.93 + """Test removing a file in use with retry""" 1.94 + filepath = os.path.join(self.tempdir, *stubs.files[1]) 1.95 + 1.96 + thread = FileOpenCloseThread(filepath, 1) 1.97 + thread.start() 1.98 + 1.99 + # Wait a bit so we can be sure the file has been opened 1.100 + time.sleep(.5) 1.101 + mozfile.remove(filepath) 1.102 + thread.join() 1.103 + 1.104 + # Check deletion was successful 1.105 + self.assertFalse(os.path.exists(filepath)) 1.106 + 1.107 + def test_removing_already_deleted_file_with_retry(self): 1.108 + """Test removing a meanwhile removed file with retry""" 1.109 + filepath = os.path.join(self.tempdir, *stubs.files[1]) 1.110 + 1.111 + thread = FileOpenCloseThread(filepath, .8, True) 1.112 + thread.start() 1.113 + 1.114 + # Wait a bit so we can be sure the file has been opened and gets deleted 1.115 + # while remove() waits for the next retry 1.116 + time.sleep(.5) 1.117 + mozfile.remove(filepath) 1.118 + thread.join() 1.119 + 1.120 + # Check deletion was successful 1.121 + self.assertFalse(os.path.exists(filepath)) 1.122 + 1.123 + def test_remove_readonly_tree(self): 1.124 + """Test removing a read-only directory""" 1.125 + 1.126 + dirpath = os.path.join(self.tempdir, "nested_tree") 1.127 + mark_readonly(dirpath) 1.128 + 1.129 + # However, mozfile should change write permissions and remove dir. 1.130 + mozfile.remove(dirpath) 1.131 + 1.132 + self.assertFalse(os.path.exists(dirpath)) 1.133 + 1.134 + def test_remove_readonly_file(self): 1.135 + """Test removing read-only files""" 1.136 + filepath = os.path.join(self.tempdir, *stubs.files[1]) 1.137 + mark_readonly(filepath) 1.138 + 1.139 + # However, mozfile should change write permission and then remove file. 1.140 + mozfile.remove(filepath) 1.141 + 1.142 + self.assertFalse(os.path.exists(filepath)) 1.143 + 1.144 + @unittest.skipIf(mozinfo.isWin, "Symlinks are not supported on Windows") 1.145 + def test_remove_symlink(self): 1.146 + """Test removing a symlink""" 1.147 + file_path = os.path.join(self.tempdir, *stubs.files[1]) 1.148 + symlink_path = os.path.join(self.tempdir, 'symlink') 1.149 + 1.150 + os.symlink(file_path, symlink_path) 1.151 + self.assertTrue(os.path.islink(symlink_path)) 1.152 + 1.153 + # The linked folder and files should not be deleted 1.154 + mozfile.remove(symlink_path) 1.155 + self.assertFalse(os.path.exists(symlink_path)) 1.156 + self.assertTrue(os.path.exists(file_path)) 1.157 + 1.158 + @unittest.skipIf(mozinfo.isWin, "Symlinks are not supported on Windows") 1.159 + def test_remove_symlink_in_subfolder(self): 1.160 + """Test removing a folder with an contained symlink""" 1.161 + file_path = os.path.join(self.tempdir, *stubs.files[0]) 1.162 + dir_path = os.path.dirname(os.path.join(self.tempdir, *stubs.files[1])) 1.163 + symlink_path = os.path.join(dir_path, 'symlink') 1.164 + 1.165 + os.symlink(file_path, symlink_path) 1.166 + self.assertTrue(os.path.islink(symlink_path)) 1.167 + 1.168 + # The folder with the contained symlink will be deleted but not the 1.169 + # original linked file 1.170 + mozfile.remove(dir_path) 1.171 + self.assertFalse(os.path.exists(dir_path)) 1.172 + self.assertFalse(os.path.exists(symlink_path)) 1.173 + self.assertTrue(os.path.exists(file_path)) 1.174 + 1.175 + @unittest.skipIf(mozinfo.isWin or not os.geteuid(), 1.176 + "Symlinks are not supported on Windows and cannot run test as root") 1.177 + def test_remove_symlink_for_system_path(self): 1.178 + """Test removing a symlink which points to a system folder""" 1.179 + symlink_path = os.path.join(self.tempdir, 'symlink') 1.180 + 1.181 + os.symlink(os.path.dirname(self.tempdir), symlink_path) 1.182 + self.assertTrue(os.path.islink(symlink_path)) 1.183 + 1.184 + # The folder with the contained symlink will be deleted but not the 1.185 + # original linked file 1.186 + mozfile.remove(symlink_path) 1.187 + self.assertFalse(os.path.exists(symlink_path))