1 package org.apache.maven.shared.utils.io;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.shared.utils.testhelpers.FileTestHelper;
23 import org.junit.Assert;
24 import org.junit.Ignore;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.junit.rules.TemporaryFolder;
28
29 import java.io.File;
30 import java.io.IOException;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.List;
34
35 import static org.junit.Assert.assertEquals;
36 import static org.junit.Assert.assertTrue;
37
38 public class DirectoryScannerTest
39 {
40 private static final String[] NONE = new String[0];
41
42 @Rule
43 public TemporaryFolder tempFolder = new TemporaryFolder();
44
45 private void createTestData()
46 throws IOException
47 {
48 File rootDir = tempFolder.getRoot();
49 File folder1 = new File( rootDir, "folder1" );
50 folder1.mkdirs();
51
52 FileTestHelper.generateTestFile( new File( rootDir, "file1.txt" ), 11 );
53 FileTestHelper.generateTestFile( new File( rootDir, "file2.txt" ), 12 );
54 FileTestHelper.generateTestFile( new File( rootDir, "file3.dat" ), 13 );
55
56 FileTestHelper.generateTestFile( new File( folder1, "file4.txt" ), 14 );
57 FileTestHelper.generateTestFile( new File( folder1, "file5.dat" ), 15 );
58
59 File folder2 = new File( folder1, "ignorefolder" );
60 folder2.mkdirs();
61 FileTestHelper.generateTestFile( new File( folder2, "file7.txt" ), 17 );
62 }
63
64 @Test
65 public void testSimpleScan()
66 throws Exception
67 {
68 createTestData();
69
70 fitScanTest( true, true, true,
71 null,
72 null,
73
74 new String[]{ "file1.txt", "file2.txt", "file3.dat", "folder1/file4.txt", "folder1/file5.dat" },
75 new String[]{ "", "folder1" },
76 NONE,
77 NONE,
78 NONE,
79 NONE );
80
81
82 fitScanTest( true, false, true,
83 null,
84 null,
85
86 new String[]{ "file1.txt", "file2.txt", "file3.dat", "folder1/file4.txt", "folder1/file5.dat" },
87 new String[]{ "", "folder1" },
88 NONE,
89 NONE,
90 NONE,
91 NONE );
92 }
93
94 @Test
95 public void testSimpleIncludes()
96 throws Exception
97 {
98 createTestData();
99
100 fitScanTest( true, true, true,
101 new String[]{ "**/*.dat", "*.somethingelse" },
102 null,
103 new String[]{ "file3.dat", "folder1/file5.dat" },
104 NONE,
105 new String[]{ "file1.txt", "file2.txt", "folder1/file4.txt" },
106 new String[]{ "", "folder1" },
107 NONE,
108 NONE );
109
110
111 fitScanTest( true, false, true,
112 new String[]{ "**/*.dat", "*.somethingelse" },
113 null,
114 new String[]{ "file3.dat", "folder1/file5.dat" },
115 NONE,
116 new String[]{ "file1.txt", "file2.txt", "folder1/file4.txt" },
117 new String[]{ "", "folder1" },
118 NONE,
119 NONE );
120 }
121
122 @Test
123 public void checkSymlinkBehaviour(){
124 DirectoryScanner ds = new DirectoryScanner();
125 ds.setBasedir( new File("src/test/resources/symlinks/src") );
126 ds.setFollowSymlinks( false );
127 ds.scan();
128 String[] includedDirectories = ds.getIncludedDirectories();
129 String[] files = ds.getIncludedFiles();
130 System.out.println( "files = " + files );
131
132
133 }
134
135 @Test
136 @Ignore("Wait until we can run with assembly 2.5 which will support symlinks properly")
137 public void followSymlinksFalse()
138 {
139 if (!Java7Support.isAtLeastJava7()) return;
140 DirectoryScanner ds = new DirectoryScanner();
141 ds.setBasedir( new File( "src/test/resources/symlinks/src/" ) );
142 ds.setFollowSymlinks( false );
143 ds.scan();
144 List<String> included = Arrays.asList( ds.getIncludedFiles() );
145 assertAlwaysIncluded( included );
146 assertEquals( 9, included.size() );
147 List<String> includedDirs = Arrays.asList( ds.getIncludedDirectories() );
148 assertTrue( includedDirs.contains( "" ) );
149 assertTrue( includedDirs.contains( "aRegularDir" ) );
150 assertTrue( includedDirs.contains( "symDir" ) );
151 assertTrue( includedDirs.contains( "symLinkToDirOnTheOutside" ) );
152 assertTrue( includedDirs.contains( "targetDir" ) );
153 assertEquals( 5, includedDirs.size() );
154 }
155
156 private void assertAlwaysIncluded( List<String> included )
157 {
158 assertTrue( included.contains( "aRegularDir/aRegularFile.txt" ) );
159 assertTrue( included.contains( "targetDir/targetFile.txt" ) );
160 assertTrue( included.contains( "fileR.txt" ) );
161 assertTrue( included.contains( "fileW.txt" ) );
162 assertTrue( included.contains( "fileX.txt" ) );
163 assertTrue( included.contains( "symR" ) );
164 assertTrue( included.contains( "symW" ) );
165 assertTrue( included.contains( "symX" ) );
166 assertTrue( included.contains( "symLinkToFileOnTheOutside" ) );
167 }
168
169 @Test
170 public void followSymlinks()
171 {
172 if (!Java7Support.isAtLeastJava7()) return;
173 DirectoryScanner ds = new DirectoryScanner();
174 ds.setBasedir( new File( "src/test/resources/symlinks/src/" ) );
175 ds.setFollowSymlinks( true );
176 ds.scan();
177 List<String> included = Arrays.asList( ds.getIncludedFiles() );
178 assertAlwaysIncluded( included );
179 assertTrue( included.contains( "symDir/targetFile.txt" ) );
180 assertTrue( included.contains( "symLinkToDirOnTheOutside/FileInDirOnTheOutside.txt" ) );
181 assertEquals( 11, included.size() );
182
183 List<String> includedDirs = Arrays.asList( ds.getIncludedDirectories() );
184 assertTrue( includedDirs.contains( "" ) );
185 assertTrue( includedDirs.contains( "aRegularDir" ) );
186 assertTrue( includedDirs.contains( "symDir" ) );
187 assertTrue( includedDirs.contains( "symLinkToDirOnTheOutside" ) );
188 assertTrue( includedDirs.contains( "targetDir" ) );
189 assertEquals( 5, includedDirs.size() );
190 }
191
192 @Test
193 public void testSimpleExcludes()
194 throws Exception
195 {
196 createTestData();
197
198 fitScanTest( true, true, true,
199 null,
200 new String[]{ "**/*.dat", "*.somethingelse" },
201 new String[]{ "file1.txt", "file2.txt", "folder1/file4.txt" },
202 new String[]{ "", "folder1" },
203 NONE,
204 NONE,
205 new String[]{ "file3.dat", "folder1/file5.dat" },
206 NONE );
207
208
209 fitScanTest( true, false, true,
210 null,
211 new String[]{ "**/*.dat", "*.somethingelse" },
212 new String[]{ "file1.txt", "file2.txt", "folder1/file4.txt" },
213 new String[]{ "", "folder1" },
214 NONE,
215 NONE,
216 new String[]{ "file3.dat", "folder1/file5.dat" },
217 NONE );
218 }
219
220 public void testIsSymLin()
221 throws IOException
222 {
223 File file = new File( "." );
224 DirectoryScanner ds = new DirectoryScanner();
225 ds.isSymbolicLink( file, "abc" );
226 }
227
228
229
230
231 private void fitScanTest( boolean caseSensitive, boolean followSymLinks, boolean addDefaultExcludes,
232 String[] includes, String[] excludes, String[] expectedIncludedFiles,
233 String[] expectedIncludedDirectories, String[] expectedNotIncludedFiles,
234 String[] expectedNotIncludedDirectories, String[] expectedExcludedFiles,
235 String[] expectedExcludedDirectories )
236 {
237 DirectoryScanner ds = new DirectoryScanner();
238 ds.setBasedir( tempFolder.getRoot() );
239
240 ds.setCaseSensitive( caseSensitive );
241 ds.setFollowSymlinks( followSymLinks );
242
243 if ( addDefaultExcludes )
244 {
245 ds.addDefaultExcludes();
246 }
247 if ( includes != null )
248 {
249 ds.setIncludes( includes );
250 }
251 if ( excludes != null )
252 {
253 ds.setExcludes( excludes );
254 }
255
256 TestScanConductor scanConductor = new TestScanConductor();
257
258 ds.setScanConductor( scanConductor );
259
260 ds.scan();
261
262 checkFiles( "expectedIncludedFiles", expectedIncludedFiles, ds.getIncludedFiles() );
263 checkFiles( "expectedIncludedDirectories", expectedIncludedDirectories, ds.getIncludedDirectories() );
264 checkFiles( "expectedNotIncludedFiles", expectedNotIncludedFiles, ds.getNotIncludedFiles() );
265 checkFiles( "expectedNotIncludedDirectories", expectedNotIncludedDirectories, ds.getNotIncludedDirectories() );
266 checkFiles( "expectedExcludedFiles", expectedExcludedFiles, ds.getExcludedFiles() );
267 checkFiles( "expectedExcludedDirectories", expectedExcludedDirectories, ds.getExcludedDirectories() );
268
269 checkFiles( "visitedFiles", expectedIncludedFiles,
270 scanConductor.visitedFiles.toArray( new String[scanConductor.visitedFiles.size()] ) );
271 }
272
273
274
275
276
277
278
279 private void checkFiles( String category, String[] expectedFiles, String[] resolvedFiles )
280 {
281 if ( expectedFiles != null )
282 {
283 String msg = category + " expected: " + Arrays.toString( expectedFiles ) + " but got: " + Arrays.toString(
284 resolvedFiles );
285 Assert.assertNotNull( msg, resolvedFiles );
286 assertEquals( msg, expectedFiles.length, resolvedFiles.length );
287
288 Arrays.sort( expectedFiles );
289 Arrays.sort( resolvedFiles );
290
291 for ( int i = 0; i < resolvedFiles.length; i++ )
292 {
293 assertEquals( msg, expectedFiles[i], resolvedFiles[i].replace( "\\", "/" ) );
294 }
295 }
296 }
297
298 private static class TestScanConductor
299 implements ScanConductor
300 {
301 final List<String> visitedFiles = new ArrayList<String>();
302
303 public ScanConductor.ScanAction visitDirectory( String name, File directory )
304 {
305 assertTrue( directory.isDirectory() );
306
307 if ( directory.getName().equals( "ignorefolder" ) )
308 {
309 return ScanAction.NO_RECURSE;
310 }
311
312 return ScanAction.CONTINUE;
313 }
314
315 public ScanConductor.ScanAction visitFile( String name, File file )
316 {
317 assertTrue( file.isFile() );
318 visitedFiles.add( name );
319 return ScanAction.CONTINUE;
320 }
321 }
322
323 private void removeAndAddSomeFiles()
324 throws IOException
325 {
326 File rootDir = tempFolder.getRoot();
327 File file2 = new File( rootDir, "file2.txt" );
328 file2.delete();
329
330 FileTestHelper.generateTestFile( new File( rootDir, "folder1/file9.txt" ), 15 );
331
332 File folder2 = new File( rootDir, "folder1/ignorefolder" );
333 FileUtils.deleteDirectory( folder2 );
334 }
335
336 @Test
337 public void testScanDiff()
338 throws Exception
339 {
340 createTestData();
341
342 DirectoryScanner dss = new DirectoryScanner();
343 dss.setBasedir( tempFolder.getRoot() );
344 Assert.assertNotNull( dss );
345
346
347 dss.scan();
348 String[] oldFiles = dss.getIncludedFiles();
349
350
351 removeAndAddSomeFiles();
352
353 dss.scan();
354
355 DirectoryScanResult dsr = dss.diffIncludedFiles( oldFiles );
356
357 String[] addedFiles = dsr.getFilesAdded();
358 String[] removedFiles = dsr.getFilesRemoved();
359 Assert.assertNotNull( addedFiles );
360 Assert.assertNotNull( removedFiles );
361 assertEquals( 1, addedFiles.length );
362 assertEquals( 2, removedFiles.length );
363 }
364
365 @Ignore( "Enable this test to run performance checks" ) @Test
366 public void performanceTest()
367 throws Exception
368 {
369
370 File rootFolder = tempFolder.getRoot();
371
372
373 for ( int i = 1; i < 200; i++ )
374 {
375 createTestData();
376 removeAndAddSomeFiles();
377 FileUtils.deleteDirectory( rootFolder );
378 }
379
380 int cycles = 2000;
381
382
383 long startTime = System.nanoTime();
384 for ( int i = 1; i < cycles; i++ )
385 {
386 createTestData();
387 removeAndAddSomeFiles();
388 FileUtils.deleteDirectory( rootFolder );
389 rootFolder.mkdir();
390 }
391 long endTime = System.nanoTime();
392
393 long durationEmptyRun = endTime - startTime;
394 System.out.println( "durationEmptyRun [ns]: " + durationEmptyRun );
395
396 startTime = System.nanoTime();
397 for ( int i = 1; i < cycles; i++ )
398 {
399 createTestData();
400 DirectoryScanner directoryScanner = new DirectoryScanner();
401 directoryScanner.setBasedir( rootFolder );
402 directoryScanner.scan();
403 String[] oldFiles = directoryScanner.getIncludedFiles();
404
405 removeAndAddSomeFiles();
406
407 directoryScanner.scan();
408
409 DirectoryScanResult directoryScanResult = directoryScanner.diffIncludedFiles( oldFiles );
410 Assert.assertNotNull( directoryScanResult );
411
412 FileUtils.deleteDirectory( rootFolder );
413 rootFolder.mkdir();
414 }
415 endTime = System.nanoTime();
416
417 long durationWithSnapshotScanner = endTime - startTime;
418 System.out.println( "durationWithSnapshotScanner [ns]: " + durationWithSnapshotScanner );
419
420 long dirScannerOverhead = durationWithSnapshotScanner - durationEmptyRun;
421
422 System.out.println( "Overhead for n cycles [ns]: " + dirScannerOverhead );
423 }
424
425 }