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