net.jqwik.engine.properties.stateful.ShrinkableActionSequence Maven / Gradle / Ivy
package net.jqwik.engine.properties.stateful;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import net.jqwik.api.*;
import net.jqwik.api.stateful.*;
import net.jqwik.engine.properties.shrinking.*;
class ShrinkableActionSequence implements Shrinkable> {
private final ComprehensiveListShrinkingCandidates listShrinkingCandidates = new ComprehensiveListShrinkingCandidates();
private final ActionSequence value;
private final ActionGenerator actionGenerator;
private final int minSize;
private final ShrinkingDistance distance;
ShrinkableActionSequence(ActionGenerator actionGenerator, int minSize, int maxSize, ShrinkingDistance distance) {
this.actionGenerator = actionGenerator;
this.minSize = minSize;
this.distance = distance;
this.value = new SequentialActionSequence<>(actionGenerator, maxSize);
}
@Override
public ActionSequence value() {
return value;
}
@Override
public ShrinkingSequence> shrink(Falsifier> falsifier) {
Falsifier> minRespectingFalsifier =
falsifier.withPostFilter(actionSequence -> actionSequence.runActions().size() >= minSize);
return shrinkSequenceOfActions(minRespectingFalsifier)
.andThen(shrinkableList -> { //
ShrinkableActionSequence shrinkableSequence = (ShrinkableActionSequence) shrinkableList;
Falsifier>> listFalsifier = list -> minRespectingFalsifier.test(toRunnableActionSequence(list));
return shrinkIndividualActions(shrinkableSequence, listFalsifier)
// Shrink list of actions again since element shrinking
// might have made some actions unnecessary
.andThen(shrinkListOfActions(listFalsifier))
.mapValue(this::toDisplayOnlyActionSequence);
});
}
private Function>>, ShrinkingSequence>>> shrinkListOfActions(Falsifier>> listFalsifier) {
return shrinkableListOfActions ->
new DeepSearchShrinkingSequence<>(shrinkableListOfActions, this::shrinkActionListCandidates, listFalsifier);
}
private Set>>> shrinkActionListCandidates(Shrinkable>> shrinkableList) {
//noinspection unchecked
return listShrinkingCandidates
.candidatesFor(shrinkableList.value())
.stream()
.map(elements -> elements.stream().map(Shrinkable::unshrinkable).collect(Collectors.toList()))
.map((List>> shrinkableElements) -> (Shrinkable>>) new ShrinkableList(shrinkableElements, 1)) //
.collect(Collectors.toSet());
}
private ElementsShrinkingSequence> shrinkIndividualActions(
ShrinkableActionSequence shrinkableActionSequence,
Falsifier>> listFalsifier
) {
return new ElementsShrinkingSequence<>(
shrinkableActionSequence.actionGenerator.generated(),
listFalsifier, ShrinkingDistance::forCollection
);
}
private ActionSequence toDisplayOnlyActionSequence(List> listOfActions) {
return new FixedActionsFailedActionSequence<>(listOfActions);
}
private ActionSequence toRunnableActionSequence(List> listOfActions) {
ActionGenerator newActionGenerator = new ListActionGenerator<>(listOfActions);
return new SequentialActionSequence(newActionGenerator, listOfActions.size());
}
private ShrinkableActionSequence toShrinkableActionSequence(List>> list) {
ActionGenerator newGenerator = new ShrinkablesActionGenerator<>(list);
ShrinkingDistance newDistance = ShrinkingDistance.forCollection(list);
return new ShrinkableActionSequence<>(newGenerator, 1, list.size(), newDistance);
}
private DeepSearchShrinkingSequence> shrinkSequenceOfActions(Falsifier> falsifier) {
return new DeepSearchShrinkingSequence<>(this, this::shrinkSequenceCandidates, falsifier);
}
private Set>> shrinkSequenceCandidates(Shrinkable> shrinkable) {
ShrinkableActionSequence shrinkableSequence = (ShrinkableActionSequence) shrinkable;
return listShrinkingCandidates
.candidatesFor(shrinkableSequence.actionGenerator.generated())
.stream()
.map(this::toShrinkableActionSequence)
.collect(Collectors.toSet());
}
@Override
public ShrinkingDistance distance() {
if (value.runState() == ActionSequence.RunState.NOT_RUN) {
return distance;
}
return ShrinkingDistance.forCollection(actionGenerator.generated());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy