Coverage Summary for Class: MapInterfaceTest (com.google.common.collect.testing)

Class Method, % Line, %
MapInterfaceTest 98.4% (63/64) 67.4% (664/985)
MapInterfaceTest$IncompatibleKeyType 50% (1/2) 50% (1/2)
Total 97% (64/66) 67.4% (665/987)


1 /* 2  * Copyright (C) 2008 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); 5  * you may not use this file except in compliance with the License. 6  * You may obtain a copy of the License at 7  * 8  * http://www.apache.org/licenses/LICENSE-2.0 9  * 10  * Unless required by applicable law or agreed to in writing, software 11  * distributed under the License is distributed on an "AS IS" BASIS, 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13  * See the License for the specific language governing permissions and 14  * limitations under the License. 15  */ 16  17 package com.google.common.collect.testing; 18  19 import static java.util.Collections.singleton; 20  21 import com.google.common.annotations.GwtCompatible; 22 import java.util.Arrays; 23 import java.util.Collection; 24 import java.util.Collections; 25 import java.util.HashSet; 26 import java.util.Iterator; 27 import java.util.Map; 28 import java.util.Map.Entry; 29 import java.util.Set; 30 import junit.framework.TestCase; 31  32 /** 33  * Tests representing the contract of {@link Map}. Concrete subclasses of this base class test 34  * conformance of concrete {@link Map} subclasses to that contract. 35  * 36  * @param <K> the type of keys used by the maps under test 37  * @param <V> the type of mapped values used the maps under test 38  * @author George van den Driessche 39  */ 40 // TODO: Descriptive assertion messages, with hints as to probable fixes. 41 // TODO: Add another constructor parameter indicating whether the class under test is ordered, and 42 // check the order if so. 43 // TODO: Refactor to share code with SetTestBuilder etc. 44 @GwtCompatible 45 public abstract class MapInterfaceTest<K, V> extends TestCase { 46  47  /** A key type that is not assignable to any classes but Object. */ 48  private static final class IncompatibleKeyType { 49  @Override 50  public String toString() { 51  return "IncompatibleKeyType"; 52  } 53  } 54  55  protected final boolean supportsPut; 56  protected final boolean supportsRemove; 57  protected final boolean supportsClear; 58  protected final boolean allowsNullKeys; 59  protected final boolean allowsNullValues; 60  protected final boolean supportsIteratorRemove; 61  62  /** 63  * Creates a new, empty instance of the class under test. 64  * 65  * @return a new, empty map instance. 66  * @throws UnsupportedOperationException if it's not possible to make an empty instance of the 67  * class under test. 68  */ 69  protected abstract Map<K, V> makeEmptyMap() throws UnsupportedOperationException; 70  71  /** 72  * Creates a new, non-empty instance of the class under test. 73  * 74  * @return a new, non-empty map instance. 75  * @throws UnsupportedOperationException if it's not possible to make a non-empty instance of the 76  * class under test. 77  */ 78  protected abstract Map<K, V> makePopulatedMap() throws UnsupportedOperationException; 79  80  /** 81  * Creates a new key that is not expected to be found in {@link #makePopulatedMap()}. 82  * 83  * @return a key. 84  * @throws UnsupportedOperationException if it's not possible to make a key that will not be found 85  * in the map. 86  */ 87  protected abstract K getKeyNotInPopulatedMap() throws UnsupportedOperationException; 88  89  /** 90  * Creates a new value that is not expected to be found in {@link #makePopulatedMap()}. 91  * 92  * @return a value. 93  * @throws UnsupportedOperationException if it's not possible to make a value that will not be 94  * found in the map. 95  */ 96  protected abstract V getValueNotInPopulatedMap() throws UnsupportedOperationException; 97  98  /** 99  * 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 }