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;
025import static com.google.common.collect.testing.testers.ReflectionFreeAssertThrows.assertThrows;
026import static java.util.Collections.singleton;
027
028import com.google.common.annotations.GwtCompatible;
029import com.google.common.collect.testing.AbstractCollectionTester;
030import com.google.common.collect.testing.MinimalCollection;
031import com.google.common.collect.testing.WrongType;
032import com.google.common.collect.testing.features.CollectionFeature;
033import com.google.common.collect.testing.features.CollectionSize;
034import java.util.AbstractSet;
035import java.util.ConcurrentModificationException;
036import java.util.Iterator;
037import org.junit.Ignore;
038
039/**
040 * A generic JUnit test which tests {@code removeAll} operations on a collection. Can't be invoked
041 * directly; please see {@link com.google.common.collect.testing.CollectionTestSuiteBuilder}.
042 *
043 * @author George van den Driessche
044 * @author Chris Povirk
045 */
046@GwtCompatible
047@Ignore("test runners must not instantiate and run this directly, only via suites we build")
048// @Ignore affects the Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
049@SuppressWarnings("JUnit4ClassUsedInJUnit3")
050public class CollectionRemoveAllTester<E> extends AbstractCollectionTester<E> {
051  @CollectionFeature.Require(SUPPORTS_REMOVE)
052  public void testRemoveAll_emptyCollection() {
053    assertFalse(
054        "removeAll(emptyCollection) should return false",
055        collection.removeAll(MinimalCollection.of()));
056    expectUnchanged();
057  }
058
059  @CollectionFeature.Require(SUPPORTS_REMOVE)
060  public void testRemoveAll_nonePresent() {
061    assertFalse(
062        "removeAll(disjointCollection) should return false",
063        collection.removeAll(MinimalCollection.of(e3())));
064    expectUnchanged();
065  }
066
067  @CollectionFeature.Require(SUPPORTS_REMOVE)
068  @CollectionSize.Require(absent = ZERO)
069  public void testRemoveAll_allPresent() {
070    assertTrue(
071        "removeAll(intersectingCollection) should return true",
072        collection.removeAll(MinimalCollection.of(e0())));
073    expectMissing(e0());
074  }
075
076  @CollectionFeature.Require(SUPPORTS_REMOVE)
077  @CollectionSize.Require(absent = ZERO)
078  public void testRemoveAll_somePresent() {
079    assertTrue(
080        "removeAll(intersectingCollection) should return true",
081        collection.removeAll(MinimalCollection.of(e0(), e3())));
082    expectMissing(e0());
083  }
084
085  @CollectionFeature.Require({SUPPORTS_REMOVE, FAILS_FAST_ON_CONCURRENT_MODIFICATION})
086  @CollectionSize.Require(SEVERAL)
087  public void testRemoveAllSomePresentConcurrentWithIteration() {
088    assertThrows(
089        ConcurrentModificationException.class,
090        () -> {
091          Iterator<E> iterator = collection.iterator();
092          assertTrue(collection.removeAll(MinimalCollection.of(e0(), e3())));
093          iterator.next();
094        });
095  }
096
097  /** Trigger the {@code other.size() >= this.size()} case in {@link AbstractSet#removeAll}. */
098  @CollectionFeature.Require(SUPPORTS_REMOVE)
099  @CollectionSize.Require(absent = ZERO)
100  public void testRemoveAll_somePresentLargeCollectionToRemove() {
101    assertTrue(
102        "removeAll(largeIntersectingCollection) should return true",
103        collection.removeAll(MinimalCollection.of(e0(), e0(), e0(), e3(), e3(), e3())));
104    expectMissing(e0());
105  }
106
107  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
108  public void testRemoveAll_unsupportedEmptyCollection() {
109    try {
110      assertFalse(
111          "removeAll(emptyCollection) should return false or throw "
112              + "UnsupportedOperationException",
113          collection.removeAll(MinimalCollection.of()));
114    } catch (UnsupportedOperationException tolerated) {
115    }
116    expectUnchanged();
117  }
118
119  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
120  public void testRemoveAll_unsupportedNonePresent() {
121    try {
122      assertFalse(
123          "removeAll(disjointCollection) should return false or throw "
124              + "UnsupportedOperationException",
125          collection.removeAll(MinimalCollection.of(e3())));
126    } catch (UnsupportedOperationException tolerated) {
127    }
128    expectUnchanged();
129  }
130
131  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
132  @CollectionSize.Require(absent = ZERO)
133  public void testRemoveAll_unsupportedPresent() {
134    assertThrows(
135        UnsupportedOperationException.class,
136        () -> collection.removeAll(MinimalCollection.of(e0())));
137    expectUnchanged();
138    assertTrue(collection.contains(e0()));
139  }
140
141  /*
142   * AbstractCollection fails the removeAll(null) test when the subject
143   * collection is empty, but we'd still like to test removeAll(null) when we
144   * can. We split the test into empty and non-empty cases. This allows us to
145   * suppress only the former.
146   */
147
148  @CollectionFeature.Require(SUPPORTS_REMOVE)
149  @CollectionSize.Require(ZERO)
150  public void testRemoveAll_nullCollectionReferenceEmptySubject() {
151    try {
152      collection.removeAll(null);
153      // Returning successfully is not ideal, but tolerated.
154    } catch (NullPointerException tolerated) {
155    }
156  }
157
158  @CollectionFeature.Require(SUPPORTS_REMOVE)
159  @CollectionSize.Require(absent = ZERO)
160  public void testRemoveAll_nullCollectionReferenceNonEmptySubject() {
161    assertThrows(NullPointerException.class, () -> collection.removeAll(null));
162  }
163
164  @CollectionFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_QUERIES)
165  public void testRemoveAll_containsNullNo() {
166    MinimalCollection<?> containsNull = MinimalCollection.of((Object) null);
167    try {
168      assertFalse(
169          "removeAll(containsNull) should return false or throw",
170          collection.removeAll(containsNull));
171    } catch (NullPointerException tolerated) {
172    }
173    expectUnchanged();
174  }
175
176  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_QUERIES})
177  public void testRemoveAll_containsNullNoButAllowed() {
178    MinimalCollection<?> containsNull = MinimalCollection.of((Object) null);
179    assertFalse("removeAll(containsNull) should return false", collection.removeAll(containsNull));
180    expectUnchanged();
181  }
182
183  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
184  @CollectionSize.Require(absent = ZERO)
185  public void testRemoveAll_containsNullYes() {
186    initCollectionWithNullElement();
187    assertTrue("removeAll(containsNull) should return true", collection.removeAll(singleton(null)));
188    // TODO: make this work with MinimalCollection
189  }
190
191  @CollectionFeature.Require(SUPPORTS_REMOVE)
192  public void testRemoveAll_containsWrongType() {
193    try {
194      assertFalse(
195          "removeAll(containsWrongType) should return false or throw",
196          collection.removeAll(MinimalCollection.of(WrongType.VALUE)));
197    } catch (ClassCastException tolerated) {
198    }
199    expectUnchanged();
200  }
201}