View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   */
19  package org.apache.rat.document;
20  
21  import java.io.File;
22  import java.io.FileFilter;
23  import java.io.FilenameFilter;
24  import java.io.IOException;
25  import java.nio.file.FileSystems;
26  import java.nio.file.Path;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.HashSet;
30  import java.util.List;
31  import java.util.Set;
32  import java.util.stream.Stream;
33  
34  import org.apache.commons.io.FileUtils;
35  import org.apache.commons.lang3.tuple.Pair;
36  import org.apache.rat.config.exclusion.ExclusionUtils;
37  import org.apache.rat.document.DocumentName.FSInfo;
38  
39  import org.assertj.core.util.Files;
40  import org.junit.jupiter.api.Test;
41  import org.junit.jupiter.params.ParameterizedTest;
42  import org.junit.jupiter.params.provider.Arguments;
43  import org.junit.jupiter.params.provider.MethodSource;
44  import org.mockito.Mockito;
45  
46  import static org.assertj.core.api.Assertions.assertThat;
47  import static org.apache.rat.document.FSInfoTest.OSX;
48  import static org.apache.rat.document.FSInfoTest.UNIX;
49  import static org.apache.rat.document.FSInfoTest.WINDOWS;
50  import static org.mockito.Mockito.mock;
51  import static org.mockito.Mockito.when;
52  import static org.mockito.ArgumentMatchers.any;
53  
54  public class DocumentNameTest {
55  
56      public static DocumentName mkName(Path tempDir, FSInfo fsInfo) {
57          File docFile = mkFile(tempDir.toFile(), fsInfo);
58          DocumentName result = DocumentName.builder(fsInfo).setName(docFile).build();
59          DocumentName mocked = Mockito.spy(result);
60  
61          String fn = result.localized(FileSystems.getDefault().getSeparator());
62          File file = tempDir.resolve(fn.substring(1)).toFile();
63          File mockedFile = mkFile(file, fsInfo);
64          when(mocked.asFile()).thenReturn(mockedFile);
65  
66          assertThat(mocked.asFile()).isEqualTo(mockedFile);
67          return mocked;
68      }
69  
70      private static File[] listFiles(File file, FSInfo fsInfo) {
71          File[] fileList = file.listFiles();
72          if (fileList == null) {
73              return fileList;
74          }
75          return Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).toArray(File[]::new);
76      }
77  
78      private static File[] listFiles(File file, FSInfo fsInfo, FileFilter filter) {
79          File[] fileList = file.listFiles();
80          if (fileList == null) {
81              return fileList;
82          }
83          return Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(filter::accept).toArray(File[]::new);
84      }
85  
86      private static File[] listFiles(File file, FSInfo fsInfo, FilenameFilter filter) {
87          File[] fileList = file.listFiles();
88          if (fileList == null) {
89              return fileList;
90          }
91          return Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(x -> filter.accept(x, x.getName())).toArray(File[]::new);
92      }
93  
94      public static File mkFile(final File file, final FSInfo fsInfo) {
95          File mockedFile = mock(File.class);
96          when(mockedFile.listFiles()).thenAnswer( env -> listFiles(file, fsInfo));
97          when(mockedFile.listFiles(any(FilenameFilter.class))).thenAnswer( env -> listFiles(file, fsInfo, env.getArgument(0, FilenameFilter.class)));
98          when(mockedFile.listFiles(any(FileFilter.class))).thenAnswer(env -> listFiles(file, fsInfo, env.getArgument(0, FileFilter.class)));
99          when(mockedFile.getName()).thenReturn(ExclusionUtils.convertSeparator(file.getName(), FSInfoTest.DEFAULT.dirSeparator(), fsInfo.dirSeparator()));
100         when(mockedFile.getAbsolutePath()).thenReturn(ExclusionUtils.convertSeparator(file.getAbsolutePath(), FSInfoTest.DEFAULT.dirSeparator(), fsInfo.dirSeparator()));
101         when(mockedFile.isFile()).thenAnswer(env -> file.isFile());
102         when(mockedFile.exists()).thenAnswer(emv -> file.exists());
103         when(mockedFile.isDirectory()).thenAnswer(env -> file.isDirectory());
104 
105         return mockedFile;
106     }
107 
108     public static DocumentName mkName(Path tempDir, DocumentName baseDir, String pth) throws IOException {
109         DocumentName result = baseDir.resolve(ExclusionUtils.convertSeparator(pth, "/", baseDir.getDirectorySeparator()));
110         DocumentName mocked = Mockito.spy(result);
111 
112         String fn = result.localized(FileSystems.getDefault().getSeparator());
113         File file = tempDir.resolve(fn.substring(1)).toFile();
114         File parent = file.getParentFile();
115         if (parent.exists() && !parent.isDirectory()) {
116             parent.delete();
117         }
118         parent.mkdirs();
119         if (file.exists()) {
120             if (file.isDirectory()) {
121                 FileUtils.deleteDirectory(file);
122             } else {
123                 FileUtils.delete(file);
124             }
125         }
126         file.createNewFile();
127         when(mocked.asFile()).thenReturn(file);
128         return mocked;
129     }
130 
131     @ParameterizedTest(name = "{index} {0} {2}")
132     @MethodSource("resolveTestData")
133     void resolveTest(String testName, DocumentName base, String toResolve, DocumentName expected) {
134        DocumentName actual = base.resolve(toResolve);
135        assertThat(actual).isEqualTo(expected);
136     }
137 
138     private static Stream<Arguments> resolveTestData() {
139         List<Arguments> lst = new ArrayList<>();
140 
141         DocumentName base = DocumentName.builder(UNIX).setName("/dir/unix").setBaseName("/").build();
142 
143         DocumentName expected = DocumentName.builder(UNIX).setName("/dir/unix/relative").setBaseName("/").build();
144         lst.add(Arguments.of("unix", base, "relative", expected));
145 
146         expected = DocumentName.builder(UNIX).setName("/from/root").setBaseName("/").build();
147         lst.add(Arguments.of("unix", base, "/from/root", expected));
148 
149         expected = DocumentName.builder(UNIX).setName("dir/up/and/down").setBaseName("/").build();
150         lst.add(Arguments.of("unix", base, "../up/and/down", expected));
151 
152         expected = DocumentName.builder(UNIX).setName("/from/root").setBaseName("/").build();
153         lst.add(Arguments.of("unix", base, "\\from\\root", expected));
154 
155         expected = DocumentName.builder(UNIX).setName("dir/up/and/down").setBaseName("/").build();
156         lst.add(Arguments.of("unix", base, "..\\up\\and\\down", expected));
157 
158         // WINDOWS
159         base = DocumentName.builder(WINDOWS).setName("\\dir\\windows").setBaseName("C:\\").build();
160 
161         expected = DocumentName.builder(WINDOWS).setName("\\dir\\windows\\relative").setBaseName("C:\\").build();
162         lst.add(Arguments.of("windows", base, "relative", expected));
163 
164         expected = DocumentName.builder(WINDOWS).setName("\\from\\root").setBaseName("C:\\").build();
165         lst.add(Arguments.of("windows", base, "/from/root", expected));
166 
167         expected = DocumentName.builder(WINDOWS).setName("dir\\up\\and\\down").setBaseName("C:\\").build();
168         lst.add(Arguments.of("windows", base, "../up/and/down", expected));
169 
170         expected = DocumentName.builder(WINDOWS).setName("\\from\\root").setBaseName("C:\\").build();
171         lst.add(Arguments.of("windows", base, "\\from\\root", expected));
172 
173         expected = DocumentName.builder(WINDOWS).setName("dir\\up\\and\\down").setBaseName("C:\\").build();
174         lst.add(Arguments.of("windows", base, "..\\up\\and\\down", expected));
175 
176         // OSX
177         base = DocumentName.builder(OSX).setName("/dir/osx").setBaseName("/").build();
178 
179         expected = DocumentName.builder(OSX).setName("/dir/osx/relative").setBaseName("/").build();
180         lst.add(Arguments.of("osx", base, "relative", expected));
181 
182         expected = DocumentName.builder(OSX).setName("/from/root").setBaseName("/").build();
183         lst.add(Arguments.of("osx", base, "/from/root", expected));
184 
185         expected = DocumentName.builder(OSX).setName("dir/up/and/down").setBaseName("/").build();
186         lst.add(Arguments.of("osx", base, "../up/and/down", expected));
187 
188         expected = DocumentName.builder(OSX).setName("/from/root").setBaseName("/").build();
189         lst.add(Arguments.of("osx", base, "\\from\\root", expected));
190 
191         expected = DocumentName.builder(OSX).setName("dir/up/and/down").setBaseName("/").build();
192         lst.add(Arguments.of("osx", base, "..\\up\\and\\down", expected));
193 
194         return lst.stream();
195     }
196 
197     @Test
198     void localizeTest() {
199         DocumentName documentName = DocumentName.builder(UNIX).setName("/a/b/c")
200                 .setBaseName("/a").build();
201         assertThat(documentName.localized()).isEqualTo("/b/c");
202         assertThat(documentName.localized("-")).isEqualTo("-b-c");
203 
204         documentName = DocumentName.builder(WINDOWS).setName("\\a\\b\\c")
205                 .setBaseName("\\a").build();
206         assertThat(documentName.localized()).isEqualTo("\\b\\c");
207         assertThat(documentName.localized("-")).isEqualTo("-b-c");
208 
209         documentName = DocumentName.builder(OSX).setName("/a/b/c")
210                 .setBaseName("/a").build();
211         assertThat(documentName.localized()).isEqualTo("/b/c");
212         assertThat(documentName.localized("-")).isEqualTo("-b-c");
213     }
214 
215     @ParameterizedTest(name = "{index} {0}")
216     @MethodSource("validBuilderData")
217     void validBuilderTest(String testName, DocumentName.Builder builder, String root, String name, String baseName, String dirSeparator) {
218         DocumentName underTest = builder.build();
219         assertThat(underTest.getRoot()).as(testName).isEqualTo(root);
220         assertThat(underTest.getDirectorySeparator()).as(testName).isEqualTo(dirSeparator);
221         assertThat(underTest.getName()).as(testName).isEqualTo(root + dirSeparator + name);
222         assertThat(underTest.getBaseName()).as(testName).isEqualTo(root + dirSeparator + baseName);
223     }
224 
225     private static Stream<Arguments> validBuilderData() {
226         List<Arguments> lst = new ArrayList<>();
227         File f = Files.newTemporaryFile();
228 
229         Set<String> roots = new HashSet<>();
230         File[] rootary = File.listRoots();
231         if (rootary != null) {
232             for (File root : rootary) {
233                 String name = root.getPath();
234                 roots.add(name);
235             }
236         }
237 
238         String name = f.getAbsolutePath();
239         String root = "";
240         for (String sysRoot : roots) {
241             if (name.startsWith(sysRoot)) {
242                 name = name.substring(sysRoot.length());
243                 if (sysRoot.endsWith(File.separator)) {
244                     root = sysRoot.substring(0, sysRoot.length() - File.separator.length());
245                 }
246                 break;
247             }
248         }
249 
250         File p = f.getParentFile();
251         String baseName = p.getAbsolutePath().substring(root.length());
252         if (baseName.startsWith(File.separator)) {
253             baseName = baseName.substring(File.separator.length());
254         }
255         lst.add(Arguments.of("setName(file)", DocumentName.builder().setName(f), root, name, baseName, File.separator));
256         lst.add(Arguments.of("Builder(file)", DocumentName.builder(f), root, name, baseName, File.separator));
257 
258         lst.add(Arguments.of("setName(dir)", DocumentName.builder().setName(p), root, baseName, baseName, File.separator));
259         lst.add(Arguments.of("Builder(dir)", DocumentName.builder(p), root, baseName, baseName, File.separator));
260 
261         File r = new File(root.isEmpty() ? File.separator : root);
262         lst.add(Arguments.of("setName(root)", DocumentName.builder().setName(r), root, "", "", File.separator));
263         lst.add(Arguments.of("Builder(root)", DocumentName.builder(r), root, "", "", File.separator));
264 
265 
266         lst.add(Arguments.of("foo/bar foo", DocumentName.builder(UNIX)
267                 .setName("/foo/bar").setBaseName("foo"), "", "foo/bar", "foo", "/"));
268 
269         DocumentName.Builder builder = DocumentName.builder(WINDOWS).setName("\\foo\\bar").setBaseName("C:\\foo")
270                 .setRoot("C:");
271         lst.add(Arguments.of("\\foo\\bar foo", builder, "C:", "foo\\bar", "foo", "\\"));
272 
273         lst.add(Arguments.of("foo/bar foo", DocumentName.builder(OSX)
274                 .setName("/foo/bar").setBaseName("foo"), "", "foo/bar", "foo", "/"));
275 
276         return lst.stream();
277     }
278 
279     @Test
280     void splitRootsTest() {
281         Pair<String, String> result = DocumentName.builder(WINDOWS).splitRoot("C:\\My\\path\\to\\a\\file.txt");
282         assertThat(result.getLeft()).isEqualTo("C:");
283         assertThat(result.getRight()).isEqualTo("My\\path\\to\\a\\file.txt");
284 
285         result = DocumentName.builder(UNIX).splitRoot("/My/path/to/a/file.txt");
286         assertThat(result.getLeft()).isEqualTo("");
287         assertThat(result.getRight()).isEqualTo("My/path/to/a/file.txt");
288 
289         result = DocumentName.builder(OSX).splitRoot("/My/path/to/a/file.txt");
290         assertThat(result.getLeft()).isEqualTo("");
291         assertThat(result.getRight()).isEqualTo("My/path/to/a/file.txt");
292     }
293 
294     @Test
295     void archiveEntryNameTest() {
296         String entryName = "./anArchiveEntry.txt";
297         DocumentName archiveName = DocumentName.builder(WINDOWS)
298                 .setName("C:\\archives\\anArchive.zip").setBaseName("C:\\archives").build();
299 
300         assertThat(archiveName.getRoot()).isEqualTo("C:");
301         assertThat(archiveName.getDirectorySeparator()).isEqualTo("\\");
302         assertThat(archiveName.getBaseName()).isEqualTo("C:\\archives");
303         assertThat(archiveName.getName()).isEqualTo("C:\\archives\\anArchive.zip");
304         assertThat(archiveName.localized()).isEqualTo("\\anArchive.zip");
305 
306         ArchiveEntryName archiveEntryName = new ArchiveEntryName(archiveName, entryName);
307 
308         assertThat(archiveEntryName.getRoot()).isEqualTo(archiveName.getName()+"#");
309         assertThat(archiveEntryName.getDirectorySeparator()).isEqualTo("/");
310         assertThat(archiveEntryName.getBaseName()).isEqualTo("C:\\archives\\anArchive.zip#");
311         assertThat(archiveEntryName.getName()).isEqualTo("C:\\archives\\anArchive.zip#/anArchiveEntry.txt");
312         assertThat(archiveEntryName.localized()).isEqualTo("/anArchiveEntry.txt");
313         assertThat(archiveEntryName.localized("/")).isEqualTo("/anArchive.zip#/anArchiveEntry.txt");
314 
315         // test with directory
316         entryName = "./someDir/anArchiveEntry.txt";
317         archiveEntryName = new ArchiveEntryName(archiveName, entryName);
318 
319         assertThat(archiveEntryName.getRoot()).isEqualTo(archiveName.getName()+"#");
320         assertThat(archiveEntryName.getDirectorySeparator()).isEqualTo("/");
321         assertThat(archiveEntryName.getBaseName()).isEqualTo("C:\\archives\\anArchive.zip#");
322         assertThat(archiveEntryName.getName()).isEqualTo("C:\\archives\\anArchive.zip#/someDir/anArchiveEntry.txt");
323         assertThat(archiveEntryName.localized()).isEqualTo("/someDir/anArchiveEntry.txt");
324         assertThat(archiveEntryName.localized("/")).isEqualTo("/anArchive.zip#/someDir/anArchiveEntry.txt");
325     }
326 }