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