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.base.Joiner;
     24 import com.google.common.collect.ImmutableBiMap.Builder;
     25 import com.google.common.collect.testing.MapInterfaceTest;
     26 import com.google.common.collect.testing.features.CollectionFeature;
     27 import com.google.common.collect.testing.features.CollectionSize;
     28 import com.google.common.collect.testing.features.MapFeature;
     29 import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapCopyOfGenerator;
     30 import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapGenerator;
     31 import com.google.common.collect.testing.google.BiMapInverseTester;
     32 import com.google.common.collect.testing.google.BiMapTestSuiteBuilder;
     33 import com.google.common.testing.SerializableTester;
     34 
     35 import junit.framework.Test;
     36 import junit.framework.TestCase;
     37 import junit.framework.TestSuite;
     38 
     39 import java.util.Collections;
     40 import java.util.LinkedHashMap;
     41 import java.util.Map;
     42 import java.util.Map.Entry;
     43 import java.util.Set;
     44 
     45 /**
     46  * Tests for {@link ImmutableBiMap}.
     47  *
     48  * @author Jared Levy
     49  */
     50 @GwtCompatible(emulated = true)
     51 public class ImmutableBiMapTest extends TestCase {
     52 
     53   // TODO: Reduce duplication of ImmutableMapTest code
     54 
     55   @GwtIncompatible("suite")
     56   public static Test suite() {
     57     TestSuite suite = new TestSuite();
     58 
     59     suite.addTestSuite(MapTests.class);
     60     suite.addTestSuite(InverseMapTests.class);
     61     suite.addTestSuite(CreationTests.class);
     62     suite.addTestSuite(BiMapSpecificTests.class);
     63 
     64     suite.addTest(BiMapTestSuiteBuilder.using(new ImmutableBiMapGenerator())
     65         .named("ImmutableBiMap")
     66         .withFeatures(CollectionSize.ANY,
     67             CollectionFeature.SERIALIZABLE,
     68             CollectionFeature.KNOWN_ORDER,
     69             MapFeature.REJECTS_DUPLICATES_AT_CREATION,
     70             MapFeature.ALLOWS_ANY_NULL_QUERIES)
     71         .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
     72         .createTestSuite());
     73     suite.addTest(BiMapTestSuiteBuilder.using(new ImmutableBiMapCopyOfGenerator())
     74         .named("ImmutableBiMap.copyOf")
     75         .withFeatures(CollectionSize.ANY,
     76             CollectionFeature.SERIALIZABLE,
     77             CollectionFeature.KNOWN_ORDER,
     78             MapFeature.ALLOWS_ANY_NULL_QUERIES)
     79         .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
     80         .createTestSuite());
     81 
     82     return suite;
     83   }
     84 
     85   public static abstract class AbstractMapTests<K, V>
     86       extends MapInterfaceTest<K, V> {
     87     public AbstractMapTests() {
     88       super(false, false, false, false, false);
     89     }
     90 
     91     @Override protected Map<K, V> makeEmptyMap() {
     92       throw new UnsupportedOperationException();
     93     }
     94 
     95     private static final Joiner joiner = Joiner.on(", ");
     96 
     97     @Override protected void assertMoreInvariants(Map<K, V> map) {
     98 
     99       BiMap<K, V> bimap = (BiMap<K, V>) map;
    100 
    101       for (Entry<K, V> entry : map.entrySet()) {
    102         assertEquals(entry.getKey() + "=" + entry.getValue(),
    103             entry.toString());
    104         assertEquals(entry.getKey(), bimap.inverse().get(entry.getValue()));
    105       }
    106 
    107       assertEquals("{" + joiner.join(map.entrySet()) + "}",
    108           map.toString());
    109       assertEquals("[" + joiner.join(map.entrySet()) + "]",
    110           map.entrySet().toString());
    111       assertEquals("[" + joiner.join(map.keySet()) + "]",
    112           map.keySet().toString());
    113       assertEquals("[" + joiner.join(map.values()) + "]",
    114           map.values().toString());
    115 
    116       assertEquals(Sets.newHashSet(map.entrySet()), map.entrySet());
    117       assertEquals(Sets.newHashSet(map.keySet()), map.keySet());
    118     }
    119   }
    120 
    121   public static class MapTests extends AbstractMapTests<String, Integer> {
    122     @Override protected Map<String, Integer> makeEmptyMap() {
    123       return ImmutableBiMap.of();
    124     }
    125 
    126     @Override protected Map<String, Integer> makePopulatedMap() {
    127       return ImmutableBiMap.of("one", 1, "two", 2, "three", 3);
    128     }
    129 
    130     @Override protected String getKeyNotInPopulatedMap() {
    131       return "minus one";
    132     }
    133 
    134     @Override protected Integer getValueNotInPopulatedMap() {
    135       return -1;
    136     }
    137   }
    138 
    139   public static class InverseMapTests
    140       extends AbstractMapTests<String, Integer> {
    141     @Override protected Map<String, Integer> makeEmptyMap() {
    142       return ImmutableBiMap.of();
    143     }
    144 
    145     @Override protected Map<String, Integer> makePopulatedMap() {
    146       return ImmutableBiMap.of(1, "one", 2, "two", 3, "three").inverse();
    147     }
    148 
    149     @Override protected String getKeyNotInPopulatedMap() {
    150       return "minus one";
    151     }
    152 
    153     @Override protected Integer getValueNotInPopulatedMap() {
    154       return -1;
    155     }
    156   }
    157 
    158   public static class CreationTests extends TestCase {
    159     public void testEmptyBuilder() {
    160       ImmutableBiMap<String, Integer> map
    161           = new Builder<String, Integer>().build();
    162       assertEquals(Collections.<String, Integer>emptyMap(), map);
    163       assertEquals(Collections.<Integer, String>emptyMap(), map.inverse());
    164       assertSame(ImmutableBiMap.of(), map);
    165     }
    166 
    167     public void testSingletonBuilder() {
    168       ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
    169           .put("one", 1)
    170           .build();
    171       assertMapEquals(map, "one", 1);
    172       assertMapEquals(map.inverse(), 1, "one");
    173     }
    174 
    175     public void testBuilder() {
    176       ImmutableBiMap<String, Integer> map
    177           = ImmutableBiMap.<String, Integer>builder()
    178             .put("one", 1)
    179             .put("two", 2)
    180             .put("three", 3)
    181             .put("four", 4)
    182             .put("five", 5)
    183             .build();
    184       assertMapEquals(map,
    185           "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
    186       assertMapEquals(map.inverse(),
    187           1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
    188     }
    189 
    190     public void testBuilderPutAllWithEmptyMap() {
    191       ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
    192           .putAll(Collections.<String, Integer>emptyMap())
    193           .build();
    194       assertEquals(Collections.<String, Integer>emptyMap(), map);
    195     }
    196 
    197     public void testBuilderPutAll() {
    198       Map<String, Integer> toPut = new LinkedHashMap<String, Integer>();
    199       toPut.put("one", 1);
    200       toPut.put("two", 2);
    201       toPut.put("three", 3);
    202       Map<String, Integer> moreToPut = new LinkedHashMap<String, Integer>();
    203       moreToPut.put("four", 4);
    204       moreToPut.put("five", 5);
    205 
    206       ImmutableBiMap<String, Integer> map = new Builder<String, Integer>()
    207           .putAll(toPut)
    208           .putAll(moreToPut)
    209           .build();
    210       assertMapEquals(map,
    211           "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
    212       assertMapEquals(map.inverse(),
    213           1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
    214     }
    215 
    216     public void testBuilderReuse() {
    217       Builder<String, Integer> builder = new Builder<String, Integer>();
    218       ImmutableBiMap<String, Integer> mapOne = builder
    219           .put("one", 1)
    220           .put("two", 2)
    221           .build();
    222       ImmutableBiMap<String, Integer> mapTwo = builder
    223           .put("three", 3)
    224           .put("four", 4)
    225           .build();
    226 
    227       assertMapEquals(mapOne, "one", 1, "two", 2);
    228       assertMapEquals(mapOne.inverse(), 1, "one", 2, "two");
    229       assertMapEquals(mapTwo, "one", 1, "two", 2, "three", 3, "four", 4);
    230       assertMapEquals(mapTwo.inverse(),
    231           1, "one", 2, "two", 3, "three", 4, "four");
    232     }
    233 
    234     public void testBuilderPutNullKey() {
    235       Builder<String, Integer> builder = new Builder<String, Integer>();
    236       try {
    237         builder.put(null, 1);
    238         fail();
    239       } catch (NullPointerException expected) {
    240       }
    241     }
    242 
    243     public void testBuilderPutNullValue() {
    244       Builder<String, Integer> builder = new Builder<String, Integer>();
    245       try {
    246         builder.put("one", null);
    247         fail();
    248       } catch (NullPointerException expected) {
    249       }
    250     }
    251 
    252     public void testBuilderPutNullKeyViaPutAll() {
    253       Builder<String, Integer> builder = new Builder<String, Integer>();
    254       try {
    255         builder.putAll(Collections.<String, Integer>singletonMap(null, 1));
    256         fail();
    257       } catch (NullPointerException expected) {
    258       }
    259     }
    260 
    261     public void testBuilderPutNullValueViaPutAll() {
    262       Builder<String, Integer> builder = new Builder<String, Integer>();
    263       try {
    264         builder.putAll(Collections.<String, Integer>singletonMap("one", null));
    265         fail();
    266       } catch (NullPointerException expected) {
    267       }
    268     }
    269 
    270     public void testPuttingTheSameKeyTwiceThrowsOnBuild() {
    271       Builder<String, Integer> builder = new Builder<String, Integer>()
    272           .put("one", 1)
    273           .put("one", 1); // throwing on this line would be even better
    274 
    275       try {
    276         builder.build();
    277         fail();
    278       } catch (IllegalArgumentException expected) {
    279         assertTrue(expected.getMessage().contains("one"));
    280       }
    281     }
    282 
    283     public void testOf() {
    284       assertMapEquals(
    285           ImmutableBiMap.of("one", 1),
    286           "one", 1);
    287       assertMapEquals(
    288           ImmutableBiMap.of("one", 1).inverse(),
    289           1, "one");
    290       assertMapEquals(
    291           ImmutableBiMap.of("one", 1, "two", 2),
    292           "one", 1, "two", 2);
    293       assertMapEquals(
    294           ImmutableBiMap.of("one", 1, "two", 2).inverse(),
    295           1, "one", 2, "two");
    296       assertMapEquals(
    297           ImmutableBiMap.of("one", 1, "two", 2, "three", 3),
    298           "one", 1, "two", 2, "three", 3);
    299       assertMapEquals(
    300           ImmutableBiMap.of("one", 1, "two", 2, "three", 3).inverse(),
    301           1, "one", 2, "two", 3, "three");
    302       assertMapEquals(
    303           ImmutableBiMap.of("one", 1, "two", 2, "three", 3, "four", 4),
    304           "one", 1, "two", 2, "three", 3, "four", 4);
    305       assertMapEquals(
    306           ImmutableBiMap.of(
    307               "one", 1, "two", 2, "three", 3, "four", 4).inverse(),
    308           1, "one", 2, "two", 3, "three", 4, "four");
    309       assertMapEquals(
    310           ImmutableBiMap.of(
    311               "one", 1, "two", 2, "three", 3, "four", 4, "five", 5),
    312           "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
    313       assertMapEquals(
    314           ImmutableBiMap.of(
    315               "one", 1, "two", 2, "three", 3, "four", 4, "five", 5).inverse(),
    316           1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
    317     }
    318 
    319     public void testOfNullKey() {
    320       try {
    321         ImmutableBiMap.of(null, 1);
    322         fail();
    323       } catch (NullPointerException expected) {
    324       }
    325 
    326       try {
    327         ImmutableBiMap.of("one", 1, null, 2);
    328         fail();
    329       } catch (NullPointerException expected) {
    330       }
    331     }
    332 
    333     public void testOfNullValue() {
    334       try {
    335         ImmutableBiMap.of("one", null);
    336         fail();
    337       } catch (NullPointerException expected) {
    338       }
    339 
    340       try {
    341         ImmutableBiMap.of("one", 1, "two", null);
    342         fail();
    343       } catch (NullPointerException expected) {
    344       }
    345     }
    346 
    347     public void testOfWithDuplicateKey() {
    348       try {
    349         ImmutableBiMap.of("one", 1, "one", 1);
    350         fail();
    351       } catch (IllegalArgumentException expected) {
    352         assertTrue(expected.getMessage().contains("one"));
    353       }
    354     }
    355 
    356     public void testCopyOfEmptyMap() {
    357       ImmutableBiMap<String, Integer> copy
    358           = ImmutableBiMap.copyOf(Collections.<String, Integer>emptyMap());
    359       assertEquals(Collections.<String, Integer>emptyMap(), copy);
    360       assertSame(copy, ImmutableBiMap.copyOf(copy));
    361       assertSame(ImmutableBiMap.of(), copy);
    362     }
    363 
    364     public void testCopyOfSingletonMap() {
    365       ImmutableBiMap<String, Integer> copy
    366           = ImmutableBiMap.copyOf(Collections.singletonMap("one", 1));
    367       assertMapEquals(copy, "one", 1);
    368       assertSame(copy, ImmutableBiMap.copyOf(copy));
    369     }
    370 
    371     public void testCopyOf() {
    372       Map<String, Integer> original = new LinkedHashMap<String, Integer>();
    373       original.put("one", 1);
    374       original.put("two", 2);
    375       original.put("three", 3);
    376 
    377       ImmutableBiMap<String, Integer> copy = ImmutableBiMap.copyOf(original);
    378       assertMapEquals(copy, "one", 1, "two", 2, "three", 3);
    379       assertSame(copy, ImmutableBiMap.copyOf(copy));
    380     }
    381 
    382     public void testEmpty() {
    383       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.of();
    384       assertEquals(Collections.<String, Integer>emptyMap(), bimap);
    385       assertEquals(Collections.<String, Integer>emptyMap(), bimap.inverse());
    386     }
    387 
    388     public void testFromHashMap() {
    389       Map<String, Integer> hashMap = Maps.newLinkedHashMap();
    390       hashMap.put("one", 1);
    391       hashMap.put("two", 2);
    392       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf(
    393           ImmutableMap.of("one", 1, "two", 2));
    394       assertMapEquals(bimap, "one", 1, "two", 2);
    395       assertMapEquals(bimap.inverse(), 1, "one", 2, "two");
    396     }
    397 
    398     public void testFromImmutableMap() {
    399       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf(
    400           new ImmutableMap.Builder<String, Integer>()
    401               .put("one", 1)
    402               .put("two", 2)
    403               .put("three", 3)
    404               .put("four", 4)
    405               .put("five", 5)
    406               .build());
    407       assertMapEquals(bimap,
    408           "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
    409       assertMapEquals(bimap.inverse(),
    410           1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
    411     }
    412 
    413     public void testDuplicateValues() {
    414       ImmutableMap<String, Integer> map
    415           = new ImmutableMap.Builder<String, Integer>()
    416               .put("one", 1)
    417               .put("two", 2)
    418               .put("uno", 1)
    419               .put("dos", 2)
    420               .build();
    421 
    422       try {
    423         ImmutableBiMap.copyOf(map);
    424         fail();
    425       } catch (IllegalArgumentException expected) {
    426         assertTrue(expected.getMessage().contains("1"));
    427       }
    428     }
    429   }
    430 
    431   public static class BiMapSpecificTests extends TestCase {
    432 
    433     @SuppressWarnings("deprecation")
    434     public void testForcePut() {
    435       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf(
    436           ImmutableMap.of("one", 1, "two", 2));
    437       try {
    438         bimap.forcePut("three", 3);
    439         fail();
    440       } catch (UnsupportedOperationException expected) {}
    441     }
    442 
    443     public void testKeySet() {
    444       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf(
    445           ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
    446       Set<String> keys = bimap.keySet();
    447       assertEquals(Sets.newHashSet("one", "two", "three", "four"), keys);
    448       assertThat(keys).has().exactly("one", "two", "three", "four").inOrder();
    449     }
    450 
    451     public void testValues() {
    452       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf(
    453           ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
    454       Set<Integer> values = bimap.values();
    455       assertEquals(Sets.newHashSet(1, 2, 3, 4), values);
    456       assertThat(values).has().exactly(1, 2, 3, 4).inOrder();
    457     }
    458 
    459     public void testDoubleInverse() {
    460       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf(
    461           ImmutableMap.of("one", 1, "two", 2));
    462       assertSame(bimap, bimap.inverse().inverse());
    463     }
    464 
    465     @GwtIncompatible("SerializableTester")
    466     public void testEmptySerialization() {
    467       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.of();
    468       assertSame(bimap, SerializableTester.reserializeAndAssert(bimap));
    469     }
    470 
    471     @GwtIncompatible("SerializableTester")
    472     public void testSerialization() {
    473       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf(
    474           ImmutableMap.of("one", 1, "two", 2));
    475       ImmutableBiMap<String, Integer> copy =
    476           SerializableTester.reserializeAndAssert(bimap);
    477       assertEquals(Integer.valueOf(1), copy.get("one"));
    478       assertEquals("one", copy.inverse().get(1));
    479       assertSame(copy, copy.inverse().inverse());
    480     }
    481 
    482     @GwtIncompatible("SerializableTester")
    483     public void testInverseSerialization() {
    484       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf(
    485           ImmutableMap.of(1, "one", 2, "two")).inverse();
    486       ImmutableBiMap<String, Integer> copy =
    487           SerializableTester.reserializeAndAssert(bimap);
    488       assertEquals(Integer.valueOf(1), copy.get("one"));
    489       assertEquals("one", copy.inverse().get(1));
    490       assertSame(copy, copy.inverse().inverse());
    491     }
    492   }
    493 
    494   private static <K, V> void assertMapEquals(Map<K, V> map,
    495       Object... alternatingKeysAndValues) {
    496     int i = 0;
    497     for (Entry<K, V> entry : map.entrySet()) {
    498       assertEquals(alternatingKeysAndValues[i++], entry.getKey());
    499       assertEquals(alternatingKeysAndValues[i++], entry.getValue());
    500     }
    501   }
    502 }
    503