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

Class Method, % Line, %
UnmodifiableCollectionTests 0% (0/10) 0% (0/164)
UnmodifiableCollectionTests$1 0% (0/3) 0% (0/3)
Total 0% (0/13) 0% (0/167)


1 /* 2  * Copyright (C) 2007 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.google; 18  19 import static junit.framework.TestCase.assertEquals; 20 import static junit.framework.TestCase.assertTrue; 21 import static junit.framework.TestCase.fail; 22  23 import com.google.common.annotations.GwtCompatible; 24 import com.google.common.collect.ArrayListMultimap; 25 import com.google.common.collect.Iterators; 26 import com.google.common.collect.LinkedHashMultiset; 27 import com.google.common.collect.Lists; 28 import com.google.common.collect.Maps; 29 import com.google.common.collect.Multimap; 30 import com.google.common.collect.Multiset; 31 import java.util.ArrayList; 32 import java.util.Collection; 33 import java.util.Collections; 34 import java.util.Iterator; 35 import java.util.List; 36 import java.util.Map.Entry; 37 import java.util.Set; 38  39 /** 40  * A series of tests that support asserting that collections cannot be modified, either through 41  * direct or indirect means. 42  * 43  * @author Robert Konigsberg 44  */ 45 @GwtCompatible 46 public class UnmodifiableCollectionTests { 47  48  public static void assertMapEntryIsUnmodifiable(Entry<?, ?> entry) { 49  try { 50  entry.setValue(null); 51  fail("setValue on unmodifiable Map.Entry succeeded"); 52  } catch (UnsupportedOperationException expected) { 53  } 54  } 55  56  /** 57  * Verifies that an Iterator is unmodifiable. 58  * 59  * <p>This test only works with iterators that iterate over a finite set. 60  */ 61  public static void assertIteratorIsUnmodifiable(Iterator<?> iterator) { 62  while (iterator.hasNext()) { 63  iterator.next(); 64  try { 65  iterator.remove(); 66  fail("Remove on unmodifiable iterator succeeded"); 67  } catch (UnsupportedOperationException expected) { 68  } 69  } 70  } 71  72  /** 73  * Asserts that two iterators contain elements in tandem. 74  * 75  * <p>This test only works with iterators that iterate over a finite set. 76  */ 77  public static void assertIteratorsInOrder( 78  Iterator<?> expectedIterator, Iterator<?> actualIterator) { 79  int i = 0; 80  while (expectedIterator.hasNext()) { 81  Object expected = expectedIterator.next(); 82  83  assertTrue( 84  "index " + i + " expected <" + expected + "., actual is exhausted", 85  actualIterator.hasNext()); 86  87  Object actual = actualIterator.next(); 88  assertEquals("index " + i, expected, actual); 89  i++; 90  } 91  if (actualIterator.hasNext()) { 92  fail("index " + i + ", expected is exhausted, actual <" + actualIterator.next() + ">"); 93  } 94  } 95  96  /** 97  * Verifies that a collection is immutable. 98  * 99  * <p>A collection is considered immutable if: 100  * 101  * <ol> 102  * <li>All its mutation methods result in UnsupportedOperationException, and do not change the 103  * underlying contents. 104  * <li>All methods that return objects that can indirectly mutate the collection throw 105  * UnsupportedOperationException when those mutators are called. 106  * </ol> 107  * 108  * @param collection the presumed-immutable collection 109  * @param sampleElement an element of the same type as that contained by {@code collection}. 110  * {@code collection} may or may not have {@code sampleElement} as a member. 111  */ 112  public static <E> void assertCollectionIsUnmodifiable(Collection<E> collection, E sampleElement) { 113  Collection<E> siblingCollection = new ArrayList<>(); 114  siblingCollection.add(sampleElement); 115  116  Collection<E> copy = new ArrayList<>(); 117  // Avoid copy.addAll(collection), which runs afoul of an Android bug in older versions: 118  // http://b.android.com/72073 http://r.android.com/98929 119  Iterators.addAll(copy, collection.iterator()); 120  121  try { 122  collection.add(sampleElement); 123  fail("add succeeded on unmodifiable collection"); 124  } catch (UnsupportedOperationException expected) { 125  } 126  127  assertCollectionsAreEquivalent(copy, collection); 128  129  try { 130  collection.addAll(siblingCollection); 131  fail("addAll succeeded on unmodifiable collection"); 132  } catch (UnsupportedOperationException expected) { 133  } 134  assertCollectionsAreEquivalent(copy, collection); 135  136  try { 137  collection.clear(); 138  fail("clear succeeded on unmodifiable collection"); 139  } catch (UnsupportedOperationException expected) { 140  } 141  assertCollectionsAreEquivalent(copy, collection); 142  143  assertIteratorIsUnmodifiable(collection.iterator()); 144  assertCollectionsAreEquivalent(copy, collection); 145  146  try { 147  collection.remove(sampleElement); 148  fail("remove succeeded on unmodifiable collection"); 149  } catch (UnsupportedOperationException expected) { 150  } 151  assertCollectionsAreEquivalent(copy, collection); 152  153  try { 154  collection.removeAll(siblingCollection); 155  fail("removeAll succeeded on unmodifiable collection"); 156  } catch (UnsupportedOperationException expected) { 157  } 158  assertCollectionsAreEquivalent(copy, collection); 159  160  try { 161  collection.retainAll(siblingCollection); 162  fail("retainAll succeeded on unmodifiable collection"); 163  } catch (UnsupportedOperationException expected) { 164  } 165  assertCollectionsAreEquivalent(copy, collection); 166  } 167  168  /** 169  * Verifies that a set is immutable. 170  * 171  * <p>A set is considered immutable if: 172  * 173  * <ol> 174  * <li>All its mutation methods result in UnsupportedOperationException, and do not change the 175  * underlying contents. 176  * <li>All methods that return objects that can indirectly mutate the set throw 177  * UnsupportedOperationException when those mutators are called. 178  * </ol> 179  * 180  * @param set the presumed-immutable set 181  * @param sampleElement an element of the same type as that contained by {@code set}. {@code set} 182  * may or may not have {@code sampleElement} as a member. 183  */ 184  public static <E> void assertSetIsUnmodifiable(Set<E> set, E sampleElement) { 185  assertCollectionIsUnmodifiable(set, sampleElement); 186  } 187  188  /** 189  * Verifies that a multiset is immutable. 190  * 191  * <p>A multiset is considered immutable if: 192  * 193  * <ol> 194  * <li>All its mutation methods result in UnsupportedOperationException, and do not change the 195  * underlying contents. 196  * <li>All methods that return objects that can indirectly mutate the multiset throw 197  * UnsupportedOperationException when those mutators are called. 198  * </ol> 199  * 200  * @param multiset the presumed-immutable multiset 201  * @param sampleElement an element of the same type as that contained by {@code multiset}. {@code 202  * multiset} may or may not have {@code sampleElement} as a member. 203  */ 204  public static <E> void assertMultisetIsUnmodifiable(Multiset<E> multiset, final E sampleElement) { 205  Multiset<E> copy = LinkedHashMultiset.create(multiset); 206  assertCollectionsAreEquivalent(multiset, copy); 207  208  // Multiset is a collection, so we can use all those tests. 209  assertCollectionIsUnmodifiable(multiset, sampleElement); 210  211  assertCollectionsAreEquivalent(multiset, copy); 212  213  try { 214  multiset.add(sampleElement, 2); 215  fail("add(Object, int) succeeded on unmodifiable collection"); 216  } catch (UnsupportedOperationException expected) { 217  } 218  assertCollectionsAreEquivalent(multiset, copy); 219  220  try { 221  multiset.remove(sampleElement, 2); 222  fail("remove(Object, int) succeeded on unmodifiable collection"); 223  } catch (UnsupportedOperationException expected) { 224  } 225  assertCollectionsAreEquivalent(multiset, copy); 226  227  assertCollectionsAreEquivalent(multiset, copy); 228  229  assertSetIsUnmodifiable(multiset.elementSet(), sampleElement); 230  assertCollectionsAreEquivalent(multiset, copy); 231  232  assertSetIsUnmodifiable( 233  multiset.entrySet(), 234  new Multiset.Entry<E>() { 235  @Override 236  public int getCount() { 237  return 1; 238  } 239  240  @Override 241  public E getElement() { 242  return sampleElement; 243  } 244  }); 245  assertCollectionsAreEquivalent(multiset, copy); 246  } 247  248  /** 249  * Verifies that a multimap is immutable. 250  * 251  * <p>A multimap is considered immutable if: 252  * 253  * <ol> 254  * <li>All its mutation methods result in UnsupportedOperationException, and do not change the 255  * underlying contents. 256  * <li>All methods that return objects that can indirectly mutate the multimap throw 257  * UnsupportedOperationException when those mutators 258  * </ol> 259  * 260  * @param multimap the presumed-immutable multimap 261  * @param sampleKey a key of the same type as that contained by {@code multimap}. {@code multimap} 262  * may or may not have {@code sampleKey} as a key. 263  * @param sampleValue a key of the same type as that contained by {@code multimap}. {@code 264  * multimap} may or may not have {@code sampleValue} as a key. 265  */ 266  public static <K, V> void assertMultimapIsUnmodifiable( 267  Multimap<K, V> multimap, final K sampleKey, final V sampleValue) { 268  List<Entry<K, V>> originalEntries = 269  Collections.unmodifiableList(Lists.newArrayList(multimap.entries())); 270  271  assertMultimapRemainsUnmodified(multimap, originalEntries); 272  273  Collection<V> sampleValueAsCollection = Collections.singleton(sampleValue); 274  275  // Test #clear() 276  try { 277  multimap.clear(); 278  fail("clear succeeded on unmodifiable multimap"); 279  } catch (UnsupportedOperationException expected) { 280  } 281  282  assertMultimapRemainsUnmodified(multimap, originalEntries); 283  284  // Test asMap().entrySet() 285  assertSetIsUnmodifiable( 286  multimap.asMap().entrySet(), Maps.immutableEntry(sampleKey, sampleValueAsCollection)); 287  288  // Test #values() 289  290  assertMultimapRemainsUnmodified(multimap, originalEntries); 291  if (!multimap.isEmpty()) { 292  Collection<V> values = multimap.asMap().entrySet().iterator().next().getValue(); 293  294  assertCollectionIsUnmodifiable(values, sampleValue); 295  } 296  297  // Test #entries() 298  assertCollectionIsUnmodifiable(multimap.entries(), Maps.immutableEntry(sampleKey, sampleValue)); 299  assertMultimapRemainsUnmodified(multimap, originalEntries); 300  301  // Iterate over every element in the entry set 302  for (Entry<K, V> entry : multimap.entries()) { 303  assertMapEntryIsUnmodifiable(entry); 304  } 305  assertMultimapRemainsUnmodified(multimap, originalEntries); 306  307  // Test #keys() 308  assertMultisetIsUnmodifiable(multimap.keys(), sampleKey); 309  assertMultimapRemainsUnmodified(multimap, originalEntries); 310  311  // Test #keySet() 312  assertSetIsUnmodifiable(multimap.keySet(), sampleKey); 313  assertMultimapRemainsUnmodified(multimap, originalEntries); 314  315  // Test #get() 316  if (!multimap.isEmpty()) { 317  K key = multimap.keySet().iterator().next(); 318  assertCollectionIsUnmodifiable(multimap.get(key), sampleValue); 319  assertMultimapRemainsUnmodified(multimap, originalEntries); 320  } 321  322  // Test #put() 323  try { 324  multimap.put(sampleKey, sampleValue); 325  fail("put succeeded on unmodifiable multimap"); 326  } catch (UnsupportedOperationException expected) { 327  } 328  assertMultimapRemainsUnmodified(multimap, originalEntries); 329  330  // Test #putAll(K, Collection<V>) 331  try { 332  multimap.putAll(sampleKey, sampleValueAsCollection); 333  fail("putAll(K, Iterable) succeeded on unmodifiable multimap"); 334  } catch (UnsupportedOperationException expected) { 335  } 336  assertMultimapRemainsUnmodified(multimap, originalEntries); 337  338  // Test #putAll(Multimap<K, V>) 339  Multimap<K, V> multimap2 = ArrayListMultimap.create(); 340  multimap2.put(sampleKey, sampleValue); 341  try { 342  multimap.putAll(multimap2); 343  fail("putAll(Multimap<K, V>) succeeded on unmodifiable multimap"); 344  } catch (UnsupportedOperationException expected) { 345  } 346  assertMultimapRemainsUnmodified(multimap, originalEntries); 347  348  // Test #remove() 349  try { 350  multimap.remove(sampleKey, sampleValue); 351  fail("remove succeeded on unmodifiable multimap"); 352  } catch (UnsupportedOperationException expected) { 353  } 354  assertMultimapRemainsUnmodified(multimap, originalEntries); 355  356  // Test #removeAll() 357  try { 358  multimap.removeAll(sampleKey); 359  fail("removeAll succeeded on unmodifiable multimap"); 360  } catch (UnsupportedOperationException expected) { 361  } 362  assertMultimapRemainsUnmodified(multimap, originalEntries); 363  364  // Test #replaceValues() 365  try { 366  multimap.replaceValues(sampleKey, sampleValueAsCollection); 367  fail("replaceValues succeeded on unmodifiable multimap"); 368  } catch (UnsupportedOperationException expected) { 369  } 370  assertMultimapRemainsUnmodified(multimap, originalEntries); 371  372  // Test #asMap() 373  try { 374  multimap.asMap().remove(sampleKey); 375  fail("asMap().remove() succeeded on unmodifiable multimap"); 376  } catch (UnsupportedOperationException expected) { 377  } 378  assertMultimapRemainsUnmodified(multimap, originalEntries); 379  380  if (!multimap.isEmpty()) { 381  K presentKey = multimap.keySet().iterator().next(); 382  try { 383  multimap.asMap().get(presentKey).remove(sampleValue); 384  fail("asMap().get().remove() succeeded on unmodifiable multimap"); 385  } catch (UnsupportedOperationException expected) { 386  } 387  assertMultimapRemainsUnmodified(multimap, originalEntries); 388  389  try { 390  multimap.asMap().values().iterator().next().remove(sampleValue); 391  fail("asMap().values().iterator().next().remove() succeeded on unmodifiable multimap"); 392  } catch (UnsupportedOperationException expected) { 393  } 394  395  try { 396  ((Collection<?>) multimap.asMap().values().toArray()[0]).clear(); 397  fail("asMap().values().toArray()[0].clear() succeeded on unmodifiable multimap"); 398  } catch (UnsupportedOperationException expected) { 399  } 400  } 401  402  assertCollectionIsUnmodifiable(multimap.values(), sampleValue); 403  assertMultimapRemainsUnmodified(multimap, originalEntries); 404  } 405  406  private static <E> void assertCollectionsAreEquivalent( 407  Collection<E> expected, Collection<E> actual) { 408  assertIteratorsInOrder(expected.iterator(), actual.iterator()); 409  } 410  411  private static <K, V> void assertMultimapRemainsUnmodified( 412  Multimap<K, V> expected, List<Entry<K, V>> actual) { 413  assertIteratorsInOrder(expected.entries().iterator(), actual.iterator()); 414  } 415 }