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