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.hooks.statistics.StatisticsCollectorImpl Maven / Gradle / Ivy
package net.jqwik.engine.hooks.statistics;
import java.util.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;
import org.opentest4j.*;
import net.jqwik.api.*;
import net.jqwik.api.statistics.*;
import net.jqwik.api.statistics.StatisticsCoverage.*;
import net.jqwik.engine.facades.*;
public class StatisticsCollectorImpl implements StatisticsCollector {
public static final Object COLLECTORS_ID = Tuple.of(StatisticsCollectorImpl.class, "collectors");
private final Map, Integer> counts = new LinkedHashMap<>();
private final List> coverageCheckers = new ArrayList<>();
private final String label;
private List statisticsEntries = null;
public StatisticsCollectorImpl(String label) {
this.label = label;
}
@Override
public StatisticsCollector collect(Object... values) {
ensureAtLeastOneParameter(values);
List key = keyFrom(values);
ensureSameNumberOfValues(key);
updateCounts(key);
return this;
}
private void updateCounts(List key) {
int count = counts.computeIfAbsent(key, any -> 0);
counts.put(key, ++count);
statisticsEntries = null;
}
private void ensureAtLeastOneParameter(Object[] values) {
if (Arrays.equals(values, new Object[0])) {
String message = String.format("StatisticsCollector[%s] must be called with at least one value", label);
throw new IllegalArgumentException(message);
}
}
private void ensureSameNumberOfValues(List keyCandidate) {
if (counts.isEmpty()) {
return;
}
List anyKey = counts.keySet().iterator().next();
if (anyKey.size() != keyCandidate.size()) {
String message = String.format("StatisticsCollector[%s] must always be called with same number of values", label);
throw new IllegalArgumentException(message);
}
}
private List keyFrom(Object[] values) {
if (values != null) {
return Arrays.asList(values);
} else {
return Collections.singletonList(null);
}
}
// Currently only used for testing
public double percentage(Object... values) {
return statisticsEntry(values).percentage();
}
private StatisticsEntry statisticsEntry(Object[] values) {
List key = keyFrom(values);
return statisticsEntries()
.stream()
.filter(entry -> entry.values().equals(key))
.findFirst()
.orElse(StatisticsEntryImpl.nullFor(key));
}
private StatisticsEntry query(Predicate super List>> query, int countAll) {
return statisticsEntries()
.stream()
.filter(entry -> {
List values = entry.values();
return query.test(values);
})
.reduce(
StatisticsEntryImpl.nullWithName(""),
(statisticsEntry, other) -> statisticsEntry.plus(other, countAll)
);
}
private StatisticsEntryImpl matchPattern(String regex, int countAll) {
String name = String.format("", regex);
return statisticsEntries()
.stream()
.filter(entry -> {
if (entry.values().size() != 1) {
return false;
}
Object value = entry.values().get(0);
if (!(value instanceof CharSequence)) {
return false;
}
CharSequence toMatch = (CharSequence) value;
return Pattern.matches(regex, toMatch);
})
.reduce(
StatisticsEntryImpl.nullWithName(name),
(statisticsEntry, other) -> statisticsEntry.plus(other, countAll)
);
}
public int countAllCollects() {
return counts.values().stream().mapToInt(aCount -> aCount).sum();
}
// Currently only used for testing
public int count(Object... values) {
return statisticsEntry(values).count();
}
@Override
public void coverage(Consumer checker) {
// The same checker shall only be used once
if (!coverageCheckers.contains(checker)) {
coverageCheckers.add(checker);
}
}
public void checkCoverage() {
for (Consumer checker : coverageCheckers) {
StatisticsCoverage coverage = new StatisticsCoverageImpl();
checker.accept(coverage);
}
}
public Map, Integer> getCounts() {
return counts;
}
public List statisticsEntries() {
if (statisticsEntries != null) {
return statisticsEntries;
}
statisticsEntries = calculateStatistics();
return statisticsEntries;
}
private List calculateStatistics() {
int sum = countAllCollects();
return counts.entrySet()
.stream()
.sorted(this::compareStatisticsEntries)
.filter(entry -> !entry.getKey().equals(Collections.emptyList()))
.map(entry -> {
double percentage = entry.getValue() * 100.0 / sum;
return new StatisticsEntryImpl(
entry.getKey(),
displayKey(entry.getKey()),
entry.getValue(), percentage
);
})
.collect(Collectors.toList());
}
private int compareStatisticsEntries(Map.Entry, Integer> e1, Map.Entry, Integer> e2) {
List k1 = e1.getKey();
List k2 = e2.getKey();
if (k1.size() != k2.size()) {
return Integer.compare(k1.size(), k2.size());
}
return e2.getValue().compareTo(e1.getValue());
}
private String displayKey(List key) {
return key.stream().map(Objects::toString).collect(Collectors.joining(" "));
}
String label() {
return label;
}
private static String statisticsLabel(String label) {
return label.equals(StatisticsFacadeImpl.DEFAULT_LABEL) ? "" : String.format(" for label \"%s\"", label);
}
private class StatisticsCoverageImpl implements StatisticsCoverage {
@Override
public CoverageChecker check(Object... values) {
StatisticsEntry entry = statisticsEntry(values);
return new CoverageCheckerImpl(label, entry, countAllCollects());
}
@SuppressWarnings("unchecked")
@Override
public CoverageChecker checkQuery(Predicate super List>> query) {
int countAll = countAllCollects();
StatisticsEntry entry = query(query, countAll);
return new CoverageCheckerImpl(label, entry, countAll);
}
@Override
public CoverageChecker checkPattern(String regex) {
int countAll = countAllCollects();
StatisticsEntry entry = matchPattern(regex, countAll);
return new CoverageCheckerImpl(label, entry, countAll);
}
}
private static class CoverageCheckerImpl implements CoverageChecker {
private final String label;
private final StatisticsEntry entry;
private final int countAll;
public CoverageCheckerImpl(String label, StatisticsEntry entry, int countAll) {
this.label = label;
this.entry = entry;
this.countAll = countAll;
}
@Override
public void count(Predicate super Integer> countChecker) {
if (!countChecker.test(entry.count())) {
String condition = String.format("Count of %s", entry.count());
failCondition(condition);
}
}
@Override
public void count(BiPredicate super Integer, ? super Integer> countChecker) {
if (!countChecker.test(entry.count(), countAll)) {
String condition = String.format("Count of (%s, %s)", entry.count(), countAll);
failCondition(condition);
}
}
@Override
public void count(Consumer super Integer> countChecker) {
count(c -> {
countChecker.accept(c);
return true;
});
}
@Override
public void count(BiConsumer super Integer, ? super Integer> countChecker) {
count((c, a) -> {
countChecker.accept(c, a);
return true;
});
}
@Override
public void percentage(Predicate super Double> percentageChecker) {
if (!percentageChecker.test(entry.percentage())) {
String condition = String.format("Percentage of %s", entry.percentage());
failCondition(condition);
}
}
@Override
public void percentage(Consumer super Double> percentageChecker) {
percentage(p -> {
percentageChecker.accept(p);
return true;
});
}
private void failCondition(String condition) {
String message = String.format(
"%s for %s does not fulfill condition%s",
condition,
entry.name(),
statisticsLabel(label)
);
fail(message);
}
private void fail(String message) {
throw new AssertionFailedError(message);
}
}
}