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