diff --git a/pom.xml b/pom.xml
index 40fefb9064..fc72b1b248 100644
--- a/pom.xml
+++ b/pom.xml
@@ -154,6 +154,22 @@
${version.mockito}
test
+
+
+
+ org.junit.platform
+ junit-platform-suite-engine
+ 1.10.2
+ test
+
+
+ io.micronaut.test
+ micronaut-test-type-pollution
+ 4.6.2
+ test
+
@@ -386,6 +403,19 @@
--add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED
+
+
+ type-pollution-test
+ test
+
+ test
+
+
+ com.fasterxml.jackson.databind.typepollution.TypePollutionSuite
+ 1
+
+
+
diff --git a/src/test-jdk17/java/com/fasterxml/jackson/databind/typepollution/TypePollutionSuite.java b/src/test-jdk17/java/com/fasterxml/jackson/databind/typepollution/TypePollutionSuite.java
new file mode 100644
index 0000000000..beb05ab08e
--- /dev/null
+++ b/src/test-jdk17/java/com/fasterxml/jackson/databind/typepollution/TypePollutionSuite.java
@@ -0,0 +1,9 @@
+package com.fasterxml.jackson.databind.typepollution;
+
+import org.junit.platform.suite.api.SelectPackages;
+import org.junit.platform.suite.api.Suite;
+
+@Suite
+@SelectPackages("com.fasterxml.jackson.databind.typepollution")
+public class TypePollutionSuite {
+}
diff --git a/src/test-jdk17/java/com/fasterxml/jackson/databind/typepollution/TypePollutionTest.java b/src/test-jdk17/java/com/fasterxml/jackson/databind/typepollution/TypePollutionTest.java
new file mode 100644
index 0000000000..cf0972470e
--- /dev/null
+++ b/src/test-jdk17/java/com/fasterxml/jackson/databind/typepollution/TypePollutionTest.java
@@ -0,0 +1,91 @@
+package com.fasterxml.jackson.databind.typepollution;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import io.micronaut.test.typepollution.FocusListener;
+import io.micronaut.test.typepollution.ThresholdFocusListener;
+import io.micronaut.test.typepollution.TypePollutionTransformer;
+import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.function.Executable;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+
+public class TypePollutionTest {
+ private static final int THRESHOLD = 1000;
+ private ThresholdFocusListener focusListener;
+
+ @BeforeAll
+ static void setupAgent() {
+ TypePollutionTransformer.install(net.bytebuddy.agent.ByteBuddyAgent.install());
+ }
+
+ @BeforeEach
+ void setUp() {
+ focusListener = new ThresholdFocusListener();
+ FocusListener.setFocusListener(focusListener);
+ }
+
+ @AfterEach
+ void verifyNoTypeThrashing() {
+ FocusListener.setFocusListener(null);
+ Assertions.assertTrue(focusListener.checkThresholds(THRESHOLD), "Threshold exceeded, check logs.");
+ }
+
+ private void doTest(Executable r) throws Throwable {
+ for (int i = 0; i < THRESHOLD * 2; i++) {
+ r.execute();
+ }
+ }
+
+ @Test
+ @Disabled
+ public void sample() throws Throwable {
+ // example test. If you enable this, it will fail, and you can see what a type pollution error looks like.
+
+ interface A {
+ }
+
+ interface B {
+ }
+
+ class Concrete implements A, B {
+ }
+
+ Object c = new Concrete();
+ AtomicInteger j = new AtomicInteger();
+ doTest(() -> {
+ if (c instanceof A) {
+ j.incrementAndGet();
+ }
+ if (c instanceof B) {
+ j.incrementAndGet();
+ }
+ });
+ System.out.println(j);
+ }
+
+ @Test
+ public void deserializeRecordWithList() throws Throwable {
+ ObjectMapper mapper = JsonMapper.builder().build();
+ ListRecord input = new ListRecord(List.of("foo"));
+ String json = mapper.writeValueAsString(input);
+ doTest(() -> Assertions.assertEquals(input, mapper.readValue(json, ListRecord.class)));
+ }
+
+ record ListRecord(List list) {
+ }
+
+ @Test
+ public void deserializeRecordWithSet() throws Throwable {
+ ObjectMapper mapper = JsonMapper.builder().build();
+ SetRecord input = new SetRecord(Set.of("foo"));
+ String json = mapper.writeValueAsString(input);
+ doTest(() -> Assertions.assertEquals(input, mapper.readValue(json, SetRecord.class)));
+ }
+
+ record SetRecord(Set list) {
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/PrimarySuite.java b/src/test/java/com/fasterxml/jackson/databind/PrimarySuite.java
new file mode 100644
index 0000000000..5bcfc4f65d
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/PrimarySuite.java
@@ -0,0 +1,15 @@
+package com.fasterxml.jackson.databind;
+
+import org.junit.platform.suite.api.ExcludeClassNamePatterns;
+import org.junit.platform.suite.api.ExcludePackages;
+import org.junit.platform.suite.api.SelectPackages;
+import org.junit.platform.suite.api.Suite;
+
+@Suite
+@SelectPackages("com.fasterxml.jackson.databind")
+@ExcludePackages("com.fasterxml.jackson.databind.typepollution")
+@ExcludeClassNamePatterns({
+ "com\\.fasterxml\\.jackson\\.databind\\.MapperFootprintTest"
+})
+public class PrimarySuite {
+}