View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.io;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.io.File;
25  import java.nio.file.Files;
26  
27  import org.junit.jupiter.api.Test;
28  import org.junit.jupiter.api.io.TempDir;
29  
30  /**
31   * Test cases for FileUtils.deleteDirectory() method.
32   */
33  public abstract class AbstractFileUtilsDeleteDirectoryTest {
34      @TempDir
35      public File top;
36  
37      protected abstract boolean setupSymlink(final File res, final File link) throws Exception;
38  
39      @Test
40      public void testDeleteDirectoryNullArgument() {
41          assertThrows(NullPointerException.class, () -> FileUtils.deleteDirectory(null));
42      }
43  
44      @Test
45      public void testDeleteDirWithASymlinkDir() throws Exception {
46  
47          final File realOuter = new File(top, "realouter");
48          assertTrue(realOuter.mkdirs());
49  
50          final File realInner = new File(realOuter, "realinner");
51          assertTrue(realInner.mkdirs());
52  
53          FileUtils.touch(new File(realInner, "file1"));
54          assertEquals(1, realInner.list().length);
55  
56          final File randomDirectory = new File(top, "randomDir");
57          assertTrue(randomDirectory.mkdirs());
58  
59          FileUtils.touch(new File(randomDirectory, "randomfile"));
60          assertEquals(1, randomDirectory.list().length);
61  
62          final File symlinkDirectory = new File(realOuter, "fakeinner");
63          assertTrue(setupSymlink(randomDirectory, symlinkDirectory));
64  
65          assertEquals(1, symlinkDirectory.list().length);
66  
67          // assert contents of the real directory were removed including the symlink
68          FileUtils.deleteDirectory(realOuter);
69          assertEquals(1, top.list().length);
70  
71          // ensure that the contents of the symlink were NOT removed.
72          assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed");
73      }
74  
75      @Test
76      public void testDeleteDirWithASymlinkDir2() throws Exception {
77  
78          final File realOuter = new File(top, "realouter");
79          assertTrue(realOuter.mkdirs());
80  
81          final File realInner = new File(realOuter, "realinner");
82          assertTrue(realInner.mkdirs());
83  
84          FileUtils.touch(new File(realInner, "file1"));
85          assertEquals(1, realInner.list().length);
86  
87          final File randomDirectory = new File(top, "randomDir");
88          assertTrue(randomDirectory.mkdirs());
89  
90          FileUtils.touch(new File(randomDirectory, "randomfile"));
91          assertEquals(1, randomDirectory.list().length);
92  
93          final File symlinkDirectory = new File(realOuter, "fakeinner");
94          Files.createSymbolicLink(symlinkDirectory.toPath(), randomDirectory.toPath());
95  
96          assertEquals(1, symlinkDirectory.list().length);
97  
98          // assert contents of the real directory were removed including the symlink
99          FileUtils.deleteDirectory(realOuter);
100         assertEquals(1, top.list().length);
101 
102         // ensure that the contents of the symlink were NOT removed.
103         assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed");
104     }
105 
106     @Test
107     public void testDeleteDirWithSymlinkFile() throws Exception {
108         final File realOuter = new File(top, "realouter");
109         assertTrue(realOuter.mkdirs());
110 
111         final File realInner = new File(realOuter, "realinner");
112         assertTrue(realInner.mkdirs());
113 
114         final File realFile = new File(realInner, "file1");
115         FileUtils.touch(realFile);
116 
117         assertEquals(1, realInner.list().length);
118 
119         final File randomFile = new File(top, "randomfile");
120         FileUtils.touch(randomFile);
121 
122         final File symlinkFile = new File(realInner, "fakeinner");
123         assertTrue(setupSymlink(randomFile, symlinkFile));
124 
125         assertEquals(2, realInner.list().length);
126         assertEquals(2, top.list().length);
127 
128         // assert the real directory were removed including the symlink
129         FileUtils.deleteDirectory(realOuter);
130         assertEquals(1, top.list().length);
131 
132         // ensure that the contents of the symlink were NOT removed.
133         assertTrue(randomFile.exists());
134         assertFalse(symlinkFile.exists());
135     }
136 
137     @Test
138     public void testDeleteInvalidLinks() throws Exception {
139         final File aFile = new File(top, "realParentDirA");
140         assertTrue(aFile.mkdir());
141         final File bFile = new File(aFile, "realChildDirB");
142         assertTrue(bFile.mkdir());
143 
144         final File cFile = new File(top, "realParentDirC");
145         assertTrue(cFile.mkdir());
146         final File dFile = new File(cFile, "realChildDirD");
147         assertTrue(dFile.mkdir());
148 
149         final File linkToC = new File(bFile, "linkToC");
150         Files.createSymbolicLink(linkToC.toPath(), cFile.toPath());
151 
152         final File linkToB = new File(dFile, "linkToB");
153         Files.createSymbolicLink(linkToB.toPath(), bFile.toPath());
154 
155         FileUtils.deleteDirectory(aFile);
156         FileUtils.deleteDirectory(cFile);
157         assertEquals(0, top.list().length);
158     }
159 
160     @Test
161     public void testDeleteParentSymlink() throws Exception {
162         final File realParent = new File(top, "realparent");
163         assertTrue(realParent.mkdirs());
164 
165         final File realInner = new File(realParent, "realinner");
166         assertTrue(realInner.mkdirs());
167 
168         FileUtils.touch(new File(realInner, "file1"));
169         assertEquals(1, realInner.list().length);
170 
171         final File randomDirectory = new File(top, "randomDir");
172         assertTrue(randomDirectory.mkdirs());
173 
174         FileUtils.touch(new File(randomDirectory, "randomfile"));
175         assertEquals(1, randomDirectory.list().length);
176 
177         final File symlinkDirectory = new File(realParent, "fakeinner");
178         assertTrue(setupSymlink(randomDirectory, symlinkDirectory));
179 
180         assertEquals(1, symlinkDirectory.list().length);
181 
182         final File symlinkParentDirectory = new File(top, "fakeouter");
183         assertTrue(setupSymlink(realParent, symlinkParentDirectory));
184 
185         // assert only the symlink is deleted, but not followed
186         FileUtils.deleteDirectory(symlinkParentDirectory);
187         assertEquals(2, top.list().length);
188 
189         // ensure that the contents of the symlink were NOT removed.
190         assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed");
191     }
192 
193     @Test
194     public void testDeleteParentSymlink2() throws Exception {
195         final File realParent = new File(top, "realparent");
196         assertTrue(realParent.mkdirs());
197 
198         final File realInner = new File(realParent, "realinner");
199         assertTrue(realInner.mkdirs());
200 
201         FileUtils.touch(new File(realInner, "file1"));
202         assertEquals(1, realInner.list().length);
203 
204         final File randomDirectory = new File(top, "randomDir");
205         assertTrue(randomDirectory.mkdirs());
206 
207         FileUtils.touch(new File(randomDirectory, "randomfile"));
208         assertEquals(1, randomDirectory.list().length);
209 
210         final File symlinkDirectory = new File(realParent, "fakeinner");
211         Files.createSymbolicLink(symlinkDirectory.toPath(), randomDirectory.toPath());
212 
213         assertEquals(1, symlinkDirectory.list().length);
214 
215         final File symlinkParentDirectory = new File(top, "fakeouter");
216         Files.createSymbolicLink(symlinkParentDirectory.toPath(), realParent.toPath());
217 
218         // assert only the symlink is deleted, but not followed
219         FileUtils.deleteDirectory(symlinkParentDirectory);
220         assertEquals(2, top.list().length);
221 
222         // ensure that the contents of the symlink were NOT removed.
223         assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed");
224     }
225 
226     @Test
227     public void testDeletesNested() throws Exception {
228         final File nested = new File(top, "nested");
229         assertTrue(nested.mkdirs());
230 
231         assertEquals(1, top.list().length);
232 
233         FileUtils.touch(new File(nested, "regular"));
234         FileUtils.touch(new File(nested, ".hidden"));
235 
236         assertEquals(2, nested.list().length);
237 
238         FileUtils.deleteDirectory(nested);
239 
240         assertEquals(0, top.list().length);
241     }
242 
243     @Test
244     public void testDeletesRegular() throws Exception {
245         final File nested = new File(top, "nested");
246         assertTrue(nested.mkdirs());
247 
248         assertEquals(1, top.list().length);
249 
250         assertEquals(0, nested.list().length);
251 
252         FileUtils.deleteDirectory(nested);
253 
254         assertEquals(0, top.list().length);
255     }
256 
257 }