diff --git a/src/test-jdk17/java/com/fasterxml/jackson/databind/failing/RecordUpdate3079FailingTest.java b/src/test-jdk17/java/com/fasterxml/jackson/databind/failing/RecordUpdate3079FailingTest.java deleted file mode 100644 index de24fe331a..0000000000 --- a/src/test-jdk17/java/com/fasterxml/jackson/databind/failing/RecordUpdate3079FailingTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.fasterxml.jackson.databind.failing; - -import java.util.Collections; - -import org.junit.jupiter.api.Test; - -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.databind.records.RecordUpdate3079Test; -import com.fasterxml.jackson.databind.testutil.DatabindTestUtil; - -import static org.junit.jupiter.api.Assertions.*; - -// 01-Dec-2022, tatu: Alas, fails on JDK 17 -// see related passing test in RecordUpdate3079Test -public class RecordUpdate3079FailingTest extends DatabindTestUtil -{ - private final ObjectMapper MAPPER = newJsonMapper(); - - // [databind#3079]: Should be able to Record value directly - @Test - public void testDirectRecordUpdate() throws Exception - { - RecordUpdate3079Test.IdNameRecord orig = new RecordUpdate3079Test.IdNameRecord(123, "Bob"); - RecordUpdate3079Test.IdNameRecord result = MAPPER.updateValue(orig, - Collections.singletonMap("id", 137)); - assertNotNull(result); - assertEquals(137, result.id()); - assertEquals("Bob", result.name()); - assertNotSame(orig, result); - } -} diff --git a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordUpdate3079Test.java b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordUpdate3079Test.java index 68647cddbe..e96ff2219d 100644 --- a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordUpdate3079Test.java +++ b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/RecordUpdate3079Test.java @@ -2,8 +2,11 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.testutil.DatabindTestUtil; +import com.fasterxml.jackson.databind.testutil.Failing; import org.junit.jupiter.api.Test; +import java.util.Collections; + import static org.junit.jupiter.api.Assertions.*; @@ -36,4 +39,17 @@ public void testRecordAsPropertyUpdate() throws Exception assertSame(orig, result); assertNotSame(origRecord, result.value); } + + @Failing // 01-Dec-2022, tatu: Alas, fails on JDK 17 + // [databind#3079]: Should be able to Record value directly + @Test + public void testDirectRecordUpdate() throws Exception { + RecordUpdate3079Test.IdNameRecord orig = new RecordUpdate3079Test.IdNameRecord(123, "Bob"); + RecordUpdate3079Test.IdNameRecord result = MAPPER.updateValue(orig, + Collections.singletonMap("id", 137)); + assertNotNull(result); + assertEquals(137, result.id()); + assertEquals("Bob", result.name()); + assertNotSame(orig, result); + } } diff --git a/src/test/java/com/fasterxml/jackson/databind/testutil/Failing.java b/src/test/java/com/fasterxml/jackson/databind/testutil/Failing.java new file mode 100644 index 0000000000..ab79e277cf --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/testutil/Failing.java @@ -0,0 +1,89 @@ +package com.fasterxml.jackson.databind.testutil; + +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; +import org.opentest4j.TestAbortedException; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@ExtendWith(Failing.FailingExtension.class) // Comment this out if you want to temporarily let the tests actually fail +public @interface Failing { + + /** + * For when a test is failing only when running on specific Java version - e.g. Java 8 & Java 11 - but passing + * for other versions, then: + *
+ * {@code @}Failing(javaVersion = { "1.8", "11" }
+ * {@code @}Test
+ * public void test...() { ... }
+ *
+ */
+ String[] javaVersion() default {};
+
+ class FailingExtension implements BeforeEachCallback, TestExecutionExceptionHandler, AfterEachCallback {
+
+ private static final String SHOULD_FAIL = "should fail";
+
+ @Override
+ public void beforeEach(ExtensionContext context) {
+ getStore(context).put(SHOULD_FAIL, matchesFailingJavaVersion(context));
+ }
+
+ @Override
+ public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable {
+ boolean shouldFail = getStore(context).get(SHOULD_FAIL, boolean.class);
+ if (!shouldFail) {
+ // the test threw exception even though it's not expected to fail for this test method, let the
+ // it fail with this exception so maintainers can investigate
+ throw throwable;
+ }
+
+ // Instead of swallowing the exception and silently passing, better to mark the test as "aborted"
+ throw new TestAbortedException("Not implemented/fixed yet", throwable);
+ }
+
+ @Override
+ public void afterEach(ExtensionContext context) {
+ boolean shouldFail = getStore(context).get(SHOULD_FAIL, boolean.class);
+ boolean testFailed = context.getExecutionException().isPresent();
+
+ if (shouldFail && !testFailed) {
+ throw new RuntimeException("Test that has been failing is now passing!");
+ }
+ }
+
+ private ExtensionContext.Store getStore(ExtensionContext context) {
+ return context.getStore(ExtensionContext.Namespace.create(getClass(), context.getRequiredTestMethod()));
+ }
+
+ private boolean matchesFailingJavaVersion(ExtensionContext context) {
+ Method method = context.getTestMethod()
+ // should not happen because @Failing can only be annotated on test methods!
+ .orElseThrow(() -> new IllegalArgumentException("Cannot get test method!"));
+
+ String currentJavaVersion = System.getProperty("java.version");
+ String[] failingJavaVersions = method.getAnnotation(Failing.class).javaVersion();
+
+ if (failingJavaVersions.length == 0) { // failing for all Java versions
+ return true;
+ }
+ for (String version : failingJavaVersions) {
+ if (currentJavaVersion.startsWith(version)) {
+ return true;
+ }
+ }
+ return false; // not expected to fail for the current Java version
+ }
+ }
+}