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

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/dev/pr-11834-36b0c9fe8e89223b45e8a313d4e5a2ee59274575
in repository https://gitbox.apache.org/repos/asf/seatunnel.git

commit 0e1d7f09c5e51fc4909281cfaa081cf71b970715
Author: Daniel <[email protected]>
AuthorDate: Tue Sep 1 07:30:25 2026 +0000

    [Test][Zeta] Use loopback IP in engine server tests (#11834)
---
 .../engine/server/AbstractSeaTunnelServerTest.java |   3 +-
 .../server/TestStallThreadDumpExtension.java       | 186 +++++++++++++++++++++
 .../resourcemanager/FakeResourceManager.java       |   2 +-
 ...akeResourceManagerForExternalExceptionTest.java |   2 +-
 ...FakeResourceManagerForRequestSlotRetryTest.java |   2 +-
 .../resourcemanager/ResourceManagerTest.java       |   4 +-
 .../server/resourcemanager/WorkerTagTest.java      |   2 +-
 .../engine/server/rest/OptionRulesApiTest.java     |   2 +-
 .../RestApiSubmitJobConfigShadeDecryptTest.java    |   2 +-
 .../RestApiSubmitJobStartWithSavePointTest.java    |   2 +-
 .../org.junit.jupiter.api.extension.Extension}     |  25 +--
 .../src/test/resources/batch_fake_to_inmemory.conf |   4 +-
 .../src/test/resources/hazelcast-client.yaml       |  30 ++--
 .../src/test/resources/hazelcast.yaml              |   4 +-
 .../src/test/resources/junit-platform.properties   |  24 +++
 .../src/test/resources/log4j2-test.properties      |  19 +++
 16 files changed, 261 insertions(+), 52 deletions(-)

diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/AbstractSeaTunnelServerTest.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/AbstractSeaTunnelServerTest.java
index 194e172e65..d95e7278ac 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/AbstractSeaTunnelServerTest.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/AbstractSeaTunnelServerTest.java
@@ -74,6 +74,7 @@ public abstract class AbstractSeaTunnelServerTest<T extends 
AbstractSeaTunnelSer
     }
 
     protected String getHazelcastConfig() {
+        // Use the IPv4 loopback address to avoid dual-stack localhost 
resolution on Windows CI.
         return "hazelcast:\n"
                 + "  cluster-name: seatunnel\n"
                 + "  network:\n"
@@ -86,7 +87,7 @@ public abstract class AbstractSeaTunnelServerTest<T extends 
AbstractSeaTunnelSer
                 + "      tcp-ip:\n"
                 + "        enabled: true\n"
                 + "        member-list:\n"
-                + "          - localhost\n"
+                + "          - 127.0.0.1\n"
                 + "    port:\n"
                 + "      auto-increment: true\n"
                 + "      port-count: 100\n"
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/TestStallThreadDumpExtension.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/TestStallThreadDumpExtension.java
new file mode 100644
index 0000000000..580b6ba464
--- /dev/null
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/TestStallThreadDumpExtension.java
@@ -0,0 +1,186 @@
+/*
+ * 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.seatunnel.engine.server;
+
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MonitorInfo;
+import java.lang.management.ThreadInfo;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Logs a full JVM thread dump when a test class's bootstrap stalls, so hangs 
like the recurring
+ * Windows-only {@code IllegalStateException: Node failed to start!} become 
diagnosable from CI
+ * logs.
+ *
+ * <p>That failure surfaces after ~311 seconds (Hazelcast's 300-second default 
{@code
+ * hazelcast.max.join.seconds} plus shutdown overhead) with no engine log line 
between the config
+ * load and the exception, so the blocked frame never reaches CI output and 
each occurrence has been
+ * untraceable. The stall always happens inside {@code @BeforeAll} while {@code
+ * SeaTunnelServerStarter.createHazelcastInstance} boots the local member, 
which is why this
+ * extension only monitors the window between the {@code beforeAll} callback 
and the first {@code
+ * beforeEach} (or {@code afterAll} for classes whose tests never run): 
legitimate long-running test
+ * methods must not trigger spurious dumps.
+ *
+ * <p>The dump threshold is intentionally below Hazelcast's 300-second join 
ceiling so the dump is
+ * taken while the startup thread is still parked in the blocked frame, not 
after the node has
+ * already given up and torn itself down.
+ *
+ * <p>Registered via {@code 
META-INF/services/org.junit.jupiter.api.extension.Extension} with {@code
+ * junit.jupiter.extensions.autodetection.enabled=true} rather than a launcher 
{@code
+ * TestExecutionListener}, because the module's test classpath only provides 
junit-jupiter-api and
+ * adding junit-platform-launcher would require a pom change.
+ */
+@Slf4j
+public class TestStallThreadDumpExtension
+        implements BeforeAllCallback, BeforeEachCallback, AfterAllCallback {
+
+    /** Bootstrap time budget after which a stall is assumed and a thread dump 
is logged. */
+    private static final long STALL_THRESHOLD_MILLIS = 
TimeUnit.SECONDS.toMillis(240);
+
+    /** How often the watchdog thread re-checks the tracked bootstrap windows. 
*/
+    private static final long SCAN_PERIOD_MILLIS = 
TimeUnit.SECONDS.toMillis(30);
+
+    /**
+     * Test classes currently inside their bootstrap window, mapped to the 
wall-clock start
+     * timestamp of that window.
+     */
+    private static final Map<String, Long> BOOTSTRAP_START_MILLIS = new 
ConcurrentHashMap<>();
+
+    /** Classes already dumped once, so a stalled class does not flood the log 
every scan. */
+    private static final Set<String> ALREADY_DUMPED = 
ConcurrentHashMap.newKeySet();
+
+    /** Ensures the single watchdog daemon thread is started at most once per 
JVM. */
+    private static final AtomicBoolean WATCHDOG_STARTED = new 
AtomicBoolean(false);
+
+    @Override
+    public void beforeAll(ExtensionContext context) {
+        // Extension beforeAll callbacks run before the class's own @BeforeAll 
methods, so this
+        // timestamp covers the whole server-bootstrap window where the known 
stalls occur.
+        BOOTSTRAP_START_MILLIS.put(context.getRequiredTestClass().getName(), 
currentTimeMillis());
+        startWatchdogIfNeeded();
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext context) {
+        // The first test-method setup proves @BeforeAll completed; stop 
monitoring this class so
+        // long-running test methods cannot trigger a spurious dump.
+        
BOOTSTRAP_START_MILLIS.remove(context.getRequiredTestClass().getName());
+    }
+
+    @Override
+    public void afterAll(ExtensionContext context) {
+        // Covers classes whose test methods never start (all skipped, or 
bootstrap threw).
+        
BOOTSTRAP_START_MILLIS.remove(context.getRequiredTestClass().getName());
+    }
+
+    private static void startWatchdogIfNeeded() {
+        if (!WATCHDOG_STARTED.compareAndSet(false, true)) {
+            return;
+        }
+        Thread watchdog =
+                new Thread(TestStallThreadDumpExtension::scanLoop, 
"seatunnel-test-stall-watchdog");
+        // A daemon thread must never keep the surefire JVM alive after the 
test run finishes.
+        watchdog.setDaemon(true);
+        watchdog.start();
+    }
+
+    private static void scanLoop() {
+        while (true) {
+            try {
+                Thread.sleep(SCAN_PERIOD_MILLIS);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                return;
+            }
+            long now = currentTimeMillis();
+            for (Map.Entry<String, Long> entry : 
BOOTSTRAP_START_MILLIS.entrySet()) {
+                long elapsedMillis = now - entry.getValue();
+                if (elapsedMillis >= STALL_THRESHOLD_MILLIS && 
ALREADY_DUMPED.add(entry.getKey())) {
+                    log.error(
+                            "Test class {} has been inside its bootstrap 
window for {} seconds;"
+                                    + " logging a full thread dump before the 
Hazelcast join"
+                                    + " timeout converts this stall into an 
opaque"
+                                    + " 'Node failed to start!' failure.\n{}",
+                            entry.getKey(),
+                            TimeUnit.MILLISECONDS.toSeconds(elapsedMillis),
+                            fullThreadDump());
+                }
+            }
+        }
+    }
+
+    /**
+     * Renders every live thread with its complete stack.
+     *
+     * <p>{@link ThreadInfo#toString()} silently truncates stacks to 8 frames, 
which is useless for
+     * locating a frame parked deep inside Hazelcast bootstrap, so the frames 
are formatted
+     * manually.
+     */
+    private static String fullThreadDump() {
+        ThreadInfo[] threads = 
ManagementFactory.getThreadMXBean().dumpAllThreads(true, true);
+        StringBuilder dump = new StringBuilder(threads.length * 512);
+        for (ThreadInfo thread : threads) {
+            if (thread == null) {
+                continue;
+            }
+            dump.append('"')
+                    .append(thread.getThreadName())
+                    .append("\" id=")
+                    .append(thread.getThreadId())
+                    .append(' ')
+                    .append(thread.getThreadState());
+            if (thread.getLockName() != null) {
+                dump.append(" on ").append(thread.getLockName());
+            }
+            if (thread.getLockOwnerName() != null) {
+                dump.append(" owned by \"")
+                        .append(thread.getLockOwnerName())
+                        .append("\" id=")
+                        .append(thread.getLockOwnerId());
+            }
+            dump.append('\n');
+            for (StackTraceElement frame : thread.getStackTrace()) {
+                dump.append("    at ").append(frame).append('\n');
+            }
+            for (MonitorInfo monitor : thread.getLockedMonitors()) {
+                dump.append("    locked ")
+                        .append(monitor)
+                        .append(" at frame depth ")
+                        .append(monitor.getLockedStackDepth())
+                        .append('\n');
+            }
+            dump.append('\n');
+        }
+        return dump.toString();
+    }
+
+    private static long currentTimeMillis() {
+        return System.currentTimeMillis();
+    }
+}
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManager.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManager.java
index 7755effb74..3c739ce701 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManager.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManager.java
@@ -51,7 +51,7 @@ public class FakeResourceManager extends 
AbstractResourceManager {
     }
 
     private void generateWorker(int port) throws UnknownHostException {
-        Address address = new Address("localhost", port);
+        Address address = new Address("127.0.0.1", port);
         WorkerProfile workerProfile =
                 new WorkerProfile(
                         address,
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManagerForExternalExceptionTest.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManagerForExternalExceptionTest.java
index 259c7fc440..e6691f8069 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManagerForExternalExceptionTest.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManagerForExternalExceptionTest.java
@@ -47,7 +47,7 @@ public class FakeResourceManagerForExternalExceptionTest 
extends AbstractResourc
     }
 
     private void generateWorker(int port) throws UnknownHostException {
-        Address address = new Address("localhost", port);
+        Address address = new Address("127.0.0.1", port);
         WorkerProfile workerProfile =
                 new WorkerProfile(
                         address,
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManagerForRequestSlotRetryTest.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManagerForRequestSlotRetryTest.java
index 40a239b375..7d4f9ca61e 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManagerForRequestSlotRetryTest.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/FakeResourceManagerForRequestSlotRetryTest.java
@@ -64,7 +64,7 @@ public class FakeResourceManagerForRequestSlotRetryTest 
extends AbstractResource
     }
 
     private void generateWorker(int port) throws UnknownHostException {
-        Address address = new Address("localhost", port);
+        Address address = new Address("127.0.0.1", port);
         WorkerProfile workerProfile =
                 new WorkerProfile(
                         address,
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/ResourceManagerTest.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/ResourceManagerTest.java
index 0e76b5114c..a2466077a7 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/ResourceManagerTest.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/ResourceManagerTest.java
@@ -235,7 +235,7 @@ public class ResourceManagerTest extends 
AbstractSeaTunnelServerTest<ResourceMan
         List<ResourceProfile> resourceProfiles = new ArrayList<>();
         resourceProfiles.add(new ResourceProfile());
         ConcurrentMap<Address, WorkerProfile> registerWorker = new 
ConcurrentHashMap<>();
-        Address address1 = new Address("localhost", 5801);
+        Address address1 = new Address("127.0.0.1", 5801);
         WorkerProfile workerProfile1 =
                 new WorkerProfile(
                         address1,
@@ -247,7 +247,7 @@ public class ResourceManagerTest extends 
AbstractSeaTunnelServerTest<ResourceMan
                         Collections.emptyMap());
         registerWorker.put(address1, workerProfile1);
 
-        Address address2 = new Address("localhost", 5802);
+        Address address2 = new Address("127.0.0.1", 5802);
         WorkerProfile workerProfile2 =
                 new WorkerProfile(
                         address2,
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/WorkerTagTest.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/WorkerTagTest.java
index 700e8046f6..6ba193bddc 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/WorkerTagTest.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/resourcemanager/WorkerTagTest.java
@@ -61,7 +61,7 @@ public class WorkerTagTest extends 
AbstractSeaTunnelServerTest<WorkerTagTest> {
                 + "      tcp-ip:\n"
                 + "        enabled: true\n"
                 + "        member-list:\n"
-                + "          - localhost\n"
+                + "          - 127.0.0.1\n"
                 + "    port:\n"
                 + "      auto-increment: true\n"
                 + "      port-count: 100\n"
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/OptionRulesApiTest.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/OptionRulesApiTest.java
index cc3125dcc1..5737f4722e 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/OptionRulesApiTest.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/OptionRulesApiTest.java
@@ -161,7 +161,7 @@ class OptionRulesApiTest {
                 + "      tcp-ip:\n"
                 + "        enabled: true\n"
                 + "        member-list:\n"
-                + "          - localhost\n"
+                + "          - 127.0.0.1\n"
                 + "    port:\n"
                 + "      auto-increment: true\n"
                 + "      port-count: 100\n"
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/RestApiSubmitJobConfigShadeDecryptTest.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/RestApiSubmitJobConfigShadeDecryptTest.java
index 89cd82ab06..f2d2316b85 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/RestApiSubmitJobConfigShadeDecryptTest.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/RestApiSubmitJobConfigShadeDecryptTest.java
@@ -369,7 +369,7 @@ public class RestApiSubmitJobConfigShadeDecryptTest {
                 + "      tcp-ip:\n"
                 + "        enabled: true\n"
                 + "        member-list:\n"
-                + "          - localhost\n"
+                + "          - 127.0.0.1\n"
                 + "    port:\n"
                 + "      auto-increment: true\n"
                 + "      port-count: 100\n"
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/RestApiSubmitJobStartWithSavePointTest.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/RestApiSubmitJobStartWithSavePointTest.java
index 2210579a1f..e6ce345c08 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/RestApiSubmitJobStartWithSavePointTest.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/RestApiSubmitJobStartWithSavePointTest.java
@@ -521,7 +521,7 @@ public class RestApiSubmitJobStartWithSavePointTest {
                 + "      tcp-ip:\n"
                 + "        enabled: true\n"
                 + "        member-list:\n"
-                + "          - localhost\n"
+                + "          - 127.0.0.1\n"
                 + "    port:\n"
                 + "      auto-increment: true\n"
                 + "      port-count: 100\n"
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast-client.yaml
 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
similarity index 60%
copy from 
seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast-client.yaml
copy to 
seatunnel-engine/seatunnel-engine-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
index 9552c382ed..861342d7bd 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast-client.yaml
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -1,4 +1,3 @@
-#
 # 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.
@@ -6,32 +5,12 @@
 # (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
+#     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.
-#
-
-hazelcast-client:
-  cluster-name: seatunnel
 
-  network:
-    cluster-members:
-      - localhost:5801
-      - localhost:5802
-      - localhost:5803
-      - localhost:5804
-      - localhost:5805
-      - localhost:5806
-      - localhost:5807
-      - localhost:5808
-      - localhost:5809
-      - localhost:5810
-      - localhost:5811
-      - localhost:5812
-      - localhost:5813
-      - localhost:5814
-      - localhost:5815
+org.apache.seatunnel.engine.server.TestStallThreadDumpExtension
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/batch_fake_to_inmemory.conf
 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/batch_fake_to_inmemory.conf
index ebe025644a..716f9eb158 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/batch_fake_to_inmemory.conf
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/batch_fake_to_inmemory.conf
@@ -46,7 +46,7 @@ sink {
     plugin_input = "fake"
     username = "st"
     password = "stpassword"
-    address = "localhost"
+    address = "127.0.0.1"
     port = 1234
   }
-}
\ No newline at end of file
+}
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast-client.yaml
 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast-client.yaml
index 9552c382ed..b256c5f9a5 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast-client.yaml
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast-client.yaml
@@ -20,18 +20,18 @@ hazelcast-client:
 
   network:
     cluster-members:
-      - localhost:5801
-      - localhost:5802
-      - localhost:5803
-      - localhost:5804
-      - localhost:5805
-      - localhost:5806
-      - localhost:5807
-      - localhost:5808
-      - localhost:5809
-      - localhost:5810
-      - localhost:5811
-      - localhost:5812
-      - localhost:5813
-      - localhost:5814
-      - localhost:5815
+      - 127.0.0.1:5801
+      - 127.0.0.1:5802
+      - 127.0.0.1:5803
+      - 127.0.0.1:5804
+      - 127.0.0.1:5805
+      - 127.0.0.1:5806
+      - 127.0.0.1:5807
+      - 127.0.0.1:5808
+      - 127.0.0.1:5809
+      - 127.0.0.1:5810
+      - 127.0.0.1:5811
+      - 127.0.0.1:5812
+      - 127.0.0.1:5813
+      - 127.0.0.1:5814
+      - 127.0.0.1:5815
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast.yaml 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast.yaml
index c3596f53b4..af81ee98a8 100644
--- a/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast.yaml
+++ b/seatunnel-engine/seatunnel-engine-server/src/test/resources/hazelcast.yaml
@@ -22,7 +22,7 @@ hazelcast:
       tcp-ip:
         enabled: true
         member-list:
-          - localhost
+          - 127.0.0.1
     port:
       auto-increment: true
       port-count: 100
@@ -37,4 +37,4 @@ hazelcast:
           path: /tmp/file-store-map
   properties:
     hazelcast.slow.operation.detector.stacktrace.logging.enabled: true
-    hazelcast.slow.operation.detector.logging.enabled: true
\ No newline at end of file
+    hazelcast.slow.operation.detector.logging.enabled: true
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/junit-platform.properties
 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000000..0c3682ddd9
--- /dev/null
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/junit-platform.properties
@@ -0,0 +1,24 @@
+################################################################################
+#  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.
+################################################################################
+
+# Required so TestStallThreadDumpExtension (registered through
+# META-INF/services/org.junit.jupiter.api.extension.Extension) is picked up 
without
+# annotating every test class. The extension logs a full thread dump when a 
test
+# class's bootstrap stalls, which is the only way to diagnose the recurring
+# Windows-only "Node failed to start!" hang from CI output.
+junit.jupiter.extensions.autodetection.enabled=true
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/log4j2-test.properties
 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/log4j2-test.properties
index cb58829e4f..bdf2fe133c 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/resources/log4j2-test.properties
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/resources/log4j2-test.properties
@@ -64,3 +64,22 @@ appender.routing.route.job.appender.name = job-${ctx:ST-JID}
 appender.routing.route.job.appender.fileName = 
${file_path}/job-${ctx:ST-JID}.log
 appender.routing.route.job.appender.layout.type = PatternLayout
 appender.routing.route.job.appender.layout.pattern = %d{yyyy-MM-dd 
HH:mm:ss,SSS} %-5p [%-30.30c{1.}] [%t] - %m%n
+
+# The routing appender's system route above references fileAppender, but this 
test config
+# historically omitted the definition (it was copied from 
config/log4j2.properties without this
+# block), so every server bootstrap logged "ERROR Appender fileAppender cannot 
be located. Route
+# ignored" - misleading noise when triaging startup hangs. Mirrors the 
production definition.
+appender.file.name = fileAppender
+appender.file.type = RollingFile
+appender.file.fileName = ${file_path}/${file_name}.log
+appender.file.filePattern = ${file_path}/${file_name}.log.%d{yyyy-MM-dd}-%i
+appender.file.append = true
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = [%X{ST-JID}] %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p 
[%-30.30c{1.}] [%t] - %m%n
+appender.file.policies.type = Policies
+appender.file.policies.time.type = TimeBasedTriggeringPolicy
+appender.file.policies.time.modulate = true
+appender.file.policies.size.type = SizeBasedTriggeringPolicy
+appender.file.policies.size.size = ${file_split_size}
+appender.file.strategy.type = DefaultRolloverStrategy
+appender.file.strategy.fileIndex = nomax

Reply via email to