| /* |
| * Copyright (C) 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.common.collect; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableBiMap.Builder; |
| import com.google.common.collect.testing.MapInterfaceTest; |
| import com.google.common.collect.testing.ReserializingTestSetGenerator; |
| import com.google.common.collect.testing.SampleElements; |
| import com.google.common.collect.testing.SetTestSuiteBuilder; |
| import com.google.common.collect.testing.TestMapEntrySetGenerator; |
| import com.google.common.collect.testing.TestSetGenerator; |
| import com.google.common.collect.testing.TestStringSetGenerator; |
| import com.google.common.collect.testing.features.CollectionFeature; |
| import com.google.common.collect.testing.features.CollectionSize; |
| import com.google.common.collect.testing.features.SetFeature; |
| import com.google.common.testing.junit3.JUnitAsserts; |
| import com.google.common.testutils.SerializableTester; |
| |
| import junit.framework.Test; |
| import junit.framework.TestCase; |
| import junit.framework.TestSuite; |
| |
| import java.util.Collections; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| /** |
| * Tests for {@link ImmutableBiMap}. |
| * |
| * @author Jared Levy |
| */ |
| public class ImmutableBiMapTest extends TestCase { |
| |
| // TODO: Reduce duplication of ImmutableMapTest code |
| |
| public static Test suite() { |
| TestSuite suite = new TestSuite(); |
| |
| suite.addTestSuite(MapTests.class); |
| suite.addTestSuite(InverseMapTests.class); |
| suite.addTestSuite(CreationTests.class); |
| suite.addTestSuite(BiMapSpecificTests.class); |
| |
| suite.addTest(SetTestSuiteBuilder.using(keySetGenerator()) |
| .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER) |
| .named("ImmutableBiMap.keySet") |
| .createTestSuite()); |
| |
| suite.addTest(SetTestSuiteBuilder.using(entrySetGenerator()) |
| .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER) |
| .named("ImmutableBiMap.entrySet") |
| .createTestSuite()); |
| |
| suite.addTest(SetTestSuiteBuilder.using(valuesGenerator()) |
| .withFeatures( |
| CollectionSize.ANY, |
| SetFeature.REJECTS_DUPLICATES_AT_CREATION, |
| CollectionFeature.KNOWN_ORDER) |
| .named("ImmutableBiMap.values") |
| .createTestSuite()); |
| |
| suite.addTest(SetTestSuiteBuilder.using(inverseKeySetGenerator()) |
| .withFeatures( |
| CollectionSize.ANY, |
| SetFeature.REJECTS_DUPLICATES_AT_CREATION, |
| CollectionFeature.KNOWN_ORDER) |
| .named("ImmutableBiMap.inverse.keys") |
| .createTestSuite()); |
| |
| suite.addTest(SetTestSuiteBuilder.using(inverseEntrySetGenerator()) |
| .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER) |
| .named("ImmutableBiMap.inverse.entrySet") |
| .createTestSuite()); |
| |
| suite.addTest(SetTestSuiteBuilder.using(inverseValuesGenerator()) |
| .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER) |
| .named("ImmutableBiMap.inverse.values") |
| .createTestSuite()); |
| |
| suite.addTest(SetTestSuiteBuilder.using( |
| ReserializingTestSetGenerator.newInstance(keySetGenerator())) |
| .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER) |
| .named("ImmutableBiMap.keySet, reserialized") |
| .createTestSuite()); |
| |
| suite.addTest(SetTestSuiteBuilder.using( |
| ReserializingTestSetGenerator.newInstance(entrySetGenerator())) |
| .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER) |
| .named("ImmutableBiMap.entrySet, reserialized") |
| .createTestSuite()); |
| |
| suite.addTest(SetTestSuiteBuilder.using( |
| ReserializingTestSetGenerator.newInstance(valuesGenerator())) |
| .withFeatures( |
| CollectionSize.ANY, |
| SetFeature.REJECTS_DUPLICATES_AT_CREATION, |
| CollectionFeature.KNOWN_ORDER) |
| .named("ImmutableBiMap.values, reserialized") |
| .createTestSuite()); |
| |
| return suite; |
| } |
| |
| private static TestMapEntrySetGenerator<String, String> entrySetGenerator() { |
| SampleElements.Strings sampleStrings = new SampleElements.Strings(); |
| return new TestMapEntrySetGenerator<String, String>( |
| sampleStrings, sampleStrings) { |
| @Override public Set<Entry<String, String>> createFromEntries( |
| Entry<String, String>[] entries) { |
| Map<String, String> map = Maps.newLinkedHashMap(); |
| for (Entry<String, String> entry : entries) { |
| map.put(entry.getKey(), entry.getValue()); |
| } |
| return ImmutableBiMap.copyOf(map).entrySet(); |
| } |
| }; |
| } |
| |
| private static TestStringSetGenerator keySetGenerator() { |
| return new TestStringSetGenerator() { |
| @Override protected Set<String> create(String[] elements) { |
| Map<String, Integer> map = Maps.newLinkedHashMap(); |
| for (int i = 0; i < elements.length; i++) { |
| map.put(elements[i], i); |
| } |
| return ImmutableBiMap.copyOf(map).keySet(); |
| } |
| }; |
| } |
| |
| private static TestStringSetGenerator valuesGenerator() { |
| return new TestStringSetGenerator() { |
| @Override protected Set<String> create(String[] elements) { |
| Map<Integer, String> map = Maps.newLinkedHashMap(); |
| for (int i = 0; i < elements.length; i++) { |
| map.put(i, elements[i]); |
| } |
| return ImmutableBiMap.copyOf(map).values(); |
| } |
| }; |
| } |
| |
| private static TestMapEntrySetGenerator<String, String> |
| inverseEntrySetGenerator() { |
| SampleElements.Strings sampleStrings = new SampleElements.Strings(); |
| return new TestMapEntrySetGenerator<String, String>( |
| sampleStrings, sampleStrings) { |
| @Override public Set<Entry<String, String>> createFromEntries( |
| Entry<String, String>[] entries) { |
| Map<String, String> map = Maps.newLinkedHashMap(); |
| for (Entry<String, String> entry : entries) { |
| map.put(entry.getValue(), entry.getKey()); |
| } |
| return ImmutableBiMap.copyOf(map).inverse().entrySet(); |
| } |
| }; |
| } |
| |
| private static TestStringSetGenerator inverseKeySetGenerator() { |
| return new TestStringSetGenerator() { |
| @Override protected Set<String> create(String[] elements) { |
| Map<Integer, String> map = Maps.newLinkedHashMap(); |
| for (int i = 0; i < elements.length; i++) { |
| map.put(i, elements[i]); |
| } |
| return ImmutableBiMap.copyOf(map).inverse().keySet(); |
| } |
| }; |
| } |
| |
| private static TestSetGenerator<String> inverseValuesGenerator() { |
| return new TestStringSetGenerator() { |
| @Override protected Set<String> create(String[] elements) { |
| Map<String, Integer> map = Maps.newLinkedHashMap(); |
| for (int i = 0; i < elements.length; i++) { |
| map.put(elements[i], i); |
| } |
| return ImmutableBiMap.copyOf(map).inverse().values(); |
| } |
| }; |
| } |
| |
| public static abstract class AbstractMapTests<K, V> |
| extends MapInterfaceTest<K, V> { |
| public AbstractMapTests() { |
| super(false, false, false, false, false); |
| } |
| |
| @Override protected Map<K, V> makeEmptyMap() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| private static final Joiner joiner = Joiner.on(", "); |
| |
| @Override protected void assertMoreInvariants(Map<K, V> map) { |
| |
| BiMap<K, V> bimap = (BiMap<K, V>) map; |
| |
| for (Entry<K, V> entry : map.entrySet()) { |
| assertEquals(entry.getKey() + "=" + entry.getValue(), |
| entry.toString()); |
| assertEquals(entry.getKey(), bimap.inverse().get(entry.getValue())); |
| } |
| |
| assertEquals("{" + joiner.join(map.entrySet()) + "}", |
| map.toString()); |
| assertEquals("[" + joiner.join(map.entrySet()) + "]", |
| map.entrySet().toString()); |
| assertEquals("[" + joiner.join(map.keySet()) + "]", |
| map.keySet().toString()); |
| assertEquals("[" + joiner.join(map.values()) + "]", |
| map.values().toString()); |
| |
| assertEquals(Sets.newHashSet(map.entrySet()), map.entrySet()); |
| assertEquals(Sets.newHashSet(map.keySet()), map.keySet()); |
| } |
| } |
| |
| public static class MapTests extends AbstractMapTests<String, Integer> { |
| @Override protected Map<String, Integer> makeEmptyMap() { |
| return ImmutableBiMap.of(); |
| } |
| |
| @Override protected Map<String, Integer> makePopulatedMap() { |
| return ImmutableBiMap.of("one", 1, "two", 2, "three", 3); |
| } |
| |
| @Override protected String getKeyNotInPopulatedMap() { |
| return "minus one"; |
| } |
| |
| @Override protected Integer getValueNotInPopulatedMap() { |
| return -1; |
| } |
| } |
| |
| public static class InverseMapTests |
| extends AbstractMapTests<String, Integer> { |
| @Override protected Map<String, Integer> makeEmptyMap() { |
| return ImmutableBiMap.of(); |
| } |
| |
| @Override protected Map<String, Integer> makePopulatedMap() { |
| return ImmutableBiMap.of(1, "one", 2, "two", 3, "three").inverse(); |
| } |
| |
| @Override protected String getKeyNotInPopulatedMap() { |
| return "minus one"; |
| } |
| |
| @Override protected Integer getValueNotInPopulatedMap() { |
| return -1; |
| } |
| } |
| |
| public static class CreationTests extends TestCase { |
| public void testEmptyBuilder() { |
| ImmutableBiMap<String, Integer> map |
| = new Builder<String, Integer>().build(); |
| assertEquals(Collections.<String, Integer>emptyMap(), map); |
| assertEquals(Collections.<Integer, String>emptyMap(), map.inverse()); |
| assertSame(ImmutableBiMap.of(), map); |
| } |
| |
| public void testSingletonBuilder() { |
| ImmutableBiMap<String, Integer> map = new Builder<String, Integer>() |
| .put("one", 1) |
| .build(); |
| assertMapEquals(map, "one", 1); |
| assertMapEquals(map.inverse(), 1, "one"); |
| } |
| |
| public void testBuilder() { |
| ImmutableBiMap<String, Integer> map |
| = ImmutableBiMap.<String, Integer>builder() |
| .put("one", 1) |
| .put("two", 2) |
| .put("three", 3) |
| .put("four", 4) |
| .put("five", 5) |
| .build(); |
| assertMapEquals(map, |
| "one", 1, "two", 2, "three", 3, "four", 4, "five", 5); |
| assertMapEquals(map.inverse(), |
| 1, "one", 2, "two", 3, "three", 4, "four", 5, "five"); |
| } |
| |
| public void testBuilderPutAllWithEmptyMap() { |
| ImmutableBiMap<String, Integer> map = new Builder<String, Integer>() |
| .putAll(Collections.<String, Integer>emptyMap()) |
| .build(); |
| assertEquals(Collections.<String, Integer>emptyMap(), map); |
| } |
| |
| public void testBuilderPutAll() { |
| Map<String, Integer> toPut = new LinkedHashMap<String, Integer>(); |
| toPut.put("one", 1); |
| toPut.put("two", 2); |
| toPut.put("three", 3); |
| Map<String, Integer> moreToPut = new LinkedHashMap<String, Integer>(); |
| moreToPut.put("four", 4); |
| moreToPut.put("five", 5); |
| |
| ImmutableBiMap<String, Integer> map = new Builder<String, Integer>() |
| .putAll(toPut) |
| .putAll(moreToPut) |
| .build(); |
| assertMapEquals(map, |
| "one", 1, "two", 2, "three", 3, "four", 4, "five", 5); |
| assertMapEquals(map.inverse(), |
| 1, "one", 2, "two", 3, "three", 4, "four", 5, "five"); |
| } |
| |
| public void testBuilderReuse() { |
| Builder<String, Integer> builder = new Builder<String, Integer>(); |
| ImmutableBiMap<String, Integer> mapOne = builder |
| .put("one", 1) |
| .put("two", 2) |
| .build(); |
| ImmutableBiMap<String, Integer> mapTwo = builder |
| .put("three", 3) |
| .put("four", 4) |
| .build(); |
| |
| assertMapEquals(mapOne, "one", 1, "two", 2); |
| assertMapEquals(mapOne.inverse(), 1, "one", 2, "two"); |
| assertMapEquals(mapTwo, "one", 1, "two", 2, "three", 3, "four", 4); |
| assertMapEquals(mapTwo.inverse(), |
| 1, "one", 2, "two", 3, "three", 4, "four"); |
| } |
| |
| public void testBuilderPutNullKey() { |
| Builder<String, Integer> builder = new Builder<String, Integer>(); |
| try { |
| builder.put(null, 1); |
| fail(); |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| public void testBuilderPutNullValue() { |
| Builder<String, Integer> builder = new Builder<String, Integer>(); |
| try { |
| builder.put("one", null); |
| fail(); |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| public void testBuilderPutNullKeyViaPutAll() { |
| Builder<String, Integer> builder = new Builder<String, Integer>(); |
| try { |
| builder.putAll(Collections.<String, Integer>singletonMap(null, 1)); |
| fail(); |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| public void testBuilderPutNullValueViaPutAll() { |
| Builder<String, Integer> builder = new Builder<String, Integer>(); |
| try { |
| builder.putAll(Collections.<String, Integer>singletonMap("one", null)); |
| fail(); |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| public void testPuttingTheSameKeyTwiceThrowsOnBuild() { |
| Builder<String, Integer> builder = new Builder<String, Integer>() |
| .put("one", 1) |
| .put("one", 1); // throwing on this line would be even better |
| |
| try { |
| builder.build(); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| assertEquals("duplicate key: one", expected.getMessage()); |
| } |
| } |
| |
| public void testOf() { |
| assertMapEquals( |
| ImmutableBiMap.of("one", 1), |
| "one", 1); |
| assertMapEquals( |
| ImmutableBiMap.of("one", 1).inverse(), |
| 1, "one"); |
| assertMapEquals( |
| ImmutableBiMap.of("one", 1, "two", 2), |
| "one", 1, "two", 2); |
| assertMapEquals( |
| ImmutableBiMap.of("one", 1, "two", 2).inverse(), |
| 1, "one", 2, "two"); |
| assertMapEquals( |
| ImmutableBiMap.of("one", 1, "two", 2, "three", 3), |
| "one", 1, "two", 2, "three", 3); |
| assertMapEquals( |
| ImmutableBiMap.of("one", 1, "two", 2, "three", 3).inverse(), |
| 1, "one", 2, "two", 3, "three"); |
| assertMapEquals( |
| ImmutableBiMap.of("one", 1, "two", 2, "three", 3, "four", 4), |
| "one", 1, "two", 2, "three", 3, "four", 4); |
| assertMapEquals( |
| ImmutableBiMap.of( |
| "one", 1, "two", 2, "three", 3, "four", 4).inverse(), |
| 1, "one", 2, "two", 3, "three", 4, "four"); |
| assertMapEquals( |
| ImmutableBiMap.of( |
| "one", 1, "two", 2, "three", 3, "four", 4, "five", 5), |
| "one", 1, "two", 2, "three", 3, "four", 4, "five", 5); |
| assertMapEquals( |
| ImmutableBiMap.of( |
| "one", 1, "two", 2, "three", 3, "four", 4, "five", 5).inverse(), |
| 1, "one", 2, "two", 3, "three", 4, "four", 5, "five"); |
| } |
| |
| public void testOfNullKey() { |
| try { |
| ImmutableBiMap.of(null, 1); |
| fail(); |
| } catch (NullPointerException expected) { |
| } |
| |
| try { |
| ImmutableBiMap.of("one", 1, null, 2); |
| fail(); |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| public void testOfNullValue() { |
| try { |
| ImmutableBiMap.of("one", null); |
| fail(); |
| } catch (NullPointerException expected) { |
| } |
| |
| try { |
| ImmutableBiMap.of("one", 1, "two", null); |
| fail(); |
| } catch (NullPointerException expected) { |
| } |
| } |
| |
| public void testOfWithDuplicateKey() { |
| try { |
| ImmutableBiMap.of("one", 1, "one", 1); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| assertEquals("duplicate key: one", expected.getMessage()); |
| } |
| } |
| |
| public void testCopyOfEmptyMap() { |
| ImmutableBiMap<String, Integer> copy |
| = ImmutableBiMap.copyOf(Collections.<String, Integer>emptyMap()); |
| assertEquals(Collections.<String, Integer>emptyMap(), copy); |
| assertSame(copy, ImmutableBiMap.copyOf(copy)); |
| assertSame(ImmutableBiMap.of(), copy); |
| } |
| |
| public void testCopyOfSingletonMap() { |
| ImmutableBiMap<String, Integer> copy |
| = ImmutableBiMap.copyOf(Collections.singletonMap("one", 1)); |
| assertMapEquals(copy, "one", 1); |
| assertSame(copy, ImmutableBiMap.copyOf(copy)); |
| } |
| |
| public void testCopyOf() { |
| Map<String, Integer> original = new LinkedHashMap<String, Integer>(); |
| original.put("one", 1); |
| original.put("two", 2); |
| original.put("three", 3); |
| |
| ImmutableBiMap<String, Integer> copy = ImmutableBiMap.copyOf(original); |
| assertMapEquals(copy, "one", 1, "two", 2, "three", 3); |
| assertSame(copy, ImmutableBiMap.copyOf(copy)); |
| } |
| |
| public void testEmpty() { |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.of(); |
| assertEquals(Collections.<String, Integer>emptyMap(), bimap); |
| assertEquals(Collections.<String, Integer>emptyMap(), bimap.inverse()); |
| } |
| |
| public void testFromHashMap() { |
| Map<String, Integer> hashMap = Maps.newLinkedHashMap(); |
| hashMap.put("one", 1); |
| hashMap.put("two", 2); |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( |
| ImmutableMap.of("one", 1, "two", 2)); |
| assertMapEquals(bimap, "one", 1, "two", 2); |
| assertMapEquals(bimap.inverse(), 1, "one", 2, "two"); |
| } |
| |
| public void testFromImmutableMap() { |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( |
| new ImmutableMap.Builder<String, Integer>() |
| .put("one", 1) |
| .put("two", 2) |
| .put("three", 3) |
| .put("four", 4) |
| .put("five", 5) |
| .build()); |
| assertMapEquals(bimap, |
| "one", 1, "two", 2, "three", 3, "four", 4, "five", 5); |
| assertMapEquals(bimap.inverse(), |
| 1, "one", 2, "two", 3, "three", 4, "four", 5, "five"); |
| } |
| |
| public void testDuplicateValues() { |
| ImmutableMap<String, Integer> map |
| = new ImmutableMap.Builder<String, Integer>() |
| .put("one", 1) |
| .put("two", 2) |
| .put("uno", 1) |
| .put("dos", 2) |
| .build(); |
| |
| try { |
| ImmutableBiMap.copyOf(map); |
| fail(); |
| } catch (IllegalArgumentException expected) { |
| assertEquals("duplicate key: 1", expected.getMessage()); |
| } |
| } |
| } |
| |
| public static class BiMapSpecificTests extends TestCase { |
| public void testForcePut() { |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( |
| ImmutableMap.of("one", 1, "two", 2)); |
| try { |
| bimap.forcePut("three", 3); |
| fail(); |
| } catch (UnsupportedOperationException expected) {} |
| } |
| |
| public void testKeySet() { |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( |
| ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4)); |
| Set<String> keys = bimap.keySet(); |
| assertEquals(Sets.newHashSet("one", "two", "three", "four"), keys); |
| JUnitAsserts.assertContentsInOrder(keys, "one", "two", "three", "four"); |
| } |
| |
| public void testValues() { |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( |
| ImmutableMap.of("one", 1, "two", 2, "three", 3, "four", 4)); |
| Set<Integer> values = bimap.values(); |
| assertEquals(Sets.newHashSet(1, 2, 3, 4), values); |
| JUnitAsserts.assertContentsInOrder(values, 1, 2, 3, 4); |
| } |
| |
| public void testDoubleInverse() { |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( |
| ImmutableMap.of("one", 1, "two", 2)); |
| assertSame(bimap, bimap.inverse().inverse()); |
| } |
| |
| public void testEmptySerialization() { |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.of(); |
| assertSame(bimap, SerializableTester.reserializeAndAssert(bimap)); |
| } |
| |
| public void testSerialization() { |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( |
| ImmutableMap.of("one", 1, "two", 2)); |
| ImmutableBiMap<String, Integer> copy = |
| SerializableTester.reserializeAndAssert(bimap); |
| assertEquals(Integer.valueOf(1), copy.get("one")); |
| assertEquals("one", copy.inverse().get(1)); |
| assertSame(copy, copy.inverse().inverse()); |
| } |
| |
| public void testInverseSerialization() { |
| ImmutableBiMap<String, Integer> bimap = ImmutableBiMap.copyOf( |
| ImmutableMap.of(1, "one", 2, "two")).inverse(); |
| ImmutableBiMap<String, Integer> copy = |
| SerializableTester.reserializeAndAssert(bimap); |
| assertEquals(Integer.valueOf(1), copy.get("one")); |
| assertEquals("one", copy.inverse().get(1)); |
| assertSame(copy, copy.inverse().inverse()); |
| } |
| } |
| |
| private static <K, V> void assertMapEquals(Map<K, V> map, |
| Object... alternatingKeysAndValues) { |
| int i = 0; |
| for (Entry<K, V> entry : map.entrySet()) { |
| assertEquals(alternatingKeysAndValues[i++], entry.getKey()); |
| assertEquals(alternatingKeysAndValues[i++], entry.getValue()); |
| } |
| } |
| } |