/* * Copyright (C) 2009 The Guava Authors * * 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 static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import com.google.common.collect.testing.MapTestSuiteBuilder; import com.google.common.collect.testing.TestStringMapGenerator; import com.google.common.collect.testing.features.CollectionSize; import com.google.common.collect.testing.features.MapFeature; import junit.framework.Test; import junit.framework.TestSuite; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /** * Unit test for {@link ForwardingMap}. * * @author Hayward Chan * @author Louis Wasserman */ public class ForwardingMapTest extends ForwardingTestCase { static class StandardImplForwardingMap extends ForwardingMap { private final Map backingMap; StandardImplForwardingMap(Map backingMap) { this.backingMap = backingMap; } @Override protected Map delegate() { return backingMap; } @Override public boolean containsKey(Object key) { return standardContainsKey(key); } @Override public boolean containsValue(Object value) { return standardContainsValue(value); } @Override public void putAll(Map map) { standardPutAll(map); } @Override public V remove(Object object) { return standardRemove(object); } @Override public boolean equals(Object object) { return standardEquals(object); } @Override public int hashCode() { return standardHashCode(); } @Override public Set keySet() { return new StandardKeySet(); } @Override public Collection values() { return new StandardValues(); } @Override public String toString() { return standardToString(); } @Override public Set> entrySet() { return new StandardEntrySet() { @Override public Iterator> iterator() { return delegate() .entrySet() .iterator(); } }; } @Override public void clear() { standardClear(); } @Override public boolean isEmpty() { return standardIsEmpty(); } } Map forward; public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(ForwardingMapTest.class); suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() { @Override protected Map create( Entry[] entries) { Map map = Maps.newLinkedHashMap(); for (Entry entry : entries) { map.put(entry.getKey(), entry.getValue()); } return new StandardImplForwardingMap(map); } }).named("ForwardingMap[LinkedHashMap] with standard implementations") .withFeatures(CollectionSize.ANY, MapFeature.ALLOWS_NULL_VALUES, MapFeature.ALLOWS_NULL_KEYS, MapFeature.GENERAL_PURPOSE) .createTestSuite()); suite.addTest(MapTestSuiteBuilder.using(new TestStringMapGenerator() { @Override protected Map create( Entry[] entries) { ImmutableMap.Builder builder = ImmutableMap.builder(); for (Entry entry : entries) { builder.put(entry.getKey(), entry.getValue()); } return new StandardImplForwardingMap(builder.build()); } }).named("ForwardingMap[ImmutableMap] with standard implementations") .withFeatures( CollectionSize.ANY, MapFeature.REJECTS_DUPLICATES_AT_CREATION, MapFeature.ALLOWS_NULL_QUERIES) .createTestSuite()); return suite; } @Override public void setUp() throws Exception { super.setUp(); /* * Class parameters must be raw, so we can't create a proxy with generic * type arguments. The created proxy only records calls and returns null, so * the type is irrelevant at runtime. */ @SuppressWarnings("unchecked") final Map map = createProxyInstance(Map.class); forward = new ForwardingMap() { @Override protected Map delegate() { return map; } }; } public void testSize() { forward().size(); assertEquals("[size]", getCalls()); } public void testIsEmpty() { forward().isEmpty(); assertEquals("[isEmpty]", getCalls()); } public void testRemove() { forward().remove(null); assertEquals("[remove(Object)]", getCalls()); } public void testClear() { forward().clear(); assertEquals("[clear]", getCalls()); } public void testContainsKey() { forward().containsKey("asdf"); assertEquals("[containsKey(Object)]", getCalls()); } public void testContainsValue() { forward().containsValue(false); assertEquals("[containsValue(Object)]", getCalls()); } public void testGet_Object() { forward().get("asdf"); assertEquals("[get(Object)]", getCalls()); } public void testPut_Key_Value() { forward().put("key", false); assertEquals("[put(Object,Object)]", getCalls()); } public void testPutAll_Map() { forward().putAll(new HashMap()); assertEquals("[putAll(Map)]", getCalls()); } public void testKeySet() { forward().keySet(); assertEquals("[keySet]", getCalls()); } public void testValues() { forward().values(); assertEquals("[values]", getCalls()); } public void testEntrySet() { forward().entrySet(); assertEquals("[entrySet]", getCalls()); } public void testToString() { forward().toString(); assertEquals("[toString]", getCalls()); } public void testEquals_Object() { forward().equals("asdf"); assertEquals("[equals(Object)]", getCalls()); } public void testHashCode() { forward().hashCode(); assertEquals("[hashCode]", getCalls()); } public void testStandardEntrySet() throws InvocationTargetException { @SuppressWarnings("unchecked") final Map map = createMock(Map.class); @SuppressWarnings("unchecked") final Set> entrySet = createMock(Set.class); expect(map.containsKey(anyObject())).andReturn(false).anyTimes(); expect(map.get(anyObject())).andReturn(null).anyTimes(); expect(map.isEmpty()).andReturn(true).anyTimes(); expect(map.remove(anyObject())).andReturn(null).anyTimes(); expect(map.size()).andReturn(0).anyTimes(); expect(entrySet.iterator()) .andReturn(Iterators.>emptyIterator()) .anyTimes(); map.clear(); expectLastCall().anyTimes(); replay(map, entrySet); Map forward = new ForwardingMap() { @Override protected Map delegate() { return map; } @Override public Set> entrySet() { return new StandardEntrySet() { @Override public Iterator> iterator() { return entrySet.iterator(); } }; } }; callAllPublicMethods(Set.class, forward.entrySet()); verify(map, entrySet); } public void testStandardKeySet() throws InvocationTargetException { @SuppressWarnings("unchecked") Set> entrySet = createMock(Set.class); expect(entrySet.iterator()).andReturn( Iterators.>emptyIterator()).anyTimes(); @SuppressWarnings("unchecked") final Map map = createMock(Map.class); expect(map.containsKey(anyObject())).andReturn(false).anyTimes(); expect(map.isEmpty()).andReturn(true).anyTimes(); expect(map.remove(anyObject())).andReturn(null).anyTimes(); expect(map.size()).andReturn(0).anyTimes(); expect(map.entrySet()).andReturn(entrySet).anyTimes(); map.clear(); expectLastCall().anyTimes(); replay(entrySet, map); Map forward = new ForwardingMap() { @Override protected Map delegate() { return map; } @Override public Set keySet() { return new StandardKeySet(); } }; callAllPublicMethods(Set.class, forward.keySet()); verify(entrySet, map); } public void testStandardValues() throws InvocationTargetException { @SuppressWarnings("unchecked") Set> entrySet = createMock(Set.class); expect(entrySet.iterator()).andReturn( Iterators.>emptyIterator()).anyTimes(); @SuppressWarnings("unchecked") final Map map = createMock(Map.class); expect(map.containsValue(anyObject())).andReturn(false).anyTimes(); expect(map.isEmpty()).andReturn(true).anyTimes(); expect(map.size()).andReturn(0).anyTimes(); expect(map.entrySet()).andReturn(entrySet).anyTimes(); map.clear(); expectLastCall().anyTimes(); replay(entrySet, map); Map forward = new ForwardingMap() { @Override protected Map delegate() { return map; } @Override public Collection values() { return new StandardValues(); } }; callAllPublicMethods(Collection.class, forward.values()); verify(entrySet, map); } Map forward() { return forward; } }