This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git
The following commit(s) were added to refs/heads/dev by this push:
new b65fe82b04 [Fix][E2E] Skip suites when all selected containers are
disabled (#12895)
b65fe82b04 is described below
commit b65fe82b040c203ce669db83431916108f3e866e
Author: zhiweiniu <[email protected]>
AuthorDate: Sat Oct 24 02:15:43 2026 +0000
[Fix][E2E] Skip suites when all selected containers are disabled (#12895)
---
.../apache/seatunnel/e2e/common/TestSuiteBase.java | 2 +
.../common/junit/ContainerSelectionCondition.java | 80 ++++++++++++++
.../junit/ContainerSelectionConditionTest.java | 123 +++++++++++++++++++++
3 files changed, 205 insertions(+)
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/TestSuiteBase.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/TestSuiteBase.java
index a82bd4e763..f32f46d3a8 100644
---
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/TestSuiteBase.java
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/TestSuiteBase.java
@@ -20,6 +20,7 @@ package org.apache.seatunnel.e2e.common;
import org.apache.seatunnel.e2e.common.container.ContainerTcpProxy;
import org.apache.seatunnel.e2e.common.container.TestContainer;
import org.apache.seatunnel.e2e.common.container.TestContainersFactory;
+import org.apache.seatunnel.e2e.common.junit.ContainerSelectionCondition;
import org.apache.seatunnel.e2e.common.junit.ContainerTestingExtension;
import org.apache.seatunnel.e2e.common.junit.TestCaseInvocationContextProvider;
import org.apache.seatunnel.e2e.common.junit.TestContainers;
@@ -41,6 +42,7 @@ import java.util.Arrays;
import java.util.List;
@ExtendWith({
+ ContainerSelectionCondition.class,
ContainerTestingExtension.class,
TestLoggerExtension.class,
TestCaseInvocationContextProvider.class,
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/junit/ContainerSelectionCondition.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/junit/ContainerSelectionCondition.java
new file mode 100644
index 0000000000..b4429523a8
--- /dev/null
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/junit/ContainerSelectionCondition.java
@@ -0,0 +1,80 @@
+/*
+ * 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.e2e.common.junit;
+
+import org.apache.seatunnel.e2e.common.container.TestContainer;
+import org.apache.seatunnel.e2e.common.util.ContainerUtil;
+
+import org.junit.jupiter.api.extension.ConditionEvaluationResult;
+import org.junit.jupiter.api.extension.ExecutionCondition;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * Skips a suite or test method when every container selected by {@code
RUN_ENGINES} is excluded by
+ * {@link DisabledOnContainer}.
+ *
+ * <p>JUnit requires a {@code TestTemplateInvocationContextProvider} to
provide a non-empty stream.
+ * Without this condition, a suite disabled for the only engine selected for a
pull request produces
+ * an empty stream and fails with {@code PreconditionViolationException}
instead of being skipped.
+ */
+@Slf4j
+public class ContainerSelectionCondition implements ExecutionCondition {
+
+ @Override
+ public ConditionEvaluationResult
evaluateExecutionCondition(ExtensionContext context) {
+ List<TestContainer> discoveredContainers =
ContainerUtil.discoverTestContainers();
+ if (shouldDisable(
+ discoveredContainers,
+ context.getRequiredTestClass(),
+ context.getTestMethod().orElse(null))) {
+ String reason =
+ String.format(
+ "All test containers selected by RUN_ENGINES are
disabled for %s.",
+ context.getDisplayName());
+ log.info(reason);
+ return ConditionEvaluationResult.disabled(reason);
+ }
+ return ConditionEvaluationResult.enabled(
+ "At least one applicable test container is available.");
+ }
+
+ /**
+ * Decides whether the class or method must be skipped.
+ *
+ * <p>An empty discovered list keeps the suite enabled so that a real
container discovery
+ * failure stays visible instead of being silently skipped.
+ */
+ static boolean shouldDisable(
+ List<TestContainer> discoveredContainers, Class<?> testClass,
Method testMethod) {
+ if (discoveredContainers.isEmpty()) {
+ return false;
+ }
+ List<TestContainer> applicableContainers =
+ AnnotationUtil.filterDisabledContainers(discoveredContainers,
testClass);
+ if (testMethod != null) {
+ applicableContainers =
+
AnnotationUtil.filterDisabledContainers(applicableContainers, testMethod);
+ }
+ return applicableContainers.isEmpty();
+ }
+}
diff --git
a/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/junit/ContainerSelectionConditionTest.java
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/junit/ContainerSelectionConditionTest.java
new file mode 100644
index 0000000000..146fe9c685
--- /dev/null
+++
b/seatunnel-e2e/seatunnel-e2e-common/src/test/java/org/apache/seatunnel/e2e/common/junit/ContainerSelectionConditionTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.e2e.common.junit;
+
+import org.apache.seatunnel.e2e.common.container.EngineType;
+import org.apache.seatunnel.e2e.common.container.TestContainer;
+import org.apache.seatunnel.e2e.common.container.TestContainerId;
+
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static
org.apache.seatunnel.e2e.common.container.TestContainerId.FLINK_1_18;
+import static
org.apache.seatunnel.e2e.common.container.TestContainerId.SEATUNNEL;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class ContainerSelectionConditionTest {
+
+ private static final List<TestContainer> ZETA_ONLY =
+ Collections.singletonList(container(SEATUNNEL));
+
+ private static final List<TestContainer> ZETA_AND_FLINK =
+ Arrays.asList(container(SEATUNNEL), container(FLINK_1_18));
+
+ @Test
+ void shouldDisableSuiteWhenAllSelectedEnginesAreDisabled() {
+ assertTrue(
+ ContainerSelectionCondition.shouldDisable(
+ ZETA_ONLY, AllEnginesDisabledSuite.class, null));
+ }
+
+ @Test
+ void shouldDisableSuiteWhenAllSelectedContainersAreDisabledByIdentifier() {
+ assertTrue(
+ ContainerSelectionCondition.shouldDisable(
+ ZETA_ONLY, ZetaContainerDisabledSuite.class, null));
+ }
+
+ @Test
+ void shouldKeepSuiteWhenAnotherSelectedEngineRemains() {
+ assertFalse(
+ ContainerSelectionCondition.shouldDisable(
+ ZETA_AND_FLINK, ZetaEngineDisabledSuite.class, null));
+ }
+
+ @Test
+ void shouldKeepSuiteWhenNoContainerWasDiscovered() {
+ assertFalse(
+ ContainerSelectionCondition.shouldDisable(
+ Collections.emptyList(),
AllEnginesDisabledSuite.class, null));
+ }
+
+ @Test
+ void shouldDisableMethodWhenAllSelectedEnginesAreDisabled() throws
Exception {
+ Method method = MethodLevelSuite.class.getDeclaredMethod("zetaOnly");
+
+ assertTrue(
+ ContainerSelectionCondition.shouldDisable(
+ ZETA_ONLY, MethodLevelSuite.class, method));
+ }
+
+ @Test
+ void shouldKeepMethodWhenAnotherSelectedEngineRemains() throws Exception {
+ Method method = MethodLevelSuite.class.getDeclaredMethod("notZeta");
+
+ assertFalse(
+ ContainerSelectionCondition.shouldDisable(
+ ZETA_AND_FLINK, MethodLevelSuite.class, method));
+ }
+
+ private static TestContainer container(TestContainerId identifier) {
+ TestContainer container = mock(TestContainer.class);
+ when(container.identifier()).thenReturn(identifier);
+ return container;
+ }
+
+ @DisabledOnContainer(
+ value = {},
+ type = {EngineType.SEATUNNEL, EngineType.FLINK})
+ private static class AllEnginesDisabledSuite {}
+
+ @DisabledOnContainer(value = SEATUNNEL)
+ private static class ZetaContainerDisabledSuite {}
+
+ @DisabledOnContainer(
+ value = {},
+ type = EngineType.SEATUNNEL)
+ private static class ZetaEngineDisabledSuite {}
+
+ private static class MethodLevelSuite {
+
+ @DisabledOnContainer(
+ value = {},
+ type = EngineType.SEATUNNEL)
+ void zetaOnly() {}
+
+ @DisabledOnContainer(
+ value = {},
+ type = EngineType.FLINK)
+ void notZeta() {}
+ }
+}