// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.collections;
import org.junit.Test;
import org.mockito.Mockito;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Simon Thoresen Hult
*/
public class LazyMapTest {
@Test
public void requireThatInitialDelegateIsEmpty() {
LazyMap map = newLazyMap(new HashMap());
assertEquals(LazyMap.EmptyMap.class, map.getDelegate().getClass());
}
@Test
public void requireThatEmptyMapPutUpgradesToSingletonMap() {
LazyMap map = newLazyMap(new HashMap());
assertNull(map.put("foo", "bar"));
assertEquals(LazyMap.SingletonMap.class, map.getDelegate().getClass());
map = newLazyMap(new HashMap());
map.putAll(Collections.singletonMap("foo", "bar"));
assertEquals(LazyMap.SingletonMap.class, map.getDelegate().getClass());
}
@Test
public void requireThatEmptyMapPutAllEmptyMapDoesNotUpgradeToSingletonMap() {
LazyMap map = newLazyMap(new HashMap());
map.putAll(Collections.emptyMap());
assertEquals(LazyMap.EmptyMap.class, map.getDelegate().getClass());
}
@Test
public void requireThatEmptyMapPutAllUpgradesToFinalMap() {
Map delegate = new HashMap<>();
LazyMap map = newLazyMap(delegate);
map.putAll(new HashMapBuilder()
.put("foo", "bar")
.put("baz", "cox").map);
assertSame(delegate, map.getDelegate());
assertEquals(2, delegate.size());
assertEquals("bar", delegate.get("foo"));
assertEquals("cox", delegate.get("baz"));
}
@Test
public void requireThatSingletonMapRemoveEntryDowngradesToEmptyMap() {
LazyMap map = newSingletonMap("foo", "bar");
assertEquals("bar", map.remove("foo"));
assertEquals(LazyMap.EmptyMap.class, map.getDelegate().getClass());
}
@Test
public void requireThatSingletonMapRemoveUnknownDoesNotDowngradesToEmptyMap() {
LazyMap map = newSingletonMap("foo", "bar");
assertNull(map.remove("baz"));
assertEquals(LazyMap.SingletonMap.class, map.getDelegate().getClass());
}
@Test
public void requireThatSingletonMapValueMayBeChangedInPlace() {
LazyMap map = newSingletonMap("foo", "bar");
Map delegate = map.getDelegate();
assertEquals("bar", map.put("foo", "baz"));
assertEquals("baz", map.get("foo"));
assertSame(delegate, map.getDelegate());
map.putAll(Collections.singletonMap("foo", "cox"));
assertSame(delegate, map.getDelegate());
assertEquals("cox", map.get("foo"));
}
@Test
public void requireThatSingletonMapPutAllEmptyMapDoesNotUpgradeToFinalMap() {
LazyMap map = newSingletonMap("foo", "bar");
map.putAll(Collections.emptyMap());
assertEquals(LazyMap.SingletonMap.class, map.getDelegate().getClass());
}
@Test
public void requireThatSingletonMapPutUpgradesToFinalMap() {
Map delegate = new HashMap<>();
LazyMap map = newSingletonMap(delegate, "fooKey", "fooVal");
map.put("barKey", "barVal");
assertSame(delegate, map.getDelegate());
assertEquals(2, delegate.size());
assertEquals("fooVal", delegate.get("fooKey"));
assertEquals("barVal", delegate.get("barKey"));
}
@Test
public void requireThatSingletonMapPutAllUpgradesToFinalMap() {
Map delegate = new HashMap<>();
LazyMap map = newSingletonMap(delegate, "fooKey", "fooVal");
map.putAll(new HashMapBuilder()
.put("barKey", "barVal")
.put("bazKey", "bazVal").map);
assertSame(delegate, map.getDelegate());
assertEquals(3, delegate.size());
assertEquals("fooVal", delegate.get("fooKey"));
assertEquals("barVal", delegate.get("barKey"));
assertEquals("bazVal", delegate.get("bazKey"));
}
@Test
public void requireThatSingletonEntryIsMutable() {
LazyMap map = newSingletonMap("foo", "bar");
Map.Entry entry = map.entrySet().iterator().next();
entry.setValue("baz");
assertEquals("baz", map.get("foo"));
}
@Test
public void requireThatSingletonEntryImplementsHashCode() {
assertEquals(newSingletonMap("foo", "bar").entrySet().iterator().next().hashCode(),
newSingletonMap("foo", "bar").entrySet().iterator().next().hashCode());
}
@Test
public void requireThatSingletonEntryImplementsEquals() {
Map.Entry map = newSingletonMap("foo", "bar").entrySet().iterator().next();
assertNotEquals(map, null);
assertNotEquals(map, new Object());
assertEquals(map, map);
assertNotEquals(map, newSingletonMap("baz", "cox").entrySet().iterator().next());
assertNotEquals(map, newSingletonMap("foo", "cox").entrySet().iterator().next());
assertEquals(map, newSingletonMap("foo", "bar").entrySet().iterator().next());
}
@Test
public void requireThatSingletonEntrySetIteratorNextThrowsIfInvokedMoreThanOnce() {
LazyMap map = newSingletonMap("foo", "bar");
Iterator> it = map.entrySet().iterator();
it.next();
try {
it.next();
fail();
} catch (NoSuchElementException e) {
}
try {
it.next();
fail();
} catch (NoSuchElementException e) {
}
}
@Test
public void requireThatSingletonEntrySetIteratorRemoveThrowsIfInvokedBeforeNext() {
LazyMap map = newSingletonMap("foo", "bar");
Iterator> it = map.entrySet().iterator();
try {
it.remove();
fail();
} catch (IllegalStateException e) {
}
}
@SuppressWarnings("unchecked")
private static Map makeMockMap() {
return Mockito.mock(Map.class);
}
@Test
public void requireThatMapDelegates() {
Map delegate = makeMockMap();
Map map = newLazyMap(delegate);
map.put("foo", "bar");
map.put("baz", "cox"); // trigger the assignment of the delegate
Mockito.verify(delegate).put("foo", "bar");
Mockito.verify(delegate).put("baz", "cox");
Map arg = Collections.singletonMap("baz", "cox");
map.putAll(arg);
Mockito.verify(delegate).putAll(arg);
assertEquals(0, map.size());
Mockito.verify(delegate).size();
assertFalse(map.isEmpty());
Mockito.verify(delegate).isEmpty();
assertFalse(map.containsKey("foo"));
Mockito.verify(delegate).containsKey("foo");
assertFalse(map.containsValue("bar"));
Mockito.verify(delegate).containsValue("bar");
assertNull(map.get("foo"));
Mockito.verify(delegate).get("foo");
assertNull(map.remove("foo"));
Mockito.verify(delegate).remove("foo");
map.clear();
Mockito.verify(delegate).clear();
assertTrue(map.keySet().isEmpty());
Mockito.verify(delegate).keySet();
assertTrue(map.values().isEmpty());
Mockito.verify(delegate).values();
assertTrue(map.entrySet().isEmpty());
Mockito.verify(delegate).entrySet();
}
@Test
public void requireThatHashCodeIsImplemented() {
assertEquals(newLazyMap(null).hashCode(),
newLazyMap(null).hashCode());
}
@Test
public void requireThatEqualsIsImplemented() {
Map