Skip to content

Commit

Permalink
Enable recursive compute test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-manes committed Feb 16, 2021
1 parent 56588a7 commit 7ed20e4
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.testng.Assert;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;

Expand Down Expand Up @@ -1097,31 +1098,32 @@ public void computeIfAbsent_nullValue(Map<Integer, Integer> map, CacheContext co
verifyStats(context, verifier -> verifier.hits(0).misses(1).success(0).failures(1));
}

// FIXME: Requires JDK8 release with JDK-8062841 fix
@CheckNoStats
@CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING })
@Test(enabled = false, dataProvider = "caches", expectedExceptions = IllegalStateException.class)
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine)
public void computeIfAbsent_recursive(Map<Integer, Integer> map, CacheContext context) {
Function<Integer, Integer> mappingFunction = new Function<Integer, Integer>() {
@Override public Integer apply(Integer key) {
return map.computeIfAbsent(key, this);
}
};
map.computeIfAbsent(context.absentKey(), mappingFunction);
try {
map.computeIfAbsent(context.absentKey(), mappingFunction);
Assert.fail();
} catch (StackOverflowError | IllegalStateException e) { /* ignored */ }
}

// FIXME: Requires JDK8 release with JDK-8062841 fix
@CheckNoStats
@CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING })
@Test(enabled = false, dataProvider = "caches", expectedExceptions = IllegalStateException.class)
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine)
public void computeIfAbsent_pingpong(Map<Integer, Integer> map, CacheContext context) {
Function<Integer, Integer> mappingFunction = new Function<Integer, Integer>() {
@Override public Integer apply(Integer key) {
Integer value = context.original().get(key);
return map.computeIfAbsent(value, this);
return map.computeIfAbsent(-key, this);
}
};
map.computeIfAbsent(context.absentKey(), mappingFunction);
try {
map.computeIfAbsent(context.absentKey(), mappingFunction);
Assert.fail();
} catch (StackOverflowError | IllegalStateException e) { /* ignored */ }
}

@Test(dataProvider = "caches")
Expand Down Expand Up @@ -1352,44 +1354,48 @@ public void compute_remove(Map<Integer, Integer> map, CacheContext context) {
verifyRemovalListener(context, verifier -> verifier.hasOnly(count, RemovalCause.EXPLICIT));
}

// FIXME: Requires JDK8 release with JDK-8062841 fix
@CheckNoStats
@CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING })
@Test(enabled = false, dataProvider = "caches", expectedExceptions = StackOverflowError.class)
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine)
public void compute_recursive(Map<Integer, Integer> map, CacheContext context) {
BiFunction<Integer, Integer, Integer> mappingFunction =
new BiFunction<Integer, Integer, Integer>() {
@Override public Integer apply(Integer key, Integer value) {
return map.compute(key, this);
}
};
map.compute(context.absentKey(), mappingFunction);
try {
map.compute(context.absentKey(), mappingFunction);
Assert.fail();
} catch (StackOverflowError | IllegalStateException e) { /* ignored */ }
}

// FIXME: Requires JDK8 release with JDK-8062841 fix
@CheckNoStats
@CacheSpec(population = { Population.SINGLETON, Population.PARTIAL, Population.FULL },
removalListener = { Listener.DEFAULT, Listener.REJECTING })
@Test(enabled = false, dataProvider = "caches", expectedExceptions = StackOverflowError.class)
@Test(dataProvider = "caches")
@CacheSpec(population = Population.EMPTY, implementation = Implementation.Caffeine)
public void compute_pingpong(Map<Integer, Integer> map, CacheContext context) {
var key1 = 1;
var key2 = 2;
BiFunction<Integer, Integer, Integer> mappingFunction =
new BiFunction<Integer, Integer, Integer>() {
@Override public Integer apply(Integer key, Integer value) {
return map.computeIfPresent(context.lastKey(), this);
return map.compute((key == key1) ? key2 : key1, this);
}
};
map.computeIfPresent(context.firstKey(), mappingFunction);
try {
map.compute(key1, mappingFunction);
Assert.fail();
} catch (StackOverflowError | IllegalStateException e) { /* ignored */ }
}

@CacheSpec
@Test(dataProvider = "caches")
public void compute_error(Map<Integer, Integer> map, CacheContext context) {
try {
map.compute(context.absentKey(), (key, value) -> { throw new Error(); });
} catch (Error e) {}
map.compute(context.absentKey(), (key, value) -> { throw new IllegalStateException(); });
Assert.fail();
} catch (IllegalStateException e) { /* ignored */ }
assertThat(map, is(equalTo(context.original())));
verifyStats(context, verifier -> verifier.hits(0).misses(0).success(0).failures(1));
assertThat(map.computeIfPresent(context.absentKey(), (k, v) -> -k), is(nullValue()));
assertThat(map.compute(context.absentKey(), (k, v) -> -k), is(-context.absentKey()));
}

@CheckNoWriter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
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.Implementation;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Listener;
import com.github.benmanes.caffeine.cache.testing.CacheSpec.Population;
import com.github.benmanes.caffeine.cache.testing.CacheValidationListener;
Expand Down Expand Up @@ -748,33 +749,34 @@ public void computeIfAbsent_nullValue(AsyncCache<Integer, Integer> cache, CacheC
assertThat(cache.asMap().size(), is(context.original().size()));
}

// FIXME: Requires JDK8 release with JDK-8062841 fix
@CheckNoStats
@CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING })
@Test(enabled = false, dataProvider = "caches", expectedExceptions = IllegalStateException.class)
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine)
public void computeIfAbsent_recursive(AsyncCache<Integer, Integer> cache, CacheContext context) {
Function<Integer, CompletableFuture<Integer>> mappingFunction =
new Function<Integer, CompletableFuture<Integer>>() {
@Override public CompletableFuture<Integer> apply(Integer key) {
return cache.asMap().computeIfAbsent(key, this);
}
};
cache.asMap().computeIfAbsent(context.absentKey(), mappingFunction);
try {
cache.asMap().computeIfAbsent(context.absentKey(), mappingFunction);
Assert.fail();
} catch (StackOverflowError | IllegalStateException e) { /* ignored */ }
}

// FIXME: Requires JDK8 release with JDK-8062841 fix
@CheckNoStats
@CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING })
@Test(enabled = false, dataProvider = "caches", expectedExceptions = IllegalStateException.class)
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine)
public void computeIfAbsent_pingpong(AsyncCache<Integer, Integer> cache, CacheContext context) {
Function<Integer, CompletableFuture<Integer>> mappingFunction =
new Function<Integer, CompletableFuture<Integer>>() {
@Override public CompletableFuture<Integer> apply(Integer key) {
Integer value = context.original().get(key);
return cache.asMap().computeIfAbsent(value, this);
return cache.asMap().computeIfAbsent(-key, this);
}
};
cache.asMap().computeIfAbsent(context.absentKey(), mappingFunction);
try {
cache.asMap().computeIfAbsent(context.absentKey(), mappingFunction);
Assert.fail();
} catch (StackOverflowError | IllegalStateException e) { /* ignored */ }
}

@Test(dataProvider = "caches")
Expand Down Expand Up @@ -964,10 +966,8 @@ public void compute_remove(AsyncCache<Integer, Integer> cache, CacheContext cont
verifyRemovalListener(context, verifier -> verifier.hasOnly(count, RemovalCause.EXPLICIT));
}

// FIXME: Requires JDK8 release with JDK-8062841 fix
@CheckNoStats
@CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING })
@Test(enabled = false, dataProvider = "caches", expectedExceptions = StackOverflowError.class)
@Test(dataProvider = "caches")
@CacheSpec(implementation = Implementation.Caffeine)
public void compute_recursive(AsyncCache<Integer, Integer> cache, CacheContext context) {
BiFunction<Integer, CompletableFuture<Integer>, CompletableFuture<Integer>> mappingFunction =
new BiFunction<Integer, CompletableFuture<Integer>, CompletableFuture<Integer>>() {
Expand All @@ -976,26 +976,30 @@ public void compute_recursive(AsyncCache<Integer, Integer> cache, CacheContext c
return cache.asMap().compute(key, this);
}
};
cache.asMap().compute(context.absentKey(), mappingFunction);
try {
cache.asMap().compute(context.absentKey(), mappingFunction);
Assert.fail();
} catch (StackOverflowError | IllegalStateException e) { /* ignored */ }
}

// FIXME: Requires JDK8 release with JDK-8062841 fix
@CheckNoStats
@CacheSpec(population = { Population.SINGLETON, Population.PARTIAL, Population.FULL },
removalListener = { Listener.DEFAULT, Listener.REJECTING })
@Test(enabled = false, dataProvider = "caches", expectedExceptions = StackOverflowError.class)
@CacheSpec(population = Population.EMPTY, implementation = Implementation.Caffeine)
@Test(dataProvider = "caches")
public void compute_pingpong(AsyncCache<Integer, Integer> cache, CacheContext context) {
var key1 = 1;
var key2 = 2;
BiFunction<Integer, CompletableFuture<Integer>, CompletableFuture<Integer>> mappingFunction =
new BiFunction<Integer, CompletableFuture<Integer>, CompletableFuture<Integer>>() {
@Override public CompletableFuture<Integer> apply(
Integer key, CompletableFuture<Integer> value) {
return cache.asMap().computeIfPresent(context.lastKey(), this);
return cache.asMap().compute((key == key1) ? key2 : key1, this);
}
};
cache.asMap().computeIfPresent(context.firstKey(), mappingFunction);
try {
cache.asMap().compute(key1, mappingFunction);
Assert.fail();
} catch (StackOverflowError | IllegalStateException e) { /* ignored */ }
}

@CheckNoStats
@Test(dataProvider = "caches")
@CacheSpec(removalListener = { Listener.DEFAULT, Listener.REJECTING })
public void compute_error(AsyncCache<Integer, Integer> cache, CacheContext context) {
Expand All @@ -1007,8 +1011,8 @@ public void compute_error(AsyncCache<Integer, Integer> cache, CacheContext conte
assertThat(cache.synchronous().asMap(), is(equalTo(context.original())));
verifyStats(context, verifier -> verifier.hits(0).misses(0).success(0).failures(0));

assertThat(cache.asMap().computeIfPresent(context.absentKey(),
(k, v) -> CompletableFuture.completedFuture(-k)), is(nullValue()));
var future = CompletableFuture.completedFuture(-context.absentKey());
assertThat(cache.asMap().compute(context.absentKey(), (k, v) -> future), is(future));
}

@CheckNoStats
Expand Down

0 comments on commit 7ed20e4

Please sign in to comment.