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

ericpai pushed a commit to branch improve/iotdb-3558
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 66369781c5cf3b7b804521ebb334cb43b576c3d3
Author: ericpai <[email protected]>
AuthorDate: Wed Jun 22 16:32:00 2022 +0800

    [IOTDB-3558] Dump node stacks if IT test request timeout
---
 .../java/org/apache/iotdb/it/env/AbstractEnv.java  |  62 ++++-----
 .../apache/iotdb/it/env/AbstractNodeWrapper.java   | 149 +++++++++++++++++++--
 .../org/apache/iotdb/it/env/ConfigNodeWrapper.java |  44 +++---
 .../org/apache/iotdb/it/env/DataNodeWrapper.java   |  33 ++---
 .../org/apache/iotdb/it/env/IoTDBTestRunner.java   |   2 +-
 .../org/apache/iotdb/it/env/RemoteServerEnv.java   |   7 +-
 .../iotdb/it/env/StandaloneDataNodeWrapper.java    |   5 +-
 .../apache/iotdb/it/env/StandaloneOnMppEnv.java    |  16 +--
 .../java/org/apache/iotdb/itbase/env/BaseEnv.java  |   4 +-
 .../apache/iotdb/itbase/env/BaseNodeWrapper.java   |   4 +
 .../itbase/runtime/ParallelRequestDelegate.java    |   3 +
 .../org/apache/iotdb/db/it/env/StandaloneEnv.java  |   6 +-
 12 files changed, 224 insertions(+), 111 deletions(-)

diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractEnv.java 
b/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractEnv.java
index c41ea0c432..27545e8dc7 100644
--- a/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractEnv.java
+++ b/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractEnv.java
@@ -34,9 +34,7 @@ import org.slf4j.LoggerFactory;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 import java.util.Random;
 import java.util.concurrent.TimeUnit;
@@ -53,28 +51,28 @@ public abstract class AbstractEnv implements BaseEnv {
   protected List<ConfigNodeWrapper> configNodeWrapperList;
   protected List<DataNodeWrapper> dataNodeWrapperList;
   private final Random rand = new Random();
-  protected String nextTestCase = null;
+  protected String testMethodName = null;
 
-  protected void initEnvironment(int configNodesNum, int dataNodesNum) throws 
InterruptedException {
+  protected void initEnvironment(int configNodesNum, int dataNodesNum) {
     this.configNodeWrapperList = new ArrayList<>();
     this.dataNodeWrapperList = new ArrayList<>();
 
-    final String testName = getTestClassName() + getNextTestCaseString();
+    final String testClassName = getTestClassName();
+    final String testMethodName = getTestMethodName();
 
-    ConfigNodeWrapper seedConfigNodeWrapper = new ConfigNodeWrapper(true, "", 
testName);
+    ConfigNodeWrapper seedConfigNodeWrapper =
+        new ConfigNodeWrapper(true, "", testClassName, testMethodName);
     seedConfigNodeWrapper.createDir();
     
seedConfigNodeWrapper.changeConfig(ConfigFactory.getConfig().getConfignodeProperties());
     seedConfigNodeWrapper.start();
     String targetConfigNode = seedConfigNodeWrapper.getIpAndPortString();
     this.configNodeWrapperList.add(seedConfigNodeWrapper);
-    logger.info(
-        "In test " + testName + " SeedConfigNode " + 
seedConfigNodeWrapper.getId() + " started.");
 
     List<String> configNodeEndpoints = new ArrayList<>();
     RequestDelegate<Void> configNodesDelegate = new 
SerialRequestDelegate<>(configNodeEndpoints);
     for (int i = 1; i < configNodesNum; i++) {
       ConfigNodeWrapper configNodeWrapper =
-          new ConfigNodeWrapper(false, targetConfigNode, testName);
+          new ConfigNodeWrapper(false, targetConfigNode, testClassName, 
testMethodName);
       this.configNodeWrapperList.add(configNodeWrapper);
       configNodeEndpoints.add(configNodeWrapper.getIpAndPortString());
       configNodeWrapper.createDir();
@@ -82,8 +80,6 @@ public abstract class AbstractEnv implements BaseEnv {
       configNodesDelegate.addRequest(
           () -> {
             configNodeWrapper.start();
-            logger.info(
-                "In test " + testName + " ConfigNode " + 
configNodeWrapper.getId() + " started.");
             return null;
           });
     }
@@ -98,7 +94,8 @@ public abstract class AbstractEnv implements BaseEnv {
     RequestDelegate<Void> dataNodesDelegate =
         new ParallelRequestDelegate<>(dataNodeEndpoints, NODE_START_TIMEOUT);
     for (int i = 0; i < dataNodesNum; i++) {
-      DataNodeWrapper dataNodeWrapper = new DataNodeWrapper(targetConfigNode, 
testName);
+      DataNodeWrapper dataNodeWrapper =
+          new DataNodeWrapper(targetConfigNode, testClassName, testMethodName);
       this.dataNodeWrapperList.add(dataNodeWrapper);
       dataNodeEndpoints.add(dataNodeWrapper.getIpAndPortString());
       dataNodeWrapper.createDir();
@@ -106,8 +103,6 @@ public abstract class AbstractEnv implements BaseEnv {
       dataNodesDelegate.addRequest(
           () -> {
             dataNodeWrapper.start();
-            logger.info(
-                "In test " + testName + " DataNode " + dataNodeWrapper.getId() 
+ " started.");
             return null;
           });
     }
@@ -133,7 +128,7 @@ public abstract class AbstractEnv implements BaseEnv {
       configNodeWrapper.waitingToShutDown();
       configNodeWrapper.destroyDir();
     }
-    nextTestCase = null;
+    testMethodName = null;
   }
 
   public String getTestClassName() {
@@ -147,19 +142,6 @@ public abstract class AbstractEnv implements BaseEnv {
     return "UNKNOWN-IT";
   }
 
-  public String getTestClassNameAndDate() {
-    Date date = new Date();
-    SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd-HHmmss");
-    StackTraceElement[] stack = Thread.currentThread().getStackTrace();
-    for (StackTraceElement stackTraceElement : stack) {
-      String className = stackTraceElement.getClassName();
-      if (className.endsWith("IT")) {
-        return className.substring(className.lastIndexOf(".") + 1) + "-" + 
formatter.format(date);
-      }
-    }
-    return "IT";
-  }
-
   public void testWorking() {
     List<String> endpoints =
         dataNodeWrapperList.stream()
@@ -205,11 +187,6 @@ public abstract class AbstractEnv implements BaseEnv {
     return new ClusterTestConnection(getWriteConnection(null), 
getReadConnections(null));
   }
 
-  @Override
-  public void setNextTestCaseName(String testCaseName) {
-    nextTestCase = testCaseName;
-  }
-
   private Connection getConnection(String endpoint, int queryTimeout) throws 
SQLException {
     IoTDBConnection connection =
         (IoTDBConnection)
@@ -287,10 +264,21 @@ public abstract class AbstractEnv implements BaseEnv {
     return sb.toString();
   }
 
-  public String getNextTestCaseString() {
-    if (nextTestCase != null) {
-      return "_" + nextTestCase;
+  public String getTestMethodName() {
+    return testMethodName;
+  }
+
+  @Override
+  public void setTestMethodName(String testMethodName) {
+    this.testMethodName = testMethodName;
+  }
+
+  public void dumpTestJVMSnapshot() {
+    for (ConfigNodeWrapper configNodeWrapper : configNodeWrapperList) {
+      configNodeWrapper.dumpJVMSnapshot(testMethodName);
+    }
+    for (DataNodeWrapper dataNodeWrapper : dataNodeWrapperList) {
+      dataNodeWrapper.dumpJVMSnapshot(testMethodName);
     }
-    return "";
   }
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractNodeWrapper.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractNodeWrapper.java
index c2390690b0..dcaf56fdc0 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractNodeWrapper.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractNodeWrapper.java
@@ -25,15 +25,32 @@ import org.apache.commons.lang3.SystemUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MonitorInfo;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.net.MalformedURLException;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -47,16 +64,20 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
       System.getProperty("user.dir") + File.separator + "target" + 
File.separator + "template-node";
   private final File NULL_FILE =
       SystemUtils.IS_OS_WINDOWS ? new File("nul") : new File("/dev/null");
-
+  protected final String testClassName;
+  protected final String testMethodName;
+  protected final int[] portList;
+  private final int jmxPort;
+  private final String jmxUserName = "root";
+  private final String jmxPassword = "passw!d";
+  private final String TAB = "  ";
   private Process instance;
-  protected final String testName;
-
-  public AbstractNodeWrapper(String testName) {
-    this.testName = testName;
-  }
 
-  protected final String getId() {
-    return "node" + getPort();
+  public AbstractNodeWrapper(String testClassName, String testMethodName) {
+    this.testClassName = testClassName;
+    this.testMethodName = testMethodName;
+    this.portList = searchAvailablePorts();
+    jmxPort = this.portList[portList.length - 1];
   }
 
   protected final int[] searchAvailablePorts() {
@@ -141,7 +162,7 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
         FileUtils.forceDelete(new File(getNodePath()));
         return;
       } catch (IOException ex) {
-        logger.error("Delete node dir failed. RetryTimes={}", i + 1, ex);
+        logger.warn("Delete node dir failed. RetryTimes={}", i + 1, ex);
         try {
           TimeUnit.SECONDS.sleep(3);
         } catch (InterruptedException e) {
@@ -161,6 +182,7 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
               .redirectOutput(stdoutFile)
               .redirectError(stdoutFile);
       this.instance = processBuilder.start();
+      logger.info("In test {} {} started.", getTestLogDirName(), getId());
     } catch (IOException ex) {
       fail("Start node failed. " + ex);
     }
@@ -219,6 +241,12 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
       try (FileWriter confOutput = new FileWriter(configPath)) {
         configProperties.store(confOutput, null);
       }
+      // Change JMX config
+      Path path = Paths.get(getEnvConfigPath());
+      String content = new String(Files.readAllBytes(path), 
StandardCharsets.UTF_8);
+      content = content.replaceAll("JMX_LOCAL=\"true\"", 
"JMX_LOCAL=\"false\"");
+      content = content.replaceAll("JMX_PORT=\"\\d+\"", 
String.format("JMX_PORT=\"%d\"", jmxPort));
+      Files.write(path, content.getBytes(StandardCharsets.UTF_8));
     } catch (IOException ex) {
       fail("Change the config of data node failed. " + ex);
     }
@@ -246,15 +274,114 @@ public abstract class AbstractNodeWrapper implements 
BaseNodeWrapper {
 
   protected abstract String getConfigPath();
 
+  protected abstract String getEnvConfigPath();
+
   protected abstract void updateConfig(Properties properties);
 
   protected abstract String getStartScriptPath();
 
   protected abstract String getStopScriptPath();
 
-  protected abstract String getLogPath();
+  private String getLogPath() {
+    return getLogDirPath() + File.separator + getId() + ".log";
+  }
+
+  private String getLogDirPath() {
+    return System.getProperty("user.dir")
+        + File.separator
+        + "target"
+        + File.separator
+        + "cluster-logs"
+        + File.separator
+        + getTestLogDirName();
+  }
 
-  protected String getNodePath() {
+  private String getNodePath() {
     return System.getProperty("user.dir") + File.separator + "target" + 
File.separator + getId();
   }
+
+  @Override
+  public void dumpJVMSnapshot(String testCaseName) {
+    JMXServiceURL url;
+    try {
+      url =
+          new JMXServiceURL(
+              
String.format("service:jmx:rmi:///jndi/rmi://127.0.0.1:%d/jmxrmi", jmxPort));
+    } catch (MalformedURLException e) {
+      logger.error("Construct JMX URL failed", e);
+      return;
+    }
+    Map<String, Object> environment =
+        Collections.singletonMap(JMXConnector.CREDENTIALS, new String[] 
{jmxUserName, jmxPassword});
+
+    try (JMXConnector connector = JMXConnectorFactory.connect(url, 
environment)) {
+      MBeanServerConnection mbsc = connector.getMBeanServerConnection();
+      ThreadMXBean tmbean =
+          ManagementFactory.newPlatformMXBeanProxy(
+              mbsc, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);
+      ThreadInfo[] threadInfos = tmbean.dumpAllThreads(true, true);
+      long[] deadlockIds = tmbean.findDeadlockedThreads();
+      LocalDateTime currentTime = LocalDateTime.now();
+      try (PrintWriter output =
+          new PrintWriter(
+              getLogDirPath() + File.separator + testCaseName + "_" + getId() 
+ "-threads.dump")) {
+        output.printf("# Captured at %s\n", currentTime);
+        output.println("==================\n");
+        if (deadlockIds != null && deadlockIds.length > 0) {
+          output.printf("Detect DEADLOCK threads!\n");
+          for (long deadlockId : deadlockIds) {
+            ThreadInfo ti = tmbean.getThreadInfo(deadlockId);
+            output.printf("%s #%d\n", ti.getThreadName(), ti.getThreadId());
+          }
+          output.println("==================\n");
+        }
+        for (ThreadInfo threadInfo : threadInfos) {
+          dumpThread(output, threadInfo);
+        }
+      }
+    } catch (IOException e) {
+      logger.error("Connect with MBeanServer {} failed", url.getURLPath(), e);
+    }
+  }
+
+  private void dumpThread(PrintWriter output, ThreadInfo ti) {
+    StringBuilder sb = new StringBuilder("\"" + ti.getThreadName() + "\"");
+    sb.append(" #").append(ti.getThreadId());
+    sb.append(" ").append(ti.getThreadState()).append("\n");
+    if (ti.getLockName() != null) {
+      sb.append("Waiting on: ").append(ti.getLockName()).append("\n");
+    }
+    if (ti.getLockOwnerName() != null) {
+      sb.append("Locked by: ")
+          .append(ti.getLockOwnerName())
+          .append(" #")
+          .append(ti.getLockOwnerId())
+          .append("\n");
+    }
+    Map<StackTraceElement, MonitorInfo> lockInfoMap = new HashMap<>();
+    for (MonitorInfo monitor : ti.getLockedMonitors()) {
+      lockInfoMap.put(monitor.getLockedStackFrame(), monitor);
+    }
+    for (StackTraceElement ele : ti.getStackTrace()) {
+      if (lockInfoMap.containsKey(ele)) {
+        MonitorInfo monitorInfo = lockInfoMap.get(ele);
+        sb.append(TAB)
+            .append("- lock ")
+            .append(monitorInfo.getClassName())
+            .append("@")
+            .append(Integer.toHexString(monitorInfo.getIdentityHashCode()))
+            .append("\n");
+      }
+      sb.append(TAB).append(ele).append("\n");
+    }
+    sb.append("\n");
+    output.print(sb);
+  }
+
+  private String getTestLogDirName() {
+    if (testMethodName == null) {
+      return testClassName;
+    }
+    return testClassName + "_" + testMethodName;
+  }
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/ConfigNodeWrapper.java 
b/integration-test/src/main/java/org/apache/iotdb/it/env/ConfigNodeWrapper.java
index cd3ff3b4ee..319e854847 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/ConfigNodeWrapper.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/ConfigNodeWrapper.java
@@ -27,14 +27,11 @@ public class ConfigNodeWrapper extends AbstractNodeWrapper {
 
   private final int consensusPort;
   private final String targetConfigNode;
-  private final int[] portList;
 
-  public ConfigNodeWrapper(boolean isSeed, String targetConfigNode, String 
testName) {
-    super(testName);
-
-    portList = super.searchAvailablePorts();
+  public ConfigNodeWrapper(
+      boolean isSeed, String targetConfigNode, String testClassName, String 
testMethodName) {
+    super(testClassName, testMethodName);
     this.consensusPort = portList[1];
-
     if (isSeed) {
       this.targetConfigNode = getIpAndPortString();
     } else {
@@ -67,6 +64,14 @@ public class ConfigNodeWrapper extends AbstractNodeWrapper {
     return workDirFilePath("confignode" + File.separator + "conf", 
"iotdb-confignode.properties");
   }
 
+  @Override
+  protected String getEnvConfigPath() {
+    if (SystemUtils.IS_OS_WINDOWS) {
+      return workDirFilePath("confignode" + File.separator + "conf", 
"confignode-env.bat");
+    }
+    return workDirFilePath("confignode" + File.separator + "conf", 
"confignode-env.sh");
+  }
+
   @Override
   protected String getStartScriptPath() {
     String scriptName = "start-confignode.sh";
@@ -86,31 +91,12 @@ public class ConfigNodeWrapper extends AbstractNodeWrapper {
   }
 
   @Override
-  protected String getLogPath() {
-    return System.getProperty("user.dir")
-        + File.separator
-        + "target"
-        + File.separator
-        + "cluster-logs"
-        + File.separator
-        + testName
-        + File.separator
-        + "Config"
-        + super.getId()
-        + ".log";
-  }
-
-  @Override
-  protected String getNodePath() {
-    return System.getProperty("user.dir")
-        + File.separator
-        + "target"
-        + File.separator
-        + super.getId();
+  public int getPort() {
+    return portList[0];
   }
 
   @Override
-  public int getPort() {
-    return portList[0];
+  public final String getId() {
+    return "ConfigNode" + getPort();
   }
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/DataNodeWrapper.java 
b/integration-test/src/main/java/org/apache/iotdb/it/env/DataNodeWrapper.java
index 87779bd2be..cb03c31d07 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/DataNodeWrapper.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/DataNodeWrapper.java
@@ -26,17 +26,14 @@ import java.util.Properties;
 public class DataNodeWrapper extends AbstractNodeWrapper {
 
   private final String targetConfigNode;
-
   private final int dataBlockManagerPort;
   private final int internalPort;
   private final int dataRegionConsensusPort;
   private final int schemaRegionConsensusPort;
-  private final int[] portList;
 
-  public DataNodeWrapper(String targetConfigNode, String testName) {
-    super(testName);
+  public DataNodeWrapper(String targetConfigNode, String testClassName, String 
testMethodName) {
+    super(testClassName, testMethodName);
     this.targetConfigNode = targetConfigNode;
-    portList = super.searchAvailablePorts();
     this.dataBlockManagerPort = portList[1];
     this.internalPort = portList[2];
     this.dataRegionConsensusPort = portList[3];
@@ -65,6 +62,14 @@ public class DataNodeWrapper extends AbstractNodeWrapper {
     return workDirFilePath("datanode" + File.separator + "conf", 
"iotdb-engine.properties");
   }
 
+  @Override
+  protected String getEnvConfigPath() {
+    if (SystemUtils.IS_OS_WINDOWS) {
+      return workDirFilePath("datanode" + File.separator + "conf", 
"iotdb-env.bat");
+    }
+    return workDirFilePath("datanode" + File.separator + "conf", 
"iotdb-env.sh");
+  }
+
   @Override
   protected String getStartScriptPath() {
     String scriptName = "start-datanode.sh";
@@ -84,22 +89,12 @@ public class DataNodeWrapper extends AbstractNodeWrapper {
   }
 
   @Override
-  protected String getLogPath() {
-    return System.getProperty("user.dir")
-        + File.separator
-        + "target"
-        + File.separator
-        + "cluster-logs"
-        + File.separator
-        + testName
-        + File.separator
-        + "Data"
-        + super.getId()
-        + ".log";
+  public int getPort() {
+    return portList[0];
   }
 
   @Override
-  public int getPort() {
-    return portList[0];
+  public final String getId() {
+    return "DataNode" + getPort();
   }
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/IoTDBTestRunner.java 
b/integration-test/src/main/java/org/apache/iotdb/it/env/IoTDBTestRunner.java
index 433c7dc357..f160f8dfc4 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/IoTDBTestRunner.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/IoTDBTestRunner.java
@@ -38,7 +38,7 @@ public class IoTDBTestRunner extends BlockJUnit4ClassRunner {
   protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
     Description description = describeChild(method);
     logger.info("Run {}", description.getMethodName());
-    EnvFactory.getEnv().setNextTestCaseName(description.getMethodName());
+    EnvFactory.getEnv().setTestMethodName(description.getMethodName());
     super.runChild(method, notifier);
   }
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/RemoteServerEnv.java 
b/integration-test/src/main/java/org/apache/iotdb/it/env/RemoteServerEnv.java
index 4bf339f335..a9be62426f 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/RemoteServerEnv.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/RemoteServerEnv.java
@@ -105,7 +105,12 @@ public class RemoteServerEnv implements BaseEnv {
     return connection;
   }
 
-  public void setNextTestCaseName(String testCaseName) {
+  public void setTestMethodName(String testCaseName) {
+    // Do nothing
+  }
+
+  @Override
+  public void dumpTestJVMSnapshot() {
     // Do nothing
   }
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/StandaloneDataNodeWrapper.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/StandaloneDataNodeWrapper.java
index 21ab80b13f..fbf28139f5 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/StandaloneDataNodeWrapper.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/StandaloneDataNodeWrapper.java
@@ -24,8 +24,9 @@ import java.io.File;
 
 public class StandaloneDataNodeWrapper extends DataNodeWrapper {
 
-  public StandaloneDataNodeWrapper(String targetConfigNode, String testName) {
-    super(targetConfigNode, testName);
+  public StandaloneDataNodeWrapper(
+      String targetConfigNode, String testClassName, String testMethodName) {
+    super(targetConfigNode, testClassName, testMethodName);
   }
 
   @Override
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/StandaloneOnMppEnv.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/StandaloneOnMppEnv.java
index 0d7e0fad35..3ae22d9739 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/StandaloneOnMppEnv.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/StandaloneOnMppEnv.java
@@ -21,21 +21,19 @@ package org.apache.iotdb.it.env;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
+import java.util.Collections;
 
 public class StandaloneOnMppEnv extends AbstractEnv {
 
   private static final Logger logger = 
LoggerFactory.getLogger(StandaloneOnMppEnv.class);
 
-  private void initEnvironment() throws InterruptedException {
-    super.dataNodeWrapperList = new ArrayList<>();
-    final String testName = super.getTestClassName() + 
super.getNextTestCaseString();
-    DataNodeWrapper dataNodeWrapper = new StandaloneDataNodeWrapper(null, 
testName);
+  private void initEnvironment() {
+    DataNodeWrapper dataNodeWrapper =
+        new StandaloneDataNodeWrapper(null, super.getTestClassName(), 
super.getTestMethodName());
     dataNodeWrapper.createDir();
     
dataNodeWrapper.changeConfig(ConfigFactory.getConfig().getEngineProperties());
     dataNodeWrapper.start();
-    super.dataNodeWrapperList.add(dataNodeWrapper);
-    logger.info("In test " + testName + " DataNode " + dataNodeWrapper.getId() 
+ " started.");
+    super.dataNodeWrapperList = Collections.singletonList(dataNodeWrapper);
     super.testWorking();
   }
 
@@ -46,7 +44,7 @@ public class StandaloneOnMppEnv extends AbstractEnv {
   }
 
   @Override
-  public void initBeforeTest() throws InterruptedException {
+  public void initBeforeTest() {
     logger.debug("=======start init test=======");
     initEnvironment();
   }
@@ -57,7 +55,7 @@ public class StandaloneOnMppEnv extends AbstractEnv {
       dataNodeWrapper.waitingToShutDown();
       dataNodeWrapper.destroyDir();
     }
-    super.nextTestCase = null;
+    super.testMethodName = null;
   }
 
   @Override
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java
index 5ed57e05b8..8e5650d44b 100644
--- a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java
+++ b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java
@@ -37,5 +37,7 @@ public interface BaseEnv {
 
   Connection getConnection(Constant.Version version) throws SQLException;
 
-  void setNextTestCaseName(String testCaseName);
+  void setTestMethodName(String testCaseName);
+
+  void dumpTestJVMSnapshot();
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseNodeWrapper.java
 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseNodeWrapper.java
index ecb2e1fc05..c1efb1f351 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseNodeWrapper.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseNodeWrapper.java
@@ -38,5 +38,9 @@ public interface BaseNodeWrapper {
 
   int getPort();
 
+  String getId();
+
   String getIpAndPortString();
+
+  void dumpJVMSnapshot(String testCaseName);
 }
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ParallelRequestDelegate.java
 
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ParallelRequestDelegate.java
index 92b5b478bc..2fae21e56c 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ParallelRequestDelegate.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ParallelRequestDelegate.java
@@ -18,6 +18,8 @@
  */
 package org.apache.iotdb.itbase.runtime;
 
+import org.apache.iotdb.it.env.EnvFactory;
+
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
@@ -53,6 +55,7 @@ public class ParallelRequestDelegate<T> extends 
RequestDelegate<T> {
       } catch (ExecutionException e) {
         exceptions[i] = e;
       } catch (InterruptedException | TimeoutException e) {
+        EnvFactory.getEnv().dumpTestJVMSnapshot();
         for (int j = i; j < getEndpoints().size(); j++) {
           resultFutures.get(j).cancel(true);
         }
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/env/StandaloneEnv.java 
b/integration-test/src/test/java/org/apache/iotdb/db/it/env/StandaloneEnv.java
index efe6c728b2..dfc4d4fa9f 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/env/StandaloneEnv.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/env/StandaloneEnv.java
@@ -87,7 +87,11 @@ public class StandaloneEnv implements BaseEnv {
     return null;
   }
 
-  public void setNextTestCaseName(String testCaseName) {
+  public void setTestMethodName(String testCaseName) {
+    // Do nothing
+  }
+
+  public void dumpTestJVMSnapshot() {
     // Do nothing
   }
 }

Reply via email to