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

jt2594838 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new ddc65546ad6 Fix test clean directory deletion (#17860)
ddc65546ad6 is described below

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

    Fix test clean directory deletion (#17860)
---
 .../pipe/PipeTaskInfoConsensusPipeTest.java        |  4 +-
 .../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 +-
 7 files changed, 140 insertions(+), 41 deletions(-)

diff --git 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/pipe/PipeTaskInfoConsensusPipeTest.java
 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/pipe/PipeTaskInfoConsensusPipeTest.java
index 95f03683336..1511c76abbc 100644
--- 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/pipe/PipeTaskInfoConsensusPipeTest.java
+++ 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/pipe/PipeTaskInfoConsensusPipeTest.java
@@ -25,6 +25,7 @@ import 
org.apache.iotdb.commons.pipe.agent.task.meta.PipeRuntimeMeta;
 import org.apache.iotdb.commons.pipe.agent.task.meta.PipeStaticMeta;
 import org.apache.iotdb.commons.pipe.agent.task.meta.PipeStatus;
 import org.apache.iotdb.commons.pipe.agent.task.meta.PipeTaskMeta;
+import org.apache.iotdb.commons.utils.FileUtils;
 import 
org.apache.iotdb.confignode.consensus.request.write.pipe.task.CreatePipePlanV2;
 import 
org.apache.iotdb.confignode.consensus.request.write.pipe.task.SetPipeStatusPlanV2;
 import 
org.apache.iotdb.confignode.consensus.request.write.pipe.task.SetPipeStatusWithStoppedByRuntimeExceptionPlanV2;
@@ -203,8 +204,7 @@ public class PipeTaskInfoConsensusPipeTest {
               .getStatus()
               .get());
     } finally {
-      new File(snapshotDir, "pipe_task_info.bin").delete();
-      snapshotDir.delete();
+      FileUtils.deleteFileOrDirectory(snapshotDir, true);
     }
   }
 
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 04c759935cd..ae4d595ee0c 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
@@ -31,6 +31,7 @@ import 
org.apache.iotdb.db.pipe.sink.protocol.iotconsensusv2.IoTConsensusV2Async
 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;
@@ -74,10 +75,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 ae419c79ecd..a21b8fc58c2 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
@@ -36,7 +36,6 @@ import java.io.InputStreamReader;
 import java.nio.file.Files;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
 
@@ -47,13 +46,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 440e32df46e..4c2e1c9c95b 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
@@ -55,7 +55,6 @@ import 
org.apache.iotdb.udf.api.exception.UDFManagementException;
 import org.apache.thrift.TConfiguration;
 import org.apache.thrift.transport.TTransport;
 import org.apache.thrift.transport.TTransportException;
-import org.apache.tsfile.external.commons.io.FileUtils;
 import org.apache.tsfile.fileSystem.FSFactoryProducer;
 import org.apache.tsfile.utils.FilePathUtils;
 import org.slf4j.Logger;
@@ -69,6 +68,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;
@@ -83,6 +88,8 @@ public class EnvironmentUtils {
   private static final DataNodeMemoryConfig memoryConfig =
       IoTDBDescriptor.getInstance().getMemoryConfig();
   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, false);
@@ -277,7 +284,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 */
@@ -338,19 +407,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 cc1586f5f74..4c2210998b0 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
@@ -46,8 +46,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