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 17 package com.google.common.collect.testing; 18 19 import com.google.common.annotations.GwtIncompatible; 20 import com.google.common.collect.testing.features.CollectionFeature; 21 import com.google.common.collect.testing.features.CollectionSize; 22 import com.google.common.collect.testing.features.SetFeature; 23 import java.io.Serializable; 24 import java.lang.reflect.Method; 25 import java.util.AbstractSet; 26 import java.util.Collection; 27 import java.util.Collections; 28 import java.util.Comparator; 29 import java.util.EnumSet; 30 import java.util.HashSet; 31 import java.util.Iterator; 32 import java.util.LinkedHashSet; 33 import java.util.Set; 34 import java.util.SortedSet; 35 import java.util.TreeSet; 36 import java.util.concurrent.ConcurrentSkipListSet; 37 import java.util.concurrent.CopyOnWriteArraySet; 38 import junit.framework.Test; 39 import junit.framework.TestSuite; 40 41 /** 42 * Generates a test suite covering the {@link Set} implementations in the {@link java.util} package. 43 * Can be subclassed to specify tests that should be suppressed. 44 * 45 * @author Kevin Bourrillion 46 */ 47 @GwtIncompatible 48 public class TestsForSetsInJavaUtil { suite()49 public static Test suite() { 50 return new TestsForSetsInJavaUtil().allTests(); 51 } 52 allTests()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(testsForCheckedSortedSet()); 66 suite.addTest(testsForAbstractSet()); 67 suite.addTest(testsForBadlyCollidingHashSet()); 68 suite.addTest(testsForConcurrentSkipListSetNatural()); 69 suite.addTest(testsForConcurrentSkipListSetWithComparator()); 70 71 return suite; 72 } 73 suppressForEmptySet()74 protected Collection<Method> suppressForEmptySet() { 75 return Collections.emptySet(); 76 } 77 suppressForSingletonSet()78 protected Collection<Method> suppressForSingletonSet() { 79 return Collections.emptySet(); 80 } 81 suppressForHashSet()82 protected Collection<Method> suppressForHashSet() { 83 return Collections.emptySet(); 84 } 85 suppressForLinkedHashSet()86 protected Collection<Method> suppressForLinkedHashSet() { 87 return Collections.emptySet(); 88 } 89 suppressForEnumSet()90 protected Collection<Method> suppressForEnumSet() { 91 return Collections.emptySet(); 92 } 93 suppressForTreeSetNatural()94 protected Collection<Method> suppressForTreeSetNatural() { 95 return Collections.emptySet(); 96 } 97 suppressForTreeSetWithComparator()98 protected Collection<Method> suppressForTreeSetWithComparator() { 99 return Collections.emptySet(); 100 } 101 suppressForCopyOnWriteArraySet()102 protected Collection<Method> suppressForCopyOnWriteArraySet() { 103 return Collections.emptySet(); 104 } 105 suppressForUnmodifiableSet()106 protected Collection<Method> suppressForUnmodifiableSet() { 107 return Collections.emptySet(); 108 } 109 suppressForCheckedSet()110 protected Collection<Method> suppressForCheckedSet() { 111 return Collections.emptySet(); 112 } 113 suppressForCheckedSortedSet()114 protected Collection<Method> suppressForCheckedSortedSet() { 115 return Collections.emptySet(); 116 } 117 suppressForAbstractSet()118 protected Collection<Method> suppressForAbstractSet() { 119 return Collections.emptySet(); 120 } 121 suppressForConcurrentSkipListSetNatural()122 protected Collection<Method> suppressForConcurrentSkipListSetNatural() { 123 return Collections.emptySet(); 124 } 125 suppressForConcurrentSkipListSetWithComparator()126 protected Collection<Method> suppressForConcurrentSkipListSetWithComparator() { 127 return Collections.emptySet(); 128 } 129 testsForEmptySet()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 } 447