This is an automated email from the ASF dual-hosted git repository.

Caideyipi pushed a commit to branch backport-17860-dev-1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 300df6f7d168084d30bd1e7511ba8c5b7ea5f16b
Author: Caideyipi <[email protected]>
AuthorDate: Thu Jun 18 16:13:52 2026 +0800

    Fix test clean directory deletion (#17860)
    
    (cherry picked from commit ddc65546ad65e167214a01f10142ecbae3d5950d)
---
 .../agent/plugin/PipeDataNodePluginAgentTest.java  |  9 ++-
 .../compaction/repair/AbstractRepairDataTest.java  | 11 +--
 .../iotdb/db/utils/ConfigurationFileUtilsTest.java |  9 +--
 .../apache/iotdb/db/utils/EnvironmentUtils.java    | 88 ++++++++++++++++++----
 .../iotdb/db/utils/EnvironmentUtilsTest.java       | 52 +++++++++++++
 .../apache/iotdb/commons/utils/FileUtilsTest.java  |  8 +-
 6 files changed, 138 insertions(+), 39 deletions(-)

diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/agent/plugin/PipeDataNodePluginAgentTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/agent/plugin/PipeDataNodePluginAgentTest.java
index ce898fab64a..034eaa7b8e5 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/agent/plugin/PipeDataNodePluginAgentTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/agent/plugin/PipeDataNodePluginAgentTest.java
@@ -29,6 +29,7 @@ import 
org.apache.iotdb.commons.pipe.config.constant.PipeSourceConstant;
 import 
org.apache.iotdb.db.pipe.sink.protocol.thrift.async.IoTDBDataRegionAsyncSink;
 import 
org.apache.iotdb.db.pipe.sink.protocol.thrift.sync.IoTDBDataRegionSyncSink;
 import org.apache.iotdb.db.pipe.source.dataregion.IoTDBDataRegionSource;
+import org.apache.iotdb.db.utils.EnvironmentUtils;
 import org.apache.iotdb.pipe.api.customizer.parameter.PipeParameters;
 
 import org.junit.After;
@@ -72,10 +73,10 @@ public class PipeDataNodePluginAgentTest {
       String pluginPath =
           PipePluginExecutableManager.getInstance()
               .getPluginsDirPath(PIPE_PLUGIN_META.getPluginName());
-      Files.deleteIfExists(Paths.get(pluginPath));
-      
Files.deleteIfExists(Paths.get(PipePluginExecutableManager.getInstance().getInstallDir()));
-      Files.deleteIfExists(Paths.get(TMP_TEMP_LIB_ROOT_DIR));
-      Files.deleteIfExists(Paths.get(TMP_LIB_ROOT_DIR));
+      EnvironmentUtils.cleanDir(pluginPath);
+      
EnvironmentUtils.cleanDir(PipePluginExecutableManager.getInstance().getInstallDir());
+      EnvironmentUtils.cleanDir(TMP_TEMP_LIB_ROOT_DIR);
+      EnvironmentUtils.cleanDir(TMP_LIB_ROOT_DIR);
     } catch (IOException e) {
       Assert.fail();
     }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/repair/AbstractRepairDataTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/repair/AbstractRepairDataTest.java
index 673e7f88106..70e4859786b 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/repair/AbstractRepairDataTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/repair/AbstractRepairDataTest.java
@@ -22,6 +22,7 @@ package 
org.apache.iotdb.db.storageengine.dataregion.compaction.repair;
 import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.AbstractCompactionTest;
+import org.apache.iotdb.db.utils.EnvironmentUtils;
 import org.apache.iotdb.db.utils.constant.TestConstant;
 
 import org.apache.tsfile.exception.write.WriteProcessException;
@@ -54,14 +55,6 @@ public class AbstractRepairDataTest extends 
AbstractCompactionTest {
   }
 
   private void deleteRepairDataLogDir() throws IOException {
-    if (repairDataLogDir.exists()) {
-      if (repairDataLogDir.isDirectory()) {
-        File[] files = repairDataLogDir.listFiles();
-        for (File file : files == null ? new File[] {} : files) {
-          Files.deleteIfExists(file.toPath());
-        }
-      }
-      Files.deleteIfExists(repairDataLogDir.toPath());
-    }
+    EnvironmentUtils.cleanDir(repairDataLogDir.getPath());
   }
 }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java
index 89ef66db385..39f078b440d 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java
@@ -30,7 +30,6 @@ import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
 import java.nio.file.Files;
-import java.util.Objects;
 import java.util.Properties;
 
 public class ConfigurationFileUtilsTest {
@@ -40,13 +39,7 @@ public class ConfigurationFileUtilsTest {
 
   @After
   public void tearDown() throws IOException {
-    if (!dir.exists()) {
-      return;
-    }
-    for (File file : Objects.requireNonNull(dir.listFiles())) {
-      Files.delete(file.toPath());
-    }
-    Files.delete(dir.toPath());
+    EnvironmentUtils.cleanDir(dir.getPath());
   }
 
   @Test
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
index 1291540be05..aaac69f757a 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
@@ -51,7 +51,6 @@ import org.apache.iotdb.rpc.TConfigurationConst;
 import org.apache.iotdb.rpc.TSocketWrapper;
 import org.apache.iotdb.udf.api.exception.UDFManagementException;
 
-import org.apache.commons.io.FileUtils;
 import org.apache.thrift.TConfiguration;
 import org.apache.thrift.transport.TTransport;
 import org.apache.thrift.transport.TTransportException;
@@ -68,6 +67,12 @@ import java.io.File;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.Socket;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.concurrent.TimeUnit;
 
 import static org.junit.Assert.fail;
@@ -80,6 +85,8 @@ public class EnvironmentUtils {
   private static final IoTDBConfig config = 
IoTDBDescriptor.getInstance().getConfig();
   private static final CommonConfig commonConfig = 
CommonDescriptor.getInstance().getConfig();
   private static final TierManager tierManager = TierManager.getInstance();
+  private static final int DELETE_RETRY_TIMES = 5;
+  private static final long DELETE_RETRY_INTERVAL_MS = 100;
 
   public static long TEST_QUERY_JOB_ID = 1;
   public static QueryContext TEST_QUERY_CONTEXT = new 
QueryContext(TEST_QUERY_JOB_ID);
@@ -253,7 +260,69 @@ public class EnvironmentUtils {
   }
 
   public static void cleanDir(String dir) throws IOException {
-    FSFactoryProducer.getFSFactory().deleteDirectory(dir);
+    Path path = FSFactoryProducer.getFSFactory().getFile(dir).toPath();
+    if (!Files.exists(path)) {
+      return;
+    }
+
+    IOException lastException = null;
+    for (int i = 0; i < DELETE_RETRY_TIMES; i++) {
+      try {
+        deleteRecursively(path);
+        return;
+      } catch (NoSuchFileException e) {
+        return;
+      } catch (IOException e) {
+        lastException = e;
+        if (i + 1 == DELETE_RETRY_TIMES) {
+          break;
+        }
+        try {
+          TimeUnit.MILLISECONDS.sleep(DELETE_RETRY_INTERVAL_MS);
+        } catch (InterruptedException interruptedException) {
+          Thread.currentThread().interrupt();
+          IOException ioException =
+              new IOException("Interrupted while deleting " + dir, 
interruptedException);
+          ioException.addSuppressed(e);
+          throw ioException;
+        }
+      }
+    }
+    throw lastException;
+  }
+
+  private static void deleteRecursively(Path path) throws IOException {
+    if (!Files.exists(path)) {
+      return;
+    }
+
+    Files.walkFileTree(
+        path,
+        new SimpleFileVisitor<Path>() {
+          @Override
+          public FileVisitResult visitFile(Path file, BasicFileAttributes 
attrs)
+              throws IOException {
+            Files.deleteIfExists(file);
+            return FileVisitResult.CONTINUE;
+          }
+
+          @Override
+          public FileVisitResult visitFileFailed(Path file, IOException exc) 
throws IOException {
+            if (exc instanceof NoSuchFileException) {
+              return FileVisitResult.CONTINUE;
+            }
+            throw exc;
+          }
+
+          @Override
+          public FileVisitResult postVisitDirectory(Path dir, IOException exc) 
throws IOException {
+            if (exc != null) {
+              throw exc;
+            }
+            Files.deleteIfExists(dir);
+            return FileVisitResult.CONTINUE;
+          }
+        });
   }
 
   /** disable memory control</br> this function should be called before all 
code in the setup */
@@ -317,19 +386,6 @@ public class EnvironmentUtils {
   }
 
   public static void recursiveDeleteFolder(String path) throws IOException {
-    File file = new File(path);
-    if (file.isDirectory()) {
-      File[] files = file.listFiles();
-      if (files == null || files.length == 0) {
-        FileUtils.deleteDirectory(file);
-      } else {
-        for (File f : files) {
-          recursiveDeleteFolder(f.getAbsolutePath());
-        }
-        FileUtils.deleteDirectory(file);
-      }
-    } else {
-      FileUtils.delete(file);
-    }
+    cleanDir(path);
   }
 }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtilsTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtilsTest.java
new file mode 100644
index 00000000000..36783d78dec
--- /dev/null
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtilsTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.utils;
+
+import org.apache.iotdb.db.utils.constant.TestConstant;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Collections;
+
+public class EnvironmentUtilsTest {
+
+  private final File testDir = new File(TestConstant.BASE_OUTPUT_PATH, 
"EnvironmentUtilsTest");
+
+  @After
+  public void tearDown() throws IOException {
+    EnvironmentUtils.cleanDir(testDir.getPath());
+  }
+
+  @Test
+  public void testCleanDirDeletesNestedDirectory() throws IOException {
+    File nestedDir = new File(testDir, "ext" + File.separator + "udf" + 
File.separator + "tmp");
+    Assert.assertTrue(nestedDir.isDirectory() || nestedDir.mkdirs());
+    Files.write(new File(nestedDir, "plugin.txt").toPath(), 
Collections.singletonList("plugin"));
+
+    EnvironmentUtils.cleanDir(testDir.getPath());
+
+    Assert.assertFalse(testDir.exists());
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java
index f4b1ed962bc..c7e52558ff0 100644
--- 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java
@@ -47,8 +47,12 @@ public class FileUtilsTest {
 
   @After
   public void tearDown() throws Exception {
-    tmpDir.delete();
-    targetDir.delete();
+    if (tmpDir != null) {
+      FileUtils.deleteFileOrDirectory(tmpDir, true);
+    }
+    if (targetDir != null) {
+      FileUtils.deleteFileOrDirectory(targetDir, true);
+    }
   }
 
   @Test

Reply via email to