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 ac9999ff1fbe..325c76ad64ea 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; @@ -34,6 +35,8 @@ import static org.assertj.core.api.Assertions.assertThat; /** + * Tests for {@link CollectionUtils}. + * * @author Rob Harrop * @author Juergen Hoeller * @author Rick Evans @@ -211,6 +214,30 @@ 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/MultiValueMapTests.java b/spring-core/src/test/java/org/springframework/util/MultiValueMapTests.java new file mode 100644 index 000000000000..0f7128fbf2e4 --- /dev/null +++ b/spring-core/src/test/java/org/springframework/util/MultiValueMapTests.java @@ -0,0 +1,198 @@ +/* + * Copyright 2002-2023 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 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 org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link MultiValueMap}. + * + * @author Mihai Dumitrescu + * @author Arjen Poutsma + * @author Juergen Hoeller + * @author Stephane Nicoll + */ +class MultiValueMapTests { + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void add(MultiValueMap map) { + int initialSize = map.size(); + map.add("key", "value1"); + map.add("key", "value2"); + assertThat(map).hasSize(initialSize + 1); + assertThat(map.get("key")).containsExactly("value1", "value2"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void addIfAbsentWhenAbsent(MultiValueMap map) { + map.addIfAbsent("key", "value1"); + assertThat(map.get("key")).containsExactly("value1"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void addIfAbsentWhenPresent(MultiValueMap map) { + map.add("key", "value1"); + map.addIfAbsent("key", "value2"); + assertThat(map.get("key")).containsExactly("value1"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void set(MultiValueMap map) { + map.set("key", "value1"); + map.set("key", "value2"); + assertThat(map.get("key")).containsExactly("value2"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void addAll(MultiValueMap map) { + int initialSize = map.size(); + map.add("key", "value1"); + map.addAll("key", Arrays.asList("value2", "value3")); + assertThat(map).hasSize(initialSize + 1); + assertThat(map.get("key")).containsExactly("value1", "value2", "value3"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void addAllWithEmptyList(MultiValueMap map) { + int initialSize = map.size(); + map.addAll("key", Collections.emptyList()); + assertThat(map).hasSize(initialSize + 1); + assertThat(map.get("key")).isEmpty(); + assertThat(map.getFirst("key")).isNull(); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void getFirst(MultiValueMap map) { + List values = List.of("value1", "value2"); + map.put("key", values); + assertThat(map.getFirst("key")).isEqualTo("value1"); + assertThat(map.getFirst("other")).isNull(); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void toSingleValueMap(MultiValueMap map) { + int initialSize = map.size(); + List values = List.of("value1", "value2"); + map.put("key", values); + Map singleValueMap = map.toSingleValueMap(); + assertThat(singleValueMap).hasSize(initialSize + 1); + assertThat(singleValueMap.get("key")).isEqualTo("value1"); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void toSingleValueMapWithEmptyList(MultiValueMap map) { + int initialSize = map.size(); + map.put("key", Collections.emptyList()); + Map singleValueMap = map.toSingleValueMap(); + assertThat(singleValueMap).hasSize(initialSize); + assertThat(singleValueMap.get("key")).isNull(); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void equalsOnExistingValues(MultiValueMap map) { + map.clear(); + map.set("key1", "value1"); + assertThat(map).isEqualTo(map); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void equalsOnEmpty(MultiValueMap map) { + map.clear(); + map.set("key1", "value1"); + MultiValueMap o1 = new LinkedMultiValueMap<>(); + o1.set("key1", "value1"); + assertThat(o1).isEqualTo(map); + assertThat(map).isEqualTo(o1); + Map> o2 = new HashMap<>(); + o2.put("key1", Collections.singletonList("value1")); + assertThat(o2).isEqualTo(map); + assertThat(map).isEqualTo(o2); + } + + @ParameterizedTest + @MethodSource("objectsUnderTest") + void canNotChangeAnUnmodifiableMultiValueMap(MultiValueMap map) { + MultiValueMap asUnmodifiableMultiValueMap = CollectionUtils.unmodifiableMultiValueMap(map); + 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"))); + + } + + private List exampleListOfValues() { + return List.of("value1", "value2"); + } + + private Map exampleHashMap() { + return Map.of("key2", "key2.value1"); + } + + private MultiValueMap exampleMultiValueMap() { + LinkedMultiValueMap map = new LinkedMultiValueMap<>(); + map.put("key1", Arrays.asList("key1.value1", "key1.value2")); + return map; + } + + static Stream> objectsUnderTest() { + return Stream.of(new LinkedMultiValueMap<>(), new LinkedMultiValueMap<>(new HashMap<>()), + new LinkedMultiValueMap<>(new LinkedHashMap<>()), + new LinkedMultiValueMap<>(Map.of("existingkey", Arrays.asList("existingvalue1", "existingvalue2"))), + CollectionUtils.toMultiValueMap(new HashMap<>())); + } + +}