diff --git a/slowCheck/src/slowCheck/GeneratorException.java b/slowCheck/src/slowCheck/GeneratorException.java new file mode 100644 index 000000000000..6cc9ea143a50 --- /dev/null +++ b/slowCheck/src/slowCheck/GeneratorException.java @@ -0,0 +1,11 @@ +package slowCheck; + +/** + * @author peter + */ +public class GeneratorException extends RuntimeException { + + GeneratorException(long seed, Throwable cause) { + super("Exception while generating data, seed=" + seed, cause); + } +} diff --git a/slowCheck/src/slowCheck/PropertyChecker.java b/slowCheck/src/slowCheck/PropertyChecker.java index 6859c043ec8e..d6ec3b6e7cc3 100644 --- a/slowCheck/src/slowCheck/PropertyChecker.java +++ b/slowCheck/src/slowCheck/PropertyChecker.java @@ -79,7 +79,13 @@ public class PropertyChecker { private CounterExampleImpl findCounterExample(int sizeHint) { for (int i = 0; i < 100; i++) { StructureNode node = new StructureNode(); - T value = generator.generateUnstructured(new GenerativeDataStructure(random, node, sizeHint)); + T value; + try { + value = generator.generateUnstructured(new GenerativeDataStructure(random, node, sizeHint)); + } + catch (Throwable e) { + throw new GeneratorException(seed, e); + } if (!generatedHashes.add(node.hashCode())) continue; return CounterExampleImpl.checkProperty(property, value, node); @@ -92,12 +98,18 @@ public class PropertyChecker { private CounterExampleImpl minimized; private int totalSteps; private int sizeHint; + private Throwable stoppingReason; PropertyFailureImpl(@NotNull CounterExampleImpl initial, int sizeHint) { this.initial = initial; this.minimized = initial; this.sizeHint = sizeHint; - shrink(); + try { + shrink(); + } + catch (Throwable e) { + stoppingReason = e; + } } @NotNull @@ -112,6 +124,12 @@ public class PropertyChecker { return minimized; } + @Nullable + @Override + public Throwable getStoppingReason() { + return stoppingReason; + } + @Override public int getTotalMinimizationStepCount() { return totalSteps; diff --git a/slowCheck/src/slowCheck/PropertyFailure.java b/slowCheck/src/slowCheck/PropertyFailure.java index 3c2fbb7b5888..5999ebc19c37 100644 --- a/slowCheck/src/slowCheck/PropertyFailure.java +++ b/slowCheck/src/slowCheck/PropertyFailure.java @@ -12,6 +12,9 @@ public interface PropertyFailure { @NotNull CounterExample getMinimalCounterexample(); + + @Nullable + Throwable getStoppingReason(); int getTotalMinimizationStepCount(); diff --git a/slowCheck/test/slowCheck/ExceptionTest.java b/slowCheck/test/slowCheck/ExceptionTest.java index 6c876fc6cc84..3494cc88106d 100644 --- a/slowCheck/test/slowCheck/ExceptionTest.java +++ b/slowCheck/test/slowCheck/ExceptionTest.java @@ -1,6 +1,8 @@ package slowCheck; +import static slowCheck.Generator.from; import static slowCheck.Generator.integers; +import static slowCheck.Generator.listsOf; /** * @author peter @@ -48,4 +50,38 @@ public class ExceptionTest extends PropertyCheckerTestCase { } } + public void testExceptionWhileGeneratingValue() { + try { + PropertyChecker.forAll(ourTestSettings, from(data -> { + throw new AssertionError("fail"); + }), i -> true); + fail(); + } + catch (GeneratorException ignore) { + } + } + + public void testExceptionWhileShrinkingValue() { + try { + PropertyChecker.forAll(ourTestSettings, listsOf(integers()).suchThat(l -> { + if (l.size() == 1 && l.get(0) == 0) throw new RuntimeException("my exception"); + return true; + }), l -> l.stream().allMatch(i -> i > 0)); + fail(); + } + catch (PropertyFalsified e) { + assertEquals("my exception", e.getFailure().getStoppingReason().getMessage()); + } + } + + public void testUnsatisfiableSuchThat() { + try { + PropertyChecker.forAll(integers(-1, 1).suchThat(i -> i > 2), i -> i == 0); + fail(); + } + catch (GeneratorException e) { + assertTrue(e.getCause() instanceof CannotSatisfyCondition); + } + } + } diff --git a/slowCheck/test/slowCheck/GeneratorTest.java b/slowCheck/test/slowCheck/GeneratorTest.java index b8be3046acde..ad83d8c2a6a3 100644 --- a/slowCheck/test/slowCheck/GeneratorTest.java +++ b/slowCheck/test/slowCheck/GeneratorTest.java @@ -75,15 +75,6 @@ public class GeneratorTest extends PropertyCheckerTestCase { PropertyChecker.forAll(integers().suchThat(i -> i < 0), i -> i < 0); } - public void testUnsatisfiableSuchThat() { - try { - PropertyChecker.forAll(integers(-1, 1).suchThat(i -> i > 2), i -> i == 0); - fail(); - } - catch (CannotSatisfyCondition ignored) { - } - } - public void testStringOfStringChecksAllChars() { checkFalsified(stringsOf("abc "), s -> !s.contains(" "),