severalStepsToList_withReversedOrderOfSuppliers sometimes runs into StackOverflowError
Testing Problem
See https://github.com/jlink/jqwik/actions/runs/3693074859/jobs/6252643488#step:5:211
java.lang.StackOverflowError
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:657)
at net.jqwik.api.ShrinkingDistance.combine(ShrinkingDistance.java:38)
at net.jqwik.engine.properties.shrinking.CombinedShrinkable.distance(CombinedShrinkable.java:54)
at net.jqwik.engine.properties.shrinking.LazyOfShrinkable.distance(LazyOfShrinkable.java:39)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:657)
at net.jqwik.api.ShrinkingDistance.combine(ShrinkingDistance.java:38)
at net.jqwik.engine.properties.shrinking.CombinedShrinkable.distance(CombinedShrinkable.java:54)
at net.jqwik.engine.properties.shrinking.LazyOfShrinkable.distance(LazyOfShrinkable.java:39)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:[234]
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:657)
at net.jqwik.api.ShrinkingDistance.combine(ShrinkingDistance.java:38)
at net.jqwik.engine.properties.shrinking.CombinedShrinkable.distance(CombinedShrinkable.java:54)
at net.jqwik.engine.properties.shrinking.LazyOfShrinkable.distance(LazyOfShrinkable.java:39)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:657)
at net.jqwik.api.ShrinkingDistance.combine(ShrinkingDistance.java:38)
at net.jqwik.engine.properties.shrinking.CombinedShrinkable.distance(CombinedShrinkable.java:54)
at net.jqwik.engine.properties.shrinking.LazyOfShrinkable.distance(LazyOfShrinkable.java:39)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:657)
at net.jqwik.api.ShrinkingDistance.combine(ShrinkingDistance.java:38)
at net.jqwik.engine.properties.shrinking.CombinedShrinkable.distance(CombinedShrinkable.java:54)
at net.jqwik.engine.properties.shrinking.LazyOfShrinkable.distance(LazyOfShrinkable.java:39)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:657)
at net.jqwik.api.ShrinkingDistance.combine(ShrinkingDistance.java:38)
at net.jqwik.engine.properties.shrinking.CombinedShrinkable.distance(CombinedShrinkable.java:54)
at net.jqwik.engine.properties.shrinking.LazyOfShrinkable.distance(LazyOfShrinkable.java:39)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:657)
at net.jqwik.api.ShrinkingDistance.combine(ShrinkingDistance.java:38)
at net.jqwik.engine.properties.shrinking.CombinedShrinkable.distance(CombinedShrinkable.java:54)
at net.jqwik.engine.properties.shrinking.LazyOfShrinkable.distance(LazyOfShrinkable.java:39)
Suggested Solution
-
Refrain from Stream API in
net.jqwik.api.ShrinkingDistance#combineandnet.jqwik.api.ShrinkingDistance#forCollectionso the stacktrace is shorter and easier to understand. -
Limit the depth of the lazy in tests somehow. I'm not sure it is realistic to test thousands of nested combine calls. As I replaced Stream API with a for loop, I got the following failure, which does not seem to have a trivial solution:
java.lang.StackOverflowError
at net.jqwik.engine.properties.shrinking.ShrinkableBigInteger.checkValueInRange(ShrinkableBigInteger.java:73)
at net.jqwik.engine.properties.shrinking.ShrinkableBigInteger.<init>(ShrinkableBigInteger.java:19)
at net.jqwik.engine.properties.arbitraries.randomized.RandomIntegralGenerators.lambda$bigIntegers$1(RandomIntegralGenerators.java:32)
at net.jqwik.api.RandomGenerator.lambda$mapShrinkable$1(RandomGenerator.java:57)
at net.jqwik.engine.properties.arbitraries.randomized.ContainerGenerator.nextUntilAccepted(ContainerGenerator.java:108)
at net.jqwik.engine.properties.arbitraries.randomized.ContainerGenerator.next(ContainerGenerator.java:70)
at net.jqwik.engine.properties.arbitraries.LazyOfArbitrary.generateCurrent(LazyOfArbitrary.java:107)
at net.jqwik.engine.properties.arbitraries.LazyOfArbitrary.lambda$generator$1(LazyOfArbitrary.java:58)
at net.jqwik.engine.properties.arbitraries.combinations.CombineArbitrary.generateShrinkables(CombineArbitrary.java:108)
at net.jqwik.engine.properties.arbitraries.combinations.CombineArbitrary.lambda$combineGenerator$1(CombineArbitrary.java:85)
at net.jqwik.engine.properties.arbitraries.LazyOfArbitrary.generateCurrent(LazyOfArbitrary.java:107)
at net.jqwik.engine.properties.arbitraries.LazyOfArbitrary.lambda$generator$1(LazyOfArbitrary.java:58)
at net.jqwik.engine.properties.arbitraries.combinations.CombineArbitrary.generateShrinkables(CombineArbitrary.java:108)
at net.jqwik.engine.properties.arbitraries.combinations.CombineArbitrary.lambda$combineGenerator$1(CombineArbitrary.java:85)
at net.jqwik.engine.properties.arbitraries.LazyOfArbitrary.generateCurrent(LazyOfArbitrary.java:107)
at net.jqwik.engine.properties.arbitraries.LazyOfArbitrary.lambda$generator$1(LazyOfArbitrary.java:58)
at net.jqwik.engine.properties.arbitraries.combinations.CombineArbitrary.generateShrinkables(CombineArbitrary.java:108)
at net.jqwik.engine.properties.arbitraries.combinations.CombineArbitrary.lambda$combineGenerator$1(CombineArbitrary.java:85)
at net.jqwik.engine.properties.arbitraries.LazyOfArbitrary.generateCurrent(LazyOfArbitrary.java:107)
at net.jqwik.engine.properties.arbitraries.LazyOfArbitrary.lambda$generator$1(LazyOfArbitrary.java:58)
at net.jqwik.engine.properties.arbitraries.combinations.CombineArbitrary.generateShrinkables(CombineArbitrary.java:108)
at net.jqwik.engine.properties.arbitraries.combinations.CombineArbitrary.lambda$combineGenerator$1(CombineArbitrary.java:85)
In CI the SOE seems to occur only on Java 18. Bad. Tried to circumvent it temporarily by fixing seed of test.
In any case, stacktrace without streams is way easier to read
In any case, stacktrace without streams is way easier to read
The code is so much more involved, though, that I'd like to leave it unchanged until tackling the underlying problem.
I agree shortening the stacktrace does not really solve the root cause.