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.ConcurrentSkipListSet;
40import 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 */
49public class TestsForSetsInJavaUtil {
50  public static Test suite() {
51    return new TestsForSetsInJavaUtil().allTests();
52  }
53
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
74  protected Collection<Method> suppressForEmptySet() {
75    return Collections.emptySet();
76  }
77  protected Collection<Method> suppressForSingletonSet() {
78    return Collections.emptySet();
79  }
80  protected Collection<Method> suppressForHashSet() {
81    return Collections.emptySet();
82  }
83  protected Collection<Method> suppressForLinkedHashSet() {
84    return Collections.emptySet();
85  }
86  protected Collection<Method> suppressForEnumSet() {
87    return Collections.emptySet();
88  }
89  protected Collection<Method> suppressForTreeSetNatural() {
90    return Collections.emptySet();
91  }
92  protected Collection<Method> suppressForTreeSetWithComparator() {
93    return Collections.emptySet();
94  }
95  protected Collection<Method> suppressForCopyOnWriteArraySet() {
96    return Collections.emptySet();
97  }
98  protected Collection<Method> suppressForUnmodifiableSet() {
99    return Collections.emptySet();
100  }
101  protected Collection<Method> suppressForCheckedSet() {
102    return Collections.emptySet();
103  }
104  protected Collection<Method> suppressForAbstractSet() {
105    return Collections.emptySet();
106  }
107  protected Collection<Method> suppressForConcurrentSkipListSetNatural() {
108    return Collections.emptySet();
109  }
110  protected Collection<Method> suppressForConcurrentSkipListSetWithComparator() {
111    return Collections.emptySet();
112  }
113
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