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
44 import static org.assertj.core.api.Assertions.assertThat;
45 import static org.assertj.core.api.Assertions.assertThatThrownBy;
46 import static org.mockito.Mockito.mock;
47 import static org.mockito.Mockito.when;
48 import static org.mockito.ArgumentMatchers.any;
49
50 public class DocumentNameTest {
51 private static final FSInfo[] TEST_SUITE = FSInfoTest.TEST_SUITE;
52
53
54
55
56
57
58
59 private static File[] listFiles(File directory, FSInfo fsInfo) {
60 File[] fileList = directory.listFiles();
61 return fileList == null ? null : Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).toArray(File[]::new);
62 }
63
64
65
66
67
68
69
70
71 private static File[] listFiles(File directory, FSInfo fsInfo, FileFilter filter) {
72 File[] fileList = directory.listFiles();
73 return fileList == null ? null : Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(filter::accept).toArray(File[]::new);
74 }
75
76
77
78
79
80
81
82
83 private static File[] listFiles(File directory, FSInfo fsInfo, FilenameFilter filter) {
84 File[] fileList = directory.listFiles();
85 return fileList == null ? null : Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(x -> filter.accept(x, x.getName())).toArray(File[]::new);
86 }
87
88
89
90
91
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
109
110
111
112
113
114
115 @ParameterizedTest(name = "{index} {0} {1} {3}")
116 @MethodSource("resolveTestData")
117 void resolveTest(DocumentName.FSInfo fsInfo, String root, DocumentName base, String toResolve, DocumentName expected) {
118 DocumentName actual = base.resolve(toResolve);
119 assertThat(actual.getName()).isEqualTo(expected.getName());
120 }
121
122 private static Stream<Arguments> resolveTestData() {
123 List<Arguments> lst = new ArrayList<>();
124 DocumentName base;
125 DocumentName expected;
126 for (DocumentName.FSInfo fsInfo : TEST_SUITE) {
127 String root = fsInfo.roots()[0];
128 for (String baseName : List.of(root, root + fsInfo.mkPath("from", "base"))) {
129 for (String testRoot : fsInfo.roots()) {
130 String name = testRoot + fsInfo.mkPath("", "dir", fsInfo.toString());
131 base = DocumentName.builder(fsInfo).setName(name).setBaseName(baseName).build();
132 lst.add(Arguments.of(fsInfo, base.getName(), base, null, base));
133
134 lst.add(Arguments.of(fsInfo, base.getName(), base, "", base));
135
136 lst.add(Arguments.of(fsInfo, base.getName(), base, " ", base));
137
138 expected = DocumentName.builder(fsInfo).setName(fsInfo.mkPath(name, "relative")).setBaseName(baseName).build();
139 lst.add(Arguments.of(fsInfo, base.getName(), base, "relative", expected));
140
141 expected = DocumentName.builder(fsInfo).setRoot(testRoot).setName(fsInfo.mkPath("", "from", "root")).setBaseName(baseName).build();
142 lst.add(Arguments.of(fsInfo, base.getName(), base, fsInfo.mkPath("", "from", "root"), expected));
143
144 expected = DocumentName.builder(fsInfo).setRoot(testRoot).setName(fsInfo.mkPath("dir", "up", "and", "down")).setBaseName(baseName).build();
145 lst.add(Arguments.of(fsInfo, base.getName(), base, fsInfo.mkPath("..", "up", "and", "down"), expected));
146
147 expected = DocumentName.builder(fsInfo).setRoot(testRoot).setName(fsInfo.mkPath("", "from", "root")).setBaseName(baseName).build();
148 String wrongSeparator = fsInfo.dirSeparator().equals("/") ? "\\" : "/";
149 lst.add(Arguments.of(fsInfo, base.getName(), base, String.join(wrongSeparator, "", "from", "root"), expected));
150
151 expected = DocumentName.builder(fsInfo).setRoot(testRoot).setName(fsInfo.mkPath("dir", "up", "and", "down")).setBaseName(baseName).build();
152 lst.add(Arguments.of(fsInfo, base.getName(), base, String.join(wrongSeparator, "..", "up", "and", "down"), expected));
153 }
154 }
155 }
156 return lst.stream();
157 }
158
159 @Test
160 void resolveWithMultipleRootsTest() {
161
162 DocumentName.FSInfo fsInfo = FSInfoTest.WINDOWS;
163 DocumentName base = DocumentName.builder(fsInfo).setName(fsInfo.mkPath("", "dir", fsInfo.toString()))
164 .setBaseName("").build();
165
166 String resolveName = fsInfo.roots()[1] + fsInfo.mkPath("dir", fsInfo.toString());
167 assertThatThrownBy(() -> base.resolve(resolveName))
168 .as(resolveName)
169 .hasMessageContaining(String.format("%s does not start with %s", resolveName, base.getName()))
170 .isInstanceOf(IllegalArgumentException.class);
171
172 String resolveName2 = fsInfo.roots()[0] + fsInfo.mkPath("dir", fsInfo.toString(), "thing");
173 assertThat(base.resolve(resolveName2).getName())
174 .isEqualTo(resolveName2);
175 }
176
177 void testNoRootSpecified() {
178
179 assertThat(DocumentName.startsWithRootOrSeparator("X:/candidate", null, "/")).isFalse();
180 assertThat(DocumentName.startsWithRootOrSeparator("X:/candidate", "", "/")).isFalse();
181 assertThat(DocumentName.startsWithRootOrSeparator("X;/candidate", " ", "/")).isFalse();
182 assertThat(DocumentName.startsWithRootOrSeparator("/candidate", null, "/")).isTrue();
183 assertThat(DocumentName.startsWithRootOrSeparator("/candidate", "", "/")).isTrue();
184 assertThat(DocumentName.startsWithRootOrSeparator("/candidate", " ", "/")).isTrue();
185 assertThat(DocumentName.startsWithRootOrSeparator("candidate", null, "/")).isFalse();
186 assertThat(DocumentName.startsWithRootOrSeparator("candidate", "", "/")).isFalse();
187 assertThat(DocumentName.startsWithRootOrSeparator("candidate", " ", "/")).isFalse();
188 }
189
190 @Test
191 void startsWithRootOrSeparatorTest() {
192 assertThat(DocumentName.startsWithRootOrSeparator("X:/candidate", "X:/", "/")).isTrue();
193 assertThat(DocumentName.startsWithRootOrSeparator("X:/candidate", "Y:/", "/")).isFalse();
194 assertThat(DocumentName.startsWithRootOrSeparator("/candidate", "X:/", "/")).isTrue();
195 assertThat(DocumentName.startsWithRootOrSeparator("\\candidate", "Y:/", "/")).isFalse();
196 assertThat(DocumentName.startsWithRootOrSeparator("candidate", "Y:/", "/")).isFalse();
197 assertThat(DocumentName.startsWithRootOrSeparator("Y:candidate", "Y:/", "/")).isFalse();
198 assertThat(DocumentName.startsWithRootOrSeparator(null, "Y:/", "/")).isFalse();
199 assertThat(DocumentName.startsWithRootOrSeparator("", "Y:/", "/")).isFalse();
200 assertThat(DocumentName.startsWithRootOrSeparator(" ", "Y:/", "/")).isFalse();
201
202 testNoRootSpecified();
203 }
204
205 @ParameterizedTest
206 @FieldSource("TEST_SUITE")
207 void localizeTest(FSInfo fsInfo) {
208 DocumentName documentName = DocumentName.builder(fsInfo).setName(
209 fsInfo.mkPath("", "a", "b", "c"))
210 .setBaseName(fsInfo.mkPath("", "a")).build();
211
212 assertThat(documentName.localized()).isEqualTo(fsInfo.mkPath("", "b", "c"));
213 assertThat(documentName.localized("-")).isEqualTo("-b-c");
214
215 documentName = DocumentName.builder(fsInfo).setName(
216 fsInfo.mkPath("", "a", "b", "c"))
217 .setBaseName(fsInfo.mkPath("", "z")).build();
218
219 assertThat(documentName.localized()).isEqualTo(fsInfo.mkPath("", "a", "b", "c"));
220
221 if (fsInfo.roots().length > 1) {
222 documentName = DocumentName.builder(fsInfo).setName(
223 fsInfo.mkPath("", "a", "b", "c"))
224 .setBaseName(fsInfo.mkPath("", "z"))
225 .setRoot(fsInfo.roots()[1]).build();
226 assertThat(documentName.localized()).isEqualTo(fsInfo.mkPath("", "a", "b", "c"));
227 }
228 }
229
230 @Test
231 void asFileTest() throws IOException {
232 File expected = File.createTempFile("docNameTest", ".txt");
233 try (FileWriter fw = new FileWriter(expected, StandardCharsets.UTF_8)) {
234 fw.write("Hello world");
235 }
236 DocumentName underTest = DocumentName.builder(expected).build();
237 File actual = underTest.asFile();
238 try (FileReader fr = new FileReader(actual, StandardCharsets.UTF_8);
239 BufferedReader br = new BufferedReader(fr)) {
240 assertThat(br.readLine()).isEqualTo("Hello world");
241 }
242 }
243
244 @Test
245 void asPathTest() throws IOException {
246 File expected = File.createTempFile("docNameTest", ".txt");
247 try (FileWriter fw = new FileWriter(expected, StandardCharsets.UTF_8)) {
248 fw.write("Hello world");
249 }
250 DocumentName underTest = DocumentName.builder(expected).build();
251 Path actual = underTest.asPath();
252 Path root = Path.of(underTest.getRoot());
253 File file = root.resolve(actual).toFile();
254 try (FileReader fr = new FileReader(file, StandardCharsets.UTF_8);
255 BufferedReader br = new BufferedReader(fr)) {
256 assertThat(br.readLine()).isEqualTo("Hello world");
257 }
258 }
259
260 @ParameterizedTest(name = "{index} {0} {1}")
261 @MethodSource("archiveEntryTestData")
262 void archiveEntryNameTest(String os, String testName, DocumentName archiveName, String root, String separator, String baseName,
263 String localizedName) {
264 assertThat(archiveName.getRoot()).as("root").isEqualTo(root);
265 assertThat(archiveName.getDirectorySeparator()).as("separator").isEqualTo(separator);
266 assertThat(archiveName.getBaseName()).as("baseName").isEqualTo(baseName);
267 assertThat(archiveName.localized()).as("localized").isEqualTo(localizedName);
268 assertThat(archiveName.getName()).as("name").isEqualTo(baseName + localizedName);
269 if (!separator.equals(archiveName.fsInfo().dirSeparator()))
270 {
271 String newBaseName = separator.equals("/") ? baseName.replace('\\', '/') : baseName.replace('/', '\\');
272 assertThat(archiveName.localized(separator)).as("localized(x)").isEqualTo(newBaseName + localizedName);
273 }
274 }
275
276 static List<Arguments> archiveEntryTestData() {
277 List<Arguments> lst = new ArrayList<>();
278
279 for (FSInfo fsInfo : FSInfoTest.TEST_SUITE) {
280 String os = fsInfo.toString();
281 String root = fsInfo.roots()[0];
282 String baseName = String.format(String.format("%sarchives", root));
283 String simpleName = String.format("%sanArchive.zip", fsInfo.dirSeparator());
284 String entryName = "./anArchiveEntry.txt";
285 DocumentName archiveName = DocumentName.builder(fsInfo).setName(baseName + simpleName).setBaseName(baseName).build();
286 lst.add(Arguments.of(os, "archive name", archiveName, root, fsInfo.dirSeparator(), baseName, simpleName));
287
288 ArchiveEntryName archiveEntryName = new ArchiveEntryName(archiveName, entryName);
289 baseName = archiveName.getName() + "#";
290 root = baseName + "/";
291 lst.add(Arguments.of(os, "archive entry name", archiveEntryName, root, "/", baseName, "/anArchiveEntry.txt"));
292
293
294 entryName = "./someDir/anArchiveEntry.txt";
295 archiveEntryName = new ArchiveEntryName(archiveName, entryName);
296
297 lst.add(Arguments.of(os, "archive entry with directory", archiveEntryName, root, "/", baseName, "/someDir/anArchiveEntry.txt"));
298 }
299 return lst;
300 }
301
302 }