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