/*
* Copyright 2016 Ben Manes. All Rights Reserved.
*
* 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.github.benmanes.caffeine.jcache;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.integration.CacheLoader;
import javax.cache.spi.CachingProvider;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.github.benmanes.caffeine.jcache.configuration.CaffeineConfiguration;
import com.github.benmanes.caffeine.jcache.spi.CaffeineCachingProvider;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.testing.FakeTicker;
/**
* A testing harness for simplifying the unit tests.
*
* @author ben.manes@gmail.com (Ben Manes)
*/
@Test(singleThreaded = true)
public abstract class AbstractJCacheTest {
protected static final long START_TIME_MS = System.currentTimeMillis();
protected static final long EXPIRY_DURATION = TimeUnit.MINUTES.toMillis(1);
protected static final Integer KEY_1 = 1, VALUE_1 = -1;
protected static final Integer KEY_2 = 2, VALUE_2 = -2;
protected static final Integer KEY_3 = 3, VALUE_3 = -3;
protected final Set<Integer> keys = ImmutableSet.of(KEY_1, KEY_2, KEY_3);
protected final Map<Integer, Integer> entries = ImmutableMap.of(
KEY_1, VALUE_1, KEY_2, VALUE_2, KEY_3, VALUE_3);
protected LoadingCacheProxy<Integer, Integer> jcacheLoading;
protected CacheProxy<Integer, Integer> jcache;
protected CacheManager cacheManager;
protected FakeTicker ticker;
@BeforeClass(alwaysRun = true)
public void beforeClass() {
CachingProvider provider = Caching.getCachingProvider(CaffeineCachingProvider.class.getName());
cacheManager = provider.getCacheManager(
provider.getDefaultURI(), provider.getDefaultClassLoader());
}
@BeforeMethod(alwaysRun = true)
public void before() {
ticker = new FakeTicker().advance(START_TIME_MS, TimeUnit.MILLISECONDS);
jcache = (CacheProxy<Integer, Integer>) cacheManager.createCache("jcache", getConfiguration());
jcacheLoading = (LoadingCacheProxy<Integer, Integer>) cacheManager.createCache(
"jcacheLoading", getLoadingConfiguration());
}
@AfterMethod(alwaysRun = true)
public void after() {
cacheManager.destroyCache("jcache");
cacheManager.destroyCache("jcacheLoading");
}
/** The base configuration used by the test. */
protected abstract CaffeineConfiguration<Integer, Integer> getConfiguration();
/* ---------------- Utility methods ------------- */
@Nullable
protected static Expirable<Integer> getExpirable(
CacheProxy<Integer, Integer> cache, Integer key) {
return cache.cache.getIfPresent(key);
}
protected void advanceHalfExpiry() {
ticker.advance(EXPIRY_DURATION / 2, TimeUnit.MILLISECONDS);
}
protected void advancePastExpiry() {
ticker.advance(2 * EXPIRY_DURATION, TimeUnit.MILLISECONDS);
}
/** @return the current time in milliseconds */
protected final long currentTimeMillis() {
return TimeUnit.NANOSECONDS.toMillis(ticker.read());
}
/** The loading configuration used by the test. */
protected CaffeineConfiguration<Integer, Integer> getLoadingConfiguration() {
CaffeineConfiguration<Integer, Integer> configuration = getConfiguration();
configuration.setCacheLoaderFactory(this::getCacheLoader);
configuration.setReadThrough(true);
return configuration;
}
/** The cache loader used by the test. */
protected CacheLoader<Integer, Integer> getCacheLoader() {
return new CacheLoader<Integer, Integer>() {
@Override public Integer load(Integer key) {
return key;
}
@Override public Map<Integer, Integer> loadAll(Iterable<? extends Integer> keys) {
return Maps.asMap(ImmutableSet.copyOf(keys), this::load);
}
};
}
}