View Javadoc
1   package org.codehaus.plexus.util;
2   
3   /*
4    * Copyright The Codehaus Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * 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, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.OutputStream;
24  import java.io.OutputStreamWriter;
25  import java.io.Reader;
26  import java.io.Writer;
27  import java.net.URL;
28  import java.nio.charset.StandardCharsets;
29  import java.nio.file.Files;
30  import java.nio.file.Paths;
31  import java.util.Properties;
32  
33  import org.junit.jupiter.api.BeforeEach;
34  import org.junit.jupiter.api.Test;
35  import org.junit.jupiter.api.condition.EnabledOnOs;
36  import org.junit.jupiter.api.condition.OS;
37  
38  import static org.junit.jupiter.api.Assertions.*;
39  
40  /**
41   * This is used to test FileUtils for correctness.
42   *
43   * @author Peter Donald
44   * @author Matthew Hawthorne
45   * @see FileUtils
46   * @since 3.4.0
47   */
48  public final class FileUtilsTest extends FileBasedTestCase {
49      // Test data
50  
51      /**
52       * Size of test directory.
53       */
54      private static final int TEST_DIRECTORY_SIZE = 0;
55  
56      private final File testFile1;
57  
58      private final File testFile2;
59  
60      private static int testFile1Size;
61  
62      private static int testFile2Size;
63  
64      public FileUtilsTest() {
65          testFile1 = new File(getTestDirectory(), "file1-test.txt");
66          testFile2 = new File(getTestDirectory(), "file1a-test.txt");
67  
68          testFile1Size = (int) testFile1.length();
69          testFile2Size = (int) testFile2.length();
70      }
71  
72      @BeforeEach
73      void setUp() throws Exception {
74          getTestDirectory().mkdirs();
75          createFile(testFile1, testFile1Size);
76          createFile(testFile2, testFile2Size);
77          FileUtils.deleteDirectory(getTestDirectory());
78          getTestDirectory().mkdirs();
79          createFile(testFile1, testFile1Size);
80          createFile(testFile2, testFile2Size);
81      }
82  
83      @Test
84      void byteCountToDisplaySize() {
85          assertEquals("0 bytes", FileUtils.byteCountToDisplaySize(0));
86          assertEquals("1 KB", FileUtils.byteCountToDisplaySize(1024));
87          assertEquals("1 MB", FileUtils.byteCountToDisplaySize(1024 * 1024));
88          assertEquals("1 GB", FileUtils.byteCountToDisplaySize(1024 * 1024 * 1024));
89      }
90  
91      @Test
92      void waitFor() {
93          FileUtils.waitFor("", -1);
94          FileUtils.waitFor("", 2);
95      }
96  
97      @Test
98      void toFile() throws Exception {
99          URL url = getClass().getResource("/test.txt");
100         url = new URL(url.toString() + "/name%20%23%2520%3F%7B%7D%5B%5D%3C%3E.txt");
101         File file = FileUtils.toFile(url);
102         assertEquals("name #%20?{}[]<>.txt", file.getName());
103     }
104 
105     @Test
106     void toFileBadProtocol() throws Exception {
107         URL url = new URL("http://maven.apache.org/");
108         assertNull(FileUtils.toFile(url));
109     }
110 
111     @Test
112     void toFileNull() {
113         File file = FileUtils.toFile(null);
114         assertNull(file);
115     }
116 
117     // Hacked to sanity by Trygve
118     @Test
119     void toURLs() throws Exception {
120         File[] files = new File[] {
121             new File("file1"), new File("file2"),
122         };
123 
124         URL[] urls = FileUtils.toURLs(files);
125 
126         assertEquals(
127                 files.length,
128                 urls.length,
129                 "The length of the generated URL's is not equals to the length of files. " + "Was " + files.length
130                         + ", expected " + urls.length);
131 
132         for (int i = 0; i < urls.length; i++) {
133             assertEquals(files[i].toURI().toURL(), urls[i]);
134         }
135     }
136 
137     @Test
138     void getFilesFromExtension() {
139         // TODO I'm not sure what is supposed to happen here
140         FileUtils.getFilesFromExtension("dir", null);
141 
142         // Non-existent files
143         String[] emptyFileNames =
144                 FileUtils.getFilesFromExtension(getTestDirectory().getAbsolutePath(), new String[] {"java"});
145         assertEquals(0, emptyFileNames.length);
146 
147         // Existing files
148         // TODO Figure out how to test this
149         /*
150          * final String[] fileNames = FileUtils.getFilesFromExtension( getClass().getResource("/java/util/").getFile(),
151          * new String[] { "class" }); assertTrue(fileNames.length > 0);
152          */
153     }
154 
155     @Test
156     void mkdir() {
157         final File dir = new File(getTestDirectory(), "testdir");
158         FileUtils.mkdir(dir.getAbsolutePath());
159         dir.deleteOnExit();
160 
161         if (Os.isFamily(Os.FAMILY_WINDOWS)) {
162             assertThrows(IllegalArgumentException.class, () -> {
163                 File winFile = new File(getTestDirectory(), "bla*bla");
164                 winFile.deleteOnExit();
165                 FileUtils.mkdir(winFile.getAbsolutePath());
166             });
167         }
168     }
169 
170     @Test
171     void contentEquals() throws Exception {
172         // Non-existent files
173         final File file = new File(getTestDirectory(), getTestMethodName());
174         assertTrue(FileUtils.contentEquals(file, file));
175 
176         // TODO Should comparing 2 directories throw an Exception instead of returning false?
177         // Directories
178         assertFalse(FileUtils.contentEquals(getTestDirectory(), getTestDirectory()));
179 
180         // Different files
181         final File objFile1 = new File(getTestDirectory(), getTestMethodName() + ".object");
182         objFile1.deleteOnExit();
183         FileUtils.copyURLToFile(getClass().getResource("/java/lang/Object.class"), objFile1);
184 
185         final File objFile2 = new File(getTestDirectory(), getTestMethodName() + ".collection");
186         objFile2.deleteOnExit();
187         FileUtils.copyURLToFile(getClass().getResource("/java/util/Collection.class"), objFile2);
188 
189         assertFalse(FileUtils.contentEquals(objFile1, objFile2), "Files should not be equal.");
190 
191         // Equal files
192         file.createNewFile();
193         assertTrue(FileUtils.contentEquals(file, file));
194     }
195 
196     @Test
197     void removePath() {
198         String fileName = FileUtils.removePath(new File(getTestDirectory(), getTestMethodName()).getAbsolutePath());
199         assertEquals(getTestMethodName(), fileName);
200     }
201 
202     @Test
203     void getPath() {
204         final String fileName = FileUtils.getPath(new File(getTestDirectory(), getTestMethodName()).getAbsolutePath());
205         assertEquals(getTestDirectory().getAbsolutePath(), fileName);
206     }
207 
208     @Test
209     void copyURLToFile() throws Exception {
210         // Creates file
211         final File file = new File(getTestDirectory(), getTestMethodName());
212         file.deleteOnExit();
213 
214         // Loads resource
215         final String resourceName = "/java/lang/Object.class";
216         FileUtils.copyURLToFile(getClass().getResource(resourceName), file);
217 
218         // Tests that resource was copied correctly
219         try (InputStream fis = Files.newInputStream(file.toPath())) {
220             assertTrue(
221                     IOUtil.contentEquals(getClass().getResourceAsStream(resourceName), fis), "Content is not equal.");
222         }
223     }
224 
225     @Test
226     void catPath() {
227         // TODO StringIndexOutOfBoundsException thrown if file doesn't contain slash.
228         // Is this acceptable?
229         // assertEquals("", FileUtils.catPath("a", "b"));
230 
231         assertEquals("/a/c", FileUtils.catPath("/a/b", "c"));
232         assertEquals("/a/d", FileUtils.catPath("/a/b/c", "../d"));
233     }
234 
235     @Test
236     void forceMkdir() throws Exception {
237         // Tests with existing directory
238         FileUtils.forceMkdir(getTestDirectory());
239 
240         // Creates test file
241         final File testFile = new File(getTestDirectory(), getTestMethodName());
242         testFile.deleteOnExit();
243         testFile.createNewFile();
244         assertTrue(testFile.exists(), "Test file does not exist.");
245 
246         // Tests with existing file
247         assertThrows(IOException.class, () -> FileUtils.forceMkdir(testFile));
248 
249         testFile.delete();
250 
251         // Tests with non-existent directory
252         FileUtils.forceMkdir(testFile);
253         assertTrue(testFile.exists(), "Directory was not created.");
254 
255         if (Os.isFamily(Os.FAMILY_WINDOWS)) {
256             assertThrows(IllegalArgumentException.class, () -> {
257                 File winFile = new File(getTestDirectory(), "bla*bla");
258                 winFile.deleteOnExit();
259                 FileUtils.forceMkdir(winFile);
260             });
261         }
262     }
263 
264     @Test
265     void sizeOfDirectory() throws Exception {
266         final File file = new File(getTestDirectory(), getTestMethodName());
267 
268         assertThrows(IllegalArgumentException.class, () -> {
269             // Non-existent file
270             FileUtils.sizeOfDirectory(file);
271         });
272 
273         // Creates file
274         file.createNewFile();
275         file.deleteOnExit();
276 
277         // Existing file
278         assertThrows(IllegalArgumentException.class, () -> FileUtils.sizeOfDirectory(file));
279 
280         // Existing directory
281         file.delete();
282         file.mkdir();
283 
284         assertEquals(TEST_DIRECTORY_SIZE, FileUtils.sizeOfDirectory(file), "Unexpected directory size");
285     }
286 
287     @Test
288     void copyFile1() throws Exception {
289         final File destination = new File(getTestDirectory(), "copy1.txt");
290         FileUtils.copyFile(testFile1, destination);
291         assertTrue(destination.exists(), "Check Exist");
292         assertEquals(destination.length(), testFile1Size, "Check Full copy");
293     }
294 
295     @Test
296     void copyFile2() throws Exception {
297         final File destination = new File(getTestDirectory(), "copy2.txt");
298         FileUtils.copyFile(testFile1, destination);
299         assertTrue(destination.exists(), "Check Exist");
300         assertEquals(destination.length(), testFile2Size, "Check Full copy");
301     }
302 
303     /**
304      * ensure we create directory tree for destination
305      */
306     @Test
307     void copyFile3() throws Exception {
308         File destDirectory = new File(getTestDirectory(), "foo/bar/testcopy");
309         if (destDirectory.exists()) {
310             destDirectory.delete();
311         }
312         final File destination = new File(destDirectory, "copy2.txt");
313         FileUtils.copyFile(testFile1, destination);
314         assertTrue(destination.exists(), "Check Exist");
315         assertEquals(destination.length(), testFile2Size, "Check Full copy");
316     }
317 
318     @Test
319     void linkFile1() throws Exception {
320         final File destination = new File(getTestDirectory(), "link1.txt");
321         FileUtils.linkFile(testFile1, destination);
322         assertTrue(destination.exists(), "Check Exist");
323         assertEquals(destination.length(), testFile1Size, "Check File length");
324         assertTrue(Files.isSymbolicLink(destination.toPath()), "Check is link");
325     }
326 
327     @Test
328     void linkFile2() throws Exception {
329         final File destination = new File(getTestDirectory(), "link2.txt");
330         FileUtils.linkFile(testFile1, destination);
331         assertTrue(destination.exists(), "Check Exist");
332         assertEquals(destination.length(), testFile2Size, "Check File length");
333         assertTrue(Files.isSymbolicLink(destination.toPath()), "Check is link");
334     }
335 
336     /**
337      * ensure we create directory tree for destination
338      */
339     @Test
340     void linkFile3() throws Exception {
341         File destDirectory = new File(getTestDirectory(), "foo/bar/testlink");
342         if (destDirectory.exists()) {
343             destDirectory.delete();
344         }
345         final File destination = new File(destDirectory, "link2.txt");
346         FileUtils.linkFile(testFile1, destination);
347         assertTrue(destination.exists(), "Check Exist");
348         assertEquals(destination.length(), testFile2Size, "Check File length");
349         assertTrue(Files.isSymbolicLink(destination.toPath()), "Check is link");
350     }
351 
352     @Test
353     void copyIfModifiedWhenSourceIsNewer() throws Exception {
354         FileUtils.forceMkdir(new File(getTestDirectory() + "/temp"));
355 
356         // Place destination
357         File destination = new File(getTestDirectory() + "/temp/copy1.txt");
358         FileUtils.copyFile(testFile1, destination);
359 
360         // Make sure source is newer
361         reallySleep(1000);
362 
363         // Place source
364         File source = new File(getTestDirectory(), "copy1.txt");
365         FileUtils.copyFile(testFile1, source);
366         source.setLastModified(System.currentTimeMillis());
367 
368         // Copy will occur when source is newer
369         assertTrue(
370                 FileUtils.copyFileIfModified(source, destination),
371                 "Failed copy. Target file should have been updated.");
372     }
373 
374     @Test
375     void copyIfModifiedWhenSourceIsOlder() throws Exception {
376         FileUtils.forceMkdir(new File(getTestDirectory() + "/temp"));
377 
378         // Place source
379         File source = new File(getTestDirectory() + "copy1.txt");
380         FileUtils.copyFile(testFile1, source);
381 
382         // Make sure destination is newer
383         reallySleep(1000);
384 
385         // Place destination
386         File destination = new File(getTestDirectory(), "/temp/copy1.txt");
387         FileUtils.copyFile(testFile1, destination);
388 
389         // Copy will occur when destination is newer
390         assertFalse(FileUtils.copyFileIfModified(source, destination), "Source file should not have been copied.");
391     }
392 
393     @Test
394     void copyIfModifiedWhenSourceHasZeroDate() throws Exception {
395         FileUtils.forceMkdir(new File(getTestDirectory(), "temp"));
396 
397         // Source modified on 1970-01-01T00:00Z
398         File source = new File(getTestDirectory(), "copy1.txt");
399         FileUtils.copyFile(testFile1, source);
400         source.setLastModified(0L);
401 
402         // A non existing destination
403         File destination = new File(getTestDirectory(), "temp/copy1.txt");
404 
405         // Should copy the source to the non existing destination.
406         assertTrue(FileUtils.copyFileIfModified(source, destination), "Source file should have been copied.");
407     }
408 
409     @Test
410     void forceDeleteAFile1() throws Exception {
411         final File destination = new File(getTestDirectory(), "copy1.txt");
412         destination.createNewFile();
413         assertTrue(destination.exists(), "Copy1.txt doesn't exist to delete");
414         FileUtils.forceDelete(destination);
415         assertFalse(destination.exists(), "Check No Exist");
416     }
417 
418     @Test
419     void forceDeleteAFile2() throws Exception {
420         final File destination = new File(getTestDirectory(), "copy2.txt");
421         destination.createNewFile();
422         assertTrue(destination.exists(), "Copy2.txt doesn't exist to delete");
423         FileUtils.forceDelete(destination);
424         assertFalse(destination.exists(), "Check No Exist");
425     }
426 
427     @Test
428     void copyFile1ToDir() throws Exception {
429         final File directory = new File(getTestDirectory(), "subdir");
430         if (!directory.exists()) {
431             directory.mkdirs();
432         }
433         final File destination = new File(directory, testFile1.getName());
434         FileUtils.copyFileToDirectory(testFile1, directory);
435         assertTrue(destination.exists(), "Check Exist");
436         assertEquals(destination.length(), testFile1Size, "Check Full copy");
437     }
438 
439     @Test
440     void copyFile2ToDir() throws Exception {
441         final File directory = new File(getTestDirectory(), "subdir");
442         if (!directory.exists()) {
443             directory.mkdirs();
444         }
445         final File destination = new File(directory, testFile1.getName());
446         FileUtils.copyFileToDirectory(testFile1, directory);
447         assertTrue(destination.exists(), "Check Exist");
448         assertEquals(destination.length(), testFile2Size, "Check Full copy");
449     }
450 
451     @Test
452     void copyFile1ToDirIfModified() throws Exception {
453         final File directory = new File(getTestDirectory(), "subdir");
454         if (directory.exists()) {
455             FileUtils.forceDelete(directory);
456         }
457         directory.mkdirs();
458 
459         final File destination = new File(directory, testFile1.getName());
460 
461         FileUtils.copyFileToDirectoryIfModified(testFile1, directory);
462 
463         final File target = new File(getTestDirectory() + "/subdir", testFile1.getName());
464         long timestamp = target.lastModified();
465 
466         assertTrue(destination.exists(), "Check Exist");
467         assertEquals(destination.length(), testFile1Size, "Check Full copy");
468 
469         FileUtils.copyFileToDirectoryIfModified(testFile1, directory);
470 
471         assertEquals(timestamp, target.lastModified(), "Timestamp was changed");
472     }
473 
474     @Test
475     void copyFile2ToDirIfModified() throws Exception {
476         final File directory = new File(getTestDirectory(), "subdir");
477         if (directory.exists()) {
478             FileUtils.forceDelete(directory);
479         }
480         directory.mkdirs();
481 
482         final File destination = new File(directory, testFile2.getName());
483 
484         FileUtils.copyFileToDirectoryIfModified(testFile2, directory);
485 
486         final File target = new File(getTestDirectory() + "/subdir", testFile2.getName());
487         long timestamp = target.lastModified();
488 
489         assertTrue(destination.exists(), "Check Exist");
490         assertEquals(destination.length(), testFile2Size, "Check Full copy");
491 
492         FileUtils.copyFileToDirectoryIfModified(testFile2, directory);
493 
494         assertEquals(timestamp, target.lastModified(), "Timestamp was changed");
495     }
496 
497     @Test
498     void forceDeleteDir() throws Exception {
499         FileUtils.forceDelete(getTestDirectory().getParentFile());
500         assertFalse(getTestDirectory().getParentFile().exists(), "Check No Exist");
501     }
502 
503     @Test
504     void resolveFileDotDot() {
505         final File file = FileUtils.resolveFile(getTestDirectory(), "..");
506         assertEquals(file, getTestDirectory().getParentFile(), "Check .. operator");
507     }
508 
509     @Test
510     void resolveFileDot() {
511         final File file = FileUtils.resolveFile(getTestDirectory(), ".");
512         assertEquals(file, getTestDirectory(), "Check . operator");
513     }
514 
515     @Test
516     void normalize() {
517         final String[] src = {
518             "",
519             "/",
520             "///",
521             "/foo",
522             "/foo//",
523             "/./",
524             "/foo/./",
525             "/foo/./bar",
526             "/foo/../bar",
527             "/foo/../bar/../baz",
528             "/foo/bar/../../baz",
529             "/././",
530             "/foo/./../bar",
531             "/foo/.././bar/",
532             "//foo//./bar",
533             "/../",
534             "/foo/../../"
535         };
536 
537         final String[] dest = {
538             "",
539             "/",
540             "/",
541             "/foo",
542             "/foo/",
543             "/",
544             "/foo/",
545             "/foo/bar",
546             "/bar",
547             "/baz",
548             "/baz",
549             "/",
550             "/bar",
551             "/bar/",
552             "/foo/bar",
553             null,
554             null
555         };
556 
557         assertEquals(src.length, dest.length, "Oops, test writer goofed");
558 
559         for (int i = 0; i < src.length; i++) {
560             assertEquals(
561                     dest[i], FileUtils.normalize(src[i]), "Check if '" + src[i] + "' normalized to '" + dest[i] + "'");
562         }
563     }
564 
565     @SuppressWarnings("deprecation")
566     @Test
567     void fileUtils() throws Exception {
568         // Loads file from classpath
569         final String path = "/test.txt";
570         final URL url = this.getClass().getResource(path);
571         assertNotNull(url, path + " was not found.");
572 
573         final String filename = Paths.get(url.toURI()).toString();
574         final String filename2 = "test2.txt";
575 
576         assertEquals("txt", FileUtils.getExtension(filename), "test.txt extension == \"txt\"");
577 
578         assertTrue(new File(filename).exists(), "Test file does exist: " + filename);
579 
580         assertFalse(new File(filename2).exists(), "Second test file does not exist");
581 
582         FileUtils.fileWrite(filename2, filename);
583         assertTrue(new File(filename2).exists(), "Second file was written");
584 
585         final String file2contents = FileUtils.fileRead(filename2);
586         assertEquals(FileUtils.fileRead(filename2), file2contents, "Second file's contents correct");
587 
588         FileUtils.fileAppend(filename2, filename);
589         assertEquals(FileUtils.fileRead(filename2), file2contents + file2contents, "Second file's contents correct");
590 
591         FileUtils.fileDelete(filename2);
592         assertFalse(new File(filename2).exists(), "Second test file does not exist");
593 
594         final String contents = FileUtils.fileRead(filename);
595         assertEquals("This is a test", contents, "FileUtils.fileRead()");
596     }
597 
598     @Test
599     void getExtension() {
600         final String[][] tests = {
601             {"filename.ext", "ext"},
602             {"README", ""},
603             {"domain.dot.com", "com"},
604             {"image.jpeg", "jpeg"},
605             {"folder" + File.separator + "image.jpeg", "jpeg"},
606             {"folder" + File.separator + "README", ""}
607         };
608 
609         for (String[] test : tests) {
610             assertEquals(test[1], FileUtils.getExtension(test[0]));
611             // assertEquals(tests[i][1], FileUtils.extension(tests[i][0]));
612         }
613     }
614 
615     @Test
616     void getExtensionWithPaths() {
617         // Since the utilities are based on the separator for the platform
618         // running the test, ensure we are using the right separator
619         final String sep = File.separator;
620         final String[][] testsWithPaths = {
621             {sep + "tmp" + sep + "foo" + sep + "filename.ext", "ext"},
622             {"C:" + sep + "temp" + sep + "foo" + sep + "filename.ext", "ext"},
623             {sep + "tmp" + sep + "foo.bar" + sep + "filename.ext", "ext"},
624             {"C:" + sep + "temp" + sep + "foo.bar" + sep + "filename.ext", "ext"},
625             {sep + "tmp" + sep + "foo.bar" + sep + "README", ""},
626             {"C:" + sep + "temp" + sep + "foo.bar" + sep + "README", ""},
627             {".." + sep + "filename.ext", "ext"},
628             {"blabla", ""}
629         };
630         for (String[] testsWithPath : testsWithPaths) {
631             assertEquals(testsWithPath[1], FileUtils.getExtension(testsWithPath[0]));
632             // assertEquals(testsWithPaths[i][1], FileUtils.extension(testsWithPaths[i][0]));
633         }
634     }
635 
636     @Test
637     void removeExtension() {
638         final String[][] tests = {
639             {"filename.ext", "filename"},
640             {"first.second.third.ext", "first.second.third"},
641             {"README", "README"},
642             {"domain.dot.com", "domain.dot"},
643             {"image.jpeg", "image"}
644         };
645 
646         for (String[] test : tests) {
647             assertEquals(test[1], FileUtils.removeExtension(test[0]));
648             // assertEquals(tests[i][1], FileUtils.basename(tests[i][0]));
649         }
650     }
651 
652     @Test
653     void removeExtensionWithPaths() {
654         // Since the utilities are based on the separator for the platform
655         // running the test, ensure we are using the right separator
656         final String sep = File.separator;
657         final String[][] testsWithPaths = {
658             {sep + "tmp" + sep + "foo" + sep + "filename.ext", sep + "tmp" + sep + "foo" + sep + "filename"},
659             {
660                 "C:" + sep + "temp" + sep + "foo" + sep + "filename.ext",
661                 "C:" + sep + "temp" + sep + "foo" + sep + "filename"
662             },
663             {sep + "tmp" + sep + "foo.bar" + sep + "filename.ext", sep + "tmp" + sep + "foo.bar" + sep + "filename"},
664             {
665                 "C:" + sep + "temp" + sep + "foo.bar" + sep + "filename.ext",
666                 "C:" + sep + "temp" + sep + "foo.bar" + sep + "filename"
667             },
668             {sep + "tmp" + sep + "foo.bar" + sep + "README", sep + "tmp" + sep + "foo.bar" + sep + "README"},
669             {
670                 "C:" + sep + "temp" + sep + "foo.bar" + sep + "README",
671                 "C:" + sep + "temp" + sep + "foo.bar" + sep + "README"
672             },
673             {".." + sep + "filename.ext", ".." + sep + "filename"}
674         };
675 
676         for (String[] testsWithPath : testsWithPaths) {
677             assertEquals(testsWithPath[1], FileUtils.removeExtension(testsWithPath[0]));
678             // assertEquals(testsWithPaths[i][1], FileUtils.basename(testsWithPaths[i][0]));
679         }
680     }
681 
682     @Test
683     void copyDirectoryStructureWithAEmptyDirectoryStructure() throws Exception {
684         File from = new File(getTestDirectory(), "from");
685 
686         FileUtils.deleteDirectory(from);
687 
688         assertTrue(from.mkdirs());
689 
690         File to = new File(getTestDirectory(), "to");
691 
692         assertTrue(to.mkdirs());
693 
694         FileUtils.copyDirectoryStructure(from, to);
695     }
696 
697     @Test
698     void copyDirectoryStructureWithAPopulatedStructure() throws Exception {
699         // Make a structure to copy
700         File from = new File(getTestDirectory(), "from");
701 
702         FileUtils.deleteDirectory(from);
703 
704         File fRoot = new File(from, "root.txt");
705 
706         File d1 = new File(from, "1");
707 
708         File d1_1 = new File(d1, "1_1");
709 
710         File d2 = new File(from, "2");
711 
712         File f2 = new File(d2, "2.txt");
713 
714         File d2_1 = new File(d2, "2_1");
715 
716         File f2_1 = new File(d2_1, "2_1.txt");
717 
718         assertTrue(from.mkdir());
719 
720         assertTrue(d1.mkdir());
721 
722         assertTrue(d1_1.mkdir());
723 
724         assertTrue(d2.mkdir());
725 
726         assertTrue(d2_1.mkdir());
727 
728         createFile(fRoot, 100);
729 
730         createFile(f2, 100);
731 
732         createFile(f2_1, 100);
733 
734         File to = new File(getTestDirectory(), "to");
735 
736         assertTrue(to.mkdirs());
737 
738         FileUtils.copyDirectoryStructure(from, to);
739 
740         checkFile(fRoot, new File(to, "root.txt"));
741 
742         assertIsDirectory(new File(to, "1"));
743 
744         assertIsDirectory(new File(to, "1/1_1"));
745 
746         assertIsDirectory(new File(to, "2"));
747 
748         assertIsDirectory(new File(to, "2/2_1"));
749 
750         checkFile(f2, new File(to, "2/2.txt"));
751 
752         checkFile(f2_1, new File(to, "2/2_1/2_1.txt"));
753     }
754 
755     @Test
756     void copyDirectoryStructureIfModified() throws Exception {
757         // Make a structure to copy
758         File from = new File(getTestDirectory(), "from");
759 
760         FileUtils.deleteDirectory(from);
761 
762         File fRoot = new File(from, "root.txt");
763 
764         File d1 = new File(from, "1");
765 
766         File d1_1 = new File(d1, "1_1");
767 
768         File d2 = new File(from, "2");
769 
770         File f2 = new File(d2, "2.txt");
771 
772         File d2_1 = new File(d2, "2_1");
773 
774         File f2_1 = new File(d2_1, "2_1.txt");
775 
776         assertTrue(from.mkdir());
777 
778         assertTrue(d1.mkdir());
779 
780         assertTrue(d1_1.mkdir());
781 
782         assertTrue(d2.mkdir());
783 
784         assertTrue(d2_1.mkdir());
785 
786         createFile(fRoot, 100);
787 
788         createFile(f2, 100);
789 
790         createFile(f2_1, 100);
791 
792         File to = new File(getTestDirectory(), "to");
793 
794         assertTrue(to.mkdirs());
795 
796         FileUtils.copyDirectoryStructureIfModified(from, to);
797 
798         File[] files = {new File(to, "root.txt"), new File(to, "2/2.txt"), new File(to, "2/2_1/2_1.txt")};
799 
800         long[] timestamps = {files[0].lastModified(), files[1].lastModified(), files[2].lastModified()};
801 
802         checkFile(fRoot, files[0]);
803 
804         assertIsDirectory(new File(to, "1"));
805 
806         assertIsDirectory(new File(to, "1/1_1"));
807 
808         assertIsDirectory(new File(to, "2"));
809 
810         assertIsDirectory(new File(to, "2/2_1"));
811 
812         checkFile(f2, files[1]);
813 
814         checkFile(f2_1, files[2]);
815 
816         FileUtils.copyDirectoryStructureIfModified(from, to);
817 
818         assertEquals(timestamps[0], files[0].lastModified(), "Unmodified file was overwritten");
819         assertEquals(timestamps[1], files[1].lastModified(), "Unmodified file was overwritten");
820         assertEquals(timestamps[2], files[2].lastModified(), "Unmodified file was overwritten");
821 
822         files[1].setLastModified(f2.lastModified() - 5000L);
823         timestamps[1] = files[1].lastModified();
824 
825         FileUtils.copyDirectoryStructureIfModified(from, to);
826 
827         assertEquals(timestamps[0], files[0].lastModified(), "Unmodified file was overwritten");
828         assertTrue(timestamps[1] < files[1].lastModified(), "Outdated file was not overwritten");
829         assertEquals(timestamps[2], files[2].lastModified(), "Unmodified file was overwritten");
830     }
831 
832     @Test
833     void copyDirectoryStructureToSelf() throws Exception {
834         // Make a structure to copy
835         File toFrom = new File(getTestDirectory(), "tofrom");
836 
837         FileUtils.deleteDirectory(toFrom);
838 
839         File fRoot = new File(toFrom, "root.txt");
840 
841         File dSub = new File(toFrom, "subdir");
842 
843         File f1 = new File(dSub, "notempty.txt");
844 
845         File dSubSub = new File(dSub, "subsubdir");
846 
847         File f2 = new File(dSubSub, "notemptytoo.txt");
848 
849         assertTrue(toFrom.mkdir());
850 
851         assertTrue(dSub.mkdir());
852 
853         assertTrue(dSubSub.mkdir());
854 
855         createFile(fRoot, 100);
856 
857         createFile(f1, 100);
858 
859         createFile(f2, 100);
860 
861         assertThrows(IOException.class, () -> FileUtils.copyDirectoryStructure(toFrom, toFrom));
862     }
863 
864     @Test
865     void filteredFileCopy() throws Exception {
866         File compareFile = new File(getTestDirectory(), "compare.txt");
867         FileUtils.fileWrite(compareFile.getAbsolutePath(), "UTF-8", "This is a test.  Test sample text\n");
868 
869         File destFile = new File(getTestDirectory(), "target.txt");
870 
871         final Properties filterProperties = new Properties();
872         filterProperties.setProperty("s", "sample text");
873 
874         // test ${token}
875         FileUtils.FilterWrapper[] wrappers1 = new FileUtils.FilterWrapper[] {
876             new FileUtils.FilterWrapper() {
877                 public Reader getReader(Reader reader) {
878                     return new InterpolationFilterReader(reader, filterProperties, "${", "}");
879                 }
880             }
881         };
882 
883         File srcFile = new File(getTestDirectory(), "root.txt");
884         FileUtils.fileWrite(srcFile.getAbsolutePath(), "UTF-8", "This is a test.  Test ${s}\n");
885 
886         FileUtils.copyFile(srcFile, destFile, "UTF-8", wrappers1);
887         assertTrue(FileUtils.contentEquals(compareFile, destFile), "Files should be equal.");
888 
889         srcFile.delete();
890         destFile.delete();
891         compareFile.delete();
892     }
893 
894     @Test
895     void filteredWithoutFilterAndOlderFile() throws Exception {
896         String content = "This is a test.";
897         File sourceFile = new File(getTestDirectory(), "source.txt");
898         FileUtils.fileWrite(sourceFile.getAbsolutePath(), "UTF-8", content);
899 
900         File destFile = new File(getTestDirectory(), "target.txt");
901         if (destFile.exists()) {
902             destFile.delete();
903         }
904         FileUtils.copyFile(sourceFile, destFile, null, null);
905         assertEqualContent(content.getBytes(StandardCharsets.UTF_8), destFile);
906 
907         String newercontent = "oldercontent";
908         File olderFile = new File(getTestDirectory(), "oldersource.txt");
909 
910         FileUtils.fileWrite(olderFile.getAbsolutePath(), "UTF-8", newercontent);
911 
912         // very old file ;-)
913         olderFile.setLastModified(1);
914         destFile = new File(getTestDirectory(), "target.txt");
915         FileUtils.copyFile(olderFile, destFile, null, null);
916         String destFileContent = FileUtils.fileRead(destFile, "UTF-8");
917         assertEquals(content, destFileContent);
918     }
919 
920     @Test
921     void filteredWithoutFilterAndOlderFileAndOverwrite() throws Exception {
922         String content = "This is a test.";
923         File sourceFile = new File(getTestDirectory(), "source.txt");
924         FileUtils.fileWrite(sourceFile.getAbsolutePath(), "UTF-8", content);
925 
926         File destFile = new File(getTestDirectory(), "target.txt");
927         if (destFile.exists()) {
928             destFile.delete();
929         }
930         FileUtils.copyFile(sourceFile, destFile, null, null);
931         assertEqualContent(content.getBytes(StandardCharsets.UTF_8), destFile);
932 
933         String newercontent = "oldercontent";
934         File olderFile = new File(getTestDirectory(), "oldersource.txt");
935 
936         FileUtils.fileWrite(olderFile.getAbsolutePath(), "UTF-8", newercontent);
937 
938         // very old file ;-)
939         olderFile.setLastModified(1);
940         destFile = new File(getTestDirectory(), "target.txt");
941         FileUtils.copyFile(olderFile, destFile, null, null, true);
942         String destFileContent = FileUtils.fileRead(destFile, "UTF-8");
943         assertEquals(newercontent, destFileContent);
944     }
945 
946     @Test
947     void fileRead() throws Exception {
948         File testFile = new File(getTestDirectory(), "testFileRead.txt");
949         String testFileName = testFile.getAbsolutePath();
950         /*
951          * NOTE: The method under test uses the JVM's default encoding which by its nature varies from machine to
952          * machine. As a consequence, we cannot know in advance which characters are supported by the effective encoding
953          * of the test runner. Therefore this test must be restricted to ASCII characters which are reasonably safe to
954          * survive the roundtrip test.
955          */
956         String testString = "Only US-ASCII characters here, see comment above!";
957         try (Writer writer = new OutputStreamWriter(Files.newOutputStream(testFile.toPath()))) {
958             writer.write(testString);
959             writer.flush();
960         }
961         assertEquals(testString, FileUtils.fileRead(testFile), "testString should be equal");
962         assertEquals(testString, FileUtils.fileRead(testFileName), "testString should be equal");
963         testFile.delete();
964     }
965 
966     @Test
967     void fileReadWithEncoding() throws Exception {
968         String encoding = "UTF-8";
969         File testFile = new File(getTestDirectory(), "testFileRead.txt");
970         String testFileName = testFile.getAbsolutePath();
971         // unicode escaped Japanese hiragana, "aiueo" + Umlaut a
972         String testString = "あいうえおä";
973         try (Writer writer = new OutputStreamWriter(Files.newOutputStream(testFile.toPath()), encoding)) {
974             writer.write(testString);
975             writer.flush();
976         }
977         assertEquals(testString, FileUtils.fileRead(testFile, "UTF-8"), "testString should be equal");
978         assertEquals(testString, FileUtils.fileRead(testFileName, "UTF-8"), "testString should be equal");
979         testFile.delete();
980     }
981 
982     @SuppressWarnings("deprecation")
983     @Test
984     void fileAppend() throws Exception {
985         String baseString = "abc";
986         File testFile = new File(getTestDirectory(), "testFileAppend.txt");
987         String testFileName = testFile.getAbsolutePath();
988         try (Writer writer = new OutputStreamWriter(Files.newOutputStream(testFile.toPath()))) {
989             writer.write(baseString);
990             writer.flush();
991         }
992         // unicode escaped Japanese hiragana, "aiueo" + Umlaut a
993         String testString = "あいうえおä";
994         FileUtils.fileAppend(testFileName, testString);
995         assertEqualContent((baseString + testString).getBytes(), testFile);
996         testFile.delete();
997     }
998 
999     @SuppressWarnings("deprecation")
1000     @Test
1001     void fileAppendWithEncoding() throws Exception {
1002         String baseString = "abc";
1003         String encoding = "UTF-8";
1004         File testFile = new File(getTestDirectory(), "testFileAppend.txt");
1005         String testFileName = testFile.getAbsolutePath();
1006         try (Writer writer = new OutputStreamWriter(Files.newOutputStream(testFile.toPath()), encoding)) {
1007             writer.write(baseString);
1008             writer.flush();
1009         }
1010         // unicode escaped Japanese hiragana, "aiueo" + Umlaut a
1011         String testString = "あいうえおä";
1012         FileUtils.fileAppend(testFileName, encoding, testString);
1013         assertEqualContent((baseString + testString).getBytes(encoding), testFile);
1014         testFile.delete();
1015     }
1016 
1017     @Test
1018     void fileWrite() throws Exception {
1019         File testFile = new File(getTestDirectory(), "testFileWrite.txt");
1020         String testFileName = testFile.getAbsolutePath();
1021         // unicode escaped Japanese hiragana, "aiueo" + Umlaut a
1022         String testString = "あいうえおä";
1023         FileUtils.fileWrite(testFileName, testString);
1024         assertEqualContent(testString.getBytes(), testFile);
1025         testFile.delete();
1026     }
1027 
1028     @Test
1029     void fileWriteWithEncoding() throws Exception {
1030         String encoding = "UTF-8";
1031         File testFile = new File(getTestDirectory(), "testFileWrite.txt");
1032         String testFileName = testFile.getAbsolutePath();
1033         // unicode escaped Japanese hiragana, "aiueo" + Umlaut a
1034         String testString = "あいうえおä";
1035         FileUtils.fileWrite(testFileName, encoding, testString);
1036         assertEqualContent(testString.getBytes(encoding), testFile);
1037         testFile.delete();
1038     }
1039 
1040     /**
1041      * Workaround for the following Sun bugs. They are fixed in JDK 6u1 and JDK 5u11.
1042      *
1043      * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4403166">Sun bug id=4403166</a>
1044      * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6182812">Sun bug id=6182812</a>
1045      * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6481955">Sun bug id=6481955</a>
1046      */
1047     @Test
1048     @EnabledOnOs(OS.WINDOWS)
1049     void deleteLongPathOnWindows() throws Exception {
1050         File a = new File(getTestDirectory(), "longpath");
1051         a.mkdir();
1052         File a1 = new File(a, "a");
1053         a1.mkdir();
1054 
1055         StringBuilder path = new StringBuilder();
1056         for (int i = 0; i < 100; i++) {
1057             path.append("../a/");
1058         }
1059 
1060         File f = new File(a1, path + "test.txt");
1061 
1062         try (InputStream is = new ByteArrayInputStream("Blabla".getBytes(StandardCharsets.UTF_8));
1063                 OutputStream os = Files.newOutputStream(f.getCanonicalFile().toPath())) {
1064             IOUtil.copy(is, os);
1065         }
1066 
1067         FileUtils.forceDelete(f);
1068 
1069         File f1 = new File(a1, "test.txt");
1070         if (f1.exists()) {
1071             throw new Exception("Unable to delete the file :" + f1.getAbsolutePath());
1072         }
1073     }
1074 
1075     @SuppressWarnings("deprecation")
1076     @Test
1077     void copyFileOnSameFile() throws Exception {
1078         String content = "ggrgreeeeeeeeeeeeeeeeeeeeeeeoierjgioejrgiojregioejrgufcdxivbsdibgfizgerfyaezgv!zeez";
1079         final File theFile = File.createTempFile("test", ".txt");
1080         theFile.deleteOnExit();
1081         FileUtils.fileAppend(theFile.getAbsolutePath(), content);
1082 
1083         assertTrue(theFile.length() > 0);
1084         // Now copy file over itself
1085         FileUtils.copyFile(theFile, theFile);
1086 
1087         // This should not fail
1088         assertTrue(theFile.length() > 0);
1089     }
1090 
1091     @Test
1092     void extensions() {
1093 
1094         String[][] values = {
1095             {"fry.frozen", "frozen"},
1096             {"fry", ""},
1097             {"fry.", ""},
1098             {"/turanga/leela/meets.fry", "fry"},
1099             {"/3000/turanga.leela.fry/zoidberg.helps", "helps"},
1100             {"/3000/turanga.leela.fry/zoidberg.", ""},
1101             {"/3000/turanga.leela.fry/zoidberg", ""},
1102             {"/3000/leela.fry.bender/", ""},
1103             {"/3000/leela.fry.bdner/.", ""},
1104             {"/3000/leela.fry.bdner/foo.bar.txt", "txt"}
1105         };
1106 
1107         for (int i = 0; i < values.length; i++) {
1108             String fileName = values[i][0].replace('/', File.separatorChar);
1109             String ext = values[i][1];
1110             String computed = FileUtils.extension(fileName);
1111             assertEquals(ext, computed, "case [" + i + "]:" + fileName + " -> " + ext + ", computed : " + computed);
1112         }
1113     }
1114 
1115     @Test
1116     void isValidWindowsFileName() {
1117         File f = new File("c:\test");
1118         assertTrue(FileUtils.isValidWindowsFileName(f));
1119 
1120         if (Os.isFamily(Os.FAMILY_WINDOWS)) {
1121             f = new File("c:\test\bla:bla");
1122             assertFalse(FileUtils.isValidWindowsFileName(f));
1123             f = new File("c:\test\bla*bla");
1124             assertFalse(FileUtils.isValidWindowsFileName(f));
1125             f = new File("c:\test\bla\"bla");
1126             assertFalse(FileUtils.isValidWindowsFileName(f));
1127             f = new File("c:\test\bla<bla");
1128             assertFalse(FileUtils.isValidWindowsFileName(f));
1129             f = new File("c:\test\bla>bla");
1130             assertFalse(FileUtils.isValidWindowsFileName(f));
1131             f = new File("c:\test\bla|bla");
1132             assertFalse(FileUtils.isValidWindowsFileName(f));
1133             f = new File("c:\test\bla*bla");
1134             assertFalse(FileUtils.isValidWindowsFileName(f));
1135         }
1136     }
1137 
1138     @Test
1139     void deleteDirectoryWithValidFileSymlink() throws Exception {
1140         File symlinkTarget = new File(getTestDirectory(), "fileSymlinkTarget");
1141         createFile(symlinkTarget, 1);
1142         File symlink = new File(getTestDirectory(), "fileSymlink");
1143         createSymlink(symlink, symlinkTarget);
1144         try {
1145             FileUtils.deleteDirectory(getTestDirectory());
1146         } finally {
1147             /*
1148              * Ensure to cleanup problematic symlink or "mvn clean" will fail
1149              */
1150             symlink.delete();
1151         }
1152         assertFalse(getTestDirectory().exists(), "Failed to delete test directory");
1153     }
1154 
1155     @Test
1156     void deleteDirectoryWithValidDirSymlink() throws Exception {
1157         File symlinkTarget = new File(getTestDirectory(), "dirSymlinkTarget");
1158         symlinkTarget.mkdir();
1159         File symlink = new File(getTestDirectory(), "dirSymlink");
1160         createSymlink(symlink, symlinkTarget);
1161         try {
1162             FileUtils.deleteDirectory(getTestDirectory());
1163         } finally {
1164             /*
1165              * Ensure to cleanup problematic symlink or "mvn clean" will fail
1166              */
1167             symlink.delete();
1168         }
1169         assertFalse(getTestDirectory().exists(), "Failed to delete test directory");
1170     }
1171 
1172     @Test
1173     void deleteDirectoryWithDanglingSymlink() throws Exception {
1174         File symlinkTarget = new File(getTestDirectory(), "missingSymlinkTarget");
1175         File symlink = new File(getTestDirectory(), "danglingSymlink");
1176         createSymlink(symlink, symlinkTarget);
1177         try {
1178             FileUtils.deleteDirectory(getTestDirectory());
1179         } finally {
1180             /*
1181              * Ensure to cleanup problematic symlink or "mvn clean" will fail
1182              */
1183             symlink.delete();
1184         }
1185         assertFalse(getTestDirectory().exists(), "Failed to delete test directory");
1186     }
1187 
1188     @Test
1189     void testcopyDirectoryLayoutWithExcludesIncludes() throws Exception {
1190         File destination = new File("target", "copyDirectoryStructureWithExcludesIncludes");
1191         if (!destination.exists()) {
1192             destination.mkdirs();
1193         }
1194         FileUtils.cleanDirectory(destination);
1195 
1196         File source = new File("src/test/resources/dir-layout-copy");
1197 
1198         FileUtils.copyDirectoryLayout(source, destination, null, null);
1199 
1200         assertTrue(destination.exists());
1201 
1202         File[] childs = destination.listFiles();
1203         assertNotNull(childs);
1204         assertEquals(2, childs.length);
1205 
1206         for (File current : childs) {
1207             if (current.getName().endsWith("empty-dir") || current.getName().endsWith("dir1")) {
1208                 if (current.getName().endsWith("dir1")) {
1209                     File[] listFiles = current.listFiles();
1210                     assertNotNull(listFiles);
1211                     assertEquals(1, listFiles.length);
1212                     assertTrue(listFiles[0].getName().endsWith("dir2"));
1213                 }
1214             } else {
1215                 fail("not empty-dir or dir1");
1216             }
1217         }
1218     }
1219 
1220     /**
1221      * Be sure that {@link org.codehaus.plexus.util.FileUtils#createTempFile(String, String, File)} is always unique.
1222      */
1223     @Test
1224     void createTempFile() {
1225         File last = FileUtils.createTempFile("unique", ".tmp", null);
1226         for (int i = 0; i < 10; i++) {
1227             File current = FileUtils.createTempFile("unique", ".tmp", null);
1228             assertNotEquals(current.getName(), last.getName(), "No unique name: " + current.getName());
1229             last = current;
1230         }
1231     }
1232 
1233     /**
1234      * Because windows(tm) quite frequently sleeps less than the advertised time
1235      *
1236      * @param time The amount of time to sleep
1237      */
1238     private void reallySleep(int time) throws InterruptedException {
1239         long until = System.currentTimeMillis() + time;
1240         Thread.sleep(time);
1241         while (System.currentTimeMillis() < until) {
1242             Thread.sleep(time / 10);
1243             Thread.yield();
1244         }
1245     }
1246 }