net.jqwik.engine.properties.state.DefaultChainArbitrary 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 net.jqwik.engine.properties.arbitraries.*;
import net.jqwik.engine.support.*;
import org.jspecify.annotations.*;
public class DefaultChainArbitrary extends TypedCloneable implements ChainArbitrary {
private int maxTransformations = Integer.MIN_VALUE;
private Supplier extends ChangeDetector super T>> changeDetectorSupplier = ChangeDetector::alwaysTrue;
private List>> weightedTransformations = new ArrayList<>();
private final Supplier extends T> initialSupplier;
public DefaultChainArbitrary(Supplier extends T> initialSupplier) {
this.initialSupplier = initialSupplier;
}
@Override
public RandomGenerator> generator(int genSize) {
final int effectiveMaxTransformations =
this.maxTransformations != Integer.MIN_VALUE ? this.maxTransformations : (int) Math.max(Math.round(Math.sqrt(genSize)), 10);
Function> transformationGenerator = new ChooseRandomlyByFrequency<>(weightedTransformations);
return random -> new ShrinkableChain<>(
random.nextLong(),
initialSupplier,
transformationGenerator,
changeDetectorSupplier,
effectiveMaxTransformations,
genSize
);
}
@Override
public ChainArbitrary withTransformation(int weight, Transformation transformation) {
if (weight <= 0) {
throw new IllegalArgumentException("Weight must be at least 1");
}
DefaultChainArbitrary clone = typedClone();
List>> newWeightedTransformations = new ArrayList<>(weightedTransformations);
newWeightedTransformations.add(Tuple.of(weight, transformation));
clone.weightedTransformations = newWeightedTransformations;
return clone;
}
@Override
public ChainArbitrary withMaxTransformations(int maxTransformations) {
DefaultChainArbitrary clone = typedClone();
clone.maxTransformations = maxTransformations;
return clone;
}
@Override
public ChainArbitrary improveShrinkingWith(Supplier extends ChangeDetector super T>> changeDetectorSupplier) {
DefaultChainArbitrary clone = typedClone();
clone.changeDetectorSupplier = changeDetectorSupplier;
return clone;
}
@Override
public EdgeCases> edgeCases(int maxEdgeCases) {
return EdgeCases.none();
}
@Override
public boolean isGeneratorMemoizable() {
// Not memoizable, because any non-memoizable arbitrary could be used in transformer providers.
return false;
}
}