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