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    *      https://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.file;
18  
19  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
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.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  import static org.junit.jupiter.api.Assumptions.assumeTrue;
26  
27  import java.io.BufferedReader;
28  import java.io.BufferedWriter;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.io.OutputStream;
32  import java.io.UncheckedIOException;
33  import java.nio.channels.SeekableByteChannel;
34  import java.nio.charset.StandardCharsets;
35  import java.nio.file.DirectoryStream;
36  import java.nio.file.FileVisitOption;
37  import java.nio.file.Files;
38  import java.nio.file.LinkOption;
39  import java.nio.file.OpenOption;
40  import java.nio.file.Path;
41  import java.nio.file.Paths;
42  import java.nio.file.StandardCopyOption;
43  import java.nio.file.StandardOpenOption;
44  import java.nio.file.attribute.BasicFileAttributes;
45  import java.nio.file.attribute.FileAttribute;
46  import java.nio.file.attribute.FileTime;
47  import java.nio.file.attribute.PosixFilePermission;
48  import java.nio.file.attribute.UserPrincipal;
49  import java.util.Arrays;
50  import java.util.Collections;
51  import java.util.HashSet;
52  import java.util.Set;
53  import java.util.stream.Stream;
54  
55  import org.apache.commons.io.IOUtils;
56  import org.apache.commons.io.function.Uncheck;
57  import org.apache.commons.io.input.NullInputStream;
58  import org.apache.commons.io.output.NullOutputStream;
59  import org.apache.commons.lang3.ArrayUtils;
60  import org.junit.jupiter.api.AfterEach;
61  import org.junit.jupiter.api.BeforeAll;
62  import org.junit.jupiter.api.BeforeEach;
63  import org.junit.jupiter.api.Test;
64  import org.junit.jupiter.api.io.TempDir;
65  
66  /**
67   * Tests {@link FilesUncheck}.
68   *
69   * These tests are simple and just makes sure we do can make the call without catching IOException.
70   */
71  class FilesUncheckTest {
72  
73      private static final FileAttribute<?>[] EMPTY_FILE_ATTRIBUTES_ARRAY = {};
74  
75      private static final Path FILE_PATH_A = Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-1/file-size-1.bin");
76  
77      private static final Path FILE_PATH_EMPTY_SRC = Paths.get("src/test/resources/org/apache/commons/io/test-file-empty.bin");
78  
79      private static Path FILE_PATH_EMPTY;
80  
81      private static Path NEW_DIR_PATH;
82  
83      private static Path NEW_FILE_PATH;
84  
85      private static Path NEW_FILE_PATH_LINK;
86  
87      private static final String PREFIX = "prefix";
88  
89      private static final String SUFFIX = "suffix";
90  
91      @TempDir
92      static Path DEST_PATH;
93  
94      @BeforeAll
95      public static void beforeAll() throws IOException {
96          NEW_DIR_PATH = DEST_PATH.resolve("newdir");
97          NEW_FILE_PATH = DEST_PATH.resolve("file.txt");
98          NEW_FILE_PATH_LINK = DEST_PATH.resolve("to_another_file.txt");
99          // Allowance for Java 25, GitHub CI on Windows, when cloned repository is on a different volume than the Java temporary directory.
100         // Details:
101         // On GitHub CI on Windows, the cloned repository is on a different volume than the Java temporary directory.
102         // This means we cannot use the source file directly as the target of a link.
103         // Copy the text fixture to the destination directory to make sure it is on the same volume as the Java temporary directory.
104         FILE_PATH_EMPTY = Files.copy(FILE_PATH_EMPTY_SRC, DEST_PATH.resolve(FILE_PATH_EMPTY_SRC.getFileName()));
105     }
106 
107     @BeforeEach
108     @AfterEach
109     public void deleteFixtures() throws IOException {
110         Files.deleteIfExists(NEW_FILE_PATH);
111         Files.deleteIfExists(NEW_DIR_PATH);
112         Files.deleteIfExists(NEW_FILE_PATH_LINK);
113     }
114 
115     @Test
116     void testCopyInputStreamPathCopyOptionArray() {
117         assertEquals(0, FilesUncheck.copy(new NullInputStream(), NEW_FILE_PATH, PathUtils.EMPTY_COPY_OPTIONS));
118     }
119 
120     @Test
121     void testCopyPathOutputStream() {
122         assertEquals(0, FilesUncheck.copy(FILE_PATH_EMPTY, NullOutputStream.INSTANCE));
123     }
124 
125     @Test
126     void testCopyPathPathCopyOptionArray() {
127         assertEquals(NEW_FILE_PATH, FilesUncheck.copy(FILE_PATH_EMPTY, NEW_FILE_PATH, PathUtils.EMPTY_COPY_OPTIONS));
128     }
129 
130     @Test
131     void testCreateDirectories() {
132         assertEquals(DEST_PATH, FilesUncheck.createDirectories(DEST_PATH, EMPTY_FILE_ATTRIBUTES_ARRAY));
133     }
134 
135     @Test
136     void testCreateDirectory() {
137         assertEquals(NEW_DIR_PATH, FilesUncheck.createDirectory(NEW_DIR_PATH, EMPTY_FILE_ATTRIBUTES_ARRAY));
138     }
139 
140     @Test
141     void testCreateFile() {
142         assertEquals(NEW_FILE_PATH, FilesUncheck.createFile(NEW_FILE_PATH, EMPTY_FILE_ATTRIBUTES_ARRAY));
143     }
144 
145     @Test
146     void testCreateLink() {
147         assertEquals(NEW_FILE_PATH_LINK, FilesUncheck.createLink(NEW_FILE_PATH_LINK, FILE_PATH_EMPTY.toAbsolutePath()));
148     }
149 
150     @Test
151     void testCreateSymbolicLink() {
152         // May cause: Caused by: java.nio.file.FileSystemException: A required privilege is not held by the client.
153         assertEquals(NEW_FILE_PATH_LINK, FilesUncheck.createSymbolicLink(NEW_FILE_PATH_LINK, FILE_PATH_EMPTY));
154     }
155 
156     @Test
157     void testCreateTempDirectoryPathStringFileAttributeOfQArray() {
158         assertEquals(DEST_PATH, FilesUncheck.createTempDirectory(DEST_PATH, PREFIX, EMPTY_FILE_ATTRIBUTES_ARRAY).getParent());
159     }
160 
161     @Test
162     void testCreateTempDirectoryStringFileAttributeOfQArray() {
163         assertEquals(PathUtils.getTempDirectory(), FilesUncheck.createTempDirectory(PREFIX, EMPTY_FILE_ATTRIBUTES_ARRAY).getParent());
164     }
165 
166     @Test
167     void testCreateTempFilePathStringStringFileAttributeOfQArray() {
168         assertEquals(DEST_PATH, FilesUncheck.createTempFile(DEST_PATH, PREFIX, SUFFIX, EMPTY_FILE_ATTRIBUTES_ARRAY).getParent());
169     }
170 
171     @Test
172     void testCreateTempFileStringStringFileAttributeOfQArray() {
173         assertEquals(PathUtils.getTempDirectory(), FilesUncheck.createTempFile(PREFIX, SUFFIX, EMPTY_FILE_ATTRIBUTES_ARRAY).getParent());
174     }
175 
176     @Test
177     void testDelete() {
178         assertThrows(UncheckedIOException.class, () -> FilesUncheck.delete(NEW_FILE_PATH));
179     }
180 
181     @Test
182     void testDeleteIfExists() {
183         assertFalse(FilesUncheck.deleteIfExists(NEW_FILE_PATH));
184     }
185 
186     @Test
187     void testFind() {
188         try (Stream<Path> find = FilesUncheck.find(FILE_PATH_EMPTY, 0, (t, u) -> false)) {
189             assertNotNull(find);
190         }
191     }
192 
193     @Test
194     void testGetAttribute() {
195         assertEquals(0L, FilesUncheck.getAttribute(FILE_PATH_EMPTY, "basic:size", LinkOption.NOFOLLOW_LINKS));
196     }
197 
198     @Test
199     void testGetFileStore() {
200         assertNotNull(FilesUncheck.getFileStore(FILE_PATH_EMPTY));
201     }
202 
203     @Test
204     void testGetLastModifiedTime() {
205         assertTrue(0 < FilesUncheck.getLastModifiedTime(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS).toMillis());
206     }
207 
208     @Test
209     void testGetOwner() {
210         assertNotNull(FilesUncheck.getOwner(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS));
211     }
212 
213     @Test
214     void testGetPosixFilePermissions() {
215         assumeTrue(PathUtils.isPosix(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS));
216         assertNotNull(FilesUncheck.getPosixFilePermissions(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS));
217     }
218 
219     @Test
220     void testIsHidden() {
221         assertFalse(FilesUncheck.isHidden(FILE_PATH_EMPTY));
222     }
223 
224     @Test
225     void testIsSameFile() {
226         assertTrue(FilesUncheck.isSameFile(FILE_PATH_EMPTY, FILE_PATH_EMPTY));
227     }
228 
229     @Test
230     void testLinesPath() {
231         try (Stream<String> stream = FilesUncheck.lines(FILE_PATH_EMPTY)) {
232             assertEquals(0, stream.count());
233         }
234     }
235 
236     @Test
237     void testLinesPathCharset() {
238         try (Stream<String> stream = FilesUncheck.lines(FILE_PATH_EMPTY, StandardCharsets.UTF_8)) {
239             assertEquals(0, stream.count());
240         }
241     }
242 
243     @Test
244     void testList() {
245         try (Stream<Path> stream = FilesUncheck.list(Paths.get("src/test/resources/org/apache/commons/io/dirs-1-file-size-0"))) {
246             assertEquals(1, stream.count());
247         }
248     }
249 
250     @Test
251     void testMove() {
252         final Path tempFile1 = FilesUncheck.createTempFile(PREFIX, SUFFIX);
253         final Path tempFile2 = FilesUncheck.createTempFile(PREFIX, SUFFIX);
254         assertEquals(tempFile2, FilesUncheck.move(tempFile1, tempFile2, StandardCopyOption.REPLACE_EXISTING));
255         FilesUncheck.delete(tempFile2);
256     }
257 
258     @Test
259     void testNewBufferedReaderPath() {
260         Uncheck.run(() -> {
261             try (BufferedReader reader = FilesUncheck.newBufferedReader(FILE_PATH_EMPTY)) {
262                 IOUtils.consume(reader);
263             }
264         });
265     }
266 
267     @Test
268     void testNewBufferedReaderPathCharset() {
269         Uncheck.run(() -> {
270             try (BufferedReader reader = FilesUncheck.newBufferedReader(FILE_PATH_EMPTY, StandardCharsets.UTF_8)) {
271                 IOUtils.consume(reader);
272             }
273         });
274     }
275 
276     @Test
277     void testNewBufferedWriterPathCharsetOpenOptionArray() {
278         final Path tempPath = FilesUncheck.createTempFile(PREFIX, SUFFIX);
279         Uncheck.run(() -> {
280             try (BufferedWriter writer = FilesUncheck.newBufferedWriter(tempPath, StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING)) {
281                 writer.append("test");
282             }
283         });
284         assertEquals("test", FilesUncheck.readAllLines(tempPath, StandardCharsets.UTF_8).get(0));
285     }
286 
287     @Test
288     void testNewBufferedWriterPathOpenOptionArray() {
289         final Path tempPath = FilesUncheck.createTempFile(PREFIX, SUFFIX);
290         Uncheck.run(() -> {
291             try (BufferedWriter writer = FilesUncheck.newBufferedWriter(tempPath, StandardOpenOption.TRUNCATE_EXISTING)) {
292                 writer.append("test");
293             }
294         });
295         assertEquals("test", FilesUncheck.readAllLines(tempPath).get(0));
296     }
297 
298     @Test
299     void testNewByteChannelPathOpenOptionArray() {
300         assertEquals(0, Uncheck.getAsLong(() -> {
301             try (SeekableByteChannel c = FilesUncheck.newByteChannel(FILE_PATH_EMPTY, StandardOpenOption.READ)) {
302                 return c.size();
303             }
304         }));
305     }
306 
307     @Test
308     void testNewByteChannelPathSetOfQextendsOpenOptionFileAttributeOfQArray() {
309         final Set<OpenOption> options = new HashSet<>();
310         options.add(StandardOpenOption.READ);
311         assertEquals(0, Uncheck.getAsLong(() -> {
312             try (SeekableByteChannel c = FilesUncheck.newByteChannel(FILE_PATH_EMPTY, options, EMPTY_FILE_ATTRIBUTES_ARRAY)) {
313                 return c.size();
314             }
315         }));
316     }
317 
318     @Test
319     void testNewDirectoryStreamPath() {
320         Uncheck.run(() -> {
321             try (DirectoryStream<Path> directoryStream = FilesUncheck.newDirectoryStream(DEST_PATH)) {
322                 directoryStream.forEach(e -> assertEquals(DEST_PATH, e.getParent()));
323             }
324         });
325     }
326 
327     @Test
328     void testNewDirectoryStreamPathFilterOfQsuperPath() {
329         Uncheck.run(() -> {
330             try (DirectoryStream<Path> directoryStream = FilesUncheck.newDirectoryStream(DEST_PATH, e -> true)) {
331                 directoryStream.forEach(e -> assertEquals(DEST_PATH, e.getParent()));
332             }
333         });
334     }
335 
336     @Test
337     void testNewDirectoryStreamPathString() {
338         Uncheck.run(() -> {
339             try (DirectoryStream<Path> directoryStream = FilesUncheck.newDirectoryStream(DEST_PATH, "*.xml")) {
340                 directoryStream.forEach(e -> assertEquals(DEST_PATH, e.getParent()));
341             }
342         });
343     }
344 
345     @Test
346     void testNewInputStream() {
347         assertEquals(0, Uncheck.getAsInt(() -> {
348             try (InputStream in = FilesUncheck.newInputStream(FILE_PATH_EMPTY, StandardOpenOption.READ)) {
349                 return in.available();
350             }
351         }));
352     }
353 
354     @Test
355     void testNewOutputStream() {
356         final Path tempPath = FilesUncheck.createTempFile(PREFIX, SUFFIX);
357         Uncheck.run(() -> {
358             try (OutputStream stream = FilesUncheck.newOutputStream(tempPath, StandardOpenOption.TRUNCATE_EXISTING)) {
359                 stream.write("test".getBytes());
360             }
361         });
362         assertEquals("test", FilesUncheck.readAllLines(tempPath).get(0));
363     }
364 
365     @Test
366     void testProbeContentType() {
367         // BOM file:
368         FilesUncheck.probeContentType(Paths.get("src/test/resources/org/apache/commons/io/testfileBOM.xml"));
369         // Empirical: probeContentType is "text/plain" on Windows
370         // Empirical: probeContentType is "application/plain" on Ubuntu
371         // Empirical: probeContentType is ? on macOS
372     }
373 
374     @Test
375     void testProbeContentTypeEmpty() {
376         // Empty file:
377         FilesUncheck.probeContentType(FILE_PATH_EMPTY);
378         // Empirical: probeContentType is null on Windows
379         // Empirical: probeContentType is "text/plain" on Ubuntu
380         // Empirical: probeContentType is ? on macOS
381     }
382 
383     @Test
384     void testReadAllBytes() {
385         assertArrayEquals(ArrayUtils.EMPTY_BYTE_ARRAY, FilesUncheck.readAllBytes(FILE_PATH_EMPTY));
386         assertArrayEquals(new byte[] {'a'}, FilesUncheck.readAllBytes(FILE_PATH_A));
387     }
388 
389     @Test
390     void testReadAllLinesPath() {
391         assertEquals(Collections.emptyList(), FilesUncheck.readAllLines(FILE_PATH_EMPTY));
392         assertEquals(Arrays.asList("a"), FilesUncheck.readAllLines(FILE_PATH_A));
393     }
394 
395     @Test
396     void testReadAllLinesPathCharset() {
397         assertEquals(Collections.emptyList(), FilesUncheck.readAllLines(FILE_PATH_EMPTY, StandardCharsets.UTF_8));
398         assertEquals(Arrays.asList("a"), FilesUncheck.readAllLines(FILE_PATH_A, StandardCharsets.UTF_8));
399     }
400 
401     @Test
402     void testReadAttributesPathClassOfALinkOptionArray() {
403         assertNotNull(FilesUncheck.readAttributes(FILE_PATH_EMPTY, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS));
404     }
405 
406     @Test
407     void testReadAttributesPathStringLinkOptionArray() {
408         assertNotNull(FilesUncheck.readAttributes(FILE_PATH_EMPTY, "basic:lastModifiedTime", LinkOption.NOFOLLOW_LINKS));
409     }
410 
411     @Test
412     void testReadSymbolicLink() {
413         assertThrows(UncheckedIOException.class, () -> FilesUncheck.readSymbolicLink(NEW_FILE_PATH_LINK));
414     }
415 
416     @Test
417     void testSetAttribute() {
418         final FileTime ft = FilesUncheck.getLastModifiedTime(FILE_PATH_EMPTY);
419         assertEquals(FILE_PATH_EMPTY, FilesUncheck.setAttribute(FILE_PATH_EMPTY, "basic:lastModifiedTime", ft, LinkOption.NOFOLLOW_LINKS));
420     }
421 
422     @Test
423     void testSetLastModifiedTime() {
424         final FileTime ft = FilesUncheck.getLastModifiedTime(FILE_PATH_EMPTY);
425         assertEquals(FILE_PATH_EMPTY, FilesUncheck.setLastModifiedTime(FILE_PATH_EMPTY, ft));
426     }
427 
428     @Test
429     void testSetOwner() {
430         final UserPrincipal owner = FilesUncheck.getOwner(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS);
431         assertEquals(FILE_PATH_EMPTY, FilesUncheck.setOwner(FILE_PATH_EMPTY, owner));
432     }
433 
434     @Test
435     void testSetPosixFilePermissions() {
436         assumeTrue(PathUtils.isPosix(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS));
437         final Set<PosixFilePermission> posixFilePermissions = FilesUncheck.getPosixFilePermissions(FILE_PATH_EMPTY, LinkOption.NOFOLLOW_LINKS);
438         assertEquals(FILE_PATH_EMPTY, FilesUncheck.setPosixFilePermissions(FILE_PATH_EMPTY, posixFilePermissions));
439     }
440 
441     @Test
442     void testSize() {
443         assertEquals(0, FilesUncheck.size(FILE_PATH_EMPTY));
444         assertEquals(1, FilesUncheck.size(FILE_PATH_A));
445     }
446 
447     @Test
448     void testWalkFileTreePathFileVisitorOfQsuperPath() {
449         assertEquals(DEST_PATH, FilesUncheck.walkFileTree(DEST_PATH, NoopPathVisitor.INSTANCE));
450     }
451 
452     @Test
453     void testWalkFileTreePathSetOfFileVisitOptionIntFileVisitorOfQsuperPath() {
454         assertEquals(DEST_PATH, FilesUncheck.walkFileTree(DEST_PATH, new HashSet<>(), 1, NoopPathVisitor.INSTANCE));
455     }
456 
457     @Test
458     void testWalkPathFileVisitOptionArray() {
459         try (Stream<Path> stream = FilesUncheck.walk(DEST_PATH, FileVisitOption.FOLLOW_LINKS)) {
460             assertTrue(0 < stream.count());
461         }
462     }
463 
464     @Test
465     void testWalkPathIntFileVisitOptionArray() {
466         try (Stream<Path> stream = FilesUncheck.walk(DEST_PATH, 0, FileVisitOption.FOLLOW_LINKS)) {
467             assertEquals(1, stream.count());
468         }
469     }
470 
471     @Test
472     void testWritePathByteArrayOpenOptionArray() {
473         final Path tempFile = FilesUncheck.createTempFile(PREFIX, SUFFIX);
474         assertEquals(tempFile, FilesUncheck.write(tempFile, "test".getBytes(), StandardOpenOption.TRUNCATE_EXISTING));
475         FilesUncheck.delete(tempFile);
476     }
477 
478     @Test
479     void testWritePathIterableOfQextendsCharSequenceCharsetOpenOptionArray() {
480         final Path tempFile = FilesUncheck.createTempFile(PREFIX, SUFFIX);
481         assertEquals(tempFile, FilesUncheck.write(tempFile, Arrays.asList("test"), StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING));
482         FilesUncheck.delete(tempFile);
483     }
484 
485     @Test
486     void testWritePathIterableOfQextendsCharSequenceOpenOptionArray() {
487         final Path tempFile = FilesUncheck.createTempFile(PREFIX, SUFFIX);
488         assertEquals(tempFile, FilesUncheck.write(tempFile, Arrays.asList("test"), StandardOpenOption.TRUNCATE_EXISTING));
489         FilesUncheck.delete(tempFile);
490     }
491 
492 }