1 /* 2 * Copyright (C) 2008 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.testing.IteratorFeature.UNMODIFIABLE; 20 import static com.google.common.truth.Truth.assertThat; 21 import static java.util.Arrays.asList; 22 23 import com.google.common.annotations.GwtCompatible; 24 import com.google.common.annotations.GwtIncompatible; 25 import com.google.common.collect.testing.Helpers; 26 import com.google.common.collect.testing.IteratorTester; 27 import com.google.common.collect.testing.MinimalCollection; 28 import com.google.common.collect.testing.MinimalIterable; 29 import java.util.Collection; 30 import java.util.Collections; 31 import java.util.EnumSet; 32 import java.util.Iterator; 33 import java.util.List; 34 import java.util.Set; 35 import junit.framework.TestCase; 36 import org.checkerframework.checker.nullness.qual.Nullable; 37 38 /** 39 * Base class for {@link ImmutableSet} and {@link ImmutableSortedSet} tests. 40 * 41 * @author Kevin Bourrillion 42 * @author Jared Levy 43 */ 44 @GwtCompatible(emulated = true) 45 public abstract class AbstractImmutableSetTest extends TestCase { 46 of()47 protected abstract <E extends Comparable<? super E>> Set<E> of(); 48 of(E e)49 protected abstract <E extends Comparable<? super E>> Set<E> of(E e); 50 of(E e1, E e2)51 protected abstract <E extends Comparable<? super E>> Set<E> of(E e1, E e2); 52 of(E e1, E e2, E e3)53 protected abstract <E extends Comparable<? super E>> Set<E> of(E e1, E e2, E e3); 54 of(E e1, E e2, E e3, E e4)55 protected abstract <E extends Comparable<? super E>> Set<E> of(E e1, E e2, E e3, E e4); 56 of(E e1, E e2, E e3, E e4, E e5)57 protected abstract <E extends Comparable<? super E>> Set<E> of(E e1, E e2, E e3, E e4, E e5); 58 59 @SuppressWarnings("unchecked") of( E e1, E e2, E e3, E e4, E e5, E e6, E... rest)60 protected abstract <E extends Comparable<? super E>> Set<E> of( 61 E e1, E e2, E e3, E e4, E e5, E e6, E... rest); 62 copyOf(E @ullable [] elements)63 protected abstract <E extends Comparable<? super E>> Set<E> copyOf(E @Nullable [] elements); 64 copyOf( Collection<? extends E> elements)65 protected abstract <E extends Comparable<? super E>> Set<E> copyOf( 66 Collection<? extends E> elements); 67 copyOf( Iterable<? extends E> elements)68 protected abstract <E extends Comparable<? super E>> Set<E> copyOf( 69 Iterable<? extends E> elements); 70 copyOf( Iterator<? extends E> elements)71 protected abstract <E extends Comparable<? super E>> Set<E> copyOf( 72 Iterator<? extends E> elements); 73 testCreation_noArgs()74 public void testCreation_noArgs() { 75 Set<String> set = of(); 76 assertEquals(Collections.<String>emptySet(), set); 77 assertSame(of(), set); 78 } 79 testCreation_oneElement()80 public void testCreation_oneElement() { 81 Set<String> set = of("a"); 82 assertEquals(Collections.singleton("a"), set); 83 } 84 testCreation_twoElements()85 public void testCreation_twoElements() { 86 Set<String> set = of("a", "b"); 87 assertEquals(Sets.newHashSet("a", "b"), set); 88 } 89 testCreation_threeElements()90 public void testCreation_threeElements() { 91 Set<String> set = of("a", "b", "c"); 92 assertEquals(Sets.newHashSet("a", "b", "c"), set); 93 } 94 testCreation_fourElements()95 public void testCreation_fourElements() { 96 Set<String> set = of("a", "b", "c", "d"); 97 assertEquals(Sets.newHashSet("a", "b", "c", "d"), set); 98 } 99 testCreation_fiveElements()100 public void testCreation_fiveElements() { 101 Set<String> set = of("a", "b", "c", "d", "e"); 102 assertEquals(Sets.newHashSet("a", "b", "c", "d", "e"), set); 103 } 104 testCreation_sixElements()105 public void testCreation_sixElements() { 106 Set<String> set = of("a", "b", "c", "d", "e", "f"); 107 assertEquals(Sets.newHashSet("a", "b", "c", "d", "e", "f"), set); 108 } 109 testCreation_sevenElements()110 public void testCreation_sevenElements() { 111 Set<String> set = of("a", "b", "c", "d", "e", "f", "g"); 112 assertEquals(Sets.newHashSet("a", "b", "c", "d", "e", "f", "g"), set); 113 } 114 testCreation_eightElements()115 public void testCreation_eightElements() { 116 Set<String> set = of("a", "b", "c", "d", "e", "f", "g", "h"); 117 assertEquals(Sets.newHashSet("a", "b", "c", "d", "e", "f", "g", "h"), set); 118 } 119 testCopyOf_emptyArray()120 public void testCopyOf_emptyArray() { 121 String[] array = new String[0]; 122 Set<String> set = copyOf(array); 123 assertEquals(Collections.<String>emptySet(), set); 124 assertSame(of(), set); 125 } 126 testCopyOf_arrayOfOneElement()127 public void testCopyOf_arrayOfOneElement() { 128 String[] array = new String[] {"a"}; 129 Set<String> set = copyOf(array); 130 assertEquals(Collections.singleton("a"), set); 131 } 132 testCopyOf_nullArray()133 public void testCopyOf_nullArray() { 134 try { 135 copyOf((String[]) null); 136 fail(); 137 } catch (NullPointerException expected) { 138 } 139 } 140 testCopyOf_arrayContainingOnlyNull()141 public void testCopyOf_arrayContainingOnlyNull() { 142 String[] array = new String[] {null}; 143 try { 144 copyOf(array); 145 fail(); 146 } catch (NullPointerException expected) { 147 } 148 } 149 testCopyOf_collection_empty()150 public void testCopyOf_collection_empty() { 151 // "<String>" is required to work around a javac 1.5 bug. 152 Collection<String> c = MinimalCollection.<String>of(); 153 Set<String> set = copyOf(c); 154 assertEquals(Collections.<String>emptySet(), set); 155 assertSame(of(), set); 156 } 157 testCopyOf_collection_oneElement()158 public void testCopyOf_collection_oneElement() { 159 Collection<String> c = MinimalCollection.of("a"); 160 Set<String> set = copyOf(c); 161 assertEquals(Collections.singleton("a"), set); 162 } 163 testCopyOf_collection_oneElementRepeated()164 public void testCopyOf_collection_oneElementRepeated() { 165 Collection<String> c = MinimalCollection.of("a", "a", "a"); 166 Set<String> set = copyOf(c); 167 assertEquals(Collections.singleton("a"), set); 168 } 169 testCopyOf_collection_general()170 public void testCopyOf_collection_general() { 171 Collection<String> c = MinimalCollection.of("a", "b", "a"); 172 Set<String> set = copyOf(c); 173 assertEquals(2, set.size()); 174 assertTrue(set.contains("a")); 175 assertTrue(set.contains("b")); 176 } 177 testCopyOf_collectionContainingNull()178 public void testCopyOf_collectionContainingNull() { 179 Collection<String> c = MinimalCollection.of("a", null, "b"); 180 try { 181 copyOf(c); 182 fail(); 183 } catch (NullPointerException expected) { 184 } 185 } 186 187 enum TestEnum { 188 A, 189 B, 190 C, 191 D 192 } 193 testCopyOf_collection_enumSet()194 public void testCopyOf_collection_enumSet() { 195 Collection<TestEnum> c = EnumSet.of(TestEnum.A, TestEnum.B, TestEnum.D); 196 Set<TestEnum> set = copyOf(c); 197 assertEquals(3, set.size()); 198 assertEquals(c, set); 199 } 200 testCopyOf_iterator_empty()201 public void testCopyOf_iterator_empty() { 202 Iterator<String> iterator = Iterators.emptyIterator(); 203 Set<String> set = copyOf(iterator); 204 assertEquals(Collections.<String>emptySet(), set); 205 assertSame(of(), set); 206 } 207 testCopyOf_iterator_oneElement()208 public void testCopyOf_iterator_oneElement() { 209 Iterator<String> iterator = Iterators.singletonIterator("a"); 210 Set<String> set = copyOf(iterator); 211 assertEquals(Collections.singleton("a"), set); 212 } 213 testCopyOf_iterator_oneElementRepeated()214 public void testCopyOf_iterator_oneElementRepeated() { 215 Iterator<String> iterator = Iterators.forArray("a", "a", "a"); 216 Set<String> set = copyOf(iterator); 217 assertEquals(Collections.singleton("a"), set); 218 } 219 testCopyOf_iterator_general()220 public void testCopyOf_iterator_general() { 221 Iterator<String> iterator = Iterators.forArray("a", "b", "a"); 222 Set<String> set = copyOf(iterator); 223 assertEquals(2, set.size()); 224 assertTrue(set.contains("a")); 225 assertTrue(set.contains("b")); 226 } 227 testCopyOf_iteratorContainingNull()228 public void testCopyOf_iteratorContainingNull() { 229 Iterator<String> c = Iterators.forArray("a", null, "b"); 230 try { 231 copyOf(c); 232 fail(); 233 } catch (NullPointerException expected) { 234 } 235 } 236 237 private static class CountingIterable implements Iterable<String> { 238 int count = 0; 239 240 @Override iterator()241 public Iterator<String> iterator() { 242 count++; 243 return Iterators.forArray("a", "b", "a"); 244 } 245 } 246 testCopyOf_plainIterable()247 public void testCopyOf_plainIterable() { 248 CountingIterable iterable = new CountingIterable(); 249 Set<String> set = copyOf(iterable); 250 assertEquals(2, set.size()); 251 assertTrue(set.contains("a")); 252 assertTrue(set.contains("b")); 253 } 254 testCopyOf_plainIterable_iteratesOnce()255 public void testCopyOf_plainIterable_iteratesOnce() { 256 CountingIterable iterable = new CountingIterable(); 257 Set<String> unused = copyOf(iterable); 258 assertEquals(1, iterable.count); 259 } 260 testCopyOf_shortcut_empty()261 public void testCopyOf_shortcut_empty() { 262 Collection<String> c = of(); 263 assertEquals(Collections.<String>emptySet(), copyOf(c)); 264 assertSame(c, copyOf(c)); 265 } 266 testCopyOf_shortcut_singleton()267 public void testCopyOf_shortcut_singleton() { 268 Collection<String> c = of("a"); 269 assertEquals(Collections.singleton("a"), copyOf(c)); 270 assertSame(c, copyOf(c)); 271 } 272 testCopyOf_shortcut_sameType()273 public void testCopyOf_shortcut_sameType() { 274 Collection<String> c = of("a", "b", "c"); 275 assertSame(c, copyOf(c)); 276 } 277 testToString()278 public void testToString() { 279 Set<String> set = of("a", "b", "c", "d", "e", "f", "g"); 280 assertEquals("[a, b, c, d, e, f, g]", set.toString()); 281 } 282 283 @GwtIncompatible // slow (~40s) testIterator_oneElement()284 public void testIterator_oneElement() { 285 new IteratorTester<String>( 286 5, UNMODIFIABLE, Collections.singleton("a"), IteratorTester.KnownOrder.KNOWN_ORDER) { 287 @Override 288 protected Iterator<String> newTargetIterator() { 289 return of("a").iterator(); 290 } 291 }.test(); 292 } 293 294 @GwtIncompatible // slow (~30s) testIterator_general()295 public void testIterator_general() { 296 new IteratorTester<String>( 297 5, UNMODIFIABLE, asList("a", "b", "c"), IteratorTester.KnownOrder.KNOWN_ORDER) { 298 @Override 299 protected Iterator<String> newTargetIterator() { 300 return of("a", "b", "c").iterator(); 301 } 302 }.test(); 303 } 304 testContainsAll_sameType()305 public void testContainsAll_sameType() { 306 Collection<String> c = of("a", "b", "c"); 307 assertFalse(c.containsAll(of("a", "b", "c", "d"))); 308 assertFalse(c.containsAll(of("a", "d"))); 309 assertTrue(c.containsAll(of("a", "c"))); 310 assertTrue(c.containsAll(of("a", "b", "c"))); 311 } 312 testEquals_sameType()313 public void testEquals_sameType() { 314 Collection<String> c = of("a", "b", "c"); 315 assertTrue(c.equals(of("a", "b", "c"))); 316 assertFalse(c.equals(of("a", "b", "d"))); 317 } 318 builder()319 abstract <E extends Comparable<E>> ImmutableSet.Builder<E> builder(); 320 testBuilderWithNonDuplicateElements()321 public void testBuilderWithNonDuplicateElements() { 322 ImmutableSet<String> set = 323 this.<String>builder() 324 .add("a") 325 .add("b", "c") 326 .add("d", "e", "f") 327 .add("g", "h", "i", "j") 328 .build(); 329 assertThat(set).containsExactly("a", "b", "c", "d", "e", "f", "g", "h", "i", "j").inOrder(); 330 } 331 testReuseBuilderWithNonDuplicateElements()332 public void testReuseBuilderWithNonDuplicateElements() { 333 ImmutableSet.Builder<String> builder = this.<String>builder().add("a").add("b"); 334 assertThat(builder.build()).containsExactly("a", "b").inOrder(); 335 builder.add("c", "d"); 336 assertThat(builder.build()).containsExactly("a", "b", "c", "d").inOrder(); 337 } 338 testBuilderWithDuplicateElements()339 public void testBuilderWithDuplicateElements() { 340 ImmutableSet<String> set = 341 this.<String>builder() 342 .add("a") 343 .add("a", "a") 344 .add("a", "a", "a") 345 .add("a", "a", "a", "a") 346 .build(); 347 assertTrue(set.contains("a")); 348 assertFalse(set.contains("b")); 349 assertEquals(1, set.size()); 350 } 351 testReuseBuilderWithDuplicateElements()352 public void testReuseBuilderWithDuplicateElements() { 353 ImmutableSet.Builder<String> builder = this.<String>builder().add("a").add("a", "a").add("b"); 354 assertThat(builder.build()).containsExactly("a", "b").inOrder(); 355 builder.add("a", "b", "c", "c"); 356 assertThat(builder.build()).containsExactly("a", "b", "c").inOrder(); 357 } 358 testBuilderAddAll()359 public void testBuilderAddAll() { 360 List<String> a = asList("a", "b", "c"); 361 List<String> b = asList("c", "d", "e"); 362 ImmutableSet<String> set = this.<String>builder().addAll(a).addAll(b).build(); 363 assertThat(set).containsExactly("a", "b", "c", "d", "e").inOrder(); 364 } 365 366 static final int LAST_COLOR_ADDED = 0x00BFFF; 367 testComplexBuilder()368 public void testComplexBuilder() { 369 List<Integer> colorElem = asList(0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF); 370 // javac won't compile this without "this.<Integer>" 371 ImmutableSet.Builder<Integer> webSafeColorsBuilder = this.<Integer>builder(); 372 for (Integer red : colorElem) { 373 for (Integer green : colorElem) { 374 for (Integer blue : colorElem) { 375 webSafeColorsBuilder.add((red << 16) + (green << 8) + blue); 376 } 377 } 378 } 379 ImmutableSet<Integer> webSafeColors = webSafeColorsBuilder.build(); 380 assertEquals(216, webSafeColors.size()); 381 Integer[] webSafeColorArray = webSafeColors.toArray(new Integer[webSafeColors.size()]); 382 assertEquals(0x000000, (int) webSafeColorArray[0]); 383 assertEquals(0x000033, (int) webSafeColorArray[1]); 384 assertEquals(0x000066, (int) webSafeColorArray[2]); 385 assertEquals(0x003300, (int) webSafeColorArray[6]); 386 assertEquals(0x330000, (int) webSafeColorArray[36]); 387 ImmutableSet<Integer> addedColor = webSafeColorsBuilder.add(LAST_COLOR_ADDED).build(); 388 assertEquals( 389 "Modifying the builder should not have changed any already built sets", 390 216, 391 webSafeColors.size()); 392 assertEquals("the new array should be one bigger than webSafeColors", 217, addedColor.size()); 393 Integer[] appendColorArray = addedColor.toArray(new Integer[addedColor.size()]); 394 assertEquals(getComplexBuilderSetLastElement(), (int) appendColorArray[216]); 395 } 396 getComplexBuilderSetLastElement()397 abstract int getComplexBuilderSetLastElement(); 398 testBuilderAddHandlesNullsCorrectly()399 public void testBuilderAddHandlesNullsCorrectly() { 400 ImmutableSet.Builder<String> builder = this.<String>builder(); 401 try { 402 builder.add((String) null); 403 fail("expected NullPointerException"); // COV_NF_LINE 404 } catch (NullPointerException expected) { 405 } 406 407 builder = this.<String>builder(); 408 try { 409 builder.add((String[]) null); 410 fail("expected NullPointerException"); // COV_NF_LINE 411 } catch (NullPointerException expected) { 412 } 413 414 builder = this.<String>builder(); 415 try { 416 builder.add("a", (String) null); 417 fail("expected NullPointerException"); // COV_NF_LINE 418 } catch (NullPointerException expected) { 419 } 420 421 builder = this.<String>builder(); 422 try { 423 builder.add("a", "b", (String) null); 424 fail("expected NullPointerException"); // COV_NF_LINE 425 } catch (NullPointerException expected) { 426 } 427 428 builder = this.<String>builder(); 429 try { 430 builder.add("a", "b", "c", null); 431 fail("expected NullPointerException"); // COV_NF_LINE 432 } catch (NullPointerException expected) { 433 } 434 435 builder = this.<String>builder(); 436 try { 437 builder.add("a", "b", null, "c"); 438 fail("expected NullPointerException"); // COV_NF_LINE 439 } catch (NullPointerException expected) { 440 } 441 } 442 testBuilderAddAllHandlesNullsCorrectly()443 public void testBuilderAddAllHandlesNullsCorrectly() { 444 ImmutableSet.Builder<String> builder = this.<String>builder(); 445 try { 446 builder.addAll((Iterable<String>) null); 447 fail("expected NullPointerException"); // COV_NF_LINE 448 } catch (NullPointerException expected) { 449 } 450 451 try { 452 builder.addAll((Iterator<String>) null); 453 fail("expected NullPointerException"); // COV_NF_LINE 454 } catch (NullPointerException expected) { 455 } 456 457 builder = this.<String>builder(); 458 List<String> listWithNulls = asList("a", null, "b"); 459 try { 460 builder.addAll(listWithNulls); 461 fail("expected NullPointerException"); // COV_NF_LINE 462 } catch (NullPointerException expected) { 463 } 464 465 Iterable<String> iterableWithNulls = MinimalIterable.of("a", null, "b"); 466 try { 467 builder.addAll(iterableWithNulls); 468 fail("expected NullPointerException"); // COV_NF_LINE 469 } catch (NullPointerException expected) { 470 } 471 } 472 473 /** 474 * Verify thread safety by using a collection whose size() may be inconsistent with the actual 475 * number of elements. Tests using this method might fail in GWT because the GWT emulations might 476 * count on size() during copy. It is safe to do so in GWT because javascript is single-threaded. 477 */ 478 // TODO(benyu): turn this into a test once all copyOf(Collection) are 479 // thread-safe 480 @GwtIncompatible // GWT is single threaded verifyThreadSafe()481 void verifyThreadSafe() { 482 List<String> sample = Lists.newArrayList("a", "b", "c"); 483 for (int delta : new int[] {-1, 0, 1}) { 484 for (int i = 0; i < sample.size(); i++) { 485 Collection<String> misleading = Helpers.misleadingSizeCollection(delta); 486 List<String> expected = sample.subList(0, i); 487 misleading.addAll(expected); 488 assertEquals( 489 "delta: " + delta + " sample size: " + i, 490 Sets.newHashSet(expected), 491 copyOf(misleading)); 492 } 493 } 494 } 495 } 496