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