001/*
002 * Copyright (C) 2009 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.collect.testing;
018
019import static java.util.Collections.emptySet;
020import static java.util.Collections.singleton;
021import static java.util.Collections.unmodifiableSet;
022
023import com.google.common.annotations.GwtIncompatible;
024import com.google.common.collect.testing.features.CollectionFeature;
025import com.google.common.collect.testing.features.CollectionSize;
026import com.google.common.collect.testing.features.SetFeature;
027import java.io.Serializable;
028import java.lang.reflect.Method;
029import java.util.AbstractSet;
030import java.util.Collection;
031import java.util.Collections;
032import java.util.Comparator;
033import java.util.EnumSet;
034import java.util.HashSet;
035import java.util.Iterator;
036import java.util.LinkedHashSet;
037import java.util.Set;
038import java.util.SortedSet;
039import java.util.TreeSet;
040import java.util.concurrent.ConcurrentSkipListSet;
041import java.util.concurrent.CopyOnWriteArraySet;
042import junit.framework.Test;
043import junit.framework.TestSuite;
044
045/**
046 * Generates a test suite covering the {@link Set} implementations in the {@link java.util} package.
047 * Can be subclassed to specify tests that should be suppressed.
048 *
049 * @author Kevin Bourrillion
050 */
051@GwtIncompatible
052public class TestsForSetsInJavaUtil {
053  public static Test suite() {
054    return new TestsForSetsInJavaUtil().allTests();
055  }
056
057  public Test allTests() {
058    TestSuite suite = new TestSuite("java.util Sets");
059    suite.addTest(testsForEmptySet());
060    suite.addTest(testsForSingletonSet());
061    suite.addTest(testsForHashSet());
062    suite.addTest(testsForLinkedHashSet());
063    suite.addTest(testsForEnumSet());
064    suite.addTest(testsForTreeSetNatural());
065    suite.addTest(testsForTreeSetWithComparator());
066    suite.addTest(testsForCopyOnWriteArraySet());
067    suite.addTest(testsForUnmodifiableSet());
068    suite.addTest(testsForCheckedSet());
069    suite.addTest(testsForCheckedSortedSet());
070    suite.addTest(testsForAbstractSet());
071    suite.addTest(testsForBadlyCollidingHashSet());
072    suite.addTest(testsForConcurrentSkipListSetNatural());
073    suite.addTest(testsForConcurrentSkipListSetWithComparator());
074
075    return suite;
076  }
077
078  protected Collection<Method> suppressForEmptySet() {
079    return emptySet();
080  }
081
082  protected Collection<Method> suppressForSingletonSet() {
083    return emptySet();
084  }
085
086  protected Collection<Method> suppressForHashSet() {
087    return emptySet();
088  }
089
090  protected Collection<Method> suppressForLinkedHashSet() {
091    return emptySet();
092  }
093
094  protected Collection<Method> suppressForEnumSet() {
095    return emptySet();
096  }
097
098  protected Collection<Method> suppressForTreeSetNatural() {
099    return emptySet();
100  }
101
102  protected Collection<Method> suppressForTreeSetWithComparator() {
103    return emptySet();
104  }
105
106  protected Collection<Method> suppressForCopyOnWriteArraySet() {
107    return Collections.emptySet();
108  }
109
110  protected Collection<Method> suppressForUnmodifiableSet() {
111    return emptySet();
112  }
113
114  protected Collection<Method> suppressForCheckedSet() {
115    return emptySet();
116  }
117
118  protected Collection<Method> suppressForCheckedSortedSet() {
119    return emptySet();
120  }
121
122  protected Collection<Method> suppressForAbstractSet() {
123    return emptySet();
124  }
125
126  protected Collection<Method> suppressForConcurrentSkipListSetNatural() {
127    return emptySet();
128  }
129
130  protected Collection<Method> suppressForConcurrentSkipListSetWithComparator() {
131    return emptySet();
132  }
133
134  public Test testsForEmptySet() {
135    return SetTestSuiteBuilder.using(
136            new TestStringSetGenerator() {
137              @Override
138              public Set<String> create(String[] elements) {
139                return emptySet();
140              }
141            })
142        .named("emptySet")
143        .withFeatures(CollectionFeature.SERIALIZABLE, CollectionSize.ZERO)
144        .suppressing(suppressForEmptySet())
145        .createTestSuite();
146  }
147
148  public Test testsForSingletonSet() {
149    return SetTestSuiteBuilder.using(
150            new TestStringSetGenerator() {
151              @Override
152              public Set<String> create(String[] elements) {
153                return singleton(elements[0]);
154              }
155            })
156        .named("singleton")
157        .withFeatures(
158            CollectionFeature.SERIALIZABLE,
159            CollectionFeature.ALLOWS_NULL_VALUES,
160            CollectionSize.ONE)
161        .suppressing(suppressForSingletonSet())
162        .createTestSuite();
163  }
164
165  public Test testsForHashSet() {
166    return SetTestSuiteBuilder.using(
167            new TestStringSetGenerator() {
168              @Override
169              public Set<String> create(String[] elements) {
170                return new HashSet<>(MinimalCollection.of(elements));
171              }
172            })
173        .named("HashSet")
174        .withFeatures(
175            SetFeature.GENERAL_PURPOSE,
176            CollectionFeature.SERIALIZABLE,
177            CollectionFeature.ALLOWS_NULL_VALUES,
178            CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
179            CollectionSize.ANY)
180        .suppressing(suppressForHashSet())
181        .createTestSuite();
182  }
183
184  public Test testsForLinkedHashSet() {
185    return SetTestSuiteBuilder.using(
186            new TestStringSetGenerator() {
187              @Override
188              public Set<String> create(String[] elements) {
189                return new LinkedHashSet<>(MinimalCollection.of(elements));
190              }
191            })
192        .named("LinkedHashSet")
193        .withFeatures(
194            SetFeature.GENERAL_PURPOSE,
195            CollectionFeature.SERIALIZABLE,
196            CollectionFeature.ALLOWS_NULL_VALUES,
197            CollectionFeature.KNOWN_ORDER,
198            CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
199            CollectionSize.ANY)
200        .suppressing(suppressForLinkedHashSet())
201        .createTestSuite();
202  }
203
204  public Test testsForEnumSet() {
205    return SetTestSuiteBuilder.using(
206            new TestEnumSetGenerator() {
207              @Override
208              public Set<AnEnum> create(AnEnum[] elements) {
209                return (elements.length == 0)
210                    ? EnumSet.noneOf(AnEnum.class)
211                    : EnumSet.copyOf(MinimalCollection.of(elements));
212              }
213            })
214        .named("EnumSet")
215        .withFeatures(
216            SetFeature.GENERAL_PURPOSE,
217            CollectionFeature.SERIALIZABLE,
218            CollectionFeature.KNOWN_ORDER,
219            CollectionFeature.RESTRICTS_ELEMENTS,
220            CollectionSize.ANY)
221        .suppressing(suppressForEnumSet())
222        .createTestSuite();
223  }
224
225  public Test testsForTreeSetNatural() {
226    return NavigableSetTestSuiteBuilder.using(
227            new TestStringSortedSetGenerator() {
228              @Override
229              public SortedSet<String> create(String[] elements) {
230                return new TreeSet<>(MinimalCollection.of(elements));
231              }
232            })
233        .named("TreeSet, natural")
234        .withFeatures(
235            SetFeature.GENERAL_PURPOSE,
236            CollectionFeature.SERIALIZABLE,
237            CollectionFeature.KNOWN_ORDER,
238            CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
239            CollectionSize.ANY)
240        .suppressing(suppressForTreeSetNatural())
241        .createTestSuite();
242  }
243
244  public Test testsForTreeSetWithComparator() {
245    return NavigableSetTestSuiteBuilder.using(
246            new TestStringSortedSetGenerator() {
247              @Override
248              public SortedSet<String> create(String[] elements) {
249                SortedSet<String> set = new TreeSet<>(arbitraryNullFriendlyComparator());
250                Collections.addAll(set, elements);
251                return set;
252              }
253            })
254        .named("TreeSet, with comparator")
255        .withFeatures(
256            SetFeature.GENERAL_PURPOSE,
257            CollectionFeature.SERIALIZABLE,
258            CollectionFeature.ALLOWS_NULL_VALUES,
259            CollectionFeature.KNOWN_ORDER,
260            CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
261            CollectionSize.ANY)
262        .suppressing(suppressForTreeSetWithComparator())
263        .createTestSuite();
264  }
265
266  public Test testsForCopyOnWriteArraySet() {
267    return SetTestSuiteBuilder.using(
268            new TestStringSetGenerator() {
269              @Override
270              public Set<String> create(String[] elements) {
271                return new CopyOnWriteArraySet<>(MinimalCollection.of(elements));
272              }
273            })
274        .named("CopyOnWriteArraySet")
275        .withFeatures(
276            CollectionFeature.SUPPORTS_ADD,
277            CollectionFeature.SUPPORTS_REMOVE,
278            CollectionFeature.SERIALIZABLE,
279            CollectionFeature.ALLOWS_NULL_VALUES,
280            CollectionFeature.KNOWN_ORDER,
281            CollectionSize.ANY)
282        .suppressing(suppressForCopyOnWriteArraySet())
283        .createTestSuite();
284  }
285
286  public Test testsForUnmodifiableSet() {
287    return SetTestSuiteBuilder.using(
288            new TestStringSetGenerator() {
289              @Override
290              public Set<String> create(String[] elements) {
291                Set<String> innerSet = new HashSet<>();
292                Collections.addAll(innerSet, elements);
293                return unmodifiableSet(innerSet);
294              }
295            })
296        .named("unmodifiableSet/HashSet")
297        .withFeatures(
298            CollectionFeature.NONE,
299            CollectionFeature.SERIALIZABLE,
300            CollectionFeature.ALLOWS_NULL_VALUES,
301            CollectionSize.ANY)
302        .suppressing(suppressForUnmodifiableSet())
303        .createTestSuite();
304  }
305
306  public Test testsForCheckedSet() {
307    return SetTestSuiteBuilder.using(
308            new TestStringSetGenerator() {
309              @Override
310              public Set<String> create(String[] elements) {
311                Set<String> innerSet = new HashSet<>();
312                Collections.addAll(innerSet, elements);
313                return Collections.checkedSet(innerSet, String.class);
314              }
315            })
316        .named("checkedSet/HashSet")
317        .withFeatures(
318            SetFeature.GENERAL_PURPOSE,
319            CollectionFeature.SERIALIZABLE,
320            CollectionFeature.ALLOWS_NULL_VALUES,
321            CollectionFeature.RESTRICTS_ELEMENTS,
322            CollectionSize.ANY)
323        .suppressing(suppressForCheckedSet())
324        .createTestSuite();
325  }
326
327  public Test testsForCheckedSortedSet() {
328    return SortedSetTestSuiteBuilder.using(
329            new TestStringSortedSetGenerator() {
330              @Override
331              public SortedSet<String> create(String[] elements) {
332                SortedSet<String> innerSet = new TreeSet<>();
333                Collections.addAll(innerSet, elements);
334                return Collections.checkedSortedSet(innerSet, String.class);
335              }
336            })
337        .named("checkedSortedSet/TreeSet, natural")
338        .withFeatures(
339            SetFeature.GENERAL_PURPOSE,
340            CollectionFeature.KNOWN_ORDER,
341            CollectionFeature.SERIALIZABLE,
342            CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
343            CollectionFeature.RESTRICTS_ELEMENTS,
344            CollectionSize.ANY)
345        .suppressing(suppressForCheckedSortedSet())
346        .createTestSuite();
347  }
348
349  public Test testsForAbstractSet() {
350    return SetTestSuiteBuilder.using(
351            new TestStringSetGenerator() {
352              @Override
353              protected Set<String> create(String[] elements) {
354                final String[] deduped = dedupe(elements);
355                return new AbstractSet<String>() {
356                  @Override
357                  public int size() {
358                    return deduped.length;
359                  }
360
361                  @Override
362                  public Iterator<String> iterator() {
363                    return MinimalCollection.of(deduped).iterator();
364                  }
365                };
366              }
367            })
368        .named("AbstractSet")
369        .withFeatures(
370            CollectionFeature.NONE,
371            CollectionFeature.ALLOWS_NULL_VALUES,
372            CollectionFeature.KNOWN_ORDER, // in this case, anyway
373            CollectionSize.ANY)
374        .suppressing(suppressForAbstractSet())
375        .createTestSuite();
376  }
377
378  public Test testsForBadlyCollidingHashSet() {
379    return SetTestSuiteBuilder.using(
380            new TestCollidingSetGenerator() {
381              @Override
382              public Set<Object> create(Object... elements) {
383                return new HashSet<>(MinimalCollection.of(elements));
384              }
385            })
386        .named("badly colliding HashSet")
387        .withFeatures(
388            SetFeature.GENERAL_PURPOSE,
389            CollectionFeature.ALLOWS_NULL_VALUES,
390            CollectionSize.SEVERAL)
391        .suppressing(suppressForHashSet())
392        .createTestSuite();
393  }
394
395  public Test testsForConcurrentSkipListSetNatural() {
396    return SetTestSuiteBuilder.using(
397            new TestStringSortedSetGenerator() {
398              @Override
399              public SortedSet<String> create(String[] elements) {
400                return new ConcurrentSkipListSet<>(MinimalCollection.of(elements));
401              }
402            })
403        .named("ConcurrentSkipListSet, natural")
404        .withFeatures(
405            SetFeature.GENERAL_PURPOSE,
406            CollectionFeature.SERIALIZABLE,
407            CollectionFeature.KNOWN_ORDER,
408            CollectionSize.ANY)
409        .suppressing(suppressForConcurrentSkipListSetNatural())
410        .createTestSuite();
411  }
412
413  public Test testsForConcurrentSkipListSetWithComparator() {
414    return SetTestSuiteBuilder.using(
415            new TestStringSortedSetGenerator() {
416              @Override
417              public SortedSet<String> create(String[] elements) {
418                SortedSet<String> set =
419                    new ConcurrentSkipListSet<>(arbitraryNullFriendlyComparator());
420                Collections.addAll(set, elements);
421                return set;
422              }
423            })
424        .named("ConcurrentSkipListSet, with comparator")
425        .withFeatures(
426            SetFeature.GENERAL_PURPOSE,
427            CollectionFeature.SERIALIZABLE,
428            CollectionFeature.KNOWN_ORDER,
429            CollectionSize.ANY)
430        .suppressing(suppressForConcurrentSkipListSetWithComparator())
431        .createTestSuite();
432  }
433
434  private static String[] dedupe(String[] elements) {
435    Set<String> tmp = new LinkedHashSet<>();
436    Collections.addAll(tmp, elements);
437    return tmp.toArray(new String[0]);
438  }
439
440  static <T> Comparator<T> arbitraryNullFriendlyComparator() {
441    return new NullFriendlyComparator<>();
442  }
443
444  private static final class NullFriendlyComparator<T> implements Comparator<T>, Serializable {
445    @Override
446    public int compare(T left, T right) {
447      return String.valueOf(left).compareTo(String.valueOf(right));
448    }
449  }
450}