Skip to content

Commit

Permalink
minor increase to test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-manes committed Aug 30, 2021
1 parent f61b922 commit 330ecc6
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 21 deletions.
1 change: 0 additions & 1 deletion build.gradle
Expand Up @@ -58,7 +58,6 @@ subprojects {
apply from: "${rootDir}/gradle/objectLayout.gradle"

sourceCompatibility = JavaVersion.VERSION_11
archivesBaseName = path[1..-1].replaceAll(':', '-').toLowerCase()

configurations {
all {
Expand Down
Expand Up @@ -127,10 +127,10 @@ abstract class BoundedLocalCache<K, V> extends BLCHeader.DrainStatusRef<K, V>
* the window into the main space. If the main space is already full, then a historic frequency
* filter determines whether to evict the newly admitted entry or the victim entry chosen by the
* eviction policy. This process ensures that the entries in the window were very recently used
* and entries in the main space are accessed very frequently and are moderately recent. The
* windowing allows the policy to have a high hit rate when entries exhibit bursty access pattern
* while the filter ensures that popular items are retained. The admission window uses LRU and
* the main space uses Segmented LRU.
* and entries in the main space are accessed very frequently and are at least moderately recent.
* The windowing allows the policy to have a high hit rate when entries exhibit a bursty access
* pattern while the filter ensures that popular items are retained. The admission window uses
* LRU and the main space uses Segmented LRU.
*
* The optimal size of the window vs main spaces is workload dependent [3]. A large admission
* window is favored by recency-biased workloads while a small one favors frequency-biased
Expand Down Expand Up @@ -939,8 +939,8 @@ boolean hasExpired(Node<K, V> node, long now) {
}

/**
* Attempts to evict the entry based on the given removal cause. A removal due to may be ignored
* if the entry was updated and is no longer eligible for eviction.
* Attempts to evict the entry based on the given removal cause. A removal may be ignored if the
* entry was updated and is no longer eligible for eviction.
*
* @param node the entry to evict
* @param cause the reason to evict
Expand Down
4 changes: 4 additions & 0 deletions checksum.xml
Expand Up @@ -46,6 +46,7 @@
<trusted-key id='7a01b0f236e5430f' group='com.google.code.gson' />
<trusted-key id='b0f3710fa64900e7' group='com.google.code.gson' />
<trusted-key id='1669c4bb543e0445' group='com.google.errorprone' />
<trusted-key id='3c27d97b0c83a85c' group='com.google.errorprone' />
<trusted-key id='912d2c0eccda55c0' group='com.google.errorprone' />
<trusted-key id='9a259c7ee636c5ed' group='com.google.errorprone' />
<trusted-key id='eba8e97b15086e24' group='com.google.errorprone' />
Expand Down Expand Up @@ -424,6 +425,9 @@
<dependency group='gradle.plugin.com.github.spotbugs.snom' module='spotbugs-gradle-plugin' version='4.7.2'>
<sha512>44C956BA53F81CEF4BC36EC4FC11A7862922524C970BCA4116790615A335795B28B0717F9F105C89949727DC77D97F5D4CE830438510776C52F69D968FCE14D6</sha512>
</dependency>
<dependency group='gradle.plugin.com.github.spotbugs.snom' module='spotbugs-gradle-plugin' version='4.7.3'>
<sha512>9EC10D4159C75F8C4E0AE9AE190FC8385FA54715B8DB8F675D1F3A64384F2C141B6EBBDEBB51AE349BD6ED162B29F94B1476E00FAB43505E9800668CBAAA84BD</sha512>
</dependency>
<dependency group='gradle.plugin.com.github.spotbugs' module='spotbugs-gradle-plugin' version='2.0.0'>
<sha512>B3BFAD07E6A3D4D73CBCE802D8614CF4AC84E589166D243D41028DC077F84C027DF4D514F145360405F37DA73A8F2E7B65D90877A9EE1151174D2440530F9051</sha512>
</dependency>
Expand Down
12 changes: 6 additions & 6 deletions gradle/dependencies.gradle
Expand Up @@ -25,7 +25,7 @@
*/
ext {
versions = [
akka: '2.6.15',
akka: '2.6.16',
cache2k: '2.2.1.Final',
checkerFramework: '3.17.0',
coherence: '20.06',
Expand All @@ -35,8 +35,8 @@ ext {
commonsIo: '2.11.0',
concurrentlinkedhashmap: '1.4.2',
config: '1.4.1',
ehcache3: '3.9.5',
errorprone: '2.8.1',
ehcache3: '3.9.6',
errorprone: '2.9.0',
errorproneJavac: '9+181-r4173-1',
elasticSearch: '8.0.0-alpha1',
expiringMap: '0.5.10',
Expand Down Expand Up @@ -72,7 +72,7 @@ ext {
jcacheTck: '1.1.1',
jctools: '3.3.0',
junit: '4.13.2',
mockito: '3.11.2',
mockito: '3.12.4',
paxExam: '4.13.4',
testng: '7.4.0',
truth: '1.1.3',
Expand All @@ -92,12 +92,12 @@ ext {
jmhReport: '0.9.0',
nexusPublish: '1.1.0',
nullaway: '1.1.0',
pmd: '6.37.0',
pmd: '6.38.0',
semanticVersioning: '1.1.0',
shadow: '7.0.0',
sonarqube: '3.3',
spotbugs: '4.4.0',
spotbugsPlugin: '4.7.2',
spotbugsPlugin: '4.7.3',
stats: '0.46.0',
versions: '0.39.0',
]
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
@@ -1,4 +1,4 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-rc-3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
Expand Down
Expand Up @@ -30,8 +30,8 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
Expand All @@ -57,7 +57,7 @@ public abstract class AbstractCopier<A> implements Copier {
Inet6Address.class, InetSocketAddress.class, LocalDate.class, LocalTime.class,
LocalDateTime.class, Instant.class, Duration.class);
JAVA_DEEP_COPY = Map.of(Date.class, o -> ((Date) o).clone(),
Calendar.class, o -> ((Calendar) o).clone());
GregorianCalendar.class, o -> ((GregorianCalendar) o).clone());
}

private final Set<Class<?>> immutableClasses;
Expand Down
Expand Up @@ -66,7 +66,7 @@ protected byte[] serialize(Object object) {
@SuppressWarnings("BanSerializableRead")
protected Object deserialize(byte[] data, ClassLoader classLoader) {
try (var bytes = new ByteArrayInputStream(data);
var input = new ClassLoaderAwareObjectInputStream(bytes, classLoader)) {
var input = newInputStream(bytes, classLoader)) {
return input.readObject();
} catch (IOException e) {
throw new CacheException("Failed to deserialize", e);
Expand All @@ -75,6 +75,12 @@ protected Object deserialize(byte[] data, ClassLoader classLoader) {
}
}

// @VisibleForTesting
ObjectInputStream newInputStream(
InputStream in, ClassLoader classLoader) throws IOException {
return new ClassLoaderAwareObjectInputStream(in, classLoader);
}

/** An {@linkplain ObjectInputStream} that instantiates using the supplied classloader. */
protected static class ClassLoaderAwareObjectInputStream extends ObjectInputStream {
private final ClassLoader classLoader;
Expand Down
Expand Up @@ -16,6 +16,7 @@
import static com.google.common.truth.Truth.assertThat;

import javax.cache.Cache;
import javax.cache.configuration.Configuration;

import org.testng.annotations.Test;

Expand Down Expand Up @@ -43,4 +44,17 @@ public void unwrap() {
assertThat(jcache.unwrap(com.github.benmanes.caffeine.cache.Cache.class))
.isSameInstanceAs(jcache.cache);
}

@SuppressWarnings("serial")
@Test(expectedExceptions = IllegalArgumentException.class)
public void unwrap_configuration() {
abstract class Dummy implements Configuration<Integer, Integer> {};
jcache.getConfiguration(Dummy.class);
}

@Test(expectedExceptions = IllegalArgumentException.class)
public void unwrap_entry() {
jcache.put(KEY_1, VALUE_1);
jcache.iterator().next().unwrap(String.class);
}
}
Expand Up @@ -17,8 +17,12 @@

import static com.google.common.truth.Truth.assertThat;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.io.UncheckedIOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
Expand All @@ -28,9 +32,13 @@
import java.util.Set;
import java.util.function.Function;

import javax.cache.CacheException;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import com.google.common.collect.ImmutableSet;

/**
* @author ben.manes@gmail.com (Ben Manes)
*/
Expand All @@ -53,8 +61,35 @@ public void null_classLoader(Copier copier) {
}

@Test(dataProvider = "copier", expectedExceptions = UncheckedIOException.class)
public void notSerializable(Copier copier) {
copy(copier, new ByteArrayInputStream(new byte[0]));
public void serializable_fail(JavaSerializationCopier copier) {
copier.serialize(new Object());
}

@Test
public void deserializable_resolveClass() throws Exception {
var copier = new JavaSerializationCopier();
copier.copy(ImmutableSet.of(), ClassLoader.getPlatformClassLoader());
}

@Test(dataProvider = "copier", expectedExceptions = CacheException.class)
public void deserializable_badData(JavaSerializationCopier copier) {
copier.deserialize(new byte[0], Thread.currentThread().getContextClassLoader());
}

@Test(expectedExceptions = CacheException.class)
public void deserializable_classNotFound() throws Exception {
var copier = new JavaSerializationCopier() {
@Override protected ObjectInputStream newInputStream(
InputStream in, ClassLoader classLoader) throws IOException {
return new ObjectInputStream(in) {
@Override protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
throw new ClassNotFoundException();
}
};
}
};
copier.roundtrip(Instant.now(), Thread.currentThread().getContextClassLoader());
}

@Test(dataProvider = "copier")
Expand Down
Expand Up @@ -64,6 +64,7 @@ protected CaffeineConfiguration<Integer, Integer> getConfiguration() {
configuration.setExpiryPolicyFactory(() -> new AccessedExpiryPolicy(
new Duration(TimeUnit.MILLISECONDS, EXPIRY_DURATION)));
configuration.setTickerFactory(() -> ticker::read);
configuration.setStatisticsEnabled(true);
return configuration;
}

Expand All @@ -72,6 +73,17 @@ public Object[] providesEternal() {
return new Object[] { true, false };
}

/* --------------- containsKey --------------- */

@Test
public void containsKey_expired() {
jcache.put(KEY_1, VALUE_1);
ticker.setAutoIncrementStep(EXPIRY_DURATION / 2, TimeUnit.MILLISECONDS);

assertThat(jcache.containsKey(KEY_1)).isFalse();
assertThat(getExpirable(jcache, KEY_1)).isNull();
}

/* --------------- get --------------- */

@Test
Expand All @@ -94,6 +106,15 @@ public void get_present(boolean eternal) {
assertThat(expirable.getExpireTimeMS()).isEqualTo(currentTimeMillis() + EXPIRY_DURATION);
}

@Test
public void get_expired() {
jcache.put(KEY_1, VALUE_1);
ticker.setAutoIncrementStep(EXPIRY_DURATION / 2, TimeUnit.MILLISECONDS);

assertThat(jcache.get(KEY_1)).isNull();
assertThat(getExpirable(jcache, KEY_1)).isNull();
}

/* --------------- get (loading) --------------- */

@Test
Expand Down
Expand Up @@ -54,9 +54,32 @@ protected CaffeineConfiguration<Integer, Integer> getConfiguration() {
configuration.setExpiryPolicyFactory(() -> new CreatedExpiryPolicy(
new Duration(TimeUnit.MILLISECONDS, EXPIRY_DURATION)));
configuration.setTickerFactory(() -> ticker::read);
configuration.setStatisticsEnabled(true);
return configuration;
}

/* --------------- containsKey --------------- */

@Test
public void containsKey_expired() {
jcache.put(KEY_1, VALUE_1);
ticker.setAutoIncrementStep(EXPIRY_DURATION / 2, TimeUnit.MILLISECONDS);

assertThat(jcache.containsKey(KEY_1)).isFalse();
assertThat(getExpirable(jcache, KEY_1)).isNull();
}

/* --------------- get --------------- */

@Test
public void get_expired() {
jcache.put(KEY_1, VALUE_1);
ticker.setAutoIncrementStep(EXPIRY_DURATION / 2, TimeUnit.MILLISECONDS);

assertThat(jcache.get(KEY_1)).isNull();
assertThat(getExpirable(jcache, KEY_1)).isNull();
}

/* --------------- get (loading) --------------- */

@Test
Expand All @@ -76,6 +99,14 @@ public void get_loading_expired() {
assertThat(expirable.getExpireTimeMS()).isEqualTo(currentTimeMillis() + EXPIRY_DURATION);
}

@Test
public void get_loading_expired_lazy() {
jcacheLoading.put(KEY_1, VALUE_1);
ticker.setAutoIncrementStep((long) (EXPIRY_DURATION / 2.5), TimeUnit.MILLISECONDS);

assertThat(jcacheLoading.get(KEY_1)).isEqualTo(KEY_1);
}

@Test
public void get_loading_present() {
jcacheLoading.put(KEY_1, VALUE_1);
Expand Down Expand Up @@ -197,11 +228,20 @@ public void putIfAbsent_expired() {
jcache.putIfAbsent(KEY_1, VALUE_1);
advancePastExpiry();

jcache.putIfAbsent(KEY_1, VALUE_2);
assertThat(jcache.putIfAbsent(KEY_1, VALUE_2)).isTrue();
Expirable<Integer> expirable = getExpirable(jcache, KEY_1);
assertThat(expirable.get()).isEqualTo(VALUE_2);
assertThat(expirable.getExpireTimeMS()).isEqualTo(currentTimeMillis() + EXPIRY_DURATION);
}

@Test
public void putIfAbsent_expired_lazy() {
jcache.putIfAbsent(KEY_1, VALUE_1);

ticker.setAutoIncrementStep(EXPIRY_DURATION / 2, TimeUnit.MILLISECONDS);
assertThat(jcache.putIfAbsent(KEY_1, VALUE_2)).isTrue();
}

@Test
public void putIfAbsent_present() {
jcache.putIfAbsent(KEY_1, VALUE_1);
Expand Down
Expand Up @@ -54,9 +54,28 @@ protected CaffeineConfiguration<Integer, Integer> getConfiguration() {
configuration.setExpiryPolicyFactory(() -> new ModifiedExpiryPolicy(
new Duration(TimeUnit.MILLISECONDS, EXPIRY_DURATION)));
configuration.setTickerFactory(() -> ticker::read);
configuration.setStatisticsEnabled(true);
return configuration;
}

@Test
public void containsKey_expired() {
jcache.put(KEY_1, VALUE_1);
ticker.setAutoIncrementStep(EXPIRY_DURATION / 2, TimeUnit.MILLISECONDS);

assertThat(jcache.containsKey(KEY_1)).isFalse();
assertThat(getExpirable(jcache, KEY_1)).isNull();
}

@Test
public void get_expired() {
jcache.put(KEY_1, VALUE_1);
ticker.setAutoIncrementStep(EXPIRY_DURATION / 2, TimeUnit.MILLISECONDS);

assertThat(jcache.get(KEY_1)).isNull();
assertThat(getExpirable(jcache, KEY_1)).isNull();
}

@Test
public void getAndPut() {
jcache.put(KEY_1, VALUE_1);
Expand Down

0 comments on commit 330ecc6

Please sign in to comment.