• 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.collect.testing.Helpers.mapEntry;
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.base.Equivalence;
25 import com.google.common.base.Joiner;
26 import com.google.common.collect.ImmutableBiMap.Builder;
27 import com.google.common.collect.testing.MapInterfaceTest;
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.features.MapFeature;
31 import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapCopyOfEntriesGenerator;
32 import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapCopyOfGenerator;
33 import com.google.common.collect.testing.google.BiMapGenerators.ImmutableBiMapGenerator;
34 import com.google.common.collect.testing.google.BiMapInverseTester;
35 import com.google.common.collect.testing.google.BiMapTestSuiteBuilder;
36 import com.google.common.collect.testing.google.TestStringBiMapGenerator;
37 import com.google.common.testing.CollectorTester;
38 import com.google.common.testing.SerializableTester;
39 import com.google.errorprone.annotations.CanIgnoreReturnValue;
40 import java.util.AbstractMap;
41 import java.util.Arrays;
42 import java.util.Collections;
43 import java.util.EnumSet;
44 import java.util.LinkedHashMap;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.Map.Entry;
48 import java.util.Set;
49 import java.util.stream.Collector;
50 import java.util.stream.Stream;
51 import junit.framework.Test;
52 import junit.framework.TestCase;
53 import junit.framework.TestSuite;
54 
55 /**
56  * Tests for {@link ImmutableBiMap}.
57  *
58  * @author Jared Levy
59  */
60 @GwtCompatible(emulated = true)
61 public class ImmutableBiMapTest extends TestCase {
62 
63   // TODO: Reduce duplication of ImmutableMapTest code
64 
65   @GwtIncompatible // suite
suite()66   public static Test suite() {
67     TestSuite suite = new TestSuite();
68 
69     suite.addTestSuite(MapTests.class);
70     suite.addTestSuite(InverseMapTests.class);
71     suite.addTestSuite(CreationTests.class);
72     suite.addTestSuite(BiMapSpecificTests.class);
73     suite.addTestSuite(FloodingTest.class);
74 
75     suite.addTest(
76         BiMapTestSuiteBuilder.using(new ImmutableBiMapGenerator())
77             .named("ImmutableBiMap")
78             .withFeatures(
79                 CollectionSize.ANY,
80                 CollectionFeature.SERIALIZABLE,
81                 CollectionFeature.KNOWN_ORDER,
82                 MapFeature.REJECTS_DUPLICATES_AT_CREATION,
83                 MapFeature.ALLOWS_ANY_NULL_QUERIES)
84             .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
85             .createTestSuite());
86     suite.addTest(
87         BiMapTestSuiteBuilder.using(
88                 new TestStringBiMapGenerator() {
89                   @Override
90                   protected BiMap<String, String> create(Entry<String, String>[] entries) {
91                     return ImmutableBiMap.<String, String>builder()
92                         .putAll(Arrays.asList(entries))
93                         .buildJdkBacked();
94                   }
95                 })
96             .named("ImmutableBiMap [JDK backed]")
97             .withFeatures(
98                 CollectionSize.ANY,
99                 CollectionFeature.SERIALIZABLE,
100                 CollectionFeature.KNOWN_ORDER,
101                 MapFeature.REJECTS_DUPLICATES_AT_CREATION,
102                 MapFeature.ALLOWS_ANY_NULL_QUERIES)
103             .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
104             .createTestSuite());
105     suite.addTest(
106         BiMapTestSuiteBuilder.using(new ImmutableBiMapCopyOfGenerator())
107             .named("ImmutableBiMap.copyOf[Map]")
108             .withFeatures(
109                 CollectionSize.ANY,
110                 CollectionFeature.SERIALIZABLE,
111                 CollectionFeature.KNOWN_ORDER,
112                 MapFeature.ALLOWS_ANY_NULL_QUERIES)
113             .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
114             .createTestSuite());
115     suite.addTest(
116         BiMapTestSuiteBuilder.using(new ImmutableBiMapCopyOfEntriesGenerator())
117             .named("ImmutableBiMap.copyOf[Iterable<Entry>]")
118             .withFeatures(
119                 CollectionSize.ANY,
120                 CollectionFeature.SERIALIZABLE,
121                 CollectionFeature.KNOWN_ORDER,
122                 MapFeature.REJECTS_DUPLICATES_AT_CREATION,
123                 MapFeature.ALLOWS_ANY_NULL_QUERIES)
124             .suppressing(BiMapInverseTester.getInverseSameAfterSerializingMethods())
125             .createTestSuite());
126     suite.addTestSuite(ImmutableBiMapTest.class);
127 
128     return suite;
129   }
130 
131   public abstract static class AbstractMapTests<K, V> extends MapInterfaceTest<K, V> {
AbstractMapTests()132     public AbstractMapTests() {
133       super(false, false, false, false, false);
134     }
135 
136     @Override
makeEmptyMap()137     protected Map<K, V> makeEmptyMap() {
138       throw new UnsupportedOperationException();
139     }
140 
141     private static final Joiner joiner = Joiner.on(", ");
142 
143     @Override
assertMoreInvariants(Map<K, V> map)144     protected void assertMoreInvariants(Map<K, V> map) {
145 
146       BiMap<K, V> bimap = (BiMap<K, V>) map;
147 
148       for (Entry<K, V> entry : map.entrySet()) {
149         assertEquals(entry.getKey() + "=" + entry.getValue(), entry.toString());
150         assertEquals(entry.getKey(), bimap.inverse().get(entry.getValue()));
151       }
152 
153       assertEquals("{" + joiner.join(map.entrySet()) + "}", map.toString());
154       assertEquals("[" + joiner.join(map.entrySet()) + "]", map.entrySet().toString());
155       assertEquals("[" + joiner.join(map.keySet()) + "]", map.keySet().toString());
156       assertEquals("[" + joiner.join(map.values()) + "]", map.values().toString());
157 
158       assertEquals(Sets.newHashSet(map.entrySet()), map.entrySet());
159       assertEquals(Sets.newHashSet(map.keySet()), map.keySet());
160     }
161   }
162 
163   public static class MapTests extends AbstractMapTests<String, Integer> {
164     @Override
makeEmptyMap()165     protected Map<String, Integer> makeEmptyMap() {
166       return ImmutableBiMap.of();
167     }
168 
169     @Override
makePopulatedMap()170     protected Map<String, Integer> makePopulatedMap() {
171       return ImmutableBiMap.of("one", 1, "two", 2, "three", 3);
172     }
173 
174     @Override
getKeyNotInPopulatedMap()175     protected String getKeyNotInPopulatedMap() {
176       return "minus one";
177     }
178 
179     @Override
getValueNotInPopulatedMap()180     protected Integer getValueNotInPopulatedMap() {
181       return -1;
182     }
183   }
184 
185   public static class InverseMapTests extends AbstractMapTests<String, Integer> {
186     @Override
makeEmptyMap()187     protected Map<String, Integer> makeEmptyMap() {
188       return ImmutableBiMap.of();
189     }
190 
191     @Override
makePopulatedMap()192     protected Map<String, Integer> makePopulatedMap() {
193       return ImmutableBiMap.of(1, "one", 2, "two", 3, "three").inverse();
194     }
195 
196     @Override
getKeyNotInPopulatedMap()197     protected String getKeyNotInPopulatedMap() {
198       return "minus one";
199     }
200 
201     @Override
getValueNotInPopulatedMap()202     protected Integer getValueNotInPopulatedMap() {
203       return -1;
204     }
205   }
206 
207   public static class CreationTests extends TestCase {
testEmptyBuilder()208     public void testEmptyBuilder() {
209       ImmutableBiMap<String, Integer> map = new Builder<String, Integer>().build();
210       assertEquals(Collections.<String, Integer>emptyMap(), map);
211       assertEquals(Collections.<Integer, String>emptyMap(), map.inverse());
212       assertSame(ImmutableBiMap.of(), map);
213     }
214 
testSingletonBuilder()215     public void testSingletonBuilder() {
216       ImmutableBiMap<String, Integer> map = new Builder<String, Integer>().put("one", 1).build();
217       assertMapEquals(map, "one", 1);
218       assertMapEquals(map.inverse(), 1, "one");
219     }
220 
testBuilder_withImmutableEntry()221     public void testBuilder_withImmutableEntry() {
222       ImmutableBiMap<String, Integer> map =
223           new Builder<String, Integer>().put(Maps.immutableEntry("one", 1)).build();
224       assertMapEquals(map, "one", 1);
225     }
226 
testBuilder()227     public void testBuilder() {
228       ImmutableBiMap<String, Integer> map =
229           ImmutableBiMap.<String, Integer>builder()
230               .put("one", 1)
231               .put("two", 2)
232               .put("three", 3)
233               .put("four", 4)
234               .put("five", 5)
235               .build();
236       assertMapEquals(map, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
237       assertMapEquals(map.inverse(), 1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
238     }
239 
240     @GwtIncompatible
testBuilderExactlySizedReusesArray()241     public void testBuilderExactlySizedReusesArray() {
242       ImmutableBiMap.Builder<Integer, Integer> builder = ImmutableBiMap.builderWithExpectedSize(10);
243       Entry<Integer, Integer>[] builderArray = builder.entries;
244       for (int i = 0; i < 10; i++) {
245         builder.put(i, i);
246       }
247       Entry<Integer, Integer>[] builderArrayAfterPuts = builder.entries;
248       RegularImmutableBiMap<Integer, Integer> map =
249           (RegularImmutableBiMap<Integer, Integer>) builder.build();
250       Entry<Integer, Integer>[] mapInternalArray = map.entries;
251       assertSame(builderArray, builderArrayAfterPuts);
252       assertSame(builderArray, mapInternalArray);
253     }
254 
testBuilder_orderEntriesByValue()255     public void testBuilder_orderEntriesByValue() {
256       ImmutableBiMap<String, Integer> map =
257           ImmutableBiMap.<String, Integer>builder()
258               .orderEntriesByValue(Ordering.natural())
259               .put("three", 3)
260               .put("one", 1)
261               .put("five", 5)
262               .put("four", 4)
263               .put("two", 2)
264               .build();
265       assertMapEquals(map, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
266       assertMapEquals(map.inverse(), 1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
267     }
268 
testBuilder_orderEntriesByValueAfterExactSizeBuild()269     public void testBuilder_orderEntriesByValueAfterExactSizeBuild() {
270       ImmutableBiMap.Builder<String, Integer> builder =
271           new ImmutableBiMap.Builder<String, Integer>(2).put("four", 4).put("one", 1);
272       ImmutableMap<String, Integer> keyOrdered = builder.build();
273       ImmutableMap<String, Integer> valueOrdered =
274           builder.orderEntriesByValue(Ordering.natural()).build();
275       assertMapEquals(keyOrdered, "four", 4, "one", 1);
276       assertMapEquals(valueOrdered, "one", 1, "four", 4);
277     }
278 
testBuilder_orderEntriesByValue_usedTwiceFails()279     public void testBuilder_orderEntriesByValue_usedTwiceFails() {
280       ImmutableBiMap.Builder<String, Integer> builder =
281           new Builder<String, Integer>().orderEntriesByValue(Ordering.natural());
282       try {
283         builder.orderEntriesByValue(Ordering.natural());
284         fail("Expected IllegalStateException");
285       } catch (IllegalStateException expected) {
286       }
287     }
288 
testBuilderPutAllWithEmptyMap()289     public void testBuilderPutAllWithEmptyMap() {
290       ImmutableBiMap<String, Integer> map =
291           new Builder<String, Integer>().putAll(Collections.<String, Integer>emptyMap()).build();
292       assertEquals(Collections.<String, Integer>emptyMap(), map);
293     }
294 
testBuilderPutAll()295     public void testBuilderPutAll() {
296       Map<String, Integer> toPut = new LinkedHashMap<>();
297       toPut.put("one", 1);
298       toPut.put("two", 2);
299       toPut.put("three", 3);
300       Map<String, Integer> moreToPut = new LinkedHashMap<>();
301       moreToPut.put("four", 4);
302       moreToPut.put("five", 5);
303 
304       ImmutableBiMap<String, Integer> map =
305           new Builder<String, Integer>().putAll(toPut).putAll(moreToPut).build();
306       assertMapEquals(map, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
307       assertMapEquals(map.inverse(), 1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
308     }
309 
testBuilderReuse()310     public void testBuilderReuse() {
311       Builder<String, Integer> builder = new Builder<>();
312       ImmutableBiMap<String, Integer> mapOne = builder.put("one", 1).put("two", 2).build();
313       ImmutableBiMap<String, Integer> mapTwo = builder.put("three", 3).put("four", 4).build();
314 
315       assertMapEquals(mapOne, "one", 1, "two", 2);
316       assertMapEquals(mapOne.inverse(), 1, "one", 2, "two");
317       assertMapEquals(mapTwo, "one", 1, "two", 2, "three", 3, "four", 4);
318       assertMapEquals(mapTwo.inverse(), 1, "one", 2, "two", 3, "three", 4, "four");
319     }
320 
testBuilderPutNullKey()321     public void testBuilderPutNullKey() {
322       Builder<String, Integer> builder = new Builder<>();
323       try {
324         builder.put(null, 1);
325         fail();
326       } catch (NullPointerException expected) {
327       }
328     }
329 
testBuilderPutNullValue()330     public void testBuilderPutNullValue() {
331       Builder<String, Integer> builder = new Builder<>();
332       try {
333         builder.put("one", null);
334         fail();
335       } catch (NullPointerException expected) {
336       }
337     }
338 
testBuilderPutNullKeyViaPutAll()339     public void testBuilderPutNullKeyViaPutAll() {
340       Builder<String, Integer> builder = new Builder<>();
341       try {
342         builder.putAll(Collections.<String, Integer>singletonMap(null, 1));
343         fail();
344       } catch (NullPointerException expected) {
345       }
346     }
347 
testBuilderPutNullValueViaPutAll()348     public void testBuilderPutNullValueViaPutAll() {
349       Builder<String, Integer> builder = new Builder<>();
350       try {
351         builder.putAll(Collections.<String, Integer>singletonMap("one", null));
352         fail();
353       } catch (NullPointerException expected) {
354       }
355     }
356 
testPuttingTheSameKeyTwiceThrowsOnBuild()357     public void testPuttingTheSameKeyTwiceThrowsOnBuild() {
358       Builder<String, Integer> builder =
359           new Builder<String, Integer>()
360               .put("one", 1)
361               .put("one", 1); // throwing on this line would be even better
362 
363       try {
364         builder.build();
365         fail();
366       } catch (IllegalArgumentException expected) {
367         assertThat(expected.getMessage()).contains("one");
368       }
369     }
370 
testOf()371     public void testOf() {
372       assertMapEquals(ImmutableBiMap.of("one", 1), "one", 1);
373       assertMapEquals(ImmutableBiMap.of("one", 1).inverse(), 1, "one");
374       assertMapEquals(ImmutableBiMap.of("one", 1, "two", 2), "one", 1, "two", 2);
375       assertMapEquals(ImmutableBiMap.of("one", 1, "two", 2).inverse(), 1, "one", 2, "two");
376       assertMapEquals(
377           ImmutableBiMap.of("one", 1, "two", 2, "three", 3), "one", 1, "two", 2, "three", 3);
378       assertMapEquals(
379           ImmutableBiMap.of("one", 1, "two", 2, "three", 3).inverse(),
380           1,
381           "one",
382           2,
383           "two",
384           3,
385           "three");
386       assertMapEquals(
387           ImmutableBiMap.of("one", 1, "two", 2, "three", 3, "four", 4),
388           "one",
389           1,
390           "two",
391           2,
392           "three",
393           3,
394           "four",
395           4);
396       assertMapEquals(
397           ImmutableBiMap.of("one", 1, "two", 2, "three", 3, "four", 4).inverse(),
398           1,
399           "one",
400           2,
401           "two",
402           3,
403           "three",
404           4,
405           "four");
406       assertMapEquals(
407           ImmutableBiMap.of("one", 1, "two", 2, "three", 3, "four", 4, "five", 5),
408           "one",
409           1,
410           "two",
411           2,
412           "three",
413           3,
414           "four",
415           4,
416           "five",
417           5);
418       assertMapEquals(
419           ImmutableBiMap.of("one", 1, "two", 2, "three", 3, "four", 4, "five", 5).inverse(),
420           1,
421           "one",
422           2,
423           "two",
424           3,
425           "three",
426           4,
427           "four",
428           5,
429           "five");
430       assertMapEquals(
431           ImmutableBiMap.of(
432               "one", 1,
433               "two", 2,
434               "three", 3,
435               "four", 4,
436               "five", 5,
437               "six", 6),
438           "one",
439           1,
440           "two",
441           2,
442           "three",
443           3,
444           "four",
445           4,
446           "five",
447           5,
448           "six",
449           6);
450       assertMapEquals(
451           ImmutableBiMap.of(
452               "one", 1,
453               "two", 2,
454               "three", 3,
455               "four", 4,
456               "five", 5,
457               "six", 6,
458               "seven", 7),
459           "one",
460           1,
461           "two",
462           2,
463           "three",
464           3,
465           "four",
466           4,
467           "five",
468           5,
469           "six",
470           6,
471           "seven",
472           7);
473       assertMapEquals(
474           ImmutableBiMap.of(
475               "one", 1,
476               "two", 2,
477               "three", 3,
478               "four", 4,
479               "five", 5,
480               "six", 6,
481               "seven", 7,
482               "eight", 8),
483           "one",
484           1,
485           "two",
486           2,
487           "three",
488           3,
489           "four",
490           4,
491           "five",
492           5,
493           "six",
494           6,
495           "seven",
496           7,
497           "eight",
498           8);
499       assertMapEquals(
500           ImmutableBiMap.of(
501               "one", 1,
502               "two", 2,
503               "three", 3,
504               "four", 4,
505               "five", 5,
506               "six", 6,
507               "seven", 7,
508               "eight", 8,
509               "nine", 9),
510           "one",
511           1,
512           "two",
513           2,
514           "three",
515           3,
516           "four",
517           4,
518           "five",
519           5,
520           "six",
521           6,
522           "seven",
523           7,
524           "eight",
525           8,
526           "nine",
527           9);
528       assertMapEquals(
529           ImmutableBiMap.of(
530               "one", 1,
531               "two", 2,
532               "three", 3,
533               "four", 4,
534               "five", 5,
535               "six", 6,
536               "seven", 7,
537               "eight", 8,
538               "nine", 9,
539               "ten", 10),
540           "one",
541           1,
542           "two",
543           2,
544           "three",
545           3,
546           "four",
547           4,
548           "five",
549           5,
550           "six",
551           6,
552           "seven",
553           7,
554           "eight",
555           8,
556           "nine",
557           9,
558           "ten",
559           10);
560     }
561 
testOfNullKey()562     public void testOfNullKey() {
563       try {
564         ImmutableBiMap.of(null, 1);
565         fail();
566       } catch (NullPointerException expected) {
567       }
568 
569       try {
570         ImmutableBiMap.of("one", 1, null, 2);
571         fail();
572       } catch (NullPointerException expected) {
573       }
574     }
575 
testOfNullValue()576     public void testOfNullValue() {
577       try {
578         ImmutableBiMap.of("one", null);
579         fail();
580       } catch (NullPointerException expected) {
581       }
582 
583       try {
584         ImmutableBiMap.of("one", 1, "two", null);
585         fail();
586       } catch (NullPointerException expected) {
587       }
588     }
589 
testOfWithDuplicateKey()590     public void testOfWithDuplicateKey() {
591       try {
592         ImmutableBiMap.of("one", 1, "one", 1);
593         fail();
594       } catch (IllegalArgumentException expected) {
595         assertThat(expected.getMessage()).contains("one");
596       }
597     }
598 
testOfEntries()599     public void testOfEntries() {
600       assertMapEquals(
601           ImmutableBiMap.ofEntries(entry("one", 1), entry("two", 2)), "one", 1, "two", 2);
602     }
603 
testOfEntriesNull()604     public void testOfEntriesNull() {
605       Entry<Integer, Integer> nullKey = entry(null, 23);
606       try {
607         ImmutableBiMap.ofEntries(nullKey);
608         fail();
609       } catch (NullPointerException expected) {
610       }
611       Entry<Integer, Integer> nullValue = entry(23, null);
612       try {
613         ImmutableBiMap.ofEntries(nullValue);
614         fail();
615       } catch (NullPointerException expected) {
616       }
617     }
618 
entry(T key, T value)619     private static <T> Entry<T, T> entry(T key, T value) {
620       return new AbstractMap.SimpleImmutableEntry<>(key, value);
621     }
622 
testCopyOfEmptyMap()623     public void testCopyOfEmptyMap() {
624       ImmutableBiMap<String, Integer> copy =
625           ImmutableBiMap.copyOf(Collections.<String, Integer>emptyMap());
626       assertEquals(Collections.<String, Integer>emptyMap(), copy);
627       assertSame(copy, ImmutableBiMap.copyOf(copy));
628       assertSame(ImmutableBiMap.of(), copy);
629     }
630 
testCopyOfSingletonMap()631     public void testCopyOfSingletonMap() {
632       ImmutableBiMap<String, Integer> copy =
633           ImmutableBiMap.copyOf(Collections.singletonMap("one", 1));
634       assertMapEquals(copy, "one", 1);
635       assertSame(copy, ImmutableBiMap.copyOf(copy));
636     }
637 
testCopyOf()638     public void testCopyOf() {
639       Map<String, Integer> original = new LinkedHashMap<>();
640       original.put("one", 1);
641       original.put("two", 2);
642       original.put("three", 3);
643 
644       ImmutableBiMap<String, Integer> copy = ImmutableBiMap.copyOf(original);
645       assertMapEquals(copy, "one", 1, "two", 2, "three", 3);
646       assertSame(copy, ImmutableBiMap.copyOf(copy));
647     }
648 
testEmpty()649     public void testEmpty() {
650       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.of();
651       assertEquals(Collections.<String, Integer>emptyMap(), bimap);
652       assertEquals(Collections.<String, Integer>emptyMap(), bimap.inverse());
653     }
654 
testFromHashMap()655     public void testFromHashMap() {
656       Map<String, Integer> hashMap = Maps.newLinkedHashMap();
657       hashMap.put("one", 1);
658       hashMap.put("two", 2);
659       ImmutableBiMap<String, Integer> bimap =
660           ImmutableBiMap.copyOf(ImmutableMap.of("one", 1, "two", 2));
661       assertMapEquals(bimap, "one", 1, "two", 2);
662       assertMapEquals(bimap.inverse(), 1, "one", 2, "two");
663     }
664 
testFromImmutableMap()665     public void testFromImmutableMap() {
666       ImmutableBiMap<String, Integer> bimap =
667           ImmutableBiMap.copyOf(
668               new ImmutableMap.Builder<String, Integer>()
669                   .put("one", 1)
670                   .put("two", 2)
671                   .put("three", 3)
672                   .put("four", 4)
673                   .put("five", 5)
674                   .build());
675       assertMapEquals(bimap, "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
676       assertMapEquals(bimap.inverse(), 1, "one", 2, "two", 3, "three", 4, "four", 5, "five");
677     }
678 
testDuplicateValues()679     public void testDuplicateValues() {
680       ImmutableMap<String, Integer> map =
681           new ImmutableMap.Builder<String, Integer>()
682               .put("one", 1)
683               .put("two", 2)
684               .put("uno", 1)
685               .put("dos", 2)
686               .build();
687 
688       try {
689         ImmutableBiMap.copyOf(map);
690         fail();
691       } catch (IllegalArgumentException expected) {
692         assertThat(expected.getMessage()).contains("1");
693       }
694     }
695 
testToImmutableBiMap()696     public void testToImmutableBiMap() {
697       Collector<Entry<String, Integer>, ?, ImmutableBiMap<String, Integer>> collector =
698           ImmutableBiMap.toImmutableBiMap(Entry::getKey, Entry::getValue);
699       Equivalence<ImmutableBiMap<String, Integer>> equivalence =
700           Equivalence.equals()
701               .<Entry<String, Integer>>pairwise()
702               .onResultOf(ImmutableBiMap::entrySet);
703       CollectorTester.of(collector, equivalence)
704           .expectCollects(
705               ImmutableBiMap.of("one", 1, "two", 2, "three", 3),
706               mapEntry("one", 1),
707               mapEntry("two", 2),
708               mapEntry("three", 3));
709     }
710 
testToImmutableBiMap_exceptionOnDuplicateKey()711     public void testToImmutableBiMap_exceptionOnDuplicateKey() {
712       Collector<Entry<String, Integer>, ?, ImmutableBiMap<String, Integer>> collector =
713           ImmutableBiMap.toImmutableBiMap(Entry::getKey, Entry::getValue);
714       try {
715         Stream.of(mapEntry("one", 1), mapEntry("one", 11)).collect(collector);
716         fail("Expected IllegalArgumentException");
717       } catch (IllegalArgumentException expected) {
718       }
719     }
720   }
721 
722   public static class BiMapSpecificTests extends TestCase {
723 
testForcePut()724     public void testForcePut() {
725       BiMap<String, Integer> bimap = ImmutableBiMap.copyOf(ImmutableMap.of("one", 1, "two", 2));
726       try {
727         bimap.forcePut("three", 3);
728         fail();
729       } catch (UnsupportedOperationException expected) {
730       }
731     }
732 
testKeySet()733     public void testKeySet() {
734       ImmutableBiMap<String, Integer> bimap =
735           ImmutableBiMap.copyOf(ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
736       Set<String> keys = bimap.keySet();
737       assertEquals(Sets.newHashSet("one", "two", "three", "four"), keys);
738       assertThat(keys).containsExactly("one", "two", "three", "four").inOrder();
739     }
740 
testValues()741     public void testValues() {
742       ImmutableBiMap<String, Integer> bimap =
743           ImmutableBiMap.copyOf(ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4));
744       Set<Integer> values = bimap.values();
745       assertEquals(Sets.newHashSet(1, 2, 3, 4), values);
746       assertThat(values).containsExactly(1, 2, 3, 4).inOrder();
747     }
748 
testDoubleInverse()749     public void testDoubleInverse() {
750       ImmutableBiMap<String, Integer> bimap =
751           ImmutableBiMap.copyOf(ImmutableMap.of("one", 1, "two", 2));
752       assertSame(bimap, bimap.inverse().inverse());
753     }
754 
755     @GwtIncompatible // SerializableTester
testEmptySerialization()756     public void testEmptySerialization() {
757       ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.of();
758       assertSame(bimap, SerializableTester.reserializeAndAssert(bimap));
759     }
760 
761     @GwtIncompatible // SerializableTester
testSerialization()762     public void testSerialization() {
763       ImmutableBiMap<String, Integer> bimap =
764           ImmutableBiMap.copyOf(ImmutableMap.of("one", 1, "two", 2));
765       ImmutableBiMap<String, Integer> copy = SerializableTester.reserializeAndAssert(bimap);
766       assertEquals(Integer.valueOf(1), copy.get("one"));
767       assertEquals("one", copy.inverse().get(1));
768       assertSame(copy, copy.inverse().inverse());
769     }
770 
771     @GwtIncompatible // SerializableTester
testInverseSerialization()772     public void testInverseSerialization() {
773       ImmutableBiMap<String, Integer> bimap =
774           ImmutableBiMap.copyOf(ImmutableMap.of(1, "one", 2, "two")).inverse();
775       ImmutableBiMap<String, Integer> copy = SerializableTester.reserializeAndAssert(bimap);
776       assertEquals(Integer.valueOf(1), copy.get("one"));
777       assertEquals("one", copy.inverse().get(1));
778       assertSame(copy, copy.inverse().inverse());
779     }
780   }
781 
assertMapEquals(Map<K, V> map, Object... alternatingKeysAndValues)782   private static <K, V> void assertMapEquals(Map<K, V> map, Object... alternatingKeysAndValues) {
783     int i = 0;
784     for (Entry<K, V> entry : map.entrySet()) {
785       assertEquals(alternatingKeysAndValues[i++], entry.getKey());
786       assertEquals(alternatingKeysAndValues[i++], entry.getValue());
787     }
788   }
789 
790   public static class FloodingTest extends AbstractHashFloodingTest<BiMap<Object, Object>> {
FloodingTest()791     public FloodingTest() {
792       super(
793           EnumSet.allOf(ConstructionPathway.class).stream()
794               .flatMap(
795                   path ->
796                       Stream.<Construction<BiMap<Object, Object>>>of(
797                           keys ->
798                               path.create(
799                                   Lists.transform(
800                                       keys, key -> Maps.immutableEntry(key, new Object()))),
801                           keys ->
802                               path.create(
803                                   Lists.transform(
804                                       keys, key -> Maps.immutableEntry(new Object(), key))),
805                           keys ->
806                               path.create(
807                                   Lists.transform(keys, key -> Maps.immutableEntry(key, key)))))
808               .collect(ImmutableList.toImmutableList()),
809           n -> n * Math.log(n),
810           ImmutableList.of(
811               QueryOp.create("BiMap.get", BiMap::get, Math::log),
812               QueryOp.create("BiMap.inverse.get", (bm, o) -> bm.inverse().get(o), Math::log)));
813     }
814 
815     /** All the ways to create an ImmutableBiMap. */
816     enum ConstructionPathway {
817       COPY_OF_MAP {
818         @Override
create(List<Map.Entry<?, ?>> entries)819         public ImmutableBiMap<Object, Object> create(List<Map.Entry<?, ?>> entries) {
820           Map<Object, Object> sourceMap = new LinkedHashMap<>();
821           for (Map.Entry<?, ?> entry : entries) {
822             if (sourceMap.put(entry.getKey(), entry.getValue()) != null) {
823               throw new UnsupportedOperationException("duplicate key");
824             }
825           }
826           return ImmutableBiMap.copyOf(sourceMap);
827         }
828       },
829       COPY_OF_ENTRIES {
830         @Override
create(List<Map.Entry<?, ?>> entries)831         public ImmutableBiMap<Object, Object> create(List<Map.Entry<?, ?>> entries) {
832           return ImmutableBiMap.copyOf(entries);
833         }
834       },
835       BUILDER_PUT_ONE_BY_ONE {
836         @Override
create(List<Map.Entry<?, ?>> entries)837         public ImmutableBiMap<Object, Object> create(List<Map.Entry<?, ?>> entries) {
838           ImmutableBiMap.Builder<Object, Object> builder = ImmutableBiMap.builder();
839           for (Map.Entry<?, ?> entry : entries) {
840             builder.put(entry.getKey(), entry.getValue());
841           }
842           return builder.build();
843         }
844       },
845       BUILDER_PUT_ALL_MAP {
846         @Override
create(List<Map.Entry<?, ?>> entries)847         public ImmutableBiMap<Object, Object> create(List<Map.Entry<?, ?>> entries) {
848           Map<Object, Object> sourceMap = new LinkedHashMap<>();
849           for (Map.Entry<?, ?> entry : entries) {
850             if (sourceMap.put(entry.getKey(), entry.getValue()) != null) {
851               throw new UnsupportedOperationException("duplicate key");
852             }
853           }
854           ImmutableBiMap.Builder<Object, Object> builder = ImmutableBiMap.builder();
855           builder.putAll(sourceMap);
856           return builder.build();
857         }
858       },
859       BUILDER_PUT_ALL_ENTRIES {
860         @Override
create(List<Map.Entry<?, ?>> entries)861         public ImmutableBiMap<Object, Object> create(List<Map.Entry<?, ?>> entries) {
862           return ImmutableBiMap.builder().putAll(entries).build();
863         }
864       },
865       FORCE_JDK {
866         @Override
create(List<Map.Entry<?, ?>> entries)867         public ImmutableBiMap<Object, Object> create(List<Map.Entry<?, ?>> entries) {
868           return ImmutableBiMap.builder().putAll(entries).buildJdkBacked();
869         }
870       };
871 
872       @CanIgnoreReturnValue
create(List<Map.Entry<?, ?>> entries)873       public abstract ImmutableBiMap<Object, Object> create(List<Map.Entry<?, ?>> entries);
874     }
875   }
876 
877   /** No-op test so that the class has at least one method, making Maven's test runner happy. */
testNoop()878   public void testNoop() {}
879 }
880