1 /* 2 * Copyright (C) 2007 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; 18 19 import static com.google.common.collect.Iterables.unmodifiableIterable; 20 import static com.google.common.collect.Sets.newEnumSet; 21 import static com.google.common.collect.Sets.newHashSet; 22 import static com.google.common.collect.Sets.newLinkedHashSet; 23 import static com.google.common.collect.Sets.powerSet; 24 import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE; 25 import static com.google.common.collect.testing.testers.CollectionIteratorTester.getIteratorKnownOrderRemoveSupportedMethod; 26 import static java.io.ObjectStreamConstants.TC_REFERENCE; 27 import static java.io.ObjectStreamConstants.baseWireHandle; 28 import static java.util.Collections.emptySet; 29 import static java.util.Collections.singleton; 30 import static org.truth0.Truth.ASSERT; 31 32 import com.google.common.annotations.GwtCompatible; 33 import com.google.common.annotations.GwtIncompatible; 34 import com.google.common.collect.testing.AnEnum; 35 import com.google.common.collect.testing.IteratorTester; 36 import com.google.common.collect.testing.MinimalIterable; 37 import com.google.common.collect.testing.SetTestSuiteBuilder; 38 import com.google.common.collect.testing.TestEnumSetGenerator; 39 import com.google.common.collect.testing.TestStringSetGenerator; 40 import com.google.common.collect.testing.features.CollectionFeature; 41 import com.google.common.collect.testing.features.CollectionSize; 42 import com.google.common.collect.testing.features.SetFeature; 43 import com.google.common.testing.EqualsTester; 44 import com.google.common.testing.NullPointerTester; 45 import com.google.common.testing.SerializableTester; 46 47 import junit.framework.Test; 48 import junit.framework.TestCase; 49 import junit.framework.TestSuite; 50 51 import java.io.ByteArrayInputStream; 52 import java.io.ByteArrayOutputStream; 53 import java.io.IOException; 54 import java.io.ObjectInputStream; 55 import java.io.ObjectOutputStream; 56 import java.io.Serializable; 57 import java.nio.ByteBuffer; 58 import java.util.ArrayList; 59 import java.util.Arrays; 60 import java.util.Collection; 61 import java.util.Collections; 62 import java.util.Comparator; 63 import java.util.EnumSet; 64 import java.util.HashMap; 65 import java.util.HashSet; 66 import java.util.Iterator; 67 import java.util.LinkedHashMap; 68 import java.util.LinkedHashSet; 69 import java.util.List; 70 import java.util.Map; 71 import java.util.NoSuchElementException; 72 import java.util.Set; 73 import java.util.SortedSet; 74 import java.util.TreeSet; 75 import java.util.concurrent.CopyOnWriteArraySet; 76 77 import javax.annotation.Nullable; 78 79 /** 80 * Unit test for {@code Sets}. 81 * 82 * @author Kevin Bourrillion 83 * @author Jared Levy 84 */ 85 @GwtCompatible(emulated = true) 86 public class SetsTest extends TestCase { 87 88 private static final IteratorTester.KnownOrder KNOWN_ORDER = 89 IteratorTester.KnownOrder.KNOWN_ORDER; 90 91 private static final Collection<Integer> EMPTY_COLLECTION 92 = Arrays.<Integer>asList(); 93 94 private static final Collection<Integer> SOME_COLLECTION 95 = Arrays.asList(0, 1, 1); 96 97 private static final Iterable<Integer> SOME_ITERABLE 98 = new Iterable<Integer>() { 99 @Override 100 public Iterator<Integer> iterator() { 101 return SOME_COLLECTION.iterator(); 102 } 103 }; 104 105 private static final List<Integer> LONGER_LIST 106 = Arrays.asList(8, 6, 7, 5, 3, 0, 9); 107 108 private static final Comparator<Integer> SOME_COMPARATOR 109 = Collections.reverseOrder(); 110 111 @GwtIncompatible("suite") suite()112 public static Test suite() { 113 TestSuite suite = new TestSuite(); 114 suite.addTestSuite(SetsTest.class); 115 116 suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() { 117 @Override protected Set<String> create(String[] elements) { 118 return Sets.newConcurrentHashSet(Arrays.asList(elements)); 119 } 120 }) 121 .named("Sets.newConcurrentHashSet") 122 .withFeatures(CollectionSize.ANY, SetFeature.GENERAL_PURPOSE) 123 .createTestSuite()); 124 125 suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() { 126 @Override protected Set<String> create(String[] elements) { 127 int size = elements.length; 128 // Remove last element, if size > 1 129 Set<String> set1 = (size > 1) 130 ? Sets.newHashSet( 131 Arrays.asList(elements).subList(0, size - 1)) 132 : Sets.newHashSet(elements); 133 // Remove first element, if size > 0 134 Set<String> set2 = (size > 0) 135 ? Sets.newHashSet( 136 Arrays.asList(elements).subList(1, size)) 137 : Sets.<String>newHashSet(); 138 return Sets.union(set1, set2); 139 } 140 }) 141 .named("Sets.union") 142 .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES) 143 .createTestSuite()); 144 145 suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() { 146 @Override protected Set<String> create(String[] elements) { 147 Set<String> set1 = Sets.newHashSet(elements); 148 set1.add(samples().e3); 149 Set<String> set2 = Sets.newHashSet(elements); 150 set2.add(samples().e4); 151 return Sets.intersection(set1, set2); 152 } 153 }) 154 .named("Sets.intersection") 155 .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES) 156 .createTestSuite()); 157 158 suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() { 159 @Override protected Set<String> create(String[] elements) { 160 Set<String> set1 = Sets.newHashSet(elements); 161 set1.add(samples().e3); 162 Set<String> set2 = Sets.newHashSet(samples().e3); 163 return Sets.difference(set1, set2); 164 } 165 }) 166 .named("Sets.difference") 167 .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES) 168 .createTestSuite()); 169 170 suite.addTest(SetTestSuiteBuilder.using(new TestEnumSetGenerator() { 171 @Override protected Set<AnEnum> create(AnEnum[] elements) { 172 AnEnum[] otherElements = new AnEnum[elements.length - 1]; 173 System.arraycopy( 174 elements, 1, otherElements, 0, otherElements.length); 175 return Sets.immutableEnumSet(elements[0], otherElements); 176 } 177 }) 178 .named("Sets.immutableEnumSet") 179 .withFeatures(CollectionSize.ONE, CollectionSize.SEVERAL, 180 CollectionFeature.ALLOWS_NULL_QUERIES) 181 .createTestSuite()); 182 183 suite.addTest(testsForFilter()); 184 suite.addTest(testsForFilterNoNulls()); 185 suite.addTest(testsForFilterFiltered()); 186 187 return suite; 188 } 189 190 @GwtIncompatible("suite") testsForFilter()191 private static Test testsForFilter() { 192 return SetTestSuiteBuilder.using(new TestStringSetGenerator() { 193 @Override public Set<String> create(String[] elements) { 194 Set<String> unfiltered = Sets.newLinkedHashSet(); 195 unfiltered.add("yyy"); 196 Collections.addAll(unfiltered, elements); 197 unfiltered.add("zzz"); 198 return Sets.filter(unfiltered, Collections2Test.NOT_YYY_ZZZ); 199 } 200 }) 201 .named("Sets.filter") 202 .withFeatures( 203 CollectionFeature.SUPPORTS_ADD, 204 CollectionFeature.SUPPORTS_REMOVE, 205 CollectionFeature.ALLOWS_NULL_VALUES, 206 CollectionFeature.KNOWN_ORDER, 207 CollectionSize.ANY) 208 .suppressing(getIteratorKnownOrderRemoveSupportedMethod()) 209 .createTestSuite(); 210 } 211 212 @GwtIncompatible("suite") 213 private static Test testsForFilterNoNulls() { 214 TestSuite suite = new TestSuite(); 215 suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() { 216 @Override public Set<String> create(String[] elements) { 217 Set<String> unfiltered = Sets.newLinkedHashSet(); 218 unfiltered.add("yyy"); 219 unfiltered.addAll(ImmutableList.copyOf(elements)); 220 unfiltered.add("zzz"); 221 return Sets.filter(unfiltered, Collections2Test.LENGTH_1); 222 } 223 }) 224 .named("Sets.filter, no nulls") 225 .withFeatures(SetFeature.GENERAL_PURPOSE, CollectionFeature.KNOWN_ORDER, 226 CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES) 227 .suppressing(getIteratorKnownOrderRemoveSupportedMethod()) 228 .createTestSuite()); 229 230 return suite; 231 } 232 233 @GwtIncompatible("suite") 234 private static Test testsForFilterFiltered() { 235 return SetTestSuiteBuilder.using(new TestStringSetGenerator() { 236 @Override public Set<String> create(String[] elements) { 237 Set<String> unfiltered = Sets.newLinkedHashSet(); 238 unfiltered.add("yyy"); 239 unfiltered.addAll(ImmutableList.copyOf(elements)); 240 unfiltered.add("zzz"); 241 unfiltered.add("abc"); 242 return Sets.filter( 243 Sets.filter(unfiltered, Collections2Test.LENGTH_1), 244 Collections2Test.NOT_YYY_ZZZ); 245 } 246 }) 247 .named("Sets.filter, filtered input") 248 .withFeatures( 249 CollectionFeature.SUPPORTS_ADD, 250 CollectionFeature.SUPPORTS_REMOVE, 251 CollectionFeature.KNOWN_ORDER, 252 CollectionSize.ANY, 253 CollectionFeature.ALLOWS_NULL_QUERIES) 254 .suppressing(getIteratorKnownOrderRemoveSupportedMethod()) 255 .createTestSuite(); 256 } 257 258 private enum SomeEnum { A, B, C, D } 259 260 public void testImmutableEnumSet() { 261 Set<SomeEnum> units = Sets.immutableEnumSet(SomeEnum.D, SomeEnum.B); 262 263 ASSERT.that(units).has().exactly(SomeEnum.B, SomeEnum.D).inOrder(); 264 try { 265 units.remove(SomeEnum.B); 266 fail("ImmutableEnumSet should throw an exception on remove()"); 267 } catch (UnsupportedOperationException expected) {} 268 try { 269 units.add(SomeEnum.C); 270 fail("ImmutableEnumSet should throw an exception on add()"); 271 } catch (UnsupportedOperationException expected) {} 272 } 273 274 @GwtIncompatible("SerializableTester") 275 public void testImmutableEnumSet_serialized() { 276 Set<SomeEnum> units = Sets.immutableEnumSet(SomeEnum.D, SomeEnum.B); 277 278 ASSERT.that(units).has().exactly(SomeEnum.B, SomeEnum.D).inOrder(); 279 280 Set<SomeEnum> copy = SerializableTester.reserializeAndAssert(units); 281 assertTrue(copy instanceof ImmutableEnumSet); 282 } 283 284 public void testImmutableEnumSet_fromIterable() { 285 ImmutableSet<SomeEnum> none 286 = Sets.immutableEnumSet(MinimalIterable.<SomeEnum>of()); 287 ASSERT.that(none).isEmpty(); 288 289 ImmutableSet<SomeEnum> one 290 = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.B)); 291 ASSERT.that(one).has().item(SomeEnum.B); 292 293 ImmutableSet<SomeEnum> two 294 = Sets.immutableEnumSet(MinimalIterable.of(SomeEnum.D, SomeEnum.B)); 295 ASSERT.that(two).has().exactly(SomeEnum.B, SomeEnum.D).inOrder(); 296 } 297 298 @GwtIncompatible("java serialization not supported in GWT.") 299 public void testImmutableEnumSet_deserializationMakesDefensiveCopy() 300 throws Exception { 301 ImmutableSet<SomeEnum> original = 302 Sets.immutableEnumSet(SomeEnum.A, SomeEnum.B); 303 int handleOffset = 6; 304 byte[] serializedForm = serializeWithBackReference(original, handleOffset); 305 ObjectInputStream in = 306 new ObjectInputStream(new ByteArrayInputStream(serializedForm)); 307 308 ImmutableSet<?> deserialized = (ImmutableSet<?>) in.readObject(); 309 EnumSet<?> delegate = (EnumSet<?>) in.readObject(); 310 311 assertEquals(original, deserialized); 312 assertTrue(delegate.remove(SomeEnum.A)); 313 assertTrue(deserialized.contains(SomeEnum.A)); 314 } 315 316 @GwtIncompatible("java serialization not supported in GWT.") 317 private static byte[] serializeWithBackReference( 318 Object original, int handleOffset) throws IOException { 319 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 320 ObjectOutputStream out = new ObjectOutputStream(bos); 321 322 out.writeObject(original); 323 324 byte[] handle = toByteArray(baseWireHandle + handleOffset); 325 byte[] ref = prepended(TC_REFERENCE, handle); 326 bos.write(ref); 327 328 return bos.toByteArray(); 329 } 330 331 private static byte[] prepended(byte b, byte[] array) { 332 byte[] out = new byte[array.length + 1]; 333 out[0] = b; 334 System.arraycopy(array, 0, out, 1, array.length); 335 return out; 336 } 337 338 @GwtIncompatible("java.nio.ByteBuffer") 339 private static byte[] toByteArray(int h) { 340 return ByteBuffer.allocate(4).putInt(h).array(); 341 } 342 343 public void testNewEnumSet_empty() { 344 EnumSet<SomeEnum> copy = 345 newEnumSet(Collections.<SomeEnum>emptySet(), SomeEnum.class); 346 assertEquals(EnumSet.noneOf(SomeEnum.class), copy); 347 } 348 349 public void testNewEnumSet_enumSet() { 350 EnumSet<SomeEnum> set = EnumSet.of(SomeEnum.A, SomeEnum.D); 351 assertEquals(set, newEnumSet(set, SomeEnum.class)); 352 } 353 354 public void testNewEnumSet_collection() { 355 Set<SomeEnum> set = ImmutableSet.of(SomeEnum.B, SomeEnum.C); 356 assertEquals(set, newEnumSet(set, SomeEnum.class)); 357 } 358 359 public void testNewEnumSet_iterable() { 360 Set<SomeEnum> set = ImmutableSet.of(SomeEnum.A, SomeEnum.B, SomeEnum.C); 361 assertEquals(set, newEnumSet(unmodifiableIterable(set), SomeEnum.class)); 362 } 363 364 public void testNewHashSetEmpty() { 365 HashSet<Integer> set = Sets.newHashSet(); 366 verifySetContents(set, EMPTY_COLLECTION); 367 } 368 369 public void testNewHashSetVarArgs() { 370 HashSet<Integer> set = Sets.newHashSet(0, 1, 1); 371 verifySetContents(set, Arrays.asList(0, 1)); 372 } 373 374 public void testNewHashSetFromCollection() { 375 HashSet<Integer> set = Sets.newHashSet(SOME_COLLECTION); 376 verifySetContents(set, SOME_COLLECTION); 377 } 378 379 public void testNewHashSetFromIterable() { 380 HashSet<Integer> set = Sets.newHashSet(SOME_ITERABLE); 381 verifySetContents(set, SOME_ITERABLE); 382 } 383 384 public void testNewHashSetWithExpectedSizeSmall() { 385 HashSet<Integer> set = Sets.newHashSetWithExpectedSize(0); 386 verifySetContents(set, EMPTY_COLLECTION); 387 } 388 389 public void testNewHashSetWithExpectedSizeLarge() { 390 HashSet<Integer> set = Sets.newHashSetWithExpectedSize(1000); 391 verifySetContents(set, EMPTY_COLLECTION); 392 } 393 394 public void testNewHashSetFromIterator() { 395 HashSet<Integer> set = Sets.newHashSet(SOME_COLLECTION.iterator()); 396 verifySetContents(set, SOME_COLLECTION); 397 } 398 399 public void testNewConcurrentHashSetEmpty() { 400 Set<Integer> set = Sets.newConcurrentHashSet(); 401 verifySetContents(set, EMPTY_COLLECTION); 402 } 403 404 public void testNewConcurrentHashSetFromCollection() { 405 Set<Integer> set = Sets.newConcurrentHashSet(SOME_COLLECTION); 406 verifySetContents(set, SOME_COLLECTION); 407 } 408 409 public void testNewLinkedHashSetEmpty() { 410 LinkedHashSet<Integer> set = Sets.newLinkedHashSet(); 411 verifyLinkedHashSetContents(set, EMPTY_COLLECTION); 412 } 413 414 public void testNewLinkedHashSetFromCollection() { 415 LinkedHashSet<Integer> set = Sets.newLinkedHashSet(LONGER_LIST); 416 verifyLinkedHashSetContents(set, LONGER_LIST); 417 } 418 419 public void testNewLinkedHashSetFromIterable() { 420 LinkedHashSet<Integer> set = Sets.newLinkedHashSet(new Iterable<Integer>() 421 { 422 @Override 423 public Iterator<Integer> iterator() { 424 return LONGER_LIST.iterator(); 425 } 426 }); 427 verifyLinkedHashSetContents(set, LONGER_LIST); 428 } 429 430 public void testNewLinkedHashSetWithExpectedSizeSmall() { 431 LinkedHashSet<Integer> set = Sets.newLinkedHashSetWithExpectedSize(0); 432 verifySetContents(set, EMPTY_COLLECTION); 433 } 434 435 public void testNewLinkedHashSetWithExpectedSizeLarge() { 436 LinkedHashSet<Integer> set = Sets.newLinkedHashSetWithExpectedSize(1000); 437 verifySetContents(set, EMPTY_COLLECTION); 438 } 439 440 public void testNewTreeSetEmpty() { 441 TreeSet<Integer> set = Sets.newTreeSet(); 442 verifySortedSetContents(set, EMPTY_COLLECTION, null); 443 } 444 445 public void testNewTreeSetEmptyDerived() { 446 TreeSet<Derived> set = Sets.newTreeSet(); 447 assertTrue(set.isEmpty()); 448 set.add(new Derived("foo")); 449 set.add(new Derived("bar")); 450 ASSERT.that(set).has().exactly(new Derived("bar"), new Derived("foo")).inOrder(); 451 } 452 453 public void testNewTreeSetEmptyNonGeneric() { 454 TreeSet<LegacyComparable> set = Sets.newTreeSet(); 455 assertTrue(set.isEmpty()); 456 set.add(new LegacyComparable("foo")); 457 set.add(new LegacyComparable("bar")); 458 ASSERT.that(set).has() 459 .exactly(new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder(); 460 } 461 462 public void testNewTreeSetFromCollection() { 463 TreeSet<Integer> set = Sets.newTreeSet(SOME_COLLECTION); 464 verifySortedSetContents(set, SOME_COLLECTION, null); 465 } 466 467 public void testNewTreeSetFromIterable() { 468 TreeSet<Integer> set = Sets.newTreeSet(SOME_ITERABLE); 469 verifySortedSetContents(set, SOME_ITERABLE, null); 470 } 471 472 public void testNewTreeSetFromIterableDerived() { 473 Iterable<Derived> iterable = 474 Arrays.asList(new Derived("foo"), new Derived("bar")); 475 TreeSet<Derived> set = Sets.newTreeSet(iterable); 476 ASSERT.that(set).has().exactly( 477 new Derived("bar"), new Derived("foo")).inOrder(); 478 } 479 480 public void testNewTreeSetFromIterableNonGeneric() { 481 Iterable<LegacyComparable> iterable = 482 Arrays.asList(new LegacyComparable("foo"), new LegacyComparable("bar")); 483 TreeSet<LegacyComparable> set = Sets.newTreeSet(iterable); 484 ASSERT.that(set).has().exactly( 485 new LegacyComparable("bar"), new LegacyComparable("foo")).inOrder(); 486 } 487 488 public void testNewTreeSetEmptyWithComparator() { 489 TreeSet<Integer> set = Sets.newTreeSet(SOME_COMPARATOR); 490 verifySortedSetContents(set, EMPTY_COLLECTION, SOME_COMPARATOR); 491 } 492 493 public void testNewIdentityHashSet() { 494 Set<Integer> set = Sets.newIdentityHashSet(); 495 Integer value1 = new Integer(12357); 496 Integer value2 = new Integer(12357); 497 assertTrue(set.add(value1)); 498 assertFalse(set.contains(value2)); 499 assertTrue(set.contains(value1)); 500 assertTrue(set.add(value2)); 501 assertEquals(2, set.size()); 502 } 503 504 @GwtIncompatible("CopyOnWriteArraySet") 505 public void testNewCOWASEmpty() { 506 CopyOnWriteArraySet<Integer> set = Sets.newCopyOnWriteArraySet(); 507 verifySetContents(set, EMPTY_COLLECTION); 508 } 509 510 @GwtIncompatible("CopyOnWriteArraySet") 511 public void testNewCOWASFromIterable() { 512 CopyOnWriteArraySet<Integer> set = Sets.newCopyOnWriteArraySet(SOME_ITERABLE); 513 verifySetContents(set, SOME_COLLECTION); 514 } 515 516 public void testComplementOfEnumSet() { 517 Set<SomeEnum> units = EnumSet.of(SomeEnum.B, SomeEnum.D); 518 EnumSet<SomeEnum> otherUnits = Sets.complementOf(units); 519 verifySetContents(otherUnits, EnumSet.of(SomeEnum.A, SomeEnum.C)); 520 } 521 522 public void testComplementOfEnumSetWithType() { 523 Set<SomeEnum> units = EnumSet.of(SomeEnum.B, SomeEnum.D); 524 EnumSet<SomeEnum> otherUnits = Sets.complementOf(units, SomeEnum.class); 525 verifySetContents(otherUnits, EnumSet.of(SomeEnum.A, SomeEnum.C)); 526 } 527 528 public void testComplementOfRegularSet() { 529 Set<SomeEnum> units = Sets.newHashSet(SomeEnum.B, SomeEnum.D); 530 EnumSet<SomeEnum> otherUnits = Sets.complementOf(units); 531 verifySetContents(otherUnits, EnumSet.of(SomeEnum.A, SomeEnum.C)); 532 } 533 534 public void testComplementOfRegularSetWithType() { 535 Set<SomeEnum> units = Sets.newHashSet(SomeEnum.B, SomeEnum.D); 536 EnumSet<SomeEnum> otherUnits = Sets.complementOf(units, SomeEnum.class); 537 verifySetContents(otherUnits, EnumSet.of(SomeEnum.A, SomeEnum.C)); 538 } 539 540 public void testComplementOfEmptySet() { 541 Set<SomeEnum> noUnits = Collections.emptySet(); 542 EnumSet<SomeEnum> allUnits = Sets.complementOf(noUnits, SomeEnum.class); 543 verifySetContents(EnumSet.allOf(SomeEnum.class), allUnits); 544 } 545 546 public void testComplementOfFullSet() { 547 Set<SomeEnum> allUnits = Sets.newHashSet(SomeEnum.values()); 548 EnumSet<SomeEnum> noUnits = Sets.complementOf(allUnits, SomeEnum.class); 549 verifySetContents(noUnits, EnumSet.noneOf(SomeEnum.class)); 550 } 551 552 public void testComplementOfEmptyEnumSetWithoutType() { 553 Set<SomeEnum> noUnits = EnumSet.noneOf(SomeEnum.class); 554 EnumSet<SomeEnum> allUnits = Sets.complementOf(noUnits); 555 verifySetContents(allUnits, EnumSet.allOf(SomeEnum.class)); 556 } 557 558 public void testComplementOfEmptySetWithoutTypeDoesntWork() { 559 Set<SomeEnum> set = Collections.emptySet(); 560 try { 561 Sets.complementOf(set); 562 fail(); 563 } catch (IllegalArgumentException expected) {} 564 } 565 566 @GwtIncompatible("NullPointerTester") 567 public void testNullPointerExceptions() { 568 new NullPointerTester() 569 .setDefault(Enum.class, SomeEnum.A) 570 .setDefault(Class.class, SomeEnum.class) // for newEnumSet 571 .testAllPublicStaticMethods(Sets.class); 572 } 573 574 public void testNewSetFromMap() { 575 Set<Integer> set = Sets.newSetFromMap(new HashMap<Integer, Boolean>()); 576 set.addAll(SOME_COLLECTION); 577 verifySetContents(set, SOME_COLLECTION); 578 } 579 580 @GwtIncompatible("SerializableTester") 581 public void testNewSetFromMapSerialization() { 582 Set<Integer> set = 583 Sets.newSetFromMap(new LinkedHashMap<Integer, Boolean>()); 584 set.addAll(SOME_COLLECTION); 585 Set<Integer> copy = SerializableTester.reserializeAndAssert(set); 586 ASSERT.that(copy).has().exactly(0, 1).inOrder(); 587 } 588 589 public void testNewSetFromMapIllegal() { 590 Map<Integer, Boolean> map = new LinkedHashMap<Integer, Boolean>(); 591 map.put(2, true); 592 try { 593 Sets.newSetFromMap(map); 594 fail(); 595 } catch (IllegalArgumentException expected) {} 596 } 597 598 // TODO: the overwhelming number of suppressions below suggests that maybe 599 // it's not worth having a varargs form of this method at all... 600 601 /** 602 * The 0-ary cartesian product is a single empty list. 603 */ 604 @SuppressWarnings("unchecked") // varargs! 605 public void testCartesianProduct_zeroary() { 606 ASSERT.that(Sets.cartesianProduct()).has().exactly(list()); 607 } 608 609 /** 610 * A unary cartesian product is one list of size 1 for each element in the 611 * input set. 612 */ 613 @SuppressWarnings("unchecked") // varargs! 614 public void testCartesianProduct_unary() { 615 ASSERT.that(Sets.cartesianProduct(set(1, 2))).has().exactly(list(1), list(2)); 616 } 617 618 @SuppressWarnings("unchecked") // varargs! 619 public void testCartesianProduct_binary0x0() { 620 Set<Integer> mt = emptySet(); 621 assertEmpty(Sets.cartesianProduct(mt, mt)); 622 } 623 624 @SuppressWarnings("unchecked") // varargs! 625 public void testCartesianProduct_binary0x1() { 626 Set<Integer> mt = emptySet(); 627 assertEmpty(Sets.cartesianProduct(mt, set(1))); 628 } 629 630 @SuppressWarnings("unchecked") // varargs! 631 public void testCartesianProduct_binary1x0() { 632 Set<Integer> mt = emptySet(); 633 assertEmpty(Sets.cartesianProduct(set(1), mt)); 634 } 635 636 private static void assertEmpty(Set<? extends List<?>> set) { 637 assertTrue(set.isEmpty()); 638 assertEquals(0, set.size()); 639 assertFalse(set.iterator().hasNext()); 640 } 641 642 @SuppressWarnings("unchecked") // varargs! 643 public void testCartesianProduct_binary1x1() { 644 ASSERT.that(Sets.cartesianProduct(set(1), set(2))).has().item(list(1, 2)); 645 } 646 647 @SuppressWarnings("unchecked") // varargs! 648 public void testCartesianProduct_binary1x2() { 649 ASSERT.that(Sets.cartesianProduct(set(1), set(2, 3))) 650 .has().exactly(list(1, 2), list(1, 3)).inOrder(); 651 } 652 653 @SuppressWarnings("unchecked") // varargs! 654 public void testCartesianProduct_binary2x2() { 655 ASSERT.that(Sets.cartesianProduct(set(1, 2), set(3, 4))) 656 .has().exactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)).inOrder(); 657 } 658 659 @SuppressWarnings("unchecked") // varargs! 660 public void testCartesianProduct_2x2x2() { 661 ASSERT.that(Sets.cartesianProduct(set(0, 1), set(0, 1), set(0, 1))).has().exactly( 662 list(0, 0, 0), list(0, 0, 1), list(0, 1, 0), list(0, 1, 1), 663 list(1, 0, 0), list(1, 0, 1), list(1, 1, 0), list(1, 1, 1)).inOrder(); 664 } 665 666 @SuppressWarnings("unchecked") // varargs! 667 public void testCartesianProduct_contains() { 668 Set<List<Integer>> actual = Sets.cartesianProduct(set(1, 2), set(3, 4)); 669 assertTrue(actual.contains(list(1, 3))); 670 assertTrue(actual.contains(list(1, 4))); 671 assertTrue(actual.contains(list(2, 3))); 672 assertTrue(actual.contains(list(2, 4))); 673 assertFalse(actual.contains(list(3, 1))); 674 } 675 676 @SuppressWarnings("unchecked") // varargs! 677 public void testCartesianProduct_unrelatedTypes() { 678 Set<Integer> x = set(1, 2); 679 Set<String> y = set("3", "4"); 680 681 List<Object> exp1 = list((Object) 1, "3"); 682 List<Object> exp2 = list((Object) 1, "4"); 683 List<Object> exp3 = list((Object) 2, "3"); 684 List<Object> exp4 = list((Object) 2, "4"); 685 686 ASSERT.that(Sets.<Object>cartesianProduct(x, y)) 687 .has().exactly(exp1, exp2, exp3, exp4).inOrder(); 688 } 689 690 @SuppressWarnings("unchecked") // varargs! 691 public void testCartesianProductTooBig() { 692 Set<Integer> set = ContiguousSet.create(Range.closed(0, 10000), DiscreteDomain.integers()); 693 try { 694 Sets.cartesianProduct(set, set, set, set, set); 695 fail("Expected IAE"); 696 } catch (IllegalArgumentException expected) {} 697 } 698 699 @SuppressWarnings("unchecked") // varargs! 700 public void testCartesianProduct_hashCode() { 701 // Run through the same cartesian products we tested above 702 703 Set<List<Integer>> degenerate = Sets.cartesianProduct(); 704 checkHashCode(degenerate); 705 706 checkHashCode(Sets.cartesianProduct(set(1, 2))); 707 708 int num = Integer.MAX_VALUE / 3 * 2; // tickle overflow-related problems 709 checkHashCode(Sets.cartesianProduct(set(1, 2, num))); 710 711 Set<Integer> mt = emptySet(); 712 checkHashCode(Sets.cartesianProduct(mt, mt)); 713 checkHashCode(Sets.cartesianProduct(mt, set(num))); 714 checkHashCode(Sets.cartesianProduct(set(num), mt)); 715 checkHashCode(Sets.cartesianProduct(set(num), set(1))); 716 checkHashCode(Sets.cartesianProduct(set(1), set(2, num))); 717 checkHashCode(Sets.cartesianProduct(set(1, num), set(2, num - 1))); 718 checkHashCode(Sets.cartesianProduct( 719 set(1, num), set(2, num - 1), set(3, num + 1))); 720 721 // a bigger one 722 checkHashCode(Sets.cartesianProduct( 723 set(1, num, num + 1), set(2), set(3, num + 2), set(4, 5, 6, 7, 8))); 724 } 725 726 public void testPowerSetEmpty() { 727 ImmutableSet<Integer> elements = ImmutableSet.of(); 728 Set<Set<Integer>> powerSet = powerSet(elements); 729 assertEquals(1, powerSet.size()); 730 assertEquals(ImmutableSet.of(ImmutableSet.of()), powerSet); 731 assertEquals(0, powerSet.hashCode()); 732 } 733 734 public void testPowerSetContents() { 735 ImmutableSet<Integer> elements = ImmutableSet.of(1, 2, 3); 736 Set<Set<Integer>> powerSet = powerSet(elements); 737 assertEquals(8, powerSet.size()); 738 assertEquals(4 * 1 + 4 * 2 + 4 * 3, powerSet.hashCode()); 739 740 Set<Set<Integer>> expected = newHashSet(); 741 expected.add(ImmutableSet.<Integer>of()); 742 expected.add(ImmutableSet.of(1)); 743 expected.add(ImmutableSet.of(2)); 744 expected.add(ImmutableSet.of(3)); 745 expected.add(ImmutableSet.of(1, 2)); 746 expected.add(ImmutableSet.of(1, 3)); 747 expected.add(ImmutableSet.of(2, 3)); 748 expected.add(ImmutableSet.of(1, 2, 3)); 749 750 Set<Set<Integer>> almostPowerSet = newHashSet(expected); 751 almostPowerSet.remove(ImmutableSet.of(1, 2, 3)); 752 almostPowerSet.add(ImmutableSet.of(1, 2, 4)); 753 754 new EqualsTester() 755 .addEqualityGroup(expected, powerSet) 756 .addEqualityGroup(ImmutableSet.of(1, 2, 3)) 757 .addEqualityGroup(almostPowerSet) 758 .testEquals(); 759 760 for (Set<Integer> subset : expected) { 761 assertTrue(powerSet.contains(subset)); 762 } 763 assertFalse(powerSet.contains(ImmutableSet.of(1, 2, 4))); 764 assertFalse(powerSet.contains(singleton(null))); 765 assertFalse(powerSet.contains(null)); 766 assertFalse(powerSet.contains("notASet")); 767 } 768 769 public void testPowerSetIteration_manual() { 770 ImmutableSet<Integer> elements = ImmutableSet.of(1, 2, 3); 771 Set<Set<Integer>> powerSet = powerSet(elements); 772 // The API doesn't promise this iteration order, but it's convenient here. 773 Iterator<Set<Integer>> i = powerSet.iterator(); 774 assertEquals(ImmutableSet.of(), i.next()); 775 assertEquals(ImmutableSet.of(1), i.next()); 776 assertEquals(ImmutableSet.of(2), i.next()); 777 assertEquals(ImmutableSet.of(2, 1), i.next()); 778 assertEquals(ImmutableSet.of(3), i.next()); 779 assertEquals(ImmutableSet.of(3, 1), i.next()); 780 assertEquals(ImmutableSet.of(3, 2), i.next()); 781 assertEquals(ImmutableSet.of(3, 2, 1), i.next()); 782 assertFalse(i.hasNext()); 783 try { 784 i.next(); 785 fail(); 786 } catch (NoSuchElementException expected) { 787 } 788 } 789 790 @GwtIncompatible("too slow for GWT") 791 public void testPowerSetIteration_iteratorTester() { 792 ImmutableSet<Integer> elements = ImmutableSet.of(1, 2); 793 794 Set<Set<Integer>> expected = newLinkedHashSet(); 795 expected.add(ImmutableSet.<Integer>of()); 796 expected.add(ImmutableSet.of(1)); 797 expected.add(ImmutableSet.of(2)); 798 expected.add(ImmutableSet.of(1, 2)); 799 800 final Set<Set<Integer>> powerSet = powerSet(elements); 801 new IteratorTester<Set<Integer>>(6, UNMODIFIABLE, expected, KNOWN_ORDER) { 802 @Override protected Iterator<Set<Integer>> newTargetIterator() { 803 return powerSet.iterator(); 804 } 805 }.test(); 806 } 807 808 public void testPowerSetIteration_iteratorTester_fast() { 809 ImmutableSet<Integer> elements = ImmutableSet.of(1, 2); 810 811 Set<Set<Integer>> expected = newLinkedHashSet(); 812 expected.add(ImmutableSet.<Integer>of()); 813 expected.add(ImmutableSet.of(1)); 814 expected.add(ImmutableSet.of(2)); 815 expected.add(ImmutableSet.of(1, 2)); 816 817 final Set<Set<Integer>> powerSet = powerSet(elements); 818 new IteratorTester<Set<Integer>>(4, UNMODIFIABLE, expected, KNOWN_ORDER) { 819 @Override protected Iterator<Set<Integer>> newTargetIterator() { 820 return powerSet.iterator(); 821 } 822 }.test(); 823 } 824 825 public void testPowerSetSize() { 826 assertPowerSetSize(1); 827 assertPowerSetSize(2, 'a'); 828 assertPowerSetSize(4, 'a', 'b'); 829 assertPowerSetSize(8, 'a', 'b', 'c'); 830 assertPowerSetSize(16, 'a', 'b', 'd', 'e'); 831 assertPowerSetSize(1 << 30, 832 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 833 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', 834 '3', '4'); 835 } 836 837 public void testPowerSetCreationErrors() { 838 try { 839 powerSet(newHashSet('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 840 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 841 'y', 'z', '1', '2', '3', '4', '5')); 842 fail(); 843 } catch (IllegalArgumentException expected) { 844 } 845 846 try { 847 powerSet(singleton(null)); 848 fail(); 849 } catch (NullPointerException expected) { 850 } 851 } 852 853 public void testPowerSetEqualsAndHashCode_verifyAgainstHashSet() { 854 ImmutableList<Integer> allElements = ImmutableList.of(4233352, 3284593, 855 3794208, 3849533, 4013967, 2902658, 1886275, 2131109, 985872, 1843868); 856 for (int i = 0; i < allElements.size(); i++) { 857 Set<Integer> elements = newHashSet(allElements.subList(0, i)); 858 Set<Set<Integer>> powerSet1 = powerSet(elements); 859 Set<Set<Integer>> powerSet2 = powerSet(elements); 860 new EqualsTester() 861 .addEqualityGroup(powerSet1, powerSet2, toHashSets(powerSet1)) 862 .addEqualityGroup(ImmutableSet.of()) 863 .addEqualityGroup(ImmutableSet.of(9999999)) 864 .addEqualityGroup("notASet") 865 .testEquals(); 866 assertEquals(toHashSets(powerSet1).hashCode(), powerSet1.hashCode()); 867 } 868 } 869 870 /** 871 * Test that a hash code miscomputed by "input.hashCode() * tooFarValue / 2" 872 * is correct under our {@code hashCode} implementation. 873 */ 874 public void testPowerSetHashCode_inputHashCodeTimesTooFarValueIsZero() { 875 Set<Object> sumToEighthMaxIntElements = 876 newHashSet(objectWithHashCode(1 << 29), objectWithHashCode(0)); 877 assertPowerSetHashCode(1 << 30, sumToEighthMaxIntElements); 878 879 Set<Object> sumToQuarterMaxIntElements = 880 newHashSet(objectWithHashCode(1 << 30), objectWithHashCode(0)); 881 assertPowerSetHashCode(1 << 31, sumToQuarterMaxIntElements); 882 } 883 884 public void testPowerSetShowOff() { 885 Set<Object> zero = ImmutableSet.of(); 886 Set<Set<Object>> one = powerSet(zero); 887 Set<Set<Set<Object>>> two = powerSet(one); 888 Set<Set<Set<Set<Object>>>> four = powerSet(two); 889 Set<Set<Set<Set<Set<Object>>>>> sixteen = powerSet(four); 890 Set<Set<Set<Set<Set<Set<Object>>>>>> sixtyFiveThousandish = 891 powerSet(sixteen); 892 assertEquals(1 << 16, sixtyFiveThousandish.size()); 893 894 assertTrue(powerSet(makeSetOfZeroToTwentyNine()) 895 .contains(makeSetOfZeroToTwentyNine())); 896 assertFalse(powerSet(makeSetOfZeroToTwentyNine()) 897 .contains(ImmutableSet.of(30))); 898 } 899 900 private static Set<Integer> makeSetOfZeroToTwentyNine() { 901 // TODO: use Range once it's publicly available 902 Set<Integer> zeroToTwentyNine = newHashSet(); 903 for (int i = 0; i < 30; i++) { 904 zeroToTwentyNine.add(i); 905 } 906 return zeroToTwentyNine; 907 } 908 909 private static <E> Set<Set<E>> toHashSets(Set<Set<E>> powerSet) { 910 Set<Set<E>> result = newHashSet(); 911 for (Set<E> subset : powerSet) { 912 result.add(new HashSet<E>(subset)); 913 } 914 return result; 915 } 916 917 private static Object objectWithHashCode(final int hashCode) { 918 return new Object() { 919 @Override public int hashCode() { 920 return hashCode; 921 } 922 }; 923 } 924 925 private static void assertPowerSetHashCode(int expected, Set<?> elements) { 926 assertEquals(expected, powerSet(elements).hashCode()); 927 } 928 929 private static void assertPowerSetSize(int i, Object... elements) { 930 assertEquals(i, powerSet(newHashSet(elements)).size()); 931 } 932 933 private static void checkHashCode(Set<?> set) { 934 assertEquals(Sets.newHashSet(set).hashCode(), set.hashCode()); 935 } 936 937 private static <E> Set<E> set(E... elements) { 938 return ImmutableSet.copyOf(elements); 939 } 940 941 private static <E> List<E> list(E... elements) { 942 return ImmutableList.copyOf(elements); 943 } 944 945 /** 946 * Utility method to verify that the given LinkedHashSet is equal to and 947 * hashes identically to a set constructed with the elements in the given 948 * collection. Also verifies that the ordering in the set is the same 949 * as the ordering of the given contents. 950 */ 951 private static <E> void verifyLinkedHashSetContents( 952 LinkedHashSet<E> set, Collection<E> contents) { 953 assertEquals("LinkedHashSet should have preserved order for iteration", 954 new ArrayList<E>(set), new ArrayList<E>(contents)); 955 verifySetContents(set, contents); 956 } 957 958 /** 959 * Utility method to verify that the given SortedSet is equal to and 960 * hashes identically to a set constructed with the elements in the 961 * given iterable. Also verifies that the comparator is the same as the 962 * given comparator. 963 */ 964 private static <E> void verifySortedSetContents( 965 SortedSet<E> set, Iterable<E> iterable, 966 @Nullable Comparator<E> comparator) { 967 assertSame(comparator, set.comparator()); 968 verifySetContents(set, iterable); 969 } 970 971 /** 972 * Utility method that verifies that the given set is equal to and hashes 973 * identically to a set constructed with the elements in the given iterable. 974 */ 975 private static <E> void verifySetContents(Set<E> set, Iterable<E> contents) { 976 Set<E> expected = null; 977 if (contents instanceof Set) { 978 expected = (Set<E>) contents; 979 } else { 980 expected = new HashSet<E>(); 981 for (E element : contents) { 982 expected.add(element); 983 } 984 } 985 assertEquals(expected, set); 986 } 987 988 /** 989 * Simple base class to verify that we handle generics correctly. 990 */ 991 static class Base implements Comparable<Base>, Serializable { 992 private final String s; 993 994 public Base(String s) { 995 this.s = s; 996 } 997 998 @Override public int hashCode() { // delegate to 's' 999 return s.hashCode(); 1000 } 1001 1002 @Override public boolean equals(Object other) { 1003 if (other == null) { 1004 return false; 1005 } else if (other instanceof Base) { 1006 return s.equals(((Base) other).s); 1007 } else { 1008 return false; 1009 } 1010 } 1011 1012 @Override 1013 public int compareTo(Base o) { 1014 return s.compareTo(o.s); 1015 } 1016 1017 private static final long serialVersionUID = 0; 1018 } 1019 1020 /** 1021 * Simple derived class to verify that we handle generics correctly. 1022 */ 1023 static class Derived extends Base { 1024 public Derived(String s) { 1025 super(s); 1026 } 1027 1028 private static final long serialVersionUID = 0; 1029 } 1030 1031 void ensureNotDirectlyModifiable(SortedSet<Integer> unmod) { 1032 try { 1033 unmod.add(4); 1034 fail("UnsupportedOperationException expected"); 1035 } catch (UnsupportedOperationException expected) { 1036 } 1037 try { 1038 unmod.remove(4); 1039 fail("UnsupportedOperationException expected"); 1040 } catch (UnsupportedOperationException expected) { 1041 } 1042 try { 1043 unmod.addAll(Collections.singleton(4)); 1044 fail("UnsupportedOperationException expected"); 1045 } catch (UnsupportedOperationException expected) { 1046 } 1047 try { 1048 Iterator<Integer> iterator = unmod.iterator(); 1049 iterator.next(); 1050 iterator.remove(); 1051 fail("UnsupportedOperationException expected"); 1052 } catch (UnsupportedOperationException expected) { 1053 } 1054 } 1055 } 1056