mockit.coverage.CoverageCheck Maven / Gradle / Ivy
/*
* Copyright (c) 2006 JMockit developers
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.coverage;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import javax.annotation.*;
import mockit.coverage.data.*;
final class CoverageCheck
{
private static final class Threshold {
private static final Pattern PARAMETER_SEPARATORS = Pattern.compile(":|=");
@Nullable private final String sourceFilePrefix;
@Nonnull private final String scopeDescription;
@Nonnull private final int[] minPercentages;
Threshold(@Nonnull String configurationParameter) {
String[] sourceFilePrefixAndMinPercentages = PARAMETER_SEPARATORS.split(configurationParameter);
String csvPercentages;
if (sourceFilePrefixAndMinPercentages.length == 1) {
sourceFilePrefix = null;
scopeDescription = "";
csvPercentages = sourceFilePrefixAndMinPercentages[0];
}
else {
String scope = sourceFilePrefixAndMinPercentages[0].trim();
if (isPerFile(scope)) {
sourceFilePrefix = scope;
scopeDescription = " for some source files";
}
else {
sourceFilePrefix = scope.replace('.', '/');
scopeDescription = " for " + scope;
}
csvPercentages = sourceFilePrefixAndMinPercentages[1];
}
minPercentages = new int[Metrics.values().length];
parseMinimumPercentages(csvPercentages);
}
private static boolean isPerFile(@Nullable String scope) { return "perFile".equalsIgnoreCase(scope); }
private void parseMinimumPercentages(@Nonnull String csvPercentages) {
String[] textualPercentages = csvPercentages.split(",");
int n = Math.min(textualPercentages.length, minPercentages.length);
for (int i = 0; i < n; i++) {
String textualValue = textualPercentages[i].trim();
try { minPercentages[i] = Integer.parseInt(textualValue); } catch (NumberFormatException ignore) {}
}
}
boolean verifyMinimum(@Nonnull Metrics metric) {
CoverageData coverageData = CoverageData.instance();
int percentage;
if (isPerFile(sourceFilePrefix)) {
percentage = coverageData.getSmallestPerFilePercentage(metric);
}
else {
percentage = coverageData.getPercentage(metric, sourceFilePrefix);
}
return percentage < 0 || verifyMinimum(metric, percentage);
}
private boolean verifyMinimum(@Nonnull Metrics metric, int percentage) {
int minPercentage = minPercentages[metric.ordinal()];
if (percentage < minPercentage) {
System.out.println(
"JMockit: " + metric + " coverage too low" + scopeDescription + ": " + percentage + "% < " + minPercentage + '%');
return false;
}
return true;
}
}
@Nullable private final List thresholds;
private boolean allThresholdsSatisfied;
CoverageCheck() {
String configuration = Configuration.getProperty("check", "");
if (configuration.isEmpty()) {
thresholds = null;
return;
}
String[] configurationParameters = configuration.split(";");
int n = configurationParameters.length;
thresholds = new ArrayList<>(n);
for (String configurationParameter : configurationParameters) {
thresholds.add(new Threshold(configurationParameter));
}
}
void verifyThresholds() {
if (thresholds == null) return;
allThresholdsSatisfied = true;
for (final Threshold threshold : thresholds) {
Metrics.performAction(new Metrics.Action() {
@Override
public void perform(@Nonnull Metrics metric) {
allThresholdsSatisfied &= threshold.verifyMinimum(metric);
}
});
}
createOrDeleteIndicatorFile();
if (!allThresholdsSatisfied) {
throw new AssertionError("JMockit: minimum coverage percentages not reached; see previous messages.");
}
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private void createOrDeleteIndicatorFile() {
String parentDir = Configuration.getOrChooseOutputDirectory("");
File indicatorFile = new File(parentDir, "coverage.check.failed");
if (indicatorFile.exists()) {
if (allThresholdsSatisfied) {
indicatorFile.delete();
}
else {
indicatorFile.setLastModified(System.currentTimeMillis());
}
}
else if (!allThresholdsSatisfied) {
try { indicatorFile.createNewFile(); } catch (IOException e) { throw new RuntimeException(e); }
}
}
}