PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/test/com/google/common/collect/testing/google/UnmodifiableCollectionTests.java

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