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.testing; 18 19 import static java.util.Collections.singleton; 20 21 import com.google.common.annotations.GwtCompatible; 22 23 import junit.framework.TestCase; 24 25 import java.util.Arrays; 26 import java.util.Collection; 27 import java.util.Collections; 28 import java.util.HashSet; 29 import java.util.Iterator; 30 import java.util.Map; 31 import java.util.Map.Entry; 32 import java.util.Set; 33 34 /** 35 * Tests representing the contract of {@link Map}. Concrete subclasses of this 36 * base class test conformance of concrete {@link Map} subclasses to that 37 * contract. 38 * 39 * TODO: Descriptive assertion messages, with hints as to probable 40 * fixes. 41 * TODO: Add another constructor parameter indicating whether the 42 * class under test is ordered, and check the order if so. 43 * TODO: Refactor to share code with SetTestBuilder &c. 44 * 45 * @param <K> the type of keys used by the maps under test 46 * @param <V> the type of mapped values used the maps under test 47 * 48 * @author George van den Driessche 49 */ 50 @GwtCompatible 51 public abstract class MapInterfaceTest<K, V> extends TestCase { 52 53 /** A key type that is not assignable to any classes but Object. */ 54 private static final class IncompatibleKeyType { toString()55 @Override public String toString() { 56 return "IncompatibleKeyType"; 57 } 58 } 59 60 protected final boolean supportsPut; 61 protected final boolean supportsRemove; 62 protected final boolean supportsClear; 63 protected final boolean allowsNullKeys; 64 protected final boolean allowsNullValues; 65 protected final boolean supportsIteratorRemove; 66 67 /** 68 * Creates a new, empty instance of the class under test. 69 * 70 * @return a new, empty map instance. 71 * @throws UnsupportedOperationException if it's not possible to make an 72 * empty instance of the class under test. 73 */ makeEmptyMap()74 protected abstract Map<K, V> makeEmptyMap() 75 throws UnsupportedOperationException; 76 77 /** 78 * Creates a new, non-empty instance of the class under test. 79 * 80 * @return a new, non-empty map instance. 81 * @throws UnsupportedOperationException if it's not possible to make a 82 * non-empty instance of the class under test. 83 */ makePopulatedMap()84 protected abstract Map<K, V> makePopulatedMap() 85 throws UnsupportedOperationException; 86 87 /** 88 * Creates a new key that is not expected to be found 89 * in {@link #makePopulatedMap()}. 90 * 91 * @return a key. 92 * @throws UnsupportedOperationException if it's not possible to make a key 93 * that will not be found in the map. 94 */ getKeyNotInPopulatedMap()95 protected abstract K getKeyNotInPopulatedMap() 96 throws UnsupportedOperationException; 97 98 /** 99 * Creates a new value that is not expected to be found 100 * in {@link #makePopulatedMap()}. 101 * 102 * @return a value. 103 * @throws UnsupportedOperationException if it's not possible to make a value 104 * that will not be found in the map. 105 */ getValueNotInPopulatedMap()106 protected abstract V getValueNotInPopulatedMap() 107 throws UnsupportedOperationException; 108 109 /** 110 * Constructor that assigns {@code supportsIteratorRemove} the same value as 111 * {@code supportsRemove}. 112 */ MapInterfaceTest( boolean allowsNullKeys, boolean allowsNullValues, boolean supportsPut, boolean supportsRemove, boolean supportsClear)113 protected MapInterfaceTest( 114 boolean allowsNullKeys, 115 boolean allowsNullValues, 116 boolean supportsPut, 117 boolean supportsRemove, 118 boolean supportsClear) { 119 this(allowsNullKeys, allowsNullValues, supportsPut, supportsRemove, 120 supportsClear, supportsRemove); 121 } 122 123 /** 124 * Constructor with an explicit {@code supportsIteratorRemove} parameter. 125 */ MapInterfaceTest( boolean allowsNullKeys, boolean allowsNullValues, boolean supportsPut, boolean supportsRemove, boolean supportsClear, boolean supportsIteratorRemove)126 protected MapInterfaceTest( 127 boolean allowsNullKeys, 128 boolean allowsNullValues, 129 boolean supportsPut, 130 boolean supportsRemove, 131 boolean supportsClear, 132 boolean supportsIteratorRemove) { 133 this.supportsPut = supportsPut; 134 this.supportsRemove = supportsRemove; 135 this.supportsClear = supportsClear; 136 this.allowsNullKeys = allowsNullKeys; 137 this.allowsNullValues = allowsNullValues; 138 this.supportsIteratorRemove = supportsIteratorRemove; 139 } 140 141 /** 142 * Used by tests that require a map, but don't care whether it's 143 * populated or not. 144 * 145 * @return a new map instance. 146 */ makeEitherMap()147 protected Map<K, V> makeEitherMap() { 148 try { 149 return makePopulatedMap(); 150 } catch (UnsupportedOperationException e) { 151 return makeEmptyMap(); 152 } 153 } 154 supportsValuesHashCode(Map<K, V> map)155 protected final boolean supportsValuesHashCode(Map<K, V> map) { 156 // get the first non-null value 157 Collection<V> values = map.values(); 158 for (V value : values) { 159 if (value != null) { 160 try { 161 value.hashCode(); 162 } catch (Exception e) { 163 return false; 164 } 165 return true; 166 } 167 } 168 return true; 169 } 170 171 /** 172 * Checks all the properties that should always hold of a map. Also calls 173 * {@link #assertMoreInvariants} to check invariants that are peculiar to 174 * specific implementations. 175 * 176 * @see #assertMoreInvariants 177 * @param map the map to check. 178 */ assertInvariants(Map<K, V> map)179 protected final void assertInvariants(Map<K, V> map) { 180 Set<K> keySet = map.keySet(); 181 Collection<V> valueCollection = map.values(); 182 Set<Entry<K, V>> entrySet = map.entrySet(); 183 184 assertEquals(map.size() == 0, map.isEmpty()); 185 assertEquals(map.size(), keySet.size()); 186 assertEquals(keySet.size() == 0, keySet.isEmpty()); 187 assertEquals(!keySet.isEmpty(), keySet.iterator().hasNext()); 188 189 int expectedKeySetHash = 0; 190 for (K key : keySet) { 191 V value = map.get(key); 192 expectedKeySetHash += key != null ? key.hashCode() : 0; 193 assertTrue(map.containsKey(key)); 194 assertTrue(map.containsValue(value)); 195 assertTrue(valueCollection.contains(value)); 196 assertTrue(valueCollection.containsAll(Collections.singleton(value))); 197 assertTrue(entrySet.contains(mapEntry(key, value))); 198 assertTrue(allowsNullKeys || (key != null)); 199 } 200 assertEquals(expectedKeySetHash, keySet.hashCode()); 201 202 assertEquals(map.size(), valueCollection.size()); 203 assertEquals(valueCollection.size() == 0, valueCollection.isEmpty()); 204 assertEquals( 205 !valueCollection.isEmpty(), valueCollection.iterator().hasNext()); 206 for (V value : valueCollection) { 207 assertTrue(map.containsValue(value)); 208 assertTrue(allowsNullValues || (value != null)); 209 } 210 211 assertEquals(map.size(), entrySet.size()); 212 assertEquals(entrySet.size() == 0, entrySet.isEmpty()); 213 assertEquals(!entrySet.isEmpty(), entrySet.iterator().hasNext()); 214 assertFalse(entrySet.contains("foo")); 215 216 boolean supportsValuesHashCode = supportsValuesHashCode(map); 217 if (supportsValuesHashCode) { 218 int expectedEntrySetHash = 0; 219 for (Entry<K, V> entry : entrySet) { 220 assertTrue(map.containsKey(entry.getKey())); 221 assertTrue(map.containsValue(entry.getValue())); 222 int expectedHash = 223 (entry.getKey() == null ? 0 : entry.getKey().hashCode()) ^ 224 (entry.getValue() == null ? 0 : entry.getValue().hashCode()); 225 assertEquals(expectedHash, entry.hashCode()); 226 expectedEntrySetHash += expectedHash; 227 } 228 assertEquals(expectedEntrySetHash, entrySet.hashCode()); 229 assertTrue(entrySet.containsAll(new HashSet<Entry<K, V>>(entrySet))); 230 assertTrue(entrySet.equals(new HashSet<Entry<K, V>>(entrySet))); 231 } 232 233 Object[] entrySetToArray1 = entrySet.toArray(); 234 assertEquals(map.size(), entrySetToArray1.length); 235 assertTrue(Arrays.asList(entrySetToArray1).containsAll(entrySet)); 236 237 Entry<?, ?>[] entrySetToArray2 = new Entry<?, ?>[map.size() + 2]; 238 entrySetToArray2[map.size()] = mapEntry("foo", 1); 239 assertSame(entrySetToArray2, entrySet.toArray(entrySetToArray2)); 240 assertNull(entrySetToArray2[map.size()]); 241 assertTrue(Arrays.asList(entrySetToArray2).containsAll(entrySet)); 242 243 Object[] valuesToArray1 = valueCollection.toArray(); 244 assertEquals(map.size(), valuesToArray1.length); 245 assertTrue(Arrays.asList(valuesToArray1).containsAll(valueCollection)); 246 247 Object[] valuesToArray2 = new Object[map.size() + 2]; 248 valuesToArray2[map.size()] = "foo"; 249 assertSame(valuesToArray2, valueCollection.toArray(valuesToArray2)); 250 assertNull(valuesToArray2[map.size()]); 251 assertTrue(Arrays.asList(valuesToArray2).containsAll(valueCollection)); 252 253 if (supportsValuesHashCode) { 254 int expectedHash = 0; 255 for (Entry<K, V> entry : entrySet) { 256 expectedHash += entry.hashCode(); 257 } 258 assertEquals(expectedHash, map.hashCode()); 259 } 260 261 assertMoreInvariants(map); 262 } 263 264 /** 265 * Override this to check invariants which should hold true for a particular 266 * implementation, but which are not generally applicable to every instance 267 * of Map. 268 * 269 * @param map the map whose additional invariants to check. 270 */ assertMoreInvariants(Map<K, V> map)271 protected void assertMoreInvariants(Map<K, V> map) { 272 } 273 testClear()274 public void testClear() { 275 final Map<K, V> map; 276 try { 277 map = makePopulatedMap(); 278 } catch (UnsupportedOperationException e) { 279 return; 280 } 281 282 if (supportsClear) { 283 map.clear(); 284 assertTrue(map.isEmpty()); 285 } else { 286 try { 287 map.clear(); 288 fail("Expected UnsupportedOperationException."); 289 } catch (UnsupportedOperationException e) { 290 // Expected. 291 } 292 } 293 assertInvariants(map); 294 } 295 testContainsKey()296 public void testContainsKey() { 297 final Map<K, V> map; 298 final K unmappedKey; 299 try { 300 map = makePopulatedMap(); 301 unmappedKey = getKeyNotInPopulatedMap(); 302 } catch (UnsupportedOperationException e) { 303 return; 304 } 305 assertFalse(map.containsKey(unmappedKey)); 306 try { 307 assertFalse(map.containsKey(new IncompatibleKeyType())); 308 } catch (ClassCastException tolerated) {} 309 assertTrue(map.containsKey(map.keySet().iterator().next())); 310 if (allowsNullKeys) { 311 map.containsKey(null); 312 } else { 313 try { 314 map.containsKey(null); 315 } catch (NullPointerException optional) { 316 } 317 } 318 assertInvariants(map); 319 } 320 testContainsValue()321 public void testContainsValue() { 322 final Map<K, V> map; 323 final V unmappedValue; 324 try { 325 map = makePopulatedMap(); 326 unmappedValue = getValueNotInPopulatedMap(); 327 } catch (UnsupportedOperationException e) { 328 return; 329 } 330 assertFalse(map.containsValue(unmappedValue)); 331 assertTrue(map.containsValue(map.values().iterator().next())); 332 if (allowsNullValues) { 333 map.containsValue(null); 334 } else { 335 try { 336 map.containsKey(null); 337 } catch (NullPointerException optional) { 338 } 339 } 340 assertInvariants(map); 341 } 342 testEntrySet()343 public void testEntrySet() { 344 final Map<K, V> map; 345 final Set<Entry<K, V>> entrySet; 346 try { 347 map = makePopulatedMap(); 348 } catch (UnsupportedOperationException e) { 349 return; 350 } 351 assertInvariants(map); 352 353 entrySet = map.entrySet(); 354 final K unmappedKey; 355 final V unmappedValue; 356 try { 357 unmappedKey = getKeyNotInPopulatedMap(); 358 unmappedValue = getValueNotInPopulatedMap(); 359 } catch (UnsupportedOperationException e) { 360 return; 361 } 362 for (Entry<K, V> entry : entrySet) { 363 assertFalse(unmappedKey.equals(entry.getKey())); 364 assertFalse(unmappedValue.equals(entry.getValue())); 365 } 366 } 367 testEntrySetForEmptyMap()368 public void testEntrySetForEmptyMap() { 369 final Map<K, V> map; 370 try { 371 map = makeEmptyMap(); 372 } catch (UnsupportedOperationException e) { 373 return; 374 } 375 assertInvariants(map); 376 } 377 testEntrySetContainsEntryIncompatibleKey()378 public void testEntrySetContainsEntryIncompatibleKey() { 379 final Map<K, V> map; 380 final Set<Entry<K, V>> entrySet; 381 try { 382 map = makeEitherMap(); 383 } catch (UnsupportedOperationException e) { 384 return; 385 } 386 assertInvariants(map); 387 388 entrySet = map.entrySet(); 389 final V unmappedValue; 390 try { 391 unmappedValue = getValueNotInPopulatedMap(); 392 } catch (UnsupportedOperationException e) { 393 return; 394 } 395 Entry<IncompatibleKeyType, V> entry 396 = mapEntry(new IncompatibleKeyType(), unmappedValue); 397 try { 398 assertFalse(entrySet.contains(entry)); 399 } catch (ClassCastException tolerated) {} 400 } 401 testEntrySetContainsEntryNullKeyPresent()402 public void testEntrySetContainsEntryNullKeyPresent() { 403 if (!allowsNullKeys || !supportsPut) { 404 return; 405 } 406 final Map<K, V> map; 407 final Set<Entry<K, V>> entrySet; 408 try { 409 map = makeEitherMap(); 410 } catch (UnsupportedOperationException e) { 411 return; 412 } 413 assertInvariants(map); 414 415 entrySet = map.entrySet(); 416 final V unmappedValue; 417 try { 418 unmappedValue = getValueNotInPopulatedMap(); 419 } catch (UnsupportedOperationException e) { 420 return; 421 } 422 423 map.put(null, unmappedValue); 424 Entry<K, V> entry = mapEntry(null, unmappedValue); 425 assertTrue(entrySet.contains(entry)); 426 assertFalse(entrySet.contains(mapEntry(null, null))); 427 } 428 testEntrySetContainsEntryNullKeyMissing()429 public void testEntrySetContainsEntryNullKeyMissing() { 430 final Map<K, V> map; 431 final Set<Entry<K, V>> entrySet; 432 try { 433 map = makeEitherMap(); 434 } catch (UnsupportedOperationException e) { 435 return; 436 } 437 assertInvariants(map); 438 439 entrySet = map.entrySet(); 440 final V unmappedValue; 441 try { 442 unmappedValue = getValueNotInPopulatedMap(); 443 } catch (UnsupportedOperationException e) { 444 return; 445 } 446 Entry<K, V> entry = mapEntry(null, unmappedValue); 447 try { 448 assertFalse(entrySet.contains(entry)); 449 } catch (NullPointerException e) { 450 assertFalse(allowsNullKeys); 451 } 452 try { 453 assertFalse(entrySet.contains(mapEntry(null, null))); 454 } catch (NullPointerException e) { 455 assertFalse(allowsNullKeys && allowsNullValues); 456 } 457 } 458 testEntrySetIteratorRemove()459 public void testEntrySetIteratorRemove() { 460 final Map<K, V> map; 461 try { 462 map = makePopulatedMap(); 463 } catch (UnsupportedOperationException e) { 464 return; 465 } 466 467 Set<Entry<K, V>> entrySet = map.entrySet(); 468 Iterator<Entry<K, V>> iterator = entrySet.iterator(); 469 if (supportsIteratorRemove) { 470 int initialSize = map.size(); 471 Entry<K, V> entry = iterator.next(); 472 Entry<K, V> entryCopy = Helpers.mapEntry( 473 entry.getKey(), entry.getValue()); 474 475 iterator.remove(); 476 assertEquals(initialSize - 1, map.size()); 477 478 // Use "entryCopy" instead of "entry" because "entry" might be invalidated after 479 // iterator.remove(). 480 assertFalse(entrySet.contains(entryCopy)); 481 assertInvariants(map); 482 try { 483 iterator.remove(); 484 fail("Expected IllegalStateException."); 485 } catch (IllegalStateException e) { 486 // Expected. 487 } 488 } else { 489 try { 490 iterator.next(); 491 iterator.remove(); 492 fail("Expected UnsupportedOperationException."); 493 } catch (UnsupportedOperationException e) { 494 // Expected. 495 } 496 } 497 assertInvariants(map); 498 } 499 testEntrySetRemove()500 public void testEntrySetRemove() { 501 final Map<K, V> map; 502 try { 503 map = makePopulatedMap(); 504 } catch (UnsupportedOperationException e) { 505 return; 506 } 507 508 Set<Entry<K, V>> entrySet = map.entrySet(); 509 if (supportsRemove) { 510 int initialSize = map.size(); 511 boolean didRemove = entrySet.remove(entrySet.iterator().next()); 512 assertTrue(didRemove); 513 assertEquals(initialSize - 1, map.size()); 514 } else { 515 try { 516 entrySet.remove(entrySet.iterator().next()); 517 fail("Expected UnsupportedOperationException."); 518 } catch (UnsupportedOperationException e) { 519 // Expected. 520 } 521 } 522 assertInvariants(map); 523 } 524 testEntrySetRemoveMissingKey()525 public void testEntrySetRemoveMissingKey() { 526 final Map<K, V> map; 527 final K key; 528 try { 529 map = makeEitherMap(); 530 key = getKeyNotInPopulatedMap(); 531 } catch (UnsupportedOperationException e) { 532 return; 533 } 534 535 Set<Entry<K, V>> entrySet = map.entrySet(); 536 Entry<K, V> entry 537 = mapEntry(key, getValueNotInPopulatedMap()); 538 int initialSize = map.size(); 539 if (supportsRemove) { 540 boolean didRemove = entrySet.remove(entry); 541 assertFalse(didRemove); 542 } else { 543 try { 544 boolean didRemove = entrySet.remove(entry); 545 assertFalse(didRemove); 546 } catch (UnsupportedOperationException optional) {} 547 } 548 assertEquals(initialSize, map.size()); 549 assertFalse(map.containsKey(key)); 550 assertInvariants(map); 551 } 552 testEntrySetRemoveDifferentValue()553 public void testEntrySetRemoveDifferentValue() { 554 final Map<K, V> map; 555 try { 556 map = makePopulatedMap(); 557 } catch (UnsupportedOperationException e) { 558 return; 559 } 560 561 Set<Entry<K, V>> entrySet = map.entrySet(); 562 K key = map.keySet().iterator().next(); 563 Entry<K, V> entry 564 = mapEntry(key, getValueNotInPopulatedMap()); 565 int initialSize = map.size(); 566 if (supportsRemove) { 567 boolean didRemove = entrySet.remove(entry); 568 assertFalse(didRemove); 569 } else { 570 try { 571 boolean didRemove = entrySet.remove(entry); 572 assertFalse(didRemove); 573 } catch (UnsupportedOperationException optional) {} 574 } 575 assertEquals(initialSize, map.size()); 576 assertTrue(map.containsKey(key)); 577 assertInvariants(map); 578 } 579 testEntrySetRemoveNullKeyPresent()580 public void testEntrySetRemoveNullKeyPresent() { 581 if (!allowsNullKeys || !supportsPut || !supportsRemove) { 582 return; 583 } 584 final Map<K, V> map; 585 final Set<Entry<K, V>> entrySet; 586 try { 587 map = makeEitherMap(); 588 } catch (UnsupportedOperationException e) { 589 return; 590 } 591 assertInvariants(map); 592 593 entrySet = map.entrySet(); 594 final V unmappedValue; 595 try { 596 unmappedValue = getValueNotInPopulatedMap(); 597 } catch (UnsupportedOperationException e) { 598 return; 599 } 600 601 map.put(null, unmappedValue); 602 assertEquals(unmappedValue, map.get(null)); 603 assertTrue(map.containsKey(null)); 604 Entry<K, V> entry = mapEntry(null, unmappedValue); 605 assertTrue(entrySet.remove(entry)); 606 assertNull(map.get(null)); 607 assertFalse(map.containsKey(null)); 608 } 609 testEntrySetRemoveNullKeyMissing()610 public void testEntrySetRemoveNullKeyMissing() { 611 final Map<K, V> map; 612 try { 613 map = makeEitherMap(); 614 } catch (UnsupportedOperationException e) { 615 return; 616 } 617 618 Set<Entry<K, V>> entrySet = map.entrySet(); 619 Entry<K, V> entry 620 = mapEntry(null, getValueNotInPopulatedMap()); 621 int initialSize = map.size(); 622 if (supportsRemove) { 623 try { 624 boolean didRemove = entrySet.remove(entry); 625 assertFalse(didRemove); 626 } catch (NullPointerException e) { 627 assertFalse(allowsNullKeys); 628 } 629 } else { 630 try { 631 boolean didRemove = entrySet.remove(entry); 632 assertFalse(didRemove); 633 } catch (UnsupportedOperationException optional) {} 634 } 635 assertEquals(initialSize, map.size()); 636 assertInvariants(map); 637 } 638 testEntrySetRemoveAll()639 public void testEntrySetRemoveAll() { 640 final Map<K, V> map; 641 try { 642 map = makePopulatedMap(); 643 } catch (UnsupportedOperationException e) { 644 return; 645 } 646 647 Set<Entry<K, V>> entrySet = map.entrySet(); 648 649 Entry<K, V> entryToRemove = entrySet.iterator().next(); 650 Set<Entry<K, V>> entriesToRemove = singleton(entryToRemove); 651 if (supportsRemove) { 652 // We use a copy of "entryToRemove" in the assertion because "entryToRemove" might be 653 // invalidated and have undefined behavior after entrySet.removeAll(entriesToRemove), 654 // for example entryToRemove.getValue() might be null. 655 Entry<K, V> entryToRemoveCopy = Helpers.mapEntry( 656 entryToRemove.getKey(), entryToRemove.getValue()); 657 658 int initialSize = map.size(); 659 boolean didRemove = entrySet.removeAll(entriesToRemove); 660 assertTrue(didRemove); 661 assertEquals(initialSize - entriesToRemove.size(), map.size()); 662 663 // Use "entryToRemoveCopy" instead of "entryToRemove" because it might be invalidated and 664 // have undefined behavior after entrySet.removeAll(entriesToRemove), 665 assertFalse(entrySet.contains(entryToRemoveCopy)); 666 } else { 667 try { 668 entrySet.removeAll(entriesToRemove); 669 fail("Expected UnsupportedOperationException."); 670 } catch (UnsupportedOperationException e) { 671 // Expected. 672 } 673 } 674 assertInvariants(map); 675 } 676 testEntrySetRemoveAllNullFromEmpty()677 public void testEntrySetRemoveAllNullFromEmpty() { 678 final Map<K, V> map; 679 try { 680 map = makeEmptyMap(); 681 } catch (UnsupportedOperationException e) { 682 return; 683 } 684 685 Set<Entry<K, V>> entrySet = map.entrySet(); 686 if (supportsRemove) { 687 try { 688 entrySet.removeAll(null); 689 fail("Expected NullPointerException."); 690 } catch (NullPointerException e) { 691 // Expected. 692 } 693 } else { 694 try { 695 entrySet.removeAll(null); 696 fail("Expected UnsupportedOperationException or NullPointerException."); 697 } catch (UnsupportedOperationException e) { 698 // Expected. 699 } catch (NullPointerException e) { 700 // Expected. 701 } 702 } 703 assertInvariants(map); 704 } 705 testEntrySetRetainAll()706 public void testEntrySetRetainAll() { 707 final Map<K, V> map; 708 try { 709 map = makePopulatedMap(); 710 } catch (UnsupportedOperationException e) { 711 return; 712 } 713 714 Set<Entry<K, V>> entrySet = map.entrySet(); 715 Set<Entry<K, V>> entriesToRetain = 716 singleton(entrySet.iterator().next()); 717 if (supportsRemove) { 718 boolean shouldRemove = (entrySet.size() > entriesToRetain.size()); 719 boolean didRemove = entrySet.retainAll(entriesToRetain); 720 assertEquals(shouldRemove, didRemove); 721 assertEquals(entriesToRetain.size(), map.size()); 722 for (Entry<K, V> entry : entriesToRetain) { 723 assertTrue(entrySet.contains(entry)); 724 } 725 } else { 726 try { 727 entrySet.retainAll(entriesToRetain); 728 fail("Expected UnsupportedOperationException."); 729 } catch (UnsupportedOperationException e) { 730 // Expected. 731 } 732 } 733 assertInvariants(map); 734 } 735 testEntrySetRetainAllNullFromEmpty()736 public void testEntrySetRetainAllNullFromEmpty() { 737 final Map<K, V> map; 738 try { 739 map = makeEmptyMap(); 740 } catch (UnsupportedOperationException e) { 741 return; 742 } 743 744 Set<Entry<K, V>> entrySet = map.entrySet(); 745 if (supportsRemove) { 746 try { 747 entrySet.retainAll(null); 748 // Returning successfully is not ideal, but tolerated. 749 } catch (NullPointerException e) { 750 // Expected. 751 } 752 } else { 753 try { 754 entrySet.retainAll(null); 755 // We have to tolerate a successful return (Sun bug 4802647) 756 } catch (UnsupportedOperationException e) { 757 // Expected. 758 } catch (NullPointerException e) { 759 // Expected. 760 } 761 } 762 assertInvariants(map); 763 } 764 testEntrySetClear()765 public void testEntrySetClear() { 766 final Map<K, V> map; 767 try { 768 map = makePopulatedMap(); 769 } catch (UnsupportedOperationException e) { 770 return; 771 } 772 773 Set<Entry<K, V>> entrySet = map.entrySet(); 774 if (supportsClear) { 775 entrySet.clear(); 776 assertTrue(entrySet.isEmpty()); 777 } else { 778 try { 779 entrySet.clear(); 780 fail("Expected UnsupportedOperationException."); 781 } catch (UnsupportedOperationException e) { 782 // Expected. 783 } 784 } 785 assertInvariants(map); 786 } 787 testEntrySetAddAndAddAll()788 public void testEntrySetAddAndAddAll() { 789 final Map<K, V> map = makeEitherMap(); 790 791 Set<Entry<K, V>> entrySet = map.entrySet(); 792 final Entry<K, V> entryToAdd = mapEntry(null, null); 793 try { 794 entrySet.add(entryToAdd); 795 fail("Expected UnsupportedOperationException or NullPointerException."); 796 } catch (UnsupportedOperationException e) { 797 // Expected. 798 } catch (NullPointerException e) { 799 // Expected. 800 } 801 assertInvariants(map); 802 803 try { 804 entrySet.addAll(singleton(entryToAdd)); 805 fail("Expected UnsupportedOperationException or NullPointerException."); 806 } catch (UnsupportedOperationException e) { 807 // Expected. 808 } catch (NullPointerException e) { 809 // Expected. 810 } 811 assertInvariants(map); 812 } 813 testEntrySetSetValue()814 public void testEntrySetSetValue() { 815 // TODO: Investigate the extent to which, in practice, maps that support 816 // put() also support Entry.setValue(). 817 if (!supportsPut) { 818 return; 819 } 820 821 final Map<K, V> map; 822 final V valueToSet; 823 try { 824 map = makePopulatedMap(); 825 valueToSet = getValueNotInPopulatedMap(); 826 } catch (UnsupportedOperationException e) { 827 return; 828 } 829 830 Set<Entry<K, V>> entrySet = map.entrySet(); 831 Entry<K, V> entry = entrySet.iterator().next(); 832 final V oldValue = entry.getValue(); 833 final V returnedValue = entry.setValue(valueToSet); 834 assertEquals(oldValue, returnedValue); 835 assertTrue(entrySet.contains( 836 mapEntry(entry.getKey(), valueToSet))); 837 assertEquals(valueToSet, map.get(entry.getKey())); 838 assertInvariants(map); 839 } 840 testEntrySetSetValueSameValue()841 public void testEntrySetSetValueSameValue() { 842 // TODO: Investigate the extent to which, in practice, maps that support 843 // put() also support Entry.setValue(). 844 if (!supportsPut) { 845 return; 846 } 847 848 final Map<K, V> map; 849 try { 850 map = makePopulatedMap(); 851 } catch (UnsupportedOperationException e) { 852 return; 853 } 854 855 Set<Entry<K, V>> entrySet = map.entrySet(); 856 Entry<K, V> entry = entrySet.iterator().next(); 857 final V oldValue = entry.getValue(); 858 final V returnedValue = entry.setValue(oldValue); 859 assertEquals(oldValue, returnedValue); 860 assertTrue(entrySet.contains( 861 mapEntry(entry.getKey(), oldValue))); 862 assertEquals(oldValue, map.get(entry.getKey())); 863 assertInvariants(map); 864 } 865 testEqualsForEqualMap()866 public void testEqualsForEqualMap() { 867 final Map<K, V> map; 868 try { 869 map = makePopulatedMap(); 870 } catch (UnsupportedOperationException e) { 871 return; 872 } 873 874 assertEquals(map, map); 875 assertEquals(makePopulatedMap(), map); 876 assertFalse(map.equals(Collections.emptyMap())); 877 //no-inspection ObjectEqualsNull 878 assertFalse(map.equals(null)); 879 } 880 testEqualsForLargerMap()881 public void testEqualsForLargerMap() { 882 if (!supportsPut) { 883 return; 884 } 885 886 final Map<K, V> map; 887 final Map<K, V> largerMap; 888 try { 889 map = makePopulatedMap(); 890 largerMap = makePopulatedMap(); 891 largerMap.put(getKeyNotInPopulatedMap(), getValueNotInPopulatedMap()); 892 } catch (UnsupportedOperationException e) { 893 return; 894 } 895 896 assertFalse(map.equals(largerMap)); 897 } 898 testEqualsForSmallerMap()899 public void testEqualsForSmallerMap() { 900 if (!supportsRemove) { 901 return; 902 } 903 904 final Map<K, V> map; 905 final Map<K, V> smallerMap; 906 try { 907 map = makePopulatedMap(); 908 smallerMap = makePopulatedMap(); 909 smallerMap.remove(smallerMap.keySet().iterator().next()); 910 } catch (UnsupportedOperationException e) { 911 return; 912 } 913 914 assertFalse(map.equals(smallerMap)); 915 } 916 testEqualsForEmptyMap()917 public void testEqualsForEmptyMap() { 918 final Map<K, V> map; 919 try { 920 map = makeEmptyMap(); 921 } catch (UnsupportedOperationException e) { 922 return; 923 } 924 925 assertEquals(map, map); 926 assertEquals(makeEmptyMap(), map); 927 assertEquals(Collections.emptyMap(), map); 928 assertFalse(map.equals(Collections.emptySet())); 929 //noinspection ObjectEqualsNull 930 assertFalse(map.equals(null)); 931 } 932 testGet()933 public void testGet() { 934 final Map<K, V> map; 935 try { 936 map = makePopulatedMap(); 937 } catch (UnsupportedOperationException e) { 938 return; 939 } 940 941 for (Entry<K, V> entry : map.entrySet()) { 942 assertEquals(entry.getValue(), map.get(entry.getKey())); 943 } 944 945 K unmappedKey = null; 946 try { 947 unmappedKey = getKeyNotInPopulatedMap(); 948 } catch (UnsupportedOperationException e) { 949 return; 950 } 951 assertNull(map.get(unmappedKey)); 952 } 953 testGetForEmptyMap()954 public void testGetForEmptyMap() { 955 final Map<K, V> map; 956 K unmappedKey = null; 957 try { 958 map = makeEmptyMap(); 959 unmappedKey = getKeyNotInPopulatedMap(); 960 } catch (UnsupportedOperationException e) { 961 return; 962 } 963 assertNull(map.get(unmappedKey)); 964 } 965 testGetNull()966 public void testGetNull() { 967 Map<K, V> map = makeEitherMap(); 968 if (allowsNullKeys) { 969 if (allowsNullValues) { 970 // TODO: decide what to test here. 971 } else { 972 assertEquals(map.containsKey(null), map.get(null) != null); 973 } 974 } else { 975 try { 976 map.get(null); 977 } catch (NullPointerException optional) { 978 } 979 } 980 assertInvariants(map); 981 } 982 testHashCode()983 public void testHashCode() { 984 final Map<K, V> map; 985 try { 986 map = makePopulatedMap(); 987 } catch (UnsupportedOperationException e) { 988 return; 989 } 990 assertInvariants(map); 991 } 992 testHashCodeForEmptyMap()993 public void testHashCodeForEmptyMap() { 994 final Map<K, V> map; 995 try { 996 map = makeEmptyMap(); 997 } catch (UnsupportedOperationException e) { 998 return; 999 } 1000 assertInvariants(map); 1001 } 1002 testPutNewKey()1003 public void testPutNewKey() { 1004 final Map<K, V> map = makeEitherMap(); 1005 final K keyToPut; 1006 final V valueToPut; 1007 try { 1008 keyToPut = getKeyNotInPopulatedMap(); 1009 valueToPut = getValueNotInPopulatedMap(); 1010 } catch (UnsupportedOperationException e) { 1011 return; 1012 } 1013 if (supportsPut) { 1014 int initialSize = map.size(); 1015 V oldValue = map.put(keyToPut, valueToPut); 1016 assertEquals(valueToPut, map.get(keyToPut)); 1017 assertTrue(map.containsKey(keyToPut)); 1018 assertTrue(map.containsValue(valueToPut)); 1019 assertEquals(initialSize + 1, map.size()); 1020 assertNull(oldValue); 1021 } else { 1022 try { 1023 map.put(keyToPut, valueToPut); 1024 fail("Expected UnsupportedOperationException."); 1025 } catch (UnsupportedOperationException e) { 1026 // Expected. 1027 } 1028 } 1029 assertInvariants(map); 1030 } 1031 testPutExistingKey()1032 public void testPutExistingKey() { 1033 final Map<K, V> map; 1034 final K keyToPut; 1035 final V valueToPut; 1036 try { 1037 map = makePopulatedMap(); 1038 valueToPut = getValueNotInPopulatedMap(); 1039 } catch (UnsupportedOperationException e) { 1040 return; 1041 } 1042 keyToPut = map.keySet().iterator().next(); 1043 if (supportsPut) { 1044 int initialSize = map.size(); 1045 map.put(keyToPut, valueToPut); 1046 assertEquals(valueToPut, map.get(keyToPut)); 1047 assertTrue(map.containsKey(keyToPut)); 1048 assertTrue(map.containsValue(valueToPut)); 1049 assertEquals(initialSize, map.size()); 1050 } else { 1051 try { 1052 map.put(keyToPut, valueToPut); 1053 fail("Expected UnsupportedOperationException."); 1054 } catch (UnsupportedOperationException e) { 1055 // Expected. 1056 } 1057 } 1058 assertInvariants(map); 1059 } 1060 testPutNullKey()1061 public void testPutNullKey() { 1062 if (!supportsPut) { 1063 return; 1064 } 1065 final Map<K, V> map = makeEitherMap(); 1066 final V valueToPut; 1067 try { 1068 valueToPut = getValueNotInPopulatedMap(); 1069 } catch (UnsupportedOperationException e) { 1070 return; 1071 } 1072 if (allowsNullKeys) { 1073 final V oldValue = map.get(null); 1074 final V returnedValue = map.put(null, valueToPut); 1075 assertEquals(oldValue, returnedValue); 1076 assertEquals(valueToPut, map.get(null)); 1077 assertTrue(map.containsKey(null)); 1078 assertTrue(map.containsValue(valueToPut)); 1079 } else { 1080 try { 1081 map.put(null, valueToPut); 1082 fail("Expected RuntimeException"); 1083 } catch (RuntimeException e) { 1084 // Expected. 1085 } 1086 } 1087 assertInvariants(map); 1088 } 1089 testPutNullValue()1090 public void testPutNullValue() { 1091 if (!supportsPut) { 1092 return; 1093 } 1094 final Map<K, V> map = makeEitherMap(); 1095 final K keyToPut; 1096 try { 1097 keyToPut = getKeyNotInPopulatedMap(); 1098 } catch (UnsupportedOperationException e) { 1099 return; 1100 } 1101 if (allowsNullValues) { 1102 int initialSize = map.size(); 1103 final V oldValue = map.get(keyToPut); 1104 final V returnedValue = map.put(keyToPut, null); 1105 assertEquals(oldValue, returnedValue); 1106 assertNull(map.get(keyToPut)); 1107 assertTrue(map.containsKey(keyToPut)); 1108 assertTrue(map.containsValue(null)); 1109 assertEquals(initialSize + 1, map.size()); 1110 } else { 1111 try { 1112 map.put(keyToPut, null); 1113 fail("Expected RuntimeException"); 1114 } catch (RuntimeException e) { 1115 // Expected. 1116 } 1117 } 1118 assertInvariants(map); 1119 } 1120 testPutNullValueForExistingKey()1121 public void testPutNullValueForExistingKey() { 1122 if (!supportsPut) { 1123 return; 1124 } 1125 final Map<K, V> map; 1126 final K keyToPut; 1127 try { 1128 map = makePopulatedMap(); 1129 keyToPut = map.keySet().iterator().next(); 1130 } catch (UnsupportedOperationException e) { 1131 return; 1132 } 1133 if (allowsNullValues) { 1134 int initialSize = map.size(); 1135 final V oldValue = map.get(keyToPut); 1136 final V returnedValue = map.put(keyToPut, null); 1137 assertEquals(oldValue, returnedValue); 1138 assertNull(map.get(keyToPut)); 1139 assertTrue(map.containsKey(keyToPut)); 1140 assertTrue(map.containsValue(null)); 1141 assertEquals(initialSize, map.size()); 1142 } else { 1143 try { 1144 map.put(keyToPut, null); 1145 fail("Expected RuntimeException"); 1146 } catch (RuntimeException e) { 1147 // Expected. 1148 } 1149 } 1150 assertInvariants(map); 1151 } 1152 testPutAllNewKey()1153 public void testPutAllNewKey() { 1154 final Map<K, V> map = makeEitherMap(); 1155 final K keyToPut; 1156 final V valueToPut; 1157 try { 1158 keyToPut = getKeyNotInPopulatedMap(); 1159 valueToPut = getValueNotInPopulatedMap(); 1160 } catch (UnsupportedOperationException e) { 1161 return; 1162 } 1163 final Map<K, V> mapToPut = Collections.singletonMap(keyToPut, valueToPut); 1164 if (supportsPut) { 1165 int initialSize = map.size(); 1166 map.putAll(mapToPut); 1167 assertEquals(valueToPut, map.get(keyToPut)); 1168 assertTrue(map.containsKey(keyToPut)); 1169 assertTrue(map.containsValue(valueToPut)); 1170 assertEquals(initialSize + 1, map.size()); 1171 } else { 1172 try { 1173 map.putAll(mapToPut); 1174 fail("Expected UnsupportedOperationException."); 1175 } catch (UnsupportedOperationException e) { 1176 // Expected. 1177 } 1178 } 1179 assertInvariants(map); 1180 } 1181 testPutAllExistingKey()1182 public void testPutAllExistingKey() { 1183 final Map<K, V> map; 1184 final K keyToPut; 1185 final V valueToPut; 1186 try { 1187 map = makePopulatedMap(); 1188 valueToPut = getValueNotInPopulatedMap(); 1189 } catch (UnsupportedOperationException e) { 1190 return; 1191 } 1192 keyToPut = map.keySet().iterator().next(); 1193 final Map<K, V> mapToPut = Collections.singletonMap(keyToPut, valueToPut); 1194 int initialSize = map.size(); 1195 if (supportsPut) { 1196 map.putAll(mapToPut); 1197 assertEquals(valueToPut, map.get(keyToPut)); 1198 assertTrue(map.containsKey(keyToPut)); 1199 assertTrue(map.containsValue(valueToPut)); 1200 } else { 1201 try { 1202 map.putAll(mapToPut); 1203 fail("Expected UnsupportedOperationException."); 1204 } catch (UnsupportedOperationException e) { 1205 // Expected. 1206 } 1207 } 1208 assertEquals(initialSize, map.size()); 1209 assertInvariants(map); 1210 } 1211 testRemove()1212 public void testRemove() { 1213 final Map<K, V> map; 1214 final K keyToRemove; 1215 try { 1216 map = makePopulatedMap(); 1217 } catch (UnsupportedOperationException e) { 1218 return; 1219 } 1220 keyToRemove = map.keySet().iterator().next(); 1221 if (supportsRemove) { 1222 int initialSize = map.size(); 1223 V expectedValue = map.get(keyToRemove); 1224 V oldValue = map.remove(keyToRemove); 1225 assertEquals(expectedValue, oldValue); 1226 assertFalse(map.containsKey(keyToRemove)); 1227 assertEquals(initialSize - 1, map.size()); 1228 } else { 1229 try { 1230 map.remove(keyToRemove); 1231 fail("Expected UnsupportedOperationException."); 1232 } catch (UnsupportedOperationException e) { 1233 // Expected. 1234 } 1235 } 1236 assertInvariants(map); 1237 } 1238 testRemoveMissingKey()1239 public void testRemoveMissingKey() { 1240 final Map<K, V> map; 1241 final K keyToRemove; 1242 try { 1243 map = makePopulatedMap(); 1244 keyToRemove = getKeyNotInPopulatedMap(); 1245 } catch (UnsupportedOperationException e) { 1246 return; 1247 } 1248 if (supportsRemove) { 1249 int initialSize = map.size(); 1250 assertNull(map.remove(keyToRemove)); 1251 assertEquals(initialSize, map.size()); 1252 } else { 1253 try { 1254 map.remove(keyToRemove); 1255 fail("Expected UnsupportedOperationException."); 1256 } catch (UnsupportedOperationException e) { 1257 // Expected. 1258 } 1259 } 1260 assertInvariants(map); 1261 } 1262 testSize()1263 public void testSize() { 1264 assertInvariants(makeEitherMap()); 1265 } 1266 testKeySetRemove()1267 public void testKeySetRemove() { 1268 final Map<K, V> map; 1269 try { 1270 map = makePopulatedMap(); 1271 } catch (UnsupportedOperationException e) { 1272 return; 1273 } 1274 1275 Set<K> keys = map.keySet(); 1276 K key = keys.iterator().next(); 1277 if (supportsRemove) { 1278 int initialSize = map.size(); 1279 keys.remove(key); 1280 assertEquals(initialSize - 1, map.size()); 1281 assertFalse(map.containsKey(key)); 1282 } else { 1283 try { 1284 keys.remove(key); 1285 fail("Expected UnsupportedOperationException."); 1286 } catch (UnsupportedOperationException e) { 1287 // Expected. 1288 } 1289 } 1290 assertInvariants(map); 1291 } 1292 testKeySetRemoveAll()1293 public void testKeySetRemoveAll() { 1294 final Map<K, V> map; 1295 try { 1296 map = makePopulatedMap(); 1297 } catch (UnsupportedOperationException e) { 1298 return; 1299 } 1300 1301 Set<K> keys = map.keySet(); 1302 K key = keys.iterator().next(); 1303 if (supportsRemove) { 1304 int initialSize = map.size(); 1305 assertTrue(keys.removeAll(Collections.singleton(key))); 1306 assertEquals(initialSize - 1, map.size()); 1307 assertFalse(map.containsKey(key)); 1308 } else { 1309 try { 1310 keys.removeAll(Collections.singleton(key)); 1311 fail("Expected UnsupportedOperationException."); 1312 } catch (UnsupportedOperationException e) { 1313 // Expected. 1314 } 1315 } 1316 assertInvariants(map); 1317 } 1318 testKeySetRetainAll()1319 public void testKeySetRetainAll() { 1320 final Map<K, V> map; 1321 try { 1322 map = makePopulatedMap(); 1323 } catch (UnsupportedOperationException e) { 1324 return; 1325 } 1326 1327 Set<K> keys = map.keySet(); 1328 K key = keys.iterator().next(); 1329 if (supportsRemove) { 1330 keys.retainAll(Collections.singleton(key)); 1331 assertEquals(1, map.size()); 1332 assertTrue(map.containsKey(key)); 1333 } else { 1334 try { 1335 keys.retainAll(Collections.singleton(key)); 1336 fail("Expected UnsupportedOperationException."); 1337 } catch (UnsupportedOperationException e) { 1338 // Expected. 1339 } 1340 } 1341 assertInvariants(map); 1342 } 1343 testKeySetClear()1344 public void testKeySetClear() { 1345 final Map<K, V> map; 1346 try { 1347 map = makeEitherMap(); 1348 } catch (UnsupportedOperationException e) { 1349 return; 1350 } 1351 1352 Set<K> keySet = map.keySet(); 1353 if (supportsClear) { 1354 keySet.clear(); 1355 assertTrue(keySet.isEmpty()); 1356 } else { 1357 try { 1358 keySet.clear(); 1359 fail("Expected UnsupportedOperationException."); 1360 } catch (UnsupportedOperationException e) { 1361 // Expected. 1362 } 1363 } 1364 assertInvariants(map); 1365 } 1366 testKeySetRemoveAllNullFromEmpty()1367 public void testKeySetRemoveAllNullFromEmpty() { 1368 final Map<K, V> map; 1369 try { 1370 map = makeEmptyMap(); 1371 } catch (UnsupportedOperationException e) { 1372 return; 1373 } 1374 1375 Set<K> keySet = map.keySet(); 1376 if (supportsRemove) { 1377 try { 1378 keySet.removeAll(null); 1379 fail("Expected NullPointerException."); 1380 } catch (NullPointerException e) { 1381 // Expected. 1382 } 1383 } else { 1384 try { 1385 keySet.removeAll(null); 1386 fail("Expected UnsupportedOperationException or NullPointerException."); 1387 } catch (UnsupportedOperationException e) { 1388 // Expected. 1389 } catch (NullPointerException e) { 1390 // Expected. 1391 } 1392 } 1393 assertInvariants(map); 1394 } 1395 testKeySetRetainAllNullFromEmpty()1396 public void testKeySetRetainAllNullFromEmpty() { 1397 final Map<K, V> map; 1398 try { 1399 map = makeEmptyMap(); 1400 } catch (UnsupportedOperationException e) { 1401 return; 1402 } 1403 1404 Set<K> keySet = map.keySet(); 1405 if (supportsRemove) { 1406 try { 1407 keySet.retainAll(null); 1408 // Returning successfully is not ideal, but tolerated. 1409 } catch (NullPointerException e) { 1410 // Expected. 1411 } 1412 } else { 1413 try { 1414 keySet.retainAll(null); 1415 // We have to tolerate a successful return (Sun bug 4802647) 1416 } catch (UnsupportedOperationException e) { 1417 // Expected. 1418 } catch (NullPointerException e) { 1419 // Expected. 1420 } 1421 } 1422 assertInvariants(map); 1423 } 1424 testValues()1425 public void testValues() { 1426 final Map<K, V> map; 1427 final Collection<V> valueCollection; 1428 try { 1429 map = makePopulatedMap(); 1430 } catch (UnsupportedOperationException e) { 1431 return; 1432 } 1433 assertInvariants(map); 1434 1435 valueCollection = map.values(); 1436 final V unmappedValue; 1437 try { 1438 unmappedValue = getValueNotInPopulatedMap(); 1439 } catch (UnsupportedOperationException e) { 1440 return; 1441 } 1442 for (V value : valueCollection) { 1443 assertFalse(unmappedValue.equals(value)); 1444 } 1445 } 1446 testValuesIteratorRemove()1447 public void testValuesIteratorRemove() { 1448 final Map<K, V> map; 1449 try { 1450 map = makePopulatedMap(); 1451 } catch (UnsupportedOperationException e) { 1452 return; 1453 } 1454 1455 Collection<V> valueCollection = map.values(); 1456 Iterator<V> iterator = valueCollection.iterator(); 1457 if (supportsIteratorRemove) { 1458 int initialSize = map.size(); 1459 iterator.next(); 1460 iterator.remove(); 1461 assertEquals(initialSize - 1, map.size()); 1462 // (We can't assert that the values collection no longer contains the 1463 // removed value, because the underlying map can have multiple mappings 1464 // to the same value.) 1465 assertInvariants(map); 1466 try { 1467 iterator.remove(); 1468 fail("Expected IllegalStateException."); 1469 } catch (IllegalStateException e) { 1470 // Expected. 1471 } 1472 } else { 1473 try { 1474 iterator.next(); 1475 iterator.remove(); 1476 fail("Expected UnsupportedOperationException."); 1477 } catch (UnsupportedOperationException e) { 1478 // Expected. 1479 } 1480 } 1481 assertInvariants(map); 1482 } 1483 testValuesRemove()1484 public void testValuesRemove() { 1485 final Map<K, V> map; 1486 try { 1487 map = makePopulatedMap(); 1488 } catch (UnsupportedOperationException e) { 1489 return; 1490 } 1491 1492 Collection<V> valueCollection = map.values(); 1493 if (supportsRemove) { 1494 int initialSize = map.size(); 1495 valueCollection.remove(valueCollection.iterator().next()); 1496 assertEquals(initialSize - 1, map.size()); 1497 // (We can't assert that the values collection no longer contains the 1498 // removed value, because the underlying map can have multiple mappings 1499 // to the same value.) 1500 } else { 1501 try { 1502 valueCollection.remove(valueCollection.iterator().next()); 1503 fail("Expected UnsupportedOperationException."); 1504 } catch (UnsupportedOperationException e) { 1505 // Expected. 1506 } 1507 } 1508 assertInvariants(map); 1509 } 1510 testValuesRemoveMissing()1511 public void testValuesRemoveMissing() { 1512 final Map<K, V> map; 1513 final V valueToRemove; 1514 try { 1515 map = makeEitherMap(); 1516 valueToRemove = getValueNotInPopulatedMap(); 1517 } catch (UnsupportedOperationException e) { 1518 return; 1519 } 1520 1521 Collection<V> valueCollection = map.values(); 1522 int initialSize = map.size(); 1523 if (supportsRemove) { 1524 assertFalse(valueCollection.remove(valueToRemove)); 1525 } else { 1526 try { 1527 assertFalse(valueCollection.remove(valueToRemove)); 1528 } catch (UnsupportedOperationException e) { 1529 // Tolerated. 1530 } 1531 } 1532 assertEquals(initialSize, map.size()); 1533 assertInvariants(map); 1534 } 1535 testValuesRemoveAll()1536 public void testValuesRemoveAll() { 1537 final Map<K, V> map; 1538 try { 1539 map = makePopulatedMap(); 1540 } catch (UnsupportedOperationException e) { 1541 return; 1542 } 1543 1544 Collection<V> valueCollection = map.values(); 1545 Set<V> valuesToRemove = singleton(valueCollection.iterator().next()); 1546 if (supportsRemove) { 1547 valueCollection.removeAll(valuesToRemove); 1548 for (V value : valuesToRemove) { 1549 assertFalse(valueCollection.contains(value)); 1550 } 1551 for (V value : valueCollection) { 1552 assertFalse(valuesToRemove.contains(value)); 1553 } 1554 } else { 1555 try { 1556 valueCollection.removeAll(valuesToRemove); 1557 fail("Expected UnsupportedOperationException."); 1558 } catch (UnsupportedOperationException e) { 1559 // Expected. 1560 } 1561 } 1562 assertInvariants(map); 1563 } 1564 testValuesRemoveAllNullFromEmpty()1565 public void testValuesRemoveAllNullFromEmpty() { 1566 final Map<K, V> map; 1567 try { 1568 map = makeEmptyMap(); 1569 } catch (UnsupportedOperationException e) { 1570 return; 1571 } 1572 1573 Collection<V> values = map.values(); 1574 if (supportsRemove) { 1575 try { 1576 values.removeAll(null); 1577 // Returning successfully is not ideal, but tolerated. 1578 } catch (NullPointerException e) { 1579 // Expected. 1580 } 1581 } else { 1582 try { 1583 values.removeAll(null); 1584 // We have to tolerate a successful return (Sun bug 4802647) 1585 } catch (UnsupportedOperationException e) { 1586 // Expected. 1587 } catch (NullPointerException e) { 1588 // Expected. 1589 } 1590 } 1591 assertInvariants(map); 1592 } 1593 testValuesRetainAll()1594 public void testValuesRetainAll() { 1595 final Map<K, V> map; 1596 try { 1597 map = makePopulatedMap(); 1598 } catch (UnsupportedOperationException e) { 1599 return; 1600 } 1601 1602 Collection<V> valueCollection = map.values(); 1603 Set<V> valuesToRetain = singleton(valueCollection.iterator().next()); 1604 if (supportsRemove) { 1605 valueCollection.retainAll(valuesToRetain); 1606 for (V value : valuesToRetain) { 1607 assertTrue(valueCollection.contains(value)); 1608 } 1609 for (V value : valueCollection) { 1610 assertTrue(valuesToRetain.contains(value)); 1611 } 1612 } else { 1613 try { 1614 valueCollection.retainAll(valuesToRetain); 1615 fail("Expected UnsupportedOperationException."); 1616 } catch (UnsupportedOperationException e) { 1617 // Expected. 1618 } 1619 } 1620 assertInvariants(map); 1621 } 1622 testValuesRetainAllNullFromEmpty()1623 public void testValuesRetainAllNullFromEmpty() { 1624 final Map<K, V> map; 1625 try { 1626 map = makeEmptyMap(); 1627 } catch (UnsupportedOperationException e) { 1628 return; 1629 } 1630 1631 Collection<V> values = map.values(); 1632 if (supportsRemove) { 1633 try { 1634 values.retainAll(null); 1635 // Returning successfully is not ideal, but tolerated. 1636 } catch (NullPointerException e) { 1637 // Expected. 1638 } 1639 } else { 1640 try { 1641 values.retainAll(null); 1642 // We have to tolerate a successful return (Sun bug 4802647) 1643 } catch (UnsupportedOperationException e) { 1644 // Expected. 1645 } catch (NullPointerException e) { 1646 // Expected. 1647 } 1648 } 1649 assertInvariants(map); 1650 } 1651 testValuesClear()1652 public void testValuesClear() { 1653 final Map<K, V> map; 1654 try { 1655 map = makePopulatedMap(); 1656 } catch (UnsupportedOperationException e) { 1657 return; 1658 } 1659 1660 Collection<V> valueCollection = map.values(); 1661 if (supportsClear) { 1662 valueCollection.clear(); 1663 assertTrue(valueCollection.isEmpty()); 1664 } else { 1665 try { 1666 valueCollection.clear(); 1667 fail("Expected UnsupportedOperationException."); 1668 } catch (UnsupportedOperationException e) { 1669 // Expected. 1670 } 1671 } 1672 assertInvariants(map); 1673 } 1674 mapEntry(K key, V value)1675 static <K, V> Entry<K, V> mapEntry(K key, V value) { 1676 return Collections.singletonMap(key, value).entrySet().iterator().next(); 1677 } 1678 } 1679