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}