1 /* 2 * Copyright (C) 2008 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import com.google.common.annotations.GwtCompatible; 20 import com.google.common.base.Function; 21 import com.google.common.base.Functions; 22 import com.google.common.collect.testing.MapInterfaceTest; 23 import java.util.Collection; 24 import java.util.Iterator; 25 import java.util.Map; 26 import java.util.Map.Entry; 27 import java.util.Set; 28 import org.checkerframework.checker.nullness.qual.Nullable; 29 30 /** 31 * Tests for {@link Maps#transformValues}. 32 * 33 * @author Isaac Shum 34 */ 35 @GwtCompatible 36 public class MapsTransformValuesTest extends MapInterfaceTest<String, String> { 37 38 /** 39 * Constructor that assigns {@code supportsIteratorRemove} the same value as {@code 40 * supportsRemove}. 41 */ MapsTransformValuesTest( boolean allowsNullKeys, boolean allowsNullValues, boolean supportsPut, boolean supportsRemove, boolean supportsClear)42 protected MapsTransformValuesTest( 43 boolean allowsNullKeys, 44 boolean allowsNullValues, 45 boolean supportsPut, 46 boolean supportsRemove, 47 boolean supportsClear) { 48 super( 49 allowsNullKeys, 50 allowsNullValues, 51 supportsPut, 52 supportsRemove, 53 supportsClear, 54 supportsRemove); 55 } 56 MapsTransformValuesTest()57 public MapsTransformValuesTest() { 58 super(false, true, false, true, true); 59 } 60 61 @Override makeEmptyMap()62 protected Map<String, String> makeEmptyMap() { 63 return Maps.transformValues(Maps.<String, String>newHashMap(), Functions.<String>identity()); 64 } 65 66 @Override makePopulatedMap()67 protected Map<String, String> makePopulatedMap() { 68 Map<String, Integer> underlying = Maps.newHashMap(); 69 underlying.put("a", 1); 70 underlying.put("b", 2); 71 underlying.put("c", 3); 72 return Maps.transformValues(underlying, Functions.toStringFunction()); 73 } 74 75 @Override getKeyNotInPopulatedMap()76 protected String getKeyNotInPopulatedMap() throws UnsupportedOperationException { 77 return "z"; 78 } 79 80 @Override getValueNotInPopulatedMap()81 protected String getValueNotInPopulatedMap() throws UnsupportedOperationException { 82 return "26"; 83 } 84 85 /** Helper assertion comparing two maps */ assertMapsEqual(Map<?, ?> expected, Map<?, ?> map)86 private void assertMapsEqual(Map<?, ?> expected, Map<?, ?> map) { 87 assertEquals(expected, map); 88 assertEquals(expected.hashCode(), map.hashCode()); 89 assertEquals(expected.entrySet(), map.entrySet()); 90 91 // Assert that expectedValues > mapValues and that 92 // mapValues > expectedValues; i.e. that expectedValues == mapValues. 93 Collection<?> expectedValues = expected.values(); 94 Collection<?> mapValues = map.values(); 95 assertEquals(expectedValues.size(), mapValues.size()); 96 assertTrue(expectedValues.containsAll(mapValues)); 97 assertTrue(mapValues.containsAll(expectedValues)); 98 } 99 testTransformEmptyMapEquality()100 public void testTransformEmptyMapEquality() { 101 Map<String, String> map = 102 Maps.transformValues(ImmutableMap.<String, Integer>of(), Functions.toStringFunction()); 103 assertMapsEqual(Maps.newHashMap(), map); 104 } 105 testTransformSingletonMapEquality()106 public void testTransformSingletonMapEquality() { 107 Map<String, String> map = 108 Maps.transformValues(ImmutableMap.of("a", 1), Functions.toStringFunction()); 109 Map<String, String> expected = ImmutableMap.of("a", "1"); 110 assertMapsEqual(expected, map); 111 assertEquals(expected.get("a"), map.get("a")); 112 } 113 testTransformIdentityFunctionEquality()114 public void testTransformIdentityFunctionEquality() { 115 Map<String, Integer> underlying = ImmutableMap.of("a", 1); 116 Map<String, Integer> map = Maps.transformValues(underlying, Functions.<Integer>identity()); 117 assertMapsEqual(underlying, map); 118 } 119 testTransformPutEntryIsUnsupported()120 public void testTransformPutEntryIsUnsupported() { 121 Map<String, String> map = 122 Maps.transformValues(ImmutableMap.of("a", 1), Functions.toStringFunction()); 123 try { 124 map.put("b", "2"); 125 fail(); 126 } catch (UnsupportedOperationException expected) { 127 } 128 129 try { 130 map.putAll(ImmutableMap.of("b", "2")); 131 fail(); 132 } catch (UnsupportedOperationException expected) { 133 } 134 135 try { 136 map.entrySet().iterator().next().setValue("one"); 137 fail(); 138 } catch (UnsupportedOperationException expected) { 139 } 140 } 141 testTransformRemoveEntry()142 public void testTransformRemoveEntry() { 143 Map<String, Integer> underlying = Maps.newHashMap(); 144 underlying.put("a", 1); 145 Map<String, String> map = Maps.transformValues(underlying, Functions.toStringFunction()); 146 assertEquals("1", map.remove("a")); 147 assertNull(map.remove("b")); 148 } 149 testTransformEqualityOfMapsWithNullValues()150 public void testTransformEqualityOfMapsWithNullValues() { 151 Map<String, String> underlying = Maps.newHashMap(); 152 underlying.put("a", null); 153 underlying.put("b", ""); 154 155 Map<String, Boolean> map = 156 Maps.transformValues( 157 underlying, 158 new Function<String, Boolean>() { 159 @Override 160 public Boolean apply(@Nullable String from) { 161 return from == null; 162 } 163 }); 164 Map<String, Boolean> expected = ImmutableMap.of("a", true, "b", false); 165 assertMapsEqual(expected, map); 166 assertEquals(expected.get("a"), map.get("a")); 167 assertEquals(expected.containsKey("a"), map.containsKey("a")); 168 assertEquals(expected.get("b"), map.get("b")); 169 assertEquals(expected.containsKey("b"), map.containsKey("b")); 170 assertEquals(expected.get("c"), map.get("c")); 171 assertEquals(expected.containsKey("c"), map.containsKey("c")); 172 } 173 testTransformReflectsUnderlyingMap()174 public void testTransformReflectsUnderlyingMap() { 175 Map<String, Integer> underlying = Maps.newHashMap(); 176 underlying.put("a", 1); 177 underlying.put("b", 2); 178 underlying.put("c", 3); 179 Map<String, String> map = Maps.transformValues(underlying, Functions.toStringFunction()); 180 assertEquals(underlying.size(), map.size()); 181 182 underlying.put("d", 4); 183 assertEquals(underlying.size(), map.size()); 184 assertEquals("4", map.get("d")); 185 186 underlying.remove("c"); 187 assertEquals(underlying.size(), map.size()); 188 assertFalse(map.containsKey("c")); 189 190 underlying.clear(); 191 assertEquals(underlying.size(), map.size()); 192 } 193 testTransformChangesAreReflectedInUnderlyingMap()194 public void testTransformChangesAreReflectedInUnderlyingMap() { 195 Map<String, Integer> underlying = Maps.newLinkedHashMap(); 196 underlying.put("a", 1); 197 underlying.put("b", 2); 198 underlying.put("c", 3); 199 underlying.put("d", 4); 200 underlying.put("e", 5); 201 underlying.put("f", 6); 202 underlying.put("g", 7); 203 Map<String, String> map = Maps.transformValues(underlying, Functions.toStringFunction()); 204 205 map.remove("a"); 206 assertFalse(underlying.containsKey("a")); 207 208 Set<String> keys = map.keySet(); 209 keys.remove("b"); 210 assertFalse(underlying.containsKey("b")); 211 212 Iterator<String> keyIterator = keys.iterator(); 213 keyIterator.next(); 214 keyIterator.remove(); 215 assertFalse(underlying.containsKey("c")); 216 217 Collection<String> values = map.values(); 218 values.remove("4"); 219 assertFalse(underlying.containsKey("d")); 220 221 Iterator<String> valueIterator = values.iterator(); 222 valueIterator.next(); 223 valueIterator.remove(); 224 assertFalse(underlying.containsKey("e")); 225 226 Set<Entry<String, String>> entries = map.entrySet(); 227 Entry<String, String> firstEntry = entries.iterator().next(); 228 entries.remove(firstEntry); 229 assertFalse(underlying.containsKey("f")); 230 231 Iterator<Entry<String, String>> entryIterator = entries.iterator(); 232 entryIterator.next(); 233 entryIterator.remove(); 234 assertFalse(underlying.containsKey("g")); 235 236 assertTrue(underlying.isEmpty()); 237 assertTrue(map.isEmpty()); 238 assertTrue(keys.isEmpty()); 239 assertTrue(values.isEmpty()); 240 assertTrue(entries.isEmpty()); 241 } 242 testTransformEquals()243 public void testTransformEquals() { 244 Map<String, Integer> underlying = ImmutableMap.of("a", 0, "b", 1, "c", 2); 245 Map<String, Integer> expected = Maps.transformValues(underlying, Functions.<Integer>identity()); 246 247 assertMapsEqual(expected, expected); 248 249 Map<String, Integer> equalToUnderlying = Maps.newTreeMap(); 250 equalToUnderlying.putAll(underlying); 251 Map<String, Integer> map = 252 Maps.transformValues(equalToUnderlying, Functions.<Integer>identity()); 253 assertMapsEqual(expected, map); 254 255 map = 256 Maps.transformValues( 257 ImmutableMap.of("a", 1, "b", 2, "c", 3), 258 new Function<Integer, Integer>() { 259 @Override 260 public Integer apply(Integer from) { 261 return from - 1; 262 } 263 }); 264 assertMapsEqual(expected, map); 265 } 266 testTransformEntrySetContains()267 public void testTransformEntrySetContains() { 268 Map<String, Boolean> underlying = Maps.newHashMap(); 269 underlying.put("a", null); 270 underlying.put("b", true); 271 underlying.put(null, true); 272 273 Map<String, Boolean> map = 274 Maps.transformValues( 275 underlying, 276 new Function<Boolean, Boolean>() { 277 @Override 278 public Boolean apply(@Nullable Boolean from) { 279 return (from == null) ? true : null; 280 } 281 }); 282 283 Set<Entry<String, Boolean>> entries = map.entrySet(); 284 assertTrue(entries.contains(Maps.immutableEntry("a", true))); 285 assertTrue(entries.contains(Maps.immutableEntry("b", (Boolean) null))); 286 assertTrue(entries.contains(Maps.immutableEntry((String) null, (Boolean) null))); 287 288 assertFalse(entries.contains(Maps.immutableEntry("c", (Boolean) null))); 289 assertFalse(entries.contains(Maps.immutableEntry((String) null, true))); 290 } 291 292 @Override testKeySetRemoveAllNullFromEmpty()293 public void testKeySetRemoveAllNullFromEmpty() { 294 try { 295 super.testKeySetRemoveAllNullFromEmpty(); 296 } catch (RuntimeException tolerated) { 297 // GWT's HashMap.keySet().removeAll(null) doesn't throws NPE. 298 } 299 } 300 301 @Override testEntrySetRemoveAllNullFromEmpty()302 public void testEntrySetRemoveAllNullFromEmpty() { 303 try { 304 super.testEntrySetRemoveAllNullFromEmpty(); 305 } catch (RuntimeException tolerated) { 306 // GWT's HashMap.entrySet().removeAll(null) doesn't throws NPE. 307 } 308 } 309 } 310