All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.jqwik.engine.properties.shrinking.AbstractSampleShrinker Maven / Gradle / Ivy
package net.jqwik.engine.properties.shrinking;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import net.jqwik.api.*;
import net.jqwik.api.Tuple.*;
import net.jqwik.api.lifecycle.*;
import net.jqwik.engine.properties.*;
abstract class AbstractSampleShrinker {
private static ShrinkingDistance calculateDistance(List> shrinkables) {
return ShrinkingDistance.forCollection(shrinkables);
}
private final Map, TryExecutionResult> falsificationCache;
public AbstractSampleShrinker(Map, TryExecutionResult> falsificationCache) {
this.falsificationCache = falsificationCache;
}
public abstract FalsifiedSample shrink(
Falsifier> falsifier,
FalsifiedSample sample,
Consumer shrinkSampleConsumer,
Consumer shrinkAttemptConsumer
);
protected FalsifiedSample shrink(
Falsifier> falsifier,
FalsifiedSample sample,
Consumer sampleShrunkConsumer,
Consumer shrinkAttemptConsumer,
Function>, Stream>>> supplyShrinkCandidates
) {
List> currentShrinkBase = sample.shrinkables();
Optional bestResult = Optional.empty();
FilteredResults filteredResults = new FilteredResults();
while (true) {
ShrinkingDistance currentDistance = calculateDistance(currentShrinkBase);
FalsifiedSample currentBest = bestResult.orElse(null);
Optional, List>, TryExecutionResult>> newShrinkingResult =
supplyShrinkCandidates.apply(currentShrinkBase)
.peek(ignore -> shrinkAttemptConsumer.accept(currentBest))
.filter(shrinkables -> calculateDistance(shrinkables).compareTo(currentDistance) <= 0)
.map(shrinkables -> {
List params = createValues(shrinkables).collect(Collectors.toList());
TryExecutionResult result = falsify(falsifier, params);
return Tuple.of(params, shrinkables, result);
})
.peek(t -> {
// Remember best 10 invalid results in case no falsified shrink is found
if (t.get3().isInvalid() && calculateDistance(t.get2()).compareTo(currentDistance) < 0) {
filteredResults.push(t);
}
})
.filter(t -> t.get3().isFalsified())
.findAny();
if (newShrinkingResult.isPresent()) {
Tuple3, List>, TryExecutionResult> falsifiedTry = newShrinkingResult.get();
TryExecutionResult tryExecutionResult = falsifiedTry.get3();
FalsifiedSample falsifiedSample = new FalsifiedSampleImpl(
falsifiedTry.get1(),
falsifiedTry.get2(),
tryExecutionResult.throwable(),
tryExecutionResult.footnotes()
);
sampleShrunkConsumer.accept(falsifiedSample);
bestResult = Optional.of(falsifiedSample);
currentShrinkBase = falsifiedTry.get2();
filteredResults.clear();
} else if (!filteredResults.isEmpty()) {
Tuple3, List>, TryExecutionResult> aFilteredResult = filteredResults.pop();
currentShrinkBase = aFilteredResult.get2();
} else {
break;
}
}
return bestResult.orElse(sample);
}
private TryExecutionResult falsify(Falsifier> falsifier, List params) {
// I wonder in which cases this is really an optimization
return falsificationCache.computeIfAbsent(params, p -> falsifier.execute(params));
}
private Stream createValues(List> shrinkables) {
return shrinkables.stream().map(Shrinkable::value);
}
private static class FilteredResults {
public static final int MAX_SIZE = 100;
Comparator super Tuple3, List>, TryExecutionResult>> resultComparator =
Comparator.comparing(left -> calculateDistance(left.get2()));
PriorityQueue, List>, TryExecutionResult>> prioritizedResults = new PriorityQueue<>(resultComparator);
Set, List>, TryExecutionResult>> removedResults = new LinkedHashSet<>();
void push(Tuple3, List>, TryExecutionResult> result) {
if (removedResults.contains(result)) {
return;
}
prioritizedResults.add(result);
if (size() > MAX_SIZE) {
prioritizedResults.poll();
}
}
int size() {
return prioritizedResults.size();
}
boolean isEmpty() {
return prioritizedResults.isEmpty();
}
Tuple3, List>, TryExecutionResult> pop() {
Tuple3, List>, TryExecutionResult> result = prioritizedResults.peek();
prioritizedResults.remove(result);
removedResults.add(result);
return result;
}
public void clear() {
prioritizedResults.clear();
removedResults.clear();
}
}
}