jqwik icon indicating copy to clipboard operation
jqwik copied to clipboard

severalStepsToList_withReversedOrderOfSuppliers sometimes runs into StackOverflowError

Open vlsi opened this issue 3 years ago • 4 comments

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

  1. Refrain from Stream API in net.jqwik.api.ShrinkingDistance#combine and net.jqwik.api.ShrinkingDistance#forCollection so the stacktrace is shorter and easier to understand.

  2. 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)

vlsi avatar Dec 14 '22 09:12 vlsi

In CI the SOE seems to occur only on Java 18. Bad. Tried to circumvent it temporarily by fixing seed of test.

jlink avatar Dec 17 '22 16:12 jlink

In any case, stacktrace without streams is way easier to read

vlsi avatar Dec 17 '22 19:12 vlsi

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.

jlink avatar Dec 18 '22 10:12 jlink

I agree shortening the stacktrace does not really solve the root cause.

vlsi avatar Dec 18 '22 16:12 vlsi