testing/mozbase/mozfile/tests/test_remove.py

changeset 0
6474c204b198
     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))

mercurial