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