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