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