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