PageRenderTime 1319ms CodeModel.GetById 379ms app.highlight 213ms RepoModel.GetById 723ms app.codeStats 0ms

/Lib/test/test_shutil.py

http://unladen-swallow.googlecode.com/
Python | 371 lines | 286 code | 49 blank | 36 comment | 36 complexity | ad42697afba722289aad1fcb9ae5c6d2 MD5 | raw file
  1# Copyright (C) 2003 Python Software Foundation
  2
  3import unittest
  4import shutil
  5import tempfile
  6import sys
  7import stat
  8import os
  9import os.path
 10from test import test_support
 11from test.test_support import TESTFN
 12
 13class TestShutil(unittest.TestCase):
 14    def test_rmtree_errors(self):
 15        # filename is guaranteed not to exist
 16        filename = tempfile.mktemp()
 17        self.assertRaises(OSError, shutil.rmtree, filename)
 18
 19    # See bug #1071513 for why we don't run this on cygwin
 20    # and bug #1076467 for why we don't run this as root.
 21    if (hasattr(os, 'chmod') and sys.platform[:6] != 'cygwin'
 22        and not (hasattr(os, 'geteuid') and os.geteuid() == 0)):
 23        def test_on_error(self):
 24            self.errorState = 0
 25            os.mkdir(TESTFN)
 26            self.childpath = os.path.join(TESTFN, 'a')
 27            f = open(self.childpath, 'w')
 28            f.close()
 29            old_dir_mode = os.stat(TESTFN).st_mode
 30            old_child_mode = os.stat(self.childpath).st_mode
 31            # Make unwritable.
 32            os.chmod(self.childpath, stat.S_IREAD)
 33            os.chmod(TESTFN, stat.S_IREAD)
 34
 35            shutil.rmtree(TESTFN, onerror=self.check_args_to_onerror)
 36            # Test whether onerror has actually been called.
 37            self.assertEqual(self.errorState, 2,
 38                             "Expected call to onerror function did not happen.")
 39
 40            # Make writable again.
 41            os.chmod(TESTFN, old_dir_mode)
 42            os.chmod(self.childpath, old_child_mode)
 43
 44            # Clean up.
 45            shutil.rmtree(TESTFN)
 46
 47    def check_args_to_onerror(self, func, arg, exc):
 48        if self.errorState == 0:
 49            self.assertEqual(func, os.remove)
 50            self.assertEqual(arg, self.childpath)
 51            self.failUnless(issubclass(exc[0], OSError))
 52            self.errorState = 1
 53        else:
 54            self.assertEqual(func, os.rmdir)
 55            self.assertEqual(arg, TESTFN)
 56            self.failUnless(issubclass(exc[0], OSError))
 57            self.errorState = 2
 58
 59    def test_rmtree_dont_delete_file(self):
 60        # When called on a file instead of a directory, don't delete it.
 61        handle, path = tempfile.mkstemp()
 62        os.fdopen(handle).close()
 63        self.assertRaises(OSError, shutil.rmtree, path)
 64        os.remove(path)
 65
 66    def test_copytree_simple(self):
 67        def write_data(path, data):
 68            f = open(path, "w")
 69            f.write(data)
 70            f.close()
 71
 72        def read_data(path):
 73            f = open(path)
 74            data = f.read()
 75            f.close()
 76            return data
 77
 78        src_dir = tempfile.mkdtemp()
 79        dst_dir = os.path.join(tempfile.mkdtemp(), 'destination')
 80
 81        write_data(os.path.join(src_dir, 'test.txt'), '123')
 82
 83        os.mkdir(os.path.join(src_dir, 'test_dir'))
 84        write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456')
 85
 86        try:
 87            shutil.copytree(src_dir, dst_dir)
 88            self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test.txt')))
 89            self.assertTrue(os.path.isdir(os.path.join(dst_dir, 'test_dir')))
 90            self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test_dir',
 91                                                        'test.txt')))
 92            actual = read_data(os.path.join(dst_dir, 'test.txt'))
 93            self.assertEqual(actual, '123')
 94            actual = read_data(os.path.join(dst_dir, 'test_dir', 'test.txt'))
 95            self.assertEqual(actual, '456')
 96        finally:
 97            for path in (
 98                    os.path.join(src_dir, 'test.txt'),
 99                    os.path.join(dst_dir, 'test.txt'),
100                    os.path.join(src_dir, 'test_dir', 'test.txt'),
101                    os.path.join(dst_dir, 'test_dir', 'test.txt'),
102                ):
103                if os.path.exists(path):
104                    os.remove(path)
105            for path in (src_dir,
106                    os.path.abspath(os.path.join(dst_dir, os.path.pardir))
107                ):
108                if os.path.exists(path):
109                    shutil.rmtree(path)
110
111    def test_copytree_with_exclude(self):
112
113        def write_data(path, data):
114            f = open(path, "w")
115            f.write(data)
116            f.close()
117
118        def read_data(path):
119            f = open(path)
120            data = f.read()
121            f.close()
122            return data
123
124        # creating data
125        join = os.path.join
126        exists = os.path.exists
127        src_dir = tempfile.mkdtemp()
128        dst_dir = join(tempfile.mkdtemp(), 'destination')
129        write_data(join(src_dir, 'test.txt'), '123')
130        write_data(join(src_dir, 'test.tmp'), '123')
131        os.mkdir(join(src_dir, 'test_dir'))
132        write_data(join(src_dir, 'test_dir', 'test.txt'), '456')
133        os.mkdir(join(src_dir, 'test_dir2'))
134        write_data(join(src_dir, 'test_dir2', 'test.txt'), '456')
135        os.mkdir(join(src_dir, 'test_dir2', 'subdir'))
136        os.mkdir(join(src_dir, 'test_dir2', 'subdir2'))
137        write_data(join(src_dir, 'test_dir2', 'subdir', 'test.txt'), '456')
138        write_data(join(src_dir, 'test_dir2', 'subdir2', 'test.py'), '456')
139
140
141        # testing glob-like patterns
142        try:
143            patterns = shutil.ignore_patterns('*.tmp', 'test_dir2')
144            shutil.copytree(src_dir, dst_dir, ignore=patterns)
145            # checking the result: some elements should not be copied
146            self.assert_(exists(join(dst_dir, 'test.txt')))
147            self.assert_(not exists(join(dst_dir, 'test.tmp')))
148            self.assert_(not exists(join(dst_dir, 'test_dir2')))
149        finally:
150            if os.path.exists(dst_dir):
151                shutil.rmtree(dst_dir)
152        try:
153            patterns = shutil.ignore_patterns('*.tmp', 'subdir*')
154            shutil.copytree(src_dir, dst_dir, ignore=patterns)
155            # checking the result: some elements should not be copied
156            self.assert_(not exists(join(dst_dir, 'test.tmp')))
157            self.assert_(not exists(join(dst_dir, 'test_dir2', 'subdir2')))
158            self.assert_(not exists(join(dst_dir, 'test_dir2', 'subdir')))
159        finally:
160            if os.path.exists(dst_dir):
161                shutil.rmtree(dst_dir)
162
163        # testing callable-style
164        try:
165            def _filter(src, names):
166                res = []
167                for name in names:
168                    path = os.path.join(src, name)
169
170                    if (os.path.isdir(path) and
171                        path.split()[-1] == 'subdir'):
172                        res.append(name)
173                    elif os.path.splitext(path)[-1] in ('.py'):
174                        res.append(name)
175                return res
176
177            shutil.copytree(src_dir, dst_dir, ignore=_filter)
178
179            # checking the result: some elements should not be copied
180            self.assert_(not exists(join(dst_dir, 'test_dir2', 'subdir2',
181                                    'test.py')))
182            self.assert_(not exists(join(dst_dir, 'test_dir2', 'subdir')))
183
184        finally:
185            if os.path.exists(dst_dir):
186                shutil.rmtree(dst_dir)
187
188    if hasattr(os, "symlink"):
189        def test_dont_copy_file_onto_link_to_itself(self):
190            # bug 851123.
191            os.mkdir(TESTFN)
192            src = os.path.join(TESTFN, 'cheese')
193            dst = os.path.join(TESTFN, 'shop')
194            try:
195                f = open(src, 'w')
196                f.write('cheddar')
197                f.close()
198
199                os.link(src, dst)
200                self.assertRaises(shutil.Error, shutil.copyfile, src, dst)
201                self.assertEqual(open(src,'r').read(), 'cheddar')
202                os.remove(dst)
203
204                # Using `src` here would mean we end up with a symlink pointing
205                # to TESTFN/TESTFN/cheese, while it should point at
206                # TESTFN/cheese.
207                os.symlink('cheese', dst)
208                self.assertRaises(shutil.Error, shutil.copyfile, src, dst)
209                self.assertEqual(open(src,'r').read(), 'cheddar')
210                os.remove(dst)
211            finally:
212                try:
213                    shutil.rmtree(TESTFN)
214                except OSError:
215                    pass
216
217        def test_rmtree_on_symlink(self):
218            # bug 1669.
219            os.mkdir(TESTFN)
220            try:
221                src = os.path.join(TESTFN, 'cheese')
222                dst = os.path.join(TESTFN, 'shop')
223                os.mkdir(src)
224                os.symlink(src, dst)
225                self.assertRaises(OSError, shutil.rmtree, dst)
226            finally:
227                shutil.rmtree(TESTFN, ignore_errors=True)
228
229
230class TestMove(unittest.TestCase):
231
232    def setUp(self):
233        filename = "foo"
234        self.src_dir = tempfile.mkdtemp()
235        self.dst_dir = tempfile.mkdtemp()
236        self.src_file = os.path.join(self.src_dir, filename)
237        self.dst_file = os.path.join(self.dst_dir, filename)
238        # Try to create a dir in the current directory, hoping that it is
239        # not located on the same filesystem as the system tmp dir.
240        try:
241            self.dir_other_fs = tempfile.mkdtemp(
242                dir=os.path.dirname(__file__))
243            self.file_other_fs = os.path.join(self.dir_other_fs,
244                filename)
245        except OSError:
246            self.dir_other_fs = None
247        with open(self.src_file, "wb") as f:
248            f.write("spam")
249
250    def tearDown(self):
251        for d in (self.src_dir, self.dst_dir, self.dir_other_fs):
252            try:
253                if d:
254                    shutil.rmtree(d)
255            except:
256                pass
257
258    def _check_move_file(self, src, dst, real_dst):
259        contents = open(src, "rb").read()
260        shutil.move(src, dst)
261        self.assertEqual(contents, open(real_dst, "rb").read())
262        self.assertFalse(os.path.exists(src))
263
264    def _check_move_dir(self, src, dst, real_dst):
265        contents = sorted(os.listdir(src))
266        shutil.move(src, dst)
267        self.assertEqual(contents, sorted(os.listdir(real_dst)))
268        self.assertFalse(os.path.exists(src))
269
270    def test_move_file(self):
271        # Move a file to another location on the same filesystem.
272        self._check_move_file(self.src_file, self.dst_file, self.dst_file)
273
274    def test_move_file_to_dir(self):
275        # Move a file inside an existing dir on the same filesystem.
276        self._check_move_file(self.src_file, self.dst_dir, self.dst_file)
277
278    def test_move_file_other_fs(self):
279        # Move a file to an existing dir on another filesystem.
280        if not self.dir_other_fs:
281            # skip
282            return
283        self._check_move_file(self.src_file, self.file_other_fs,
284            self.file_other_fs)
285
286    def test_move_file_to_dir_other_fs(self):
287        # Move a file to another location on another filesystem.
288        if not self.dir_other_fs:
289            # skip
290            return
291        self._check_move_file(self.src_file, self.dir_other_fs,
292            self.file_other_fs)
293
294    def test_move_dir(self):
295        # Move a dir to another location on the same filesystem.
296        dst_dir = tempfile.mktemp()
297        try:
298            self._check_move_dir(self.src_dir, dst_dir, dst_dir)
299        finally:
300            try:
301                shutil.rmtree(dst_dir)
302            except:
303                pass
304
305    def test_move_dir_other_fs(self):
306        # Move a dir to another location on another filesystem.
307        if not self.dir_other_fs:
308            # skip
309            return
310        dst_dir = tempfile.mktemp(dir=self.dir_other_fs)
311        try:
312            self._check_move_dir(self.src_dir, dst_dir, dst_dir)
313        finally:
314            try:
315                shutil.rmtree(dst_dir)
316            except:
317                pass
318
319    def test_move_dir_to_dir(self):
320        # Move a dir inside an existing dir on the same filesystem.
321        self._check_move_dir(self.src_dir, self.dst_dir,
322            os.path.join(self.dst_dir, os.path.basename(self.src_dir)))
323
324    def test_move_dir_to_dir_other_fs(self):
325        # Move a dir inside an existing dir on another filesystem.
326        if not self.dir_other_fs:
327            # skip
328            return
329        self._check_move_dir(self.src_dir, self.dir_other_fs,
330            os.path.join(self.dir_other_fs, os.path.basename(self.src_dir)))
331
332    def test_existing_file_inside_dest_dir(self):
333        # A file with the same name inside the destination dir already exists.
334        with open(self.dst_file, "wb"):
335            pass
336        self.assertRaises(shutil.Error, shutil.move, self.src_file, self.dst_dir)
337
338    def test_dont_move_dir_in_itself(self):
339        # Moving a dir inside itself raises an Error.
340        dst = os.path.join(self.src_dir, "bar")
341        self.assertRaises(shutil.Error, shutil.move, self.src_dir, dst)
342
343    def test_destinsrc_false_negative(self):
344        os.mkdir(TESTFN)
345        try:
346            for src, dst in [('srcdir', 'srcdir/dest')]:
347                src = os.path.join(TESTFN, src)
348                dst = os.path.join(TESTFN, dst)
349                self.assert_(shutil.destinsrc(src, dst),
350                             msg='destinsrc() wrongly concluded that '
351                             'dst (%s) is not in src (%s)' % (dst, src))
352        finally:
353            shutil.rmtree(TESTFN, ignore_errors=True)
354
355    def test_destinsrc_false_positive(self):
356        os.mkdir(TESTFN)
357        try:
358            for src, dst in [('srcdir', 'src/dest'), ('srcdir', 'srcdir.new')]:
359                src = os.path.join(TESTFN, src)
360                dst = os.path.join(TESTFN, dst)
361                self.failIf(shutil.destinsrc(src, dst),
362                            msg='destinsrc() wrongly concluded that '
363                            'dst (%s) is in src (%s)' % (dst, src))
364        finally:
365            shutil.rmtree(TESTFN, ignore_errors=True)
366
367def test_main():
368    test_support.run_unittest(TestShutil, TestMove)
369
370if __name__ == '__main__':
371    test_main()