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