• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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")
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> {
AbstractMapTests()145     public AbstractMapTests() {
146       super(false, false, false, false, false);
147     }
148 
makeEmptyMap()149     @Override protected Map<K, V> makeEmptyMap() {
150       throw new UnsupportedOperationException();
151     }
152 
153     private static final Joiner joiner = Joiner.on(", ");
154 
assertMoreInvariants(Map<K, V> map)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> {
makeEmptyMap()180     @Override protected Map<String, Integer> makeEmptyMap() {
181       return ImmutableBiMap.of();
182     }
183 
makePopulatedMap()184     @Override protected Map<String, Integer> makePopulatedMap() {
185       return ImmutableBiMap.of("one", 1, "two", 2, "three", 3);
186     }
187 
getKeyNotInPopulatedMap()188     @Override protected String getKeyNotInPopulatedMap() {
189       return "minus one";
190     }
191 
getValueNotInPopulatedMap()192     @Override protected Integer getValueNotInPopulatedMap() {
193       return -1;
194     }
195   }
196 
197   public static class InverseMapTests
198       extends AbstractMapTests<String, Integer> {
makeEmptyMap()199     @Override protected Map<String, Integer> makeEmptyMap() {
200       return ImmutableBiMap.of();
201     }
202 
makePopulatedMap()203     @Override protected Map<String, Integer> makePopulatedMap() {
204       return ImmutableBiMap.of(1, "one", 2, "two", 3, "three").inverse();
205     }
206 
getKeyNotInPopulatedMap()207     @Override protected String getKeyNotInPopulatedMap() {
208       return "minus one";
209     }
210 
getValueNotInPopulatedMap()211     @Override protected Integer getValueNotInPopulatedMap() {
212       return -1;
213     }
214   }
215 
216   public static class CreationTests extends TestCase {
testEmptyBuilder()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 
testSingletonBuilder()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 
testBuilder()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 
testBuilderPutAllWithEmptyMap()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 
testBuilderPutAll()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 
testBuilderReuse()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 
testBuilderPutNullKey()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 
testBuilderPutNullValue()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 
testBuilderPutNullKeyViaPutAll()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 
testBuilderPutNullValueViaPutAll()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 
testPuttingTheSameKeyTwiceThrowsOnBuild()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 
testOf()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 
testOfNullKey()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 
testOfNullValue()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 
testOfWithDuplicateKey()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 
testCopyOfEmptyMap()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 
testCopyOfSingletonMap()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 
testCopyOf()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 
testEmpty()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 
testFromHashMap()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 
testFromImmutableMap()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 
testDuplicateValues()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 
testForcePut()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 
testKeySet()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 
testValues()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 
testDoubleInverse()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")
testEmptySerialization()523     public void testEmptySerialization() {
524       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.of();
525       assertSame(bimap, SerializableTester.reserializeAndAssert(bimap));
526     }
527 
528     @GwtIncompatible("SerializableTester")
testSerialization()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")
testInverseSerialization()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 
assertMapEquals(Map<K, V> map, Object... alternatingKeysAndValues)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