diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/LocalAsyncCache.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/LocalAsyncCache.java index 25d47832d8..3e5c6667ea 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/LocalAsyncCache.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/LocalAsyncCache.java @@ -275,9 +275,6 @@ private void fillProxies(Map result) { /** Adds to the cache any extra entries computed that were not requested. */ private void addNewEntries(Map result) { - if (proxies.size() == result.size()) { - return; - } result.forEach((key, value) -> { if (!proxies.containsKey(key)) { cache.put(key, CompletableFuture.completedFuture(value)); diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncCacheTest.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncCacheTest.java index 6fda56543a..2f789d573d 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncCacheTest.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncCacheTest.java @@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat; import static java.util.function.Function.identity; import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toSet; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -436,6 +437,25 @@ public void getAllFunction_exceeds(AsyncCache cache, CacheContext cont assertThat(context).stats().hits(0).misses(result.size()).success(1).failures(0); } + @Test(dataProvider = "caches") + @CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING }) + public void getAllFunction_different(AsyncCache cache, CacheContext context) { + int requested = ThreadLocalRandom.current().nextInt(1, context.absent().size() / 2); + var requestedKeys = context.absentKeys().stream().limit(requested).collect(toSet()); + var actual = context.absent().entrySet().stream() + .filter(entry -> !requestedKeys.contains(entry.getKey())) + .limit(requested) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + var result = cache.getAll(requestedKeys, keys -> { + return actual; + }).join(); + + assertThat(result).isEmpty(); + assertThat(cache).hasSize(context.initialSize() + actual.size()); + assertThat(cache.synchronous().asMap()).containsAtLeastEntriesIn(actual); + assertThat(context).stats().hits(0).misses(actual.size()).success(1).failures(0); + } + @Test(dataProvider = "caches") @CacheSpec(population = { Population.SINGLETON, Population.PARTIAL, Population.FULL }, removalListener = { Listener.DEFAULT, Listener.REJECTING }) @@ -653,6 +673,25 @@ public void getAllBifunction_exceeds(AsyncCache cache, CacheContext co assertThat(context).stats().hits(0).misses(result.size()).success(1).failures(0); } + @Test(dataProvider = "caches") + @CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING }) + public void getAllBifunction_different(AsyncCache cache, CacheContext context) { + int requested = ThreadLocalRandom.current().nextInt(1, context.absent().size() / 2); + var requestedKeys = context.absentKeys().stream().limit(requested).collect(toSet()); + var actual = context.absent().entrySet().stream() + .filter(entry -> !requestedKeys.contains(entry.getKey())) + .limit(requested) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + var result = cache.getAll(requestedKeys, (keys, executor) -> { + return CompletableFuture.completedFuture(actual); + }).join(); + + assertThat(result).isEmpty(); + assertThat(cache).hasSize(context.initialSize() + actual.size()); + assertThat(cache.synchronous().asMap()).containsAtLeastEntriesIn(actual); + assertThat(context).stats().hits(0).misses(actual.size()).success(1).failures(0); + } + @Test(dataProvider = "caches") @CacheSpec(population = { Population.SINGLETON, Population.PARTIAL, Population.FULL }, removalListener = { Listener.DEFAULT, Listener.REJECTING }) diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncLoadingCacheTest.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncLoadingCacheTest.java index 226235e732..bd4ad3e97f 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncLoadingCacheTest.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/AsyncLoadingCacheTest.java @@ -217,6 +217,17 @@ public void getAll_exceeds(AsyncLoadingCache cache, CacheContext conte assertThat(context).stats().hits(0).misses(result.size()).success(1).failures(0); } + @Test(dataProvider = "caches") + @CacheSpec(loader = Loader.BULK_DIFFERENT, + removalListener = { Listener.DEFAULT, Listener.REJECTING }) + public void getAll_different(AsyncLoadingCache cache, CacheContext context) { + var result = cache.getAll(context.absentKeys()).join(); + + assertThat(result).isEmpty(); + assertThat(cache.asMap()).containsAtLeastEntriesIn(result); + assertThat(context).stats().hits(0).misses(context.absent().size()).success(1).failures(0); + } + @Test(dataProvider = "caches") @CacheSpec(loader = { Loader.NEGATIVE, Loader.BULK_NEGATIVE }, population = { Population.SINGLETON, Population.PARTIAL, Population.FULL }, diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheSpec.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheSpec.java index fc4c913ec5..4dca3cb46c 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheSpec.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/CacheSpec.java @@ -476,6 +476,19 @@ enum Loader implements CacheLoader { return result; } }, + /** A bulk-only loader that loads only keys that were not requested. */ + BULK_DIFFERENT { + @Override public Int load(Int key) { + throw new UnsupportedOperationException(); + } + @Override public Map loadAll(Set keys) throws Exception { + var result = new HashMap(keys.size()); + for (Int key : keys) { + result.put(key.negate(), key); + } + return result; + } + }, /** A bulk-only loader that loads more than requested. */ BULK_NEGATIVE_EXCEEDS { @Override public Int load(Int key) {