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