SetsTest.java revision 1d580d0f6ee4f21eb309ba7b509d2c6d671c4044
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
17package com.google.common.collect;
18
19import static com.google.common.collect.Iterables.unmodifiableIterable;
20import static com.google.common.collect.Sets.newEnumSet;
21import static com.google.common.collect.Sets.newHashSet;
22import static com.google.common.collect.Sets.powerSet;
23import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
24import static com.google.common.collect.testing.testers.CollectionIteratorTester.getIteratorKnownOrderRemoveSupportedMethod;
25import static java.io.ObjectStreamConstants.TC_REFERENCE;
26import static java.io.ObjectStreamConstants.baseWireHandle;
27import static java.util.Collections.emptySet;
28import static java.util.Collections.singleton;
29import static org.junit.contrib.truth.Truth.ASSERT;
30
31import com.google.common.annotations.GwtCompatible;
32import com.google.common.annotations.GwtIncompatible;
33import com.google.common.base.Predicate;
34import com.google.common.base.Predicates;
35import com.google.common.collect.testing.AnEnum;
36import com.google.common.collect.testing.IteratorTester;
37import com.google.common.collect.testing.MinimalIterable;
38import com.google.common.collect.testing.SetTestSuiteBuilder;
39import com.google.common.collect.testing.TestEnumSetGenerator;
40import com.google.common.collect.testing.TestStringSetGenerator;
41import com.google.common.collect.testing.features.CollectionFeature;
42import com.google.common.collect.testing.features.CollectionSize;
43import com.google.common.collect.testing.features.SetFeature;
44import com.google.common.testing.EqualsTester;
45import com.google.common.testing.NullPointerTester;
46import com.google.common.testing.SerializableTester;
47
48import junit.framework.Test;
49import junit.framework.TestCase;
50import junit.framework.TestSuite;
51
52import java.io.ByteArrayInputStream;
53import java.io.ByteArrayOutputStream;
54import java.io.IOException;
55import java.io.ObjectInputStream;
56import java.io.ObjectOutputStream;
57import java.io.Serializable;
58import java.nio.ByteBuffer;
59import java.util.ArrayList;
60import java.util.Arrays;
61import java.util.Collection;
62import java.util.Collections;
63import java.util.Comparator;
64import java.util.EnumSet;
65import java.util.HashMap;
66import java.util.HashSet;
67import java.util.Iterator;
68import java.util.LinkedHashMap;
69import java.util.LinkedHashSet;
70import java.util.List;
71import java.util.Map;
72import java.util.NoSuchElementException;
73import java.util.Set;
74import java.util.SortedSet;
75import java.util.TreeSet;
76
77import 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)
86public 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