Tests IO-850

DeletingPathVisitor always fails to delete a dir when symbolic link
target is deleted before the link itself

https://issues.apache.org/jira/browse/IO-850
diff --git a/src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java b/src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java
index 38c0a34..e76f025 100644
--- a/src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java
+++ b/src/test/java/org/apache/commons/io/file/AbstractTempDirTest.java
@@ -31,22 +31,24 @@
  */
 public abstract class AbstractTempDirTest {
 
+    protected static final String SUB_DIR = "subdir";
+    protected static final String SYMLINKED_DIR = "symlinked-dir";
+
     /**
-     * Creates directory test fixtures.
+     * Creates directory test fixtures in the given directory {@code rootDir}.
      * <ol>
-     * <li>tempDirPath/subdir</li>
-     * <li>tempDirPath/symlinked-dir -> tempDirPath/subdir</li>
+     * <li>{@code rootDir/subdir}</li>
+     * <li>{@code rootDir/symlinked-dir} -> {@code rootDir/subdir}</li>
      * </ol>
      * @param rootDir Root for directory entries.
-     * @return Path to tempDirPath/subdir.
+     * @return Path for {@code tempDirPath/subdir}.
      * @throws IOException if an I/O error occurs or the parent directory does not exist.
      */
     protected static Path createTempSymlinkedRelativeDir(final Path rootDir) throws IOException {
-        final Path targetDir = rootDir.resolve("subdir");
-        final Path symlinkDir = rootDir.resolve("symlinked-dir");
+        final Path targetDir = rootDir.resolve(SUB_DIR);
+        final Path symlinkDir = rootDir.resolve(SYMLINKED_DIR);
         Files.createDirectory(targetDir);
-        Files.createSymbolicLink(symlinkDir, targetDir);
-        return symlinkDir;
+        return Files.createSymbolicLink(symlinkDir, targetDir);
     }
 
     /**
@@ -56,15 +58,15 @@
     public Path managedTempDirPath;
 
     /**
-     * A temporary directory managed by each test so we can optionally fiddle with its permissions independently.
-     */
-    public Path tempDirPath;
-
-    /**
      * A File version of this test's Path object.
      */
     public File tempDirFile;
 
+    /**
+     * A temporary directory managed by each test so we can optionally fiddle with its permissions independently.
+     */
+    public Path tempDirPath;
+
     @BeforeEach
     public void beforeEachCreateTempDirs() throws IOException {
         tempDirPath = Files.createTempDirectory(managedTempDirPath, getClass().getSimpleName());
diff --git a/src/test/java/org/apache/commons/io/file/DeletingPathVisitorTest.java b/src/test/java/org/apache/commons/io/file/DeletingPathVisitorTest.java
index 8570d4a..a0e3b3f 100644
--- a/src/test/java/org/apache/commons/io/file/DeletingPathVisitorTest.java
+++ b/src/test/java/org/apache/commons/io/file/DeletingPathVisitorTest.java
@@ -18,14 +18,18 @@
 package org.apache.commons.io.file;
 
 import static org.apache.commons.io.file.CounterAssertions.assertCounts;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
 import org.apache.commons.io.file.Counters.PathCounters;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
 
@@ -113,4 +117,42 @@
         // This will throw if not empty.
         Files.deleteIfExists(tempDirPath);
     }
+
+    /**
+     * Tests https://issues.apache.org/jira/browse/IO-850
+     */
+    @Test
+    public void testIO850DirectoriesOnly() throws IOException {
+        final Path rootDir = Files.createDirectory(managedTempDirPath.resolve("IO850"));
+        createTempSymlinkedRelativeDir(rootDir);
+        final Path targetDir = rootDir.resolve(SUB_DIR);
+        final Path symlinkDir = rootDir.resolve(SYMLINKED_DIR);
+        final DeletingPathVisitor visitor = DeletingPathVisitor.withLongCounters();
+        Files.walkFileTree(rootDir, visitor);
+        assertFalse(Files.exists(targetDir));
+        assertFalse(Files.exists(symlinkDir));
+        assertFalse(Files.exists(rootDir));
+        assertTrue(visitor.getPathCounters().getDirectoryCounter().get() > 0);
+    }
+
+    /**
+     * Tests https://issues.apache.org/jira/browse/IO-850
+     */
+    @Test
+    public void testIO850DirectoriesAndFiles() throws IOException {
+        final Path rootDir = Files.createDirectory(managedTempDirPath.resolve("IO850"));
+        createTempSymlinkedRelativeDir(rootDir);
+        final Path targetDir = rootDir.resolve(SUB_DIR);
+        final Path symlinkDir = rootDir.resolve(SYMLINKED_DIR);
+        Files.write(targetDir.resolve("file0.txt"), "Hello".getBytes(StandardCharsets.UTF_8));
+        final Path subDir0 = Files.createDirectory(targetDir.resolve("subDir0"));
+        Files.write(subDir0.resolve("file1.txt"), "Hello".getBytes(StandardCharsets.UTF_8));
+        final DeletingPathVisitor visitor = DeletingPathVisitor.withLongCounters();
+        Files.walkFileTree(rootDir, visitor);
+        assertFalse(Files.exists(targetDir));
+        assertFalse(Files.exists(symlinkDir));
+        assertFalse(Files.exists(rootDir));
+        assertTrue(visitor.getPathCounters().getDirectoryCounter().get() > 0);
+        assertTrue(visitor.getPathCounters().getFileCounter().get() > 0);
+    }
 }