1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.document;
20
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.FileFilter;
24 import java.io.FileReader;
25 import java.io.FileWriter;
26 import java.io.FilenameFilter;
27 import java.io.IOException;
28 import java.nio.charset.StandardCharsets;
29 import java.nio.file.Path;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.List;
33 import java.util.stream.Stream;
34
35 import org.apache.rat.config.exclusion.ExclusionUtils;
36 import org.apache.rat.document.DocumentName.FSInfo;
37
38 import org.junit.jupiter.api.Test;
39 import org.junit.jupiter.params.ParameterizedTest;
40 import org.junit.jupiter.params.provider.Arguments;
41 import org.junit.jupiter.params.provider.FieldSource;
42 import org.junit.jupiter.params.provider.MethodSource;
43 import org.junit.jupiter.params.provider.ValueSource;
44
45 import static org.assertj.core.api.Assertions.assertThat;
46 import static org.assertj.core.api.Assertions.assertThatThrownBy;
47 import static org.mockito.Mockito.mock;
48 import static org.mockito.Mockito.when;
49 import static org.mockito.ArgumentMatchers.any;
50
51 public class DocumentNameTest {
52 private static final FSInfo[] TEST_SUITE = FSInfoTest.TEST_SUITE;
53
54 @ParameterizedTest
55 @ValueSource(booleans = {true, false})
56 void splitRootRespectsCaseSensitivity(boolean caseSensitive) {
57 FSInfo info = new FSInfo("test", "\\", caseSensitive, List.of("F:\\"));
58 String path = "f:\\workspace\\target\\rat.txt";
59 var result = DocumentName.builder(info).splitRoot(path);
60
61 assertThat(result.getLeft()).isEqualTo(caseSensitive ? "" : "F:\\");
62 assertThat(result.getRight()).isEqualTo(caseSensitive ? path : "workspace\\target\\rat.txt");
63 }
64
65
66
67
68
69
70
71 private static File[] listFiles(File directory, FSInfo fsInfo) {
72 File[] fileList = directory.listFiles();
73 return fileList == null ? null : Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).toArray(File[]::new);
74 }
75
76
77
78
79
80
81
82
83 private static File[] listFiles(File directory, FSInfo fsInfo, FileFilter filter) {
84 File[] fileList = directory.listFiles();
85 return fileList == null ? null : Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(filter::accept).toArray(File[]::new);
86 }
87
88
89
90
91
92
93
94
95 private static File[] listFiles(File directory, FSInfo fsInfo, FilenameFilter filter) {
96 File[] fileList = directory.listFiles();
97 return fileList == null ? null : Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(x -> filter.accept(x, x.getName())).toArray(File[]::new);
98 }
99
100
101
102
103
104
105
106 public static File mkFile(final File file, final FSInfo fsInfo) {
107 File mockedFile = mock(File.class);
108 when(mockedFile.listFiles()).thenAnswer( env -> listFiles(file, fsInfo));
109 when(mockedFile.listFiles(any(FilenameFilter.class))).thenAnswer( env -> listFiles(file, fsInfo, env.getArgument(0, FilenameFilter.class)));
110 when(mockedFile.listFiles(any(FileFilter.class))).thenAnswer(env -> listFiles(file, fsInfo, env.getArgument(0, FileFilter.class)));
111 when(mockedFile.getName()).thenReturn(ExclusionUtils.convertSeparator(file.getName(), FSInfoTest.DEFAULT.dirSeparator(), fsInfo.dirSeparator()));
112 when(mockedFile.getAbsolutePath()).thenReturn(ExclusionUtils.convertSeparator(file.getAbsolutePath(), FSInfoTest.DEFAULT.dirSeparator(), fsInfo.dirSeparator()));
113 when(mockedFile.isFile()).thenAnswer(env -> file.isFile());
114 when(mockedFile.exists()).thenAnswer(emv -> file.exists());
115 when(mockedFile.isDirectory()).thenAnswer(env -> file.isDirectory());
116
117 return mockedFile;
118 }
119
120
121
122
123
124
125
126
127 @ParameterizedTest(name = "{index} {0} {1} {3}")
128 @MethodSource("resolveTestData")
129 void resolveTest(DocumentName.FSInfo fsInfo, String root, DocumentName base, String toResolve, DocumentName expected) {
130 DocumentName actual = base.resolve(toResolve);
131 assertThat(actual.getName()).isEqualTo(expected.getName());
132 }
133
134 private static Stream<Arguments> resolveTestData() {
135 List<Arguments> lst = new ArrayList<>();
136 DocumentName base;
137 DocumentName expected;
138 for (DocumentName.FSInfo fsInfo : TEST_SUITE) {
139 String root = fsInfo.roots()[0];
140 for (String baseName : List.of(root, root + fsInfo.mkPath("from", "base"))) {
141 for (String testRoot : fsInfo.roots()) {
142 String name = testRoot + fsInfo.mkPath("", "dir", fsInfo.toString());
143 base = DocumentName.builder(fsInfo).setName(name).setBaseName(baseName).build();
144 lst.add(Arguments.of(fsInfo, base.getName(), base, null, base));
145
146 lst.add(Arguments.of(fsInfo, base.getName(), base, "", base));
147
148 lst.add(Arguments.of(fsInfo, base.getName(), base, " ", base));
149
150 expected = DocumentName.builder(fsInfo).setName(fsInfo.mkPath(name, "relative")).setBaseName(baseName).build();
151 lst.add(Arguments.of(fsInfo, base.getName(), base, "relative", expected));
152
153 expected = DocumentName.builder(fsInfo).setRoot(testRoot).setName(fsInfo.mkPath("", "from", "root")).setBaseName(baseName).build();
154 lst.add(Arguments.of(fsInfo, base.getName(), base, fsInfo.mkPath("", "from", "root"), expected));
155
156 expected = DocumentName.builder(fsInfo).setRoot(testRoot).setName(fsInfo.mkPath("dir", "up", "and", "down")).setBaseName(baseName).build();
157 lst.add(Arguments.of(fsInfo, base.getName(), base, fsInfo.mkPath("..", "up", "and", "down"), expected));
158
159 expected = DocumentName.builder(fsInfo).setRoot(testRoot).setName(fsInfo.mkPath("", "from", "root")).setBaseName(baseName).build();
160 String wrongSeparator = fsInfo.dirSeparator().equals("/") ? "\\" : "/";
161 lst.add(Arguments.of(fsInfo, base.getName(), base, String.join(wrongSeparator, "", "from", "root"), expected));
162
163 expected = DocumentName.builder(fsInfo).setRoot(testRoot).setName(fsInfo.mkPath("dir", "up", "and", "down")).setBaseName(baseName).build();
164 lst.add(Arguments.of(fsInfo, base.getName(), base, String.join(wrongSeparator, "..", "up", "and", "down"), expected));
165 }
166 }
167 }
168 return lst.stream();
169 }
170
171 @Test
172 void resolveWithMultipleRootsTest() {
173
174 DocumentName.FSInfo fsInfo = FSInfoTest.WINDOWS;
175 DocumentName base = DocumentName.builder(fsInfo).setName(fsInfo.mkPath("", "dir", fsInfo.toString()))
176 .setBaseName("").build();
177
178 String resolveName = fsInfo.roots()[1] + fsInfo.mkPath("dir", fsInfo.toString());
179 assertThatThrownBy(() -> base.resolve(resolveName))
180 .as(resolveName)
181 .hasMessageContaining(String.format("%s does not start with %s", resolveName, base.getName()))
182 .isInstanceOf(IllegalArgumentException.class);
183
184 String resolveName2 = fsInfo.roots()[0] + fsInfo.mkPath("dir", fsInfo.toString(), "thing");
185 assertThat(base.resolve(resolveName2).getName())
186 .isEqualTo(resolveName2);
187 }
188
189 void testNoRootSpecified() {
190
191 assertThat(DocumentName.startsWithRootOrSeparator("X:/candidate", null, "/")).isFalse();
192 assertThat(DocumentName.startsWithRootOrSeparator("X:/candidate", "", "/")).isFalse();
193 assertThat(DocumentName.startsWithRootOrSeparator("X;/candidate", " ", "/")).isFalse();
194 assertThat(DocumentName.startsWithRootOrSeparator("/candidate", null, "/")).isTrue();
195 assertThat(DocumentName.startsWithRootOrSeparator("/candidate", "", "/")).isTrue();
196 assertThat(DocumentName.startsWithRootOrSeparator("/candidate", " ", "/")).isTrue();
197 assertThat(DocumentName.startsWithRootOrSeparator("candidate", null, "/")).isFalse();
198 assertThat(DocumentName.startsWithRootOrSeparator("candidate", "", "/")).isFalse();
199 assertThat(DocumentName.startsWithRootOrSeparator("candidate", " ", "/")).isFalse();
200 }
201
202 @Test
203 void startsWithRootOrSeparatorTest() {
204 assertThat(DocumentName.startsWithRootOrSeparator("X:/candidate", "X:/", "/")).isTrue();
205 assertThat(DocumentName.startsWithRootOrSeparator("X:/candidate", "Y:/", "/")).isFalse();
206 assertThat(DocumentName.startsWithRootOrSeparator("/candidate", "X:/", "/")).isTrue();
207 assertThat(DocumentName.startsWithRootOrSeparator("\\candidate", "Y:/", "/")).isFalse();
208 assertThat(DocumentName.startsWithRootOrSeparator("candidate", "Y:/", "/")).isFalse();
209 assertThat(DocumentName.startsWithRootOrSeparator("Y:candidate", "Y:/", "/")).isFalse();
210 assertThat(DocumentName.startsWithRootOrSeparator(null, "Y:/", "/")).isFalse();
211 assertThat(DocumentName.startsWithRootOrSeparator("", "Y:/", "/")).isFalse();
212 assertThat(DocumentName.startsWithRootOrSeparator(" ", "Y:/", "/")).isFalse();
213
214 testNoRootSpecified();
215 }
216
217 @ParameterizedTest
218 @FieldSource("TEST_SUITE")
219 void localizeTest(FSInfo fsInfo) {
220 DocumentName documentName = DocumentName.builder(fsInfo).setName(
221 fsInfo.mkPath("", "a", "b", "c"))
222 .setBaseName(fsInfo.mkPath("", "a")).build();
223
224 assertThat(documentName.localized()).isEqualTo(fsInfo.mkPath("", "b", "c"));
225 assertThat(documentName.localized("-")).isEqualTo("-b-c");
226
227 documentName = DocumentName.builder(fsInfo).setName(
228 fsInfo.mkPath("", "a", "b", "c"))
229 .setBaseName(fsInfo.mkPath("", "z")).build();
230
231 assertThat(documentName.localized()).isEqualTo(fsInfo.mkPath("", "a", "b", "c"));
232
233 if (fsInfo.roots().length > 1) {
234 documentName = DocumentName.builder(fsInfo).setName(
235 fsInfo.mkPath("", "a", "b", "c"))
236 .setBaseName(fsInfo.mkPath("", "z"))
237 .setRoot(fsInfo.roots()[1]).build();
238 assertThat(documentName.localized()).isEqualTo(fsInfo.mkPath("", "a", "b", "c"));
239 }
240 }
241
242 @Test
243 void asFileTest() throws IOException {
244 File expected = File.createTempFile("docNameTest", ".txt");
245 try (FileWriter fw = new FileWriter(expected, StandardCharsets.UTF_8)) {
246 fw.write("Hello world");
247 }
248 DocumentName underTest = DocumentName.builder(expected).build();
249 File actual = underTest.asFile();
250 try (FileReader fr = new FileReader(actual, StandardCharsets.UTF_8);
251 BufferedReader br = new BufferedReader(fr)) {
252 assertThat(br.readLine()).isEqualTo("Hello world");
253 }
254 }
255
256 @Test
257 void asPathTest() throws IOException {
258 File expected = File.createTempFile("docNameTest", ".txt");
259 try (FileWriter fw = new FileWriter(expected, StandardCharsets.UTF_8)) {
260 fw.write("Hello world");
261 }
262 DocumentName underTest = DocumentName.builder(expected).build();
263 Path actual = underTest.asPath();
264 Path root = Path.of(underTest.getRoot());
265 File file = root.resolve(actual).toFile();
266 try (FileReader fr = new FileReader(file, StandardCharsets.UTF_8);
267 BufferedReader br = new BufferedReader(fr)) {
268 assertThat(br.readLine()).isEqualTo("Hello world");
269 }
270 }
271
272 @ParameterizedTest(name = "{index} {0} {1}")
273 @MethodSource("archiveEntryTestData")
274 void archiveEntryNameTest(String os, String testName, DocumentName archiveName, String root, String separator, String baseName,
275 String localizedName) {
276 assertThat(archiveName.getRoot()).as("root").isEqualTo(root);
277 assertThat(archiveName.getDirectorySeparator()).as("separator").isEqualTo(separator);
278 assertThat(archiveName.getBaseName()).as("baseName").isEqualTo(baseName);
279 assertThat(archiveName.localized()).as("localized").isEqualTo(localizedName);
280 assertThat(archiveName.getName()).as("name").isEqualTo(baseName + localizedName);
281 if (!separator.equals(archiveName.fsInfo().dirSeparator()))
282 {
283 String newBaseName = separator.equals("/") ? baseName.replace('\\', '/') : baseName.replace('/', '\\');
284 assertThat(archiveName.localized(separator)).as("localized(x)").isEqualTo(newBaseName + localizedName);
285 }
286 }
287
288 static List<Arguments> archiveEntryTestData() {
289 List<Arguments> lst = new ArrayList<>();
290
291 for (FSInfo fsInfo : FSInfoTest.TEST_SUITE) {
292 String os = fsInfo.toString();
293 String root = fsInfo.roots()[0];
294 String baseName = root + "archives";
295 String simpleName = String.format("%sanArchive.zip", fsInfo.dirSeparator());
296 String entryName = "./anArchiveEntry.txt";
297 DocumentName archiveName = DocumentName.builder(fsInfo).setName(baseName + simpleName).setBaseName(baseName).build();
298 lst.add(Arguments.of(os, "archive name", archiveName, root, fsInfo.dirSeparator(), baseName, simpleName));
299
300 ArchiveEntryName archiveEntryName = new ArchiveEntryName(archiveName, entryName);
301 baseName = archiveName.getName() + "#";
302 root = baseName + "/";
303 lst.add(Arguments.of(os, "archive entry name", archiveEntryName, root, "/", baseName, "/anArchiveEntry.txt"));
304
305
306 entryName = "./someDir/anArchiveEntry.txt";
307 archiveEntryName = new ArchiveEntryName(archiveName, entryName);
308
309 lst.add(Arguments.of(os, "archive entry with directory", archiveEntryName, root, "/", baseName, "/someDir/anArchiveEntry.txt"));
310 }
311 return lst;
312 }
313 }