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  
18  package org.apache.commons.io.filefilter;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.io.File;
25  import java.io.IOException;
26  import java.nio.file.FileVisitResult;
27  import java.nio.file.Files;
28  import java.nio.file.Path;
29  
30  import org.apache.commons.io.file.PathUtils;
31  import org.apache.commons.io.function.IOBiFunction;
32  import org.apache.commons.lang3.SystemUtils;
33  import org.junit.jupiter.api.AfterAll;
34  import org.junit.jupiter.api.BeforeAll;
35  import org.junit.jupiter.api.Test;
36  
37  /**
38   * Tests {@link SymbolicLinkFileFilter}.
39   */
40  public class SymbolicLinkFileFilterTest {
41  
42      public static final String TARGET_SHORT_NAME = "SLFF_Target";
43      public static final String TARGET_EXT = ".txt";
44      public static final String TARGET_NAME = TARGET_SHORT_NAME + TARGET_EXT;
45      public static final String DIRECTORY_NAME = "SLFF_TargetDirectory";
46      public static final String DIRECTORY_LINK_NAME = "SLFF_LinkDirectory";
47      public static final String MISSING = "Missing";
48  
49      private static File testTargetFile; // hard file
50      private static Path testTargetPath; // hard file Path
51      private static File parentDirectoryFile; // System Temp directory
52      private static File testLinkFile; // symbolic link to hard file
53      private static String linkName; // Name of link file
54      private static Path testLinkPath; // symbolic link to hard file Path
55      private static File targetDirFile; //
56      private static Path targetDirPath; // hard directory Path
57      private static Path testLinkDirPath; // symbolic link to hardDirectory
58      private static File testLinkDirFile;
59      private static File missingFileFile; // non-existent file
60      private static Path missingFilePath; // non-existent file
61      private static SymbolicLinkFileFilter filter;
62  
63      // Mock filter for testing on Windows.
64      private static SymbolicLinkFileFilter createMockFilter() {
65          return new SymbolicLinkFileFilter() {
66  
67              private static final long serialVersionUID = 1L;
68  
69              @Override
70              boolean isSymbolicLink(final Path filePath) {
71                  return filePath.toFile().exists() && filePath.toString().contains("Link"); // Mock test
72              }
73          };
74      }
75  
76      private static Path createMockSymbolicLink(final Path link, final Path target) throws IOException {
77          return Files.createFile(link);
78      }
79  
80      private static Path createRealSymbolicLink(final Path link, final Path target) throws IOException {
81          Files.deleteIfExists(link);
82          return Files.createSymbolicLink(link, target);
83      }
84  
85      @AfterAll
86      static void tearDown() {
87          // Fortunately, delete() doesn't throw an exception if the file doesn't exist.
88          testLinkDirFile.delete();
89          targetDirFile.delete();
90          testLinkFile.delete();
91          testTargetFile.delete();
92      }
93  
94      /**
95       * <p>
96       * Unit test setup creates a hard file, a symbolic link to the hard file, a hard directory, and a symbolic link to that directory. All are created in the
97       * temp directory
98       * </p>
99       * <p>
100      * Unit test teardown deletes all four of these files.
101      * </p>
102      *
103      * @throws IOException If it fails to create the temporary files
104      */
105     @BeforeAll
106     static void testSetup() throws IOException {
107         final IOBiFunction<Path, Path, Path> symbolicLinkCreator;
108 
109         // We can't create symbolic links on Windows without admin privileges,
110         // so iff that's our OS, we mock them.
111         if (SystemUtils.IS_OS_WINDOWS) {
112             symbolicLinkCreator = SymbolicLinkFileFilterTest::createMockSymbolicLink;
113             filter = createMockFilter();
114         } else {
115             symbolicLinkCreator = SymbolicLinkFileFilterTest::createRealSymbolicLink;
116             filter = SymbolicLinkFileFilter.INSTANCE;
117         }
118 
119         testTargetFile = File.createTempFile(TARGET_SHORT_NAME, TARGET_EXT);
120         testTargetPath = testTargetFile.toPath();
121         parentDirectoryFile = testTargetFile.getParentFile();
122         // parent directory
123         final Path parentDirectoryPath = parentDirectoryFile.toPath();
124         linkName = "SLFF_LinkTo" + testTargetFile.getName();
125         testLinkPath = symbolicLinkCreator.apply(parentDirectoryPath.resolve(linkName), testTargetPath);
126         testLinkFile = testLinkPath.toFile();
127         targetDirPath = Files.createDirectories(parentDirectoryPath.resolve(DIRECTORY_NAME));
128         targetDirFile = targetDirPath.toFile();
129         testLinkDirPath = symbolicLinkCreator.apply(parentDirectoryPath.resolve(DIRECTORY_LINK_NAME), targetDirPath);
130         testLinkDirFile = testLinkDirPath.toFile();
131         missingFileFile = new File(parentDirectoryPath.toFile(), MISSING);
132         missingFilePath = missingFileFile.toPath();
133     }
134 
135     @Test
136     public void testFileFilter_HardDirectory() {
137         assertFalse(filter.accept(targetDirFile));
138     }
139 
140     @Test
141     public void testFileFilter_HardFile() {
142         assertFalse(filter.accept(testTargetFile));
143     }
144 
145     @Test
146     public void testFileFilter_Link() {
147         assertTrue(filter.accept(testLinkFile));
148     }
149 
150     @Test
151     public void testFileFilter_missingFile() {
152         assertFalse(filter.accept(missingFileFile));
153     }
154 
155     @Test
156     public void testFileFilter_PathLink() {
157         assertTrue(filter.accept(testLinkDirFile));
158     }
159 
160     @Test
161     public void testFileNameFilter_HardDirectory() {
162         assertFalse(filter.accept(parentDirectoryFile, DIRECTORY_NAME));
163     }
164 
165     @Test
166     public void testFileNameFilter_HardFile() {
167         assertFalse(filter.accept(parentDirectoryFile, TARGET_NAME));
168     }
169 
170     @Test
171     public void testFileNameFilter_Link() {
172         assertTrue(filter.accept(parentDirectoryFile, linkName));
173     }
174 
175     @Test
176     public void testFileNameFilter_missingFile() {
177         assertFalse(filter.accept(parentDirectoryFile, MISSING));
178     }
179 
180     @Test
181     public void testFileNameFilter_PathLink() {
182         assertTrue(filter.accept(parentDirectoryFile, DIRECTORY_LINK_NAME));
183     }
184 
185     @Test
186     public void testPathFilter_HardDirectory() {
187         assertEquals(FileVisitResult.TERMINATE, filter.accept(targetDirPath, null));
188         assertFalse(filter.matches(targetDirPath));
189     }
190 
191     @Test
192     public void testPathFilter_HardFile() {
193         assertEquals(FileVisitResult.TERMINATE, filter.accept(testTargetPath, null));
194         assertFalse(filter.matches(testTargetPath));
195     }
196 
197     @Test
198     public void testPathFilter_Link() {
199         assertEquals(FileVisitResult.CONTINUE, filter.accept(testLinkPath, null));
200         assertTrue(filter.matches(testLinkPath));
201 
202     }
203 
204     @Test
205     public void testPathFilter_missingFile() {
206         assertEquals(FileVisitResult.TERMINATE, filter.accept(missingFilePath, null));
207         assertFalse(filter.matches(missingFilePath));
208     }
209 
210     @Test
211     public void testPathFilter_PathLink() {
212         assertEquals(FileVisitResult.CONTINUE, filter.accept(testLinkDirPath, null));
213         assertTrue(filter.matches(testLinkDirPath));
214     }
215 
216     @Test
217     public void testSymbolicLinkFileFilter() {
218         assertEquals(FileVisitResult.TERMINATE, SymbolicLinkFileFilter.INSTANCE.accept(PathUtils.current(), null));
219         assertFalse(filter.matches(PathUtils.current()));
220     }
221 }