package net.sourceforge.cobertura.check;
import net.sourceforge.cobertura.coveragedata.ClassData;
import net.sourceforge.cobertura.coveragedata.CoverageDataFileHandler;
import net.sourceforge.cobertura.coveragedata.ProjectData;
import net.sourceforge.cobertura.dsl.Arguments;
import net.sourceforge.cobertura.reporting.CoverageThresholdsReport;
import net.sourceforge.cobertura.reporting.Report;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import static net.sourceforge.cobertura.check.CoverageResultEntry.CoverageLevel.*;
import static net.sourceforge.cobertura.check.CoverageResultEntry.CoverageType.BRANCH;
import static net.sourceforge.cobertura.check.CoverageResultEntry.CoverageType.LINE;
public class CheckCoverageTask {
private static final Logger logger = LoggerFactory
.getLogger(CheckCoverageMain.class);
private final Perl5Matcher pm = new Perl5Matcher();
private final Perl5Compiler pc = new Perl5Compiler();
private CoverageRate minimumCoverageRate;
private Map<Pattern, CoverageRate> minimumCoverageRates = new HashMap<Pattern, CoverageRate>();
private Map<String, PackageCoverage> packageCoverageMap = new HashMap<String, PackageCoverage>();
private CoverageRate findMinimumCoverageRate(String classname) {
for (Map.Entry<Pattern, CoverageRate> patternCoverageRateEntry : this.minimumCoverageRates
.entrySet()) {
Map.Entry entry = (Map.Entry) patternCoverageRateEntry;
if (pm.matches(classname, (Pattern) entry.getKey())) {
return (CoverageRate) entry.getValue();
}
}
return this.minimumCoverageRate;
}
public Report checkCoverage(Arguments arguments, ProjectData projectData) {
File dataFile = CoverageDataFileHandler.getDefaultDataFile();
double branchCoverageRate;
double lineCoverageRate;
double packageBranchCoverageRate;
double packageLineCoverageRate;
double totalBranchCoverageRate;
double totalLineCoverageRate;
branchCoverageRate = arguments.getClassBranchThreshold();
dataFile = arguments.getDataFile();
lineCoverageRate = arguments.getClassLineThreshold();
for (CoverageThreshold threshold : arguments
.getMinimumCoverageThresholds()) {
try {
this.minimumCoverageRates.put(pc.compile(threshold.getRegex()),
new CoverageRate(threshold.getMinBranchPercentage(),
threshold.getMinLinePercentage()));
} catch (MalformedPatternException e) {
logger.error(String.format("Got malformed regex expression %s",
threshold.getRegex()), e);
}
}
packageBranchCoverageRate = arguments.getPackageBranchThreshold();
packageLineCoverageRate = arguments.getPackageLineThreshold();
totalBranchCoverageRate = arguments.getTotalBranchThreshold();
totalLineCoverageRate = arguments.getTotalLineThreshold();
if ((branchCoverageRate == -1.0) && (lineCoverageRate == -1.0)
&& (packageLineCoverageRate == -1.0)
&& (packageBranchCoverageRate == -1.0)
&& (totalLineCoverageRate == -1.0)
&& (totalBranchCoverageRate == -1.0)
&& (this.minimumCoverageRates.size() == 0)) {
branchCoverageRate = 0.5;
lineCoverageRate = 0.5;
packageBranchCoverageRate = 0.5;
packageLineCoverageRate = 0.5;
totalBranchCoverageRate = 0.5;
totalLineCoverageRate = 0.5;
}
else {
if (branchCoverageRate == -1.0)
branchCoverageRate = 0.0;
if (lineCoverageRate == -1.0)
lineCoverageRate = 0.0;
if (packageLineCoverageRate == -1.0)
packageLineCoverageRate = 0.0;
if (packageBranchCoverageRate == -1.0)
packageBranchCoverageRate = 0.0;
if (totalLineCoverageRate == -1.0)
totalLineCoverageRate = 0.0;
if (totalBranchCoverageRate == -1.0)
totalBranchCoverageRate = 0.0;
}
this.minimumCoverageRate = new CoverageRate(lineCoverageRate,
branchCoverageRate);
double totalLines = 0;
double totalLinesCovered = 0;
double totalBranches = 0;
double totalBranchesCovered = 0;
Iterator iter = projectData.getClasses().iterator();
List<CoverageResultEntry> coverageResultEntries = new ArrayList<CoverageResultEntry>();
while (iter.hasNext()) {
ClassData classData = (ClassData) iter.next();
CoverageRate coverageRate = findMinimumCoverageRate(classData
.getName());
if (totalBranchCoverageRate > 0.0) {
totalBranches += classData.getNumberOfValidBranches();
totalBranchesCovered += classData.getNumberOfCoveredBranches();
}
if (totalLineCoverageRate > 0.0) {
totalLines += classData.getNumberOfValidLines();
totalLinesCovered += classData.getNumberOfCoveredLines();
}
PackageCoverage packageCoverage = getPackageCoverage(classData
.getPackageName());
if (packageBranchCoverageRate > 0.0) {
packageCoverage.addBranchCount(classData
.getNumberOfValidBranches());
packageCoverage.addBranchCoverage(classData
.getNumberOfCoveredBranches());
}
if (packageLineCoverageRate > 0.0) {
packageCoverage.addLineCount(classData.getNumberOfValidLines());
packageCoverage.addLineCoverage(classData
.getNumberOfCoveredLines());
}
logger.debug("Class " + classData.getName()
+ ", line coverage rate: "
+ percentage(classData.getLineCoverageRate())
+ "%, branch coverage rate: "
+ percentage(classData.getBranchCoverageRate()) + "%");
coverageResultEntries.add(new CoverageResultEntry(CLASS, BRANCH,
classData.getName(), classData.getBranchCoverageRate(),
coverageRate.getBranchCoverageRate()));
coverageResultEntries.add(new CoverageResultEntry(CLASS, LINE,
classData.getName(), classData.getLineCoverageRate(),
coverageRate.getLineCoverageRate()));
}
coverageResultEntries.addAll(checkPackageCoverageLevels(
packageBranchCoverageRate, packageLineCoverageRate));
coverageResultEntries.add(new CoverageResultEntry(PROJECT, BRANCH,
"project", totalBranchesCovered / totalBranches,
totalBranchCoverageRate));
coverageResultEntries.add(new CoverageResultEntry(PROJECT, LINE,
"project", totalLinesCovered / totalLines,
totalLineCoverageRate));
return new CoverageThresholdsReport(Collections
.unmodifiableList(coverageResultEntries));
}
private PackageCoverage getPackageCoverage(String packageName) {
PackageCoverage packageCoverage = packageCoverageMap.get(packageName);
if (packageCoverage == null) {
packageCoverage = new PackageCoverage();
packageCoverageMap.put(packageName, packageCoverage);
}
return packageCoverage;
}
private List<CoverageResultEntry> checkPackageCoverageLevels(
double packageBranchCoverageRate, double packageLineCoverageRate) {
for (Map.Entry<String, PackageCoverage> entry : packageCoverageMap
.entrySet()) {
String packageName = entry.getKey();
PackageCoverage packageCoverage = entry.getValue();
return checkPackageCoverage(packageBranchCoverageRate,
packageLineCoverageRate, packageName, packageCoverage);
}
return new ArrayList<CoverageResultEntry>();
}
private List<CoverageResultEntry> checkPackageCoverage(
double packageBranchCoverageRate, double packageLineCoverageRate,
String packageName, PackageCoverage packageCoverage) {
List<CoverageResultEntry> coverageResultEntries = new ArrayList<CoverageResultEntry>();
coverageResultEntries.add(new CoverageResultEntry(PACKAGE, BRANCH,
packageName, packageCoverage.getBranchCoverage()
/ packageCoverage.getBranchCount(),
packageBranchCoverageRate));
coverageResultEntries.add(new CoverageResultEntry(PACKAGE, LINE,
packageName, packageCoverage.getLineCoverage()
/ packageCoverage.getLineCount(),
packageLineCoverageRate));
return coverageResultEntries;
}
private String percentage(double coverateRate) {
BigDecimal decimal = new BigDecimal(coverateRate * 100);
return decimal.setScale(1, BigDecimal.ROUND_DOWN).toString();
}
}