net.jqwik.engine.properties.state.ShrinkableChainIteration Maven / Gradle / Ivy
package net.jqwik.engine.properties.state;
import java.util.*;
import java.util.function.*;
import net.jqwik.api.*;
import net.jqwik.api.state.*;
import org.jspecify.annotations.*;
class ShrinkableChainIteration {
final Shrinkable> shrinkable;
final boolean accessState;
final boolean changeState;
private final @Nullable Predicate precondition;
private final @Nullable Transformer cachedTransformer;
ShrinkableChainIteration(
@Nullable Predicate precondition,
boolean accessState,
Shrinkable> shrinkable
) {
// By default transformers are considered to change the state.
this(precondition, accessState, true, shrinkable);
}
private ShrinkableChainIteration(
@Nullable Predicate precondition,
boolean accessState,
boolean changeState,
Shrinkable> shrinkable
) {
this.precondition = precondition;
this.accessState = accessState;
this.changeState = changeState;
this.shrinkable = shrinkable;
cachedTransformer = cacheTransformerIfItAccessesState(accessState, shrinkable);
}
private Transformer cacheTransformerIfItAccessesState(boolean accessState, Shrinkable> shrinkable) {
// Transformer method might access state, so we need to cache the value here
// otherwise it might be evaluated with wrong state (e.g. after chain executes)
return accessState ? shrinkable.value() : null;
}
@Override
public String toString() {
return String.format(
"Iteration[accessState=%s, changeState=%s, transformation=%s]",
accessState, changeState, transformer().transformation()
);
}
boolean isEndOfChain() {
return transformer().equals(Transformer.END_OF_CHAIN);
}
Optional> precondition() {
return Optional.ofNullable(precondition);
}
ShrinkableChainIteration withShrinkable(Shrinkable> shrinkable) {
return new ShrinkableChainIteration<>(precondition, accessState, changeState, shrinkable);
}
ShrinkableChainIteration withStateChange(boolean stateHasBeenChanged) {
if (this.changeState == stateHasBeenChanged) {
return this;
}
return new ShrinkableChainIteration<>(precondition, accessState, stateHasBeenChanged, shrinkable);
}
String transformation() {
return transformer().transformation();
}
Transformer transformer() {
return cachedTransformer == null ? shrinkable.value() : cachedTransformer;
}
}