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 System.out.println( "files = " + files );
135
136
137 }
138
139 @Test
140 public void followSymlinksFalse()
141 throws IOException
142 {
143 assumeFalse( Os.isFamily( Os.FAMILY_WINDOWS ) );
144 assumeTrue( Java7Support.isAtLeastJava7() );
145
146 File testDir = SymlinkTestSetup.createStandardSymlinkTestDir( new File( "target/test/symlinkTestCase" ) );
147
148 DirectoryScanner ds = new DirectoryScanner();
149 ds.setBasedir( testDir );
150 ds.setFollowSymlinks( false );
151 ds.scan();
152 List<String> included = Arrays.asList( ds.getIncludedFiles() );
153 assertAlwaysIncluded( included );
154 assertEquals( 9, included.size() );
155 List<String> includedDirs = Arrays.asList( ds.getIncludedDirectories() );
156 assertTrue( includedDirs.contains( "" ) );
157 assertTrue( includedDirs.contains( "aRegularDir" ) );
158 assertTrue( includedDirs.contains( "symDir" ) );
159 assertTrue( includedDirs.contains( "symLinkToDirOnTheOutside" ) );
160 assertTrue( includedDirs.contains( "targetDir" ) );
161 assertEquals( 5, includedDirs.size() );
162 }
163
164 private void assertAlwaysIncluded( List<String> included )
165 {
166 assertTrue( included.contains( "aRegularDir/aRegularFile.txt" ) );
167 assertTrue( included.contains( "targetDir/targetFile.txt" ) );
168 assertTrue( included.contains( "fileR.txt" ) );
169 assertTrue( included.contains( "fileW.txt" ) );
170 assertTrue( included.contains( "fileX.txt" ) );
171 assertTrue( included.contains( "symR" ) );
172 assertTrue( included.contains( "symW" ) );
173 assertTrue( included.contains( "symX" ) );
174 assertTrue( included.contains( "symLinkToFileOnTheOutside" ) );
175 }
176
177 @Test
178 public void followSymlinks()
179 throws IOException
180 {
181 assumeFalse( Os.isFamily( Os.FAMILY_WINDOWS ) );
182 assumeTrue( Java7Support.isAtLeastJava7() );
183
184 DirectoryScanner ds = new DirectoryScanner();
185 File testDir = SymlinkTestSetup.createStandardSymlinkTestDir( new File( "target/test/symlinkTestCase" ) );
186
187 ds.setBasedir( testDir );
188 ds.setFollowSymlinks( true );
189 ds.scan();
190 List<String> included = Arrays.asList( ds.getIncludedFiles() );
191 assertAlwaysIncluded( included );
192 assertTrue( included.contains( "symDir/targetFile.txt" ) );
193 assertTrue( included.contains( "symLinkToDirOnTheOutside/FileInDirOnTheOutside.txt" ) );
194 assertEquals( 11, included.size() );
195
196 List<String> includedDirs = Arrays.asList( ds.getIncludedDirectories() );
197 assertTrue( includedDirs.contains( "" ) );
198 assertTrue( includedDirs.contains( "aRegularDir" ) );
199 assertTrue( includedDirs.contains( "symDir" ) );
200 assertTrue( includedDirs.contains( "symLinkToDirOnTheOutside" ) );
201 assertTrue( includedDirs.contains( "targetDir" ) );
202 assertEquals( 5, includedDirs.size() );
203 }
204
205
206
207
208
209 @Test
210 public void testSimpleExcludes()
211 throws Exception
212 {
213 createTestData();
214
215 fitScanTest( true, true, true,
216 null,
217 new String[]{ "**/*.dat", "*.somethingelse" },
218 new String[]{ "file1.txt", "file2.txt", "folder1/file4.txt" },
219 new String[]{ "", "folder1" },
220 NONE,
221 NONE,
222 new String[]{ "file3.dat", "folder1/file5.dat" },
223 NONE );
224
225
226 fitScanTest( true, false, true,
227 null,
228 new String[]{ "**/*.dat", "*.somethingelse" },
229 new String[]{ "file1.txt", "file2.txt", "folder1/file4.txt" },
230 new String[]{ "", "folder1" },
231 NONE,
232 NONE,
233 new String[]{ "file3.dat", "folder1/file5.dat" },
234 NONE );
235 }
236
237 public void testIsSymLin()
238 throws IOException
239 {
240 File file = new File( "." );
241 DirectoryScanner ds = new DirectoryScanner();
242 ds.isSymbolicLink( file, "abc" );
243 }
244
245
246
247
248 private void fitScanTest( boolean caseSensitive, boolean followSymLinks, boolean addDefaultExcludes,
249 String[] includes, String[] excludes, String[] expectedIncludedFiles,
250 String[] expectedIncludedDirectories, String[] expectedNotIncludedFiles,
251 String[] expectedNotIncludedDirectories, String[] expectedExcludedFiles,
252 String[] expectedExcludedDirectories )
253 {
254 DirectoryScanner ds = new DirectoryScanner();
255 ds.setBasedir( tempFolder.getRoot() );
256
257 ds.setCaseSensitive( caseSensitive );
258 ds.setFollowSymlinks( followSymLinks );
259
260 if ( addDefaultExcludes )
261 {
262 ds.addDefaultExcludes();
263 }
264 if ( includes != null )
265 {
266 ds.setIncludes( includes );
267 }
268 if ( excludes != null )
269 {
270 ds.setExcludes( excludes );
271 }
272
273 TestScanConductor scanConductor = new TestScanConductor();
274
275 ds.setScanConductor( scanConductor );
276
277 ds.scan();
278
279 checkFiles( "expectedIncludedFiles", expectedIncludedFiles, ds.getIncludedFiles() );
280 checkFiles( "expectedIncludedDirectories", expectedIncludedDirectories, ds.getIncludedDirectories() );
281 checkFiles( "expectedNotIncludedFiles", expectedNotIncludedFiles, ds.getNotIncludedFiles() );
282 checkFiles( "expectedNotIncludedDirectories", expectedNotIncludedDirectories, ds.getNotIncludedDirectories() );
283 checkFiles( "expectedExcludedFiles", expectedExcludedFiles, ds.getExcludedFiles() );
284 checkFiles( "expectedExcludedDirectories", expectedExcludedDirectories, ds.getExcludedDirectories() );
285
286 checkFiles( "visitedFiles", expectedIncludedFiles,
287 scanConductor.visitedFiles.toArray( new String[scanConductor.visitedFiles.size()] ) );
288 }
289
290
291
292
293
294
295
296 private void checkFiles( String category, String[] expectedFiles, String[] resolvedFiles )
297 {
298 if ( expectedFiles != null )
299 {
300 String msg = category + " expected: " + Arrays.toString( expectedFiles ) + " but got: " + Arrays.toString(
301 resolvedFiles );
302 Assert.assertNotNull( msg, resolvedFiles );
303 assertEquals( msg, expectedFiles.length, resolvedFiles.length );
304
305 Arrays.sort( expectedFiles );
306 Arrays.sort( resolvedFiles );
307
308 for ( int i = 0; i < resolvedFiles.length; i++ )
309 {
310 assertEquals( msg, expectedFiles[i], resolvedFiles[i].replace( "\\", "/" ) );
311 }
312 }
313 }
314
315 private static class TestScanConductor
316 implements ScanConductor
317 {
318 final List<String> visitedFiles = new ArrayList<String>();
319
320 public ScanConductor.ScanAction visitDirectory( String name, File directory )
321 {
322 assertTrue( directory.isDirectory() );
323
324 if ( directory.getName().equals( "ignorefolder" ) )
325 {
326 return ScanAction.NO_RECURSE;
327 }
328
329 return ScanAction.CONTINUE;
330 }
331
332 public ScanConductor.ScanAction visitFile( String name, File file )
333 {
334 assertTrue( file.isFile() );
335 visitedFiles.add( name );
336 return ScanAction.CONTINUE;
337 }
338 }
339
340 private void removeAndAddSomeFiles()
341 throws IOException
342 {
343 File rootDir = tempFolder.getRoot();
344 File file2 = new File( rootDir, "file2.txt" );
345 file2.delete();
346
347 FileTestHelper.generateTestFile( new File( rootDir, "folder1/file9.txt" ), 15 );
348
349 File folder2 = new File( rootDir, "folder1/ignorefolder" );
350 FileUtils.deleteDirectory( folder2 );
351 }
352
353 @Test
354 public void testScanDiff()
355 throws Exception
356 {
357 createTestData();
358
359 DirectoryScanner dss = new DirectoryScanner();
360 dss.setBasedir( tempFolder.getRoot() );
361 Assert.assertNotNull( dss );
362
363
364 dss.scan();
365 String[] oldFiles = dss.getIncludedFiles();
366
367
368 removeAndAddSomeFiles();
369
370 dss.scan();
371
372 DirectoryScanResult dsr = dss.diffIncludedFiles( oldFiles );
373
374 String[] addedFiles = dsr.getFilesAdded();
375 String[] removedFiles = dsr.getFilesRemoved();
376 Assert.assertNotNull( addedFiles );
377 Assert.assertNotNull( removedFiles );
378 assertEquals( 1, addedFiles.length );
379 assertEquals( 2, removedFiles.length );
380 }
381
382 @Ignore( "Enable this test to run performance checks" )
383 @Test
384 public void performanceTest()
385 throws Exception
386 {
387
388 File rootFolder = tempFolder.getRoot();
389
390
391 for ( int i = 1; i < 200; i++ )
392 {
393 createTestData();
394 removeAndAddSomeFiles();
395 FileUtils.deleteDirectory( rootFolder );
396 }
397
398 int cycles = 2000;
399
400
401 long startTime = System.nanoTime();
402 for ( int i = 1; i < cycles; i++ )
403 {
404 createTestData();
405 removeAndAddSomeFiles();
406 FileUtils.deleteDirectory( rootFolder );
407 rootFolder.mkdir();
408 }
409 long endTime = System.nanoTime();
410
411 long durationEmptyRun = endTime - startTime;
412 System.out.println( "durationEmptyRun [ns]: " + durationEmptyRun );
413
414 startTime = System.nanoTime();
415 for ( int i = 1; i < cycles; i++ )
416 {
417 createTestData();
418 DirectoryScanner directoryScanner = new DirectoryScanner();
419 directoryScanner.setBasedir( rootFolder );
420 directoryScanner.scan();
421 String[] oldFiles = directoryScanner.getIncludedFiles();
422
423 removeAndAddSomeFiles();
424
425 directoryScanner.scan();
426
427 DirectoryScanResult directoryScanResult = directoryScanner.diffIncludedFiles( oldFiles );
428 Assert.assertNotNull( directoryScanResult );
429
430 FileUtils.deleteDirectory( rootFolder );
431 rootFolder.mkdir();
432 }
433 endTime = System.nanoTime();
434
435 long durationWithSnapshotScanner = endTime - startTime;
436 System.out.println( "durationWithSnapshotScanner [ns]: " + durationWithSnapshotScanner );
437
438 long dirScannerOverhead = durationWithSnapshotScanner - durationEmptyRun;
439
440 System.out.println( "Overhead for n cycles [ns]: " + dirScannerOverhead );
441 }
442
443 }