0001: /*
0002: * Copyright 1999-2004 The Apache Software Foundation
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016: package org.apache.commons.collections;
0017:
0018: import java.util.ArrayList;
0019: import java.util.Arrays;
0020: import java.util.Collection;
0021: import java.util.Collections;
0022: import java.util.HashSet;
0023: import java.util.Iterator;
0024: import java.util.List;
0025: import java.util.NoSuchElementException;
0026: import java.util.Set;
0027:
0028: /**
0029: * Tests base {@link java.util.Collection} methods and contracts.
0030: * <p>
0031: * You should create a concrete subclass of this class to test any custom
0032: * {@link Collection} implementation. At minimum, you'll have to
0033: * implement the {@link #makeCollection()} method. You might want to
0034: * override some of the additional protected methods as well:<P>
0035: *
0036: * <B>Element Population Methods</B><P>
0037: *
0038: * Override these if your collection restricts what kind of elements are
0039: * allowed (for instance, if <Code>null</Code> is not permitted):
0040: * <UL>
0041: * <Li>{@link #getFullElements()}
0042: * <Li>{@link #getOtherElements()}
0043: * </UL>
0044: *
0045: * <B>Supported Operation Methods</B><P>
0046: *
0047: * Override these if your collection doesn't support certain operations:
0048: * <UL>
0049: * <LI>{@link #isAddSuppoted()}
0050: * <LI>{@link #isRemoveSupported()}
0051: * <li>{@link #areEqualElementsDistinguishable()}
0052: * </UL>
0053: *
0054: * <B>Fixture Methods</B><P>
0055: *
0056: * Fixtures are used to verify that the the operation results in correct state
0057: * for the collection. Basically, the operation is performed against your
0058: * collection implementation, and an identical operation is performed against a
0059: * <I>confirmed</I> collection implementation. A confirmed collection
0060: * implementation is something like <Code>java.util.ArrayList</Code>, which is
0061: * known to conform exactly to its collection interface's contract. After the
0062: * operation takes place on both your collection implementation and the
0063: * confirmed collection implementation, the two collections are compared to see
0064: * if their state is identical. The comparison is usually much more involved
0065: * than a simple <Code>equals</Code> test. This verification is used to ensure
0066: * proper modifications are made along with ensuring that the collection does
0067: * not change when read-only modifications are made.<P>
0068: *
0069: * The {@link #collection} field holds an instance of your collection
0070: * implementation; the {@link #confirmed} field holds an instance of the
0071: * confirmed collection implementation. The {@link #resetEmpty()} and
0072: * {@link #resetFull()} methods set these fields to empty or full collections,
0073: * so that tests can proceed from a known state.<P>
0074: *
0075: * After a modification operation to both {@link #collection} and
0076: * {@link #confirmed}, the {@link #verify()} method is invoked to compare
0077: * the results. You may want to override {@link #verify()} to perform
0078: * additional verifications. For instance, when testing the collection
0079: * views of a map, {@link TestMap} would override {@link #verify()} to make
0080: * sure the map is changed after the collection view is changed.
0081: *
0082: * If you're extending this class directly, you will have to provide
0083: * implementations for the following:
0084: * <UL>
0085: * <LI>{@link #makeConfirmedCollection()}
0086: * <LI>{@link #makeConfirmedFullCollection()}
0087: * </UL>
0088: *
0089: * Those methods should provide a confirmed collection implementation
0090: * that's compatible with your collection implementation.<P>
0091: *
0092: * If you're extending {@link TestList}, {@link TestSet},
0093: * or {@link TestBag}, you probably don't have to worry about the
0094: * above methods, because those three classes already override the methods
0095: * to provide standard JDK confirmed collections.<P>
0096: *
0097: * <B>Other notes</B><P>
0098: *
0099: * If your {@link Collection} fails one of these tests by design,
0100: * you may still use this base set of cases. Simply override the
0101: * test case (method) your {@link Collection} fails. For instance, the
0102: * {@link #testIteratorFailFast()} method is provided since most collections
0103: * have fail-fast iterators; however, that's not strictly required by the
0104: * collection contract, so you may want to override that method to do
0105: * nothing.<P>
0106: *
0107: * @author Rodney Waldhoff
0108: * @author Paul Jack
0109: * @author <a href="mailto:mas@apache.org">Michael A. Smith</a>
0110: * @version $Id: TestCollection.java,v 1.9.2.1 2004/05/22 12:14:05 scolebourne Exp $
0111: */
0112: public abstract class TestCollection extends TestObject {
0113:
0114: //
0115: // NOTE:
0116: //
0117: // Collection doesn't define any semantics for equals, and recommends you
0118: // use reference-based default behavior of Object.equals. (And a test for
0119: // that already exists in TestObject). Tests for equality of lists, sets
0120: // and bags will have to be written in test subclasses. Thus, there is no
0121: // tests on Collection.equals nor any for Collection.hashCode.
0122: //
0123:
0124: // These fields are used by reset() and verify(), and any test
0125: // method that tests a modification.
0126:
0127: /**
0128: * A collection instance that will be used for testing.
0129: */
0130: protected Collection collection;
0131:
0132: /**
0133: * Confirmed collection. This is an instance of a collection that is
0134: * confirmed to conform exactly to the java.util.Collection contract.
0135: * Modification operations are tested by performing a mod on your
0136: * collection, performing the exact same mod on an equivalent confirmed
0137: * collection, and then calling verify() to make sure your collection
0138: * still matches the confirmed collection.
0139: */
0140: protected Collection confirmed;
0141:
0142: /**
0143: * Resets the {@link #collection} and {@link #confirmed} fields to empty
0144: * collections. Invoke this method before performing a modification
0145: * test.
0146: */
0147: protected void resetEmpty() {
0148: this .collection = makeCollection();
0149: this .confirmed = makeConfirmedCollection();
0150: }
0151:
0152: /**
0153: * Resets the {@link #collection} and {@link #confirmed} fields to full
0154: * collections. Invoke this method before performing a modification
0155: * test.
0156: */
0157: protected void resetFull() {
0158: this .collection = makeFullCollection();
0159: this .confirmed = makeConfirmedFullCollection();
0160: }
0161:
0162: /**
0163: * Specifies whether equal elements in the collection are, in fact,
0164: * distinguishable with information not readily available. That is, if a
0165: * particular value is to be removed from the collection, then there is
0166: * one and only one value that can be removed, even if there are other
0167: * elements which are equal to it.
0168: *
0169: * <P>In most collection cases, elements are not distinguishable (equal is
0170: * equal), thus this method defaults to return false. In some cases,
0171: * however, they are. For example, the collection returned from the map's
0172: * values() collection view are backed by the map, so while there may be
0173: * two values that are equal, their associated keys are not. Since the
0174: * keys are distinguishable, the values are.
0175: *
0176: * <P>This flag is used to skip some verifications for iterator.remove()
0177: * where it is impossible to perform an equivalent modification on the
0178: * confirmed collection because it is not possible to determine which
0179: * value in the confirmed collection to actually remove. Tests that
0180: * override the default (i.e. where equal elements are distinguishable),
0181: * should provide additional tests on iterator.remove() to make sure the
0182: * proper elements are removed when remove() is called on the iterator.
0183: **/
0184: protected boolean areEqualElementsDistinguishable() {
0185: return false;
0186: }
0187:
0188: /**
0189: * Verifies that {@link #collection} and {@link #confirmed} have
0190: * identical state.
0191: */
0192: protected void verify() {
0193: int confirmedSize = confirmed.size();
0194: assertEquals(
0195: "Collection size should match confirmed collection's",
0196: confirmedSize, collection.size());
0197: assertEquals(
0198: "Collection isEmpty() result should match confirmed "
0199: + " collection's", confirmed.isEmpty(),
0200: collection.isEmpty());
0201:
0202: // verify the collections are the same by attempting to match each
0203: // object in the collection and confirmed collection. To account for
0204: // duplicates and differing orders, each confirmed element is copied
0205: // into an array and a flag is maintained for each element to determine
0206: // whether it has been matched once and only once. If all elements in
0207: // the confirmed collection are matched once and only once and there
0208: // aren't any elements left to be matched in the collection,
0209: // verification is a success.
0210:
0211: // copy each collection value into an array
0212: Object[] confirmedValues = new Object[confirmedSize];
0213:
0214: Iterator iter;
0215:
0216: iter = confirmed.iterator();
0217: int pos = 0;
0218: while (iter.hasNext()) {
0219: confirmedValues[pos++] = iter.next();
0220: }
0221:
0222: // allocate an array of boolean flags for tracking values that have
0223: // been matched once and only once.
0224: boolean[] matched = new boolean[confirmedSize];
0225:
0226: // now iterate through the values of the collection and try to match
0227: // the value with one in the confirmed array.
0228: iter = collection.iterator();
0229: while (iter.hasNext()) {
0230: Object o = iter.next();
0231: boolean match = false;
0232: for (int i = 0; i < confirmedSize; i++) {
0233: if (matched[i]) {
0234: // skip values already matched
0235: continue;
0236: }
0237: if (o == confirmedValues[i]
0238: || (o != null && o.equals(confirmedValues[i]))) {
0239: // values matched
0240: matched[i] = true;
0241: match = true;
0242: break;
0243: }
0244: }
0245: // no match found!
0246: if (!match) {
0247: fail("Collection should not contain a value that the "
0248: + "confirmed collection does not have.");
0249: }
0250: }
0251:
0252: // make sure there aren't any unmatched values
0253: for (int i = 0; i < confirmedSize; i++) {
0254: if (!matched[i]) {
0255: // the collection didn't match all the confirmed values
0256: fail("Collection should contain all values that are in the "
0257: + "confirmed collection");
0258: }
0259: }
0260: }
0261:
0262: /**
0263: * Returns a confirmed empty collection.
0264: * For instance, an {@link java.util.ArrayList} for lists or a
0265: * {@link java.util.HashSet} for sets.
0266: *
0267: * @return a confirmed empty collection
0268: */
0269: protected abstract Collection makeConfirmedCollection();
0270:
0271: /**
0272: * Returns a confirmed full collection.
0273: * For instance, an {@link java.util.ArrayList} for lists or a
0274: * {@link java.util.HashSet} for sets. The returned collection
0275: * should contain the elements returned by {@link #getFullElements()}.
0276: *
0277: * @return a confirmed full collection
0278: */
0279: protected abstract Collection makeConfirmedFullCollection();
0280:
0281: /**
0282: * Returns true if the collections produced by
0283: * {@link #makeCollection()} and {@link #makeFullCollection()}
0284: * support the <Code>add</Code> and <Code>addAll</Code>
0285: * operations.<P>
0286: * Default implementation returns true. Override if your collection
0287: * class does not support add or addAll.
0288: */
0289: protected boolean isAddSupported() {
0290: return true;
0291: }
0292:
0293: /**
0294: * Returns true if the collections produced by
0295: * {@link #makeCollection()} and {@link #makeFullCollection()}
0296: * support the <Code>remove</Code>, <Code>removeAll</Code>,
0297: * <Code>retainAll</Code>, <Code>clear</Code> and
0298: * <Code>iterator().remove()</Code> methods.
0299: * Default implementation returns true. Override if your collection
0300: * class does not support removal operations.
0301: */
0302: protected boolean isRemoveSupported() {
0303: return true;
0304: }
0305:
0306: /**
0307: * Returns an array of objects that are contained in a collection
0308: * produced by {@link #makeFullCollection()}. Every element in the
0309: * returned array <I>must</I> be an element in a full collection.<P>
0310: * The default implementation returns a heterogenous array of
0311: * objects with some duplicates and with the null element.
0312: * Override if you require specific testing elements. Note that if you
0313: * override {@link #makeFullCollection()}, you <I>must</I> override
0314: * this method to reflect the contents of a full collection.
0315: */
0316: protected Object[] getFullElements() {
0317: ArrayList list = new ArrayList();
0318:
0319: list.addAll(Arrays.asList(getFullNonNullElements()));
0320: list.add(4, null);
0321: return list.toArray();
0322: }
0323:
0324: /**
0325: * Returns an array of elements that are <I>not</I> contained in a
0326: * full collection. Every element in the returned array must
0327: * not exist in a collection returned by {@link #makeFullCollection()}.
0328: * The default implementation returns a heterogenous array of elements
0329: * without null. Note that some of the tests add these elements
0330: * to an empty or full collection, so if your collection restricts
0331: * certain kinds of elements, you should override this method.
0332: */
0333: protected Object[] getOtherElements() {
0334: return getOtherNonNullElements();
0335: }
0336:
0337: /**
0338: * Return a new, empty {@link Collection} to be used for testing.
0339: */
0340: protected abstract Collection makeCollection();
0341:
0342: /**
0343: * Returns a full collection to be used for testing. The collection
0344: * returned by this method should contain every element returned by
0345: * {@link #getFullElements()}. The default implementation, in fact,
0346: * simply invokes <Code>addAll</Code> on an empty collection with
0347: * the results of {@link #getFullElements()}. Override this default
0348: * if your collection doesn't support addAll.
0349: */
0350: protected Collection makeFullCollection() {
0351: Collection c = makeCollection();
0352: c.addAll(Arrays.asList(getFullElements()));
0353: return c;
0354: }
0355:
0356: /**
0357: * Returns an empty collection for Object tests.
0358: */
0359: public Object makeObject() {
0360: return makeCollection();
0361: }
0362:
0363: /**
0364: * Tests {@link Collection#add(Object)}.
0365: */
0366: public void testCollectionAdd() {
0367: if (!isAddSupported())
0368: return;
0369:
0370: Object[] elements = getFullElements();
0371: for (int i = 0; i < elements.length; i++) {
0372: resetEmpty();
0373: boolean r = collection.add(elements[i]);
0374: confirmed.add(elements[i]);
0375: verify();
0376: assertTrue("Empty collection changed after add", r);
0377: assertTrue("Collection size is 1 after first add",
0378: collection.size() == 1);
0379: }
0380:
0381: resetEmpty();
0382: int size = 0;
0383: for (int i = 0; i < elements.length; i++) {
0384: boolean r = collection.add(elements[i]);
0385: confirmed.add(elements[i]);
0386: verify();
0387: if (r)
0388: size++;
0389: assertEquals("Collection size should grow after add", size,
0390: collection.size());
0391: assertTrue("Collection should contain added element",
0392: collection.contains(elements[i]));
0393: }
0394: }
0395:
0396: /**
0397: * Tests {@link Collection#addAll(Collection)}.
0398: */
0399: public void testCollectionAddAll() {
0400: if (!isAddSupported())
0401: return;
0402:
0403: resetEmpty();
0404: Object[] elements = getFullElements();
0405: boolean r = collection.addAll(Arrays.asList(elements));
0406: confirmed.addAll(Arrays.asList(elements));
0407: verify();
0408: assertTrue("Empty collection should change after addAll", r);
0409: for (int i = 0; i < elements.length; i++) {
0410: assertTrue("Collection should contain added element",
0411: collection.contains(elements[i]));
0412: }
0413:
0414: resetFull();
0415: int size = collection.size();
0416: elements = getOtherElements();
0417: r = collection.addAll(Arrays.asList(elements));
0418: confirmed.addAll(Arrays.asList(elements));
0419: verify();
0420: assertTrue("Full collection should change after addAll", r);
0421: for (int i = 0; i < elements.length; i++) {
0422: assertTrue("Full collection should contain added element",
0423: collection.contains(elements[i]));
0424: }
0425: assertEquals("Size should increase after addAll", size
0426: + elements.length, collection.size());
0427:
0428: resetFull();
0429: size = collection.size();
0430: r = collection.addAll(Arrays.asList(getFullElements()));
0431: confirmed.addAll(Arrays.asList(getFullElements()));
0432: verify();
0433: if (r) {
0434: assertTrue("Size should increase if addAll returns true",
0435: size < collection.size());
0436: } else {
0437: assertEquals(
0438: "Size should not change if addAll returns false",
0439: size, collection.size());
0440: }
0441: }
0442:
0443: /**
0444: * If {@link #isAddSupported()} returns false, tests that add operations
0445: * raise <Code>UnsupportedOperationException.
0446: */
0447: public void testUnsupportedAdd() {
0448: if (isAddSupported())
0449: return;
0450:
0451: resetEmpty();
0452: try {
0453: collection.add(new Object());
0454: fail("Emtpy collection should not support add.");
0455: } catch (UnsupportedOperationException e) {
0456: // expected
0457: }
0458: // make sure things didn't change even if the expected exception was
0459: // thrown.
0460: verify();
0461:
0462: try {
0463: collection.addAll(Arrays.asList(getFullElements()));
0464: fail("Emtpy collection should not support addAll.");
0465: } catch (UnsupportedOperationException e) {
0466: // expected
0467: }
0468: // make sure things didn't change even if the expected exception was
0469: // thrown.
0470: verify();
0471:
0472: resetFull();
0473: try {
0474: collection.add(new Object());
0475: fail("Full collection should not support add.");
0476: } catch (UnsupportedOperationException e) {
0477: // expected
0478: }
0479: // make sure things didn't change even if the expected exception was
0480: // thrown.
0481: verify();
0482:
0483: try {
0484: collection.addAll(Arrays.asList(getOtherElements()));
0485: fail("Full collection should not support addAll.");
0486: } catch (UnsupportedOperationException e) {
0487: // expected
0488: }
0489: // make sure things didn't change even if the expected exception was
0490: // thrown.
0491: verify();
0492: }
0493:
0494: /**
0495: * Test {@link Collection#clear()}.
0496: */
0497: public void testCollectionClear() {
0498: if (!isRemoveSupported())
0499: return;
0500:
0501: resetEmpty();
0502: collection.clear(); // just to make sure it doesn't raise anything
0503: verify();
0504:
0505: resetFull();
0506: collection.clear();
0507: confirmed.clear();
0508: verify();
0509: }
0510:
0511: /**
0512: * Tests {@link Collection#contains(Object)}.
0513: */
0514: public void testCollectionContains() {
0515: Object[] elements;
0516:
0517: resetEmpty();
0518: elements = getFullElements();
0519: for (int i = 0; i < elements.length; i++) {
0520: assertTrue("Empty collection shouldn'y contain element",
0521: !collection.contains(elements[i]));
0522: }
0523: // make sure calls to "contains" don't change anything
0524: verify();
0525:
0526: elements = getOtherElements();
0527: for (int i = 0; i < elements.length; i++) {
0528: assertTrue("Empty collection shouldn'y contain element",
0529: !collection.contains(elements[i]));
0530: }
0531: // make sure calls to "contains" don't change anything
0532: verify();
0533:
0534: resetFull();
0535: elements = getFullElements();
0536: for (int i = 0; i < elements.length; i++) {
0537: assertTrue("Full collection should contain element.",
0538: collection.contains(elements[i]));
0539: }
0540: // make sure calls to "contains" don't change anything
0541: verify();
0542:
0543: resetFull();
0544: elements = getOtherElements();
0545: for (int i = 0; i < elements.length; i++) {
0546: assertTrue("Full collection shouldn't contain element",
0547: !collection.contains(elements[i]));
0548: }
0549: }
0550:
0551: /**
0552: * Tests {@link Collection#containsAll(Collection)}.
0553: */
0554: public void testCollectionContainsAll() {
0555: resetEmpty();
0556: Collection col = new HashSet();
0557: assertTrue(
0558: "Every Collection should contain all elements of an "
0559: + "empty Collection.", collection
0560: .containsAll(col));
0561: col.addAll(Arrays.asList(getOtherElements()));
0562: assertTrue(
0563: "Empty Collection shouldn't contain all elements of "
0564: + "a non-empty Collection.", !collection
0565: .containsAll(col));
0566: // make sure calls to "containsAll" don't change anything
0567: verify();
0568:
0569: resetFull();
0570: assertTrue("Full collection shouldn't contain other elements",
0571: !collection.containsAll(col));
0572:
0573: col.clear();
0574: col.addAll(Arrays.asList(getFullElements()));
0575: assertTrue("Full collection should containAll full elements",
0576: collection.containsAll(col));
0577: // make sure calls to "containsAll" don't change anything
0578: verify();
0579:
0580: assertTrue("Full collection should containAll itself",
0581: collection.containsAll(collection));
0582:
0583: // make sure calls to "containsAll" don't change anything
0584: verify();
0585:
0586: col = new ArrayList();
0587: col.addAll(Arrays.asList(getFullElements()));
0588: col.addAll(Arrays.asList(getFullElements()));
0589: assertTrue("Full collection should containAll duplicate full "
0590: + "elements", collection.containsAll(col));
0591:
0592: // make sure calls to "containsAll" don't change anything
0593: verify();
0594: }
0595:
0596: /**
0597: * Tests {@link Collection#isEmpty()}.
0598: */
0599: public void testCollectionIsEmpty() {
0600: resetEmpty();
0601: assertEquals("New Collection should be empty.", true,
0602: collection.isEmpty());
0603: // make sure calls to "isEmpty() don't change anything
0604: verify();
0605:
0606: resetFull();
0607: assertEquals("Full collection shouldn't be empty", false,
0608: collection.isEmpty());
0609: // make sure calls to "isEmpty() don't change anything
0610: verify();
0611: }
0612:
0613: /**
0614: * Tests the read-only functionality of {@link Collection#iterator()}.
0615: */
0616: public void testCollectionIterator() {
0617: resetEmpty();
0618: Iterator it1 = collection.iterator();
0619: assertEquals(
0620: "Iterator for empty Collection shouldn't have next.",
0621: false, it1.hasNext());
0622: try {
0623: it1.next();
0624: fail("Iterator at end of Collection should throw "
0625: + "NoSuchElementException when next is called.");
0626: } catch (NoSuchElementException e) {
0627: // expected
0628: }
0629: // make sure nothing has changed after non-modification
0630: verify();
0631:
0632: resetFull();
0633: it1 = collection.iterator();
0634: for (int i = 0; i < collection.size(); i++) {
0635: assertTrue("Iterator for full collection should haveNext",
0636: it1.hasNext());
0637: it1.next();
0638: }
0639: assertTrue("Iterator should be finished", !it1.hasNext());
0640:
0641: ArrayList list = new ArrayList();
0642: it1 = collection.iterator();
0643: for (int i = 0; i < collection.size(); i++) {
0644: Object next = it1.next();
0645: assertTrue("Collection should contain element returned by "
0646: + "its iterator", collection.contains(next));
0647: list.add(next);
0648: }
0649: try {
0650: it1.next();
0651: fail("iterator.next() should raise NoSuchElementException "
0652: + "after it finishes");
0653: } catch (NoSuchElementException e) {
0654: // expected
0655: }
0656: // make sure nothing has changed after non-modification
0657: verify();
0658: }
0659:
0660: /**
0661: * Tests removals from {@link Collection#iterator()}.
0662: */
0663: public void testCollectionIteratorRemove() {
0664: if (!isRemoveSupported())
0665: return;
0666:
0667: resetEmpty();
0668: try {
0669: collection.iterator().remove();
0670: fail("New iterator.remove should raise IllegalState");
0671: } catch (IllegalStateException e) {
0672: // expected
0673: }
0674: verify();
0675:
0676: try {
0677: Iterator iter = collection.iterator();
0678: iter.hasNext();
0679: iter.remove();
0680: fail("New iterator.remove should raise IllegalState "
0681: + "even after hasNext");
0682: } catch (IllegalStateException e) {
0683: // expected
0684: }
0685: verify();
0686:
0687: resetFull();
0688: int size = collection.size();
0689: Iterator iter = collection.iterator();
0690: while (iter.hasNext()) {
0691: Object o = iter.next();
0692: iter.remove();
0693:
0694: // if the elements aren't distinguishable, we can just remove a
0695: // matching element from the confirmed collection and verify
0696: // contents are still the same. Otherwise, we don't have the
0697: // ability to distinguish the elements and determine which to
0698: // remove from the confirmed collection (in which case, we don't
0699: // verify because we don't know how).
0700: //
0701: // see areEqualElementsDistinguishable()
0702: if (!areEqualElementsDistinguishable()) {
0703: confirmed.remove(o);
0704: verify();
0705: }
0706:
0707: size--;
0708: assertEquals("Collection should shrink by one after "
0709: + "iterator.remove", size, collection.size());
0710: }
0711: assertTrue("Collection should be empty after iterator purge",
0712: collection.isEmpty());
0713:
0714: resetFull();
0715: iter = collection.iterator();
0716: iter.next();
0717: iter.remove();
0718: try {
0719: iter.remove();
0720: fail("Second iter.remove should raise IllegalState");
0721: } catch (IllegalStateException e) {
0722: // expected
0723: }
0724: }
0725:
0726: /**
0727: * Tests {@link Collection#remove(Object)}.
0728: */
0729: public void testCollectionRemove() {
0730: if (!isRemoveSupported())
0731: return;
0732:
0733: resetEmpty();
0734: Object[] elements = getFullElements();
0735: for (int i = 0; i < elements.length; i++) {
0736: assertTrue("Shouldn't remove nonexistent element",
0737: !collection.remove(elements[i]));
0738: verify();
0739: }
0740:
0741: Object[] other = getOtherElements();
0742:
0743: resetFull();
0744: for (int i = 0; i < other.length; i++) {
0745: assertTrue("Shouldn't remove nonexistent other element",
0746: !collection.remove(other[i]));
0747: verify();
0748: }
0749:
0750: int size = collection.size();
0751: for (int i = 0; i < elements.length; i++) {
0752: resetFull();
0753: assertTrue("Collection should remove extant element",
0754: collection.remove(elements[i]));
0755:
0756: // if the elements aren't distinguishable, we can just remove a
0757: // matching element from the confirmed collection and verify
0758: // contents are still the same. Otherwise, we don't have the
0759: // ability to distinguish the elements and determine which to
0760: // remove from the confirmed collection (in which case, we don't
0761: // verify because we don't know how).
0762: //
0763: // see areEqualElementsDistinguishable()
0764: if (!areEqualElementsDistinguishable()) {
0765: confirmed.remove(elements[i]);
0766: verify();
0767: }
0768:
0769: assertEquals("Collection should shrink after remove",
0770: size - 1, collection.size());
0771: }
0772: }
0773:
0774: /**
0775: * Tests {@link Collection#removeAll(Collection)}.
0776: */
0777: public void testCollectionRemoveAll() {
0778: if (!isRemoveSupported())
0779: return;
0780:
0781: resetEmpty();
0782: assertTrue(
0783: "Emtpy collection removeAll should return false for "
0784: + "empty input", !collection
0785: .removeAll(Collections.EMPTY_SET));
0786: verify();
0787:
0788: assertTrue(
0789: "Emtpy collection removeAll should return false for "
0790: + "nonempty input", !collection
0791: .removeAll(new ArrayList(collection)));
0792: verify();
0793:
0794: resetFull();
0795: assertTrue("Full collection removeAll should return false for "
0796: + "empty input", !collection
0797: .removeAll(Collections.EMPTY_SET));
0798: verify();
0799:
0800: assertTrue("Full collection removeAll should return false for "
0801: + "other elements", !collection.removeAll(Arrays
0802: .asList(getOtherElements())));
0803: verify();
0804:
0805: assertTrue("Full collection removeAll should return true for "
0806: + "full elements", collection.removeAll(new HashSet(
0807: collection)));
0808: confirmed.removeAll(new HashSet(confirmed));
0809: verify();
0810:
0811: resetFull();
0812:
0813: int size = collection.size();
0814: Object[] s = getFullElements();
0815: List l = new ArrayList();
0816: l.add(s[2]);
0817: l.add(s[3]);
0818: l.add(s[3]);
0819:
0820: assertTrue("Full collection removeAll should work", collection
0821: .removeAll(l));
0822: confirmed.removeAll(l);
0823: verify();
0824:
0825: assertTrue("Collection should shrink after removeAll",
0826: collection.size() < size);
0827: Iterator iter = l.iterator();
0828: while (iter.hasNext()) {
0829: assertTrue("Collection shouldn't contain removed element",
0830: !collection.contains(iter.next()));
0831: }
0832: }
0833:
0834: /**
0835: * Tests {@link Collection#retainAll(Collection)}.
0836: */
0837: public void testCollectionRetainAll() {
0838: if (!isRemoveSupported())
0839: return;
0840:
0841: resetEmpty();
0842: List elements = Arrays.asList(getFullElements());
0843: List other = Arrays.asList(getOtherElements());
0844: Set empty = new HashSet();
0845:
0846: assertTrue("Empty retainAll() should return false", !collection
0847: .retainAll(empty));
0848: verify();
0849:
0850: assertTrue("Empty retainAll() should return false", !collection
0851: .retainAll(elements));
0852: verify();
0853:
0854: resetFull();
0855: assertTrue("Collection should change from retainAll empty",
0856: collection.retainAll(empty));
0857: confirmed.retainAll(empty);
0858: verify();
0859:
0860: resetFull();
0861: assertTrue("Collection changed from retainAll other",
0862: collection.retainAll(other));
0863: confirmed.retainAll(other);
0864: verify();
0865:
0866: resetFull();
0867: int size = collection.size();
0868: assertTrue(
0869: "Collection shouldn't change from retainAll elements",
0870: !collection.retainAll(elements));
0871: verify();
0872: assertEquals("Collection size shouldn't change", size,
0873: collection.size());
0874:
0875: resetFull();
0876: HashSet set = new HashSet(elements);
0877: size = collection.size();
0878: assertTrue(
0879: "Collection shouldn't change from retainAll without "
0880: + "duplicate elements", !collection
0881: .retainAll(set));
0882: verify();
0883: assertEquals("Collection size didn't change from nonduplicate "
0884: + "retainAll", size, collection.size());
0885: }
0886:
0887: /**
0888: * Tests {@link Collection#size()}.
0889: */
0890: public void testCollectionSize() {
0891: resetEmpty();
0892: assertEquals("Size of new Collection is 0.", 0, collection
0893: .size());
0894:
0895: resetFull();
0896: assertTrue(
0897: "Size of full collection should be greater than zero",
0898: collection.size() > 0);
0899: }
0900:
0901: /**
0902: * Tests <Code>toString</Code> on a collection.
0903: */
0904: public void testCollectionToString() {
0905: resetEmpty();
0906: assertTrue("toString shouldn't return null", collection
0907: .toString() != null);
0908:
0909: resetFull();
0910: assertTrue("toString shouldn't return null", collection
0911: .toString() != null);
0912: }
0913:
0914: /**
0915: * If isRemoveSupported() returns false, tests to see that remove
0916: * operations raise an UnsupportedOperationException.
0917: */
0918: public void testUnsupportedRemove() {
0919: if (isRemoveSupported())
0920: return;
0921:
0922: resetEmpty();
0923: try {
0924: collection.clear();
0925: fail("clear should raise UnsupportedOperationException");
0926: } catch (UnsupportedOperationException e) {
0927: // expected
0928: }
0929: verify();
0930:
0931: try {
0932: collection.remove(null);
0933: fail("remove should raise UnsupportedOperationException");
0934: } catch (UnsupportedOperationException e) {
0935: // expected
0936: }
0937: verify();
0938:
0939: try {
0940: collection.removeAll(null);
0941: fail("removeAll should raise UnsupportedOperationException");
0942: } catch (UnsupportedOperationException e) {
0943: // expected
0944: }
0945: verify();
0946:
0947: try {
0948: collection.retainAll(null);
0949: fail("removeAll should raise UnsupportedOperationException");
0950: } catch (UnsupportedOperationException e) {
0951: // expected
0952: }
0953: verify();
0954:
0955: resetFull();
0956: try {
0957: Iterator iterator = collection.iterator();
0958: iterator.next();
0959: iterator.remove();
0960: fail("iterator.remove should raise UnsupportedOperationException");
0961: } catch (UnsupportedOperationException e) {
0962: // expected
0963: }
0964: verify();
0965:
0966: }
0967:
0968: /**
0969: * Returns a list of elements suitable for return by
0970: * {@link #getFullElements()}. The array returned by this method
0971: * does not include null, but does include a variety of objects
0972: * of different types. Override getFullElements to return
0973: * the results of this method if your collection does not support
0974: * the null element.
0975: */
0976: public static Object[] getFullNonNullElements() {
0977: return new Object[] { new String(""), new String("One"),
0978: new Integer(2), "Three", new Integer(4), "One",
0979: new Double(5), new Float(6), "Seven", "Eight",
0980: new String("Nine"), new Integer(10),
0981: new Short((short) 11), new Long(12), "Thirteen", "14",
0982: "15", new Byte((byte) 16) };
0983: }
0984:
0985: /**
0986: * Returns the default list of objects returned by
0987: * {@link #getOtherElements()}. Includes many objects
0988: * of different types.
0989: */
0990: public static Object[] getOtherNonNullElements() {
0991: return new Object[] { new Integer(0), new Float(0),
0992: new Double(0), "Zero", new Short((short) 0),
0993: new Byte((byte) 0), new Long(0),
0994: new Character('\u0000'), "0" };
0995: }
0996:
0997: /**
0998: * Returns a list of string elements suitable for return by
0999: * {@link #getFullElements()}. Override getFullElements to return
1000: * the results of this method if your collection does not support
1001: * heterogenous elements or the null element.
1002: */
1003: public static Object[] getFullNonNullStringElements() {
1004: return new Object[] { "If", "the", "dull", "substance", "of",
1005: "my", "flesh", "were", "thought", "Injurious",
1006: "distance", "could", "not", "stop", "my", "way", };
1007: }
1008:
1009: /**
1010: * Returns a list of string elements suitable for return by
1011: * {@link #getOtherElements()}. Override getOtherElements to return
1012: * the results of this method if your collection does not support
1013: * heterogenous elements or the null element.
1014: */
1015: public static Object[] getOtherNonNullStringElements() {
1016: return new Object[] { "For", "then", "despite",/* of */
1017: "space", "I", "would", "be", "brought", "From",
1018: "limits", "far", "remote", "where", "thou", "dost",
1019: "stay" };
1020: }
1021: }
|