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