/*
* Copyright 2015 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.cache;
import static com.github.benmanes.caffeine.cache.testing.CacheWriterVerifier.verifyWriter;
import static com.github.benmanes.caffeine.cache.testing.HasRemovalNotifications.hasRemovalNotifications;
import static com.github.benmanes.caffeine.testing.IsEmptyMap.emptyMap;
import static com.github.benmanes.caffeine.testing.IsFutureValue.futureOf;
import static java.util.stream.Collectors.toMap;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import com.github.benmanes.caffeine.cache.testing.CacheContext;
import com.github.benmanes.caffeine.cache.testing.CacheProvider;
import com.github.benmanes.caffeine.cache.testing.CacheSpec;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.CacheWeigher;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Compute;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Expire;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Implementation;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Listener;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Loader;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Maximum;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Population;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.ReferenceType;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Stats;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Writer;
import com.github.benmanes.caffeine.cache.testing.CacheValidationListener;
import com.github.benmanes.caffeine.cache.testing.RejectingCacheWriter.DeleteException;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import com.google.common.testing.GcFinalization;
/**
* The test cases for caches that support a reference eviction policy.
*
* @author ben.manes@gmail.com (Ben Manes)
*/
@Listeners(CacheValidationListener.class)
@SuppressWarnings("BoxedPrimitiveConstructor")
@Test(groups = "slow", dataProviderClass = CacheProvider.class)
public final class ReferenceTest {
// These tests require that the JVM uses -XX:SoftRefLRUPolicyMSPerMB=0 so that soft references
// can be reliably garbage collected (by making them behave as weak references).
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.WEAK, population = Population.FULL)
public void identity_keys(Cache<Integer, Integer> cache, CacheContext context) {
Integer key = new Integer(context.firstKey());
assertThat(cache.getIfPresent(key), is(nullValue()));
}
@Test(dataProvider = "caches")
@CacheSpec(values = {ReferenceType.WEAK, ReferenceType.SOFT}, population = Population.FULL)
public void identity_values(Cache<Integer, Integer> cache, CacheContext context) {
Integer value = new Integer(context.original().get(context.firstKey()));
assertThat(cache.asMap().containsValue(value), is(false));
}
/* ---------------- Cache -------------- */
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void getIfPresent(Cache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.getIfPresent(key), is(nullValue()));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void get(Cache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.get(key, k -> context.absentValue()), is(context.absentValue()));
long count = context.initialSize() - cache.estimatedSize() + 1;
if (context.population() != Population.SINGLETON) {
assertThat(count, is(greaterThan(1L)));
}
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void get_writerFails(Cache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
cache.get(key, Function.identity());
} finally {
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void getAllPresent(Cache<Integer, Integer> cache, CacheContext context) {
Set<Integer> keys = context.firstMiddleLastKeys();
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.getAllPresent(keys), is(emptyMap()));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void put(Cache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
cache.put(key, context.absentValue());
long count = context.initialSize() - cache.estimatedSize() + 1;
if (context.population() != Population.SINGLETON) {
assertThat(count, is(greaterThan(1L)));
}
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void put_writerFails(Cache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
cache.put(key, context.absentValue());
} finally {
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void putAll(Cache<Integer, Integer> cache, CacheContext context) {
Map<Integer, Integer> entries = ImmutableMap.of(context.firstKey(), context.absentValue(),
context.middleKey(), context.absentValue(), context.lastKey(), context.absentValue());
context.clear();
GcFinalization.awaitFullGc();
cache.putAll(entries);
if (context.population() != Population.SINGLETON) {
assertThat(context.initialSize() - cache.estimatedSize(), is(greaterThan(0L)));
}
long count = context.initialSize() - cache.estimatedSize() + 3;
assertThat(count, is(greaterThan(3L)));
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void putAll_writerFails(Cache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
cache.putAll(ImmutableMap.of(key, context.absentValue()));
} finally {
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void invalidate(Cache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
cache.invalidate(key);
long count = context.initialSize() - cache.estimatedSize();
assertThat(count, is(greaterThan(0L)));
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void invalidate_writerFails(Cache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
cache.invalidate(key);
} finally {
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void invalidateAll(Cache<Integer, Integer> cache, CacheContext context) {
Set<Integer> keys = context.firstMiddleLastKeys();
context.clear();
GcFinalization.awaitFullGc();
cache.invalidateAll(keys);
long count = context.initialSize() - cache.estimatedSize();
assertThat(count, is(greaterThan(0L)));
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void invalidateAll_writerFails(Cache<Integer, Integer> cache, CacheContext context) {
Set<Integer> keys = context.firstMiddleLastKeys();
try {
context.clear();
GcFinalization.awaitFullGc();
cache.invalidateAll(keys);
} finally {
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void invalidateAll_full(Cache<Integer, Integer> cache, CacheContext context) {
context.clear();
GcFinalization.awaitFullGc();
cache.invalidateAll();
long count = context.initialSize() - cache.estimatedSize();
assertThat(count, is(greaterThan(0L)));
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void invalidateAll_full_writerFails(Cache<Integer, Integer> cache, CacheContext context) {
try {
context.clear();
GcFinalization.awaitFullGc();
cache.invalidateAll();
} finally {
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void estimatedSize(Cache<Integer, Integer> cache, CacheContext context) {
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.estimatedSize(), is(context.initialSize()));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void cleanUp(Cache<Integer, Integer> cache, CacheContext context) {
context.clear();
GcFinalization.awaitFullGc();
cache.cleanUp();
long count = context.initialSize() - cache.estimatedSize();
assertThat(count, is(greaterThan(0L)));
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void cleanUp_writerFails(Cache<Integer, Integer> cache, CacheContext context) {
context.clear();
GcFinalization.awaitFullGc();
cache.cleanUp();
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
/* ---------------- LoadingCache -------------- */
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.SINGLETON, stats = Stats.ENABLED, loader = Loader.IDENTITY,
removalListener = Listener.CONSUMING)
public void get(LoadingCache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.get(key), is(key));
assertThat(cache, hasRemovalNotifications(context, 1, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(1, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void get_writerFails(LoadingCache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
cache.get(key);
} finally {
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED,
loader = {Loader.IDENTITY, Loader.BULK_IDENTITY}, removalListener = Listener.CONSUMING)
public void getAll(LoadingCache<Integer, Integer> cache, CacheContext context) {
Set<Integer> keys = context.firstMiddleLastKeys();
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.getAll(keys), is(Maps.uniqueIndex(keys, Functions.identity())));
long count = context.initialSize() - cache.estimatedSize() + keys.size();
assertThat(count, is(greaterThan((long) keys.size())));
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL,
compute = Compute.SYNC, loader = {Loader.IDENTITY, Loader.BULK_IDENTITY})
public void getAll_writerFails(LoadingCache<Integer, Integer> cache, CacheContext context) {
Set<Integer> keys = context.firstMiddleLastKeys();
try {
context.clear();
GcFinalization.awaitFullGc();
cache.getAll(keys);
} finally {
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, loader = Loader.IDENTITY,
removalListener = Listener.CONSUMING)
public void refresh(LoadingCache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
cache.refresh(key);
long count = context.initialSize() - cache.estimatedSize() + 1;
assertThat(count, is(greaterThan(1L)));
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> {
verifier.deleted(key, context.original().get(key), RemovalCause.COLLECTED);
});
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void refresh_writerFails(LoadingCache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
cache.refresh(key);
context.disableRejectingCacheWriter();
assertThat(cache.asMap().isEmpty(), is(false));
}
/* ---------------- AsyncLoadingCache -------------- */
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.WEAK, values = ReferenceType.STRONG,
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void getIfPresent(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.getIfPresent(key), is(not(nullValue())));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.WEAK, values = ReferenceType.STRONG,
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, loader = Loader.IDENTITY,
removalListener = Listener.CONSUMING)
public void get(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) {
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.get(context.absentKey()), is(futureOf(context.absentKey())));
long count = context.initialSize();
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.WEAK, values = ReferenceType.STRONG,
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED,
loader = {Loader.NEGATIVE, Loader.BULK_NEGATIVE}, removalListener = Listener.CONSUMING)
public void getAll(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) {
Set<Integer> keys = ImmutableSet.of(context.firstKey(), context.lastKey(), context.absentKey());
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.getAll(keys).join(),
is(keys.stream().collect(toMap(Function.identity(), key -> -key))));
long count = context.initialSize() - cache.synchronous().estimatedSize() + 1;
assertThat(count, is(greaterThan((long) keys.size())));
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.WEAK, values = ReferenceType.STRONG,
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void put(AsyncLoadingCache<Integer, Integer> cache, CacheContext context) {
Integer key = context.absentKey();
context.clear();
GcFinalization.awaitFullGc();
cache.put(key, CompletableFuture.completedFuture(context.absentValue()));
long count = context.initialSize();
assertThat(cache.synchronous().estimatedSize(), is(1L));
assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
}
/* ---------------- Map -------------- */
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void isEmpty(Map<Integer, Integer> cache, CacheContext context) {
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.isEmpty(), is(false));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void size(Map<Integer, Integer> cache, CacheContext context) {
context.clear();
GcFinalization.awaitFullGc();
assertThat(cache.size(), is((int) context.initialSize()));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void containsKey(Map<Integer, Integer> map, CacheContext context) {
Integer first = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.containsKey(first), is(false));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.WEAK, values = ReferenceType.STRONG,
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void containsValue(Map<Integer, Integer> map, CacheContext context) {
Integer value = context.original().get(context.firstKey());
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.containsValue(value), is(false));
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void clear(Map<Integer, Integer> map, CacheContext context) {
context.clear();
GcFinalization.awaitFullGc();
map.clear();
long count = context.initialSize() - map.size();
assertThat(count, is(greaterThan(0L)));
assertThat(map, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void clear_writerFails(Map<Integer, Integer> map, CacheContext context) {
try {
context.clear();
GcFinalization.awaitFullGc();
map.clear();
} finally {
context.disableRejectingCacheWriter();
assertThat(map.keySet().isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void putIfAbsent(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.putIfAbsent(key, context.absentValue()), is(nullValue()));
assertThat(map.get(key), is(context.absentValue()));
long count = context.initialSize() - map.size() + 1;
assertThat(count, is(greaterThan(1L)));
assertThat(map, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void putIfAbsent_writerFails(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
map.putIfAbsent(key, context.absentValue());
} finally {
context.disableRejectingCacheWriter();
assertThat(map.isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void put(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.put(key, context.absentValue()), is(nullValue()));
assertThat(map.get(key), is(context.absentValue()));
long count = context.initialSize() - map.size() + 1;
assertThat(count, is(greaterThan(1L)));
assertThat(map, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void put_writerFails(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
map.put(key, context.absentValue());
} finally {
context.disableRejectingCacheWriter();
assertThat(map.isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void replace(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.replace(key, context.absentValue()), is(nullValue()));
}
// replace_writerFail: Not needed due to replacement being impossible
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void replaceConditionally(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.replace(key, context.absentValue(), context.absentValue()), is(false));
}
// replace_writerFail: Not needed due to replacement being impossible
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void remove(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.remove(key), is(nullValue()));
long count = context.initialSize() - map.size();
assertThat(count, is(greaterThan(0L)));
assertThat(map, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void remove_writerFails(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
map.remove(key);
} finally {
context.disableRejectingCacheWriter();
assertThat(map.isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void removeConditionally(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
Integer value = context.original().get(key);
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.remove(key, value), is(true));
long count = context.initialSize() - map.size() - 1;
assertThat(count, is(greaterThan(0L)));
assertThat(map, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
// removeConditionally_writerFail: Not needed due to removal being impossible
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void computeIfAbsent(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.computeIfAbsent(key, k -> context.absentValue()), is(context.absentValue()));
long count = context.initialSize() - map.size() + 1;
assertThat(count, is(greaterThan(1L)));
assertThat(map, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void computeIfAbsent_writerFails(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
map.computeIfAbsent(key, k -> context.absentValue());
} finally {
context.disableRejectingCacheWriter();
assertThat(map.isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void computeIfPresent(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.computeIfPresent(key, (k, v) -> context.absentValue()), is(nullValue()));
if (context.isGuava()) {
context.cleanUp();
}
long count = context.initialSize() - map.size();
assertThat(count, is(greaterThan(0L)));
assertThat(map, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
// computeIfPresent_writerFail: Not needed due to exiting without side-effects
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void compute(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.compute(key, (k, v) -> {
assertThat(v, is(nullValue()));
return context.absentValue();
}), is(context.absentValue()));
long count = context.initialSize() - map.size() + 1;
assertThat(count, is(greaterThan(1L)));
assertThat(map, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void compute_writerFails(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
map.compute(key, (k, v) -> context.absentValue());
} finally {
context.disableRejectingCacheWriter();
assertThat(map.isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
expireAfterAccess = Expire.DISABLED, expireAfterWrite = Expire.DISABLED,
maximumSize = Maximum.DISABLED, weigher = CacheWeigher.DEFAULT,
population = Population.FULL, stats = Stats.ENABLED, removalListener = Listener.CONSUMING)
public void merge(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
context.clear();
GcFinalization.awaitFullGc();
assertThat(map.merge(key, context.absentValue(), (oldValue, v) -> {
throw new AssertionError("Should never be called");
}), is(context.absentValue()));
long count = context.initialSize() - map.size() + 1;
assertThat(count, is(greaterThan(1L)));
assertThat(map, hasRemovalNotifications(context, count, RemovalCause.COLLECTED));
verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED));
}
@Test(dataProvider = "caches", expectedExceptions = DeleteException.class)
@CacheSpec(keys = ReferenceType.STRONG, values = {ReferenceType.WEAK, ReferenceType.SOFT},
implementation = Implementation.Caffeine, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.DISABLED,
weigher = CacheWeigher.DEFAULT, population = Population.FULL, stats = Stats.ENABLED,
compute = Compute.SYNC, removalListener = Listener.CONSUMING, writer = Writer.EXCEPTIONAL)
public void merge_writerFails(Map<Integer, Integer> map, CacheContext context) {
Integer key = context.firstKey();
try {
context.clear();
GcFinalization.awaitFullGc();
map.merge(key, context.absentValue(), (k, v) -> v);
} finally {
context.disableRejectingCacheWriter();
assertThat(map.isEmpty(), is(false));
}
}
@Test(dataProvider = "caches")
@CacheSpec(requiresWeakOrSoft = true)
public void iterators(Map<Integer, Integer> map, CacheContext context) {
context.clear();
GcFinalization.awaitFullGc();
assertThat(Iterators.size(map.keySet().iterator()), is(0));
assertThat(Iterators.size(map.values().iterator()), is(0));
assertThat(Iterators.size(map.entrySet().iterator()), is(0));
}
/* ---------------- Weights -------------- */
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine, keys = ReferenceType.STRONG,
values = {ReferenceType.WEAK, ReferenceType.SOFT}, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.UNREACHABLE,
weigher = CacheWeigher.COLLECTION, population = Population.EMPTY, stats = Stats.ENABLED,
removalListener = Listener.CONSUMING, writer = Writer.DISABLED)
public void putIfAbsent_weighted(Cache<Integer, List<Integer>> cache, CacheContext context) {
Integer key = context.absentKey();
cache.put(key, ImmutableList.of(1));
GcFinalization.awaitFullGc();
assertThat(cache.asMap().putIfAbsent(key, ImmutableList.of(1, 2, 3)), is(nullValue()));
assertThat(cache.policy().eviction().get().weightedSize().getAsLong(), is(3L));
}
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine, keys = ReferenceType.STRONG,
values = {ReferenceType.WEAK, ReferenceType.SOFT}, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.UNREACHABLE,
weigher = CacheWeigher.COLLECTION, population = Population.EMPTY, stats = Stats.ENABLED,
removalListener = Listener.DEFAULT, writer = Writer.DISABLED)
public void put_weighted(Cache<Integer, List<Integer>> cache, CacheContext context) {
Integer key = context.absentKey();
cache.put(key, ImmutableList.of(1));
GcFinalization.awaitFullGc();
assertThat(cache.asMap().put(key, ImmutableList.of(1, 2, 3)), is(nullValue()));
assertThat(cache.policy().eviction().get().weightedSize().getAsLong(), is(3L));
}
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine, keys = ReferenceType.STRONG,
values = {ReferenceType.WEAK, ReferenceType.SOFT}, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.UNREACHABLE,
weigher = CacheWeigher.COLLECTION, population = Population.EMPTY, stats = Stats.ENABLED,
removalListener = Listener.DEFAULT, writer = Writer.DISABLED)
public void computeIfAbsent_weighted(Cache<Integer, List<Integer>> cache, CacheContext context) {
Integer key = context.absentKey();
cache.put(key, ImmutableList.of(1));
GcFinalization.awaitFullGc();
cache.asMap().computeIfAbsent(1, k -> ImmutableList.of(1, 2, 3));
assertThat(cache.policy().eviction().get().weightedSize().getAsLong(), is(3L));
}
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine, keys = ReferenceType.STRONG,
values = {ReferenceType.WEAK, ReferenceType.SOFT}, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.UNREACHABLE,
weigher = CacheWeigher.COLLECTION, population = Population.EMPTY, stats = Stats.ENABLED,
removalListener = Listener.DEFAULT, writer = Writer.DISABLED)
public void compute_weighted(Cache<Integer, List<Integer>> cache, CacheContext context) {
Integer key = context.absentKey();
cache.put(key, ImmutableList.of(1));
GcFinalization.awaitFullGc();
cache.asMap().compute(1, (k, v) -> ImmutableList.of(1, 2, 3));
assertThat(cache.policy().eviction().get().weightedSize().getAsLong(), is(3L));
}
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine, keys = ReferenceType.STRONG,
values = {ReferenceType.WEAK, ReferenceType.SOFT}, expireAfterAccess = Expire.DISABLED,
expireAfterWrite = Expire.DISABLED, maximumSize = Maximum.UNREACHABLE,
weigher = CacheWeigher.COLLECTION, population = Population.EMPTY, stats = Stats.ENABLED,
removalListener = Listener.DEFAULT, writer = Writer.DISABLED)
public void merge_weighted(Cache<Integer, List<Integer>> cache, CacheContext context) {
Integer key = context.absentKey();
cache.put(key, ImmutableList.of(1));
GcFinalization.awaitFullGc();
cache.asMap().merge(1, ImmutableList.of(1, 2, 3), (oldValue, v) -> {
throw new AssertionError("Should never be called");
});
assertThat(cache.policy().eviction().get().weightedSize().getAsLong(), is(3L));
}
}