CollectionRetainAllTester.java revision 3c77433663281544363151bf284b0240dfd22a42
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 * <p>This class is GWT compatible.
41 *
42 * @author Chris Povirk
43 */
44@SuppressWarnings("unchecked") // too many "unchecked generic array creations"
45@GwtCompatible
46public class CollectionRetainAllTester<E> extends AbstractCollectionTester<E> {
47
48  /**
49   * A collection of elements to retain, along with a description for use in
50   * failure messages.
51   */
52  private class Target {
53    private final Collection<E> toRetain;
54    private final String description;
55
56    private Target(Collection<E> toRetain, String description) {
57      this.toRetain = toRetain;
58      this.description = description;
59    }
60
61    @Override public String toString() {
62      return description;
63    }
64  }
65
66  private Target empty;
67  private Target disjoint;
68  private Target superset;
69  private Target nonEmptyProperSubset;
70  private Target sameElements;
71  private Target partialOverlap;
72  private Target containsDuplicates;
73  private Target nullSingleton;
74
75  @Override public void setUp() throws Exception {
76    super.setUp();
77
78    empty = new Target(emptyCollection(), "empty");
79    /*
80     * We test that nullSingleton.retainAll(disjointList) does NOT throw a
81     * NullPointerException when disjointList does not, so we can't use
82     * MinimalCollection, which throws NullPointerException on calls to
83     * contains(null).
84     */
85    List<E> disjointList = Arrays.asList(samples.e3, samples.e4);
86    disjoint
87        = new Target(disjointList, "disjoint");
88    superset
89        = new Target(MinimalCollection.of(
90            samples.e0, samples.e1, samples.e2, samples.e3, samples.e4),
91            "superset");
92    nonEmptyProperSubset
93        = new Target(MinimalCollection.of(samples.e1), "subset");
94    sameElements
95        = new Target(Arrays.asList(createSamplesArray()), "sameElements");
96    containsDuplicates = new Target(
97        MinimalCollection.of(samples.e0, samples.e0, samples.e3, samples.e3),
98        "containsDuplicates");
99    partialOverlap
100        = new Target(MinimalCollection.of(samples.e2, samples.e3),
101            "partialOverlap");
102    nullSingleton
103        = new Target(Collections.<E>singleton(null), "nullSingleton");
104  }
105
106  // retainAll(empty)
107
108  @CollectionFeature.Require(SUPPORTS_REMOVE)
109  @CollectionSize.Require(ZERO)
110  public void testRetainAll_emptyPreviouslyEmpty() {
111    expectReturnsFalse(empty);
112    expectUnchanged();
113  }
114
115  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
116  @CollectionSize.Require(ZERO)
117  public void testRetainAll_emptyPreviouslyEmptyUnsupported() {
118    expectReturnsFalseOrThrows(empty);
119    expectUnchanged();
120  }
121
122  @CollectionFeature.Require(SUPPORTS_REMOVE)
123  @CollectionSize.Require(absent = ZERO)
124  public void testRetainAll_emptyPreviouslyNonEmpty() {
125    expectReturnsTrue(empty);
126    expectContents();
127    expectMissing(samples.e0, samples.e1, samples.e2);
128  }
129
130  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
131  @CollectionSize.Require(absent = ZERO)
132  public void testRetainAll_emptyPreviouslyNonEmptyUnsupported() {
133    expectThrows(empty);
134    expectUnchanged();
135  }
136
137  // retainAll(disjoint)
138
139  @CollectionFeature.Require(SUPPORTS_REMOVE)
140  @CollectionSize.Require(ZERO)
141  public void testRetainAll_disjointPreviouslyEmpty() {
142    expectReturnsFalse(disjoint);
143    expectUnchanged();
144  }
145
146  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
147  @CollectionSize.Require(ZERO)
148  public void testRetainAll_disjointPreviouslyEmptyUnsupported() {
149    expectReturnsFalseOrThrows(disjoint);
150    expectUnchanged();
151  }
152
153  @CollectionFeature.Require(SUPPORTS_REMOVE)
154  @CollectionSize.Require(absent = ZERO)
155  public void testRetainAll_disjointPreviouslyNonEmpty() {
156    expectReturnsTrue(disjoint);
157    expectContents();
158    expectMissing(samples.e0, samples.e1, samples.e2);
159  }
160
161  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
162  @CollectionSize.Require(absent = ZERO)
163  public void testRetainAll_disjointPreviouslyNonEmptyUnsupported() {
164    expectThrows(disjoint);
165    expectUnchanged();
166  }
167
168  // retainAll(superset)
169
170  @CollectionFeature.Require(SUPPORTS_REMOVE)
171  public void testRetainAll_superset() {
172    expectReturnsFalse(superset);
173    expectUnchanged();
174  }
175
176  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
177  public void testRetainAll_supersetUnsupported() {
178    expectReturnsFalseOrThrows(superset);
179    expectUnchanged();
180  }
181
182  // retainAll(subset)
183
184  @CollectionFeature.Require(SUPPORTS_REMOVE)
185  @CollectionSize.Require(absent = {ZERO, ONE})
186  public void testRetainAll_subset() {
187    expectReturnsTrue(nonEmptyProperSubset);
188    expectContents(nonEmptyProperSubset.toRetain);
189  }
190
191  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
192  @CollectionSize.Require(absent = {ZERO, ONE})
193  public void testRetainAll_subsetUnsupported() {
194    expectThrows(nonEmptyProperSubset);
195    expectUnchanged();
196  }
197
198  // retainAll(sameElements)
199
200  @CollectionFeature.Require(SUPPORTS_REMOVE)
201  public void testRetainAll_sameElements() {
202    expectReturnsFalse(sameElements);
203    expectUnchanged();
204  }
205
206  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
207  public void testRetainAll_sameElementsUnsupported() {
208    expectReturnsFalseOrThrows(sameElements);
209    expectUnchanged();
210  }
211
212  // retainAll(partialOverlap)
213
214  @CollectionFeature.Require(SUPPORTS_REMOVE)
215  @CollectionSize.Require(absent = {ZERO, ONE})
216  public void testRetainAll_partialOverlap() {
217    expectReturnsTrue(partialOverlap);
218    expectContents(samples.e2);
219  }
220
221  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
222  @CollectionSize.Require(absent = {ZERO, ONE})
223  public void testRetainAll_partialOverlapUnsupported() {
224    expectThrows(partialOverlap);
225    expectUnchanged();
226  }
227
228  // retainAll(containsDuplicates)
229
230  @CollectionFeature.Require(SUPPORTS_REMOVE)
231  @CollectionSize.Require(ONE)
232  public void testRetainAll_containsDuplicatesSizeOne() {
233    expectReturnsFalse(containsDuplicates);
234    expectContents(samples.e0);
235  }
236
237  @CollectionFeature.Require(SUPPORTS_REMOVE)
238  @CollectionSize.Require(absent = {ZERO, ONE})
239  public void testRetainAll_containsDuplicatesSizeSeveral() {
240    expectReturnsTrue(containsDuplicates);
241    expectContents(samples.e0);
242  }
243
244  // retainAll(nullSingleton)
245
246  @CollectionFeature.Require(SUPPORTS_REMOVE)
247  @CollectionSize.Require(ZERO)
248  public void testRetainAll_nullSingletonPreviouslyEmpty() {
249    expectReturnsFalse(nullSingleton);
250    expectUnchanged();
251  }
252
253  @CollectionFeature.Require(SUPPORTS_REMOVE)
254  @CollectionSize.Require(absent = ZERO)
255  public void testRetainAll_nullSingletonPreviouslyNonEmpty() {
256    expectReturnsTrue(nullSingleton);
257    expectContents();
258  }
259
260  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
261  @CollectionSize.Require(ONE)
262  public void testRetainAll_nullSingletonPreviouslySingletonWithNull() {
263    initCollectionWithNullElement();
264    expectReturnsFalse(nullSingleton);
265    expectContents(createArrayWithNullElement());
266  }
267
268  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
269  @CollectionSize.Require(absent = {ZERO, ONE})
270  public void testRetainAll_nullSingletonPreviouslySeveralWithNull() {
271    initCollectionWithNullElement();
272    expectReturnsTrue(nullSingleton);
273    expectContents(nullSingleton.toRetain);
274  }
275
276  // nullSingleton.retainAll()
277
278  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
279  @CollectionSize.Require(absent = ZERO)
280  public void testRetainAll_containsNonNullWithNull() {
281    initCollectionWithNullElement();
282    expectReturnsTrue(disjoint);
283    expectContents();
284  }
285
286  // retainAll(null)
287
288  /*
289   * AbstractCollection fails the retainAll(null) test when the subject
290   * collection is empty, but we'd still like to test retainAll(null) when we
291   * can. We split the test into empty and non-empty cases. This allows us to
292   * suppress only the former.
293   */
294
295  @CollectionFeature.Require(SUPPORTS_REMOVE)
296  @CollectionSize.Require(ZERO)
297  public void testRetainAll_nullCollectionReferenceEmptySubject() {
298    try {
299      collection.retainAll(null);
300      // Returning successfully is not ideal, but tolerated.
301    } catch (NullPointerException expected) {
302    }
303  }
304
305  @CollectionFeature.Require(SUPPORTS_REMOVE)
306  @CollectionSize.Require(absent = ZERO)
307  public void testRetainAll_nullCollectionReferenceNonEmptySubject() {
308    try {
309      collection.retainAll(null);
310      fail("retainAll(null) should throw NullPointerException");
311    } catch (NullPointerException expected) {
312    }
313  }
314
315  private void expectReturnsTrue(Target target) {
316    String message
317        = Platform.format("retainAll(%s) should return true", target);
318    assertTrue(message, collection.retainAll(target.toRetain));
319  }
320
321  private void expectReturnsFalse(Target target) {
322    String message
323        = Platform.format("retainAll(%s) should return false", target);
324    assertFalse(message, collection.retainAll(target.toRetain));
325  }
326
327  private void expectThrows(Target target) {
328    try {
329      collection.retainAll(target.toRetain);
330      String message = Platform.format("retainAll(%s) should throw", target);
331      fail(message);
332    } catch (UnsupportedOperationException expected) {
333    }
334  }
335
336  private void expectReturnsFalseOrThrows(Target target) {
337    String message
338        = Platform.format("retainAll(%s) should return false or throw", target);
339    try {
340      assertFalse(message, collection.retainAll(target.toRetain));
341    } catch (UnsupportedOperationException tolerated) {
342    }
343  }
344}
345