/*
* Copyright Terracotta, 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 org.ehcache.core;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.core.events.CacheEventDispatcher;
import org.ehcache.expiry.Expiry;
import org.ehcache.core.spi.function.Function;
import org.ehcache.core.spi.store.Store;
import org.ehcache.core.spi.store.Store.ValueHolder;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.core.IsCollectionContaining.hasItems;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* @author Ludovic Orban
*/
@SuppressWarnings({ "unchecked", "serial", "rawtypes" })
public class EhcacheBulkMethodsTest {
@Test
public void testPutAll() throws Exception {
Store<Number, CharSequence> store = mock(Store.class);
InternalCache<Number, CharSequence> ehcache = getCache(store);
ehcache.init();
ehcache.putAll(new HashMap<Number, CharSequence>() {{
put(1, "one");
put(2, "two");
put(3, "three");
}});
verify(store).bulkCompute((Set<? extends Number>) Matchers.argThat(hasItems((Number)1, 2, 3)), any(Function.class));
}
@Test
public void testGetAll() throws Exception {
Store<Number, CharSequence> store = mock(Store.class);
when(store.bulkComputeIfAbsent((Set<? extends Number>)argThat(hasItems(1, 2, 3)), any(Function.class))).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Function function = (Function)invocation.getArguments()[1];
function.apply(invocation.getArguments()[0]);
return new HashMap(){{put(1, null); put(2, null); put(3, valueHolder("three")); }};
}
});
InternalCache<Number, CharSequence> ehcache = getCache(store);
ehcache.init();
Map<Number, CharSequence> result = ehcache.getAll(new HashSet<Number>(Arrays.asList(1, 2, 3)));
assertThat(result, hasEntry((Number)1, (CharSequence) null));
assertThat(result, hasEntry((Number)2, (CharSequence) null));
assertThat(result, hasEntry((Number)3, (CharSequence)"three"));
verify(store).bulkComputeIfAbsent((Set<? extends Number>)argThat(hasItems(1, 2, 3)), any(Function.class));
}
@Test
public void testRemoveAll() throws Exception {
Store<Number, CharSequence> store = mock(Store.class);
InternalCache<Number, CharSequence> ehcache = getCache(store);
ehcache.init();
ehcache.removeAll(new HashSet<Number>(Arrays.asList(1, 2, 3)));
verify(store).bulkCompute((Set<? extends Number>) argThat(hasItems(1, 2, 3)), any(Function.class));
}
protected InternalCache<Number, CharSequence> getCache(Store<Number, CharSequence> store) {
CacheConfiguration<Number, CharSequence> cacheConfig = mock(CacheConfiguration.class);
when(cacheConfig.getExpiry()).thenReturn(mock(Expiry.class));
CacheEventDispatcher<Number, CharSequence> cacheEventDispatcher = mock(CacheEventDispatcher.class);
return new Ehcache<Number, CharSequence>(cacheConfig, store, cacheEventDispatcher, LoggerFactory.getLogger(Ehcache.class + "-" + "EhcacheBulkMethodsTest"));
}
static <K, V> Map.Entry<K, V> entry(final K key, final V value) {
return new Map.Entry<K, V>() {
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
return null;
}
@Override
public int hashCode() {
return key.hashCode() + value.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj.getClass() == getClass()) {
Map.Entry<K, V> other = (Map.Entry<K, V>)obj;
return key.equals(other.getKey()) && value.equals(other.getValue());
}
return false;
}
@Override
public String toString() {
return key + "/" + value;
}
};
}
static <V> ValueHolder<V> valueHolder(final V value) {
return new ValueHolder<V>() {
@Override
public V value() {
return value;
}
@Override
public long creationTime(TimeUnit unit) {
throw new AssertionError();
}
@Override
public long expirationTime(TimeUnit unit) {
return 0;
}
@Override
public boolean isExpired(long expirationTime, TimeUnit unit) {
return false;
}
@Override
public long lastAccessTime(TimeUnit unit) {
throw new AssertionError();
}
@Override
public float hitRate(long now, TimeUnit unit) {
throw new AssertionError();
}
@Override
public long hits() {
throw new UnsupportedOperationException("Implement me!");
}
@Override
public long getId() {
throw new UnsupportedOperationException("Implement me!");
}
};
}
}