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_VALUES;
020import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
021import static com.google.common.collect.testing.features.CollectionSize.ONE;
022import static com.google.common.collect.testing.features.CollectionSize.ZERO;
023
024import com.google.common.annotations.GwtCompatible;
025import com.google.common.collect.testing.AbstractCollectionTester;
026import com.google.common.collect.testing.MinimalCollection;
027import com.google.common.collect.testing.features.CollectionFeature;
028import com.google.common.collect.testing.features.CollectionSize;
029import java.util.Arrays;
030import java.util.Collection;
031import java.util.Collections;
032import java.util.List;
033import org.junit.Ignore;
034
035/**
036 * A generic JUnit test which tests {@code retainAll} operations on a collection. Can't be invoked
037 * directly; please see {@link com.google.common.collect.testing.CollectionTestSuiteBuilder}.
038 *
039 * @author Chris Povirk
040 */
041@GwtCompatible
042@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
043public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
044
045  /** A collection of elements to retain, along with a description for use in failure messages. */
046  private class Target {
047    private final Collection<E> toRetain;
048    private final String description;
049
050    private Target(Collection<E> toRetain, String description) {
051      this.toRetain = toRetain;
052      this.description = description;
053    }
054
055    @Override
056    public String toString() {
057      return description;
058    }
059  }
060
061  private Target empty;
062  private Target disjoint;
063  private Target superset;
064  private Target nonEmptyProperSubset;
065  private Target sameElements;
066  private Target partialOverlap;
067  private Target containsDuplicates;
068  private Target nullSingleton;
069
070  @Override
071  public void setUp() throws Exception {
072    super.setUp();
073
074    empty = new Target(emptyCollection(), "empty");
075    /*
076     * We test that nullSingleton.retainAll(disjointList) does NOT throw a
077     * NullPointerException when disjointList does not, so we can't use
078     * MinimalCollection, which throws NullPointerException on calls to
079     * contains(null).
080     */
081    List<E> disjointList = Arrays.asList(e3(), e4());
082    disjoint = new Target(disjointList, "disjoint");
083    superset = new Target(MinimalCollection.of(e0(), e1(), e2(), e3(), e4()), "superset");
084    nonEmptyProperSubset = new Target(MinimalCollection.of(e1()), "subset");
085    sameElements = new Target(Arrays.asList(createSamplesArray()), "sameElements");
086    containsDuplicates =
087        new Target(MinimalCollection.of(e0(), e0(), e3(), e3()), "containsDuplicates");
088    partialOverlap = new Target(MinimalCollection.of(e2(), e3()), "partialOverlap");
089    nullSingleton = new Target(Collections.<E>singleton(null), "nullSingleton");
090  }
091
092  // retainAll(empty)
093
094  @CollectionFeature.Require(SUPPORTS_REMOVE)
095  @CollectionSize.Require(ZERO)
096  public void testRetainAll_emptyPreviouslyEmpty() {
097    expectReturnsFalse(empty);
098    expectUnchanged();
099  }
100
101  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
102  @CollectionSize.Require(ZERO)
103  public void testRetainAll_emptyPreviouslyEmptyUnsupported() {
104    expectReturnsFalseOrThrows(empty);
105    expectUnchanged();
106  }
107
108  @CollectionFeature.Require(SUPPORTS_REMOVE)
109  @CollectionSize.Require(absent = ZERO)
110  public void testRetainAll_emptyPreviouslyNonEmpty() {
111    expectReturnsTrue(empty);
112    expectContents();
113    expectMissing(e0(), e1(), e2());
114  }
115
116  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
117  @CollectionSize.Require(absent = ZERO)
118  public void testRetainAll_emptyPreviouslyNonEmptyUnsupported() {
119    expectThrows(empty);
120    expectUnchanged();
121  }
122
123  // retainAll(disjoint)
124
125  @CollectionFeature.Require(SUPPORTS_REMOVE)
126  @CollectionSize.Require(ZERO)
127  public void testRetainAll_disjointPreviouslyEmpty() {
128    expectReturnsFalse(disjoint);
129    expectUnchanged();
130  }
131
132  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
133  @CollectionSize.Require(ZERO)
134  public void testRetainAll_disjointPreviouslyEmptyUnsupported() {
135    expectReturnsFalseOrThrows(disjoint);
136    expectUnchanged();
137  }
138
139  @CollectionFeature.Require(SUPPORTS_REMOVE)
140  @CollectionSize.Require(absent = ZERO)
141  public void testRetainAll_disjointPreviouslyNonEmpty() {
142    expectReturnsTrue(disjoint);
143    expectContents();
144    expectMissing(e0(), e1(), e2());
145  }
146
147  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
148  @CollectionSize.Require(absent = ZERO)
149  public void testRetainAll_disjointPreviouslyNonEmptyUnsupported() {
150    expectThrows(disjoint);
151    expectUnchanged();
152  }
153
154  // retainAll(superset)
155
156  @CollectionFeature.Require(SUPPORTS_REMOVE)
157  public void testRetainAll_superset() {
158    expectReturnsFalse(superset);
159    expectUnchanged();
160  }
161
162  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
163  public void testRetainAll_supersetUnsupported() {
164    expectReturnsFalseOrThrows(superset);
165    expectUnchanged();
166  }
167
168  // retainAll(subset)
169
170  @CollectionFeature.Require(SUPPORTS_REMOVE)
171  @CollectionSize.Require(absent = {ZERO, ONE})
172  public void testRetainAll_subset() {
173    expectReturnsTrue(nonEmptyProperSubset);
174    expectContents(nonEmptyProperSubset.toRetain);
175  }
176
177  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
178  @CollectionSize.Require(absent = {ZERO, ONE})
179  public void testRetainAll_subsetUnsupported() {
180    expectThrows(nonEmptyProperSubset);
181    expectUnchanged();
182  }
183
184  // retainAll(sameElements)
185
186  @CollectionFeature.Require(SUPPORTS_REMOVE)
187  public void testRetainAll_sameElements() {
188    expectReturnsFalse(sameElements);
189    expectUnchanged();
190  }
191
192  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
193  public void testRetainAll_sameElementsUnsupported() {
194    expectReturnsFalseOrThrows(sameElements);
195    expectUnchanged();
196  }
197
198  // retainAll(partialOverlap)
199
200  @CollectionFeature.Require(SUPPORTS_REMOVE)
201  @CollectionSize.Require(absent = {ZERO, ONE})
202  public void testRetainAll_partialOverlap() {
203    expectReturnsTrue(partialOverlap);
204    expectContents(e2());
205  }
206
207  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
208  @CollectionSize.Require(absent = {ZERO, ONE})
209  public void testRetainAll_partialOverlapUnsupported() {
210    expectThrows(partialOverlap);
211    expectUnchanged();
212  }
213
214  // retainAll(containsDuplicates)
215
216  @CollectionFeature.Require(SUPPORTS_REMOVE)
217  @CollectionSize.Require(ONE)
218  public void testRetainAll_containsDuplicatesSizeOne() {
219    expectReturnsFalse(containsDuplicates);
220    expectContents(e0());
221  }
222
223  @CollectionFeature.Require(SUPPORTS_REMOVE)
224  @CollectionSize.Require(absent = {ZERO, ONE})
225  public void testRetainAll_containsDuplicatesSizeSeveral() {
226    expectReturnsTrue(containsDuplicates);
227    expectContents(e0());
228  }
229
230  // retainAll(nullSingleton)
231
232  @CollectionFeature.Require(SUPPORTS_REMOVE)
233  @CollectionSize.Require(ZERO)
234  public void testRetainAll_nullSingletonPreviouslyEmpty() {
235    expectReturnsFalse(nullSingleton);
236    expectUnchanged();
237  }
238
239  @CollectionFeature.Require(SUPPORTS_REMOVE)
240  @CollectionSize.Require(absent = ZERO)
241  public void testRetainAll_nullSingletonPreviouslyNonEmpty() {
242    expectReturnsTrue(nullSingleton);
243    expectContents();
244  }
245
246  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
247  @CollectionSize.Require(ONE)
248  public void testRetainAll_nullSingletonPreviouslySingletonWithNull() {
249    initCollectionWithNullElement();
250    expectReturnsFalse(nullSingleton);
251    expectContents(createArrayWithNullElement());
252  }
253
254  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
255  @CollectionSize.Require(absent = {ZERO, ONE})
256  public void testRetainAll_nullSingletonPreviouslySeveralWithNull() {
257    initCollectionWithNullElement();
258    expectReturnsTrue(nullSingleton);
259    expectContents(nullSingleton.toRetain);
260  }
261
262  // nullSingleton.retainAll()
263
264  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
265  @CollectionSize.Require(absent = ZERO)
266  public void testRetainAll_containsNonNullWithNull() {
267    initCollectionWithNullElement();
268    expectReturnsTrue(disjoint);
269    expectContents();
270  }
271
272  // retainAll(null)
273
274  /*
275   * AbstractCollection fails the retainAll(null) test when the subject
276   * collection is empty, but we'd still like to test retainAll(null) when we
277   * can. We split the test into empty and non-empty cases. This allows us to
278   * suppress only the former.
279   */
280
281  @CollectionFeature.Require(SUPPORTS_REMOVE)
282  @CollectionSize.Require(ZERO)
283  public void testRetainAll_nullCollectionReferenceEmptySubject() {
284    try {
285      collection.retainAll(null);
286      // Returning successfully is not ideal, but tolerated.
287    } catch (NullPointerException tolerated) {
288    }
289  }
290
291  @CollectionFeature.Require(SUPPORTS_REMOVE)
292  @CollectionSize.Require(absent = ZERO)
293  public void testRetainAll_nullCollectionReferenceNonEmptySubject() {
294    try {
295      collection.retainAll(null);
296      fail("retainAll(null) should throw NullPointerException");
297    } catch (NullPointerException expected) {
298    }
299  }
300
301  private void expectReturnsTrue(Target target) {
302    String message = Platform.format("retainAll(%s) should return true", target);
303    assertTrue(message, collection.retainAll(target.toRetain));
304  }
305
306  private void expectReturnsFalse(Target target) {
307    String message = Platform.format("retainAll(%s) should return false", target);
308    assertFalse(message, collection.retainAll(target.toRetain));
309  }
310
311  private void expectThrows(Target target) {
312    try {
313      collection.retainAll(target.toRetain);
314      String message = Platform.format("retainAll(%s) should throw", target);
315      fail(message);
316    } catch (UnsupportedOperationException expected) {
317    }
318  }
319
320  private void expectReturnsFalseOrThrows(Target target) {
321    String message = Platform.format("retainAll(%s) should return false or throw", target);
322    try {
323      assertFalse(message, collection.retainAll(target.toRetain));
324    } catch (UnsupportedOperationException tolerated) {
325    }
326  }
327}