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 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 final 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 final Map<K, V> map; 290 final 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 final Map<K, V> map; 316 final 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 final Map<K, V> map; 338 final 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 final K unmappedKey; 348 final 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 final 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 final Map<K, V> map; 373 final 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 final 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 final Map<K, V> map; 400 final 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 final 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 final Map<K, V> map; 424 final 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 final 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 final 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 try { 481 iterator.next(); 482 iterator.remove(); 483 fail("Expected UnsupportedOperationException."); 484 } catch (UnsupportedOperationException expected) { 485 } 486 } 487 assertInvariants(map); 488 } 489 testEntrySetRemove()490 public void testEntrySetRemove() { 491 final 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 final Map<K, V> map; 516 final 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 final 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 final Map<K, V> map; 574 final 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 final 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 final 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 final 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 final 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 final 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 final 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 expected) { 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 final 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 final Map<K, V> map = makeEitherMap(); 769 770 Set<Entry<K, V>> entrySet = map.entrySet(); 771 final 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 final Map<K, V> map; 797 final 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 final V oldValue = entry.getValue(); 808 final 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 final 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 final V oldValue = entry.getValue(); 832 final 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 final Map<K, V> map; 841 try { 842 map = makePopulatedMap(); 843 } catch (UnsupportedOperationException e) { 844 return; 845 } 846 847 assertEquals(map, map); 848 assertEquals(makePopulatedMap(), map); 849 assertFalse(map.equals(Collections.emptyMap())); 850 // no-inspection ObjectEqualsNull 851 assertFalse(map.equals(null)); 852 } 853 testEqualsForLargerMap()854 public void testEqualsForLargerMap() { 855 if (!supportsPut) { 856 return; 857 } 858 859 final Map<K, V> map; 860 final Map<K, V> largerMap; 861 try { 862 map = makePopulatedMap(); 863 largerMap = makePopulatedMap(); 864 largerMap.put(getKeyNotInPopulatedMap(), getValueNotInPopulatedMap()); 865 } catch (UnsupportedOperationException e) { 866 return; 867 } 868 869 assertFalse(map.equals(largerMap)); 870 } 871 testEqualsForSmallerMap()872 public void testEqualsForSmallerMap() { 873 if (!supportsRemove) { 874 return; 875 } 876 877 final Map<K, V> map; 878 final Map<K, V> smallerMap; 879 try { 880 map = makePopulatedMap(); 881 smallerMap = makePopulatedMap(); 882 smallerMap.remove(smallerMap.keySet().iterator().next()); 883 } catch (UnsupportedOperationException e) { 884 return; 885 } 886 887 assertFalse(map.equals(smallerMap)); 888 } 889 testEqualsForEmptyMap()890 public void testEqualsForEmptyMap() { 891 final Map<K, V> map; 892 try { 893 map = makeEmptyMap(); 894 } catch (UnsupportedOperationException e) { 895 return; 896 } 897 898 assertEquals(map, map); 899 assertEquals(makeEmptyMap(), map); 900 assertEquals(Collections.emptyMap(), map); 901 assertFalse(map.equals(Collections.emptySet())); 902 // noinspection ObjectEqualsNull 903 assertFalse(map.equals(null)); 904 } 905 testGet()906 public void testGet() { 907 final Map<K, V> map; 908 try { 909 map = makePopulatedMap(); 910 } catch (UnsupportedOperationException e) { 911 return; 912 } 913 914 for (Entry<K, V> entry : map.entrySet()) { 915 assertEquals(entry.getValue(), map.get(entry.getKey())); 916 } 917 918 K unmappedKey = null; 919 try { 920 unmappedKey = getKeyNotInPopulatedMap(); 921 } catch (UnsupportedOperationException e) { 922 return; 923 } 924 assertNull(map.get(unmappedKey)); 925 } 926 testGetForEmptyMap()927 public void testGetForEmptyMap() { 928 final Map<K, V> map; 929 K unmappedKey = null; 930 try { 931 map = makeEmptyMap(); 932 unmappedKey = getKeyNotInPopulatedMap(); 933 } catch (UnsupportedOperationException e) { 934 return; 935 } 936 assertNull(map.get(unmappedKey)); 937 } 938 testGetNull()939 public void testGetNull() { 940 Map<K, V> map = makeEitherMap(); 941 if (allowsNullKeys) { 942 if (allowsNullValues) { 943 // TODO: decide what to test here. 944 } else { 945 assertEquals(map.containsKey(null), map.get(null) != null); 946 } 947 } else { 948 try { 949 map.get(null); 950 } catch (NullPointerException optional) { 951 } 952 } 953 assertInvariants(map); 954 } 955 testHashCode()956 public void testHashCode() { 957 final Map<K, V> map; 958 try { 959 map = makePopulatedMap(); 960 } catch (UnsupportedOperationException e) { 961 return; 962 } 963 assertInvariants(map); 964 } 965 testHashCodeForEmptyMap()966 public void testHashCodeForEmptyMap() { 967 final Map<K, V> map; 968 try { 969 map = makeEmptyMap(); 970 } catch (UnsupportedOperationException e) { 971 return; 972 } 973 assertInvariants(map); 974 } 975 testPutNewKey()976 public void testPutNewKey() { 977 final Map<K, V> map = makeEitherMap(); 978 final K keyToPut; 979 final V valueToPut; 980 try { 981 keyToPut = getKeyNotInPopulatedMap(); 982 valueToPut = getValueNotInPopulatedMap(); 983 } catch (UnsupportedOperationException e) { 984 return; 985 } 986 if (supportsPut) { 987 int initialSize = map.size(); 988 V oldValue = map.put(keyToPut, valueToPut); 989 assertEquals(valueToPut, map.get(keyToPut)); 990 assertTrue(map.containsKey(keyToPut)); 991 assertTrue(map.containsValue(valueToPut)); 992 assertEquals(initialSize + 1, map.size()); 993 assertNull(oldValue); 994 } else { 995 try { 996 map.put(keyToPut, valueToPut); 997 fail("Expected UnsupportedOperationException."); 998 } catch (UnsupportedOperationException expected) { 999 } 1000 } 1001 assertInvariants(map); 1002 } 1003 testPutExistingKey()1004 public void testPutExistingKey() { 1005 final Map<K, V> map; 1006 final K keyToPut; 1007 final V valueToPut; 1008 try { 1009 map = makePopulatedMap(); 1010 valueToPut = getValueNotInPopulatedMap(); 1011 } catch (UnsupportedOperationException e) { 1012 return; 1013 } 1014 keyToPut = map.keySet().iterator().next(); 1015 if (supportsPut) { 1016 int initialSize = map.size(); 1017 map.put(keyToPut, valueToPut); 1018 assertEquals(valueToPut, map.get(keyToPut)); 1019 assertTrue(map.containsKey(keyToPut)); 1020 assertTrue(map.containsValue(valueToPut)); 1021 assertEquals(initialSize, map.size()); 1022 } else { 1023 try { 1024 map.put(keyToPut, valueToPut); 1025 fail("Expected UnsupportedOperationException."); 1026 } catch (UnsupportedOperationException expected) { 1027 } 1028 } 1029 assertInvariants(map); 1030 } 1031 testPutNullKey()1032 public void testPutNullKey() { 1033 if (!supportsPut) { 1034 return; 1035 } 1036 final Map<K, V> map = makeEitherMap(); 1037 final V valueToPut; 1038 try { 1039 valueToPut = getValueNotInPopulatedMap(); 1040 } catch (UnsupportedOperationException e) { 1041 return; 1042 } 1043 if (allowsNullKeys) { 1044 final V oldValue = map.get(null); 1045 final V returnedValue = map.put(null, valueToPut); 1046 assertEquals(oldValue, returnedValue); 1047 assertEquals(valueToPut, map.get(null)); 1048 assertTrue(map.containsKey(null)); 1049 assertTrue(map.containsValue(valueToPut)); 1050 } else { 1051 try { 1052 map.put(null, valueToPut); 1053 fail("Expected RuntimeException"); 1054 } catch (RuntimeException expected) { 1055 } 1056 } 1057 assertInvariants(map); 1058 } 1059 testPutNullValue()1060 public void testPutNullValue() { 1061 if (!supportsPut) { 1062 return; 1063 } 1064 final Map<K, V> map = makeEitherMap(); 1065 final K keyToPut; 1066 try { 1067 keyToPut = getKeyNotInPopulatedMap(); 1068 } catch (UnsupportedOperationException e) { 1069 return; 1070 } 1071 if (allowsNullValues) { 1072 int initialSize = map.size(); 1073 final V oldValue = map.get(keyToPut); 1074 final V returnedValue = map.put(keyToPut, null); 1075 assertEquals(oldValue, returnedValue); 1076 assertNull(map.get(keyToPut)); 1077 assertTrue(map.containsKey(keyToPut)); 1078 assertTrue(map.containsValue(null)); 1079 assertEquals(initialSize + 1, map.size()); 1080 } else { 1081 try { 1082 map.put(keyToPut, null); 1083 fail("Expected RuntimeException"); 1084 } catch (RuntimeException expected) { 1085 } 1086 } 1087 assertInvariants(map); 1088 } 1089 testPutNullValueForExistingKey()1090 public void testPutNullValueForExistingKey() { 1091 if (!supportsPut) { 1092 return; 1093 } 1094 final Map<K, V> map; 1095 final K keyToPut; 1096 try { 1097 map = makePopulatedMap(); 1098 keyToPut = map.keySet().iterator().next(); 1099 } catch (UnsupportedOperationException e) { 1100 return; 1101 } 1102 if (allowsNullValues) { 1103 int initialSize = map.size(); 1104 final V oldValue = map.get(keyToPut); 1105 final V returnedValue = map.put(keyToPut, null); 1106 assertEquals(oldValue, returnedValue); 1107 assertNull(map.get(keyToPut)); 1108 assertTrue(map.containsKey(keyToPut)); 1109 assertTrue(map.containsValue(null)); 1110 assertEquals(initialSize, map.size()); 1111 } else { 1112 try { 1113 map.put(keyToPut, null); 1114 fail("Expected RuntimeException"); 1115 } catch (RuntimeException expected) { 1116 } 1117 } 1118 assertInvariants(map); 1119 } 1120 testPutAllNewKey()1121 public void testPutAllNewKey() { 1122 final Map<K, V> map = makeEitherMap(); 1123 final K keyToPut; 1124 final V valueToPut; 1125 try { 1126 keyToPut = getKeyNotInPopulatedMap(); 1127 valueToPut = getValueNotInPopulatedMap(); 1128 } catch (UnsupportedOperationException e) { 1129 return; 1130 } 1131 final Map<K, V> mapToPut = Collections.singletonMap(keyToPut, valueToPut); 1132 if (supportsPut) { 1133 int initialSize = map.size(); 1134 map.putAll(mapToPut); 1135 assertEquals(valueToPut, map.get(keyToPut)); 1136 assertTrue(map.containsKey(keyToPut)); 1137 assertTrue(map.containsValue(valueToPut)); 1138 assertEquals(initialSize + 1, map.size()); 1139 } else { 1140 try { 1141 map.putAll(mapToPut); 1142 fail("Expected UnsupportedOperationException."); 1143 } catch (UnsupportedOperationException expected) { 1144 } 1145 } 1146 assertInvariants(map); 1147 } 1148 testPutAllExistingKey()1149 public void testPutAllExistingKey() { 1150 final Map<K, V> map; 1151 final K keyToPut; 1152 final V valueToPut; 1153 try { 1154 map = makePopulatedMap(); 1155 valueToPut = getValueNotInPopulatedMap(); 1156 } catch (UnsupportedOperationException e) { 1157 return; 1158 } 1159 keyToPut = map.keySet().iterator().next(); 1160 final Map<K, V> mapToPut = Collections.singletonMap(keyToPut, valueToPut); 1161 int initialSize = map.size(); 1162 if (supportsPut) { 1163 map.putAll(mapToPut); 1164 assertEquals(valueToPut, map.get(keyToPut)); 1165 assertTrue(map.containsKey(keyToPut)); 1166 assertTrue(map.containsValue(valueToPut)); 1167 } else { 1168 try { 1169 map.putAll(mapToPut); 1170 fail("Expected UnsupportedOperationException."); 1171 } catch (UnsupportedOperationException expected) { 1172 } 1173 } 1174 assertEquals(initialSize, map.size()); 1175 assertInvariants(map); 1176 } 1177 testRemove()1178 public void testRemove() { 1179 final Map<K, V> map; 1180 final K keyToRemove; 1181 try { 1182 map = makePopulatedMap(); 1183 } catch (UnsupportedOperationException e) { 1184 return; 1185 } 1186 keyToRemove = map.keySet().iterator().next(); 1187 if (supportsRemove) { 1188 int initialSize = map.size(); 1189 V expectedValue = map.get(keyToRemove); 1190 V oldValue = map.remove(keyToRemove); 1191 assertEquals(expectedValue, oldValue); 1192 assertFalse(map.containsKey(keyToRemove)); 1193 assertEquals(initialSize - 1, map.size()); 1194 } else { 1195 try { 1196 map.remove(keyToRemove); 1197 fail("Expected UnsupportedOperationException."); 1198 } catch (UnsupportedOperationException expected) { 1199 } 1200 } 1201 assertInvariants(map); 1202 } 1203 testRemoveMissingKey()1204 public void testRemoveMissingKey() { 1205 final Map<K, V> map; 1206 final K keyToRemove; 1207 try { 1208 map = makePopulatedMap(); 1209 keyToRemove = getKeyNotInPopulatedMap(); 1210 } catch (UnsupportedOperationException e) { 1211 return; 1212 } 1213 if (supportsRemove) { 1214 int initialSize = map.size(); 1215 assertNull(map.remove(keyToRemove)); 1216 assertEquals(initialSize, map.size()); 1217 } else { 1218 try { 1219 map.remove(keyToRemove); 1220 fail("Expected UnsupportedOperationException."); 1221 } catch (UnsupportedOperationException expected) { 1222 } 1223 } 1224 assertInvariants(map); 1225 } 1226 testSize()1227 public void testSize() { 1228 assertInvariants(makeEitherMap()); 1229 } 1230 testKeySetRemove()1231 public void testKeySetRemove() { 1232 final Map<K, V> map; 1233 try { 1234 map = makePopulatedMap(); 1235 } catch (UnsupportedOperationException e) { 1236 return; 1237 } 1238 1239 Set<K> keys = map.keySet(); 1240 K key = keys.iterator().next(); 1241 if (supportsRemove) { 1242 int initialSize = map.size(); 1243 keys.remove(key); 1244 assertEquals(initialSize - 1, map.size()); 1245 assertFalse(map.containsKey(key)); 1246 } else { 1247 try { 1248 keys.remove(key); 1249 fail("Expected UnsupportedOperationException."); 1250 } catch (UnsupportedOperationException expected) { 1251 } 1252 } 1253 assertInvariants(map); 1254 } 1255 testKeySetRemoveAll()1256 public void testKeySetRemoveAll() { 1257 final Map<K, V> map; 1258 try { 1259 map = makePopulatedMap(); 1260 } catch (UnsupportedOperationException e) { 1261 return; 1262 } 1263 1264 Set<K> keys = map.keySet(); 1265 K key = keys.iterator().next(); 1266 if (supportsRemove) { 1267 int initialSize = map.size(); 1268 assertTrue(keys.removeAll(Collections.singleton(key))); 1269 assertEquals(initialSize - 1, map.size()); 1270 assertFalse(map.containsKey(key)); 1271 } else { 1272 try { 1273 keys.removeAll(Collections.singleton(key)); 1274 fail("Expected UnsupportedOperationException."); 1275 } catch (UnsupportedOperationException expected) { 1276 } 1277 } 1278 assertInvariants(map); 1279 } 1280 testKeySetRetainAll()1281 public void testKeySetRetainAll() { 1282 final Map<K, V> map; 1283 try { 1284 map = makePopulatedMap(); 1285 } catch (UnsupportedOperationException e) { 1286 return; 1287 } 1288 1289 Set<K> keys = map.keySet(); 1290 K key = keys.iterator().next(); 1291 if (supportsRemove) { 1292 keys.retainAll(Collections.singleton(key)); 1293 assertEquals(1, map.size()); 1294 assertTrue(map.containsKey(key)); 1295 } else { 1296 try { 1297 keys.retainAll(Collections.singleton(key)); 1298 fail("Expected UnsupportedOperationException."); 1299 } catch (UnsupportedOperationException expected) { 1300 } 1301 } 1302 assertInvariants(map); 1303 } 1304 testKeySetClear()1305 public void testKeySetClear() { 1306 final Map<K, V> map; 1307 try { 1308 map = makeEitherMap(); 1309 } catch (UnsupportedOperationException e) { 1310 return; 1311 } 1312 1313 Set<K> keySet = map.keySet(); 1314 if (supportsClear) { 1315 keySet.clear(); 1316 assertTrue(keySet.isEmpty()); 1317 } else { 1318 try { 1319 keySet.clear(); 1320 fail("Expected UnsupportedOperationException."); 1321 } catch (UnsupportedOperationException expected) { 1322 } 1323 } 1324 assertInvariants(map); 1325 } 1326 testKeySetRemoveAllNullFromEmpty()1327 public void testKeySetRemoveAllNullFromEmpty() { 1328 final Map<K, V> map; 1329 try { 1330 map = makeEmptyMap(); 1331 } catch (UnsupportedOperationException e) { 1332 return; 1333 } 1334 1335 Set<K> keySet = map.keySet(); 1336 if (supportsRemove) { 1337 try { 1338 keySet.removeAll(null); 1339 fail("Expected NullPointerException."); 1340 } catch (NullPointerException expected) { 1341 } 1342 } else { 1343 try { 1344 keySet.removeAll(null); 1345 fail("Expected UnsupportedOperationException or NullPointerException."); 1346 } catch (UnsupportedOperationException | NullPointerException e) { 1347 // Expected. 1348 } 1349 } 1350 assertInvariants(map); 1351 } 1352 testKeySetRetainAllNullFromEmpty()1353 public void testKeySetRetainAllNullFromEmpty() { 1354 final Map<K, V> map; 1355 try { 1356 map = makeEmptyMap(); 1357 } catch (UnsupportedOperationException e) { 1358 return; 1359 } 1360 1361 Set<K> keySet = map.keySet(); 1362 if (supportsRemove) { 1363 try { 1364 keySet.retainAll(null); 1365 // Returning successfully is not ideal, but tolerated. 1366 } catch (NullPointerException expected) { 1367 } 1368 } else { 1369 try { 1370 keySet.retainAll(null); 1371 // We have to tolerate a successful return (Sun bug 4802647) 1372 } catch (UnsupportedOperationException | NullPointerException e) { 1373 // Expected. 1374 } 1375 } 1376 assertInvariants(map); 1377 } 1378 testValues()1379 public void testValues() { 1380 final Map<K, V> map; 1381 final Collection<V> valueCollection; 1382 try { 1383 map = makePopulatedMap(); 1384 } catch (UnsupportedOperationException e) { 1385 return; 1386 } 1387 assertInvariants(map); 1388 1389 valueCollection = map.values(); 1390 final V unmappedValue; 1391 try { 1392 unmappedValue = getValueNotInPopulatedMap(); 1393 } catch (UnsupportedOperationException e) { 1394 return; 1395 } 1396 for (V value : valueCollection) { 1397 assertFalse(unmappedValue.equals(value)); 1398 } 1399 } 1400 testValuesIteratorRemove()1401 public void testValuesIteratorRemove() { 1402 final Map<K, V> map; 1403 try { 1404 map = makePopulatedMap(); 1405 } catch (UnsupportedOperationException e) { 1406 return; 1407 } 1408 1409 Collection<V> valueCollection = map.values(); 1410 Iterator<V> iterator = valueCollection.iterator(); 1411 if (supportsIteratorRemove) { 1412 int initialSize = map.size(); 1413 iterator.next(); 1414 iterator.remove(); 1415 assertEquals(initialSize - 1, map.size()); 1416 // (We can't assert that the values collection no longer contains the 1417 // removed value, because the underlying map can have multiple mappings 1418 // to the same value.) 1419 assertInvariants(map); 1420 try { 1421 iterator.remove(); 1422 fail("Expected IllegalStateException."); 1423 } catch (IllegalStateException expected) { 1424 } 1425 } else { 1426 try { 1427 iterator.next(); 1428 iterator.remove(); 1429 fail("Expected UnsupportedOperationException."); 1430 } catch (UnsupportedOperationException expected) { 1431 } 1432 } 1433 assertInvariants(map); 1434 } 1435 testValuesRemove()1436 public void testValuesRemove() { 1437 final Map<K, V> map; 1438 try { 1439 map = makePopulatedMap(); 1440 } catch (UnsupportedOperationException e) { 1441 return; 1442 } 1443 1444 Collection<V> valueCollection = map.values(); 1445 if (supportsRemove) { 1446 int initialSize = map.size(); 1447 valueCollection.remove(valueCollection.iterator().next()); 1448 assertEquals(initialSize - 1, map.size()); 1449 // (We can't assert that the values collection no longer contains the 1450 // removed value, because the underlying map can have multiple mappings 1451 // to the same value.) 1452 } else { 1453 try { 1454 valueCollection.remove(valueCollection.iterator().next()); 1455 fail("Expected UnsupportedOperationException."); 1456 } catch (UnsupportedOperationException expected) { 1457 } 1458 } 1459 assertInvariants(map); 1460 } 1461 testValuesRemoveMissing()1462 public void testValuesRemoveMissing() { 1463 final Map<K, V> map; 1464 final V valueToRemove; 1465 try { 1466 map = makeEitherMap(); 1467 valueToRemove = getValueNotInPopulatedMap(); 1468 } catch (UnsupportedOperationException e) { 1469 return; 1470 } 1471 1472 Collection<V> valueCollection = map.values(); 1473 int initialSize = map.size(); 1474 if (supportsRemove) { 1475 assertFalse(valueCollection.remove(valueToRemove)); 1476 } else { 1477 try { 1478 assertFalse(valueCollection.remove(valueToRemove)); 1479 } catch (UnsupportedOperationException e) { 1480 // Tolerated. 1481 } 1482 } 1483 assertEquals(initialSize, map.size()); 1484 assertInvariants(map); 1485 } 1486 testValuesRemoveAll()1487 public void testValuesRemoveAll() { 1488 final Map<K, V> map; 1489 try { 1490 map = makePopulatedMap(); 1491 } catch (UnsupportedOperationException e) { 1492 return; 1493 } 1494 1495 Collection<V> valueCollection = map.values(); 1496 Set<V> valuesToRemove = singleton(valueCollection.iterator().next()); 1497 if (supportsRemove) { 1498 valueCollection.removeAll(valuesToRemove); 1499 for (V value : valuesToRemove) { 1500 assertFalse(valueCollection.contains(value)); 1501 } 1502 for (V value : valueCollection) { 1503 assertFalse(valuesToRemove.contains(value)); 1504 } 1505 } else { 1506 try { 1507 valueCollection.removeAll(valuesToRemove); 1508 fail("Expected UnsupportedOperationException."); 1509 } catch (UnsupportedOperationException expected) { 1510 } 1511 } 1512 assertInvariants(map); 1513 } 1514 testValuesRemoveAllNullFromEmpty()1515 public void testValuesRemoveAllNullFromEmpty() { 1516 final Map<K, V> map; 1517 try { 1518 map = makeEmptyMap(); 1519 } catch (UnsupportedOperationException e) { 1520 return; 1521 } 1522 1523 Collection<V> values = map.values(); 1524 if (supportsRemove) { 1525 try { 1526 values.removeAll(null); 1527 // Returning successfully is not ideal, but tolerated. 1528 } catch (NullPointerException expected) { 1529 } 1530 } else { 1531 try { 1532 values.removeAll(null); 1533 // We have to tolerate a successful return (Sun bug 4802647) 1534 } catch (UnsupportedOperationException | NullPointerException e) { 1535 // Expected. 1536 } 1537 } 1538 assertInvariants(map); 1539 } 1540 testValuesRetainAll()1541 public void testValuesRetainAll() { 1542 final Map<K, V> map; 1543 try { 1544 map = makePopulatedMap(); 1545 } catch (UnsupportedOperationException e) { 1546 return; 1547 } 1548 1549 Collection<V> valueCollection = map.values(); 1550 Set<V> valuesToRetain = singleton(valueCollection.iterator().next()); 1551 if (supportsRemove) { 1552 valueCollection.retainAll(valuesToRetain); 1553 for (V value : valuesToRetain) { 1554 assertTrue(valueCollection.contains(value)); 1555 } 1556 for (V value : valueCollection) { 1557 assertTrue(valuesToRetain.contains(value)); 1558 } 1559 } else { 1560 try { 1561 valueCollection.retainAll(valuesToRetain); 1562 fail("Expected UnsupportedOperationException."); 1563 } catch (UnsupportedOperationException expected) { 1564 } 1565 } 1566 assertInvariants(map); 1567 } 1568 testValuesRetainAllNullFromEmpty()1569 public void testValuesRetainAllNullFromEmpty() { 1570 final Map<K, V> map; 1571 try { 1572 map = makeEmptyMap(); 1573 } catch (UnsupportedOperationException e) { 1574 return; 1575 } 1576 1577 Collection<V> values = map.values(); 1578 if (supportsRemove) { 1579 try { 1580 values.retainAll(null); 1581 // Returning successfully is not ideal, but tolerated. 1582 } catch (NullPointerException expected) { 1583 } 1584 } else { 1585 try { 1586 values.retainAll(null); 1587 // We have to tolerate a successful return (Sun bug 4802647) 1588 } catch (UnsupportedOperationException | NullPointerException e) { 1589 // Expected. 1590 } 1591 } 1592 assertInvariants(map); 1593 } 1594 testValuesClear()1595 public void testValuesClear() { 1596 final Map<K, V> map; 1597 try { 1598 map = makePopulatedMap(); 1599 } catch (UnsupportedOperationException e) { 1600 return; 1601 } 1602 1603 Collection<V> valueCollection = map.values(); 1604 if (supportsClear) { 1605 valueCollection.clear(); 1606 assertTrue(valueCollection.isEmpty()); 1607 } else { 1608 try { 1609 valueCollection.clear(); 1610 fail("Expected UnsupportedOperationException."); 1611 } catch (UnsupportedOperationException expected) { 1612 } 1613 } 1614 assertInvariants(map); 1615 } 1616 mapEntry(K key, V value)1617 static <K, V> Entry<K, V> mapEntry(K key, V value) { 1618 return Collections.singletonMap(key, value).entrySet().iterator().next(); 1619 } 1620 } 1621