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 int unused = value.hashCode(); 153 } catch (Exception e) { 154 return false; 155 } 156 return true; 157 } 158 } 159 return true; 160 } 161 162 /** 163 * Checks all the properties that should always hold of a map. Also calls {@link 164 * #assertMoreInvariants} to check invariants that are peculiar to specific implementations. 165 * 166 * @see #assertMoreInvariants 167 * @param map the map to check. 168 */ 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 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 Map<K, V> map; 290 K unmappedKey; 291 try { 292 map = makePopulatedMap(); 293 unmappedKey = getKeyNotInPopulatedMap(); 294 } catch (UnsupportedOperationException e) { 295 return; 296 } 297 assertFalse(map.containsKey(unmappedKey)); 298 try { 299 assertFalse(map.containsKey(new IncompatibleKeyType())); 300 } catch (ClassCastException tolerated) { 301 } 302 assertTrue(map.containsKey(map.keySet().iterator().next())); 303 if (allowsNullKeys) { 304 boolean unused = map.containsKey(null); 305 } else { 306 try { 307 boolean unused2 = map.containsKey(null); 308 } catch (NullPointerException optional) { 309 } 310 } 311 assertInvariants(map); 312 } 313 314 public void testContainsValue() { 315 Map<K, V> map; 316 V unmappedValue; 317 try { 318 map = makePopulatedMap(); 319 unmappedValue = getValueNotInPopulatedMap(); 320 } catch (UnsupportedOperationException e) { 321 return; 322 } 323 assertFalse(map.containsValue(unmappedValue)); 324 assertTrue(map.containsValue(map.values().iterator().next())); 325 if (allowsNullValues) { 326 boolean unused = map.containsValue(null); 327 } else { 328 try { 329 boolean unused2 = map.containsKey(null); 330 } catch (NullPointerException optional) { 331 } 332 } 333 assertInvariants(map); 334 } 335 336 public void testEntrySet() { 337 Map<K, V> map; 338 Set<Entry<K, V>> entrySet; 339 try { 340 map = makePopulatedMap(); 341 } catch (UnsupportedOperationException e) { 342 return; 343 } 344 assertInvariants(map); 345 346 entrySet = map.entrySet(); 347 K unmappedKey; 348 V unmappedValue; 349 try { 350 unmappedKey = getKeyNotInPopulatedMap(); 351 unmappedValue = getValueNotInPopulatedMap(); 352 } catch (UnsupportedOperationException e) { 353 return; 354 } 355 for (Entry<K, V> entry : entrySet) { 356 assertFalse(unmappedKey.equals(entry.getKey())); 357 assertFalse(unmappedValue.equals(entry.getValue())); 358 } 359 } 360 361 public void testEntrySetForEmptyMap() { 362 Map<K, V> map; 363 try { 364 map = makeEmptyMap(); 365 } catch (UnsupportedOperationException e) { 366 return; 367 } 368 assertInvariants(map); 369 } 370 371 public void testEntrySetContainsEntryIncompatibleKey() { 372 Map<K, V> map; 373 Set<Entry<K, V>> entrySet; 374 try { 375 map = makeEitherMap(); 376 } catch (UnsupportedOperationException e) { 377 return; 378 } 379 assertInvariants(map); 380 381 entrySet = map.entrySet(); 382 V unmappedValue; 383 try { 384 unmappedValue = getValueNotInPopulatedMap(); 385 } catch (UnsupportedOperationException e) { 386 return; 387 } 388 Entry<IncompatibleKeyType, V> entry = mapEntry(new IncompatibleKeyType(), unmappedValue); 389 try { 390 assertFalse(entrySet.contains(entry)); 391 } catch (ClassCastException tolerated) { 392 } 393 } 394 395 public void testEntrySetContainsEntryNullKeyPresent() { 396 if (!allowsNullKeys || !supportsPut) { 397 return; 398 } 399 Map<K, V> map; 400 Set<Entry<K, V>> entrySet; 401 try { 402 map = makeEitherMap(); 403 } catch (UnsupportedOperationException e) { 404 return; 405 } 406 assertInvariants(map); 407 408 entrySet = map.entrySet(); 409 V unmappedValue; 410 try { 411 unmappedValue = getValueNotInPopulatedMap(); 412 } catch (UnsupportedOperationException e) { 413 return; 414 } 415 416 map.put(null, unmappedValue); 417 Entry<K, V> entry = mapEntry(null, unmappedValue); 418 assertTrue(entrySet.contains(entry)); 419 assertFalse(entrySet.contains(mapEntry(null, null))); 420 } 421 422 public void testEntrySetContainsEntryNullKeyMissing() { 423 Map<K, V> map; 424 Set<Entry<K, V>> entrySet; 425 try { 426 map = makeEitherMap(); 427 } catch (UnsupportedOperationException e) { 428 return; 429 } 430 assertInvariants(map); 431 432 entrySet = map.entrySet(); 433 V unmappedValue; 434 try { 435 unmappedValue = getValueNotInPopulatedMap(); 436 } catch (UnsupportedOperationException e) { 437 return; 438 } 439 Entry<K, V> entry = mapEntry(null, unmappedValue); 440 try { 441 assertFalse(entrySet.contains(entry)); 442 } catch (NullPointerException e) { 443 assertFalse(allowsNullKeys); 444 } 445 try { 446 assertFalse(entrySet.contains(mapEntry(null, null))); 447 } catch (NullPointerException e) { 448 assertFalse(allowsNullKeys && allowsNullValues); 449 } 450 } 451 452 public void testEntrySetIteratorRemove() { 453 Map<K, V> map; 454 try { 455 map = makePopulatedMap(); 456 } catch (UnsupportedOperationException e) { 457 return; 458 } 459 460 Set<Entry<K, V>> entrySet = map.entrySet(); 461 Iterator<Entry<K, V>> iterator = entrySet.iterator(); 462 if (supportsIteratorRemove) { 463 int initialSize = map.size(); 464 Entry<K, V> entry = iterator.next(); 465 Entry<K, V> entryCopy = Helpers.mapEntry(entry.getKey(), entry.getValue()); 466 467 iterator.remove(); 468 assertEquals(initialSize - 1, map.size()); 469 470 // Use "entryCopy" instead of "entry" because "entry" might be invalidated after 471 // iterator.remove(). 472 assertFalse(entrySet.contains(entryCopy)); 473 assertInvariants(map); 474 try { 475 iterator.remove(); 476 fail("Expected IllegalStateException."); 477 } catch (IllegalStateException expected) { 478 } 479 } else { 480 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 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 Map<K, V> map; 516 K key; 517 try { 518 map = makeEitherMap(); 519 key = getKeyNotInPopulatedMap(); 520 } catch (UnsupportedOperationException e) { 521 return; 522 } 523 524 Set<Entry<K, V>> entrySet = map.entrySet(); 525 Entry<K, V> entry = mapEntry(key, getValueNotInPopulatedMap()); 526 int initialSize = map.size(); 527 if (supportsRemove) { 528 boolean didRemove = entrySet.remove(entry); 529 assertFalse(didRemove); 530 } else { 531 try { 532 boolean didRemove = entrySet.remove(entry); 533 assertFalse(didRemove); 534 } catch (UnsupportedOperationException optional) { 535 } 536 } 537 assertEquals(initialSize, map.size()); 538 assertFalse(map.containsKey(key)); 539 assertInvariants(map); 540 } 541 542 public void testEntrySetRemoveDifferentValue() { 543 Map<K, V> map; 544 try { 545 map = makePopulatedMap(); 546 } catch (UnsupportedOperationException e) { 547 return; 548 } 549 550 Set<Entry<K, V>> entrySet = map.entrySet(); 551 K key = map.keySet().iterator().next(); 552 Entry<K, V> entry = mapEntry(key, getValueNotInPopulatedMap()); 553 int initialSize = map.size(); 554 if (supportsRemove) { 555 boolean didRemove = entrySet.remove(entry); 556 assertFalse(didRemove); 557 } else { 558 try { 559 boolean didRemove = entrySet.remove(entry); 560 assertFalse(didRemove); 561 } catch (UnsupportedOperationException optional) { 562 } 563 } 564 assertEquals(initialSize, map.size()); 565 assertTrue(map.containsKey(key)); 566 assertInvariants(map); 567 } 568 569 public void testEntrySetRemoveNullKeyPresent() { 570 if (!allowsNullKeys || !supportsPut || !supportsRemove) { 571 return; 572 } 573 Map<K, V> map; 574 Set<Entry<K, V>> entrySet; 575 try { 576 map = makeEitherMap(); 577 } catch (UnsupportedOperationException e) { 578 return; 579 } 580 assertInvariants(map); 581 582 entrySet = map.entrySet(); 583 V unmappedValue; 584 try { 585 unmappedValue = getValueNotInPopulatedMap(); 586 } catch (UnsupportedOperationException e) { 587 return; 588 } 589 590 map.put(null, unmappedValue); 591 assertEquals(unmappedValue, map.get(null)); 592 assertTrue(map.containsKey(null)); 593 Entry<K, V> entry = mapEntry(null, unmappedValue); 594 assertTrue(entrySet.remove(entry)); 595 assertNull(map.get(null)); 596 assertFalse(map.containsKey(null)); 597 } 598 599 public void testEntrySetRemoveNullKeyMissing() { 600 Map<K, V> map; 601 try { 602 map = makeEitherMap(); 603 } catch (UnsupportedOperationException e) { 604 return; 605 } 606 607 Set<Entry<K, V>> entrySet = map.entrySet(); 608 Entry<K, V> entry = mapEntry(null, getValueNotInPopulatedMap()); 609 int initialSize = map.size(); 610 if (supportsRemove) { 611 try { 612 boolean didRemove = entrySet.remove(entry); 613 assertFalse(didRemove); 614 } catch (NullPointerException e) { 615 assertFalse(allowsNullKeys); 616 } 617 } else { 618 try { 619 boolean didRemove = entrySet.remove(entry); 620 assertFalse(didRemove); 621 } catch (UnsupportedOperationException optional) { 622 } 623 } 624 assertEquals(initialSize, map.size()); 625 assertInvariants(map); 626 } 627 628 public void testEntrySetRemoveAll() { 629 Map<K, V> map; 630 try { 631 map = makePopulatedMap(); 632 } catch (UnsupportedOperationException e) { 633 return; 634 } 635 636 Set<Entry<K, V>> entrySet = map.entrySet(); 637 638 Entry<K, V> entryToRemove = entrySet.iterator().next(); 639 Set<Entry<K, V>> entriesToRemove = singleton(entryToRemove); 640 if (supportsRemove) { 641 // We use a copy of "entryToRemove" in the assertion because "entryToRemove" might be 642 // invalidated and have undefined behavior after entrySet.removeAll(entriesToRemove), 643 // for example entryToRemove.getValue() might be null. 644 Entry<K, V> entryToRemoveCopy = 645 Helpers.mapEntry(entryToRemove.getKey(), entryToRemove.getValue()); 646 647 int initialSize = map.size(); 648 boolean didRemove = entrySet.removeAll(entriesToRemove); 649 assertTrue(didRemove); 650 assertEquals(initialSize - entriesToRemove.size(), map.size()); 651 652 // Use "entryToRemoveCopy" instead of "entryToRemove" because it might be invalidated and 653 // have undefined behavior after entrySet.removeAll(entriesToRemove), 654 assertFalse(entrySet.contains(entryToRemoveCopy)); 655 } else { 656 try { 657 entrySet.removeAll(entriesToRemove); 658 fail("Expected UnsupportedOperationException."); 659 } catch (UnsupportedOperationException expected) { 660 } 661 } 662 assertInvariants(map); 663 } 664 665 public void testEntrySetRemoveAllNullFromEmpty() { 666 Map<K, V> map; 667 try { 668 map = makeEmptyMap(); 669 } catch (UnsupportedOperationException e) { 670 return; 671 } 672 673 Set<Entry<K, V>> entrySet = map.entrySet(); 674 if (supportsRemove) { 675 try { 676 entrySet.removeAll(null); 677 fail("Expected NullPointerException."); 678 } catch (NullPointerException expected) { 679 } 680 } else { 681 try { 682 entrySet.removeAll(null); 683 fail("Expected UnsupportedOperationException or NullPointerException."); 684 } catch (UnsupportedOperationException | NullPointerException e) { 685 // Expected. 686 } 687 } 688 assertInvariants(map); 689 } 690 691 public void testEntrySetRetainAll() { 692 Map<K, V> map; 693 try { 694 map = makePopulatedMap(); 695 } catch (UnsupportedOperationException e) { 696 return; 697 } 698 699 Set<Entry<K, V>> entrySet = map.entrySet(); 700 Set<Entry<K, V>> entriesToRetain = singleton(entrySet.iterator().next()); 701 if (supportsRemove) { 702 boolean shouldRemove = (entrySet.size() > entriesToRetain.size()); 703 boolean didRemove = entrySet.retainAll(entriesToRetain); 704 assertEquals(shouldRemove, didRemove); 705 assertEquals(entriesToRetain.size(), map.size()); 706 for (Entry<K, V> entry : entriesToRetain) { 707 assertTrue(entrySet.contains(entry)); 708 } 709 } else { 710 try { 711 entrySet.retainAll(entriesToRetain); 712 fail("Expected UnsupportedOperationException."); 713 } catch (UnsupportedOperationException expected) { 714 } 715 } 716 assertInvariants(map); 717 } 718 719 public void testEntrySetRetainAllNullFromEmpty() { 720 Map<K, V> map; 721 try { 722 map = makeEmptyMap(); 723 } catch (UnsupportedOperationException e) { 724 return; 725 } 726 727 Set<Entry<K, V>> entrySet = map.entrySet(); 728 if (supportsRemove) { 729 try { 730 entrySet.retainAll(null); 731 // Returning successfully is not ideal, but tolerated. 732 } catch (NullPointerException 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 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 Map<K, V> map = makeEitherMap(); 769 770 Set<Entry<K, V>> entrySet = map.entrySet(); 771 Entry<K, V> entryToAdd = mapEntry(null, null); 772 try { 773 entrySet.add(entryToAdd); 774 fail("Expected UnsupportedOperationException or NullPointerException."); 775 } catch (UnsupportedOperationException | NullPointerException e) { 776 // Expected. 777 } 778 assertInvariants(map); 779 780 try { 781 entrySet.addAll(singleton(entryToAdd)); 782 fail("Expected UnsupportedOperationException or NullPointerException."); 783 } catch (UnsupportedOperationException | NullPointerException e) { 784 // Expected. 785 } 786 assertInvariants(map); 787 } 788 789 public void testEntrySetSetValue() { 790 // TODO: Investigate the extent to which, in practice, maps that support 791 // put() also support Entry.setValue(). 792 if (!supportsPut) { 793 return; 794 } 795 796 Map<K, V> map; 797 V valueToSet; 798 try { 799 map = makePopulatedMap(); 800 valueToSet = getValueNotInPopulatedMap(); 801 } catch (UnsupportedOperationException e) { 802 return; 803 } 804 805 Set<Entry<K, V>> entrySet = map.entrySet(); 806 Entry<K, V> entry = entrySet.iterator().next(); 807 V oldValue = entry.getValue(); 808 V returnedValue = entry.setValue(valueToSet); 809 assertEquals(oldValue, returnedValue); 810 assertTrue(entrySet.contains(mapEntry(entry.getKey(), valueToSet))); 811 assertEquals(valueToSet, map.get(entry.getKey())); 812 assertInvariants(map); 813 } 814 815 public void testEntrySetSetValueSameValue() { 816 // TODO: Investigate the extent to which, in practice, maps that support 817 // put() also support Entry.setValue(). 818 if (!supportsPut) { 819 return; 820 } 821 822 Map<K, V> map; 823 try { 824 map = makePopulatedMap(); 825 } catch (UnsupportedOperationException e) { 826 return; 827 } 828 829 Set<Entry<K, V>> entrySet = map.entrySet(); 830 Entry<K, V> entry = entrySet.iterator().next(); 831 V oldValue = entry.getValue(); 832 V returnedValue = entry.setValue(oldValue); 833 assertEquals(oldValue, returnedValue); 834 assertTrue(entrySet.contains(mapEntry(entry.getKey(), oldValue))); 835 assertEquals(oldValue, map.get(entry.getKey())); 836 assertInvariants(map); 837 } 838 839 public void testEqualsForEqualMap() { 840 Map<K, V> map; 841 try { 842 map = makePopulatedMap(); 843 } catch (UnsupportedOperationException e) { 844 return; 845 } 846 847 // Explicitly call `equals`; `assertEquals` might return fast 848 assertTrue(map.equals(map)); 849 assertTrue(makePopulatedMap().equals(map)); 850 assertFalse(map.equals(Collections.emptyMap())); 851 // no-inspection ObjectEqualsNull 852 assertFalse(map.equals(null)); 853 } 854 855 public void testEqualsForLargerMap() { 856 if (!supportsPut) { 857 return; 858 } 859 860 Map<K, V> map; 861 Map<K, V> largerMap; 862 try { 863 map = makePopulatedMap(); 864 largerMap = makePopulatedMap(); 865 largerMap.put(getKeyNotInPopulatedMap(), getValueNotInPopulatedMap()); 866 } catch (UnsupportedOperationException e) { 867 return; 868 } 869 870 assertFalse(map.equals(largerMap)); 871 } 872 873 public void testEqualsForSmallerMap() { 874 if (!supportsRemove) { 875 return; 876 } 877 878 Map<K, V> map; 879 Map<K, V> smallerMap; 880 try { 881 map = makePopulatedMap(); 882 smallerMap = makePopulatedMap(); 883 smallerMap.remove(smallerMap.keySet().iterator().next()); 884 } catch (UnsupportedOperationException e) { 885 return; 886 } 887 888 assertFalse(map.equals(smallerMap)); 889 } 890 891 public void testEqualsForEmptyMap() { 892 Map<K, V> map; 893 try { 894 map = makeEmptyMap(); 895 } catch (UnsupportedOperationException e) { 896 return; 897 } 898 899 // Explicitly call `equals`; `assertEquals` might return fast 900 assertTrue(map.equals(map)); 901 assertTrue(makeEmptyMap().equals(map)); 902 assertEquals(Collections.emptyMap(), map); 903 assertFalse(map.equals(Collections.emptySet())); 904 // noinspection ObjectEqualsNull 905 assertFalse(map.equals(null)); 906 } 907 908 public void testGet() { 909 Map<K, V> map; 910 try { 911 map = makePopulatedMap(); 912 } catch (UnsupportedOperationException e) { 913 return; 914 } 915 916 for (Entry<K, V> entry : map.entrySet()) { 917 assertEquals(entry.getValue(), map.get(entry.getKey())); 918 } 919 920 K unmappedKey = null; 921 try { 922 unmappedKey = getKeyNotInPopulatedMap(); 923 } catch (UnsupportedOperationException e) { 924 return; 925 } 926 assertNull(map.get(unmappedKey)); 927 } 928 929 public void testGetForEmptyMap() { 930 Map<K, V> map; 931 K unmappedKey = null; 932 try { 933 map = makeEmptyMap(); 934 unmappedKey = getKeyNotInPopulatedMap(); 935 } catch (UnsupportedOperationException e) { 936 return; 937 } 938 assertNull(map.get(unmappedKey)); 939 } 940 941 public void testGetNull() { 942 Map<K, V> map = makeEitherMap(); 943 if (allowsNullKeys) { 944 if (allowsNullValues) { 945 // TODO: decide what to test here. 946 } else { 947 assertEquals(map.containsKey(null), map.get(null) != null); 948 } 949 } else { 950 try { 951 map.get(null); 952 } catch (NullPointerException optional) { 953 } 954 } 955 assertInvariants(map); 956 } 957 958 public void testHashCode() { 959 Map<K, V> map; 960 try { 961 map = makePopulatedMap(); 962 } catch (UnsupportedOperationException e) { 963 return; 964 } 965 assertInvariants(map); 966 } 967 968 public void testHashCodeForEmptyMap() { 969 Map<K, V> map; 970 try { 971 map = makeEmptyMap(); 972 } catch (UnsupportedOperationException e) { 973 return; 974 } 975 assertInvariants(map); 976 } 977 978 public void testPutNewKey() { 979 Map<K, V> map = makeEitherMap(); 980 K keyToPut; 981 V valueToPut; 982 try { 983 keyToPut = getKeyNotInPopulatedMap(); 984 valueToPut = getValueNotInPopulatedMap(); 985 } catch (UnsupportedOperationException e) { 986 return; 987 } 988 if (supportsPut) { 989 int initialSize = map.size(); 990 V oldValue = map.put(keyToPut, valueToPut); 991 assertEquals(valueToPut, map.get(keyToPut)); 992 assertTrue(map.containsKey(keyToPut)); 993 assertTrue(map.containsValue(valueToPut)); 994 assertEquals(initialSize + 1, map.size()); 995 assertNull(oldValue); 996 } else { 997 try { 998 map.put(keyToPut, valueToPut); 999 fail("Expected UnsupportedOperationException."); 1000 } catch (UnsupportedOperationException expected) { 1001 } 1002 } 1003 assertInvariants(map); 1004 } 1005 1006 public void testPutExistingKey() { 1007 Map<K, V> map; 1008 K keyToPut; 1009 V valueToPut; 1010 try { 1011 map = makePopulatedMap(); 1012 valueToPut = getValueNotInPopulatedMap(); 1013 } catch (UnsupportedOperationException e) { 1014 return; 1015 } 1016 keyToPut = map.keySet().iterator().next(); 1017 if (supportsPut) { 1018 int initialSize = map.size(); 1019 map.put(keyToPut, valueToPut); 1020 assertEquals(valueToPut, map.get(keyToPut)); 1021 assertTrue(map.containsKey(keyToPut)); 1022 assertTrue(map.containsValue(valueToPut)); 1023 assertEquals(initialSize, map.size()); 1024 } else { 1025 try { 1026 map.put(keyToPut, valueToPut); 1027 fail("Expected UnsupportedOperationException."); 1028 } catch (UnsupportedOperationException expected) { 1029 } 1030 } 1031 assertInvariants(map); 1032 } 1033 1034 public void testPutNullKey() { 1035 if (!supportsPut) { 1036 return; 1037 } 1038 Map<K, V> map = makeEitherMap(); 1039 V valueToPut; 1040 try { 1041 valueToPut = getValueNotInPopulatedMap(); 1042 } catch (UnsupportedOperationException e) { 1043 return; 1044 } 1045 if (allowsNullKeys) { 1046 V oldValue = map.get(null); 1047 V returnedValue = map.put(null, valueToPut); 1048 assertEquals(oldValue, returnedValue); 1049 assertEquals(valueToPut, map.get(null)); 1050 assertTrue(map.containsKey(null)); 1051 assertTrue(map.containsValue(valueToPut)); 1052 } else { 1053 try { 1054 map.put(null, valueToPut); 1055 fail("Expected RuntimeException"); 1056 } catch (RuntimeException expected) { 1057 } 1058 } 1059 assertInvariants(map); 1060 } 1061 1062 public void testPutNullValue() { 1063 if (!supportsPut) { 1064 return; 1065 } 1066 Map<K, V> map = makeEitherMap(); 1067 K keyToPut; 1068 try { 1069 keyToPut = getKeyNotInPopulatedMap(); 1070 } catch (UnsupportedOperationException e) { 1071 return; 1072 } 1073 if (allowsNullValues) { 1074 int initialSize = map.size(); 1075 V oldValue = map.get(keyToPut); 1076 V returnedValue = map.put(keyToPut, null); 1077 assertEquals(oldValue, returnedValue); 1078 assertNull(map.get(keyToPut)); 1079 assertTrue(map.containsKey(keyToPut)); 1080 assertTrue(map.containsValue(null)); 1081 assertEquals(initialSize + 1, map.size()); 1082 } else { 1083 try { 1084 map.put(keyToPut, null); 1085 fail("Expected RuntimeException"); 1086 } catch (RuntimeException expected) { 1087 } 1088 } 1089 assertInvariants(map); 1090 } 1091 1092 public void testPutNullValueForExistingKey() { 1093 if (!supportsPut) { 1094 return; 1095 } 1096 Map<K, V> map; 1097 K keyToPut; 1098 try { 1099 map = makePopulatedMap(); 1100 keyToPut = map.keySet().iterator().next(); 1101 } catch (UnsupportedOperationException e) { 1102 return; 1103 } 1104 if (allowsNullValues) { 1105 int initialSize = map.size(); 1106 V oldValue = map.get(keyToPut); 1107 V returnedValue = map.put(keyToPut, null); 1108 assertEquals(oldValue, returnedValue); 1109 assertNull(map.get(keyToPut)); 1110 assertTrue(map.containsKey(keyToPut)); 1111 assertTrue(map.containsValue(null)); 1112 assertEquals(initialSize, map.size()); 1113 } else { 1114 try { 1115 map.put(keyToPut, null); 1116 fail("Expected RuntimeException"); 1117 } catch (RuntimeException expected) { 1118 } 1119 } 1120 assertInvariants(map); 1121 } 1122 1123 public void testPutAllNewKey() { 1124 Map<K, V> map = makeEitherMap(); 1125 K keyToPut; 1126 V valueToPut; 1127 try { 1128 keyToPut = getKeyNotInPopulatedMap(); 1129 valueToPut = getValueNotInPopulatedMap(); 1130 } catch (UnsupportedOperationException e) { 1131 return; 1132 } 1133 Map<K, V> mapToPut = Collections.singletonMap(keyToPut, valueToPut); 1134 if (supportsPut) { 1135 int initialSize = map.size(); 1136 map.putAll(mapToPut); 1137 assertEquals(valueToPut, map.get(keyToPut)); 1138 assertTrue(map.containsKey(keyToPut)); 1139 assertTrue(map.containsValue(valueToPut)); 1140 assertEquals(initialSize + 1, map.size()); 1141 } else { 1142 try { 1143 map.putAll(mapToPut); 1144 fail("Expected UnsupportedOperationException."); 1145 } catch (UnsupportedOperationException expected) { 1146 } 1147 } 1148 assertInvariants(map); 1149 } 1150 1151 public void testPutAllExistingKey() { 1152 Map<K, V> map; 1153 K keyToPut; 1154 V valueToPut; 1155 try { 1156 map = makePopulatedMap(); 1157 valueToPut = getValueNotInPopulatedMap(); 1158 } catch (UnsupportedOperationException e) { 1159 return; 1160 } 1161 keyToPut = map.keySet().iterator().next(); 1162 Map<K, V> mapToPut = Collections.singletonMap(keyToPut, valueToPut); 1163 int initialSize = map.size(); 1164 if (supportsPut) { 1165 map.putAll(mapToPut); 1166 assertEquals(valueToPut, map.get(keyToPut)); 1167 assertTrue(map.containsKey(keyToPut)); 1168 assertTrue(map.containsValue(valueToPut)); 1169 } else { 1170 try { 1171 map.putAll(mapToPut); 1172 fail("Expected UnsupportedOperationException."); 1173 } catch (UnsupportedOperationException expected) { 1174 } 1175 } 1176 assertEquals(initialSize, map.size()); 1177 assertInvariants(map); 1178 } 1179 1180 public void testRemove() { 1181 Map<K, V> map; 1182 K keyToRemove; 1183 try { 1184 map = makePopulatedMap(); 1185 } catch (UnsupportedOperationException e) { 1186 return; 1187 } 1188 keyToRemove = map.keySet().iterator().next(); 1189 if (supportsRemove) { 1190 int initialSize = map.size(); 1191 V expectedValue = map.get(keyToRemove); 1192 V oldValue = map.remove(keyToRemove); 1193 assertEquals(expectedValue, oldValue); 1194 assertFalse(map.containsKey(keyToRemove)); 1195 assertEquals(initialSize - 1, map.size()); 1196 } else { 1197 try { 1198 map.remove(keyToRemove); 1199 fail("Expected UnsupportedOperationException."); 1200 } catch (UnsupportedOperationException expected) { 1201 } 1202 } 1203 assertInvariants(map); 1204 } 1205 1206 public void testRemoveMissingKey() { 1207 Map<K, V> map; 1208 K keyToRemove; 1209 try { 1210 map = makePopulatedMap(); 1211 keyToRemove = getKeyNotInPopulatedMap(); 1212 } catch (UnsupportedOperationException e) { 1213 return; 1214 } 1215 if (supportsRemove) { 1216 int initialSize = map.size(); 1217 assertNull(map.remove(keyToRemove)); 1218 assertEquals(initialSize, map.size()); 1219 } else { 1220 try { 1221 map.remove(keyToRemove); 1222 fail("Expected UnsupportedOperationException."); 1223 } catch (UnsupportedOperationException expected) { 1224 } 1225 } 1226 assertInvariants(map); 1227 } 1228 1229 public void testSize() { 1230 assertInvariants(makeEitherMap()); 1231 } 1232 1233 public void testKeySetRemove() { 1234 Map<K, V> map; 1235 try { 1236 map = makePopulatedMap(); 1237 } catch (UnsupportedOperationException e) { 1238 return; 1239 } 1240 1241 Set<K> keys = map.keySet(); 1242 K key = keys.iterator().next(); 1243 if (supportsRemove) { 1244 int initialSize = map.size(); 1245 keys.remove(key); 1246 assertEquals(initialSize - 1, map.size()); 1247 assertFalse(map.containsKey(key)); 1248 } else { 1249 try { 1250 keys.remove(key); 1251 fail("Expected UnsupportedOperationException."); 1252 } catch (UnsupportedOperationException expected) { 1253 } 1254 } 1255 assertInvariants(map); 1256 } 1257 1258 public void testKeySetRemoveAll() { 1259 Map<K, V> map; 1260 try { 1261 map = makePopulatedMap(); 1262 } catch (UnsupportedOperationException e) { 1263 return; 1264 } 1265 1266 Set<K> keys = map.keySet(); 1267 K key = keys.iterator().next(); 1268 if (supportsRemove) { 1269 int initialSize = map.size(); 1270 assertTrue(keys.removeAll(Collections.singleton(key))); 1271 assertEquals(initialSize - 1, map.size()); 1272 assertFalse(map.containsKey(key)); 1273 } else { 1274 try { 1275 keys.removeAll(Collections.singleton(key)); 1276 fail("Expected UnsupportedOperationException."); 1277 } catch (UnsupportedOperationException expected) { 1278 } 1279 } 1280 assertInvariants(map); 1281 } 1282 1283 public void testKeySetRetainAll() { 1284 Map<K, V> map; 1285 try { 1286 map = makePopulatedMap(); 1287 } catch (UnsupportedOperationException e) { 1288 return; 1289 } 1290 1291 Set<K> keys = map.keySet(); 1292 K key = keys.iterator().next(); 1293 if (supportsRemove) { 1294 keys.retainAll(Collections.singleton(key)); 1295 assertEquals(1, map.size()); 1296 assertTrue(map.containsKey(key)); 1297 } else { 1298 try { 1299 keys.retainAll(Collections.singleton(key)); 1300 fail("Expected UnsupportedOperationException."); 1301 } catch (UnsupportedOperationException expected) { 1302 } 1303 } 1304 assertInvariants(map); 1305 } 1306 1307 public void testKeySetClear() { 1308 Map<K, V> map; 1309 try { 1310 map = makeEitherMap(); 1311 } catch (UnsupportedOperationException e) { 1312 return; 1313 } 1314 1315 Set<K> keySet = map.keySet(); 1316 if (supportsClear) { 1317 keySet.clear(); 1318 assertTrue(keySet.isEmpty()); 1319 } else { 1320 try { 1321 keySet.clear(); 1322 fail("Expected UnsupportedOperationException."); 1323 } catch (UnsupportedOperationException expected) { 1324 } 1325 } 1326 assertInvariants(map); 1327 } 1328 1329 public void testKeySetRemoveAllNullFromEmpty() { 1330 Map<K, V> map; 1331 try { 1332 map = makeEmptyMap(); 1333 } catch (UnsupportedOperationException e) { 1334 return; 1335 } 1336 1337 Set<K> keySet = map.keySet(); 1338 if (supportsRemove) { 1339 try { 1340 keySet.removeAll(null); 1341 fail("Expected NullPointerException."); 1342 } catch (NullPointerException expected) { 1343 } 1344 } else { 1345 try { 1346 keySet.removeAll(null); 1347 fail("Expected UnsupportedOperationException or NullPointerException."); 1348 } catch (UnsupportedOperationException | NullPointerException e) { 1349 // Expected. 1350 } 1351 } 1352 assertInvariants(map); 1353 } 1354 1355 public void testKeySetRetainAllNullFromEmpty() { 1356 Map<K, V> map; 1357 try { 1358 map = makeEmptyMap(); 1359 } catch (UnsupportedOperationException e) { 1360 return; 1361 } 1362 1363 Set<K> keySet = map.keySet(); 1364 if (supportsRemove) { 1365 try { 1366 keySet.retainAll(null); 1367 // Returning successfully is not ideal, but tolerated. 1368 } catch (NullPointerException expected) { 1369 } 1370 } else { 1371 try { 1372 keySet.retainAll(null); 1373 // We have to tolerate a successful return (Sun bug 4802647) 1374 } catch (UnsupportedOperationException | NullPointerException e) { 1375 // Expected. 1376 } 1377 } 1378 assertInvariants(map); 1379 } 1380 1381 public void testValues() { 1382 Map<K, V> map; 1383 Collection<V> valueCollection; 1384 try { 1385 map = makePopulatedMap(); 1386 } catch (UnsupportedOperationException e) { 1387 return; 1388 } 1389 assertInvariants(map); 1390 1391 valueCollection = map.values(); 1392 V unmappedValue; 1393 try { 1394 unmappedValue = getValueNotInPopulatedMap(); 1395 } catch (UnsupportedOperationException e) { 1396 return; 1397 } 1398 for (V value : valueCollection) { 1399 assertFalse(unmappedValue.equals(value)); 1400 } 1401 } 1402 1403 public void testValuesIteratorRemove() { 1404 Map<K, V> map; 1405 try { 1406 map = makePopulatedMap(); 1407 } catch (UnsupportedOperationException e) { 1408 return; 1409 } 1410 1411 Collection<V> valueCollection = map.values(); 1412 Iterator<V> iterator = valueCollection.iterator(); 1413 if (supportsIteratorRemove) { 1414 int initialSize = map.size(); 1415 iterator.next(); 1416 iterator.remove(); 1417 assertEquals(initialSize - 1, map.size()); 1418 // (We can't assert that the values collection no longer contains the 1419 // removed value, because the underlying map can have multiple mappings 1420 // to the same value.) 1421 assertInvariants(map); 1422 try { 1423 iterator.remove(); 1424 fail("Expected IllegalStateException."); 1425 } catch (IllegalStateException expected) { 1426 } 1427 } else { 1428 try { 1429 iterator.next(); 1430 iterator.remove(); 1431 fail("Expected UnsupportedOperationException."); 1432 } catch (UnsupportedOperationException expected) { 1433 } 1434 } 1435 assertInvariants(map); 1436 } 1437 1438 public void testValuesRemove() { 1439 Map<K, V> map; 1440 try { 1441 map = makePopulatedMap(); 1442 } catch (UnsupportedOperationException e) { 1443 return; 1444 } 1445 1446 Collection<V> valueCollection = map.values(); 1447 if (supportsRemove) { 1448 int initialSize = map.size(); 1449 valueCollection.remove(valueCollection.iterator().next()); 1450 assertEquals(initialSize - 1, map.size()); 1451 // (We can't assert that the values collection no longer contains the 1452 // removed value, because the underlying map can have multiple mappings 1453 // to the same value.) 1454 } else { 1455 try { 1456 valueCollection.remove(valueCollection.iterator().next()); 1457 fail("Expected UnsupportedOperationException."); 1458 } catch (UnsupportedOperationException expected) { 1459 } 1460 } 1461 assertInvariants(map); 1462 } 1463 1464 public void testValuesRemoveMissing() { 1465 Map<K, V> map; 1466 V valueToRemove; 1467 try { 1468 map = makeEitherMap(); 1469 valueToRemove = getValueNotInPopulatedMap(); 1470 } catch (UnsupportedOperationException e) { 1471 return; 1472 } 1473 1474 Collection<V> valueCollection = map.values(); 1475 int initialSize = map.size(); 1476 if (supportsRemove) { 1477 assertFalse(valueCollection.remove(valueToRemove)); 1478 } else { 1479 try { 1480 assertFalse(valueCollection.remove(valueToRemove)); 1481 } catch (UnsupportedOperationException e) { 1482 // Tolerated. 1483 } 1484 } 1485 assertEquals(initialSize, map.size()); 1486 assertInvariants(map); 1487 } 1488 1489 public void testValuesRemoveAll() { 1490 Map<K, V> map; 1491 try { 1492 map = makePopulatedMap(); 1493 } catch (UnsupportedOperationException e) { 1494 return; 1495 } 1496 1497 Collection<V> valueCollection = map.values(); 1498 Set<V> valuesToRemove = singleton(valueCollection.iterator().next()); 1499 if (supportsRemove) { 1500 valueCollection.removeAll(valuesToRemove); 1501 for (V value : valuesToRemove) { 1502 assertFalse(valueCollection.contains(value)); 1503 } 1504 for (V value : valueCollection) { 1505 assertFalse(valuesToRemove.contains(value)); 1506 } 1507 } else { 1508 try { 1509 valueCollection.removeAll(valuesToRemove); 1510 fail("Expected UnsupportedOperationException."); 1511 } catch (UnsupportedOperationException expected) { 1512 } 1513 } 1514 assertInvariants(map); 1515 } 1516 1517 public void testValuesRemoveAllNullFromEmpty() { 1518 Map<K, V> map; 1519 try { 1520 map = makeEmptyMap(); 1521 } catch (UnsupportedOperationException e) { 1522 return; 1523 } 1524 1525 Collection<V> values = map.values(); 1526 if (supportsRemove) { 1527 try { 1528 values.removeAll(null); 1529 // Returning successfully is not ideal, but tolerated. 1530 } catch (NullPointerException expected) { 1531 } 1532 } else { 1533 try { 1534 values.removeAll(null); 1535 // We have to tolerate a successful return (Sun bug 4802647) 1536 } catch (UnsupportedOperationException | NullPointerException e) { 1537 // Expected. 1538 } 1539 } 1540 assertInvariants(map); 1541 } 1542 1543 public void testValuesRetainAll() { 1544 Map<K, V> map; 1545 try { 1546 map = makePopulatedMap(); 1547 } catch (UnsupportedOperationException e) { 1548 return; 1549 } 1550 1551 Collection<V> valueCollection = map.values(); 1552 Set<V> valuesToRetain = singleton(valueCollection.iterator().next()); 1553 if (supportsRemove) { 1554 valueCollection.retainAll(valuesToRetain); 1555 for (V value : valuesToRetain) { 1556 assertTrue(valueCollection.contains(value)); 1557 } 1558 for (V value : valueCollection) { 1559 assertTrue(valuesToRetain.contains(value)); 1560 } 1561 } else { 1562 try { 1563 valueCollection.retainAll(valuesToRetain); 1564 fail("Expected UnsupportedOperationException."); 1565 } catch (UnsupportedOperationException expected) { 1566 } 1567 } 1568 assertInvariants(map); 1569 } 1570 1571 public void testValuesRetainAllNullFromEmpty() { 1572 Map<K, V> map; 1573 try { 1574 map = makeEmptyMap(); 1575 } catch (UnsupportedOperationException e) { 1576 return; 1577 } 1578 1579 Collection<V> values = map.values(); 1580 if (supportsRemove) { 1581 try { 1582 values.retainAll(null); 1583 // Returning successfully is not ideal, but tolerated. 1584 } catch (NullPointerException expected) { 1585 } 1586 } else { 1587 try { 1588 values.retainAll(null); 1589 // We have to tolerate a successful return (Sun bug 4802647) 1590 } catch (UnsupportedOperationException | NullPointerException e) { 1591 // Expected. 1592 } 1593 } 1594 assertInvariants(map); 1595 } 1596 1597 public void testValuesClear() { 1598 Map<K, V> map; 1599 try { 1600 map = makePopulatedMap(); 1601 } catch (UnsupportedOperationException e) { 1602 return; 1603 } 1604 1605 Collection<V> valueCollection = map.values(); 1606 if (supportsClear) { 1607 valueCollection.clear(); 1608 assertTrue(valueCollection.isEmpty()); 1609 } else { 1610 try { 1611 valueCollection.clear(); 1612 fail("Expected UnsupportedOperationException."); 1613 } catch (UnsupportedOperationException expected) { 1614 } 1615 } 1616 assertInvariants(map); 1617 } 1618 1619 static <K, V> Entry<K, V> mapEntry(K key, V value) { 1620 return Collections.singletonMap(key, value).entrySet().iterator().next(); 1621 } 1622}