1 /* 2 * Copyright (C) 2007 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 static com.google.common.collect.Maps.transformEntries; 20 import static com.google.common.collect.Maps.transformValues; 21 import static com.google.common.collect.Maps.unmodifiableNavigableMap; 22 import static com.google.common.collect.testing.Helpers.mapEntry; 23 import static com.google.common.truth.Truth.assertThat; 24 import static java.util.Arrays.asList; 25 26 import com.google.common.annotations.GwtCompatible; 27 import com.google.common.annotations.GwtIncompatible; 28 import com.google.common.base.Converter; 29 import com.google.common.base.Equivalence; 30 import com.google.common.base.Function; 31 import com.google.common.base.Functions; 32 import com.google.common.base.Predicate; 33 import com.google.common.base.Predicates; 34 import com.google.common.collect.Maps.EntryTransformer; 35 import com.google.common.collect.Maps.ValueDifferenceImpl; 36 import com.google.common.collect.SetsTest.Derived; 37 import com.google.common.testing.EqualsTester; 38 import com.google.common.testing.NullPointerTester; 39 import com.google.common.testing.SerializableTester; 40 41 import junit.framework.TestCase; 42 43 import java.io.IOException; 44 import java.io.StringReader; 45 import java.lang.reflect.Field; 46 import java.util.Arrays; 47 import java.util.Collection; 48 import java.util.Collections; 49 import java.util.Comparator; 50 import java.util.EnumMap; 51 import java.util.Enumeration; 52 import java.util.HashMap; 53 import java.util.IdentityHashMap; 54 import java.util.Iterator; 55 import java.util.LinkedHashMap; 56 import java.util.List; 57 import java.util.Map; 58 import java.util.Map.Entry; 59 import java.util.NavigableMap; 60 import java.util.NavigableSet; 61 import java.util.Properties; 62 import java.util.Set; 63 import java.util.SortedMap; 64 import java.util.SortedSet; 65 import java.util.TreeMap; 66 import java.util.concurrent.ConcurrentMap; 67 68 /** 69 * Unit test for {@code Maps}. 70 * 71 * @author Kevin Bourrillion 72 * @author Mike Bostock 73 * @author Jared Levy 74 */ 75 @GwtCompatible(emulated = true) 76 public class MapsTest extends TestCase { 77 78 private static final Comparator<Integer> SOME_COMPARATOR = 79 Collections.reverseOrder(); 80 testHashMap()81 public void testHashMap() { 82 HashMap<Integer, Integer> map = Maps.newHashMap(); 83 assertEquals(Collections.emptyMap(), map); 84 } 85 testHashMapWithInitialMap()86 public void testHashMapWithInitialMap() { 87 Map<String, Integer> original = new TreeMap<String, Integer>(); 88 original.put("a", 1); 89 original.put("b", 2); 90 original.put("c", 3); 91 HashMap<String, Integer> map = Maps.newHashMap(original); 92 assertEquals(original, map); 93 } 94 testHashMapGeneralizesTypes()95 public void testHashMapGeneralizesTypes() { 96 Map<String, Integer> original = new TreeMap<String, Integer>(); 97 original.put("a", 1); 98 original.put("b", 2); 99 original.put("c", 3); 100 HashMap<Object, Object> map = 101 Maps.newHashMap((Map<? extends Object, ? extends Object>) original); 102 assertEquals(original, map); 103 } 104 testCapacityForNegativeSizeFails()105 public void testCapacityForNegativeSizeFails() { 106 try { 107 Maps.capacity(-1); 108 fail("Negative expected size must result in IllegalArgumentException"); 109 } catch (IllegalArgumentException ex) { 110 } 111 } 112 113 /** 114 * Tests that nHMWES makes hash maps large enough that adding the expected 115 * number of elements won't cause a rehash. 116 * 117 * As of jdk7u40, HashMap has an empty-map optimization. The argument to 118 * new HashMap(int) is noted, but the initial table is a zero-length array. 119 * 120 * This test may fail miserably on non-OpenJDK environments... 121 */ 122 @GwtIncompatible("reflection") testNewHashMapWithExpectedSize_wontGrow()123 public void testNewHashMapWithExpectedSize_wontGrow() throws Exception { 124 // before jdk7u40: creates one-bucket table 125 // after jdk7u40: creates empty table 126 assertTrue(bucketsOf(Maps.newHashMapWithExpectedSize(0)) <= 1); 127 128 for (int size = 1; size < 200; size++) { 129 HashMap<Integer, Void> map1 = Maps.newHashMapWithExpectedSize(size); 130 131 // Only start measuring table size after the first element inserted, to 132 // deal with empty-map optimization. 133 map1.put(0, null); 134 135 int initialBuckets = bucketsOf(map1); 136 137 for (int i = 1; i < size; i++) { 138 map1.put(i, null); 139 } 140 assertEquals("table size after adding " + size + " elements", 141 initialBuckets, bucketsOf(map1)); 142 143 /* 144 * Something slightly different happens when the entries are added all at 145 * once; make sure that passes too. 146 */ 147 HashMap<Integer, Void> map2 = Maps.newHashMapWithExpectedSize(size); 148 map2.putAll(map1); 149 assertEquals("table size after adding " + size + "elements", 150 initialBuckets, bucketsOf(map2)); 151 } 152 } 153 154 @GwtIncompatible("reflection") bucketsOf(HashMap<?, ?> hashMap)155 private static int bucketsOf(HashMap<?, ?> hashMap) throws Exception { 156 Field tableField = HashMap.class.getDeclaredField("table"); 157 tableField.setAccessible(true); 158 Object[] table = (Object[]) tableField.get(hashMap); 159 return table.length; 160 } 161 testCapacityForLargeSizes()162 public void testCapacityForLargeSizes() { 163 int[] largeExpectedSizes = new int[] { 164 Integer.MAX_VALUE / 2 - 1, 165 Integer.MAX_VALUE / 2, 166 Integer.MAX_VALUE / 2 + 1, 167 Integer.MAX_VALUE - 1, 168 Integer.MAX_VALUE}; 169 for (int expectedSize : largeExpectedSizes) { 170 int capacity = Maps.capacity(expectedSize); 171 assertTrue( 172 "capacity (" + capacity + ") must be >= expectedSize (" + expectedSize + ")", 173 capacity >= expectedSize); 174 } 175 } 176 testLinkedHashMap()177 public void testLinkedHashMap() { 178 LinkedHashMap<Integer, Integer> map = Maps.newLinkedHashMap(); 179 assertEquals(Collections.emptyMap(), map); 180 } 181 182 @SuppressWarnings("serial") testLinkedHashMapWithInitialMap()183 public void testLinkedHashMapWithInitialMap() { 184 Map<String, String> map = new LinkedHashMap<String, String>() {{ 185 put("Hello", "World"); 186 put("first", "second"); 187 put("polygene", "lubricants"); 188 put("alpha", "betical"); 189 }}; 190 191 LinkedHashMap<String, String> copy = Maps.newLinkedHashMap(map); 192 193 Iterator<Entry<String, String>> iter = copy.entrySet().iterator(); 194 assertTrue(iter.hasNext()); 195 Entry<String, String> entry = iter.next(); 196 assertEquals("Hello", entry.getKey()); 197 assertEquals("World", entry.getValue()); 198 assertTrue(iter.hasNext()); 199 200 entry = iter.next(); 201 assertEquals("first", entry.getKey()); 202 assertEquals("second", entry.getValue()); 203 assertTrue(iter.hasNext()); 204 205 entry = iter.next(); 206 assertEquals("polygene", entry.getKey()); 207 assertEquals("lubricants", entry.getValue()); 208 assertTrue(iter.hasNext()); 209 210 entry = iter.next(); 211 assertEquals("alpha", entry.getKey()); 212 assertEquals("betical", entry.getValue()); 213 assertFalse(iter.hasNext()); 214 } 215 testLinkedHashMapGeneralizesTypes()216 public void testLinkedHashMapGeneralizesTypes() { 217 Map<String, Integer> original = new LinkedHashMap<String, Integer>(); 218 original.put("a", 1); 219 original.put("b", 2); 220 original.put("c", 3); 221 HashMap<Object, Object> map 222 = Maps.<Object, Object>newLinkedHashMap(original); 223 assertEquals(original, map); 224 } 225 testIdentityHashMap()226 public void testIdentityHashMap() { 227 IdentityHashMap<Integer, Integer> map = Maps.newIdentityHashMap(); 228 assertEquals(Collections.emptyMap(), map); 229 } 230 testConcurrentMap()231 public void testConcurrentMap() { 232 ConcurrentMap<Integer, Integer> map = Maps.newConcurrentMap(); 233 assertEquals(Collections.emptyMap(), map); 234 } 235 testTreeMap()236 public void testTreeMap() { 237 TreeMap<Integer, Integer> map = Maps.newTreeMap(); 238 assertEquals(Collections.emptyMap(), map); 239 assertNull(map.comparator()); 240 } 241 testTreeMapDerived()242 public void testTreeMapDerived() { 243 TreeMap<Derived, Integer> map = Maps.newTreeMap(); 244 assertEquals(Collections.emptyMap(), map); 245 map.put(new Derived("foo"), 1); 246 map.put(new Derived("bar"), 2); 247 assertThat(map.keySet()).has().exactly( 248 new Derived("bar"), new Derived("foo")).inOrder(); 249 assertThat(map.values()).has().exactly(2, 1).inOrder(); 250 assertNull(map.comparator()); 251 } 252 testTreeMapNonGeneric()253 public void testTreeMapNonGeneric() { 254 TreeMap<LegacyComparable, Integer> map = Maps.newTreeMap(); 255 assertEquals(Collections.emptyMap(), map); 256 map.put(new LegacyComparable("foo"), 1); 257 map.put(new LegacyComparable("bar"), 2); 258 assertThat(map.keySet()).has().exactly( 259 new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder(); 260 assertThat(map.values()).has().exactly(2, 1).inOrder(); 261 assertNull(map.comparator()); 262 } 263 testTreeMapWithComparator()264 public void testTreeMapWithComparator() { 265 TreeMap<Integer, Integer> map = Maps.newTreeMap(SOME_COMPARATOR); 266 assertEquals(Collections.emptyMap(), map); 267 assertSame(SOME_COMPARATOR, map.comparator()); 268 } 269 testTreeMapWithInitialMap()270 public void testTreeMapWithInitialMap() { 271 SortedMap<Integer, Integer> map = Maps.newTreeMap(); 272 map.put(5, 10); 273 map.put(3, 20); 274 map.put(1, 30); 275 TreeMap<Integer, Integer> copy = Maps.newTreeMap(map); 276 assertEquals(copy, map); 277 assertSame(copy.comparator(), map.comparator()); 278 } 279 280 public enum SomeEnum { SOME_INSTANCE } 281 testEnumMap()282 public void testEnumMap() { 283 EnumMap<SomeEnum, Integer> map = Maps.newEnumMap(SomeEnum.class); 284 assertEquals(Collections.emptyMap(), map); 285 map.put(SomeEnum.SOME_INSTANCE, 0); 286 assertEquals(Collections.singletonMap(SomeEnum.SOME_INSTANCE, 0), map); 287 } 288 testEnumMapNullClass()289 public void testEnumMapNullClass() { 290 try { 291 Maps.<SomeEnum, Long>newEnumMap((Class<MapsTest.SomeEnum>) null); 292 fail("no exception thrown"); 293 } catch (NullPointerException expected) { 294 } 295 } 296 testEnumMapWithInitialEnumMap()297 public void testEnumMapWithInitialEnumMap() { 298 EnumMap<SomeEnum, Integer> original = Maps.newEnumMap(SomeEnum.class); 299 original.put(SomeEnum.SOME_INSTANCE, 0); 300 EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original); 301 assertEquals(original, copy); 302 } 303 testEnumMapWithInitialEmptyEnumMap()304 public void testEnumMapWithInitialEmptyEnumMap() { 305 EnumMap<SomeEnum, Integer> original = Maps.newEnumMap(SomeEnum.class); 306 EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original); 307 assertEquals(original, copy); 308 assertNotSame(original, copy); 309 } 310 testEnumMapWithInitialMap()311 public void testEnumMapWithInitialMap() { 312 HashMap<SomeEnum, Integer> original = Maps.newHashMap(); 313 original.put(SomeEnum.SOME_INSTANCE, 0); 314 EnumMap<SomeEnum, Integer> copy = Maps.newEnumMap(original); 315 assertEquals(original, copy); 316 } 317 testEnumMapWithInitialEmptyMap()318 public void testEnumMapWithInitialEmptyMap() { 319 Map<SomeEnum, Integer> original = Maps.newHashMap(); 320 try { 321 Maps.newEnumMap(original); 322 fail("Empty map must result in an IllegalArgumentException"); 323 } catch (IllegalArgumentException expected) {} 324 } 325 testToStringImplWithNullKeys()326 public void testToStringImplWithNullKeys() throws Exception { 327 Map<String, String> hashmap = Maps.newHashMap(); 328 hashmap.put("foo", "bar"); 329 hashmap.put(null, "baz"); 330 331 assertEquals(hashmap.toString(), Maps.toStringImpl(hashmap)); 332 } 333 testToStringImplWithNullValues()334 public void testToStringImplWithNullValues() throws Exception { 335 Map<String, String> hashmap = Maps.newHashMap(); 336 hashmap.put("foo", "bar"); 337 hashmap.put("baz", null); 338 339 assertEquals(hashmap.toString(), Maps.toStringImpl(hashmap)); 340 } 341 342 @GwtIncompatible("NullPointerTester") testNullPointerExceptions()343 public void testNullPointerExceptions() { 344 new NullPointerTester().testAllPublicStaticMethods(Maps.class); 345 } 346 347 private static final Map<Integer, Integer> EMPTY 348 = Collections.emptyMap(); 349 private static final Map<Integer, Integer> SINGLETON 350 = Collections.singletonMap(1, 2); 351 testMapDifferenceEmptyEmpty()352 public void testMapDifferenceEmptyEmpty() { 353 MapDifference<Integer, Integer> diff = Maps.difference(EMPTY, EMPTY); 354 assertTrue(diff.areEqual()); 355 assertEquals(EMPTY, diff.entriesOnlyOnLeft()); 356 assertEquals(EMPTY, diff.entriesOnlyOnRight()); 357 assertEquals(EMPTY, diff.entriesInCommon()); 358 assertEquals(EMPTY, diff.entriesDiffering()); 359 assertEquals("equal", diff.toString()); 360 } 361 testMapDifferenceEmptySingleton()362 public void testMapDifferenceEmptySingleton() { 363 MapDifference<Integer, Integer> diff = Maps.difference(EMPTY, SINGLETON); 364 assertFalse(diff.areEqual()); 365 assertEquals(EMPTY, diff.entriesOnlyOnLeft()); 366 assertEquals(SINGLETON, diff.entriesOnlyOnRight()); 367 assertEquals(EMPTY, diff.entriesInCommon()); 368 assertEquals(EMPTY, diff.entriesDiffering()); 369 assertEquals("not equal: only on right={1=2}", diff.toString()); 370 } 371 testMapDifferenceSingletonEmpty()372 public void testMapDifferenceSingletonEmpty() { 373 MapDifference<Integer, Integer> diff = Maps.difference(SINGLETON, EMPTY); 374 assertFalse(diff.areEqual()); 375 assertEquals(SINGLETON, diff.entriesOnlyOnLeft()); 376 assertEquals(EMPTY, diff.entriesOnlyOnRight()); 377 assertEquals(EMPTY, diff.entriesInCommon()); 378 assertEquals(EMPTY, diff.entriesDiffering()); 379 assertEquals("not equal: only on left={1=2}", diff.toString()); 380 } 381 testMapDifferenceTypical()382 public void testMapDifferenceTypical() { 383 Map<Integer, String> left = ImmutableMap.of( 384 1, "a", 2, "b", 3, "c", 4, "d", 5, "e"); 385 Map<Integer, String> right = ImmutableMap.of( 386 1, "a", 3, "f", 5, "g", 6, "z"); 387 388 MapDifference<Integer, String> diff1 = Maps.difference(left, right); 389 assertFalse(diff1.areEqual()); 390 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff1.entriesOnlyOnLeft()); 391 assertEquals(ImmutableMap.of(6, "z"), diff1.entriesOnlyOnRight()); 392 assertEquals(ImmutableMap.of(1, "a"), diff1.entriesInCommon()); 393 assertEquals(ImmutableMap.of(3, 394 ValueDifferenceImpl.create("c", "f"), 5, 395 ValueDifferenceImpl.create("e", "g")), 396 diff1.entriesDiffering()); 397 assertEquals("not equal: only on left={2=b, 4=d}: only on right={6=z}: " 398 + "value differences={3=(c, f), 5=(e, g)}", diff1.toString()); 399 400 MapDifference<Integer, String> diff2 = Maps.difference(right, left); 401 assertFalse(diff2.areEqual()); 402 assertEquals(ImmutableMap.of(6, "z"), diff2.entriesOnlyOnLeft()); 403 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff2.entriesOnlyOnRight()); 404 assertEquals(ImmutableMap.of(1, "a"), diff2.entriesInCommon()); 405 assertEquals(ImmutableMap.of(3, 406 ValueDifferenceImpl.create("f", "c"), 5, 407 ValueDifferenceImpl.create("g", "e")), 408 diff2.entriesDiffering()); 409 assertEquals("not equal: only on left={6=z}: only on right={2=b, 4=d}: " 410 + "value differences={3=(f, c), 5=(g, e)}", diff2.toString()); 411 } 412 testMapDifferenceEquals()413 public void testMapDifferenceEquals() { 414 Map<Integer, String> left = ImmutableMap.of( 415 1, "a", 2, "b", 3, "c", 4, "d", 5, "e"); 416 Map<Integer, String> right = ImmutableMap.of( 417 1, "a", 3, "f", 5, "g", 6, "z"); 418 Map<Integer, String> right2 = ImmutableMap.of( 419 1, "a", 3, "h", 5, "g", 6, "z"); 420 MapDifference<Integer, String> original = Maps.difference(left, right); 421 MapDifference<Integer, String> same = Maps.difference(left, right); 422 MapDifference<Integer, String> reverse = Maps.difference(right, left); 423 MapDifference<Integer, String> diff2 = Maps.difference(left, right2); 424 425 new EqualsTester() 426 .addEqualityGroup(original, same) 427 .addEqualityGroup(reverse) 428 .addEqualityGroup(diff2) 429 .testEquals(); 430 } 431 testMapDifferencePredicateTypical()432 public void testMapDifferencePredicateTypical() { 433 Map<Integer, String> left = ImmutableMap.of( 434 1, "a", 2, "b", 3, "c", 4, "d", 5, "e"); 435 Map<Integer, String> right = ImmutableMap.of( 436 1, "A", 3, "F", 5, "G", 6, "Z"); 437 438 // TODO(kevinb): replace with Ascii.caseInsensitiveEquivalence() when it 439 // exists 440 Equivalence<String> caseInsensitiveEquivalence = Equivalence.equals().onResultOf( 441 new Function<String, String>() { 442 @Override public String apply(String input) { 443 return input.toLowerCase(); 444 } 445 }); 446 447 MapDifference<Integer, String> diff1 = Maps.difference(left, right, 448 caseInsensitiveEquivalence); 449 assertFalse(diff1.areEqual()); 450 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff1.entriesOnlyOnLeft()); 451 assertEquals(ImmutableMap.of(6, "Z"), diff1.entriesOnlyOnRight()); 452 assertEquals(ImmutableMap.of(1, "a"), diff1.entriesInCommon()); 453 assertEquals(ImmutableMap.of(3, 454 ValueDifferenceImpl.create("c", "F"), 5, 455 ValueDifferenceImpl.create("e", "G")), 456 diff1.entriesDiffering()); 457 assertEquals("not equal: only on left={2=b, 4=d}: only on right={6=Z}: " 458 + "value differences={3=(c, F), 5=(e, G)}", diff1.toString()); 459 460 MapDifference<Integer, String> diff2 = Maps.difference(right, left, 461 caseInsensitiveEquivalence); 462 assertFalse(diff2.areEqual()); 463 assertEquals(ImmutableMap.of(6, "Z"), diff2.entriesOnlyOnLeft()); 464 assertEquals(ImmutableMap.of(2, "b", 4, "d"), diff2.entriesOnlyOnRight()); 465 assertEquals(ImmutableMap.of(1, "A"), diff2.entriesInCommon()); 466 assertEquals(ImmutableMap.of(3, 467 ValueDifferenceImpl.create("F", "c"), 5, 468 ValueDifferenceImpl.create("G", "e")), 469 diff2.entriesDiffering()); 470 assertEquals("not equal: only on left={6=Z}: only on right={2=b, 4=d}: " 471 + "value differences={3=(F, c), 5=(G, e)}", diff2.toString()); 472 } 473 474 private static final SortedMap<Integer, Integer> SORTED_EMPTY = Maps.newTreeMap(); 475 private static final SortedMap<Integer, Integer> SORTED_SINGLETON = 476 ImmutableSortedMap.of(1, 2); 477 testMapDifferenceOfSortedMapIsSorted()478 public void testMapDifferenceOfSortedMapIsSorted() { 479 Map<Integer, Integer> map = SORTED_SINGLETON; 480 MapDifference<Integer, Integer> difference = Maps.difference(map, EMPTY); 481 assertTrue(difference instanceof SortedMapDifference); 482 } 483 testSortedMapDifferenceEmptyEmpty()484 public void testSortedMapDifferenceEmptyEmpty() { 485 SortedMapDifference<Integer, Integer> diff = 486 Maps.difference(SORTED_EMPTY, SORTED_EMPTY); 487 assertTrue(diff.areEqual()); 488 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnLeft()); 489 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnRight()); 490 assertEquals(SORTED_EMPTY, diff.entriesInCommon()); 491 assertEquals(SORTED_EMPTY, diff.entriesDiffering()); 492 assertEquals("equal", diff.toString()); 493 } 494 testSortedMapDifferenceEmptySingleton()495 public void testSortedMapDifferenceEmptySingleton() { 496 SortedMapDifference<Integer, Integer> diff = 497 Maps.difference(SORTED_EMPTY, SORTED_SINGLETON); 498 assertFalse(diff.areEqual()); 499 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnLeft()); 500 assertEquals(SORTED_SINGLETON, diff.entriesOnlyOnRight()); 501 assertEquals(SORTED_EMPTY, diff.entriesInCommon()); 502 assertEquals(SORTED_EMPTY, diff.entriesDiffering()); 503 assertEquals("not equal: only on right={1=2}", diff.toString()); 504 } 505 testSortedMapDifferenceSingletonEmpty()506 public void testSortedMapDifferenceSingletonEmpty() { 507 SortedMapDifference<Integer, Integer> diff = 508 Maps.difference(SORTED_SINGLETON, SORTED_EMPTY); 509 assertFalse(diff.areEqual()); 510 assertEquals(SORTED_SINGLETON, diff.entriesOnlyOnLeft()); 511 assertEquals(SORTED_EMPTY, diff.entriesOnlyOnRight()); 512 assertEquals(SORTED_EMPTY, diff.entriesInCommon()); 513 assertEquals(SORTED_EMPTY, diff.entriesDiffering()); 514 assertEquals("not equal: only on left={1=2}", diff.toString()); 515 } 516 testSortedMapDifferenceTypical()517 public void testSortedMapDifferenceTypical() { 518 SortedMap<Integer, String> left = 519 ImmutableSortedMap.<Integer, String>reverseOrder() 520 .put(1, "a").put(2, "b").put(3, "c").put(4, "d").put(5, "e") 521 .build(); 522 523 SortedMap<Integer, String> right = 524 ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z"); 525 526 SortedMapDifference<Integer, String> diff1 = 527 Maps.difference(left, right); 528 assertFalse(diff1.areEqual()); 529 assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly( 530 Maps.immutableEntry(4, "d"), Maps.immutableEntry(2, "b")).inOrder(); 531 assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item( 532 Maps.immutableEntry(6, "z")); 533 assertThat(diff1.entriesInCommon().entrySet()).has().item( 534 Maps.immutableEntry(1, "a")); 535 assertThat(diff1.entriesDiffering().entrySet()).has().exactly( 536 Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g")), 537 Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f"))).inOrder(); 538 assertEquals("not equal: only on left={4=d, 2=b}: only on right={6=z}: " 539 + "value differences={5=(e, g), 3=(c, f)}", diff1.toString()); 540 541 SortedMapDifference<Integer, String> diff2 = 542 Maps.difference(right, left); 543 assertFalse(diff2.areEqual()); 544 assertThat(diff2.entriesOnlyOnLeft().entrySet()).has().item( 545 Maps.immutableEntry(6, "z")); 546 assertThat(diff2.entriesOnlyOnRight().entrySet()).has().exactly( 547 Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder(); 548 assertThat(diff1.entriesInCommon().entrySet()).has().item( 549 Maps.immutableEntry(1, "a")); 550 assertEquals(ImmutableMap.of( 551 3, ValueDifferenceImpl.create("f", "c"), 552 5, ValueDifferenceImpl.create("g", "e")), 553 diff2.entriesDiffering()); 554 assertEquals("not equal: only on left={6=z}: only on right={2=b, 4=d}: " 555 + "value differences={3=(f, c), 5=(g, e)}", diff2.toString()); 556 } 557 testSortedMapDifferenceImmutable()558 public void testSortedMapDifferenceImmutable() { 559 SortedMap<Integer, String> left = Maps.newTreeMap( 560 ImmutableSortedMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e")); 561 SortedMap<Integer, String> right = 562 Maps.newTreeMap(ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z")); 563 564 SortedMapDifference<Integer, String> diff1 = 565 Maps.difference(left, right); 566 left.put(6, "z"); 567 assertFalse(diff1.areEqual()); 568 assertThat(diff1.entriesOnlyOnLeft().entrySet()).has().exactly( 569 Maps.immutableEntry(2, "b"), Maps.immutableEntry(4, "d")).inOrder(); 570 assertThat(diff1.entriesOnlyOnRight().entrySet()).has().item( 571 Maps.immutableEntry(6, "z")); 572 assertThat(diff1.entriesInCommon().entrySet()).has().item( 573 Maps.immutableEntry(1, "a")); 574 assertThat(diff1.entriesDiffering().entrySet()).has().exactly( 575 Maps.immutableEntry(3, ValueDifferenceImpl.create("c", "f")), 576 Maps.immutableEntry(5, ValueDifferenceImpl.create("e", "g"))).inOrder(); 577 try { 578 diff1.entriesInCommon().put(7, "x"); 579 fail(); 580 } catch (UnsupportedOperationException expected) { 581 } 582 try { 583 diff1.entriesOnlyOnLeft().put(7, "x"); 584 fail(); 585 } catch (UnsupportedOperationException expected) { 586 } 587 try { 588 diff1.entriesOnlyOnRight().put(7, "x"); 589 fail(); 590 } catch (UnsupportedOperationException expected) { 591 } 592 } 593 testSortedMapDifferenceEquals()594 public void testSortedMapDifferenceEquals() { 595 SortedMap<Integer, String> left = 596 ImmutableSortedMap.of(1, "a", 2, "b", 3, "c", 4, "d", 5, "e"); 597 SortedMap<Integer, String> right = 598 ImmutableSortedMap.of(1, "a", 3, "f", 5, "g", 6, "z"); 599 SortedMap<Integer, String> right2 = 600 ImmutableSortedMap.of(1, "a", 3, "h", 5, "g", 6, "z"); 601 SortedMapDifference<Integer, String> original = 602 Maps.difference(left, right); 603 SortedMapDifference<Integer, String> same = 604 Maps.difference(left, right); 605 SortedMapDifference<Integer, String> reverse = 606 Maps.difference(right, left); 607 SortedMapDifference<Integer, String> diff2 = 608 Maps.difference(left, right2); 609 610 new EqualsTester() 611 .addEqualityGroup(original, same) 612 .addEqualityGroup(reverse) 613 .addEqualityGroup(diff2) 614 .testEquals(); 615 } 616 617 private static final Function<String, Integer> LENGTH_FUNCTION = 618 new Function<String, Integer>() { 619 @Override 620 public Integer apply(String input) { 621 return input.length(); 622 } 623 }; 624 testAsMap()625 public void testAsMap() { 626 Set<String> strings = ImmutableSet.of("one", "two", "three"); 627 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 628 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 629 assertEquals(Integer.valueOf(5), map.get("three")); 630 assertNull(map.get("five")); 631 assertThat(map.entrySet()).has().exactly( 632 mapEntry("one", 3), 633 mapEntry("two", 3), 634 mapEntry("three", 5)).inOrder(); 635 } 636 testAsMapReadsThrough()637 public void testAsMapReadsThrough() { 638 Set<String> strings = Sets.newLinkedHashSet(); 639 Collections.addAll(strings, "one", "two", "three"); 640 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 641 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 642 assertNull(map.get("four")); 643 strings.add("four"); 644 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5, "four", 4), map); 645 assertEquals(Integer.valueOf(4), map.get("four")); 646 } 647 testAsMapWritesThrough()648 public void testAsMapWritesThrough() { 649 Set<String> strings = Sets.newLinkedHashSet(); 650 Collections.addAll(strings, "one", "two", "three"); 651 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 652 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 653 assertEquals(Integer.valueOf(3), map.remove("two")); 654 assertThat(strings).has().exactly("one", "three").inOrder(); 655 } 656 testAsMapEmpty()657 public void testAsMapEmpty() { 658 Set<String> strings = ImmutableSet.of(); 659 Map<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 660 assertThat(map.entrySet()).isEmpty(); 661 assertTrue(map.isEmpty()); 662 assertNull(map.get("five")); 663 } 664 665 private static class NonNavigableSortedSet 666 extends ForwardingSortedSet<String> { 667 private final SortedSet<String> delegate = Sets.newTreeSet(); 668 669 @Override delegate()670 protected SortedSet<String> delegate() { 671 return delegate; 672 } 673 } 674 testAsMapReturnsSortedMapForSortedSetInput()675 public void testAsMapReturnsSortedMapForSortedSetInput() { 676 Set<String> set = new NonNavigableSortedSet(); 677 assertTrue(Maps.asMap(set, Functions.identity()) instanceof SortedMap); 678 } 679 testAsMapSorted()680 public void testAsMapSorted() { 681 SortedSet<String> strings = new NonNavigableSortedSet(); 682 Collections.addAll(strings, "one", "two", "three"); 683 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 684 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 685 assertEquals(Integer.valueOf(5), map.get("three")); 686 assertNull(map.get("five")); 687 assertThat(map.entrySet()).has().exactly( 688 mapEntry("one", 3), 689 mapEntry("three", 5), 690 mapEntry("two", 3)).inOrder(); 691 assertThat(map.tailMap("onea").entrySet()).has().exactly( 692 mapEntry("three", 5), 693 mapEntry("two", 3)).inOrder(); 694 assertThat(map.subMap("one", "two").entrySet()).has().exactly( 695 mapEntry("one", 3), 696 mapEntry("three", 5)).inOrder(); 697 } 698 testAsMapSortedReadsThrough()699 public void testAsMapSortedReadsThrough() { 700 SortedSet<String> strings = new NonNavigableSortedSet(); 701 Collections.addAll(strings, "one", "two", "three"); 702 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 703 assertNull(map.comparator()); 704 assertEquals(ImmutableSortedMap.of("one", 3, "two", 3, "three", 5), map); 705 assertNull(map.get("four")); 706 strings.add("four"); 707 assertEquals( 708 ImmutableSortedMap.of("one", 3, "two", 3, "three", 5, "four", 4), 709 map); 710 assertEquals(Integer.valueOf(4), map.get("four")); 711 SortedMap<String, Integer> headMap = map.headMap("two"); 712 assertEquals( 713 ImmutableSortedMap.of("four", 4, "one", 3, "three", 5), 714 headMap); 715 strings.add("five"); 716 strings.remove("one"); 717 assertEquals( 718 ImmutableSortedMap.of("five", 4, "four", 4, "three", 5), 719 headMap); 720 assertThat(map.entrySet()).has().exactly( 721 mapEntry("five", 4), 722 mapEntry("four", 4), 723 mapEntry("three", 5), 724 mapEntry("two", 3)).inOrder(); 725 } 726 testAsMapSortedWritesThrough()727 public void testAsMapSortedWritesThrough() { 728 SortedSet<String> strings = new NonNavigableSortedSet(); 729 Collections.addAll(strings, "one", "two", "three"); 730 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 731 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 732 assertEquals(Integer.valueOf(3), map.remove("two")); 733 assertThat(strings).has().exactly("one", "three").inOrder(); 734 } 735 testAsMapSortedSubViewKeySetsDoNotSupportAdd()736 public void testAsMapSortedSubViewKeySetsDoNotSupportAdd() { 737 SortedMap<String, Integer> map = Maps.asMap( 738 new NonNavigableSortedSet(), LENGTH_FUNCTION); 739 try { 740 map.subMap("a", "z").keySet().add("a"); 741 fail(); 742 } catch (UnsupportedOperationException expected) { 743 } 744 try { 745 map.tailMap("a").keySet().add("a"); 746 fail(); 747 } catch (UnsupportedOperationException expected) { 748 } 749 try { 750 map.headMap("r").keySet().add("a"); 751 fail(); 752 } catch (UnsupportedOperationException expected) { 753 } 754 try { 755 map.headMap("r").tailMap("m").keySet().add("a"); 756 fail(); 757 } catch (UnsupportedOperationException expected) { 758 } 759 } 760 testAsMapSortedEmpty()761 public void testAsMapSortedEmpty() { 762 SortedSet<String> strings = new NonNavigableSortedSet(); 763 SortedMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 764 assertThat(map.entrySet()).isEmpty(); 765 assertTrue(map.isEmpty()); 766 assertNull(map.get("five")); 767 } 768 769 @GwtIncompatible("NavigableMap") testAsMapReturnsNavigableMapForNavigableSetInput()770 public void testAsMapReturnsNavigableMapForNavigableSetInput() { 771 Set<String> set = Sets.newTreeSet(); 772 assertTrue(Maps.asMap(set, Functions.identity()) instanceof NavigableMap); 773 } 774 775 @GwtIncompatible("NavigableMap") testAsMapNavigable()776 public void testAsMapNavigable() { 777 NavigableSet<String> strings = 778 Sets.newTreeSet(asList("one", "two", "three")); 779 NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 780 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 781 assertEquals(Integer.valueOf(5), map.get("three")); 782 assertNull(map.get("five")); 783 assertThat(map.entrySet()).has().exactly( 784 mapEntry("one", 3), 785 mapEntry("three", 5), 786 mapEntry("two", 3)).inOrder(); 787 assertThat(map.tailMap("onea").entrySet()).has().exactly( 788 mapEntry("three", 5), 789 mapEntry("two", 3)).inOrder(); 790 assertThat(map.subMap("one", "two").entrySet()).has().exactly( 791 mapEntry("one", 3), 792 mapEntry("three", 5)).inOrder(); 793 794 assertEquals(ImmutableSortedMap.of("two", 3, "three", 5), 795 map.tailMap("three", true)); 796 assertEquals(ImmutableSortedMap.of("one", 3, "three", 5), 797 map.headMap("two", false)); 798 assertEquals(ImmutableSortedMap.of("three", 5), 799 map.subMap("one", false, "tr", true)); 800 801 assertEquals("three", map.higherKey("one")); 802 assertEquals("three", map.higherKey("r")); 803 assertEquals("three", map.ceilingKey("r")); 804 assertEquals("one", map.ceilingKey("one")); 805 assertEquals(mapEntry("three", 5), map.higherEntry("one")); 806 assertEquals(mapEntry("one", 3), map.ceilingEntry("one")); 807 assertEquals("one", map.lowerKey("three")); 808 assertEquals("one", map.lowerKey("r")); 809 assertEquals("one", map.floorKey("r")); 810 assertEquals("three", map.floorKey("three")); 811 812 assertThat(map.descendingMap().entrySet()).has().exactly( 813 mapEntry("two", 3), 814 mapEntry("three", 5), 815 mapEntry("one", 3)).inOrder(); 816 assertEquals(map.headMap("three", true), 817 map.descendingMap().tailMap("three", true)); 818 assertThat(map.tailMap("three", false).entrySet()).has().item( 819 mapEntry("two", 3)); 820 assertNull(map.tailMap("three", true).lowerEntry("three")); 821 assertThat(map.headMap("two", false).values()).has().exactly(3, 5).inOrder(); 822 assertThat(map.headMap("two", false).descendingMap().values()) 823 .has().exactly(5, 3).inOrder(); 824 assertThat(map.descendingKeySet()).has().exactly( 825 "two", "three", "one").inOrder(); 826 827 assertEquals(mapEntry("one", 3), map.pollFirstEntry()); 828 assertEquals(mapEntry("two", 3), map.pollLastEntry()); 829 assertEquals(1, map.size()); 830 } 831 832 @GwtIncompatible("NavigableMap") testAsMapNavigableReadsThrough()833 public void testAsMapNavigableReadsThrough() { 834 NavigableSet<String> strings = Sets.newTreeSet(); 835 Collections.addAll(strings, "one", "two", "three"); 836 NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 837 assertNull(map.comparator()); 838 assertEquals(ImmutableSortedMap.of("one", 3, "two", 3, "three", 5), map); 839 assertNull(map.get("four")); 840 strings.add("four"); 841 assertEquals( 842 ImmutableSortedMap.of("one", 3, "two", 3, "three", 5, "four", 4), 843 map); 844 assertEquals(Integer.valueOf(4), map.get("four")); 845 SortedMap<String, Integer> headMap = map.headMap("two"); 846 assertEquals( 847 ImmutableSortedMap.of("four", 4, "one", 3, "three", 5), 848 headMap); 849 strings.add("five"); 850 strings.remove("one"); 851 assertEquals( 852 ImmutableSortedMap.of("five", 4, "four", 4, "three", 5), 853 headMap); 854 assertThat(map.entrySet()).has().exactly( 855 mapEntry("five", 4), 856 mapEntry("four", 4), 857 mapEntry("three", 5), 858 mapEntry("two", 3)).inOrder(); 859 860 NavigableMap<String, Integer> tailMap = map.tailMap("s", true); 861 NavigableMap<String, Integer> subMap = map.subMap("a", true, "t", false); 862 863 strings.add("six"); 864 strings.remove("two"); 865 assertThat(tailMap.entrySet()).has().exactly( 866 mapEntry("six", 3), 867 mapEntry("three", 5)).inOrder(); 868 assertThat(subMap.entrySet()).has().exactly( 869 mapEntry("five", 4), 870 mapEntry("four", 4), 871 mapEntry("six", 3)).inOrder(); 872 } 873 874 @GwtIncompatible("NavigableMap") testAsMapNavigableWritesThrough()875 public void testAsMapNavigableWritesThrough() { 876 NavigableSet<String> strings = Sets.newTreeSet(); 877 Collections.addAll(strings, "one", "two", "three"); 878 NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 879 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 880 assertEquals(Integer.valueOf(3), map.remove("two")); 881 assertThat(strings).has().exactly("one", "three").inOrder(); 882 assertEquals(mapEntry("three", 5), 883 map.subMap("one", false, "zzz", true).pollLastEntry()); 884 assertThat(strings).has().item("one"); 885 } 886 887 @GwtIncompatible("NavigableMap") testAsMapNavigableSubViewKeySetsDoNotSupportAdd()888 public void testAsMapNavigableSubViewKeySetsDoNotSupportAdd() { 889 NavigableMap<String, Integer> map = Maps.asMap( 890 Sets.<String>newTreeSet(), LENGTH_FUNCTION); 891 try { 892 map.descendingKeySet().add("a"); 893 fail(); 894 } catch (UnsupportedOperationException expected) { 895 } 896 try { 897 map.subMap("a", true, "z", false).keySet().add("a"); 898 fail(); 899 } catch (UnsupportedOperationException expected) { 900 } 901 try { 902 map.tailMap("a", true).keySet().add("a"); 903 fail(); 904 } catch (UnsupportedOperationException expected) { 905 } 906 try { 907 map.headMap("r", true).keySet().add("a"); 908 fail(); 909 } catch (UnsupportedOperationException expected) { 910 } 911 try { 912 map.headMap("r", false).tailMap("m", true).keySet().add("a"); 913 fail(); 914 } catch (UnsupportedOperationException expected) { 915 } 916 } 917 918 @GwtIncompatible("NavigableMap") testAsMapNavigableEmpty()919 public void testAsMapNavigableEmpty() { 920 NavigableSet<String> strings = ImmutableSortedSet.of(); 921 NavigableMap<String, Integer> map = Maps.asMap(strings, LENGTH_FUNCTION); 922 assertThat(map.entrySet()).isEmpty(); 923 assertTrue(map.isEmpty()); 924 assertNull(map.get("five")); 925 } 926 testToMap()927 public void testToMap() { 928 Iterable<String> strings = ImmutableList.of("one", "two", "three"); 929 ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION); 930 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 931 assertThat(map.entrySet()).has().exactly( 932 mapEntry("one", 3), 933 mapEntry("two", 3), 934 mapEntry("three", 5)).inOrder(); 935 } 936 testToMapIterator()937 public void testToMapIterator() { 938 Iterator<String> strings = ImmutableList.of("one", "two", "three").iterator(); 939 ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION); 940 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 941 assertThat(map.entrySet()).has().exactly( 942 mapEntry("one", 3), 943 mapEntry("two", 3), 944 mapEntry("three", 5)).inOrder(); 945 } 946 testToMapWithDuplicateKeys()947 public void testToMapWithDuplicateKeys() { 948 Iterable<String> strings = ImmutableList.of("one", "two", "three", "two", "one"); 949 ImmutableMap<String, Integer> map = Maps.toMap(strings, LENGTH_FUNCTION); 950 assertEquals(ImmutableMap.of("one", 3, "two", 3, "three", 5), map); 951 assertThat(map.entrySet()).has().exactly( 952 mapEntry("one", 3), 953 mapEntry("two", 3), 954 mapEntry("three", 5)).inOrder(); 955 } 956 testToMapWithNullKeys()957 public void testToMapWithNullKeys() { 958 Iterable<String> strings = Arrays.asList("one", null, "three"); 959 try { 960 Maps.toMap(strings, Functions.constant("foo")); 961 fail(); 962 } catch (NullPointerException expected) { 963 } 964 } 965 testToMapWithNullValues()966 public void testToMapWithNullValues() { 967 Iterable<String> strings = ImmutableList.of("one", "two", "three"); 968 try { 969 Maps.toMap(strings, Functions.constant(null)); 970 fail(); 971 } catch (NullPointerException expected) { 972 } 973 } 974 975 private static final BiMap<Integer, String> INT_TO_STRING_MAP = 976 new ImmutableBiMap.Builder<Integer, String>() 977 .put(1, "one") 978 .put(2, "two") 979 .put(3, "three") 980 .build(); 981 testUniqueIndexCollection()982 public void testUniqueIndexCollection() { 983 ImmutableMap<Integer, String> outputMap = 984 Maps.uniqueIndex(INT_TO_STRING_MAP.values(), 985 Functions.forMap(INT_TO_STRING_MAP.inverse())); 986 assertEquals(INT_TO_STRING_MAP, outputMap); 987 } 988 testUniqueIndexIterable()989 public void testUniqueIndexIterable() { 990 ImmutableMap<Integer, String> outputMap = 991 Maps.uniqueIndex(new Iterable<String>() { 992 @Override 993 public Iterator<String> iterator() { 994 return INT_TO_STRING_MAP.values().iterator(); 995 } 996 }, 997 Functions.forMap(INT_TO_STRING_MAP.inverse())); 998 assertEquals(INT_TO_STRING_MAP, outputMap); 999 } 1000 testUniqueIndexIterator()1001 public void testUniqueIndexIterator() { 1002 ImmutableMap<Integer, String> outputMap = 1003 Maps.uniqueIndex(INT_TO_STRING_MAP.values().iterator(), 1004 Functions.forMap(INT_TO_STRING_MAP.inverse())); 1005 assertEquals(INT_TO_STRING_MAP, outputMap); 1006 } 1007 1008 /** Can't create the map if more than one value maps to the same key. */ testUniqueIndexDuplicates()1009 public void testUniqueIndexDuplicates() { 1010 try { 1011 Maps.uniqueIndex(ImmutableSet.of("one", "uno"), Functions.constant(1)); 1012 fail(); 1013 } catch (IllegalArgumentException expected) { 1014 } 1015 } 1016 1017 /** Null values are not allowed. */ testUniqueIndexNullValue()1018 public void testUniqueIndexNullValue() { 1019 List<String> listWithNull = Lists.newArrayList((String) null); 1020 try { 1021 Maps.uniqueIndex(listWithNull, Functions.constant(1)); 1022 fail(); 1023 } catch (NullPointerException expected) { 1024 } 1025 } 1026 1027 /** Null keys aren't allowed either. */ testUniqueIndexNullKey()1028 public void testUniqueIndexNullKey() { 1029 List<String> oneStringList = Lists.newArrayList("foo"); 1030 try { 1031 Maps.uniqueIndex(oneStringList, Functions.constant(null)); 1032 fail(); 1033 } catch (NullPointerException expected) { 1034 } 1035 } 1036 1037 @GwtIncompatible("Maps.fromProperties") 1038 @SuppressWarnings("deprecation") // StringBufferInputStream testFromProperties()1039 public void testFromProperties() throws IOException { 1040 Properties testProp = new Properties(); 1041 1042 Map<String, String> result = Maps.fromProperties(testProp); 1043 assertTrue(result.isEmpty()); 1044 testProp.setProperty("first", "true"); 1045 1046 result = Maps.fromProperties(testProp); 1047 assertEquals("true", result.get("first")); 1048 assertEquals(1, result.size()); 1049 testProp.setProperty("second", "null"); 1050 1051 result = Maps.fromProperties(testProp); 1052 assertEquals("true", result.get("first")); 1053 assertEquals("null", result.get("second")); 1054 assertEquals(2, result.size()); 1055 1056 // Now test values loaded from a stream. 1057 String props = "test\n second = 2\n Third item : a short phrase "; 1058 1059 testProp.load(new StringReader(props)); 1060 1061 result = Maps.fromProperties(testProp); 1062 assertEquals(4, result.size()); 1063 assertEquals("true", result.get("first")); 1064 assertEquals("", result.get("test")); 1065 assertEquals("2", result.get("second")); 1066 assertEquals("item : a short phrase ", result.get("Third")); 1067 assertFalse(result.containsKey("not here")); 1068 1069 // Test loading system properties 1070 result = Maps.fromProperties(System.getProperties()); 1071 assertTrue(result.containsKey("java.version")); 1072 1073 // Test that defaults work, too. 1074 testProp = new Properties(System.getProperties()); 1075 String override = "test\njava.version : hidden"; 1076 1077 testProp.load(new StringReader(override)); 1078 1079 result = Maps.fromProperties(testProp); 1080 assertTrue(result.size() > 2); 1081 assertEquals("", result.get("test")); 1082 assertEquals("hidden", result.get("java.version")); 1083 assertNotSame(System.getProperty("java.version"), 1084 result.get("java.version")); 1085 } 1086 1087 @GwtIncompatible("Maps.fromProperties") 1088 @SuppressWarnings("serial") // never serialized testFromPropertiesNullKey()1089 public void testFromPropertiesNullKey() { 1090 Properties properties = new Properties() { 1091 @Override public Enumeration<?> propertyNames() { 1092 return Iterators.asEnumeration( 1093 Arrays.asList(null, "first", "second").iterator()); 1094 } 1095 }; 1096 properties.setProperty("first", "true"); 1097 properties.setProperty("second", "null"); 1098 1099 try { 1100 Maps.fromProperties(properties); 1101 fail(); 1102 } catch (NullPointerException expected) {} 1103 } 1104 1105 @GwtIncompatible("Maps.fromProperties") 1106 @SuppressWarnings("serial") // never serialized testFromPropertiesNonStringKeys()1107 public void testFromPropertiesNonStringKeys() { 1108 Properties properties = new Properties() { 1109 @Override public Enumeration<?> propertyNames() { 1110 return Iterators.asEnumeration( 1111 Arrays.<Object>asList(Integer.valueOf(123), "first").iterator()); 1112 } 1113 }; 1114 1115 try { 1116 Maps.fromProperties(properties); 1117 fail(); 1118 } catch (ClassCastException expected) {} 1119 } 1120 testAsConverter_nominal()1121 public void testAsConverter_nominal() throws Exception { 1122 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of( 1123 "one", 1, 1124 "two", 2); 1125 Converter<String, Integer> converter = Maps.asConverter(biMap); 1126 for (Entry<String, Integer> entry : biMap.entrySet()) { 1127 assertSame(entry.getValue(), converter.convert(entry.getKey())); 1128 } 1129 } 1130 testAsConverter_inverse()1131 public void testAsConverter_inverse() throws Exception { 1132 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of( 1133 "one", 1, 1134 "two", 2); 1135 Converter<String, Integer> converter = Maps.asConverter(biMap); 1136 for (Entry<String, Integer> entry : biMap.entrySet()) { 1137 assertSame(entry.getKey(), converter.reverse().convert(entry.getValue())); 1138 } 1139 } 1140 testAsConverter_noMapping()1141 public void testAsConverter_noMapping() throws Exception { 1142 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of( 1143 "one", 1, 1144 "two", 2); 1145 Converter<String, Integer> converter = Maps.asConverter(biMap); 1146 try { 1147 converter.convert("three"); 1148 fail(); 1149 } catch (IllegalArgumentException expected) { 1150 } 1151 } 1152 testAsConverter_nullConversions()1153 public void testAsConverter_nullConversions() throws Exception { 1154 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of( 1155 "one", 1, 1156 "two", 2); 1157 Converter<String, Integer> converter = Maps.asConverter(biMap); 1158 assertNull(converter.convert(null)); 1159 assertNull(converter.reverse().convert(null)); 1160 } 1161 testAsConverter_isAView()1162 public void testAsConverter_isAView() throws Exception { 1163 BiMap<String, Integer> biMap = HashBiMap.create(); 1164 biMap.put("one", 1); 1165 biMap.put("two", 2); 1166 Converter<String, Integer> converter = Maps.asConverter(biMap); 1167 1168 assertSame(1, converter.convert("one")); 1169 assertSame(2, converter.convert("two")); 1170 try { 1171 converter.convert("three"); 1172 fail(); 1173 } catch (IllegalArgumentException expected) { 1174 } 1175 1176 biMap.put("three", 3); 1177 1178 assertSame(1, converter.convert("one")); 1179 assertSame(2, converter.convert("two")); 1180 assertSame(3, converter.convert("three")); 1181 } 1182 testAsConverter_withNullMapping()1183 public void testAsConverter_withNullMapping() throws Exception { 1184 BiMap<String, Integer> biMap = HashBiMap.create(); 1185 biMap.put("one", 1); 1186 biMap.put("two", 2); 1187 biMap.put("three", null); 1188 try { 1189 Maps.asConverter(biMap).convert("three"); 1190 fail(); 1191 } catch (IllegalArgumentException expected) { 1192 } 1193 } 1194 testAsConverter_toString()1195 public void testAsConverter_toString() { 1196 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of( 1197 "one", 1, 1198 "two", 2); 1199 Converter<String, Integer> converter = Maps.asConverter(biMap); 1200 assertEquals("Maps.asConverter({one=1, two=2})", converter.toString()); 1201 } 1202 testAsConverter_serialization()1203 public void testAsConverter_serialization() { 1204 ImmutableBiMap<String, Integer> biMap = ImmutableBiMap.of( 1205 "one", 1, 1206 "two", 2); 1207 Converter<String, Integer> converter = Maps.asConverter(biMap); 1208 SerializableTester.reserializeAndAssert(converter); 1209 } 1210 testUnmodifiableBiMap()1211 public void testUnmodifiableBiMap() { 1212 BiMap<Integer, String> mod = HashBiMap.create(); 1213 mod.put(1, "one"); 1214 mod.put(2, "two"); 1215 mod.put(3, "three"); 1216 1217 BiMap<Number, String> unmod = Maps.<Number, String>unmodifiableBiMap(mod); 1218 1219 /* No aliasing on inverse operations. */ 1220 assertSame(unmod.inverse(), unmod.inverse()); 1221 assertSame(unmod, unmod.inverse().inverse()); 1222 1223 /* Unmodifiable is a view. */ 1224 mod.put(4, "four"); 1225 assertEquals(true, unmod.get(4).equals("four")); 1226 assertEquals(true, unmod.inverse().get("four").equals(4)); 1227 1228 /* UnsupportedOperationException on direct modifications. */ 1229 try { 1230 unmod.put(4, "four"); 1231 fail("UnsupportedOperationException expected"); 1232 } catch (UnsupportedOperationException expected) {} 1233 try { 1234 unmod.forcePut(4, "four"); 1235 fail("UnsupportedOperationException expected"); 1236 } catch (UnsupportedOperationException expected) {} 1237 try { 1238 unmod.putAll(Collections.singletonMap(4, "four")); 1239 fail("UnsupportedOperationException expected"); 1240 } catch (UnsupportedOperationException expected) {} 1241 1242 /* UnsupportedOperationException on indirect modifications. */ 1243 BiMap<String, Number> inverse = unmod.inverse(); 1244 try { 1245 inverse.put("four", 4); 1246 fail("UnsupportedOperationException expected"); 1247 } catch (UnsupportedOperationException expected) {} 1248 try { 1249 inverse.forcePut("four", 4); 1250 fail("UnsupportedOperationException expected"); 1251 } catch (UnsupportedOperationException expected) {} 1252 try { 1253 inverse.putAll(Collections.singletonMap("four", 4)); 1254 fail("UnsupportedOperationException expected"); 1255 } catch (UnsupportedOperationException expected) {} 1256 Set<String> values = unmod.values(); 1257 try { 1258 values.remove("four"); 1259 fail("UnsupportedOperationException expected"); 1260 } catch (UnsupportedOperationException expected) {} 1261 Set<Map.Entry<Number, String>> entries = unmod.entrySet(); 1262 Map.Entry<Number, String> entry = entries.iterator().next(); 1263 try { 1264 entry.setValue("four"); 1265 fail("UnsupportedOperationException expected"); 1266 } catch (UnsupportedOperationException expected) {} 1267 @SuppressWarnings("unchecked") 1268 Map.Entry<Integer, String> entry2 1269 = (Map.Entry<Integer, String>) entries.toArray()[0]; 1270 try { 1271 entry2.setValue("four"); 1272 fail("UnsupportedOperationException expected"); 1273 } catch (UnsupportedOperationException expected) {} 1274 } 1275 testImmutableEntry()1276 public void testImmutableEntry() { 1277 Map.Entry<String, Integer> e = Maps.immutableEntry("foo", 1); 1278 assertEquals("foo", e.getKey()); 1279 assertEquals(1, (int) e.getValue()); 1280 try { 1281 e.setValue(2); 1282 fail("UnsupportedOperationException expected"); 1283 } catch (UnsupportedOperationException expected) {} 1284 assertEquals("foo=1", e.toString()); 1285 assertEquals(101575, e.hashCode()); 1286 } 1287 testImmutableEntryNull()1288 public void testImmutableEntryNull() { 1289 Map.Entry<String, Integer> e 1290 = Maps.immutableEntry((String) null, (Integer) null); 1291 assertNull(e.getKey()); 1292 assertNull(e.getValue()); 1293 try { 1294 e.setValue(null); 1295 fail("UnsupportedOperationException expected"); 1296 } catch (UnsupportedOperationException expected) {} 1297 assertEquals("null=null", e.toString()); 1298 assertEquals(0, e.hashCode()); 1299 } 1300 1301 /** See {@link SynchronizedBiMapTest} for more tests. */ testSynchronizedBiMap()1302 public void testSynchronizedBiMap() { 1303 BiMap<String, Integer> bimap = HashBiMap.create(); 1304 bimap.put("one", 1); 1305 BiMap<String, Integer> sync = Maps.synchronizedBiMap(bimap); 1306 bimap.put("two", 2); 1307 sync.put("three", 3); 1308 assertEquals(ImmutableSet.of(1, 2, 3), bimap.inverse().keySet()); 1309 assertEquals(ImmutableSet.of(1, 2, 3), sync.inverse().keySet()); 1310 } 1311 1312 private static final Predicate<String> NOT_LENGTH_3 1313 = new Predicate<String>() { 1314 @Override 1315 public boolean apply(String input) { 1316 return input == null || input.length() != 3; 1317 } 1318 }; 1319 1320 private static final Predicate<Integer> EVEN 1321 = new Predicate<Integer>() { 1322 @Override 1323 public boolean apply(Integer input) { 1324 return input == null || input % 2 == 0; 1325 } 1326 }; 1327 1328 private static final Predicate<Entry<String, Integer>> CORRECT_LENGTH 1329 = new Predicate<Entry<String, Integer>>() { 1330 @Override 1331 public boolean apply(Entry<String, Integer> input) { 1332 return input.getKey().length() == input.getValue(); 1333 } 1334 }; 1335 1336 private static final Function<Integer, Double> SQRT_FUNCTION = new Function<Integer, Double>() { 1337 @Override 1338 public Double apply(Integer in) { 1339 return Math.sqrt(in); 1340 } 1341 }; 1342 1343 public static class FilteredMapTest extends TestCase { createUnfiltered()1344 Map<String, Integer> createUnfiltered() { 1345 return Maps.newHashMap(); 1346 } 1347 testFilteredKeysIllegalPut()1348 public void testFilteredKeysIllegalPut() { 1349 Map<String, Integer> unfiltered = createUnfiltered(); 1350 Map<String, Integer> filtered = Maps.filterKeys(unfiltered, NOT_LENGTH_3); 1351 filtered.put("a", 1); 1352 filtered.put("b", 2); 1353 assertEquals(ImmutableMap.of("a", 1, "b", 2), filtered); 1354 1355 try { 1356 filtered.put("yyy", 3); 1357 fail(); 1358 } catch (IllegalArgumentException expected) {} 1359 } 1360 testFilteredKeysIllegalPutAll()1361 public void testFilteredKeysIllegalPutAll() { 1362 Map<String, Integer> unfiltered = createUnfiltered(); 1363 Map<String, Integer> filtered = Maps.filterKeys(unfiltered, NOT_LENGTH_3); 1364 filtered.put("a", 1); 1365 filtered.put("b", 2); 1366 assertEquals(ImmutableMap.of("a", 1, "b", 2), filtered); 1367 1368 try { 1369 filtered.putAll(ImmutableMap.of("c", 3, "zzz", 4, "b", 5)); 1370 fail(); 1371 } catch (IllegalArgumentException expected) {} 1372 1373 assertEquals(ImmutableMap.of("a", 1, "b", 2), filtered); 1374 } 1375 testFilteredKeysFilteredReflectsBackingChanges()1376 public void testFilteredKeysFilteredReflectsBackingChanges() { 1377 Map<String, Integer> unfiltered = createUnfiltered(); 1378 Map<String, Integer> filtered = Maps.filterKeys(unfiltered, NOT_LENGTH_3); 1379 unfiltered.put("two", 2); 1380 unfiltered.put("three", 3); 1381 unfiltered.put("four", 4); 1382 assertEquals(ImmutableMap.of("two", 2, "three", 3, "four", 4), unfiltered); 1383 assertEquals(ImmutableMap.of("three", 3, "four", 4), filtered); 1384 1385 unfiltered.remove("three"); 1386 assertEquals(ImmutableMap.of("two", 2, "four", 4), unfiltered); 1387 assertEquals(ImmutableMap.of("four", 4), filtered); 1388 1389 unfiltered.clear(); 1390 assertEquals(ImmutableMap.of(), unfiltered); 1391 assertEquals(ImmutableMap.of(), filtered); 1392 } 1393 testFilteredValuesIllegalPut()1394 public void testFilteredValuesIllegalPut() { 1395 Map<String, Integer> unfiltered = createUnfiltered(); 1396 Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN); 1397 filtered.put("a", 2); 1398 unfiltered.put("b", 4); 1399 unfiltered.put("c", 5); 1400 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered); 1401 1402 try { 1403 filtered.put("yyy", 3); 1404 fail(); 1405 } catch (IllegalArgumentException expected) {} 1406 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered); 1407 } 1408 testFilteredValuesIllegalPutAll()1409 public void testFilteredValuesIllegalPutAll() { 1410 Map<String, Integer> unfiltered = createUnfiltered(); 1411 Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN); 1412 filtered.put("a", 2); 1413 unfiltered.put("b", 4); 1414 unfiltered.put("c", 5); 1415 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered); 1416 1417 try { 1418 filtered.putAll(ImmutableMap.of("c", 4, "zzz", 5, "b", 6)); 1419 fail(); 1420 } catch (IllegalArgumentException expected) {} 1421 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered); 1422 } 1423 testFilteredValuesIllegalSetValue()1424 public void testFilteredValuesIllegalSetValue() { 1425 Map<String, Integer> unfiltered = createUnfiltered(); 1426 Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN); 1427 filtered.put("a", 2); 1428 filtered.put("b", 4); 1429 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered); 1430 1431 Entry<String, Integer> entry = filtered.entrySet().iterator().next(); 1432 try { 1433 entry.setValue(5); 1434 fail(); 1435 } catch (IllegalArgumentException expected) {} 1436 1437 assertEquals(ImmutableMap.of("a", 2, "b", 4), filtered); 1438 } 1439 testFilteredValuesClear()1440 public void testFilteredValuesClear() { 1441 Map<String, Integer> unfiltered = createUnfiltered(); 1442 unfiltered.put("one", 1); 1443 unfiltered.put("two", 2); 1444 unfiltered.put("three", 3); 1445 unfiltered.put("four", 4); 1446 Map<String, Integer> filtered = Maps.filterValues(unfiltered, EVEN); 1447 assertEquals(ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4), 1448 unfiltered); 1449 assertEquals(ImmutableMap.of("two", 2, "four", 4), filtered); 1450 1451 filtered.clear(); 1452 assertEquals(ImmutableMap.of("one", 1, "three", 3), unfiltered); 1453 assertTrue(filtered.isEmpty()); 1454 } 1455 testFilteredEntriesIllegalPut()1456 public void testFilteredEntriesIllegalPut() { 1457 Map<String, Integer> unfiltered = createUnfiltered(); 1458 unfiltered.put("cat", 3); 1459 unfiltered.put("dog", 2); 1460 unfiltered.put("horse", 5); 1461 Map<String, Integer> filtered 1462 = Maps.filterEntries(unfiltered, CORRECT_LENGTH); 1463 assertEquals(ImmutableMap.of("cat", 3, "horse", 5), filtered); 1464 1465 filtered.put("chicken", 7); 1466 assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered); 1467 1468 try { 1469 filtered.put("cow", 7); 1470 fail(); 1471 } catch (IllegalArgumentException expected) {} 1472 assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered); 1473 } 1474 testFilteredEntriesIllegalPutAll()1475 public void testFilteredEntriesIllegalPutAll() { 1476 Map<String, Integer> unfiltered = createUnfiltered(); 1477 unfiltered.put("cat", 3); 1478 unfiltered.put("dog", 2); 1479 unfiltered.put("horse", 5); 1480 Map<String, Integer> filtered 1481 = Maps.filterEntries(unfiltered, CORRECT_LENGTH); 1482 assertEquals(ImmutableMap.of("cat", 3, "horse", 5), filtered); 1483 1484 filtered.put("chicken", 7); 1485 assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered); 1486 1487 try { 1488 filtered.putAll(ImmutableMap.of("sheep", 5, "cow", 7)); 1489 fail(); 1490 } catch (IllegalArgumentException expected) {} 1491 assertEquals(ImmutableMap.of("cat", 3, "horse", 5, "chicken", 7), filtered); 1492 } 1493 testFilteredEntriesObjectPredicate()1494 public void testFilteredEntriesObjectPredicate() { 1495 Map<String, Integer> unfiltered = createUnfiltered(); 1496 unfiltered.put("cat", 3); 1497 unfiltered.put("dog", 2); 1498 unfiltered.put("horse", 5); 1499 Predicate<Object> predicate = Predicates.alwaysFalse(); 1500 Map<String, Integer> filtered 1501 = Maps.filterEntries(unfiltered, predicate); 1502 assertTrue(filtered.isEmpty()); 1503 } 1504 testFilteredEntriesWildCardEntryPredicate()1505 public void testFilteredEntriesWildCardEntryPredicate() { 1506 Map<String, Integer> unfiltered = createUnfiltered(); 1507 unfiltered.put("cat", 3); 1508 unfiltered.put("dog", 2); 1509 unfiltered.put("horse", 5); 1510 Predicate<Entry<?, ?>> predicate = new Predicate<Entry<?, ?>>() { 1511 @Override 1512 public boolean apply(Entry<?, ?> input) { 1513 return "cat".equals(input.getKey()) 1514 || Integer.valueOf(2) == input.getValue(); 1515 } 1516 }; 1517 Map<String, Integer> filtered 1518 = Maps.filterEntries(unfiltered, predicate); 1519 assertEquals(ImmutableMap.of("cat", 3, "dog", 2), filtered); 1520 } 1521 } 1522 1523 public static class FilteredSortedMapTest extends FilteredMapTest { 1524 @Override createUnfiltered()1525 SortedMap<String, Integer> createUnfiltered() { 1526 return Maps.newTreeMap(); 1527 } 1528 testFilterKeysIdentifiesSortedMap()1529 public void testFilterKeysIdentifiesSortedMap() { 1530 SortedMap<String, Integer> map = createUnfiltered(); 1531 assertTrue(Maps.filterKeys((Map<String, Integer>) map, NOT_LENGTH_3) 1532 instanceof SortedMap); 1533 } 1534 testFilterValuesIdentifiesSortedMap()1535 public void testFilterValuesIdentifiesSortedMap() { 1536 SortedMap<String, Integer> map = createUnfiltered(); 1537 assertTrue(Maps.filterValues((Map<String, Integer>) map, EVEN) 1538 instanceof SortedMap); 1539 } 1540 testFilterEntriesIdentifiesSortedMap()1541 public void testFilterEntriesIdentifiesSortedMap() { 1542 SortedMap<String, Integer> map = createUnfiltered(); 1543 assertTrue(Maps.filterEntries((Map<String, Integer>) map, CORRECT_LENGTH) 1544 instanceof SortedMap); 1545 } 1546 testFirstAndLastKeyFilteredMap()1547 public void testFirstAndLastKeyFilteredMap() { 1548 SortedMap<String, Integer> unfiltered = createUnfiltered(); 1549 unfiltered.put("apple", 2); 1550 unfiltered.put("banana", 6); 1551 unfiltered.put("cat", 3); 1552 unfiltered.put("dog", 5); 1553 1554 SortedMap<String, Integer> filtered = Maps.filterEntries(unfiltered, CORRECT_LENGTH); 1555 assertEquals("banana", filtered.firstKey()); 1556 assertEquals("cat", filtered.lastKey()); 1557 } 1558 testHeadSubTailMap_FilteredMap()1559 public void testHeadSubTailMap_FilteredMap() { 1560 SortedMap<String, Integer> unfiltered = createUnfiltered(); 1561 unfiltered.put("apple", 2); 1562 unfiltered.put("banana", 6); 1563 unfiltered.put("cat", 4); 1564 unfiltered.put("dog", 3); 1565 SortedMap<String, Integer> filtered = Maps.filterEntries(unfiltered, CORRECT_LENGTH); 1566 1567 assertEquals(ImmutableMap.of("banana", 6), filtered.headMap("dog")); 1568 assertEquals(ImmutableMap.of(), filtered.headMap("banana")); 1569 assertEquals(ImmutableMap.of("banana", 6, "dog", 3), filtered.headMap("emu")); 1570 1571 assertEquals(ImmutableMap.of("banana", 6), filtered.subMap("banana", "dog")); 1572 assertEquals(ImmutableMap.of("dog", 3), filtered.subMap("cat", "emu")); 1573 1574 assertEquals(ImmutableMap.of("dog", 3), filtered.tailMap("cat")); 1575 assertEquals(ImmutableMap.of("banana", 6, "dog", 3), filtered.tailMap("banana")); 1576 } 1577 } 1578 1579 public static class FilteredBiMapTest extends FilteredMapTest { 1580 @Override createUnfiltered()1581 BiMap<String, Integer> createUnfiltered() { 1582 return HashBiMap.create(); 1583 } 1584 testFilterKeysIdentifiesBiMap()1585 public void testFilterKeysIdentifiesBiMap() { 1586 BiMap<String, Integer> map = createUnfiltered(); 1587 assertTrue(Maps.filterKeys((Map<String, Integer>) map, NOT_LENGTH_3) 1588 instanceof BiMap); 1589 } 1590 testFilterValuesIdentifiesBiMap()1591 public void testFilterValuesIdentifiesBiMap() { 1592 BiMap<String, Integer> map = createUnfiltered(); 1593 assertTrue(Maps.filterValues((Map<String, Integer>) map, EVEN) 1594 instanceof BiMap); 1595 } 1596 testFilterEntriesIdentifiesBiMap()1597 public void testFilterEntriesIdentifiesBiMap() { 1598 BiMap<String, Integer> map = createUnfiltered(); 1599 assertTrue(Maps.filterEntries((Map<String, Integer>) map, CORRECT_LENGTH) 1600 instanceof BiMap); 1601 } 1602 } 1603 testTransformValues()1604 public void testTransformValues() { 1605 Map<String, Integer> map = ImmutableMap.of("a", 4, "b", 9); 1606 Map<String, Double> transformed = transformValues(map, SQRT_FUNCTION); 1607 1608 assertEquals(ImmutableMap.of("a", 2.0, "b", 3.0), transformed); 1609 } 1610 testTransformValuesSecretlySorted()1611 public void testTransformValuesSecretlySorted() { 1612 Map<String, Integer> map = 1613 sortedNotNavigable(ImmutableSortedMap.of("a", 4, "b", 9)); 1614 Map<String, Double> transformed = transformValues(map, SQRT_FUNCTION); 1615 1616 assertEquals(ImmutableMap.of("a", 2.0, "b", 3.0), transformed); 1617 assertTrue(transformed instanceof SortedMap); 1618 } 1619 1620 @GwtIncompatible("NavigableMap") testTransformValuesSecretlyNavigable()1621 public void testTransformValuesSecretlyNavigable() { 1622 Map<String, Integer> map = ImmutableSortedMap.of("a", 4, "b", 9); 1623 Map<String, Double> transformed; 1624 1625 transformed = transformValues(map, SQRT_FUNCTION); 1626 assertEquals(ImmutableMap.of("a", 2.0, "b", 3.0), transformed); 1627 assertTrue(transformed instanceof NavigableMap); 1628 1629 transformed = 1630 transformValues((SortedMap<String, Integer>) map, SQRT_FUNCTION); 1631 assertEquals(ImmutableMap.of("a", 2.0, "b", 3.0), transformed); 1632 assertTrue(transformed instanceof NavigableMap); 1633 } 1634 testTransformEntries()1635 public void testTransformEntries() { 1636 Map<String, String> map = ImmutableMap.of("a", "4", "b", "9"); 1637 EntryTransformer<String, String, String> concat = 1638 new EntryTransformer<String, String, String>() { 1639 @Override 1640 public String transformEntry(String key, String value) { 1641 return key + value; 1642 } 1643 }; 1644 Map<String, String> transformed = transformEntries(map, concat); 1645 1646 assertEquals(ImmutableMap.of("a", "a4", "b", "b9"), transformed); 1647 } 1648 testTransformEntriesSecretlySorted()1649 public void testTransformEntriesSecretlySorted() { 1650 Map<String, String> map = ImmutableSortedMap.of("a", "4", "b", "9"); 1651 EntryTransformer<String, String, String> concat = 1652 new EntryTransformer<String, String, String>() { 1653 @Override 1654 public String transformEntry(String key, String value) { 1655 return key + value; 1656 } 1657 }; 1658 Map<String, String> transformed = transformEntries(map, concat); 1659 1660 assertEquals(ImmutableMap.of("a", "a4", "b", "b9"), transformed); 1661 assertTrue(transformed instanceof SortedMap); 1662 } 1663 1664 @GwtIncompatible("NavigableMap") testTransformEntriesSecretlyNavigable()1665 public void testTransformEntriesSecretlyNavigable() { 1666 Map<String, String> map = ImmutableSortedMap.of("a", "4", "b", "9"); 1667 EntryTransformer<String, String, String> concat = 1668 new EntryTransformer<String, String, String>() { 1669 @Override 1670 public String transformEntry(String key, String value) { 1671 return key + value; 1672 } 1673 }; 1674 Map<String, String> transformed; 1675 1676 transformed = transformEntries(map, concat); 1677 assertEquals(ImmutableMap.of("a", "a4", "b", "b9"), transformed); 1678 assertTrue(transformed instanceof NavigableMap); 1679 1680 transformed = transformEntries((SortedMap<String, String>) map, concat); 1681 assertEquals(ImmutableMap.of("a", "a4", "b", "b9"), transformed); 1682 assertTrue(transformed instanceof NavigableMap); 1683 } 1684 1685 @SuppressWarnings("unused") testTransformEntriesGenerics()1686 public void testTransformEntriesGenerics() { 1687 Map<Object, Object> map1 = ImmutableMap.<Object, Object>of(1, 2); 1688 Map<Object, Number> map2 = ImmutableMap.<Object, Number>of(1, 2); 1689 Map<Object, Integer> map3 = ImmutableMap.<Object, Integer>of(1, 2); 1690 Map<Number, Object> map4 = ImmutableMap.<Number, Object>of(1, 2); 1691 Map<Number, Number> map5 = ImmutableMap.<Number, Number>of(1, 2); 1692 Map<Number, Integer> map6 = ImmutableMap.<Number, Integer>of(1, 2); 1693 Map<Integer, Object> map7 = ImmutableMap.<Integer, Object>of(1, 2); 1694 Map<Integer, Number> map8 = ImmutableMap.<Integer, Number>of(1, 2); 1695 Map<Integer, Integer> map9 = ImmutableMap.<Integer, Integer>of(1, 2); 1696 Map<? extends Number, ? extends Number> map0 = ImmutableMap.of(1, 2); 1697 1698 EntryTransformer<Number, Number, Double> transformer = 1699 new EntryTransformer<Number, Number, Double>() { 1700 @Override 1701 public Double transformEntry(Number key, Number value) { 1702 return key.doubleValue() + value.doubleValue(); 1703 } 1704 }; 1705 1706 Map<Object, Double> objectKeyed; 1707 Map<Number, Double> numberKeyed; 1708 Map<Integer, Double> integerKeyed; 1709 1710 numberKeyed = transformEntries(map5, transformer); 1711 numberKeyed = transformEntries(map6, transformer); 1712 integerKeyed = transformEntries(map8, transformer); 1713 integerKeyed = transformEntries(map9, transformer); 1714 1715 Map<? extends Number, Double> wildcarded = transformEntries(map0, transformer); 1716 1717 // Can't loosen the key type: 1718 // objectKeyed = transformEntries(map5, transformer); 1719 // objectKeyed = transformEntries(map6, transformer); 1720 // objectKeyed = transformEntries(map8, transformer); 1721 // objectKeyed = transformEntries(map9, transformer); 1722 // numberKeyed = transformEntries(map8, transformer); 1723 // numberKeyed = transformEntries(map9, transformer); 1724 1725 // Can't loosen the value type: 1726 // Map<Number, Number> looseValued1 = transformEntries(map5, transformer); 1727 // Map<Number, Number> looseValued2 = transformEntries(map6, transformer); 1728 // Map<Integer, Number> looseValued3 = transformEntries(map8, transformer); 1729 // Map<Integer, Number> looseValued4 = transformEntries(map9, transformer); 1730 1731 // Can't call with too loose a key: 1732 // transformEntries(map1, transformer); 1733 // transformEntries(map2, transformer); 1734 // transformEntries(map3, transformer); 1735 1736 // Can't call with too loose a value: 1737 // transformEntries(map1, transformer); 1738 // transformEntries(map4, transformer); 1739 // transformEntries(map7, transformer); 1740 } 1741 testTransformEntriesExample()1742 public void testTransformEntriesExample() { 1743 Map<String, Boolean> options = 1744 ImmutableMap.of("verbose", true, "sort", false); 1745 EntryTransformer<String, Boolean, String> flagPrefixer = 1746 new EntryTransformer<String, Boolean, String>() { 1747 @Override 1748 public String transformEntry(String key, Boolean value) { 1749 return value ? key : "no" + key; 1750 } 1751 }; 1752 Map<String, String> transformed = transformEntries(options, flagPrefixer); 1753 assertEquals("{verbose=verbose, sort=nosort}", transformed.toString()); 1754 } 1755 1756 // Logically this would accept a NavigableMap, but that won't work under GWT. sortedNotNavigable( final SortedMap<K, V> map)1757 private static <K, V> SortedMap<K, V> sortedNotNavigable( 1758 final SortedMap<K, V> map) { 1759 return new ForwardingSortedMap<K, V>() { 1760 @Override protected SortedMap<K, V> delegate() { 1761 return map; 1762 } 1763 }; 1764 } 1765 1766 public void testSortedMapTransformValues() { 1767 SortedMap<String, Integer> map = 1768 sortedNotNavigable(ImmutableSortedMap.of("a", 4, "b", 9)); 1769 SortedMap<String, Double> transformed = 1770 transformValues(map, SQRT_FUNCTION); 1771 1772 /* 1773 * We'd like to sanity check that we didn't get a NavigableMap out, but we 1774 * can't easily do so while maintaining GWT compatibility. 1775 */ 1776 assertEquals(ImmutableSortedMap.of("a", 2.0, "b", 3.0), transformed); 1777 } 1778 1779 @GwtIncompatible("NavigableMap") 1780 public void testNavigableMapTransformValues() { 1781 NavigableMap<String, Integer> map = ImmutableSortedMap.of("a", 4, "b", 9); 1782 NavigableMap<String, Double> transformed = 1783 transformValues(map, SQRT_FUNCTION); 1784 1785 assertEquals(ImmutableSortedMap.of("a", 2.0, "b", 3.0), transformed); 1786 } 1787 1788 public void testSortedMapTransformEntries() { 1789 SortedMap<String, String> map = 1790 sortedNotNavigable(ImmutableSortedMap.of("a", "4", "b", "9")); 1791 EntryTransformer<String, String, String> concat = 1792 new EntryTransformer<String, String, String>() { 1793 @Override 1794 public String transformEntry(String key, String value) { 1795 return key + value; 1796 } 1797 }; 1798 SortedMap<String, String> transformed = transformEntries(map, concat); 1799 1800 /* 1801 * We'd like to sanity check that we didn't get a NavigableMap out, but we 1802 * can't easily do so while maintaining GWT compatibility. 1803 */ 1804 assertEquals(ImmutableSortedMap.of("a", "a4", "b", "b9"), transformed); 1805 } 1806 1807 @GwtIncompatible("NavigableMap") 1808 public void testNavigableMapTransformEntries() { 1809 NavigableMap<String, String> map = 1810 ImmutableSortedMap.of("a", "4", "b", "9"); 1811 EntryTransformer<String, String, String> concat = 1812 new EntryTransformer<String, String, String>() { 1813 @Override 1814 public String transformEntry(String key, String value) { 1815 return key + value; 1816 } 1817 }; 1818 NavigableMap<String, String> transformed = transformEntries(map, concat); 1819 1820 assertEquals(ImmutableSortedMap.of("a", "a4", "b", "b9"), transformed); 1821 } 1822 1823 @GwtIncompatible("NavigableMap") 1824 public void testUnmodifiableNavigableMap() { 1825 TreeMap<Integer, String> mod = Maps.newTreeMap(); 1826 mod.put(1, "one"); 1827 mod.put(2, "two"); 1828 mod.put(3, "three"); 1829 1830 NavigableMap<Integer, String> unmod = unmodifiableNavigableMap(mod); 1831 1832 /* unmod is a view. */ 1833 mod.put(4, "four"); 1834 assertEquals("four", unmod.get(4)); 1835 assertEquals("four", unmod.descendingMap().get(4)); 1836 1837 ensureNotDirectlyModifiable(unmod); 1838 ensureNotDirectlyModifiable(unmod.descendingMap()); 1839 ensureNotDirectlyModifiable(unmod.headMap(2, true)); 1840 ensureNotDirectlyModifiable(unmod.subMap(1, true, 3, true)); 1841 ensureNotDirectlyModifiable(unmod.tailMap(2, true)); 1842 1843 Collection<String> values = unmod.values(); 1844 try { 1845 values.add("4"); 1846 fail("UnsupportedOperationException expected"); 1847 } catch (UnsupportedOperationException expected) { 1848 } 1849 try { 1850 values.remove("four"); 1851 fail("UnsupportedOperationException expected"); 1852 } catch (UnsupportedOperationException expected) { 1853 } 1854 try { 1855 values.removeAll(Collections.singleton("four")); 1856 fail("UnsupportedOperationException expected"); 1857 } catch (UnsupportedOperationException expected) { 1858 } 1859 try { 1860 values.retainAll(Collections.singleton("four")); 1861 fail("UnsupportedOperationException expected"); 1862 } catch (UnsupportedOperationException expected) { 1863 } 1864 try { 1865 Iterator<String> iterator = values.iterator(); 1866 iterator.next(); 1867 iterator.remove(); 1868 fail("UnsupportedOperationException expected"); 1869 } catch (UnsupportedOperationException expected) { 1870 } 1871 1872 Set<Map.Entry<Integer, String>> entries = unmod.entrySet(); 1873 try { 1874 Iterator<Map.Entry<Integer, String>> iterator = entries.iterator(); 1875 iterator.next(); 1876 iterator.remove(); 1877 fail("UnsupportedOperationException expected"); 1878 } catch (UnsupportedOperationException expected) { 1879 } 1880 Map.Entry<Integer, String> entry = entries.iterator().next(); 1881 try { 1882 entry.setValue("four"); 1883 fail("UnsupportedOperationException expected"); 1884 } catch (UnsupportedOperationException expected) { 1885 } 1886 entry = unmod.lowerEntry(1); 1887 assertNull(entry); 1888 entry = unmod.floorEntry(2); 1889 try { 1890 entry.setValue("four"); 1891 fail("UnsupportedOperationException expected"); 1892 } catch (UnsupportedOperationException expected) { 1893 } 1894 entry = unmod.ceilingEntry(2); 1895 try { 1896 entry.setValue("four"); 1897 fail("UnsupportedOperationException expected"); 1898 } catch (UnsupportedOperationException expected) { 1899 } 1900 entry = unmod.lowerEntry(2); 1901 try { 1902 entry.setValue("four"); 1903 fail("UnsupportedOperationException expected"); 1904 } catch (UnsupportedOperationException expected) { 1905 } 1906 entry = unmod.higherEntry(2); 1907 try { 1908 entry.setValue("four"); 1909 fail("UnsupportedOperationException expected"); 1910 } catch (UnsupportedOperationException expected) { 1911 } 1912 entry = unmod.firstEntry(); 1913 try { 1914 entry.setValue("four"); 1915 fail("UnsupportedOperationException expected"); 1916 } catch (UnsupportedOperationException expected) { 1917 } 1918 entry = unmod.lastEntry(); 1919 try { 1920 entry.setValue("four"); 1921 fail("UnsupportedOperationException expected"); 1922 } catch (UnsupportedOperationException expected) { 1923 } 1924 @SuppressWarnings("unchecked") 1925 Map.Entry<Integer, String> entry2 = 1926 (Map.Entry<Integer, String>) entries.toArray()[0]; 1927 try { 1928 entry2.setValue("four"); 1929 fail("UnsupportedOperationException expected"); 1930 } catch (UnsupportedOperationException expected) { 1931 } 1932 } 1933 1934 @GwtIncompatible("NavigableMap") 1935 void ensureNotDirectlyModifiable(NavigableMap<Integer, String> unmod) { 1936 try { 1937 unmod.put(4, "four"); 1938 fail("UnsupportedOperationException expected"); 1939 } catch (UnsupportedOperationException expected) { 1940 } 1941 try { 1942 unmod.putAll(Collections.singletonMap(4, "four")); 1943 fail("UnsupportedOperationException expected"); 1944 } catch (UnsupportedOperationException expected) { 1945 } 1946 try { 1947 unmod.remove("four"); 1948 fail("UnsupportedOperationException expected"); 1949 } catch (UnsupportedOperationException expected) { 1950 } 1951 try { 1952 unmod.pollFirstEntry(); 1953 fail("UnsupportedOperationException expected"); 1954 } catch (UnsupportedOperationException expected) { 1955 } 1956 try { 1957 unmod.pollLastEntry(); 1958 fail("UnsupportedOperationException expected"); 1959 } catch (UnsupportedOperationException expected) { 1960 } 1961 } 1962 } 1963