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