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