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