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