Home | History | Annotate | Download | only in collect
      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.collect.Lists.newArrayList;
     20 import static com.google.common.collect.Sets.newHashSet;
     21 import static com.google.common.collect.Sets.newLinkedHashSet;
     22 import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
     23 import static com.google.common.collect.testing.IteratorFeature.SUPPORTS_REMOVE;
     24 import static com.google.common.collect.testing.IteratorFeature.SUPPORTS_SET;
     25 import static java.util.Arrays.asList;
     26 import static org.junit.contrib.truth.Truth.ASSERT;
     27 
     28 import com.google.common.annotations.GwtCompatible;
     29 import com.google.common.annotations.GwtIncompatible;
     30 import com.google.common.collect.testing.IteratorTester;
     31 import com.google.common.collect.testing.ListIteratorTester;
     32 
     33 import java.util.Arrays;
     34 import java.util.Collection;
     35 import java.util.Collections;
     36 import java.util.Iterator;
     37 import java.util.List;
     38 import java.util.ListIterator;
     39 import java.util.Map;
     40 import java.util.Map.Entry;
     41 import java.util.RandomAccess;
     42 import java.util.Set;
     43 
     44 /**
     45  * Tests for {@code LinkedListMultimap}.
     46  *
     47  * @author Mike Bostock
     48  */
     49 @GwtCompatible(emulated = true)
     50 public class LinkedListMultimapTest extends AbstractListMultimapTest {
     51 
     52   @Override protected LinkedListMultimap<String, Integer> create() {
     53     return LinkedListMultimap.create();
     54   }
     55 
     56   /**
     57    * Confirm that get() returns a List that doesn't implement RandomAccess.
     58    */
     59   public void testGetRandomAccess() {
     60     Multimap<String, Integer> multimap = create();
     61     multimap.put("foo", 1);
     62     multimap.put("foo", 3);
     63     assertFalse(multimap.get("foo") instanceof RandomAccess);
     64     assertFalse(multimap.get("bar") instanceof RandomAccess);
     65   }
     66 
     67   /**
     68    * Confirm that removeAll() returns a List that implements RandomAccess, even
     69    * though get() doesn't.
     70    */
     71   public void testRemoveAllRandomAccess() {
     72     Multimap<String, Integer> multimap = create();
     73     multimap.put("foo", 1);
     74     multimap.put("foo", 3);
     75     assertTrue(multimap.removeAll("foo") instanceof RandomAccess);
     76     assertTrue(multimap.removeAll("bar") instanceof RandomAccess);
     77   }
     78 
     79   /**
     80    * Confirm that replaceValues() returns a List that implements RandomAccess,
     81    * even though get() doesn't.
     82    */
     83   public void testReplaceValuesRandomAccess() {
     84     Multimap<String, Integer> multimap = create();
     85     multimap.put("foo", 1);
     86     multimap.put("foo", 3);
     87     assertTrue(multimap.replaceValues("foo", Arrays.asList(2, 4))
     88         instanceof RandomAccess);
     89     assertTrue(multimap.replaceValues("bar", Arrays.asList(2, 4))
     90         instanceof RandomAccess);
     91   }
     92 
     93   public void testCreateFromMultimap() {
     94     Multimap<String, Integer> multimap = createSample();
     95     LinkedListMultimap<String, Integer> copy =
     96         LinkedListMultimap.create(multimap);
     97     assertEquals(multimap, copy);
     98   }
     99 
    100   public void testCreateFromSize() {
    101     LinkedListMultimap<String, Integer> multimap
    102         = LinkedListMultimap.create(20);
    103     multimap.put("foo", 1);
    104     multimap.put("bar", 2);
    105     multimap.put("foo", 3);
    106     assertEquals(ImmutableList.of(1, 3), multimap.get("foo"));
    107   }
    108 
    109   public void testCreateFromIllegalSize() {
    110     try {
    111       LinkedListMultimap.create(-20);
    112       fail();
    113     } catch (IllegalArgumentException expected) {}
    114   }
    115 
    116   /* "Linked" prefix avoids collision with AbstractMultimapTest. */
    117 
    118   public void testLinkedToString() {
    119     assertEquals("{foo=[3, -1, 2, 4, 1], bar=[1, 2, 3, 1]}",
    120         createSample().toString());
    121   }
    122 
    123   public void testLinkedGetAdd() {
    124     LinkedListMultimap<String, Integer> map = create();
    125     map.put("bar", 1);
    126     Collection<Integer> foos = map.get("foo");
    127     foos.add(2);
    128     foos.add(3);
    129     map.put("bar", 4);
    130     map.put("foo", 5);
    131     assertEquals("{bar=[1, 4], foo=[2, 3, 5]}", map.toString());
    132     assertEquals("[bar=1, foo=2, foo=3, bar=4, foo=5]",
    133         map.entries().toString());
    134   }
    135 
    136   public void testLinkedGetInsert() {
    137     ListMultimap<String, Integer> map = create();
    138     map.put("bar", 1);
    139     List<Integer> foos = map.get("foo");
    140     foos.add(2);
    141     foos.add(0, 3);
    142     map.put("bar", 4);
    143     map.put("foo", 5);
    144     assertEquals("{bar=[1, 4], foo=[3, 2, 5]}", map.toString());
    145     assertEquals("[bar=1, foo=3, foo=2, bar=4, foo=5]",
    146         map.entries().toString());
    147   }
    148 
    149   public void testLinkedPutInOrder() {
    150     Multimap<String, Integer> map = create();
    151     map.put("foo", 1);
    152     map.put("bar", 2);
    153     map.put("bar", 3);
    154     assertEquals("{foo=[1], bar=[2, 3]}", map.toString());
    155     assertEquals("[foo=1, bar=2, bar=3]", map.entries().toString());
    156   }
    157 
    158   public void testLinkedPutOutOfOrder() {
    159     Multimap<String, Integer> map = create();
    160     map.put("bar", 1);
    161     map.put("foo", 2);
    162     map.put("bar", 3);
    163     assertEquals("{bar=[1, 3], foo=[2]}", map.toString());
    164     assertEquals("[bar=1, foo=2, bar=3]", map.entries().toString());
    165   }
    166 
    167   public void testLinkedPutAllMultimap() {
    168     Multimap<String, Integer> src = create();
    169     src.put("bar", 1);
    170     src.put("foo", 2);
    171     src.put("bar", 3);
    172     Multimap<String, Integer> dst = create();
    173     dst.putAll(src);
    174     assertEquals("{bar=[1, 3], foo=[2]}", dst.toString());
    175     assertEquals("[bar=1, foo=2, bar=3]", src.entries().toString());
    176   }
    177 
    178   public void testLinkedReplaceValues() {
    179     Multimap<String, Integer> map = create();
    180     map.put("bar", 1);
    181     map.put("foo", 2);
    182     map.put("bar", 3);
    183     map.put("bar", 4);
    184     assertEquals("{bar=[1, 3, 4], foo=[2]}", map.toString());
    185     map.replaceValues("bar", asList(1, 2));
    186     assertEquals("[bar=1, foo=2, bar=2]", map.entries().toString());
    187     assertEquals("{bar=[1, 2], foo=[2]}", map.toString());
    188   }
    189 
    190   public void testLinkedClear() {
    191     ListMultimap<String, Integer> map = create();
    192     map.put("foo", 1);
    193     map.put("foo", 2);
    194     map.put("bar", 3);
    195     List<Integer> foos = map.get("foo");
    196     Collection<Integer> values = map.values();
    197     assertEquals(asList(1, 2), foos);
    198     ASSERT.that(values).hasContentsInOrder(1, 2, 3);
    199     map.clear();
    200     assertEquals(Collections.emptyList(), foos);
    201     ASSERT.that(values).hasContentsInOrder();
    202     assertEquals("[]", map.entries().toString());
    203     assertEquals("{}", map.toString());
    204   }
    205 
    206   public void testLinkedKeySet() {
    207     Multimap<String, Integer> map = create();
    208     map.put("bar", 1);
    209     map.put("foo", 2);
    210     map.put("bar", 3);
    211     map.put("bar", 4);
    212     assertEquals("[bar, foo]", map.keySet().toString());
    213     map.keySet().remove("bar");
    214     assertEquals("{foo=[2]}", map.toString());
    215   }
    216 
    217   public void testLinkedKeys() {
    218     Multimap<String, Integer> map = create();
    219     map.put("bar", 1);
    220     map.put("foo", 2);
    221     map.put("bar", 3);
    222     map.put("bar", 4);
    223     assertEquals("[bar=1, foo=2, bar=3, bar=4]",
    224         map.entries().toString());
    225     ASSERT.that(map.keys()).hasContentsInOrder("bar", "foo", "bar", "bar");
    226     map.keys().remove("bar"); // bar is no longer the first key!
    227     assertEquals("{foo=[2], bar=[3, 4]}", map.toString());
    228   }
    229 
    230   public void testLinkedValues() {
    231     Multimap<String, Integer> map = create();
    232     map.put("bar", 1);
    233     map.put("foo", 2);
    234     map.put("bar", 3);
    235     map.put("bar", 4);
    236     assertEquals("[1, 2, 3, 4]", map.values().toString());
    237     map.values().remove(2);
    238     assertEquals("{bar=[1, 3, 4]}", map.toString());
    239   }
    240 
    241   public void testLinkedEntries() {
    242     Multimap<String, Integer> map = create();
    243     map.put("bar", 1);
    244     map.put("foo", 2);
    245     map.put("bar", 3);
    246     Iterator<Map.Entry<String, Integer>> entries = map.entries().iterator();
    247     Map.Entry<String, Integer> entry = entries.next();
    248     assertEquals("bar", entry.getKey());
    249     assertEquals(1, (int) entry.getValue());
    250     entry = entries.next();
    251     assertEquals("foo", entry.getKey());
    252     assertEquals(2, (int) entry.getValue());
    253     entry.setValue(4);
    254     entry = entries.next();
    255     assertEquals("bar", entry.getKey());
    256     assertEquals(3, (int) entry.getValue());
    257     assertFalse(entries.hasNext());
    258     entries.remove();
    259     assertEquals("{bar=[1], foo=[4]}", map.toString());
    260   }
    261 
    262   public void testLinkedAsMapEntries() {
    263     Multimap<String, Integer> map = create();
    264     map.put("bar", 1);
    265     map.put("foo", 2);
    266     map.put("bar", 3);
    267     Iterator<Map.Entry<String, Collection<Integer>>> entries
    268         = map.asMap().entrySet().iterator();
    269     Map.Entry<String, Collection<Integer>> entry = entries.next();
    270     assertEquals("bar", entry.getKey());
    271     ASSERT.that(entry.getValue()).hasContentsInOrder(1, 3);
    272     try {
    273       entry.setValue(Arrays.<Integer>asList());
    274       fail("UnsupportedOperationException expected");
    275     } catch (UnsupportedOperationException expected) {}
    276     entries.remove(); // clear
    277     entry = entries.next();
    278     assertEquals("foo", entry.getKey());
    279     ASSERT.that(entry.getValue()).hasContentsInOrder(2);
    280     assertFalse(entries.hasNext());
    281     assertEquals("{foo=[2]}", map.toString());
    282   }
    283 
    284   /**
    285    * Test calling setValue() on an entry returned by multimap.entries().
    286    */
    287   @Override public void testEntrySetValue() {
    288     ListMultimap<String, Integer> multimap = create();
    289     multimap.put("foo", 1);
    290     multimap.put("bar", 3);
    291     Collection<Map.Entry<String, Integer>> entries = multimap.entries();
    292     Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
    293     Map.Entry<String, Integer> entrya = iterator.next();
    294     Map.Entry<String, Integer> entryb = iterator.next();
    295 
    296     int oldValue = entrya.setValue(2);
    297     assertEquals(1, oldValue);
    298     assertFalse(multimap.containsEntry("foo", 1));
    299     assertTrue(multimap.containsEntry("foo", 2));
    300     assertTrue(multimap.containsEntry("bar", 3));
    301     assertEquals(2, (int) entrya.getValue());
    302     assertEquals(3, (int) entryb.getValue());
    303   }
    304 
    305   public void testEntriesAfterMultimapUpdate() {
    306     ListMultimap<String, Integer> multimap = create();
    307     multimap.put("foo", 2);
    308     multimap.put("bar", 3);
    309     Collection<Map.Entry<String, Integer>> entries = multimap.entries();
    310     Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
    311     Map.Entry<String, Integer> entrya = iterator.next();
    312     Map.Entry<String, Integer> entryb = iterator.next();
    313 
    314     assertEquals(2, (int) multimap.get("foo").set(0, 4));
    315     assertFalse(multimap.containsEntry("foo", 2));
    316     assertTrue(multimap.containsEntry("foo", 4));
    317     assertTrue(multimap.containsEntry("bar", 3));
    318     assertEquals(4, (int) entrya.getValue());
    319     assertEquals(3, (int) entryb.getValue());
    320 
    321     assertTrue(multimap.put("foo", 5));
    322     assertTrue(multimap.containsEntry("foo", 5));
    323     assertTrue(multimap.containsEntry("foo", 4));
    324     assertTrue(multimap.containsEntry("bar", 3));
    325     assertEquals(4, (int) entrya.getValue());
    326     assertEquals(3, (int) entryb.getValue());
    327   }
    328 
    329   @SuppressWarnings("unchecked")
    330   @GwtIncompatible("unreasonable slow")
    331   public void testEntriesIteration() {
    332     List<Entry<String, Integer>> addItems = ImmutableList.of(
    333         Maps.immutableEntry("foo", 99),
    334         Maps.immutableEntry("foo", 88),
    335         Maps.immutableEntry("bar", 77));
    336 
    337     for (final int startIndex : new int[] {0, 3, 5}) {
    338       List<Entry<String, Integer>> list = Lists.newArrayList(
    339           Maps.immutableEntry("foo", 2),
    340           Maps.immutableEntry("foo", 3),
    341           Maps.immutableEntry("bar", 4),
    342           Maps.immutableEntry("bar", 5),
    343           Maps.immutableEntry("foo", 6));
    344       new ListIteratorTester<Entry<String, Integer>>(3, addItems,
    345           ImmutableList.of(SUPPORTS_REMOVE), list, startIndex) {
    346         private LinkedListMultimap<String, Integer> multimap;
    347 
    348         @Override protected ListIterator<Entry<String, Integer>> newTargetIterator() {
    349           multimap = create();
    350           multimap.putAll("foo", asList(2, 3));
    351           multimap.putAll("bar", asList(4, 5));
    352           multimap.put("foo", 6);
    353           return multimap.entries().listIterator(startIndex);
    354         }
    355 
    356         @Override protected void verify(List<Entry<String, Integer>> elements) {
    357           assertEquals(elements, multimap.entries());
    358         }
    359       }.test();
    360     }
    361   }
    362 
    363   @GwtIncompatible("unreasonable slow")
    364   public void testKeysIteration() {
    365     new IteratorTester<String>(6, MODIFIABLE, newArrayList("foo", "foo", "bar",
    366         "bar", "foo"), IteratorTester.KnownOrder.KNOWN_ORDER) {
    367       private Multimap<String, Integer> multimap;
    368 
    369       @Override protected Iterator<String> newTargetIterator() {
    370         multimap = create();
    371         multimap.putAll("foo", asList(2, 3));
    372         multimap.putAll("bar", asList(4, 5));
    373         multimap.putAll("foo", asList(6));
    374         return multimap.keys().iterator();
    375       }
    376 
    377       @Override protected void verify(List<String> elements) {
    378         assertEquals(elements, Lists.newArrayList(multimap.keys()));
    379       }
    380     }.test();
    381   }
    382 
    383   @GwtIncompatible("unreasonable slow")
    384   public void testValuesIteration() {
    385     List<Integer> addItems = ImmutableList.of(99, 88, 77);
    386 
    387     for (final int startIndex : new int[] {0, 3, 5}) {
    388       new ListIteratorTester<Integer>(3, addItems,
    389           ImmutableList.of(SUPPORTS_REMOVE, SUPPORTS_SET),
    390           Lists.newArrayList(2, 3, 4, 5, 6), startIndex) {
    391         private LinkedListMultimap<String, Integer> multimap;
    392 
    393         @Override protected ListIterator<Integer> newTargetIterator() {
    394           multimap = create();
    395           multimap.put("bar", 2);
    396           multimap.putAll("foo", Arrays.asList(3, 4));
    397           multimap.put("bar", 5);
    398           multimap.put("foo", 6);
    399           return multimap.values().listIterator(startIndex);
    400         }
    401 
    402         @Override protected void verify(List<Integer> elements) {
    403           assertEquals(elements, multimap.values());
    404         }
    405       }.test();
    406     }
    407   }
    408 
    409   @GwtIncompatible("unreasonable slow")
    410   public void testKeySetIteration() {
    411     new IteratorTester<String>(6, MODIFIABLE, newLinkedHashSet(asList(
    412         "foo", "bar", "baz", "dog", "cat")),
    413         IteratorTester.KnownOrder.KNOWN_ORDER) {
    414       private Multimap<String, Integer> multimap;
    415 
    416       @Override protected Iterator<String> newTargetIterator() {
    417         multimap = create();
    418         multimap.putAll("foo", asList(2, 3));
    419         multimap.putAll("bar", asList(4, 5));
    420         multimap.putAll("foo", asList(6));
    421         multimap.putAll("baz", asList(7, 8));
    422         multimap.putAll("dog", asList(9));
    423         multimap.putAll("bar", asList(10, 11));
    424         multimap.putAll("cat", asList(12, 13, 14));
    425         return multimap.keySet().iterator();
    426       }
    427 
    428       @Override protected void verify(List<String> elements) {
    429         assertEquals(newHashSet(elements), multimap.keySet());
    430       }
    431     }.test();
    432   }
    433 
    434   @SuppressWarnings("unchecked")
    435   @GwtIncompatible("unreasonable slow")
    436   public void testAsSetIteration() {
    437     Set<Entry<String, Collection<Integer>>> set = Sets.newLinkedHashSet(asList(
    438         Maps.immutableEntry("foo",
    439             (Collection<Integer>) asList(2, 3, 6)),
    440         Maps.immutableEntry("bar",
    441             (Collection<Integer>) asList(4, 5, 10, 11)),
    442         Maps.immutableEntry("baz",
    443             (Collection<Integer>) asList(7, 8)),
    444         Maps.immutableEntry("dog",
    445             (Collection<Integer>) asList(9)),
    446         Maps.immutableEntry("cat",
    447             (Collection<Integer>) asList(12, 13, 14))
    448     ));
    449 
    450     new IteratorTester<Entry<String, Collection<Integer>>>(6, MODIFIABLE, set,
    451         IteratorTester.KnownOrder.KNOWN_ORDER) {
    452       private Multimap<String, Integer> multimap;
    453 
    454       @Override protected Iterator<Entry<String, Collection<Integer>>>
    455           newTargetIterator() {
    456         multimap = create();
    457         multimap.putAll("foo", asList(2, 3));
    458         multimap.putAll("bar", asList(4, 5));
    459         multimap.putAll("foo", asList(6));
    460         multimap.putAll("baz", asList(7, 8));
    461         multimap.putAll("dog", asList(9));
    462         multimap.putAll("bar", asList(10, 11));
    463         multimap.putAll("cat", asList(12, 13, 14));
    464         return multimap.asMap().entrySet().iterator();
    465       }
    466 
    467       @Override protected void verify(
    468           List<Entry<String, Collection<Integer>>> elements) {
    469         assertEquals(newHashSet(elements), multimap.asMap().entrySet());
    470       }
    471     }.test();
    472   }
    473 }
    474