1 /*
2  * Copyright (C) 2009 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;
18 
19 import com.google.common.collect.testing.features.CollectionFeature;
20 import com.google.common.collect.testing.features.CollectionSize;
21 import com.google.common.collect.testing.features.SetFeature;
22 
23 import junit.framework.Test;
24 import junit.framework.TestSuite;
25 
26 import java.io.Serializable;
27 import java.lang.reflect.Method;
28 import java.util.AbstractSet;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.EnumSet;
33 import java.util.HashSet;
34 import java.util.Iterator;
35 import java.util.LinkedHashSet;
36 import java.util.Set;
37 import java.util.SortedSet;
38 import java.util.TreeSet;
39 import java.util.concurrent.ConcurrentSkipListSet;
40 import java.util.concurrent.CopyOnWriteArraySet;
41 
42 /**
43  * Generates a test suite covering the {@link Set} implementations in the
44  * {@link java.util} package. Can be subclassed to specify tests that should
45  * be suppressed.
46  *
47  * @author Kevin Bourrillion
48  */
49 public class TestsForSetsInJavaUtil {
suite()50   public static Test suite() {
51     return new TestsForSetsInJavaUtil().allTests();
52   }
53 
allTests()54   public Test allTests() {
55     TestSuite suite = new TestSuite("java.util Sets");
56     suite.addTest(testsForEmptySet());
57     suite.addTest(testsForSingletonSet());
58     suite.addTest(testsForHashSet());
59     suite.addTest(testsForLinkedHashSet());
60     suite.addTest(testsForEnumSet());
61     suite.addTest(testsForTreeSetNatural());
62     suite.addTest(testsForTreeSetWithComparator());
63     suite.addTest(testsForCopyOnWriteArraySet());
64     suite.addTest(testsForUnmodifiableSet());
65     suite.addTest(testsForCheckedSet());
66     suite.addTest(testsForAbstractSet());
67     suite.addTest(testsForBadlyCollidingHashSet());
68     suite.addTest(testsForConcurrentSkipListSetNatural());
69     suite.addTest(testsForConcurrentSkipListSetWithComparator());
70 
71     return suite;
72   }
73 
suppressForEmptySet()74   protected Collection<Method> suppressForEmptySet() {
75     return Collections.emptySet();
76   }
suppressForSingletonSet()77   protected Collection<Method> suppressForSingletonSet() {
78     return Collections.emptySet();
79   }
suppressForHashSet()80   protected Collection<Method> suppressForHashSet() {
81     return Collections.emptySet();
82   }
suppressForLinkedHashSet()83   protected Collection<Method> suppressForLinkedHashSet() {
84     return Collections.emptySet();
85   }
suppressForEnumSet()86   protected Collection<Method> suppressForEnumSet() {
87     return Collections.emptySet();
88   }
suppressForTreeSetNatural()89   protected Collection<Method> suppressForTreeSetNatural() {
90     return Collections.emptySet();
91   }
suppressForTreeSetWithComparator()92   protected Collection<Method> suppressForTreeSetWithComparator() {
93     return Collections.emptySet();
94   }
suppressForCopyOnWriteArraySet()95   protected Collection<Method> suppressForCopyOnWriteArraySet() {
96     return Collections.emptySet();
97   }
suppressForUnmodifiableSet()98   protected Collection<Method> suppressForUnmodifiableSet() {
99     return Collections.emptySet();
100   }
suppressForCheckedSet()101   protected Collection<Method> suppressForCheckedSet() {
102     return Collections.emptySet();
103   }
suppressForAbstractSet()104   protected Collection<Method> suppressForAbstractSet() {
105     return Collections.emptySet();
106   }
suppressForConcurrentSkipListSetNatural()107   protected Collection<Method> suppressForConcurrentSkipListSetNatural() {
108     return Collections.emptySet();
109   }
suppressForConcurrentSkipListSetWithComparator()110   protected Collection<Method> suppressForConcurrentSkipListSetWithComparator() {
111     return Collections.emptySet();
112   }
113 
testsForEmptySet()114   public Test testsForEmptySet() {
115     return SetTestSuiteBuilder
116         .using(new TestStringSetGenerator() {
117             @Override public Set<String> create(String[] elements) {
118               return Collections.emptySet();
119             }
120           })
121         .named("emptySet")
122         .withFeatures(
123             CollectionFeature.SERIALIZABLE,
124             CollectionSize.ZERO)
125         .suppressing(suppressForEmptySet())
126         .createTestSuite();
127   }
128 
129   public Test testsForSingletonSet() {
130     return SetTestSuiteBuilder
131         .using(new TestStringSetGenerator() {
132             @Override public Set<String> create(String[] elements) {
133               return Collections.singleton(elements[0]);
134             }
135           })
136         .named("singleton")
137         .withFeatures(
138             CollectionFeature.SERIALIZABLE,
139             CollectionFeature.ALLOWS_NULL_VALUES,
140             CollectionSize.ONE)
141         .suppressing(suppressForSingletonSet())
142         .createTestSuite();
143   }
144 
145   public Test testsForHashSet() {
146     return SetTestSuiteBuilder
147         .using(new TestStringSetGenerator() {
148             @Override public Set<String> create(String[] elements) {
149               return new HashSet<String>(MinimalCollection.of(elements));
150             }
151           })
152         .named("HashSet")
153         .withFeatures(
154             SetFeature.GENERAL_PURPOSE,
155             CollectionFeature.SERIALIZABLE,
156             CollectionFeature.ALLOWS_NULL_VALUES,
157             CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
158             CollectionSize.ANY)
159         .suppressing(suppressForHashSet())
160         .createTestSuite();
161   }
162 
163   public Test testsForLinkedHashSet() {
164     return SetTestSuiteBuilder
165         .using(new TestStringSetGenerator() {
166             @Override public Set<String> create(String[] elements) {
167               return new LinkedHashSet<String>(MinimalCollection.of(elements));
168             }
169           })
170         .named("LinkedHashSet")
171         .withFeatures(
172             SetFeature.GENERAL_PURPOSE,
173             CollectionFeature.SERIALIZABLE,
174             CollectionFeature.ALLOWS_NULL_VALUES,
175             CollectionFeature.KNOWN_ORDER,
176             CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
177             CollectionSize.ANY)
178         .suppressing(suppressForLinkedHashSet())
179         .createTestSuite();
180   }
181 
182   public Test testsForEnumSet() {
183     return SetTestSuiteBuilder
184         .using(new TestEnumSetGenerator() {
185             @Override public Set<AnEnum> create(AnEnum[] elements) {
186               return (elements.length == 0)
187                   ? EnumSet.noneOf(AnEnum.class)
188                   : EnumSet.copyOf(MinimalCollection.of(elements));
189             }
190           })
191         .named("EnumSet")
192         .withFeatures(
193             SetFeature.GENERAL_PURPOSE,
194             CollectionFeature.SERIALIZABLE,
195             CollectionFeature.KNOWN_ORDER,
196             CollectionFeature.RESTRICTS_ELEMENTS,
197             CollectionSize.ANY)
198         .suppressing(suppressForEnumSet())
199         .createTestSuite();
200   }
201 
202   public Test testsForTreeSetNatural() {
203     return NavigableSetTestSuiteBuilder
204         .using(new TestStringSortedSetGenerator() {
205             @Override public SortedSet<String> create(String[] elements) {
206               return new TreeSet<String>(MinimalCollection.of(elements));
207             }
208           })
209         .named("TreeSet, natural")
210         .withFeatures(
211             SetFeature.GENERAL_PURPOSE,
212             CollectionFeature.SERIALIZABLE,
213             CollectionFeature.KNOWN_ORDER,
214             CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
215             CollectionSize.ANY)
216         .suppressing(suppressForTreeSetNatural())
217         .createTestSuite();
218   }
219 
220   public Test testsForTreeSetWithComparator() {
221     return NavigableSetTestSuiteBuilder
222         .using(new TestStringSortedSetGenerator() {
223             @Override public SortedSet<String> create(String[] elements) {
224               SortedSet<String> set
225                   = new TreeSet<String>(arbitraryNullFriendlyComparator());
226               Collections.addAll(set, elements);
227               return set;
228             }
229           })
230         .named("TreeSet, with comparator")
231         .withFeatures(
232             SetFeature.GENERAL_PURPOSE,
233             CollectionFeature.SERIALIZABLE,
234             CollectionFeature.ALLOWS_NULL_VALUES,
235             CollectionFeature.KNOWN_ORDER,
236             CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
237             CollectionSize.ANY)
238         .suppressing(suppressForTreeSetWithComparator())
239         .createTestSuite();
240   }
241 
242   public Test testsForCopyOnWriteArraySet() {
243     return SetTestSuiteBuilder
244         .using(new TestStringSetGenerator() {
245             @Override public Set<String> create(String[] elements) {
246               return new CopyOnWriteArraySet<String>(
247                   MinimalCollection.of(elements));
248             }
249           })
250         .named("CopyOnWriteArraySet")
251         .withFeatures(
252             CollectionFeature.SUPPORTS_ADD,
253             CollectionFeature.SUPPORTS_REMOVE,
254             CollectionFeature.SERIALIZABLE,
255             CollectionFeature.ALLOWS_NULL_VALUES,
256             CollectionFeature.KNOWN_ORDER,
257             CollectionSize.ANY)
258         .suppressing(suppressForCopyOnWriteArraySet())
259         .createTestSuite();
260   }
261 
262   public Test testsForUnmodifiableSet() {
263     return SetTestSuiteBuilder
264         .using(new TestStringSetGenerator() {
265             @Override public Set<String> create(String[] elements) {
266               Set<String> innerSet = new HashSet<String>();
267               Collections.addAll(innerSet, elements);
268               return Collections.unmodifiableSet(innerSet);
269             }
270           })
271         .named("unmodifiableSet/HashSet")
272         .withFeatures(
273             CollectionFeature.NONE,
274             CollectionFeature.SERIALIZABLE,
275             CollectionFeature.ALLOWS_NULL_VALUES,
276             CollectionSize.ANY)
277         .suppressing(suppressForUnmodifiableSet())
278         .createTestSuite();
279   }
280 
281   public Test testsForCheckedSet() {
282     return SetTestSuiteBuilder
283         .using(new TestStringSetGenerator() {
284             @Override public Set<String> create(String[] elements) {
285               Set<String> innerSet = new HashSet<String>();
286               Collections.addAll(innerSet, elements);
287               return Collections.checkedSet(innerSet, String.class);
288             }
289           })
290         .named("checkedSet/HashSet")
291         .withFeatures(
292             SetFeature.GENERAL_PURPOSE,
293             CollectionFeature.SERIALIZABLE,
294             CollectionFeature.ALLOWS_NULL_VALUES,
295             CollectionFeature.RESTRICTS_ELEMENTS,
296             CollectionSize.ANY)
297         .suppressing(suppressForCheckedSet())
298         .createTestSuite();
299   }
300 
301   public Test testsForAbstractSet() {
302     return SetTestSuiteBuilder
303         .using(new TestStringSetGenerator () {
304             @Override protected Set<String> create(String[] elements) {
305               final String[] deduped = dedupe(elements);
306               return new AbstractSet<String>() {
307                 @Override public int size() {
308                   return deduped.length;
309                 }
310                 @Override public Iterator<String> iterator() {
311                   return MinimalCollection.of(deduped).iterator();
312                 }
313               };
314             }
315           })
316         .named("AbstractSet")
317         .withFeatures(
318             CollectionFeature.NONE,
319             CollectionFeature.ALLOWS_NULL_VALUES,
320             CollectionFeature.KNOWN_ORDER, // in this case, anyway
321             CollectionSize.ANY)
322         .suppressing(suppressForAbstractSet())
323         .createTestSuite();
324   }
325 
326   public Test testsForBadlyCollidingHashSet() {
327     return SetTestSuiteBuilder
328         .using(new TestCollidingSetGenerator() {
329             @Override
330             public Set<Object> create(Object... elements) {
331               return new HashSet<Object>(MinimalCollection.of(elements));
332             }
333           })
334         .named("badly colliding HashSet")
335         .withFeatures(
336             SetFeature.GENERAL_PURPOSE,
337             CollectionFeature.ALLOWS_NULL_VALUES,
338             CollectionSize.SEVERAL)
339         .suppressing(suppressForHashSet())
340         .createTestSuite();
341   }
342 
343   public Test testsForConcurrentSkipListSetNatural() {
344     return SetTestSuiteBuilder
345         .using(new TestStringSortedSetGenerator() {
346             @Override public SortedSet<String> create(String[] elements) {
347               return new ConcurrentSkipListSet<String>(MinimalCollection.of(elements));
348             }
349           })
350         .named("ConcurrentSkipListSet, natural")
351         .withFeatures(
352             SetFeature.GENERAL_PURPOSE,
353             CollectionFeature.SERIALIZABLE,
354             CollectionFeature.KNOWN_ORDER,
355             CollectionSize.ANY)
356         .suppressing(suppressForConcurrentSkipListSetNatural())
357         .createTestSuite();
358   }
359 
360   public Test testsForConcurrentSkipListSetWithComparator() {
361     return SetTestSuiteBuilder
362         .using(new TestStringSortedSetGenerator() {
363             @Override public SortedSet<String> create(String[] elements) {
364               SortedSet<String> set
365                   = new ConcurrentSkipListSet<String>(arbitraryNullFriendlyComparator());
366               Collections.addAll(set, elements);
367               return set;
368             }
369           })
370         .named("ConcurrentSkipListSet, with comparator")
371         .withFeatures(
372             SetFeature.GENERAL_PURPOSE,
373             CollectionFeature.SERIALIZABLE,
374             CollectionFeature.KNOWN_ORDER,
375             CollectionSize.ANY)
376         .suppressing(suppressForConcurrentSkipListSetWithComparator())
377         .createTestSuite();
378   }
379 
380   private static String[] dedupe(String[] elements) {
381     Set<String> tmp = new LinkedHashSet<String>();
382     Collections.addAll(tmp, elements);
383     return tmp.toArray(new String[0]);
384   }
385 
386   static <T> Comparator<T> arbitraryNullFriendlyComparator() {
387     return new NullFriendlyComparator<T>();
388   }
389 
390   private static final class NullFriendlyComparator<T>
391       implements Comparator<T>, Serializable {
392     @Override
393     public int compare(T left, T right) {
394       return String.valueOf(left).compareTo(String.valueOf(right));
395     }
396   }
397 }
398