CollectionRetainAllTester.java revision 0888a09821a98ac0680fad765217302858e70fa4
1/*
2 * Copyright (C) 2008 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.collect.testing.testers;
18
19import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
20import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
21import static com.google.common.collect.testing.features.CollectionSize.ONE;
22import static com.google.common.collect.testing.features.CollectionSize.ZERO;
23
24import com.google.common.annotations.GwtCompatible;
25import com.google.common.collect.testing.AbstractCollectionTester;
26import com.google.common.collect.testing.MinimalCollection;
27import com.google.common.collect.testing.features.CollectionFeature;
28import com.google.common.collect.testing.features.CollectionSize;
29
30import java.util.Arrays;
31import java.util.Collection;
32import java.util.Collections;
33import java.util.List;
34
35/**
36 * A generic JUnit test which tests {@code retainAll} operations on a
37 * collection. Can't be invoked directly; please see
38 * {@link com.google.common.collect.testing.CollectionTestSuiteBuilder}.
39 *
40 * @author Chris Povirk
41 */
42@SuppressWarnings("unchecked") // too many "unchecked generic array creations"
43@GwtCompatible
44public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
45
46  /**
47   * A collection of elements to retain, along with a description for use in
48   * failure messages.
49   */
50  private class Target {
51    private final Collection<E> toRetain;
52    private final String description;
53
54    private Target(Collection<E> toRetain, String description) {
55      this.toRetain = toRetain;
56      this.description = description;
57    }
58
59    @Override public String toString() {
60      return description;
61    }
62  }
63
64  private Target empty;
65  private Target disjoint;
66  private Target superset;
67  private Target nonEmptyProperSubset;
68  private Target sameElements;
69  private Target partialOverlap;
70  private Target containsDuplicates;
71  private Target nullSingleton;
72
73  @Override public void setUp() throws Exception {
74    super.setUp();
75
76    empty = new Target(emptyCollection(), "empty");
77    /*
78     * We test that nullSingleton.retainAll(disjointList) does NOT throw a
79     * NullPointerException when disjointList does not, so we can't use
80     * MinimalCollection, which throws NullPointerException on calls to
81     * contains(null).
82     */
83    List<E> disjointList = Arrays.asList(samples.e3, samples.e4);
84    disjoint
85        = new Target(disjointList, "disjoint");
86    superset
87        = new Target(MinimalCollection.of(
88            samples.e0, samples.e1, samples.e2, samples.e3, samples.e4),
89            "superset");
90    nonEmptyProperSubset
91        = new Target(MinimalCollection.of(samples.e1), "subset");
92    sameElements
93        = new Target(Arrays.asList(createSamplesArray()), "sameElements");
94    containsDuplicates = new Target(
95        MinimalCollection.of(samples.e0, samples.e0, samples.e3, samples.e3),
96        "containsDuplicates");
97    partialOverlap
98        = new Target(MinimalCollection.of(samples.e2, samples.e3),
99            "partialOverlap");
100    nullSingleton
101        = new Target(Collections.<E>singleton(null), "nullSingleton");
102  }
103
104  // retainAll(empty)
105
106  @CollectionFeature.Require(SUPPORTS_REMOVE)
107  @CollectionSize.Require(ZERO)
108  public void testRetainAll_emptyPreviouslyEmpty() {
109    expectReturnsFalse(empty);
110    expectUnchanged();
111  }
112
113  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
114  @CollectionSize.Require(ZERO)
115  public void testRetainAll_emptyPreviouslyEmptyUnsupported() {
116    expectReturnsFalseOrThrows(empty);
117    expectUnchanged();
118  }
119
120  @CollectionFeature.Require(SUPPORTS_REMOVE)
121  @CollectionSize.Require(absent = ZERO)
122  public void testRetainAll_emptyPreviouslyNonEmpty() {
123    expectReturnsTrue(empty);
124    expectContents();
125    expectMissing(samples.e0, samples.e1, samples.e2);
126  }
127
128  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
129  @CollectionSize.Require(absent = ZERO)
130  public void testRetainAll_emptyPreviouslyNonEmptyUnsupported() {
131    expectThrows(empty);
132    expectUnchanged();
133  }
134
135  // retainAll(disjoint)
136
137  @CollectionFeature.Require(SUPPORTS_REMOVE)
138  @CollectionSize.Require(ZERO)
139  public void testRetainAll_disjointPreviouslyEmpty() {
140    expectReturnsFalse(disjoint);
141    expectUnchanged();
142  }
143
144  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
145  @CollectionSize.Require(ZERO)
146  public void testRetainAll_disjointPreviouslyEmptyUnsupported() {
147    expectReturnsFalseOrThrows(disjoint);
148    expectUnchanged();
149  }
150
151  @CollectionFeature.Require(SUPPORTS_REMOVE)
152  @CollectionSize.Require(absent = ZERO)
153  public void testRetainAll_disjointPreviouslyNonEmpty() {
154    expectReturnsTrue(disjoint);
155    expectContents();
156    expectMissing(samples.e0, samples.e1, samples.e2);
157  }
158
159  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
160  @CollectionSize.Require(absent = ZERO)
161  public void testRetainAll_disjointPreviouslyNonEmptyUnsupported() {
162    expectThrows(disjoint);
163    expectUnchanged();
164  }
165
166  // retainAll(superset)
167
168  @CollectionFeature.Require(SUPPORTS_REMOVE)
169  public void testRetainAll_superset() {
170    expectReturnsFalse(superset);
171    expectUnchanged();
172  }
173
174  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
175  public void testRetainAll_supersetUnsupported() {
176    expectReturnsFalseOrThrows(superset);
177    expectUnchanged();
178  }
179
180  // retainAll(subset)
181
182  @CollectionFeature.Require(SUPPORTS_REMOVE)
183  @CollectionSize.Require(absent = {ZERO, ONE})
184  public void testRetainAll_subset() {
185    expectReturnsTrue(nonEmptyProperSubset);
186    expectContents(nonEmptyProperSubset.toRetain);
187  }
188
189  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
190  @CollectionSize.Require(absent = {ZERO, ONE})
191  public void testRetainAll_subsetUnsupported() {
192    expectThrows(nonEmptyProperSubset);
193    expectUnchanged();
194  }
195
196  // retainAll(sameElements)
197
198  @CollectionFeature.Require(SUPPORTS_REMOVE)
199  public void testRetainAll_sameElements() {
200    expectReturnsFalse(sameElements);
201    expectUnchanged();
202  }
203
204  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
205  public void testRetainAll_sameElementsUnsupported() {
206    expectReturnsFalseOrThrows(sameElements);
207    expectUnchanged();
208  }
209
210  // retainAll(partialOverlap)
211
212  @CollectionFeature.Require(SUPPORTS_REMOVE)
213  @CollectionSize.Require(absent = {ZERO, ONE})
214  public void testRetainAll_partialOverlap() {
215    expectReturnsTrue(partialOverlap);
216    expectContents(samples.e2);
217  }
218
219  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
220  @CollectionSize.Require(absent = {ZERO, ONE})
221  public void testRetainAll_partialOverlapUnsupported() {
222    expectThrows(partialOverlap);
223    expectUnchanged();
224  }
225
226  // retainAll(containsDuplicates)
227
228  @CollectionFeature.Require(SUPPORTS_REMOVE)
229  @CollectionSize.Require(ONE)
230  public void testRetainAll_containsDuplicatesSizeOne() {
231    expectReturnsFalse(containsDuplicates);
232    expectContents(samples.e0);
233  }
234
235  @CollectionFeature.Require(SUPPORTS_REMOVE)
236  @CollectionSize.Require(absent = {ZERO, ONE})
237  public void testRetainAll_containsDuplicatesSizeSeveral() {
238    expectReturnsTrue(containsDuplicates);
239    expectContents(samples.e0);
240  }
241
242  // retainAll(nullSingleton)
243
244  @CollectionFeature.Require(SUPPORTS_REMOVE)
245  @CollectionSize.Require(ZERO)
246  public void testRetainAll_nullSingletonPreviouslyEmpty() {
247    expectReturnsFalse(nullSingleton);
248    expectUnchanged();
249  }
250
251  @CollectionFeature.Require(SUPPORTS_REMOVE)
252  @CollectionSize.Require(absent = ZERO)
253  public void testRetainAll_nullSingletonPreviouslyNonEmpty() {
254    expectReturnsTrue(nullSingleton);
255    expectContents();
256  }
257
258  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
259  @CollectionSize.Require(ONE)
260  public void testRetainAll_nullSingletonPreviouslySingletonWithNull() {
261    initCollectionWithNullElement();
262    expectReturnsFalse(nullSingleton);
263    expectContents(createArrayWithNullElement());
264  }
265
266  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
267  @CollectionSize.Require(absent = {ZERO, ONE})
268  public void testRetainAll_nullSingletonPreviouslySeveralWithNull() {
269    initCollectionWithNullElement();
270    expectReturnsTrue(nullSingleton);
271    expectContents(nullSingleton.toRetain);
272  }
273
274  // nullSingleton.retainAll()
275
276  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
277  @CollectionSize.Require(absent = ZERO)
278  public void testRetainAll_containsNonNullWithNull() {
279    initCollectionWithNullElement();
280    expectReturnsTrue(disjoint);
281    expectContents();
282  }
283
284  // retainAll(null)
285
286  /*
287   * AbstractCollection fails the retainAll(null) test when the subject
288   * collection is empty, but we'd still like to test retainAll(null) when we
289   * can. We split the test into empty and non-empty cases. This allows us to
290   * suppress only the former.
291   */
292
293  @CollectionFeature.Require(SUPPORTS_REMOVE)
294  @CollectionSize.Require(ZERO)
295  public void testRetainAll_nullCollectionReferenceEmptySubject() {
296    try {
297      collection.retainAll(null);
298      // Returning successfully is not ideal, but tolerated.
299    } catch (NullPointerException expected) {
300    }
301  }
302
303  @CollectionFeature.Require(SUPPORTS_REMOVE)
304  @CollectionSize.Require(absent = ZERO)
305  public void testRetainAll_nullCollectionReferenceNonEmptySubject() {
306    try {
307      collection.retainAll(null);
308      fail("retainAll(null) should throw NullPointerException");
309    } catch (NullPointerException expected) {
310    }
311  }
312
313  private void expectReturnsTrue(Target target) {
314    String message
315        = Platform.format("retainAll(%s) should return true", target);
316    assertTrue(message, collection.retainAll(target.toRetain));
317  }
318
319  private void expectReturnsFalse(Target target) {
320    String message
321        = Platform.format("retainAll(%s) should return false", target);
322    assertFalse(message, collection.retainAll(target.toRetain));
323  }
324
325  private void expectThrows(Target target) {
326    try {
327      collection.retainAll(target.toRetain);
328      String message = Platform.format("retainAll(%s) should throw", target);
329      fail(message);
330    } catch (UnsupportedOperationException expected) {
331    }
332  }
333
334  private void expectReturnsFalseOrThrows(Target target) {
335    String message
336        = Platform.format("retainAll(%s) should return false or throw", target);
337    try {
338      assertFalse(message, collection.retainAll(target.toRetain));
339    } catch (UnsupportedOperationException tolerated) {
340    }
341  }
342}
343