2020import static org .junit .jupiter .api .Assertions .assertFalse ;
2121import static org .junit .jupiter .api .Assertions .assertThrows ;
2222import static org .junit .jupiter .api .Assertions .assertTrue ;
23+ import static org .junit .jupiter .api .Assertions .fail ;
2324
2425import java .io .File ;
2526import java .io .IOException ;
27+ import java .nio .charset .StandardCharsets ;
28+ import java .nio .file .Files ;
29+ import java .nio .file .Path ;
2630import java .util .ArrayList ;
2731import java .util .Collection ;
2832import java .util .Iterator ;
2933import java .util .List ;
34+ import java .util .UUID ;
35+ import java .util .concurrent .CompletableFuture ;
36+ import java .util .concurrent .ExecutionException ;
3037import java .util .stream .Collectors ;
3138import java .util .stream .Stream ;
3239
40+ import org .apache .commons .io .file .PathUtils ;
3341import org .apache .commons .io .filefilter .FileFilterUtils ;
3442import org .apache .commons .io .filefilter .IOFileFilter ;
3543import org .apache .commons .io .function .Uncheck ;
3644import org .apache .commons .lang3 .function .Consumers ;
3745import org .junit .jupiter .api .BeforeEach ;
3846import org .junit .jupiter .api .Test ;
47+ import org .junit .jupiter .api .condition .EnabledOnOs ;
48+ import org .junit .jupiter .api .condition .OS ;
3949import org .junit .jupiter .api .io .TempDir ;
4050
4151/**
@@ -211,7 +221,9 @@ public void testListFilesWithDeletion() throws IOException {
211221 final String [] extensions = {"xml" , "txt" };
212222 final List <File > list ;
213223 final File xFile = new File (temporaryFolder , "x.xml" );
214- xFile .createNewFile ();
224+ if (!xFile .createNewFile ()) {
225+ fail ("could not create test file: " + xFile );
226+ }
215227 final Collection <File > files = FileUtils .listFiles (temporaryFolder , extensions , true );
216228 assertEquals (5 , files .size ());
217229 try (Stream <File > stream = Uncheck .get (() -> FileUtils .streamFiles (temporaryFolder , true , extensions ))) {
@@ -222,4 +234,49 @@ public void testListFilesWithDeletion() throws IOException {
222234 assertEquals (4 , list .size ());
223235 }
224236
237+ /**
238+ * Tests <a href="https://issues.apache.org/jira/browse/IO-856">IO-856</a> ListFiles should not fail on vanishing files.
239+ */
240+ @ Test
241+ @ EnabledOnOs (value = OS .WINDOWS )
242+ public void testListFilesWithDeletionThreaded () throws ExecutionException , InterruptedException {
243+ // test for IO-856
244+ // create random directory in tmp, create the directory if it does not exist
245+ final Path tempPath = PathUtils .getTempDirectory ().resolve ("IO-856" );
246+ final File tempDir = tempPath .toFile ();
247+ if (!tempDir .exists () && !tempDir .mkdirs ()) {
248+ fail ("Could not create file path: " + tempDir .getAbsolutePath ());
249+ }
250+ final int waitTime = 10_000 ;
251+ final byte [] bytes = "TEST" .getBytes (StandardCharsets .UTF_8 );
252+ final CompletableFuture <Void > c1 = CompletableFuture .runAsync (() -> {
253+ final long endTime = System .currentTimeMillis () + waitTime ;
254+ while (System .currentTimeMillis () < endTime ) {
255+ final File file = new File (tempDir .getAbsolutePath (), UUID .randomUUID () + ".deletetester" );
256+ file .deleteOnExit ();
257+ try {
258+ Files .write (file .toPath (), bytes );
259+ } catch (final Exception e ) {
260+ fail ("Could not create test file: " + file .getAbsolutePath (), e );
261+ }
262+ if (!file .delete ()) {
263+ fail ("Could not delete test file: " + file .getAbsolutePath ());
264+ }
265+ }
266+ });
267+ final CompletableFuture <Void > c2 = CompletableFuture .runAsync (() -> {
268+ final long endTime = System .currentTimeMillis () + waitTime ;
269+ try {
270+ while (System .currentTimeMillis () < endTime ) {
271+ FileUtils .listFiles (tempDir , new String [] { "\\ .deletetester" }, false );
272+ }
273+ } catch (final Exception e ) {
274+ fail ("Should not happen" , e );
275+ }
276+ });
277+ // wait for the threads to finish
278+ c1 .get ();
279+ c2 .get ();
280+ }
281+
225282}
0 commit comments