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