diff --git a/spring-core/src/test/java/org/springframework/util/CollectionUtilsTests.java b/spring-core/src/test/java/org/springframework/util/CollectionUtilsTests.java index fa781881b0b5..45efbeea5e37 100644 --- a/spring-core/src/test/java/org/springframework/util/CollectionUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/CollectionUtilsTests.java @@ -17,6 +17,7 @@ package org.springframework.util; import java.util.ArrayList; +import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -210,6 +211,31 @@ void hasUniqueObject() { assertThat(CollectionUtils.hasUniqueObject(list)).isFalse(); } + @Test + void conversionOfEmptyMap() { + MultiValueMap> asMultiValueMap = CollectionUtils.toMultiValueMap(new HashMap<>()); + assertThat(asMultiValueMap.isEmpty()).isTrue(); + assertThat(asMultiValueMap).isEmpty(); + } + + @Test + void conversionOfNonEmptyMap() { + Map> wrapped = new HashMap<>(); + wrapped.put("key", Arrays.asList("first", "second")); + MultiValueMap asMultiValueMap = CollectionUtils.toMultiValueMap(wrapped); + assertThat(asMultiValueMap).containsAllEntriesOf(wrapped); + } + + @Test + void changesValueByReference() { + Map> wrapped = new HashMap<>(); + MultiValueMap asMultiValueMap = CollectionUtils.toMultiValueMap(wrapped); + assertThat(asMultiValueMap).doesNotContainKeys("key"); + wrapped.put("key", new ArrayList<>()); + + assertThat(asMultiValueMap).containsKey("key"); + } + private static final class Instance { diff --git a/spring-core/src/test/java/org/springframework/util/MultiValueMapRelatedTests.java b/spring-core/src/test/java/org/springframework/util/MultiValueMapRelatedTests.java new file mode 100644 index 000000000000..686d77a1a2d5 --- /dev/null +++ b/spring-core/src/test/java/org/springframework/util/MultiValueMapRelatedTests.java @@ -0,0 +1,214 @@ +/* + * Copyright 2002-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.util; + +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Mihai Dumitrescu + * @author Arjen Poutsma + * @author Juergen Hoeller + */ +class MultiValueMapRelatedTests { + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void add(MultiValueMap objectUnderTest) { + int startingSize = objectUnderTest.size(); + objectUnderTest.add("key", "value1"); + objectUnderTest.add("key", "value2"); + assertThat(objectUnderTest).hasSize(startingSize + 1); + assertThat(objectUnderTest.get("key")).containsExactly("value1", "value2"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void addIfAbsentWhenAbsent(MultiValueMap objectUnderTest) { + objectUnderTest.addIfAbsent("key", "value1"); + assertThat(objectUnderTest.get("key")).containsExactly("value1"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void addIfAbsentWhenPresent(MultiValueMap objectUnderTest) { + objectUnderTest.add("key", "value1"); + objectUnderTest.addIfAbsent("key", "value2"); + assertThat(objectUnderTest.get("key")).containsExactly("value1"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void set(MultiValueMap objectUnderTest) { + objectUnderTest.set("key", "value1"); + objectUnderTest.set("key", "value2"); + assertThat(objectUnderTest.get("key")).containsExactly("value2"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void addAll(MultiValueMap objectUnderTest) { + int startingSize = objectUnderTest.size(); + + objectUnderTest.add("key", "value1"); + objectUnderTest.addAll("key", Arrays.asList("value2", "value3")); + assertThat(objectUnderTest).hasSize(startingSize + 1); + assertThat(objectUnderTest.get("key")).containsExactly("value1", "value2", "value3"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + @Disabled("to be fixed in gh-25140") + void addAllWithEmptyList(MultiValueMap objectUnderTest) { + objectUnderTest.addAll("key", Collections.emptyList()); + assertThat(objectUnderTest).hasSize(1); + assertThat(objectUnderTest.get("key")).isEmpty(); + assertThat(objectUnderTest.getFirst("key")).isNull(); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void getFirst(MultiValueMap objectUnderTest) { + List values = new ArrayList<>(2); + values.add("value1"); + values.add("value2"); + objectUnderTest.put("key", values); + assertThat(objectUnderTest.getFirst("key")).isEqualTo("value1"); + assertThat(objectUnderTest.getFirst("other")).isNull(); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void toSingleValueMap(MultiValueMap objectUnderTest) { + + int startingSize = objectUnderTest.size(); + + List values = new ArrayList<>(2); + values.add("value1"); + values.add("value2"); + objectUnderTest.put("key", values); + Map singleValueMap = objectUnderTest.toSingleValueMap(); + assertThat(singleValueMap).hasSize(startingSize + 1); + assertThat(singleValueMap.get("key")).isEqualTo("value1"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + @Disabled("to be fixed in gh-25140") + void toSingleValueMapWithEmptyList(MultiValueMap objectUnderTest) { + objectUnderTest.put("key", Collections.emptyList()); + Map singleValueMap = objectUnderTest.toSingleValueMap(); + assertThat(singleValueMap).isEmpty(); + assertThat(singleValueMap.get("key")).isNull(); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void equalsOnExistingValues(MultiValueMap objectUnderTest) { + objectUnderTest.clear(); + objectUnderTest.set("key1", "value1"); + assertThat(objectUnderTest).isEqualTo(objectUnderTest); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void equalsOnEmpty(MultiValueMap objectUnderTest) { + objectUnderTest.clear(); + objectUnderTest.set("key1", "value1"); + MultiValueMap o1 = new LinkedMultiValueMap<>(); + o1.set("key1", "value1"); + assertThat(o1).isEqualTo(objectUnderTest); + assertThat(objectUnderTest).isEqualTo(o1); + Map> o2 = new HashMap<>(); + o2.put("key1", Collections.singletonList("value1")); + assertThat(o2).isEqualTo(objectUnderTest); + assertThat(objectUnderTest).isEqualTo(o2); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void canNotChangeAnUnmodifiableMultiValueMap(MultiValueMap objectUnderTest) { + MultiValueMap asUnmodifiableMultiValueMap = CollectionUtils.unmodifiableMultiValueMap(objectUnderTest); + Assertions.assertAll( + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.add("key", "value")), + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.addIfAbsent("key", "value")), + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.addAll("key", exampleListOfValues())), + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.addAll(exampleMultiValueMap())), + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.set("key", "value")), + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.setAll(exampleHashMap())), + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.put("key", exampleListOfValues())), + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.putIfAbsent("key", exampleListOfValues())), + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.putAll(exampleMultiValueMap())), + () -> Assertions.assertThrows(UnsupportedOperationException.class, + () -> asUnmodifiableMultiValueMap.remove("key1")) + ); + + } + + @NotNull + private List exampleListOfValues() { + return Arrays.asList("value1", "value2"); + } + + @NotNull + private HashMap exampleHashMap() { + return new HashMap() {{ + put("key2", "key2.value1"); + }}; + } + + private MultiValueMap exampleMultiValueMap() { + return new LinkedMultiValueMap() {{ + put("key1", Arrays.asList("key1.value1", "key1.value2")); + }}; + } + + static Stream> objectsUnderTest() { + return Stream.of( + new LinkedMultiValueMap<>(), + new LinkedMultiValueMap<>(new HashMap<>()), + new LinkedMultiValueMap<>(new LinkedHashMap<>()), + new LinkedMultiValueMap<>(new HashMap>(){{ + put("existingkey", Arrays.asList("existingvalue1", "existingvalue2")); + }}), + CollectionUtils.toMultiValueMap(new HashMap<>())); + } + +}