diff --git a/integration-tests/test-extension/tests/src/test/java/io/quarkus/it/extension/ParamsTest.java b/integration-tests/test-extension/tests/src/test/java/io/quarkus/it/extension/ParamsTest.java index 8460db8b12324..b211657c3838f 100644 --- a/integration-tests/test-extension/tests/src/test/java/io/quarkus/it/extension/ParamsTest.java +++ b/integration-tests/test-extension/tests/src/test/java/io/quarkus/it/extension/ParamsTest.java @@ -3,6 +3,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Stream; @@ -119,6 +120,15 @@ static List testDataListArguments() { return Arrays.asList(Arguments.of(new TestData(), "foo"), Arguments.of(new TestData(), "foo")); } + @ParameterizedTest + @MethodSource("testStreamOfMapEntryArguments") + public void methodList(Map.Entry ignore) { + } + + static Stream> testStreamOfMapEntryArguments() { + return Map.of("a", "b").entrySet().stream(); + } + @SuppressWarnings("unused") static class TestData { final List foo = Arrays.asList("one", "two", "three"); diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/internal/CustomMapEntryConverter.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/internal/CustomMapEntryConverter.java new file mode 100644 index 0000000000000..f20a7fe3e3f36 --- /dev/null +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/internal/CustomMapEntryConverter.java @@ -0,0 +1,55 @@ +package io.quarkus.test.junit.internal; + +import java.util.AbstractMap; +import java.util.Map; +import java.util.Set; + +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.converters.collections.MapConverter; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.mapper.Mapper; + +/** + * A custom Map.Entry converter that always uses AbstractMap.SimpleEntry for unmarshalling. + * This is probably not semantically correct 100% of the time, but it's likely fine + * for all the cases where we are using marshalling / unmarshalling. + * + * The reason for doing this is to avoid XStream causing illegal access issues + * for internal JDK types + */ +@SuppressWarnings({ "rawtypes", "unchecked" }) +public class CustomMapEntryConverter extends MapConverter { + + private final Set SUPPORTED_CLASS_NAMES = Set + .of(Map.entry(Integer.MAX_VALUE, Integer.MAX_VALUE).getClass().getName()); + + public CustomMapEntryConverter(Mapper mapper) { + super(mapper); + } + + @Override + public boolean canConvert(Class type) { + return (type != null) && SUPPORTED_CLASS_NAMES.contains(type.getName()); + } + + @Override + public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { + var entryName = mapper().serializedClass(Map.Entry.class); + var entry = (Map.Entry) source; + writer.startNode(entryName); + writeCompleteItem(entry.getKey(), context, writer); + writeCompleteItem(entry.getValue(), context, writer); + writer.endNode(); + } + + @Override + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + reader.moveDown(); + var key = readCompleteItem(reader, context, null); + var value = readCompleteItem(reader, context, null); + reader.moveUp(); + return new AbstractMap.SimpleEntry(key, value); + } +} diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/internal/XStreamDeepClone.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/internal/XStreamDeepClone.java index 23aba9ec4ace3..0c99bb7e35ff1 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/internal/XStreamDeepClone.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/internal/XStreamDeepClone.java @@ -20,6 +20,7 @@ class XStreamDeepClone implements DeepClone { result.registerConverter(new CustomListConverter(result.getMapper())); result.registerConverter(new CustomSetConverter(result.getMapper())); result.registerConverter(new CustomMapConverter(result.getMapper())); + result.registerConverter(new CustomMapEntryConverter(result.getMapper())); return result; }; }