• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.assertTrue;
22 
23 import java.io.File;
24 import java.util.ArrayList;
25 import java.util.List;
26 
27 import org.apache.commons.lang3.ArrayUtils;
28 import org.junit.jupiter.api.Test;
29 import org.junit.jupiter.api.io.TempDir;
30 
31 /**
32  * Test cases for FileUtils.cleanDirectory() method that involve symlinks.
33  * & FileUtils.isSymlink(File file)
34  */
35 public class FileUtilsCleanSymlinksTest {
36 
37     @TempDir
38     public File top;
39 
setupSymlink(final File res, final File link)40     private boolean setupSymlink(final File res, final File link) throws Exception {
41         // create symlink
42         final List<String> args = new ArrayList<>();
43         args.add("ln");
44         args.add("-s");
45 
46         args.add(res.getAbsolutePath());
47         args.add(link.getAbsolutePath());
48 
49         final Process proc;
50 
51         proc = Runtime.getRuntime().exec(args.toArray(ArrayUtils.EMPTY_STRING_ARRAY));
52         return proc.waitFor() == 0;
53     }
54 
55 
56     @Test
testCleanDirWithASymlinkDir()57     public void testCleanDirWithASymlinkDir() throws Exception {
58         if (System.getProperty("os.name").startsWith("Win")) {
59             // Can't use "ln" for symlinks on the command line in Windows.
60             return;
61         }
62 
63         final File realOuter = new File(top, "realouter");
64         assertTrue(realOuter.mkdirs());
65 
66         final File realInner = new File(realOuter, "realinner");
67         assertTrue(realInner.mkdirs());
68 
69         FileUtils.touch(new File(realInner, "file1"));
70         assertEquals(1, realInner.list().length);
71 
72         final File randomDirectory = new File(top, "randomDir");
73         assertTrue(randomDirectory.mkdirs());
74 
75         FileUtils.touch(new File(randomDirectory, "randomfile"));
76         assertEquals(1, randomDirectory.list().length);
77 
78         final File symlinkDirectory = new File(realOuter, "fakeinner");
79         assertTrue(setupSymlink(randomDirectory, symlinkDirectory));
80 
81         assertEquals(1, symlinkDirectory.list().length);
82 
83         // assert contents of the real directory were removed including the symlink
84         FileUtils.cleanDirectory(realOuter);
85         assertEquals(0, realOuter.list().length);
86 
87         // ensure that the contents of the symlink were NOT removed.
88         assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed");
89     }
90 
91     @Test
testCleanDirWithParentSymlinks()92     public void testCleanDirWithParentSymlinks() throws Exception {
93         if (System.getProperty("os.name").startsWith("Win")) {
94             // Can't use "ln" for symlinks on the command line in Windows.
95             return;
96         }
97 
98         final File realParent = new File(top, "realparent");
99         assertTrue(realParent.mkdirs());
100 
101         final File realInner = new File(realParent, "realinner");
102         assertTrue(realInner.mkdirs());
103 
104         FileUtils.touch(new File(realInner, "file1"));
105         assertEquals(1, realInner.list().length);
106 
107         final File randomDirectory = new File(top, "randomDir");
108         assertTrue(randomDirectory.mkdirs());
109 
110         FileUtils.touch(new File(randomDirectory, "randomfile"));
111         assertEquals(1, randomDirectory.list().length);
112 
113         final File symlinkDirectory = new File(realParent, "fakeinner");
114         assertTrue(setupSymlink(randomDirectory, symlinkDirectory));
115 
116         assertEquals(1, symlinkDirectory.list().length);
117 
118         final File symlinkParentDirectory = new File(top, "fakeouter");
119         assertTrue(setupSymlink(realParent, symlinkParentDirectory));
120 
121         // assert contents of the real directory were removed including the symlink
122         FileUtils.cleanDirectory(symlinkParentDirectory);// should clean the contents of this but not recurse into other links
123         assertEquals(0, symlinkParentDirectory.list().length);
124         assertEquals(0, realParent.list().length);
125 
126         // ensure that the contents of the symlink were NOT removed.
127         assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed");
128     }
129 
130     @Test
testCleanDirWithSymlinkFile()131     public void testCleanDirWithSymlinkFile() throws Exception {
132         if (System.getProperty("os.name").startsWith("Win")) {
133             // Can't use "ln" for symlinks on the command line in Windows.
134             return;
135         }
136 
137         final File realOuter = new File(top, "realouter");
138         assertTrue(realOuter.mkdirs());
139 
140         final File realInner = new File(realOuter, "realinner");
141         assertTrue(realInner.mkdirs());
142 
143         final File realFile = new File(realInner, "file1");
144         FileUtils.touch(realFile);
145         assertEquals(1, realInner.list().length);
146 
147         final File randomFile = new File(top, "randomfile");
148         FileUtils.touch(randomFile);
149 
150         final File symlinkFile = new File(realInner, "fakeinner");
151         assertTrue(setupSymlink(randomFile, symlinkFile));
152 
153         assertEquals(2, realInner.list().length);
154 
155         // assert contents of the real directory were removed including the symlink
156         FileUtils.cleanDirectory(realOuter);
157         assertEquals(0, realOuter.list().length);
158 
159         // ensure that the contents of the symlink were NOT removed.
160         assertTrue(randomFile.exists());
161         assertFalse(symlinkFile.exists());
162     }
163 
164 
165     @Test
testCorrectlyIdentifySymlinkWithParentSymLink()166     public void testCorrectlyIdentifySymlinkWithParentSymLink() throws Exception {
167         if (System.getProperty("os.name").startsWith("Win")) {
168             // Can't use "ln" for symlinks on the command line in Windows.
169             return;
170         }
171 
172         final File realParent = new File(top, "realparent");
173         assertTrue(realParent.mkdirs());
174 
175         final File symlinkParentDirectory = new File(top, "fakeparent");
176         assertTrue(setupSymlink(realParent, symlinkParentDirectory));
177 
178         final File realChild = new File(symlinkParentDirectory, "realChild");
179         assertTrue(realChild.mkdirs());
180 
181         final File symlinkChild = new File(symlinkParentDirectory, "fakeChild");
182         assertTrue(setupSymlink(realChild, symlinkChild));
183 
184         assertTrue(FileUtils.isSymlink(symlinkChild));
185         assertFalse(FileUtils.isSymlink(realChild));
186     }
187 
188     @Test
testIdentifiesBrokenSymlinkFile()189     public void testIdentifiesBrokenSymlinkFile() throws Exception {
190         if (System.getProperty("os.name").startsWith("Win")) {
191             // Can't use "ln" for symlinks on the command line in Windows.
192             return;
193         }
194 
195         final File nonExistentFile = new File(top, "non-existent");
196         final File symlinkFile = new File(top, "fakeinner");
197         final File badSymlinkInPathFile = new File(symlinkFile, "fakeinner");
198         final File nonExistentParentFile = new File("non-existent", "file");
199 
200         assertTrue(setupSymlink(nonExistentFile, symlinkFile));
201 
202         assertTrue(FileUtils.isSymlink(symlinkFile));
203         assertFalse(FileUtils.isSymlink(nonExistentFile));
204         assertFalse(FileUtils.isSymlink(nonExistentParentFile));
205         assertFalse(FileUtils.isSymlink(badSymlinkInPathFile));
206     }
207 
208     @Test
testIdentifiesSymlinkDir()209     public void testIdentifiesSymlinkDir() throws Exception {
210         if (System.getProperty("os.name").startsWith("Win")) {
211             // Can't use "ln" for symlinks on the command line in Windows.
212             return;
213         }
214 
215         final File randomDirectory = new File(top, "randomDir");
216         assertTrue(randomDirectory.mkdirs());
217 
218         final File symlinkDirectory = new File(top, "fakeDir");
219         assertTrue(setupSymlink(randomDirectory, symlinkDirectory));
220 
221         assertTrue(FileUtils.isSymlink(symlinkDirectory));
222         assertFalse(FileUtils.isSymlink(randomDirectory));
223     }
224 
225     @Test
testIdentifiesSymlinkFile()226     public void testIdentifiesSymlinkFile() throws Exception {
227         if (System.getProperty("os.name").startsWith("Win")) {
228             // Can't use "ln" for symlinks on the command line in Windows.
229             return;
230         }
231 
232         final File randomFile = new File(top, "randomfile");
233         FileUtils.touch(randomFile);
234 
235         final File symlinkFile = new File(top, "fakeinner");
236         assertTrue(setupSymlink(randomFile, symlinkFile));
237 
238         assertTrue(FileUtils.isSymlink(symlinkFile));
239         assertFalse(FileUtils.isSymlink(randomFile));
240     }
241 
242     @Test
testStillClearsIfGivenDirectoryIsASymlink()243     public void testStillClearsIfGivenDirectoryIsASymlink() throws Exception {
244         if (System.getProperty("os.name").startsWith("Win")) {
245             // Can't use "ln" for symlinks on the command line in Windows.
246             return;
247         }
248 
249         final File randomDirectory = new File(top, "randomDir");
250         assertTrue(randomDirectory.mkdirs());
251 
252         FileUtils.touch(new File(randomDirectory, "randomfile"));
253         assertEquals(1, randomDirectory.list().length);
254 
255         final File symlinkDirectory = new File(top, "fakeDir");
256         assertTrue(setupSymlink(randomDirectory, symlinkDirectory));
257 
258         FileUtils.cleanDirectory(symlinkDirectory);
259         assertEquals(0, symlinkDirectory.list().length);
260         assertEquals(0, randomDirectory.list().length);
261     }
262 
263 }
264