Testing Problem
The issue has initially been described here: #134 (comment)
State-depending transformation might use the state for, well, figuring out the available transformations.
However, after the transformation is applied, the set of "allowable" transformations might change, so jqwik should use only the valid state objects when deriving transformations.
Here's a test case that shows invalid result produced by chain.transformations().
I believe, the root cause here is that net.jqwik.engine.properties.state.ShrinkableChainIteration#transformer re-instantiates transformation shrinkable, and it uses the same state object for instantiating transformers and taking their names.
The exact seed does not matter much, however, the failure scenarios are different depending on the seed.
seed=42
// As you see the actual ".transformations()" produces a weird "add 10 to []" as if adding 7 was ignored.
[chain.transformations(), final state is []]
expected: ["add 7 to []", "add 10 to [7]", "clear [7, 10]", "clear []"]
but was: ["add 7 to []", "add 10 to []", "clear [7, 10]", "clear []"]
seed=43
// Here "adding elements after clear" is printed as "noop"
expected: ["clear []", "add 10 to []", "add 7 to [10]", "add 4 to [7, 10]"]
but was: ["clear []", "noop", "noop", "noop"]
@Property(seed = "43")
void chainActionsAreProperlyDescribedEvenAfterChainExecution(@ForAll Random random) {
List<String> actualOps = new ArrayList<>();
ActionChainArbitrary<Set<Integer>> chains =
ActionChain.<Set<Integer>>startWith(HashSet::new)
.addAction(
1,
(Action.Dependent<Set<Integer>>)
state ->
Arbitraries.just(
Transformer.<Set<Integer>>mutate("clear " + state, set -> {
actualOps.add("clear " + set);
set.clear();
})
)
)
.addAction(
2,
(Action.Dependent<Set<Integer>>)
state ->
Arbitraries.integers()
.between(1, 10)
.map(i -> {
if (state.contains(i)) {
return Transformer.noop();
} else {
return Transformer.mutate("add " + i + " to " + state, set -> {
actualOps.add("add " + i + " to " + set);
set.add(i);
});
}
}
)
)
.withMaxTransformations(4);
ActionChain<Set<Integer>> chain = TestingSupport.generateFirst(chains, random);
Set<Integer> finalState = chain.run();
assertThat(chain.transformations())
.describedAs("chain.transformations(), final state is %s", finalState)
.isEqualTo(actualOps);
}
Testing Problem
The issue has initially been described here: #134 (comment)
State-depending transformation might use the state for, well, figuring out the available transformations.
However, after the transformation is applied, the set of "allowable" transformations might change, so jqwik should use only the valid state objects when deriving transformations.
Here's a test case that shows invalid result produced by
chain.transformations().I believe, the root cause here is that
net.jqwik.engine.properties.state.ShrinkableChainIteration#transformerre-instantiates transformation shrinkable, and it uses the same state object for instantiating transformers and taking their names.The exact seed does not matter much, however, the failure scenarios are different depending on the seed.