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 org.junit.contrib.truth.Truth.ASSERT;
     20 
     21 import com.google.common.annotations.GwtCompatible;
     22 import com.google.common.annotations.GwtIncompatible;
     23 import com.google.common.collect.ImmutableListMultimap.Builder;
     24 import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
     25 import com.google.common.testing.EqualsTester;
     26 import com.google.common.testing.SerializableTester;
     27 
     28 import junit.framework.TestCase;
     29 
     30 import java.util.Arrays;
     31 import java.util.Collection;
     32 import java.util.Collections;
     33 import java.util.Map.Entry;
     34 
     35 /**
     36  * Tests for {@link ImmutableListMultimap}.
     37  *
     38  * @author Jared Levy
     39  */
     40 @GwtCompatible(emulated = true)
     41 public class ImmutableListMultimapTest extends TestCase {
     42 
     43   public void testBuilder_withImmutableEntry() {
     44     ImmutableListMultimap<String, Integer> multimap = new Builder<String, Integer>()
     45         .put(Maps.immutableEntry("one", 1))
     46         .build();
     47     assertEquals(Arrays.asList(1), multimap.get("one"));
     48   }
     49 
     50   public void testBuilder_withImmutableEntryAndNullContents() {
     51     Builder<String, Integer> builder = new Builder<String, Integer>();
     52     try {
     53       builder.put(Maps.immutableEntry("one", (Integer) null));
     54       fail();
     55     } catch (NullPointerException expected) {
     56     }
     57     try {
     58       builder.put(Maps.immutableEntry((String) null, 1));
     59       fail();
     60     } catch (NullPointerException expected) {
     61     }
     62   }
     63 
     64   private static class StringHolder {
     65     String string;
     66   }
     67 
     68   public void testBuilder_withMutableEntry() {
     69     ImmutableListMultimap.Builder<String, Integer> builder =
     70         new Builder<String, Integer>();
     71     final StringHolder holder = new StringHolder();
     72     holder.string = "one";
     73     Entry<String, Integer> entry = new AbstractMapEntry<String, Integer>() {
     74       @Override public String getKey() {
     75         return holder.string;
     76       }
     77       @Override public Integer getValue() {
     78         return 1;
     79       }
     80     };
     81 
     82     builder.put(entry);
     83     holder.string = "two";
     84     assertEquals(Arrays.asList(1), builder.build().get("one"));
     85   }
     86 
     87   public void testBuilderPutAllIterable() {
     88     ImmutableListMultimap.Builder<String, Integer> builder
     89         = ImmutableListMultimap.builder();
     90     builder.putAll("foo", Arrays.asList(1, 2, 3));
     91     builder.putAll("bar", Arrays.asList(4, 5));
     92     builder.putAll("foo", Arrays.asList(6, 7));
     93     Multimap<String, Integer> multimap = builder.build();
     94     assertEquals(Arrays.asList(1, 2, 3, 6, 7), multimap.get("foo"));
     95     assertEquals(Arrays.asList(4, 5), multimap.get("bar"));
     96     assertEquals(7, multimap.size());
     97   }
     98 
     99   public void testBuilderPutAllVarargs() {
    100     ImmutableListMultimap.Builder<String, Integer> builder
    101         = ImmutableListMultimap.builder();
    102     builder.putAll("foo", 1, 2, 3);
    103     builder.putAll("bar", 4, 5);
    104     builder.putAll("foo", 6, 7);
    105     Multimap<String, Integer> multimap = builder.build();
    106     assertEquals(Arrays.asList(1, 2, 3, 6, 7), multimap.get("foo"));
    107     assertEquals(Arrays.asList(4, 5), multimap.get("bar"));
    108     assertEquals(7, multimap.size());
    109   }
    110 
    111   public void testBuilderPutAllMultimap() {
    112     Multimap<String, Integer> toPut = LinkedListMultimap.create();
    113     toPut.put("foo", 1);
    114     toPut.put("bar", 4);
    115     toPut.put("foo", 2);
    116     toPut.put("foo", 3);
    117     Multimap<String, Integer> moreToPut = LinkedListMultimap.create();
    118     moreToPut.put("foo", 6);
    119     moreToPut.put("bar", 5);
    120     moreToPut.put("foo", 7);
    121     ImmutableListMultimap.Builder<String, Integer> builder
    122         = ImmutableListMultimap.builder();
    123     builder.putAll(toPut);
    124     builder.putAll(moreToPut);
    125     Multimap<String, Integer> multimap = builder.build();
    126     assertEquals(Arrays.asList(1, 2, 3, 6, 7), multimap.get("foo"));
    127     assertEquals(Arrays.asList(4, 5), multimap.get("bar"));
    128     assertEquals(7, multimap.size());
    129   }
    130 
    131   public void testBuilderPutAllWithDuplicates() {
    132     ImmutableListMultimap.Builder<String, Integer> builder
    133         = ImmutableListMultimap.builder();
    134     builder.putAll("foo", 1, 2, 3);
    135     builder.putAll("bar", 4, 5);
    136     builder.putAll("foo", 1, 6, 7);
    137     ImmutableListMultimap<String, Integer> multimap = builder.build();
    138     assertEquals(Arrays.asList(1, 2, 3, 1, 6, 7), multimap.get("foo"));
    139     assertEquals(Arrays.asList(4, 5), multimap.get("bar"));
    140     assertEquals(8, multimap.size());
    141   }
    142 
    143   public void testBuilderPutWithDuplicates() {
    144     ImmutableListMultimap.Builder<String, Integer> builder
    145         = ImmutableListMultimap.builder();
    146     builder.putAll("foo", 1, 2, 3);
    147     builder.putAll("bar", 4, 5);
    148     builder.put("foo", 1);
    149     ImmutableListMultimap<String, Integer> multimap = builder.build();
    150     assertEquals(Arrays.asList(1, 2, 3, 1), multimap.get("foo"));
    151     assertEquals(Arrays.asList(4, 5), multimap.get("bar"));
    152     assertEquals(6, multimap.size());
    153   }
    154 
    155   public void testBuilderPutAllMultimapWithDuplicates() {
    156     Multimap<String, Integer> toPut = LinkedListMultimap.create();
    157     toPut.put("foo", 1);
    158     toPut.put("bar", 4);
    159     toPut.put("foo", 2);
    160     toPut.put("foo", 1);
    161     toPut.put("bar", 5);
    162     Multimap<String, Integer> moreToPut = LinkedListMultimap.create();
    163     moreToPut.put("foo", 6);
    164     moreToPut.put("bar", 4);
    165     moreToPut.put("foo", 7);
    166     moreToPut.put("foo", 2);
    167     ImmutableListMultimap.Builder<String, Integer> builder
    168         = ImmutableListMultimap.builder();
    169     builder.putAll(toPut);
    170     builder.putAll(moreToPut);
    171     Multimap<String, Integer> multimap = builder.build();
    172     assertEquals(Arrays.asList(1, 2, 1, 6, 7, 2), multimap.get("foo"));
    173     assertEquals(Arrays.asList(4, 5, 4), multimap.get("bar"));
    174     assertEquals(9, multimap.size());
    175   }
    176 
    177   public void testBuilderPutNullKey() {
    178     Multimap<String, Integer> toPut = LinkedListMultimap.create();
    179     toPut.put("foo", null);
    180     ImmutableListMultimap.Builder<String, Integer> builder
    181         = ImmutableListMultimap.builder();
    182     try {
    183       builder.put(null, 1);
    184       fail();
    185     } catch (NullPointerException expected) {}
    186     try {
    187       builder.putAll(null, Arrays.asList(1, 2, 3));
    188       fail();
    189     } catch (NullPointerException expected) {}
    190     try {
    191       builder.putAll(null, 1, 2, 3);
    192       fail();
    193     } catch (NullPointerException expected) {}
    194     try {
    195       builder.putAll(toPut);
    196       fail();
    197     } catch (NullPointerException expected) {}
    198   }
    199 
    200   public void testBuilderPutNullValue() {
    201     Multimap<String, Integer> toPut = LinkedListMultimap.create();
    202     toPut.put(null, 1);
    203     ImmutableListMultimap.Builder<String, Integer> builder
    204         = ImmutableListMultimap.builder();
    205     try {
    206       builder.put("foo", null);
    207       fail();
    208     } catch (NullPointerException expected) {}
    209     try {
    210       builder.putAll("foo", Arrays.asList(1, null, 3));
    211       fail();
    212     } catch (NullPointerException expected) {}
    213     try {
    214       builder.putAll("foo", 1, null, 3);
    215       fail();
    216     } catch (NullPointerException expected) {}
    217     try {
    218       builder.putAll(toPut);
    219       fail();
    220     } catch (NullPointerException expected) {}
    221   }
    222 
    223   public void testBuilderOrderKeysBy() {
    224     ImmutableListMultimap.Builder<String, Integer> builder
    225         = ImmutableListMultimap.builder();
    226     builder.put("b", 3);
    227     builder.put("d", 2);
    228     builder.put("a", 5);
    229     builder.orderKeysBy(Collections.reverseOrder());
    230     builder.put("c", 4);
    231     builder.put("a", 2);
    232     builder.put("b", 6);
    233     ImmutableListMultimap<String, Integer> multimap = builder.build();
    234     ASSERT.that(multimap.keySet()).hasContentsInOrder("d", "c", "b", "a");
    235     ASSERT.that(multimap.values()).hasContentsInOrder(2, 4, 3, 6, 5, 2);
    236     ASSERT.that(multimap.get("a")).hasContentsInOrder(5, 2);
    237     ASSERT.that(multimap.get("b")).hasContentsInOrder(3, 6);
    238   }
    239 
    240   public void testBuilderOrderValuesBy() {
    241     ImmutableListMultimap.Builder<String, Integer> builder
    242         = ImmutableListMultimap.builder();
    243     builder.put("b", 3);
    244     builder.put("d", 2);
    245     builder.put("a", 5);
    246     builder.orderValuesBy(Collections.reverseOrder());
    247     builder.put("c", 4);
    248     builder.put("a", 2);
    249     builder.put("b", 6);
    250     ImmutableListMultimap<String, Integer> multimap = builder.build();
    251     ASSERT.that(multimap.keySet()).hasContentsInOrder("b", "d", "a", "c");
    252     ASSERT.that(multimap.values()).hasContentsInOrder(6, 3, 2, 5, 2, 4);
    253     ASSERT.that(multimap.get("a")).hasContentsInOrder(5, 2);
    254     ASSERT.that(multimap.get("b")).hasContentsInOrder(6, 3);
    255   }
    256 
    257   public void testBuilderOrderKeysAndValuesBy() {
    258     ImmutableListMultimap.Builder<String, Integer> builder
    259         = ImmutableListMultimap.builder();
    260     builder.put("b", 3);
    261     builder.put("d", 2);
    262     builder.put("a", 5);
    263     builder.orderKeysBy(Collections.reverseOrder());
    264     builder.orderValuesBy(Collections.reverseOrder());
    265     builder.put("c", 4);
    266     builder.put("a", 2);
    267     builder.put("b", 6);
    268     ImmutableListMultimap<String, Integer> multimap = builder.build();
    269     ASSERT.that(multimap.keySet()).hasContentsInOrder("d", "c", "b", "a");
    270     ASSERT.that(multimap.values()).hasContentsInOrder(2, 4, 6, 3, 5, 2);
    271     ASSERT.that(multimap.get("a")).hasContentsInOrder(5, 2);
    272     ASSERT.that(multimap.get("b")).hasContentsInOrder(6, 3);
    273   }
    274 
    275   public void testCopyOf() {
    276     ArrayListMultimap<String, Integer> input = ArrayListMultimap.create();
    277     input.put("foo", 1);
    278     input.put("bar", 2);
    279     input.put("foo", 3);
    280     Multimap<String, Integer> multimap = ImmutableListMultimap.copyOf(input);
    281     assertEquals(multimap, input);
    282     assertEquals(input, multimap);
    283   }
    284 
    285   public void testCopyOfWithDuplicates() {
    286     ArrayListMultimap<String, Integer> input = ArrayListMultimap.create();
    287     input.put("foo", 1);
    288     input.put("bar", 2);
    289     input.put("foo", 3);
    290     input.put("foo", 1);
    291     Multimap<String, Integer> multimap = ImmutableListMultimap.copyOf(input);
    292     assertEquals(multimap, input);
    293     assertEquals(input, multimap);
    294   }
    295 
    296   public void testCopyOfEmpty() {
    297     ArrayListMultimap<String, Integer> input = ArrayListMultimap.create();
    298     Multimap<String, Integer> multimap = ImmutableListMultimap.copyOf(input);
    299     assertEquals(multimap, input);
    300     assertEquals(input, multimap);
    301   }
    302 
    303   public void testCopyOfImmutableListMultimap() {
    304     Multimap<String, Integer> multimap = createMultimap();
    305     assertSame(multimap, ImmutableListMultimap.copyOf(multimap));
    306   }
    307 
    308   public void testCopyOfNullKey() {
    309     ArrayListMultimap<String, Integer> input = ArrayListMultimap.create();
    310     input.put(null, 1);
    311     try {
    312       ImmutableListMultimap.copyOf(input);
    313       fail();
    314     } catch (NullPointerException expected) {}
    315   }
    316 
    317   public void testCopyOfNullValue() {
    318     ArrayListMultimap<String, Integer> input = ArrayListMultimap.create();
    319     input.putAll("foo", Arrays.asList(1, null, 3));
    320     try {
    321       ImmutableListMultimap.copyOf(input);
    322       fail();
    323     } catch (NullPointerException expected) {}
    324   }
    325 
    326   public void testEmptyMultimapReads() {
    327     Multimap<String, Integer> multimap = ImmutableListMultimap.of();
    328     assertFalse(multimap.containsKey("foo"));
    329     assertFalse(multimap.containsValue(1));
    330     assertFalse(multimap.containsEntry("foo", 1));
    331     assertTrue(multimap.entries().isEmpty());
    332     assertTrue(multimap.equals(ArrayListMultimap.create()));
    333     assertEquals(Collections.emptyList(), multimap.get("foo"));
    334     assertEquals(0, multimap.hashCode());
    335     assertTrue(multimap.isEmpty());
    336     assertEquals(HashMultiset.create(), multimap.keys());
    337     assertEquals(Collections.emptySet(), multimap.keySet());
    338     assertEquals(0, multimap.size());
    339     assertTrue(multimap.values().isEmpty());
    340     assertEquals("{}", multimap.toString());
    341   }
    342 
    343   public void testEmptyMultimapWrites() {
    344     Multimap<String, Integer> multimap = ImmutableListMultimap.of();
    345     UnmodifiableCollectionTests.assertMultimapIsUnmodifiable(
    346         multimap, "foo", 1);
    347   }
    348 
    349   private Multimap<String, Integer> createMultimap() {
    350     return ImmutableListMultimap.<String, Integer>builder()
    351         .put("foo", 1).put("bar", 2).put("foo", 3).build();
    352   }
    353 
    354   public void testMultimapReads() {
    355     Multimap<String, Integer> multimap = createMultimap();
    356     assertTrue(multimap.containsKey("foo"));
    357     assertFalse(multimap.containsKey("cat"));
    358     assertTrue(multimap.containsValue(1));
    359     assertFalse(multimap.containsValue(5));
    360     assertTrue(multimap.containsEntry("foo", 1));
    361     assertFalse(multimap.containsEntry("cat", 1));
    362     assertFalse(multimap.containsEntry("foo", 5));
    363     assertFalse(multimap.entries().isEmpty());
    364     assertEquals(3, multimap.size());
    365     assertFalse(multimap.isEmpty());
    366     assertEquals("{foo=[1, 3], bar=[2]}", multimap.toString());
    367   }
    368 
    369   public void testMultimapWrites() {
    370     Multimap<String, Integer> multimap = createMultimap();
    371     UnmodifiableCollectionTests.assertMultimapIsUnmodifiable(
    372         multimap, "bar", 2);
    373   }
    374 
    375   public void testMultimapEquals() {
    376     Multimap<String, Integer> multimap = createMultimap();
    377     Multimap<String, Integer> arrayListMultimap
    378         = ArrayListMultimap.create();
    379     arrayListMultimap.putAll("foo", Arrays.asList(1, 3));
    380     arrayListMultimap.put("bar", 2);
    381 
    382     new EqualsTester()
    383         .addEqualityGroup(multimap, createMultimap(), arrayListMultimap,
    384             ImmutableListMultimap.<String, Integer>builder()
    385                 .put("bar", 2).put("foo", 1).put("foo", 3).build())
    386         .addEqualityGroup(ImmutableListMultimap.<String, Integer>builder()
    387             .put("bar", 2).put("foo", 3).put("foo", 1).build())
    388         .addEqualityGroup(ImmutableListMultimap.<String, Integer>builder()
    389             .put("foo", 2).put("foo", 3).put("foo", 1).build())
    390         .addEqualityGroup(ImmutableListMultimap.<String, Integer>builder()
    391             .put("bar", 2).put("foo", 3).build())
    392         .testEquals();
    393   }
    394 
    395   public void testOf() {
    396     assertMultimapEquals(
    397         ImmutableListMultimap.of("one", 1),
    398         "one", 1);
    399     assertMultimapEquals(
    400         ImmutableListMultimap.of("one", 1, "two", 2),
    401         "one", 1, "two", 2);
    402     assertMultimapEquals(
    403         ImmutableListMultimap.of("one", 1, "two", 2, "three", 3),
    404         "one", 1, "two", 2, "three", 3);
    405     assertMultimapEquals(
    406         ImmutableListMultimap.of("one", 1, "two", 2, "three", 3, "four", 4),
    407         "one", 1, "two", 2, "three", 3, "four", 4);
    408     assertMultimapEquals(
    409         ImmutableListMultimap.of(
    410             "one", 1, "two", 2, "three", 3, "four", 4, "five", 5),
    411         "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
    412   }
    413 
    414   public void testInverse() {
    415     assertEquals(
    416         ImmutableListMultimap.<Integer, String>of(),
    417         ImmutableListMultimap.<String, Integer>of().inverse());
    418     assertEquals(
    419         ImmutableListMultimap.of(1, "one"),
    420         ImmutableListMultimap.of("one", 1).inverse());
    421     assertEquals(
    422         ImmutableListMultimap.of(1, "one", 2, "two"),
    423         ImmutableListMultimap.of("one", 1, "two", 2).inverse());
    424     assertEquals(
    425         ImmutableListMultimap.of("of", 'o', "of", 'f', "to", 't', "to", 'o').inverse(),
    426         ImmutableListMultimap.of('o', "of", 'f', "of", 't', "to", 'o', "to"));
    427     assertEquals(
    428         ImmutableListMultimap.of('f', "foo", 'o', "foo", 'o', "foo"),
    429         ImmutableListMultimap.of("foo", 'f', "foo", 'o', "foo", 'o').inverse());
    430   }
    431 
    432   public void testInverseMinimizesWork() {
    433     ImmutableListMultimap<String, Character> multimap =
    434         ImmutableListMultimap.<String, Character>builder()
    435             .put("foo", 'f')
    436             .put("foo", 'o')
    437             .put("foo", 'o')
    438             .put("poo", 'p')
    439             .put("poo", 'o')
    440             .put("poo", 'o')
    441             .build();
    442     assertSame(multimap.inverse(), multimap.inverse());
    443     assertSame(multimap, multimap.inverse().inverse());
    444   }
    445 
    446   private static <K, V> void assertMultimapEquals(Multimap<K, V> multimap,
    447       Object... alternatingKeysAndValues) {
    448     assertEquals(multimap.size(), alternatingKeysAndValues.length / 2);
    449     int i = 0;
    450     for (Entry<K, V> entry : multimap.entries()) {
    451       assertEquals(alternatingKeysAndValues[i++], entry.getKey());
    452       assertEquals(alternatingKeysAndValues[i++], entry.getValue());
    453     }
    454   }
    455 
    456   @GwtIncompatible("SerializableTester")
    457   public void testSerialization() {
    458     Multimap<String, Integer> multimap = createMultimap();
    459     SerializableTester.reserializeAndAssert(multimap);
    460     assertEquals(multimap.size(),
    461         SerializableTester.reserialize(multimap).size());
    462     SerializableTester.reserializeAndAssert(multimap.get("foo"));
    463     LenientSerializableTester.reserializeAndAssertLenient(multimap.keySet());
    464     SerializableTester.reserializeAndAssert(multimap.keys());
    465     SerializableTester.reserializeAndAssert(multimap.asMap());
    466     Collection<Integer> valuesCopy
    467         = SerializableTester.reserialize(multimap.values());
    468     assertEquals(HashMultiset.create(multimap.values()),
    469         HashMultiset.create(valuesCopy));
    470   }
    471 
    472   @GwtIncompatible("SerializableTester")
    473   public void testEmptySerialization() {
    474     Multimap<String, Integer> multimap = ImmutableListMultimap.of();
    475     assertSame(multimap, SerializableTester.reserialize(multimap));
    476   }
    477 }
    478