• 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.truth.Truth.assertThat;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.annotations.GwtIncompatible;
23 import com.google.common.collect.ImmutableSet.Builder;
24 import com.google.common.collect.testing.ListTestSuiteBuilder;
25 import com.google.common.collect.testing.SetTestSuiteBuilder;
26 import com.google.common.collect.testing.features.CollectionFeature;
27 import com.google.common.collect.testing.features.CollectionSize;
28 import com.google.common.collect.testing.google.SetGenerators.DegeneratedImmutableSetGenerator;
29 import com.google.common.collect.testing.google.SetGenerators.ImmutableSetAsListGenerator;
30 import com.google.common.collect.testing.google.SetGenerators.ImmutableSetCopyOfGenerator;
31 import com.google.common.collect.testing.google.SetGenerators.ImmutableSetSizedBuilderGenerator;
32 import com.google.common.collect.testing.google.SetGenerators.ImmutableSetTooBigBuilderGenerator;
33 import com.google.common.collect.testing.google.SetGenerators.ImmutableSetTooSmallBuilderGenerator;
34 import com.google.common.collect.testing.google.SetGenerators.ImmutableSetUnsizedBuilderGenerator;
35 import com.google.common.collect.testing.google.SetGenerators.ImmutableSetWithBadHashesGenerator;
36 import com.google.common.testing.EqualsTester;
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.Iterator;
40 import java.util.Set;
41 import junit.framework.Test;
42 import junit.framework.TestSuite;
43 
44 /**
45  * Unit test for {@link ImmutableSet}.
46  *
47  * @author Kevin Bourrillion
48  * @author Jared Levy
49  * @author Nick Kralevich
50  */
51 @GwtCompatible(emulated = true)
52 public class ImmutableSetTest extends AbstractImmutableSetTest {
53 
54   @GwtIncompatible // suite
suite()55   public static Test suite() {
56     TestSuite suite = new TestSuite();
57 
58     suite.addTest(
59         SetTestSuiteBuilder.using(new ImmutableSetCopyOfGenerator())
60             .named(ImmutableSetTest.class.getName())
61             .withFeatures(
62                 CollectionSize.ANY,
63                 CollectionFeature.KNOWN_ORDER,
64                 CollectionFeature.SERIALIZABLE,
65                 CollectionFeature.ALLOWS_NULL_QUERIES)
66             .createTestSuite());
67 
68     suite.addTest(
69         SetTestSuiteBuilder.using(new ImmutableSetUnsizedBuilderGenerator())
70             .named(ImmutableSetTest.class.getName() + ", with unsized builder")
71             .withFeatures(
72                 CollectionSize.ANY,
73                 CollectionFeature.KNOWN_ORDER,
74                 CollectionFeature.SERIALIZABLE,
75                 CollectionFeature.ALLOWS_NULL_QUERIES)
76             .createTestSuite());
77 
78     suite.addTest(
79         SetTestSuiteBuilder.using(new ImmutableSetSizedBuilderGenerator())
80             .named(ImmutableSetTest.class.getName() + ", with exactly sized builder")
81             .withFeatures(
82                 CollectionSize.ANY,
83                 CollectionFeature.KNOWN_ORDER,
84                 CollectionFeature.SERIALIZABLE,
85                 CollectionFeature.ALLOWS_NULL_QUERIES)
86             .createTestSuite());
87 
88     suite.addTest(
89         SetTestSuiteBuilder.using(new ImmutableSetTooBigBuilderGenerator())
90             .named(ImmutableSetTest.class.getName() + ", with oversized builder")
91             .withFeatures(
92                 CollectionSize.ANY,
93                 CollectionFeature.KNOWN_ORDER,
94                 CollectionFeature.SERIALIZABLE,
95                 CollectionFeature.ALLOWS_NULL_QUERIES)
96             .createTestSuite());
97 
98     suite.addTest(
99         SetTestSuiteBuilder.using(new ImmutableSetTooSmallBuilderGenerator())
100             .named(ImmutableSetTest.class.getName() + ", with undersized builder")
101             .withFeatures(
102                 CollectionSize.ANY,
103                 CollectionFeature.KNOWN_ORDER,
104                 CollectionFeature.SERIALIZABLE,
105                 CollectionFeature.ALLOWS_NULL_QUERIES)
106             .createTestSuite());
107 
108     suite.addTest(
109         SetTestSuiteBuilder.using(new ImmutableSetWithBadHashesGenerator())
110             .named(ImmutableSetTest.class.getName() + ", with bad hashes")
111             .withFeatures(
112                 CollectionSize.ANY,
113                 CollectionFeature.KNOWN_ORDER,
114                 CollectionFeature.ALLOWS_NULL_QUERIES)
115             .createTestSuite());
116 
117     suite.addTest(
118         SetTestSuiteBuilder.using(new DegeneratedImmutableSetGenerator())
119             .named(ImmutableSetTest.class.getName() + ", degenerate")
120             .withFeatures(
121                 CollectionSize.ONE,
122                 CollectionFeature.KNOWN_ORDER,
123                 CollectionFeature.ALLOWS_NULL_QUERIES)
124             .createTestSuite());
125 
126     suite.addTest(
127         ListTestSuiteBuilder.using(new ImmutableSetAsListGenerator())
128             .named("ImmutableSet.asList")
129             .withFeatures(
130                 CollectionSize.ANY,
131                 CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
132                 CollectionFeature.SERIALIZABLE,
133                 CollectionFeature.ALLOWS_NULL_QUERIES)
134             .createTestSuite());
135 
136     suite.addTestSuite(ImmutableSetTest.class);
137 
138     return suite;
139   }
140 
141   @Override
of()142   protected <E extends Comparable<? super E>> Set<E> of() {
143     return ImmutableSet.of();
144   }
145 
146   @Override
of(E e)147   protected <E extends Comparable<? super E>> Set<E> of(E e) {
148     return ImmutableSet.of(e);
149   }
150 
151   @Override
of(E e1, E e2)152   protected <E extends Comparable<? super E>> Set<E> of(E e1, E e2) {
153     return ImmutableSet.of(e1, e2);
154   }
155 
156   @Override
of(E e1, E e2, E e3)157   protected <E extends Comparable<? super E>> Set<E> of(E e1, E e2, E e3) {
158     return ImmutableSet.of(e1, e2, e3);
159   }
160 
161   @Override
of(E e1, E e2, E e3, E e4)162   protected <E extends Comparable<? super E>> Set<E> of(E e1, E e2, E e3, E e4) {
163     return ImmutableSet.of(e1, e2, e3, e4);
164   }
165 
166   @Override
of(E e1, E e2, E e3, E e4, E e5)167   protected <E extends Comparable<? super E>> Set<E> of(E e1, E e2, E e3, E e4, E e5) {
168     return ImmutableSet.of(e1, e2, e3, e4, e5);
169   }
170 
171   @SuppressWarnings("unchecked")
172   @Override
of( E e1, E e2, E e3, E e4, E e5, E e6, E... rest)173   protected <E extends Comparable<? super E>> Set<E> of(
174       E e1, E e2, E e3, E e4, E e5, E e6, E... rest) {
175     return ImmutableSet.of(e1, e2, e3, e4, e5, e6, rest);
176   }
177 
178   @Override
copyOf(E[] elements)179   protected <E extends Comparable<? super E>> Set<E> copyOf(E[] elements) {
180     return ImmutableSet.copyOf(elements);
181   }
182 
183   @Override
copyOf(Collection<? extends E> elements)184   protected <E extends Comparable<? super E>> Set<E> copyOf(Collection<? extends E> elements) {
185     return ImmutableSet.copyOf(elements);
186   }
187 
188   @Override
copyOf(Iterable<? extends E> elements)189   protected <E extends Comparable<? super E>> Set<E> copyOf(Iterable<? extends E> elements) {
190     return ImmutableSet.copyOf(elements);
191   }
192 
193   @Override
copyOf(Iterator<? extends E> elements)194   protected <E extends Comparable<? super E>> Set<E> copyOf(Iterator<? extends E> elements) {
195     return ImmutableSet.copyOf(elements);
196   }
197 
testCreation_allDuplicates()198   public void testCreation_allDuplicates() {
199     ImmutableSet<String> set = ImmutableSet.copyOf(Lists.newArrayList("a", "a"));
200     assertTrue(set instanceof SingletonImmutableSet);
201     assertEquals(Lists.newArrayList("a"), Lists.newArrayList(set));
202   }
203 
testCreation_oneDuplicate()204   public void testCreation_oneDuplicate() {
205     // now we'll get the varargs overload
206     ImmutableSet<String> set =
207         ImmutableSet.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "a");
208     assertEquals(
209         Lists.newArrayList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"),
210         Lists.newArrayList(set));
211   }
212 
testCreation_manyDuplicates()213   public void testCreation_manyDuplicates() {
214     // now we'll get the varargs overload
215     ImmutableSet<String> set =
216         ImmutableSet.of("a", "b", "c", "c", "c", "c", "b", "b", "a", "a", "c", "c", "c", "a");
217     assertThat(set).containsExactly("a", "b", "c").inOrder();
218   }
219 
220   @GwtIncompatible("Builder impl")
testBuilderForceCopy()221   public void testBuilderForceCopy() {
222     ImmutableSet.Builder<Integer> builder = ImmutableSet.builder();
223     builder.add(-1);
224     Object[] prevArray = null;
225     for (int i = 0; i < 10; i++) {
226       builder.add(i);
227       assertNotSame(builder.contents, prevArray);
228       prevArray = builder.contents;
229       ImmutableSet<Integer> unused = builder.build();
230     }
231   }
232 
233   @GwtIncompatible("Builder impl")
testPresizedBuilderDedups()234   public void testPresizedBuilderDedups() {
235     ImmutableSet.Builder<String> builder = ImmutableSet.builderWithExpectedSize(4);
236     builder.add("a");
237     assertEquals(1, builder.size);
238     builder.add("a");
239     assertEquals(1, builder.size);
240     builder.add("b", "c", "d");
241     assertEquals(4, builder.size);
242     Object[] table = builder.hashTable;
243     assertNotNull(table);
244     assertSame(table, ((RegularImmutableSet<String>) builder.build()).table);
245   }
246 
247   @GwtIncompatible("Builder impl")
testPresizedBuilderForceCopy()248   public void testPresizedBuilderForceCopy() {
249     for (int expectedSize = 1; expectedSize < 4; expectedSize++) {
250       ImmutableSet.Builder<Integer> builder = ImmutableSet.builderWithExpectedSize(expectedSize);
251       builder.add(-1);
252       Object[] prevArray = null;
253       for (int i = 0; i < 10; i++) {
254         ImmutableSet<Integer> prevBuilt = builder.build();
255         builder.add(i);
256         assertFalse(prevBuilt.contains(i));
257         assertNotSame(builder.contents, prevArray);
258         prevArray = builder.contents;
259       }
260     }
261   }
262 
testCreation_arrayOfArray()263   public void testCreation_arrayOfArray() {
264     String[] array = new String[] {"a"};
265     Set<String[]> set = ImmutableSet.<String[]>of(array);
266     assertEquals(Collections.singleton(array), set);
267   }
268 
269   @GwtIncompatible // ImmutableSet.chooseTableSize
testChooseTableSize()270   public void testChooseTableSize() {
271     assertEquals(8, ImmutableSet.chooseTableSize(3));
272     assertEquals(8, ImmutableSet.chooseTableSize(4));
273 
274     assertEquals(1 << 29, ImmutableSet.chooseTableSize(1 << 28));
275     assertEquals(1 << 29, ImmutableSet.chooseTableSize((1 << 29) * 3 / 5));
276 
277     // Now we hit the cap
278     assertEquals(1 << 30, ImmutableSet.chooseTableSize(1 << 29));
279     assertEquals(1 << 30, ImmutableSet.chooseTableSize((1 << 30) - 1));
280 
281     // Now we've gone too far
282     try {
283       ImmutableSet.chooseTableSize(1 << 30);
284       fail();
285     } catch (IllegalArgumentException expected) {
286     }
287   }
288 
289   @GwtIncompatible // RegularImmutableSet.table not in emulation
testResizeTable()290   public void testResizeTable() {
291     verifyTableSize(100, 2, 4);
292     verifyTableSize(100, 5, 8);
293     verifyTableSize(100, 33, 64);
294     verifyTableSize(60, 60, 128);
295     verifyTableSize(120, 60, 256);
296     // if the table is only double the necessary size, we don't bother resizing it
297     verifyTableSize(180, 60, 128);
298     // but if it's even bigger than double, we rebuild the table
299     verifyTableSize(17, 17, 32);
300     verifyTableSize(17, 16, 32);
301     verifyTableSize(17, 15, 32);
302   }
303 
304   @GwtIncompatible // RegularImmutableSet.table not in emulation
verifyTableSize(int inputSize, int setSize, int tableSize)305   private void verifyTableSize(int inputSize, int setSize, int tableSize) {
306     Builder<Integer> builder = ImmutableSet.builder();
307     for (int i = 0; i < inputSize; i++) {
308       builder.add(i % setSize);
309     }
310     ImmutableSet<Integer> set = builder.build();
311     assertTrue(set instanceof RegularImmutableSet);
312     assertEquals(
313         "Input size " + inputSize + " and set size " + setSize,
314         tableSize,
315         ((RegularImmutableSet<Integer>) set).table.length);
316   }
317 
testCopyOf_copiesImmutableSortedSet()318   public void testCopyOf_copiesImmutableSortedSet() {
319     ImmutableSortedSet<String> sortedSet = ImmutableSortedSet.of("a");
320     ImmutableSet<String> copy = ImmutableSet.copyOf(sortedSet);
321     assertNotSame(sortedSet, copy);
322   }
323 
324   // TODO(b/172823566): Use mainline testToImmutableSet once CollectorTester is usable to java7.
testToImmutableSet_java7()325   public void testToImmutableSet_java7() {
326     ImmutableSet.Builder<String> zis = ImmutableSet.<String>builder().add("a", "b", "a");
327     ImmutableSet.Builder<String> zat = ImmutableSet.<String>builder().add("c", "b", "d", "c");
328     ImmutableSet<String> set = zis.combine(zat).build();
329     assertThat(set).containsExactly("a", "b", "c", "d").inOrder();
330   }
331 
332   @GwtIncompatible // GWT is single threaded
testCopyOf_threadSafe()333   public void testCopyOf_threadSafe() {
334     verifyThreadSafe();
335   }
336 
337   @Override
builder()338   <E extends Comparable<E>> Builder<E> builder() {
339     return ImmutableSet.builder();
340   }
341 
342   @Override
getComplexBuilderSetLastElement()343   int getComplexBuilderSetLastElement() {
344     return LAST_COLOR_ADDED;
345   }
346 
testEquals()347   public void testEquals() {
348     new EqualsTester()
349         .addEqualityGroup(ImmutableSet.of(), ImmutableSet.of())
350         .addEqualityGroup(ImmutableSet.of(1), ImmutableSet.of(1), ImmutableSet.of(1, 1))
351         .addEqualityGroup(ImmutableSet.of(1, 2, 1), ImmutableSet.of(2, 1, 1))
352         .testEquals();
353   }
354 
355   @GwtIncompatible("internals")
testControlsArraySize()356   public void testControlsArraySize() {
357     ImmutableSet.Builder<String> builder = new ImmutableSet.Builder<String>();
358     for (int i = 0; i < 10; i++) {
359       builder.add("foo");
360     }
361     builder.add("bar");
362     RegularImmutableSet<String> set = (RegularImmutableSet<String>) builder.build();
363     assertTrue(set.elements.length <= 2 * set.size());
364   }
365 
366   @GwtIncompatible("internals")
testReusedBuilder()367   public void testReusedBuilder() {
368     ImmutableSet.Builder<String> builder = new ImmutableSet.Builder<String>();
369     for (int i = 0; i < 10; i++) {
370       builder.add("foo");
371     }
372     builder.add("bar");
373     RegularImmutableSet<String> set = (RegularImmutableSet<String>) builder.build();
374     builder.add("baz");
375     assertTrue(set.elements != builder.contents);
376   }
377 
testReuseBuilderReducingHashTableSizeWithPowerOfTwoTotalElements()378   public void testReuseBuilderReducingHashTableSizeWithPowerOfTwoTotalElements() {
379     ImmutableSet.Builder<Object> builder = ImmutableSet.builderWithExpectedSize(6);
380     builder.add(0);
381     ImmutableSet<Object> unused = builder.build();
382     ImmutableSet<Object> subject = builder.add(1).add(2).add(3).build();
383     assertFalse(subject.contains(4));
384   }
385 }
386