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