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