/** * awaitFullGc() is not quite as reliable a way to ensure calling of a specific finalize method as * the more direct await* methods, but should be reliable enough in practice to avoid flakiness of * this test. (And if it isn't, we'd like to know about it first!) */ public void testAwaitFullGc() { final CountDownLatch finalizerRan = new CountDownLatch(1); final WeakReference<Object> ref = new WeakReference<Object>( new Object() { @Override protected void finalize() { finalizerRan.countDown(); } }); // Don't copy this into your own test! // Use e.g. awaitClear or await(CountDownLatch) instead. GcFinalization.awaitFullGc(); // If this test turns out to be flaky, add a second call to awaitFullGc() // GcFinalization.awaitFullGc(); assertEquals(0, finalizerRan.getCount()); assertNull(ref.get()); } }
@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)); }
@Test(dataProvider = "caches") @CacheSpec(requiresWeakOrSoft = true, 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> map, CacheContext context) { context.clear(); GcFinalization.awaitFullGc(); assertThat(map.isEmpty(), is(false)); awaitFullCleanup(context.cache()); assertThat(map.isEmpty(), is(true)); }
@Test(dataProvider = "caches") @CacheSpec(requiresWeakOrSoft = true, 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> map, CacheContext context) { context.clear(); GcFinalization.awaitFullGc(); assertThat(map.size(), is((int) context.initialSize())); awaitFullCleanup(context.cache()); assertThat(map.size(), is(0)); }
@Test(dataProvider = "caches") @CacheSpec(requiresWeakOrSoft = true, 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 key = context.firstKey(); context.clear(); GcFinalization.awaitFullGc(); assertThat(map.containsKey(key), is(context.isStrongValues())); }
@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(implementation = Implementation.Caffeine, requiresWeakOrSoft = true, 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)), context.isStrongValues() ? is(ImmutableList.of(1)) : nullValue()); assertThat(cache.policy().eviction().get().weightedSize().getAsLong(), is(3L)); }
@Test(dataProvider = "caches") @CacheSpec(requiresWeakOrSoft = true, 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( context.isStrongValues() ? notNullValue() : nullValue())); }
@Test(dataProvider = "caches") @CacheSpec(implementation = Implementation.Caffeine, requiresWeakOrSoft = true, 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)), context.isStrongValues() ? is(ImmutableList.of(1)) : nullValue()); assertThat(cache.policy().eviction().get().weightedSize().getAsLong(), is(context.isStrongValues() ? 1L : 3L)); }
@Test(dataProvider = "caches") @CacheSpec(requiresWeakOrSoft = true, 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(); assertThat(map.size(), is(0)); assertThat(map, 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)); }
@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(requiresWeakOrSoft = true, 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(); Integer value = context.original().get(key); context.clear(); GcFinalization.awaitFullGc(); assertThat(map.replace(key, value, context.absentValue()), is(true)); }
@Test(dataProvider = "caches") @CacheSpec(implementation = Implementation.Caffeine, requiresWeakOrSoft = true, 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(key, (k, v) -> ImmutableList.of(1, 2, 3)); assertThat(cache.policy().eviction().get().weightedSize().getAsLong(), is(3L)); }
@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)); }
@Test(dataProvider = "caches") @CacheSpec(requiresWeakOrSoft = true, 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(); Integer value = context.original().get(key); context.clear(); GcFinalization.awaitFullGc(); awaitFullCleanup(cache.synchronous()); assertThat(cache.synchronous().getIfPresent(key), is(value)); }
@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)); }
@Test(dataProvider = "caches") @CacheSpec(requiresWeakOrSoft = true, 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(LoadingCache<Integer, Integer> cache, CacheContext context) { Set<Integer> keys = context.firstMiddleLastKeys(); context.clear(); GcFinalization.awaitFullGc(); awaitFullCleanup(cache); assertThat(cache.getAll(keys), is(Maps.toMap(keys, key -> -key))); long count = context.initialSize() - (context.isStrongValues() ? keys.size() : 0); assertThat(cache.estimatedSize(), is((long) keys.size())); assertThat(cache, hasRemovalNotifications(context, count, RemovalCause.COLLECTED)); verifyWriter(context, (verifier, writer) -> verifier.deletions(count, RemovalCause.COLLECTED)); }
@Test(dataProvider = "caches") @CacheSpec(requiresWeakOrSoft = true, 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(); awaitFullCleanup(cache); assertThat(cache.estimatedSize(), is(0L)); 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.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)); }