package com.cedarsoftware.util; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.powermock.modules.junit4.PowerMockRunner; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.verify; @SuppressWarnings("ResultOfMethodCallIgnored") @RunWith(PowerMockRunner.class) public class TestTrackingMap { @Mock public Map<String, Object> mockedBackingMap; @Mock public Map<String, Object> anotherMockedBackingMap; @Test public void getFree() { TrackingMap<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "value"); map.put("second", "value"); map.expungeUnused(); assertEquals(0, map.size()); assertTrue(map.isEmpty()); } @Test public void getOne() { TrackingMap<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "value"); map.get("first"); map.expungeUnused(); assertEquals(1, map.size()); assertEquals(map.get("first"), "firstValue"); assertFalse(map.isEmpty()); } @Test public void getOneCaseInsensitive() { TrackingMap<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "value"); map.get("FiRsT"); map.expungeUnused(); assertEquals(1, map.size()); assertEquals(map.get("first"), "firstValue"); assertFalse(map.isEmpty()); } @Test public void getOneMultiple() { TrackingMap<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "value"); map.get("FiRsT"); map.get("FIRST"); map.get("First"); map.expungeUnused(); assertEquals(1, map.size()); assertEquals(map.get("first"), "firstValue"); assertFalse(map.isEmpty()); } @Test public void containsKeyCounts() { TrackingMap<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "value"); map.containsKey("first"); map.expungeUnused(); assertEquals(1, map.size()); assertEquals(map.get("first"), "firstValue"); assertFalse(map.isEmpty()); } @Test public void containsValueDoesNotCount() { TrackingMap<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "value"); map.containsValue("firstValue"); map.expungeUnused(); assertEquals(0, map.size()); assertTrue(map.isEmpty()); } @Test public void sameBackingMapsAreEqual() { CaseInsensitiveMap<String, Object> backingMap = new CaseInsensitiveMap<>(); TrackingMap<String, Object> map1 = new TrackingMap<>(backingMap); TrackingMap<String, Object> map2 = new TrackingMap<>(backingMap); assertEquals(map1, map2); } @Test public void equalBackingMapsAreEqual() { Map map1 = new TrackingMap<>(new HashMap<>()); Map map2 = new TrackingMap<>(new HashMap<>()); assertEquals(map1, map2); map1.put('a', 65); map1.put('b', 66); map2 = new TrackingMap<>(new HashMap<>()); map2.put('a', 65); map2.put('b', 66); assertEquals(map1, map2); } @Test public void unequalBackingMapsAreNotEqual() { Map map1 = new TrackingMap<>(new HashMap<>()); Map map2 = new TrackingMap<>(new HashMap<>()); assertEquals(map1, map2); map1.put('a', 65); map1.put('b', 66); map2 = new TrackingMap<>(new HashMap<>()); map2.put('a', 65); map2.put('b', 66); map2.put('c', 67); assertNotEquals(map1, map2); } @Test public void testDifferentClassIsEqual() { CaseInsensitiveMap<String, Object> backingMap = new CaseInsensitiveMap<>(); backingMap.put("a", "alpha"); backingMap.put("b", "bravo"); // Identity check Map map1 = new TrackingMap<>(backingMap); assert map1.equals(backingMap); // Equivalence check Map map2 = new LinkedHashMap<>(); map2.put("b", "bravo"); map2.put("a", "alpha"); assert map1.equals(map2); } @Test public void testGet() throws Exception { Map<String, Object> map = new TrackingMap<>(mockedBackingMap); map.get("key"); verify(mockedBackingMap).get("key"); } @Test public void testPut() throws Exception { Map<String, Object> map = new TrackingMap<>(mockedBackingMap); map.put("key", "value"); verify(mockedBackingMap).put("key", "value"); } @Test public void testContainsKey() throws Exception { Map<String, Object> map = new TrackingMap<>(mockedBackingMap); map.containsKey("key"); verify(mockedBackingMap).containsKey("key"); } @Test public void testPutAll() throws Exception { Map<String, Object> map = new TrackingMap<>(mockedBackingMap); Map additionalEntries = new HashMap(); additionalEntries.put("animal", "aardvaark"); additionalEntries.put("ballast", "bubbles"); additionalEntries.put("tricky", additionalEntries); map.putAll(additionalEntries); verify(mockedBackingMap).putAll(additionalEntries); } @Test public void testRemove() throws Exception { TrackingMap<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "secondValue"); map.put("third", "thirdValue"); map.get("FiRsT"); map.get("ThirD"); map.remove("first"); map.expungeUnused(); assertEquals(1, map.size()); assertEquals(map.get("thiRd"), "thirdValue"); assertFalse(map.isEmpty()); } @Test public void testHashCode() throws Exception { Map<String, Object> map1 = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map1.put("f", "foxtrot"); map1.put("o", "oscar"); Map<String, Object> map2 = new LinkedHashMap<>(); map2.put("o", "foxtrot"); map2.put("f", "oscar"); Map map3 = new TrackingMap<>(new CaseInsensitiveMap<>()); map3.put("F", "foxtrot"); map3.put("O", "oscar"); assert map1.hashCode() == map2.hashCode(); assert map2.hashCode() == map3.hashCode(); } @Test public void testToString() throws Exception { TrackingMap<String, Object> map = new TrackingMap<>(mockedBackingMap); assertNotNull(map.toString()); } @Test public void testClear() throws Exception { Map<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "secondValue"); map.put("third", "thirdValue"); map.get("FiRsT"); map.get("ThirD"); map.clear(); assertEquals(0, map.size()); assertTrue(map.isEmpty()); } @Test public void testValues() throws Exception { Map<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "secondValue"); map.put("third", "thirdValue"); Collection<Object> values = map.values(); assertNotNull(values); assertEquals(3, map.size()); assertTrue(values.contains("firstValue")); assertTrue(values.contains("secondValue")); assertTrue(values.contains("thirdValue")); } @Test public void testKeySet() throws Exception { Map<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "secondValue"); map.put("third", "thirdValue"); Collection<String> keys = map.keySet(); assertNotNull(keys); assertEquals(3, map.size()); assertTrue(keys.contains("first")); assertTrue(keys.contains("second")); assertTrue(keys.contains("third")); } @Test public void testEntrySet() throws Exception { CaseInsensitiveMap<String, Object> backingMap = new CaseInsensitiveMap<>(); Map<String, Object> map = new TrackingMap<>(backingMap); map.put("first", "firstValue"); map.put("second", "secondValue"); map.put("third", "thirdValue"); Set<Map.Entry<String, Object>> keys = map.entrySet(); assertNotNull(keys); assertEquals(3, keys.size()); assertEquals(backingMap.entrySet(), map.entrySet()); } @Test public void testInformAdditionalUsage() throws Exception { TrackingMap<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "secondValue"); map.put("third", "thirdValue"); Collection<String> additionalUsage = new HashSet<>(); additionalUsage.add("FiRsT"); additionalUsage.add("ThirD"); map.informAdditionalUsage(additionalUsage); map.remove("first"); map.expungeUnused(); assertEquals(1, map.size()); assertEquals(map.get("thiRd"), "thirdValue"); assertFalse(map.isEmpty()); } @Test public void testInformAdditionalUsage1() throws Exception { TrackingMap<String, Object> map = new TrackingMap<>(new CaseInsensitiveMap<String, Object>()); map.put("first", "firstValue"); map.put("second", "secondValue"); map.put("third", "thirdValue"); TrackingMap<String, Object> additionalUsage = new TrackingMap<>(map); additionalUsage.get("FiRsT"); additionalUsage.get("ThirD"); map.informAdditionalUsage(additionalUsage); map.remove("first"); map.expungeUnused(); assertEquals(1, map.size()); assertEquals(map.get("thiRd"), "thirdValue"); assertFalse(map.isEmpty()); } @Test public void testConstructWithNull() { try { new TrackingMap(null); fail(); } catch (IllegalArgumentException ignored) { } } @Test public void testPuDoesNotCountAsAccess() { TrackingMap trackMap = new TrackingMap(new CaseInsensitiveMap()); trackMap.put("k", "kite"); trackMap.put("u", "uniform"); assert trackMap.keysUsed().isEmpty(); trackMap.put("K", "kilo"); assert trackMap.keysUsed().isEmpty(); assert trackMap.size() == 2; } @Test public void testContainsKeyNotCoundOnNonExistentKey() { TrackingMap trackMap = new TrackingMap(new CaseInsensitiveMap()); trackMap.put("y", "yankee"); trackMap.put("z", "zulu"); trackMap.containsKey("f"); assert trackMap.keysUsed().size() == 1; assert trackMap.keysUsed().contains("f"); } @Test public void testGetNotCoundOnNonExistentKey() { TrackingMap trackMap = new TrackingMap(new CaseInsensitiveMap()); trackMap.put("y", "yankee"); trackMap.put("z", "zulu"); trackMap.get("f"); assert trackMap.keysUsed().size() == 1; assert trackMap.keysUsed().contains("f"); } @Test public void testGetOfNullValueCountsAsAccess() { TrackingMap trackMap = new TrackingMap(new CaseInsensitiveMap()); trackMap.put("y", null); trackMap.put("z", "zulu"); trackMap.get("y"); assert trackMap.keysUsed().size() == 1; } @Test public void testFetchInternalMap() { TrackingMap trackMap = new TrackingMap(new CaseInsensitiveMap()); assert trackMap.getWrappedMap() instanceof CaseInsensitiveMap; trackMap = new TrackingMap(new HashMap()); assert trackMap.getWrappedMap() instanceof HashMap; } }