@@ -117,6 +117,38 @@ def test_rmtree_works_on_bytes(self):
117117 self .assertIsInstance (victim , bytes )
118118 shutil .rmtree (victim )
119119
120+ @support .skip_unless_symlink
121+ def test_rmtree_fails_on_symlink (self ):
122+ tmp = self .mkdtemp ()
123+ dir_ = os .path .join (tmp , 'dir' )
124+ os .mkdir (dir_ )
125+ link = os .path .join (tmp , 'link' )
126+ os .symlink (dir_ , link )
127+ self .assertRaises (OSError , shutil .rmtree , link )
128+ self .assertTrue (os .path .exists (dir_ ))
129+
130+ @support .skip_unless_symlink
131+ def test_rmtree_works_on_symlinks (self ):
132+ tmp = self .mkdtemp ()
133+ dir1 = os .path .join (tmp , 'dir1' )
134+ dir2 = os .path .join (dir1 , 'dir2' )
135+ dir3 = os .path .join (tmp , 'dir3' )
136+ for d in dir1 , dir2 , dir3 :
137+ os .mkdir (d )
138+ file1 = os .path .join (tmp , 'file1' )
139+ write_file (file1 , 'foo' )
140+ link1 = os .path .join (dir1 , 'link1' )
141+ os .symlink (dir2 , link1 )
142+ link2 = os .path .join (dir1 , 'link2' )
143+ os .symlink (dir3 , link2 )
144+ link3 = os .path .join (dir1 , 'link3' )
145+ os .symlink (file1 , link3 )
146+ # make sure symlinks are removed but not followed
147+ shutil .rmtree (dir1 )
148+ self .assertFalse (os .path .exists (dir1 ))
149+ self .assertTrue (os .path .exists (dir3 ))
150+ self .assertTrue (os .path .exists (file1 ))
151+
120152 def test_rmtree_errors (self ):
121153 # filename is guaranteed not to exist
122154 filename = tempfile .mktemp ()
@@ -184,7 +216,7 @@ def check_args_to_onerror(self, func, arg, exc):
184216 def test_rmtree_does_not_choke_on_failing_lstat (self ):
185217 try :
186218 orig_lstat = os .lstat
187- def raiser (fn ):
219+ def raiser (fn , * args , ** kwargs ):
188220 if fn != TESTFN :
189221 raise OSError ()
190222 else :
0 commit comments