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 static com.google.common.collect.testing.testers.CollectionSpliteratorTester.getSpliteratorNotImmutableCollectionAllowsAddMethod; 20 import static com.google.common.collect.testing.testers.CollectionSpliteratorTester.getSpliteratorNotImmutableCollectionAllowsRemoveMethod; 21 import static java.util.Arrays.asList; 22 23 import com.google.common.annotations.GwtIncompatible; 24 import com.google.common.collect.testing.features.CollectionFeature; 25 import com.google.common.collect.testing.features.CollectionSize; 26 import com.google.common.collect.testing.features.SetFeature; 27 import java.io.Serializable; 28 import java.lang.reflect.Method; 29 import java.util.AbstractSet; 30 import java.util.Collection; 31 import java.util.Collections; 32 import java.util.Comparator; 33 import java.util.EnumSet; 34 import java.util.HashSet; 35 import java.util.Iterator; 36 import java.util.LinkedHashSet; 37 import java.util.NavigableSet; 38 import java.util.Set; 39 import java.util.SortedSet; 40 import java.util.TreeSet; 41 import java.util.concurrent.ConcurrentSkipListSet; 42 import java.util.concurrent.CopyOnWriteArraySet; 43 import junit.framework.Test; 44 import junit.framework.TestSuite; 45 46 /** 47 * Generates a test suite covering the {@link Set} implementations in the {@link java.util} package. 48 * Can be subclassed to specify tests that should be suppressed. 49 * 50 * @author Kevin Bourrillion 51 */ 52 @GwtIncompatible 53 public class TestsForSetsInJavaUtil { suite()54 public static Test suite() { 55 return new TestsForSetsInJavaUtil().allTests(); 56 } 57 allTests()58 public Test allTests() { 59 TestSuite suite = new TestSuite("java.util Sets"); 60 suite.addTest(testsForCheckedNavigableSet()); 61 suite.addTest(testsForEmptySet()); 62 suite.addTest(testsForEmptyNavigableSet()); 63 suite.addTest(testsForEmptySortedSet()); 64 suite.addTest(testsForSingletonSet()); 65 suite.addTest(testsForHashSet()); 66 suite.addTest(testsForLinkedHashSet()); 67 suite.addTest(testsForEnumSet()); 68 suite.addTest(testsForSynchronizedNavigableSet()); 69 suite.addTest(testsForTreeSetNatural()); 70 suite.addTest(testsForTreeSetWithComparator()); 71 suite.addTest(testsForCopyOnWriteArraySet()); 72 suite.addTest(testsForUnmodifiableSet()); 73 suite.addTest(testsForUnmodifiableNavigableSet()); 74 suite.addTest(testsForCheckedSet()); 75 suite.addTest(testsForCheckedSortedSet()); 76 suite.addTest(testsForAbstractSet()); 77 suite.addTest(testsForBadlyCollidingHashSet()); 78 suite.addTest(testsForConcurrentSkipListSetNatural()); 79 suite.addTest(testsForConcurrentSkipListSetWithComparator()); 80 81 return suite; 82 } 83 suppressForCheckedNavigableSet()84 protected Collection<Method> suppressForCheckedNavigableSet() { 85 return Collections.emptySet(); 86 } 87 suppressForEmptySet()88 protected Collection<Method> suppressForEmptySet() { 89 return Collections.emptySet(); 90 } 91 suppressForEmptyNavigableSet()92 protected Collection<Method> suppressForEmptyNavigableSet() { 93 return Collections.emptySet(); 94 } 95 suppressForEmptySortedSet()96 protected Collection<Method> suppressForEmptySortedSet() { 97 return Collections.emptySet(); 98 } 99 suppressForSingletonSet()100 protected Collection<Method> suppressForSingletonSet() { 101 return Collections.emptySet(); 102 } 103 suppressForHashSet()104 protected Collection<Method> suppressForHashSet() { 105 return Collections.emptySet(); 106 } 107 suppressForLinkedHashSet()108 protected Collection<Method> suppressForLinkedHashSet() { 109 return Collections.emptySet(); 110 } 111 suppressForEnumSet()112 protected Collection<Method> suppressForEnumSet() { 113 return Collections.emptySet(); 114 } 115 suppressForSynchronizedNavigableSet()116 protected Collection<Method> suppressForSynchronizedNavigableSet() { 117 return Collections.emptySet(); 118 } 119 suppressForTreeSetNatural()120 protected Collection<Method> suppressForTreeSetNatural() { 121 return Collections.emptySet(); 122 } 123 suppressForTreeSetWithComparator()124 protected Collection<Method> suppressForTreeSetWithComparator() { 125 return Collections.emptySet(); 126 } 127 suppressForCopyOnWriteArraySet()128 protected Collection<Method> suppressForCopyOnWriteArraySet() { 129 return asList( 130 getSpliteratorNotImmutableCollectionAllowsAddMethod(), 131 getSpliteratorNotImmutableCollectionAllowsRemoveMethod()); 132 } 133 suppressForUnmodifiableSet()134 protected Collection<Method> suppressForUnmodifiableSet() { 135 return Collections.emptySet(); 136 } 137 suppressForUnmodifiableNavigableSet()138 protected Collection<Method> suppressForUnmodifiableNavigableSet() { 139 return Collections.emptySet(); 140 } 141 suppressForCheckedSet()142 protected Collection<Method> suppressForCheckedSet() { 143 return Collections.emptySet(); 144 } 145 suppressForCheckedSortedSet()146 protected Collection<Method> suppressForCheckedSortedSet() { 147 return Collections.emptySet(); 148 } 149 suppressForAbstractSet()150 protected Collection<Method> suppressForAbstractSet() { 151 return Collections.emptySet(); 152 } 153 suppressForConcurrentSkipListSetNatural()154 protected Collection<Method> suppressForConcurrentSkipListSetNatural() { 155 return Collections.emptySet(); 156 } 157 suppressForConcurrentSkipListSetWithComparator()158 protected Collection<Method> suppressForConcurrentSkipListSetWithComparator() { 159 return Collections.emptySet(); 160 } 161 testsForCheckedNavigableSet()162 public Test testsForCheckedNavigableSet() { 163 return SortedSetTestSuiteBuilder.using( 164 new TestStringSortedSetGenerator() { 165 @Override 166 public NavigableSet<String> create(String[] elements) { 167 NavigableSet<String> innerSet = new TreeSet<>(); 168 Collections.addAll(innerSet, elements); 169 return Collections.checkedNavigableSet(innerSet, String.class); 170 } 171 }) 172 .named("checkedNavigableSet/TreeSet, natural") 173 .withFeatures( 174 SetFeature.GENERAL_PURPOSE, 175 CollectionFeature.KNOWN_ORDER, 176 CollectionFeature.SERIALIZABLE, 177 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 178 CollectionFeature.RESTRICTS_ELEMENTS, 179 CollectionSize.ANY) 180 .suppressing(suppressForCheckedNavigableSet()) 181 .createTestSuite(); 182 } 183 184 public Test testsForEmptySet() { 185 return SetTestSuiteBuilder.using( 186 new TestStringSetGenerator() { 187 @Override 188 public Set<String> create(String[] elements) { 189 return Collections.emptySet(); 190 } 191 }) 192 .named("emptySet") 193 .withFeatures(CollectionFeature.SERIALIZABLE, CollectionSize.ZERO) 194 .suppressing(suppressForEmptySet()) 195 .createTestSuite(); 196 } 197 198 public Test testsForEmptyNavigableSet() { 199 return SetTestSuiteBuilder.using( 200 new TestStringSortedSetGenerator() { 201 @Override 202 public NavigableSet<String> create(String[] elements) { 203 return Collections.emptyNavigableSet(); 204 } 205 }) 206 .named("emptyNavigableSet") 207 .withFeatures(CollectionFeature.SERIALIZABLE, CollectionSize.ZERO) 208 .suppressing(suppressForEmptyNavigableSet()) 209 .createTestSuite(); 210 } 211 212 public Test testsForEmptySortedSet() { 213 return SetTestSuiteBuilder.using( 214 new TestStringSortedSetGenerator() { 215 @Override 216 public SortedSet<String> create(String[] elements) { 217 return Collections.emptySortedSet(); 218 } 219 }) 220 .named("emptySortedSet") 221 .withFeatures(CollectionFeature.SERIALIZABLE, CollectionSize.ZERO) 222 .suppressing(suppressForEmptySortedSet()) 223 .createTestSuite(); 224 } 225 226 public Test testsForSingletonSet() { 227 return SetTestSuiteBuilder.using( 228 new TestStringSetGenerator() { 229 @Override 230 public Set<String> create(String[] elements) { 231 return Collections.singleton(elements[0]); 232 } 233 }) 234 .named("singleton") 235 .withFeatures( 236 CollectionFeature.SERIALIZABLE, 237 CollectionFeature.ALLOWS_NULL_VALUES, 238 CollectionSize.ONE) 239 .suppressing(suppressForSingletonSet()) 240 .createTestSuite(); 241 } 242 243 public Test testsForHashSet() { 244 return SetTestSuiteBuilder.using( 245 new TestStringSetGenerator() { 246 @Override 247 public Set<String> create(String[] elements) { 248 return new HashSet<>(MinimalCollection.of(elements)); 249 } 250 }) 251 .named("HashSet") 252 .withFeatures( 253 SetFeature.GENERAL_PURPOSE, 254 CollectionFeature.SERIALIZABLE, 255 CollectionFeature.ALLOWS_NULL_VALUES, 256 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 257 CollectionSize.ANY) 258 .suppressing(suppressForHashSet()) 259 .createTestSuite(); 260 } 261 262 public Test testsForLinkedHashSet() { 263 return SetTestSuiteBuilder.using( 264 new TestStringSetGenerator() { 265 @Override 266 public Set<String> create(String[] elements) { 267 return new LinkedHashSet<>(MinimalCollection.of(elements)); 268 } 269 }) 270 .named("LinkedHashSet") 271 .withFeatures( 272 SetFeature.GENERAL_PURPOSE, 273 CollectionFeature.SERIALIZABLE, 274 CollectionFeature.ALLOWS_NULL_VALUES, 275 CollectionFeature.KNOWN_ORDER, 276 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 277 CollectionSize.ANY) 278 .suppressing(suppressForLinkedHashSet()) 279 .createTestSuite(); 280 } 281 282 public Test testsForEnumSet() { 283 return SetTestSuiteBuilder.using( 284 new TestEnumSetGenerator() { 285 @Override 286 public Set<AnEnum> create(AnEnum[] elements) { 287 return (elements.length == 0) 288 ? EnumSet.noneOf(AnEnum.class) 289 : EnumSet.copyOf(MinimalCollection.of(elements)); 290 } 291 }) 292 .named("EnumSet") 293 .withFeatures( 294 SetFeature.GENERAL_PURPOSE, 295 CollectionFeature.SERIALIZABLE, 296 CollectionFeature.KNOWN_ORDER, 297 CollectionFeature.RESTRICTS_ELEMENTS, 298 CollectionSize.ANY) 299 .suppressing(suppressForEnumSet()) 300 .createTestSuite(); 301 } 302 303 /** 304 * Tests regular NavigableSet behavior of synchronizedNavigableSet(treeSet); does not test the 305 * fact that it's synchronized. 306 */ 307 public Test testsForSynchronizedNavigableSet() { 308 return NavigableSetTestSuiteBuilder.using( 309 new TestStringSortedSetGenerator() { 310 @Override 311 public SortedSet<String> create(String[] elements) { 312 NavigableSet<String> delegate = new TreeSet<>(MinimalCollection.of(elements)); 313 return Collections.synchronizedNavigableSet(delegate); 314 } 315 }) 316 .named("synchronizedNavigableSet/TreeSet, natural") 317 .withFeatures( 318 SetFeature.GENERAL_PURPOSE, 319 CollectionFeature.SERIALIZABLE, 320 CollectionFeature.KNOWN_ORDER, 321 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 322 CollectionSize.ANY) 323 .suppressing(suppressForSynchronizedNavigableSet()) 324 .createTestSuite(); 325 } 326 327 public Test testsForTreeSetNatural() { 328 return NavigableSetTestSuiteBuilder.using( 329 new TestStringSortedSetGenerator() { 330 @Override 331 public SortedSet<String> create(String[] elements) { 332 return new TreeSet<>(MinimalCollection.of(elements)); 333 } 334 }) 335 .named("TreeSet, natural") 336 .withFeatures( 337 SetFeature.GENERAL_PURPOSE, 338 CollectionFeature.SERIALIZABLE, 339 CollectionFeature.KNOWN_ORDER, 340 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 341 CollectionSize.ANY) 342 .suppressing(suppressForTreeSetNatural()) 343 .createTestSuite(); 344 } 345 346 public Test testsForTreeSetWithComparator() { 347 return NavigableSetTestSuiteBuilder.using( 348 new TestStringSortedSetGenerator() { 349 @Override 350 public SortedSet<String> create(String[] elements) { 351 SortedSet<String> set = new TreeSet<>(arbitraryNullFriendlyComparator()); 352 Collections.addAll(set, elements); 353 return set; 354 } 355 }) 356 .named("TreeSet, with comparator") 357 .withFeatures( 358 SetFeature.GENERAL_PURPOSE, 359 CollectionFeature.SERIALIZABLE, 360 CollectionFeature.ALLOWS_NULL_VALUES, 361 CollectionFeature.KNOWN_ORDER, 362 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 363 CollectionSize.ANY) 364 .suppressing(suppressForTreeSetWithComparator()) 365 .createTestSuite(); 366 } 367 368 public Test testsForCopyOnWriteArraySet() { 369 return SetTestSuiteBuilder.using( 370 new TestStringSetGenerator() { 371 @Override 372 public Set<String> create(String[] elements) { 373 return new CopyOnWriteArraySet<>(MinimalCollection.of(elements)); 374 } 375 }) 376 .named("CopyOnWriteArraySet") 377 .withFeatures( 378 CollectionFeature.SUPPORTS_ADD, 379 CollectionFeature.SUPPORTS_REMOVE, 380 CollectionFeature.SERIALIZABLE, 381 CollectionFeature.ALLOWS_NULL_VALUES, 382 CollectionFeature.KNOWN_ORDER, 383 CollectionSize.ANY) 384 .suppressing(suppressForCopyOnWriteArraySet()) 385 .createTestSuite(); 386 } 387 388 public Test testsForUnmodifiableSet() { 389 return SetTestSuiteBuilder.using( 390 new TestStringSetGenerator() { 391 @Override 392 public Set<String> create(String[] elements) { 393 Set<String> innerSet = new HashSet<>(); 394 Collections.addAll(innerSet, elements); 395 return Collections.unmodifiableSet(innerSet); 396 } 397 }) 398 .named("unmodifiableSet/HashSet") 399 .withFeatures( 400 CollectionFeature.NONE, 401 CollectionFeature.SERIALIZABLE, 402 CollectionFeature.ALLOWS_NULL_VALUES, 403 CollectionSize.ANY) 404 .suppressing(suppressForUnmodifiableSet()) 405 .createTestSuite(); 406 } 407 408 public Test testsForUnmodifiableNavigableSet() { 409 return SetTestSuiteBuilder.using( 410 new TestStringSortedSetGenerator() { 411 @Override 412 public NavigableSet<String> create(String[] elements) { 413 NavigableSet<String> innerSet = new TreeSet<>(); 414 Collections.addAll(innerSet, elements); 415 return Collections.unmodifiableNavigableSet(innerSet); 416 } 417 }) 418 .named("unmodifiableNavigableSet/TreeSet, natural") 419 .withFeatures( 420 CollectionFeature.KNOWN_ORDER, 421 CollectionFeature.RESTRICTS_ELEMENTS, 422 CollectionFeature.SERIALIZABLE, 423 CollectionSize.ANY) 424 .suppressing(suppressForUnmodifiableNavigableSet()) 425 .createTestSuite(); 426 } 427 428 public Test testsForCheckedSet() { 429 return SetTestSuiteBuilder.using( 430 new TestStringSetGenerator() { 431 @Override 432 public Set<String> create(String[] elements) { 433 Set<String> innerSet = new HashSet<>(); 434 Collections.addAll(innerSet, elements); 435 return Collections.checkedSet(innerSet, String.class); 436 } 437 }) 438 .named("checkedSet/HashSet") 439 .withFeatures( 440 SetFeature.GENERAL_PURPOSE, 441 CollectionFeature.SERIALIZABLE, 442 CollectionFeature.ALLOWS_NULL_VALUES, 443 CollectionFeature.RESTRICTS_ELEMENTS, 444 CollectionSize.ANY) 445 .suppressing(suppressForCheckedSet()) 446 .createTestSuite(); 447 } 448 449 public Test testsForCheckedSortedSet() { 450 return SortedSetTestSuiteBuilder.using( 451 new TestStringSortedSetGenerator() { 452 @Override 453 public SortedSet<String> create(String[] elements) { 454 SortedSet<String> innerSet = new TreeSet<>(); 455 Collections.addAll(innerSet, elements); 456 return Collections.checkedSortedSet(innerSet, String.class); 457 } 458 }) 459 .named("checkedSortedSet/TreeSet, natural") 460 .withFeatures( 461 SetFeature.GENERAL_PURPOSE, 462 CollectionFeature.KNOWN_ORDER, 463 CollectionFeature.SERIALIZABLE, 464 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 465 CollectionFeature.RESTRICTS_ELEMENTS, 466 CollectionSize.ANY) 467 .suppressing(suppressForCheckedSortedSet()) 468 .createTestSuite(); 469 } 470 471 public Test testsForAbstractSet() { 472 return SetTestSuiteBuilder.using( 473 new TestStringSetGenerator() { 474 @Override 475 protected Set<String> create(String[] elements) { 476 final String[] deduped = dedupe(elements); 477 return new AbstractSet<String>() { 478 @Override 479 public int size() { 480 return deduped.length; 481 } 482 483 @Override 484 public Iterator<String> iterator() { 485 return MinimalCollection.of(deduped).iterator(); 486 } 487 }; 488 } 489 }) 490 .named("AbstractSet") 491 .withFeatures( 492 CollectionFeature.NONE, 493 CollectionFeature.ALLOWS_NULL_VALUES, 494 CollectionFeature.KNOWN_ORDER, // in this case, anyway 495 CollectionSize.ANY) 496 .suppressing(suppressForAbstractSet()) 497 .createTestSuite(); 498 } 499 500 public Test testsForBadlyCollidingHashSet() { 501 return SetTestSuiteBuilder.using( 502 new TestCollidingSetGenerator() { 503 @Override 504 public Set<Object> create(Object... elements) { 505 return new HashSet<>(MinimalCollection.of(elements)); 506 } 507 }) 508 .named("badly colliding HashSet") 509 .withFeatures( 510 SetFeature.GENERAL_PURPOSE, 511 CollectionFeature.ALLOWS_NULL_VALUES, 512 CollectionSize.SEVERAL) 513 .suppressing(suppressForHashSet()) 514 .createTestSuite(); 515 } 516 517 public Test testsForConcurrentSkipListSetNatural() { 518 return SetTestSuiteBuilder.using( 519 new TestStringSortedSetGenerator() { 520 @Override 521 public SortedSet<String> create(String[] elements) { 522 return new ConcurrentSkipListSet<>(MinimalCollection.of(elements)); 523 } 524 }) 525 .named("ConcurrentSkipListSet, natural") 526 .withFeatures( 527 SetFeature.GENERAL_PURPOSE, 528 CollectionFeature.SERIALIZABLE, 529 CollectionFeature.KNOWN_ORDER, 530 CollectionSize.ANY) 531 .suppressing(suppressForConcurrentSkipListSetNatural()) 532 .createTestSuite(); 533 } 534 535 public Test testsForConcurrentSkipListSetWithComparator() { 536 return SetTestSuiteBuilder.using( 537 new TestStringSortedSetGenerator() { 538 @Override 539 public SortedSet<String> create(String[] elements) { 540 SortedSet<String> set = 541 new ConcurrentSkipListSet<>(arbitraryNullFriendlyComparator()); 542 Collections.addAll(set, elements); 543 return set; 544 } 545 }) 546 .named("ConcurrentSkipListSet, with comparator") 547 .withFeatures( 548 SetFeature.GENERAL_PURPOSE, 549 CollectionFeature.SERIALIZABLE, 550 CollectionFeature.KNOWN_ORDER, 551 CollectionSize.ANY) 552 .suppressing(suppressForConcurrentSkipListSetWithComparator()) 553 .createTestSuite(); 554 } 555 556 private static String[] dedupe(String[] elements) { 557 Set<String> tmp = new LinkedHashSet<>(); 558 Collections.addAll(tmp, elements); 559 return tmp.toArray(new String[0]); 560 } 561 562 static <T> Comparator<T> arbitraryNullFriendlyComparator() { 563 return new NullFriendlyComparator<T>(); 564 } 565 566 private static final class NullFriendlyComparator<T> implements Comparator<T>, Serializable { 567 @Override 568 public int compare(T left, T right) { 569 return String.valueOf(left).compareTo(String.valueOf(right)); 570 } 571 } 572 } 573