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.collect.testing.features.CollectionFeature; 20 import com.google.common.collect.testing.features.CollectionSize; 21 import com.google.common.collect.testing.features.SetFeature; 22 23 import junit.framework.Test; 24 import junit.framework.TestSuite; 25 26 import java.io.Serializable; 27 import java.lang.reflect.Method; 28 import java.util.AbstractSet; 29 import java.util.Collection; 30 import java.util.Collections; 31 import java.util.Comparator; 32 import java.util.EnumSet; 33 import java.util.HashSet; 34 import java.util.Iterator; 35 import java.util.LinkedHashSet; 36 import java.util.Set; 37 import java.util.SortedSet; 38 import java.util.TreeSet; 39 import java.util.concurrent.ConcurrentSkipListSet; 40 import java.util.concurrent.CopyOnWriteArraySet; 41 42 /** 43 * Generates a test suite covering the {@link Set} implementations in the 44 * {@link java.util} package. Can be subclassed to specify tests that should 45 * be suppressed. 46 * 47 * @author Kevin Bourrillion 48 */ 49 public class TestsForSetsInJavaUtil { suite()50 public static Test suite() { 51 return new TestsForSetsInJavaUtil().allTests(); 52 } 53 allTests()54 public Test allTests() { 55 TestSuite suite = new TestSuite("java.util Sets"); 56 suite.addTest(testsForEmptySet()); 57 suite.addTest(testsForSingletonSet()); 58 suite.addTest(testsForHashSet()); 59 suite.addTest(testsForLinkedHashSet()); 60 suite.addTest(testsForEnumSet()); 61 suite.addTest(testsForTreeSetNatural()); 62 suite.addTest(testsForTreeSetWithComparator()); 63 suite.addTest(testsForCopyOnWriteArraySet()); 64 suite.addTest(testsForUnmodifiableSet()); 65 suite.addTest(testsForCheckedSet()); 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 } suppressForSingletonSet()77 protected Collection<Method> suppressForSingletonSet() { 78 return Collections.emptySet(); 79 } suppressForHashSet()80 protected Collection<Method> suppressForHashSet() { 81 return Collections.emptySet(); 82 } suppressForLinkedHashSet()83 protected Collection<Method> suppressForLinkedHashSet() { 84 return Collections.emptySet(); 85 } suppressForEnumSet()86 protected Collection<Method> suppressForEnumSet() { 87 return Collections.emptySet(); 88 } suppressForTreeSetNatural()89 protected Collection<Method> suppressForTreeSetNatural() { 90 return Collections.emptySet(); 91 } suppressForTreeSetWithComparator()92 protected Collection<Method> suppressForTreeSetWithComparator() { 93 return Collections.emptySet(); 94 } suppressForCopyOnWriteArraySet()95 protected Collection<Method> suppressForCopyOnWriteArraySet() { 96 return Collections.emptySet(); 97 } suppressForUnmodifiableSet()98 protected Collection<Method> suppressForUnmodifiableSet() { 99 return Collections.emptySet(); 100 } suppressForCheckedSet()101 protected Collection<Method> suppressForCheckedSet() { 102 return Collections.emptySet(); 103 } suppressForAbstractSet()104 protected Collection<Method> suppressForAbstractSet() { 105 return Collections.emptySet(); 106 } suppressForConcurrentSkipListSetNatural()107 protected Collection<Method> suppressForConcurrentSkipListSetNatural() { 108 return Collections.emptySet(); 109 } suppressForConcurrentSkipListSetWithComparator()110 protected Collection<Method> suppressForConcurrentSkipListSetWithComparator() { 111 return Collections.emptySet(); 112 } 113 testsForEmptySet()114 public Test testsForEmptySet() { 115 return SetTestSuiteBuilder 116 .using(new TestStringSetGenerator() { 117 @Override public Set<String> create(String[] elements) { 118 return Collections.emptySet(); 119 } 120 }) 121 .named("emptySet") 122 .withFeatures( 123 CollectionFeature.SERIALIZABLE, 124 CollectionSize.ZERO) 125 .suppressing(suppressForEmptySet()) 126 .createTestSuite(); 127 } 128 129 public Test testsForSingletonSet() { 130 return SetTestSuiteBuilder 131 .using(new TestStringSetGenerator() { 132 @Override public Set<String> create(String[] elements) { 133 return Collections.singleton(elements[0]); 134 } 135 }) 136 .named("singleton") 137 .withFeatures( 138 CollectionFeature.SERIALIZABLE, 139 CollectionFeature.ALLOWS_NULL_VALUES, 140 CollectionSize.ONE) 141 .suppressing(suppressForSingletonSet()) 142 .createTestSuite(); 143 } 144 145 public Test testsForHashSet() { 146 return SetTestSuiteBuilder 147 .using(new TestStringSetGenerator() { 148 @Override public Set<String> create(String[] elements) { 149 return new HashSet<String>(MinimalCollection.of(elements)); 150 } 151 }) 152 .named("HashSet") 153 .withFeatures( 154 SetFeature.GENERAL_PURPOSE, 155 CollectionFeature.SERIALIZABLE, 156 CollectionFeature.ALLOWS_NULL_VALUES, 157 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 158 CollectionSize.ANY) 159 .suppressing(suppressForHashSet()) 160 .createTestSuite(); 161 } 162 163 public Test testsForLinkedHashSet() { 164 return SetTestSuiteBuilder 165 .using(new TestStringSetGenerator() { 166 @Override public Set<String> create(String[] elements) { 167 return new LinkedHashSet<String>(MinimalCollection.of(elements)); 168 } 169 }) 170 .named("LinkedHashSet") 171 .withFeatures( 172 SetFeature.GENERAL_PURPOSE, 173 CollectionFeature.SERIALIZABLE, 174 CollectionFeature.ALLOWS_NULL_VALUES, 175 CollectionFeature.KNOWN_ORDER, 176 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 177 CollectionSize.ANY) 178 .suppressing(suppressForLinkedHashSet()) 179 .createTestSuite(); 180 } 181 182 public Test testsForEnumSet() { 183 return SetTestSuiteBuilder 184 .using(new TestEnumSetGenerator() { 185 @Override public Set<AnEnum> create(AnEnum[] elements) { 186 return (elements.length == 0) 187 ? EnumSet.noneOf(AnEnum.class) 188 : EnumSet.copyOf(MinimalCollection.of(elements)); 189 } 190 }) 191 .named("EnumSet") 192 .withFeatures( 193 SetFeature.GENERAL_PURPOSE, 194 CollectionFeature.SERIALIZABLE, 195 CollectionFeature.KNOWN_ORDER, 196 CollectionFeature.RESTRICTS_ELEMENTS, 197 CollectionSize.ANY) 198 .suppressing(suppressForEnumSet()) 199 .createTestSuite(); 200 } 201 202 public Test testsForTreeSetNatural() { 203 return NavigableSetTestSuiteBuilder 204 .using(new TestStringSortedSetGenerator() { 205 @Override public SortedSet<String> create(String[] elements) { 206 return new TreeSet<String>(MinimalCollection.of(elements)); 207 } 208 }) 209 .named("TreeSet, natural") 210 .withFeatures( 211 SetFeature.GENERAL_PURPOSE, 212 CollectionFeature.SERIALIZABLE, 213 CollectionFeature.KNOWN_ORDER, 214 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 215 CollectionSize.ANY) 216 .suppressing(suppressForTreeSetNatural()) 217 .createTestSuite(); 218 } 219 220 public Test testsForTreeSetWithComparator() { 221 return NavigableSetTestSuiteBuilder 222 .using(new TestStringSortedSetGenerator() { 223 @Override public SortedSet<String> create(String[] elements) { 224 SortedSet<String> set 225 = new TreeSet<String>(arbitraryNullFriendlyComparator()); 226 Collections.addAll(set, elements); 227 return set; 228 } 229 }) 230 .named("TreeSet, with comparator") 231 .withFeatures( 232 SetFeature.GENERAL_PURPOSE, 233 CollectionFeature.SERIALIZABLE, 234 CollectionFeature.ALLOWS_NULL_VALUES, 235 CollectionFeature.KNOWN_ORDER, 236 CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION, 237 CollectionSize.ANY) 238 .suppressing(suppressForTreeSetWithComparator()) 239 .createTestSuite(); 240 } 241 242 public Test testsForCopyOnWriteArraySet() { 243 return SetTestSuiteBuilder 244 .using(new TestStringSetGenerator() { 245 @Override public Set<String> create(String[] elements) { 246 return new CopyOnWriteArraySet<String>( 247 MinimalCollection.of(elements)); 248 } 249 }) 250 .named("CopyOnWriteArraySet") 251 .withFeatures( 252 CollectionFeature.SUPPORTS_ADD, 253 CollectionFeature.SUPPORTS_REMOVE, 254 CollectionFeature.SERIALIZABLE, 255 CollectionFeature.ALLOWS_NULL_VALUES, 256 CollectionFeature.KNOWN_ORDER, 257 CollectionSize.ANY) 258 .suppressing(suppressForCopyOnWriteArraySet()) 259 .createTestSuite(); 260 } 261 262 public Test testsForUnmodifiableSet() { 263 return SetTestSuiteBuilder 264 .using(new TestStringSetGenerator() { 265 @Override public Set<String> create(String[] elements) { 266 Set<String> innerSet = new HashSet<String>(); 267 Collections.addAll(innerSet, elements); 268 return Collections.unmodifiableSet(innerSet); 269 } 270 }) 271 .named("unmodifiableSet/HashSet") 272 .withFeatures( 273 CollectionFeature.NONE, 274 CollectionFeature.SERIALIZABLE, 275 CollectionFeature.ALLOWS_NULL_VALUES, 276 CollectionSize.ANY) 277 .suppressing(suppressForUnmodifiableSet()) 278 .createTestSuite(); 279 } 280 281 public Test testsForCheckedSet() { 282 return SetTestSuiteBuilder 283 .using(new TestStringSetGenerator() { 284 @Override public Set<String> create(String[] elements) { 285 Set<String> innerSet = new HashSet<String>(); 286 Collections.addAll(innerSet, elements); 287 return Collections.checkedSet(innerSet, String.class); 288 } 289 }) 290 .named("checkedSet/HashSet") 291 .withFeatures( 292 SetFeature.GENERAL_PURPOSE, 293 CollectionFeature.SERIALIZABLE, 294 CollectionFeature.ALLOWS_NULL_VALUES, 295 CollectionFeature.RESTRICTS_ELEMENTS, 296 CollectionSize.ANY) 297 .suppressing(suppressForCheckedSet()) 298 .createTestSuite(); 299 } 300 301 public Test testsForAbstractSet() { 302 return SetTestSuiteBuilder 303 .using(new TestStringSetGenerator () { 304 @Override protected Set<String> create(String[] elements) { 305 final String[] deduped = dedupe(elements); 306 return new AbstractSet<String>() { 307 @Override public int size() { 308 return deduped.length; 309 } 310 @Override public Iterator<String> iterator() { 311 return MinimalCollection.of(deduped).iterator(); 312 } 313 }; 314 } 315 }) 316 .named("AbstractSet") 317 .withFeatures( 318 CollectionFeature.NONE, 319 CollectionFeature.ALLOWS_NULL_VALUES, 320 CollectionFeature.KNOWN_ORDER, // in this case, anyway 321 CollectionSize.ANY) 322 .suppressing(suppressForAbstractSet()) 323 .createTestSuite(); 324 } 325 326 public Test testsForBadlyCollidingHashSet() { 327 return SetTestSuiteBuilder 328 .using(new TestCollidingSetGenerator() { 329 @Override 330 public Set<Object> create(Object... elements) { 331 return new HashSet<Object>(MinimalCollection.of(elements)); 332 } 333 }) 334 .named("badly colliding HashSet") 335 .withFeatures( 336 SetFeature.GENERAL_PURPOSE, 337 CollectionFeature.ALLOWS_NULL_VALUES, 338 CollectionSize.SEVERAL) 339 .suppressing(suppressForHashSet()) 340 .createTestSuite(); 341 } 342 343 public Test testsForConcurrentSkipListSetNatural() { 344 return SetTestSuiteBuilder 345 .using(new TestStringSortedSetGenerator() { 346 @Override public SortedSet<String> create(String[] elements) { 347 return new ConcurrentSkipListSet<String>(MinimalCollection.of(elements)); 348 } 349 }) 350 .named("ConcurrentSkipListSet, natural") 351 .withFeatures( 352 SetFeature.GENERAL_PURPOSE, 353 CollectionFeature.SERIALIZABLE, 354 CollectionFeature.KNOWN_ORDER, 355 CollectionSize.ANY) 356 .suppressing(suppressForConcurrentSkipListSetNatural()) 357 .createTestSuite(); 358 } 359 360 public Test testsForConcurrentSkipListSetWithComparator() { 361 return SetTestSuiteBuilder 362 .using(new TestStringSortedSetGenerator() { 363 @Override public SortedSet<String> create(String[] elements) { 364 SortedSet<String> set 365 = new ConcurrentSkipListSet<String>(arbitraryNullFriendlyComparator()); 366 Collections.addAll(set, elements); 367 return set; 368 } 369 }) 370 .named("ConcurrentSkipListSet, with comparator") 371 .withFeatures( 372 SetFeature.GENERAL_PURPOSE, 373 CollectionFeature.SERIALIZABLE, 374 CollectionFeature.KNOWN_ORDER, 375 CollectionSize.ANY) 376 .suppressing(suppressForConcurrentSkipListSetWithComparator()) 377 .createTestSuite(); 378 } 379 380 private static String[] dedupe(String[] elements) { 381 Set<String> tmp = new LinkedHashSet<String>(); 382 Collections.addAll(tmp, elements); 383 return tmp.toArray(new String[0]); 384 } 385 386 static <T> Comparator<T> arbitraryNullFriendlyComparator() { 387 return new NullFriendlyComparator<T>(); 388 } 389 390 private static final class NullFriendlyComparator<T> 391 implements Comparator<T>, Serializable { 392 @Override 393 public int compare(T left, T right) { 394 return String.valueOf(left).compareTo(String.valueOf(right)); 395 } 396 } 397 } 398