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