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