IDEA-354877 [FileComparison] fix: check the full hierarchy of the test exception class

The users can throw the test assertion exception that can be inherited from the default assertion exception classes.

GitOrigin-RevId: 0d6e89002e76a3b30bb2baeec6f7f6a0ac5e5c50
This commit is contained in:
Sergei Vorobyov
2024-06-13 19:04:29 +02:00
committed by intellij-monorepo-bot
parent 72734925bd
commit 8907525bf3
2 changed files with 19 additions and 60 deletions

View File

@@ -20,10 +20,10 @@ public class ComparisonFailureData {
private static final String ASSERTION_CLASS_NAME = "java.lang.AssertionError";
private static final String ASSERTION_FAILED_CLASS_NAME = "junit.framework.AssertionFailedError";
public static final String OPENTEST4J_ASSERTION = "org.opentest4j.AssertionFailedError";
public static final String OPENTEST4J_VALUE_WRAPPER = "org.opentest4j.ValueWrapper";
public static final String OPENTEST4J_FILE_INFO = "org.opentest4j.FileInfo";
public static final Charset OPENTEST4J_FILE_CONTENT_CHARSET = StandardCharsets.UTF_8;
private static final String OPENTEST4J_ASSERTION = "org.opentest4j.AssertionFailedError";
private static final String OPENTEST4J_VALUE_WRAPPER = "org.opentest4j.ValueWrapper";
private static final String OPENTEST4J_FILE_INFO = "org.opentest4j.FileInfo";
private static final Charset OPENTEST4J_FILE_CONTENT_CHARSET = StandardCharsets.UTF_8;
private final String myExpected;
private final String myActual;
@@ -172,30 +172,22 @@ public class ComparisonFailureData {
attrs.put(expectedOrActualPrefix, text);
}
public static boolean isInstance(Class<?> aClass, String className) {
if (aClass == null) return false;
if (className.equals(aClass.getName())) return true;
return isInstance(aClass.getSuperclass(), className);
}
public static boolean isAssertionError(Class<?> throwableClass) {
if (throwableClass == null) return false;
final String throwableClassName = throwableClass.getName();
if (throwableClassName.equals(ASSERTION_CLASS_NAME) ||
throwableClassName.equals(ASSERTION_FAILED_CLASS_NAME) ||
throwableClassName.equals(OPENTEST4J_ASSERTION)) {
return true;
}
return isAssertionError(throwableClass.getSuperclass());
return isInstance(throwableClass, ASSERTION_CLASS_NAME) ||
isInstance(throwableClass, ASSERTION_FAILED_CLASS_NAME) ||
isInstance(throwableClass, OPENTEST4J_ASSERTION);
}
public static boolean isComparisonFailure(Class<?> aClass) {
if (aClass == null) return false;
final String throwableClassName = aClass.getName();
if (JUNIT_3_COMPARISON_FAILURE.equals(throwableClassName)) {
return true;
}
if (JUNIT_4_COMPARISON_FAILURE.equals(throwableClassName)) {
return true;
}
if (OPENTEST4J_ASSERTION.equals(throwableClassName)) {
return true;
}
return isComparisonFailure(aClass.getSuperclass());
return isInstance(aClass, JUNIT_3_COMPARISON_FAILURE) ||
isInstance(aClass, JUNIT_4_COMPARISON_FAILURE) ||
isInstance(aClass, OPENTEST4J_ASSERTION);
}
public String getExpectedFilePath() {
@@ -257,7 +249,7 @@ public class ComparisonFailureData {
private static ComparisonFailureData createOpentest4jAssertion(Throwable assertion) {
try {
if (OPENTEST4J_ASSERTION.equals(assertion.getClass().getName())) {
if (isInstance(assertion.getClass(), OPENTEST4J_ASSERTION)) {
Method isExpectedDefinedMethod = assertion.getClass().getDeclaredMethod("isExpectedDefined");
Method isActualDefinedMethod = assertion.getClass().getDeclaredMethod("isActualDefined");
boolean isExpectedDefined = ((Boolean)isExpectedDefinedMethod.invoke(assertion)).booleanValue();
@@ -281,10 +273,10 @@ public class ComparisonFailureData {
private static AssertionValue getOpentest4jAssertionValue(Object valueWrapper)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
if (OPENTEST4J_VALUE_WRAPPER.equals(valueWrapper.getClass().getName())) {
if (isInstance(valueWrapper.getClass(), OPENTEST4J_VALUE_WRAPPER)) {
Method valueMethod = valueWrapper.getClass().getDeclaredMethod("getValue");
Object value = valueMethod.invoke(valueWrapper);
if (value != null && OPENTEST4J_FILE_INFO.equals(value.getClass().getName())) {
if (value != null && isInstance(value.getClass(), OPENTEST4J_FILE_INFO)) {
Method contentAsStringMethod = value.getClass().getDeclaredMethod("getContentsAsString", Charset.class);
String valueString = (String)contentAsStringMethod.invoke(value, OPENTEST4J_FILE_CONTENT_CHARSET);
Method pathMethod = value.getClass().getDeclaredMethod("getPath");

View File

@@ -3,7 +3,6 @@ package com.intellij.junit5;
import com.intellij.junit4.ExpectedPatterns;
import com.intellij.rt.execution.junit.ComparisonFailureData;
import com.intellij.rt.execution.junit.ComparisonFailureData.AssertionValue;
import com.intellij.rt.execution.junit.MapSerializerUtil;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.engine.TestSource;
@@ -16,10 +15,7 @@ import org.junit.platform.engine.support.descriptor.MethodSource;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
import org.opentest4j.AssertionFailedError;
import org.opentest4j.FileInfo;
import org.opentest4j.MultipleFailuresError;
import org.opentest4j.ValueWrapper;
import java.io.File;
import java.io.PrintStream;
@@ -28,8 +24,6 @@ import java.io.StringWriter;
import java.util.*;
import static com.intellij.rt.execution.TestListenerProtocol.CLASS_CONFIGURATION;
import static com.intellij.rt.execution.junit.ComparisonFailureData.OPENTEST4J_FILE_CONTENT_CHARSET;
import static com.intellij.rt.execution.junit.ComparisonFailureData.OPENTEST4J_FILE_INFO;
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public class JUnit5TestExecutionListener implements TestExecutionListener {
@@ -266,13 +260,7 @@ public class JUnit5TestExecutionListener implements TestExecutionListener {
testFailure(methodName, id, parentId, messageName, assertionError, duration, reason, true);
}
}
else if (ex instanceof AssertionFailedError &&
((AssertionFailedError)ex).isActualDefined() &&
((AssertionFailedError)ex).isExpectedDefined()) {
failureData = createOpentest4jAssertion((AssertionFailedError)ex);
}
else {
//try to detect failure with junit 4 if present in the classpath
try {
failureData = ExpectedPatterns.createExceptionNotification(ex);
}
@@ -444,25 +432,4 @@ public class JUnit5TestExecutionListener implements TestExecutionListener {
return null;
}).orElse(null);
}
private static ComparisonFailureData createOpentest4jAssertion(AssertionFailedError assertion) {
ValueWrapper expectedValueWrapper = assertion.getExpected();
ValueWrapper actualValueWrapper = assertion.getActual();
AssertionValue expected = getOpentest4jAssertionValue(expectedValueWrapper);
AssertionValue actual = getOpentest4jAssertionValue(actualValueWrapper);
return new ComparisonFailureData(expected.text, actual.text, expected.path, actual.path);
}
private static AssertionValue getOpentest4jAssertionValue(ValueWrapper valueWrapper) {
Object value = valueWrapper.getValue();
if (value != null && OPENTEST4J_FILE_INFO.equals(value.getClass().getName())) {
String valueString = ((FileInfo)value).getContentsAsString(OPENTEST4J_FILE_CONTENT_CHARSET);
String valuePath = ((FileInfo)value).getPath();
return new AssertionValue(valueString, valuePath);
}
else {
String valueString = valueWrapper.getStringRepresentation();
return new AssertionValue(valueString, null);
}
}
}