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.testing.Helpers.orderEntriesByKey;
     20 import static com.google.common.truth.Truth.assertThat;
     21 
     22 import com.google.common.annotations.GwtCompatible;
     23 import com.google.common.annotations.GwtIncompatible;
     24 import com.google.common.collect.testing.Helpers;
     25 import com.google.common.collect.testing.SampleElements;
     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.BiMapTestSuiteBuilder;
     30 import com.google.common.collect.testing.google.TestBiMapGenerator;
     31 import com.google.common.testing.EqualsTester;
     32 import com.google.common.testing.NullPointerTester;
     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.Iterator;
     41 import java.util.List;
     42 import java.util.Map;
     43 import java.util.Map.Entry;
     44 import java.util.Set;
     45 
     46 /**
     47  * Tests for {@code EnumBiMap}.
     48  *
     49  * @author Mike Bostock
     50  * @author Jared Levy
     51  */
     52 @GwtCompatible(emulated = true)
     53 public class EnumBiMapTest extends TestCase {
     54   private enum Currency { DOLLAR, FRANC, PESO, POUND, YEN }
     55   private enum Country { CANADA, CHILE, JAPAN, SWITZERLAND, UK }
     56 
     57   public static final class EnumBiMapGenerator implements TestBiMapGenerator<Country, Currency> {
     58     @SuppressWarnings("unchecked")
     59     @Override
     60     public BiMap<Country, Currency> create(Object... entries) {
     61       BiMap<Country, Currency> result = EnumBiMap.create(Country.class, Currency.class);
     62       for (Object object : entries) {
     63         Entry<Country, Currency> entry = (Entry<Country, Currency>) object;
     64         result.put(entry.getKey(), entry.getValue());
     65       }
     66       return result;
     67     }
     68 
     69     @Override
     70     public SampleElements<Entry<Country, Currency>> samples() {
     71       return new SampleElements<Entry<Country, Currency>>(
     72           Helpers.mapEntry(Country.CANADA, Currency.DOLLAR),
     73           Helpers.mapEntry(Country.CHILE, Currency.PESO),
     74           Helpers.mapEntry(Country.UK, Currency.POUND),
     75           Helpers.mapEntry(Country.JAPAN, Currency.YEN),
     76           Helpers.mapEntry(Country.SWITZERLAND, Currency.FRANC));
     77     }
     78 
     79     @SuppressWarnings("unchecked")
     80     @Override
     81     public Entry<Country, Currency>[] createArray(int length) {
     82       return new Entry[length];
     83     }
     84 
     85     @Override
     86     public Iterable<Entry<Country, Currency>> order(List<Entry<Country, Currency>> insertionOrder) {
     87       return orderEntriesByKey(insertionOrder);
     88     }
     89 
     90     @Override
     91     public Country[] createKeyArray(int length) {
     92       return new Country[length];
     93     }
     94 
     95     @Override
     96     public Currency[] createValueArray(int length) {
     97       return new Currency[length];
     98     }
     99   }
    100 
    101   @GwtIncompatible("suite")
    102   public static Test suite() {
    103     TestSuite suite = new TestSuite();
    104     suite.addTest(BiMapTestSuiteBuilder.using(new EnumBiMapGenerator())
    105         .named("EnumBiMap")
    106         .withFeatures(CollectionSize.ANY,
    107             CollectionFeature.SERIALIZABLE,
    108             CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
    109             MapFeature.GENERAL_PURPOSE,
    110             CollectionFeature.KNOWN_ORDER)
    111         .createTestSuite());
    112     suite.addTestSuite(EnumBiMapTest.class);
    113     return suite;
    114   }
    115 
    116   public void testCreate() {
    117     EnumBiMap<Currency, Country> bimap =
    118         EnumBiMap.create(Currency.class, Country.class);
    119     assertTrue(bimap.isEmpty());
    120     assertEquals("{}", bimap.toString());
    121     assertEquals(HashBiMap.create(), bimap);
    122     bimap.put(Currency.DOLLAR, Country.CANADA);
    123     assertEquals(Country.CANADA, bimap.get(Currency.DOLLAR));
    124     assertEquals(Currency.DOLLAR, bimap.inverse().get(Country.CANADA));
    125   }
    126 
    127   public void testCreateFromMap() {
    128     /* Test with non-empty Map. */
    129     Map<Currency, Country> map = ImmutableMap.of(
    130         Currency.DOLLAR, Country.CANADA,
    131         Currency.PESO, Country.CHILE,
    132         Currency.FRANC, Country.SWITZERLAND);
    133     EnumBiMap<Currency, Country> bimap = EnumBiMap.create(map);
    134     assertEquals(Country.CANADA, bimap.get(Currency.DOLLAR));
    135     assertEquals(Currency.DOLLAR, bimap.inverse().get(Country.CANADA));
    136 
    137     /* Map must have at least one entry if not an EnumBiMap. */
    138     try {
    139       EnumBiMap.create(Collections.<Currency, Country>emptyMap());
    140       fail("IllegalArgumentException expected");
    141     } catch (IllegalArgumentException expected) {}
    142     try {
    143       EnumBiMap.create(
    144           EnumHashBiMap.<Currency, Country>create(Currency.class));
    145       fail("IllegalArgumentException expected");
    146     } catch (IllegalArgumentException expected) {}
    147 
    148     /* Map can be empty if it's an EnumBiMap. */
    149     Map<Currency, Country> emptyBimap =
    150         EnumBiMap.create(Currency.class, Country.class);
    151     bimap = EnumBiMap.create(emptyBimap);
    152     assertTrue(bimap.isEmpty());
    153   }
    154 
    155   public void testEnumBiMapConstructor() {
    156     /* Test that it copies existing entries. */
    157     EnumBiMap<Currency, Country> bimap1 =
    158         EnumBiMap.create(Currency.class, Country.class);
    159     bimap1.put(Currency.DOLLAR, Country.CANADA);
    160     EnumBiMap<Currency, Country> bimap2 =
    161         EnumBiMap.create(bimap1);
    162     assertEquals(Country.CANADA, bimap2.get(Currency.DOLLAR));
    163     assertEquals(bimap1, bimap2);
    164     bimap2.inverse().put(Country.SWITZERLAND, Currency.FRANC);
    165     assertEquals(Country.SWITZERLAND, bimap2.get(Currency.FRANC));
    166     assertNull(bimap1.get(Currency.FRANC));
    167     assertFalse(bimap2.equals(bimap1));
    168 
    169     /* Test that it can be empty. */
    170     EnumBiMap<Currency, Country> emptyBimap =
    171         EnumBiMap.create(Currency.class, Country.class);
    172     EnumBiMap<Currency, Country> bimap3 =
    173         EnumBiMap.create(emptyBimap);
    174     assertEquals(bimap3, emptyBimap);
    175   }
    176 
    177   public void testKeyType() {
    178     EnumBiMap<Currency, Country> bimap =
    179         EnumBiMap.create(Currency.class, Country.class);
    180     assertEquals(Currency.class, bimap.keyType());
    181   }
    182 
    183   public void testValueType() {
    184     EnumBiMap<Currency, Country> bimap =
    185         EnumBiMap.create(Currency.class, Country.class);
    186     assertEquals(Country.class, bimap.valueType());
    187   }
    188 
    189   public void testIterationOrder() {
    190     // The enum orderings are alphabetical, leading to the bimap and its inverse
    191     // having inconsistent iteration orderings.
    192     Map<Currency, Country> map = ImmutableMap.of(
    193         Currency.DOLLAR, Country.CANADA,
    194         Currency.PESO, Country.CHILE,
    195         Currency.FRANC, Country.SWITZERLAND);
    196     EnumBiMap<Currency, Country> bimap = EnumBiMap.create(map);
    197 
    198     // forward map ordered by currency
    199     assertThat(bimap.keySet())
    200         .has().exactly(Currency.DOLLAR, Currency.FRANC, Currency.PESO).inOrder();
    201     // forward map ordered by currency (even for country values)
    202     assertThat(bimap.values())
    203         .has().exactly(Country.CANADA, Country.SWITZERLAND, Country.CHILE).inOrder();
    204     // backward map ordered by country
    205     assertThat(bimap.inverse().keySet())
    206         .has().exactly(Country.CANADA, Country.CHILE, Country.SWITZERLAND).inOrder();
    207     // backward map ordered by country (even for currency values)
    208     assertThat(bimap.inverse().values())
    209         .has().exactly(Currency.DOLLAR, Currency.PESO, Currency.FRANC).inOrder();
    210   }
    211 
    212   public void testKeySetIteratorRemove() {
    213     // The enum orderings are alphabetical, leading to the bimap and its inverse
    214     // having inconsistent iteration orderings.
    215     Map<Currency, Country> map = ImmutableMap.of(
    216         Currency.DOLLAR, Country.CANADA,
    217         Currency.PESO, Country.CHILE,
    218         Currency.FRANC, Country.SWITZERLAND);
    219     EnumBiMap<Currency, Country> bimap = EnumBiMap.create(map);
    220 
    221     Iterator<Currency> iter = bimap.keySet().iterator();
    222     assertEquals(Currency.DOLLAR, iter.next());
    223     iter.remove();
    224 
    225     // forward map ordered by currency
    226     assertThat(bimap.keySet())
    227         .has().exactly(Currency.FRANC, Currency.PESO).inOrder();
    228     // forward map ordered by currency (even for country values)
    229     assertThat(bimap.values())
    230         .has().exactly(Country.SWITZERLAND, Country.CHILE).inOrder();
    231     // backward map ordered by country
    232     assertThat(bimap.inverse().keySet())
    233         .has().exactly(Country.CHILE, Country.SWITZERLAND).inOrder();
    234     // backward map ordered by country (even for currency values)
    235     assertThat(bimap.inverse().values())
    236         .has().exactly(Currency.PESO, Currency.FRANC).inOrder();
    237   }
    238 
    239   public void testValuesIteratorRemove() {
    240     // The enum orderings are alphabetical, leading to the bimap and its inverse
    241     // having inconsistent iteration orderings.
    242     Map<Currency, Country> map = ImmutableMap.of(
    243         Currency.DOLLAR, Country.CANADA,
    244         Currency.PESO, Country.CHILE,
    245         Currency.FRANC, Country.SWITZERLAND);
    246     EnumBiMap<Currency, Country> bimap = EnumBiMap.create(map);
    247 
    248     Iterator<Currency> iter = bimap.keySet().iterator();
    249     assertEquals(Currency.DOLLAR, iter.next());
    250     assertEquals(Currency.FRANC, iter.next());
    251     iter.remove();
    252 
    253     // forward map ordered by currency
    254     assertThat(bimap.keySet())
    255         .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
    256     // forward map ordered by currency (even for country values)
    257     assertThat(bimap.values())
    258         .has().exactly(Country.CANADA, Country.CHILE).inOrder();
    259     // backward map ordered by country
    260     assertThat(bimap.inverse().keySet())
    261         .has().exactly(Country.CANADA, Country.CHILE).inOrder();
    262     // backward map ordered by country (even for currency values)
    263     assertThat(bimap.inverse().values())
    264         .has().exactly(Currency.DOLLAR, Currency.PESO).inOrder();
    265   }
    266 
    267   public void testEntrySet() {
    268     // Bug 3168290
    269     Map<Currency, Country> map = ImmutableMap.of(
    270         Currency.DOLLAR, Country.CANADA,
    271         Currency.PESO, Country.CHILE,
    272         Currency.FRANC, Country.SWITZERLAND);
    273     EnumBiMap<Currency, Country> bimap = EnumBiMap.create(map);
    274     Set<Object> uniqueEntries = Sets.newIdentityHashSet();
    275     uniqueEntries.addAll(bimap.entrySet());
    276     assertEquals(3, uniqueEntries.size());
    277   }
    278 
    279   @GwtIncompatible("serialization")
    280   public void testSerializable() {
    281     SerializableTester.reserializeAndAssert(
    282         EnumBiMap.create(ImmutableMap.of(Currency.DOLLAR, Country.CANADA)));
    283   }
    284 
    285   @GwtIncompatible("reflection")
    286   public void testNulls() {
    287     new NullPointerTester().testAllPublicStaticMethods(EnumBiMap.class);
    288     new NullPointerTester()
    289         .testAllPublicInstanceMethods(
    290             EnumBiMap.create(ImmutableMap.of(Currency.DOLLAR, Country.CHILE)));
    291   }
    292 
    293   public void testEquals() {
    294     new EqualsTester()
    295         .addEqualityGroup(
    296             EnumBiMap.create(ImmutableMap.of(Currency.DOLLAR, Country.CANADA)),
    297             EnumBiMap.create(ImmutableMap.of(Currency.DOLLAR, Country.CANADA)))
    298         .addEqualityGroup(EnumBiMap.create(ImmutableMap.of(Currency.DOLLAR, Country.CHILE)))
    299         .addEqualityGroup(EnumBiMap.create(ImmutableMap.of(Currency.FRANC, Country.CANADA)))
    300         .testEquals();
    301   }
    302 
    303   /* Remaining behavior tested by AbstractBiMapTest. */
    304 }
    305