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