|
1 # Copyright (C) 2003 Python Software Foundation |
|
2 |
|
3 import unittest |
|
4 import shutil |
|
5 import tempfile |
|
6 import sys |
|
7 import stat |
|
8 import os |
|
9 import os.path |
|
10 from test import test_support |
|
11 from test.test_support import TESTFN |
|
12 |
|
13 class 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_dont_move_dir_in_itself(self): |
|
67 src_dir = tempfile.mkdtemp() |
|
68 try: |
|
69 dst = os.path.join(src_dir, 'foo') |
|
70 self.assertRaises(shutil.Error, shutil.move, src_dir, dst) |
|
71 finally: |
|
72 try: |
|
73 os.rmdir(src_dir) |
|
74 except: |
|
75 pass |
|
76 |
|
77 def test_copytree_simple(self): |
|
78 def write_data(path, data): |
|
79 f = open(path, "w") |
|
80 f.write(data) |
|
81 f.close() |
|
82 |
|
83 def read_data(path): |
|
84 f = open(path) |
|
85 data = f.read() |
|
86 f.close() |
|
87 return data |
|
88 |
|
89 src_dir = tempfile.mkdtemp() |
|
90 dst_dir = os.path.join(tempfile.mkdtemp(), 'destination') |
|
91 |
|
92 write_data(os.path.join(src_dir, 'test.txt'), '123') |
|
93 |
|
94 os.mkdir(os.path.join(src_dir, 'test_dir')) |
|
95 write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456') |
|
96 |
|
97 try: |
|
98 shutil.copytree(src_dir, dst_dir) |
|
99 self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test.txt'))) |
|
100 self.assertTrue(os.path.isdir(os.path.join(dst_dir, 'test_dir'))) |
|
101 self.assertTrue(os.path.isfile(os.path.join(dst_dir, 'test_dir', |
|
102 'test.txt'))) |
|
103 actual = read_data(os.path.join(dst_dir, 'test.txt')) |
|
104 self.assertEqual(actual, '123') |
|
105 actual = read_data(os.path.join(dst_dir, 'test_dir', 'test.txt')) |
|
106 self.assertEqual(actual, '456') |
|
107 finally: |
|
108 for path in ( |
|
109 os.path.join(src_dir, 'test.txt'), |
|
110 os.path.join(dst_dir, 'test.txt'), |
|
111 os.path.join(src_dir, 'test_dir', 'test.txt'), |
|
112 os.path.join(dst_dir, 'test_dir', 'test.txt'), |
|
113 ): |
|
114 if os.path.exists(path): |
|
115 os.remove(path) |
|
116 for path in ( |
|
117 os.path.join(src_dir, 'test_dir'), |
|
118 os.path.join(dst_dir, 'test_dir'), |
|
119 ): |
|
120 if os.path.exists(path): |
|
121 os.removedirs(path) |
|
122 |
|
123 |
|
124 if hasattr(os, "symlink"): |
|
125 def test_dont_copy_file_onto_link_to_itself(self): |
|
126 # bug 851123. |
|
127 os.mkdir(TESTFN) |
|
128 src = os.path.join(TESTFN, 'cheese') |
|
129 dst = os.path.join(TESTFN, 'shop') |
|
130 try: |
|
131 f = open(src, 'w') |
|
132 f.write('cheddar') |
|
133 f.close() |
|
134 |
|
135 os.link(src, dst) |
|
136 self.assertRaises(shutil.Error, shutil.copyfile, src, dst) |
|
137 self.assertEqual(open(src,'r').read(), 'cheddar') |
|
138 os.remove(dst) |
|
139 |
|
140 # Using `src` here would mean we end up with a symlink pointing |
|
141 # to TESTFN/TESTFN/cheese, while it should point at |
|
142 # TESTFN/cheese. |
|
143 os.symlink('cheese', dst) |
|
144 self.assertRaises(shutil.Error, shutil.copyfile, src, dst) |
|
145 self.assertEqual(open(src,'r').read(), 'cheddar') |
|
146 os.remove(dst) |
|
147 finally: |
|
148 try: |
|
149 shutil.rmtree(TESTFN) |
|
150 except OSError: |
|
151 pass |
|
152 |
|
153 def test_main(): |
|
154 test_support.run_unittest(TestShutil) |
|
155 |
|
156 if __name__ == '__main__': |
|
157 test_main() |