diff --git a/src/main/java/org/apache/commons/io/FileCleaningTracker.java b/src/main/java/org/apache/commons/io/FileCleaningTracker.java index 376f5d636cb..5b647ff53e3 100644 --- a/src/main/java/org/apache/commons/io/FileCleaningTracker.java +++ b/src/main/java/org/apache/commons/io/FileCleaningTracker.java @@ -220,6 +220,17 @@ public synchronized void exitWhenFinished() { } } + /** + * Tests whether {@link #exitWhenFinished()} has been called, and therefore whether the file cleaner thread will terminate when there are no more objects + * being tracked for deletion. + * + * @return {@code true} if {@link #exitWhenFinished()} has been called, {@code false} otherwise. + * @since 2.23.0 + */ + public synchronized boolean exitWhenFinishedTest() { + return exitWhenFinished; + } + /** * Gets a copy of the file paths that failed to delete. * diff --git a/src/test/java/org/apache/commons/io/FileCleaningTrackerTest.java b/src/test/java/org/apache/commons/io/FileCleaningTrackerTest.java index 85bfea1aa00..bca09be09c5 100644 --- a/src/test/java/org/apache/commons/io/FileCleaningTrackerTest.java +++ b/src/test/java/org/apache/commons/io/FileCleaningTrackerTest.java @@ -115,6 +115,42 @@ public void tearDown() { fileCleaningTracker = null; } + @Test + void testExitWhenFinishedTestMatchesField() { + // Before calling exitWhenFinished() + assertEquals(fileCleaningTracker.exitWhenFinished, fileCleaningTracker.exitWhenFinishedTest(), + "exitWhenFinishedTest() must reflect the exitWhenFinished field (before)"); + fileCleaningTracker.exitWhenFinished(); + // After calling exitWhenFinished() + assertEquals(fileCleaningTracker.exitWhenFinished, fileCleaningTracker.exitWhenFinishedTest(), + "exitWhenFinishedTest() must reflect the exitWhenFinished field (after)"); + } + + @Test + void testExitWhenFinishedTestReturnsFalseInitially() { + assertFalse(fileCleaningTracker.exitWhenFinishedTest(), "exitWhenFinishedTest() should return false before exitWhenFinished() is called"); + } + + @Test + void testExitWhenFinishedTestReturnsTrueAfterExitWhenFinished() { + fileCleaningTracker.exitWhenFinished(); + assertTrue(fileCleaningTracker.exitWhenFinishedTest(), "exitWhenFinishedTest() should return true after exitWhenFinished() is called"); + } + + @Test + void testExitWhenFinishedTestWithActiveReaper() throws Exception { + final String path = testFile.getPath(); + // Start the reaper by tracking a file + final RandomAccessFile raf = createRandomAccessFile(); + fileCleaningTracker.track(path, raf); + assertFalse(fileCleaningTracker.exitWhenFinishedTest(), "exitWhenFinishedTest() should return false while reaper is still active"); + assertTrue(fileCleaningTracker.reaper.isAlive(), "Reaper should be alive"); + fileCleaningTracker.exitWhenFinished(); + assertTrue(fileCleaningTracker.exitWhenFinishedTest(), + "exitWhenFinishedTest() should return true after exitWhenFinished() is called with active reaper"); + raf.close(); + } + @Test void testFileCleanerDirectory_ForceStrategy_FileSource() throws Exception { if (!testFile.getParentFile().exists()) {