001/*
002 * Copyright (C) 2008 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.collect.testing.testers;
018
019import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
020import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
021import static com.google.common.collect.testing.features.CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION;
022import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
023import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
024import static com.google.common.collect.testing.features.CollectionSize.ZERO;
025
026import com.google.common.annotations.GwtCompatible;
027import com.google.common.collect.testing.AbstractCollectionTester;
028import com.google.common.collect.testing.MinimalCollection;
029import com.google.common.collect.testing.WrongType;
030import com.google.common.collect.testing.features.CollectionFeature;
031import com.google.common.collect.testing.features.CollectionSize;
032import java.util.Collections;
033import java.util.ConcurrentModificationException;
034import java.util.Iterator;
035
036/**
037 * A generic JUnit test which tests {@code removeAll} operations on a collection. Can't be invoked
038 * directly; please see {@link com.google.common.collect.testing.CollectionTestSuiteBuilder}.
039 *
040 * @author George van den Driessche
041 * @author Chris Povirk
042 */
043@SuppressWarnings("unchecked") // too many "unchecked generic array creations"
044@GwtCompatible
045public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
046  @CollectionFeature.Require(SUPPORTS_REMOVE)
047  public void testRemoveAll_emptyCollection() {
048    assertFalse(
049        "removeAll(emptyCollection) should return false",
050        collection.removeAll(MinimalCollection.of()));
051    expectUnchanged();
052  }
053
054  @CollectionFeature.Require(SUPPORTS_REMOVE)
055  public void testRemoveAll_nonePresent() {
056    assertFalse(
057        "removeAll(disjointCollection) should return false",
058        collection.removeAll(MinimalCollection.of(e3())));
059    expectUnchanged();
060  }
061
062  @CollectionFeature.Require(SUPPORTS_REMOVE)
063  @CollectionSize.Require(absent = ZERO)
064  public void testRemoveAll_allPresent() {
065    assertTrue(
066        "removeAll(intersectingCollection) should return true",
067        collection.removeAll(MinimalCollection.of(e0())));
068    expectMissing(e0());
069  }
070
071  @CollectionFeature.Require(SUPPORTS_REMOVE)
072  @CollectionSize.Require(absent = ZERO)
073  public void testRemoveAll_somePresent() {
074    assertTrue(
075        "removeAll(intersectingCollection) should return true",
076        collection.removeAll(MinimalCollection.of(e0(), e3())));
077    expectMissing(e0());
078  }
079
080  @CollectionFeature.Require({SUPPORTS_REMOVE, FAILS_FAST_ON_CONCURRENT_MODIFICATION})
081  @CollectionSize.Require(SEVERAL)
082  public void testRemoveAllSomePresentConcurrentWithIteration() {
083    try {
084      Iterator<E> iterator = collection.iterator();
085      assertTrue(collection.removeAll(MinimalCollection.of(e0(), e3())));
086      iterator.next();
087      fail("Expected ConcurrentModificationException");
088    } catch (ConcurrentModificationException expected) {
089      // success
090    }
091  }
092
093  /** Trigger the {@code other.size() >= this.size()} case in {@link AbstractSet#removeAll()}. */
094  @CollectionFeature.Require(SUPPORTS_REMOVE)
095  @CollectionSize.Require(absent = ZERO)
096  public void testRemoveAll_somePresentLargeCollectionToRemove() {
097    assertTrue(
098        "removeAll(largeIntersectingCollection) should return true",
099        collection.removeAll(MinimalCollection.of(e0(), e0(), e0(), e3(), e3(), e3())));
100    expectMissing(e0());
101  }
102
103  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
104  public void testRemoveAll_unsupportedEmptyCollection() {
105    try {
106      assertFalse(
107          "removeAll(emptyCollection) should return false or throw "
108              + "UnsupportedOperationException",
109          collection.removeAll(MinimalCollection.of()));
110    } catch (UnsupportedOperationException tolerated) {
111    }
112    expectUnchanged();
113  }
114
115  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
116  public void testRemoveAll_unsupportedNonePresent() {
117    try {
118      assertFalse(
119          "removeAll(disjointCollection) should return false or throw "
120              + "UnsupportedOperationException",
121          collection.removeAll(MinimalCollection.of(e3())));
122    } catch (UnsupportedOperationException tolerated) {
123    }
124    expectUnchanged();
125  }
126
127  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
128  @CollectionSize.Require(absent = ZERO)
129  public void testRemoveAll_unsupportedPresent() {
130    try {
131      collection.removeAll(MinimalCollection.of(e0()));
132      fail("removeAll(intersectingCollection) should throw UnsupportedOperationException");
133    } catch (UnsupportedOperationException expected) {
134    }
135    expectUnchanged();
136    assertTrue(collection.contains(e0()));
137  }
138
139  /*
140   * AbstractCollection fails the removeAll(null) test when the subject
141   * collection is empty, but we'd still like to test removeAll(null) when we
142   * can. We split the test into empty and non-empty cases. This allows us to
143   * suppress only the former.
144   */
145
146  @CollectionFeature.Require(SUPPORTS_REMOVE)
147  @CollectionSize.Require(ZERO)
148  public void testRemoveAll_nullCollectionReferenceEmptySubject() {
149    try {
150      collection.removeAll(null);
151      // Returning successfully is not ideal, but tolerated.
152    } catch (NullPointerException tolerated) {
153    }
154  }
155
156  @CollectionFeature.Require(SUPPORTS_REMOVE)
157  @CollectionSize.Require(absent = ZERO)
158  public void testRemoveAll_nullCollectionReferenceNonEmptySubject() {
159    try {
160      collection.removeAll(null);
161      fail("removeAll(null) should throw NullPointerException");
162    } catch (NullPointerException expected) {
163    }
164  }
165
166  @CollectionFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_QUERIES)
167  public void testRemoveAll_containsNullNo() {
168    MinimalCollection<?> containsNull = MinimalCollection.of((Object) null);
169    try {
170      assertFalse(
171          "removeAll(containsNull) should return false or throw",
172          collection.removeAll(containsNull));
173    } catch (NullPointerException tolerated) {
174    }
175    expectUnchanged();
176  }
177
178  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_QUERIES})
179  public void testRemoveAll_containsNullNoButAllowed() {
180    MinimalCollection<?> containsNull = MinimalCollection.of((Object) null);
181    assertFalse("removeAll(containsNull) should return false", collection.removeAll(containsNull));
182    expectUnchanged();
183  }
184
185  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
186  @CollectionSize.Require(absent = ZERO)
187  public void testRemoveAll_containsNullYes() {
188    initCollectionWithNullElement();
189    assertTrue(
190        "removeAll(containsNull) should return true",
191        collection.removeAll(Collections.singleton(null)));
192    // TODO: make this work with MinimalCollection
193  }
194
195  @CollectionFeature.Require(SUPPORTS_REMOVE)
196  public void testRemoveAll_containsWrongType() {
197    try {
198      assertFalse(
199          "removeAll(containsWrongType) should return false or throw",
200          collection.removeAll(MinimalCollection.of(WrongType.VALUE)));
201    } catch (ClassCastException tolerated) {
202    }
203    expectUnchanged();
204  }
205}