Copilot commented on code in PR #3489:
URL: https://github.com/apache/maven-surefire/pull/3489#discussion_r4346508831


##########
surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/LauncherAdapter.java:
##########
@@ -57,15 +66,73 @@ void execute(LauncherDiscoveryRequest discoveryRequest, 
TestExecutionListener...
 
     void executeWithoutCancellationToken(
             LauncherDiscoveryRequest discoveryRequest, 
TestExecutionListener... listeners) {
-        delegate.execute(discoveryRequest, listeners);
+        try {
+            delegate.execute(discoveryRequest, listeners);
+        } catch (JUnitException e) {
+            throw withRootCauseMessage(e);
+        }
     }
 
     private void executeWithCancellationToken(
             LauncherDiscoveryRequest discoveryRequest, 
TestExecutionListener... listeners) {
 
         Method executeMethod = 
requireNonNull(EXECUTE_METHOD_WITH_LAUNCHER_EXECUTION_REQUEST_PARAMETER);
         Object executionRequest = createExecutionRequest(discoveryRequest, 
listeners);
-        ReflectionUtils.invokeMethodWithArray(delegate, executeMethod, 
executionRequest);
+        try {
+            ReflectionUtils.invokeMethodWithArray(delegate, executeMethod, 
executionRequest);
+        } catch (JUnitException e) {
+            throw withRootCauseMessage(e);
+        } catch (SurefireReflectionException e) {
+            JUnitException junitException = findJUnitException(e);
+            if (junitException != null) {
+                throw withRootCauseMessage(junitException);
+            }
+            throw e;
+        }
+    }
+
+    static JUnitException findJUnitException(Throwable failure) {
+        Set<Throwable> visited = Collections.newSetFromMap(new 
IdentityHashMap<Throwable, Boolean>());
+        Throwable cause = failure;
+        while (cause != null && visited.add(cause)) {
+            if (cause instanceof JUnitException) {
+                return (JUnitException) cause;
+            }
+            cause = cause.getCause();
+        }
+        return null;
+    }
+
+    private static JUnitException withRootCauseMessage(JUnitException failure) 
{
+        Throwable rootCause = failure;
+        Set<Throwable> visited = Collections.newSetFromMap(new 
IdentityHashMap<Throwable, Boolean>());
+        visited.add(rootCause);
+        while (rootCause.getCause() != null && 
visited.add(rootCause.getCause())) {
+            rootCause = rootCause.getCause();
+        }
+
+        if (rootCause == failure) {
+            return failure;
+        }
+
+        String causeMessage = rootCause.getMessage();
+        String rootCauseDescription = rootCause.toString();
+        String message = failure.getMessage();
+        if (message != null) {
+            if (message.contains(rootCauseDescription)) {
+                return failure;
+            }
+            if (causeMessage != null && !causeMessage.isEmpty() && 
message.contains(causeMessage)) {
+                String rootCauseType = rootCause.getClass().getName();
+                if (message.contains(rootCauseType)) {
+                    return failure;
+                }
+                return new JUnitException(message + ": " + rootCauseType, 
failure);
+            }
+        }
+        return new JUnitException(
+                message == null || message.isEmpty() ? rootCauseDescription : 
message + ": " + rootCauseDescription,
+                failure);
     }
 

Review Comment:
   When `withRootCauseMessage` creates a new `JUnitException`, the top-level 
stack trace and suppressed exceptions change/are lost, which can reduce the 
diagnostic value compared to the original failure. Consider copying the 
original stack trace (e.g., `newEx.setStackTrace(failure.getStackTrace())`) and 
propagating suppressed exceptions from `failure` to the new exception before 
throwing, so log output remains actionable while preserving original debugging 
context.



##########
surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/LauncherAdapter.java:
##########
@@ -44,7 +49,11 @@ final class LauncherAdapter {
     }
 
     TestPlan discover(LauncherDiscoveryRequest discoveryRequest) {
-        return delegate.discover(discoveryRequest);
+        try {
+            return delegate.discover(discoveryRequest);
+        } catch (JUnitException e) {
+            throw withRootCauseMessage(e);
+        }
     }

Review Comment:
   The same `try/catch (JUnitException) { throw withRootCauseMessage(...) }` 
pattern is duplicated across `discover(...)` and 
`executeWithoutCancellationToken(...)` (and partially in the cancellation-token 
path). To reduce repetition and keep behavior consistent, consider extracting a 
small private helper to run an action and translate `JUnitException`s in one 
place (e.g., a `translateJUnitException(Supplier<T>)` / 
`translateJUnitException(Runnable)` style helper).



##########
surefire-its/src/test/resources/surefire-3463-testng-extension-failure/src/test/resources/META-INF/services/org.testng.ITestNGListener:
##########
@@ -0,0 +1 @@
+issue3463.FailingSuiteListener

Review Comment:
   Service provider configuration files typically should end with a trailing 
newline to avoid tooling edge-cases (some editors and resource filters can 
mishandle the last line without it). Consider ensuring this file ends with a 
newline.



##########
surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/LauncherAdapter.java:
##########
@@ -57,15 +66,73 @@ void execute(LauncherDiscoveryRequest discoveryRequest, 
TestExecutionListener...
 
     void executeWithoutCancellationToken(
             LauncherDiscoveryRequest discoveryRequest, 
TestExecutionListener... listeners) {
-        delegate.execute(discoveryRequest, listeners);
+        try {
+            delegate.execute(discoveryRequest, listeners);
+        } catch (JUnitException e) {
+            throw withRootCauseMessage(e);
+        }
     }

Review Comment:
   The same `try/catch (JUnitException) { throw withRootCauseMessage(...) }` 
pattern is duplicated across `discover(...)` and 
`executeWithoutCancellationToken(...)` (and partially in the cancellation-token 
path). To reduce repetition and keep behavior consistent, consider extracting a 
small private helper to run an action and translate `JUnitException`s in one 
place (e.g., a `translateJUnitException(Supplier<T>)` / 
`translateJUnitException(Runnable)` style helper).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to