mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
jetCheck: re-run top-level generator when deep suchThat condition fails
This commit is contained in:
@@ -26,9 +26,12 @@ public interface DataStructure {
|
||||
return drawInt(IntDistribution.uniform(0, getSizeHint()));
|
||||
}
|
||||
|
||||
/** Runs the given generator on this data structure and returns the result */
|
||||
<T> T generate(@NotNull Generator<T> generator);
|
||||
|
||||
/** @see Generator#noShrink() */
|
||||
<T> T generateNonShrinkable(@NotNull Generator<T> generator);
|
||||
|
||||
/** @see Generator#suchThat */
|
||||
<T> T generateConditional(@NotNull Generator<T> generator, @NotNull Predicate<T> condition);
|
||||
}
|
||||
|
||||
@@ -74,10 +74,18 @@ public class Generator<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips all generated data that doesn't satisfy the given condition. Useful to avoid infrequent corner cases.
|
||||
* If the condition fails too often, data generation is stopped prematurely due to inability to produce the data.<p/>
|
||||
* Attempts to generate the value several times, until one comes out that satisfies the given condition. That value is returned as generator result.
|
||||
* Results of all previous attempts are discarded. During shrinking, the underlying data structures from those attempts
|
||||
* won't be used for re-running generation, so be careful that those attempts don't leave any traces of themselves
|
||||
* (e.g. side effects, even ones internal to an outer generator).<p/>
|
||||
*
|
||||
* To eliminate large portions of search space, consider changing the generator instead of using {@code suchThat}.
|
||||
* If the condition still fails after a large number of attempts, data generation is stopped prematurely and {@link CannotSatisfyCondition} exception is thrown.<p/>
|
||||
*
|
||||
* This method is useful to avoid infrequent corner cases (e.g. {@code integers().suchThat(i -> i != 0)}).
|
||||
* To eliminate large portions of search space, this strategy might prove ineffective
|
||||
* and result in generator failure due to inability to come up with satisfying examples
|
||||
* (e.g. {@code integers().suchThat(i -> i > 0 && i <= 10)}
|
||||
* where the condition would be {@code true} in just 10 of about 4 billion times). In such cases, please consider changing the generator instead of using {@code suchThat}.
|
||||
*/
|
||||
public Generator<T> suchThat(@NotNull Predicate<T> condition) {
|
||||
return from(data -> data.generateConditional(this, condition));
|
||||
|
||||
@@ -45,6 +45,9 @@ class Iteration<T> {
|
||||
try {
|
||||
value = session.generator.getGeneratorFunction().apply(new GenerativeDataStructure(random, node, sizeHint));
|
||||
}
|
||||
catch (CannotSatisfyCondition e) {
|
||||
continue;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
throw new GeneratorException(this, e);
|
||||
}
|
||||
@@ -52,7 +55,7 @@ class Iteration<T> {
|
||||
|
||||
return CounterExampleImpl.checkProperty(session.property, value, node);
|
||||
}
|
||||
throw new CannotSatisfyCondition(DATA_IS_DIFFERENT);
|
||||
throw new GeneratorException(this, new CannotSatisfyCondition(DATA_IS_DIFFERENT));
|
||||
}
|
||||
|
||||
String printToReproduce() {
|
||||
|
||||
@@ -77,6 +77,10 @@ public class GeneratorTest extends PropertyCheckerTestCase {
|
||||
PropertyChecker.forAll(integers().suchThat(i -> i < 0)).shouldHold(i -> i < 0);
|
||||
}
|
||||
|
||||
public void testNestedSometimesVeryRareSuchThat() {
|
||||
forAllStable(frequency(50, constant(0), 1, integers(1, 1000)).suchThat(i -> i > 0)).shouldHold(i -> i > 0);
|
||||
}
|
||||
|
||||
public void testStringOfStringChecksAllChars() {
|
||||
checkFalsified(stringsOf("abc "),
|
||||
s -> !s.contains(" "),
|
||||
|
||||
Reference in New Issue
Block a user