Skip to content

Instantly share code, notes, and snippets.

@timotm
Created October 17, 2022 11:05
Show Gist options
  • Save timotm/2f55d4ad9aa3ab04bfe5e760c990abe6 to your computer and use it in GitHub Desktop.
Save timotm/2f55d4ad9aa3ab04bfe5e760c990abe6 to your computer and use it in GitHub Desktop.
cobertura
/*
* Cobertura - http://cobertura.sourceforge.net/
*
* Copyright (C) 2003 jcoverage ltd.
* Copyright (C) 2005 Mark Doliner
* Copyright (C) 2005 Jeremy Thomerson
* Copyright (C) 2006 Jiri Mares
* Copyright (C) 2008 Julian Gamble
*
* Cobertura is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* Cobertura is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Cobertura; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
package net.sourceforge.cobertura.reporting.xml;
import net.sourceforge.cobertura.coveragedata.*;
import net.sourceforge.cobertura.reporting.ComplexityCalculator;
import net.sourceforge.cobertura.util.FileFinder;
import net.sourceforge.cobertura.util.Header;
import net.sourceforge.cobertura.util.IOUtil;
import net.sourceforge.cobertura.util.StringUtil;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class XMLReport {
private static final Logger logger = LoggerFactory
.getLogger(XMLReport.class);
protected final static String coverageDTD = "coverage-04.dtd";
private final PrintWriter pw;
private final FileFinder finder;
private final ComplexityCalculator complexity;
private int indent = 0;
public XMLReport(ProjectData projectData, File destinationDir,
FileFinder finder, ComplexityCalculator complexity)
throws IOException {
this.complexity = complexity;
this.finder = finder;
File file = new File(destinationDir, "coverage.xml");
pw = IOUtil.getPrintWriter(file);
try {
println("<?xml version=\"1.0\"?>");
println("<!DOCTYPE coverage SYSTEM \"http://cobertura.sourceforge.net/xml/"
+ coverageDTD + "\">");
println("");
double ccn = complexity.getCCNForProject(projectData);
int numLinesCovered = projectData.getNumberOfCoveredLines();
int numLinesValid = projectData.getNumberOfValidLines();
int numBranchesCovered = projectData.getNumberOfCoveredBranches();
int numBranchesValid = projectData.getNumberOfValidBranches();
// TODO: Set a schema?
//println("<coverage " + sourceDirectories.toString() + " xmlns=\"http://cobertura.sourceforge.net\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://cobertura.sourceforge.net/xml/coverage.xsd\">");
println("<coverage line-rate=\""
+ projectData.getLineCoverageRate() + "\" branch-rate=\""
+ projectData.getBranchCoverageRate()
+ "\" lines-covered=\"" + numLinesCovered
+ "\" lines-valid=\"" + numLinesValid
+ "\" branches-covered=\"" + numBranchesCovered
+ "\" branches-valid=\"" + numBranchesValid
+ "\" complexity=\"" + ccn
+ "\" version=\"" + Header.version() + "\" timestamp=\""
+ new Date().getTime() + "\">");
increaseIndentation();
dumpSources();
dumpPackages(projectData);
decreaseIndentation();
println("</coverage>");
} finally {
pw.close();
}
}
void increaseIndentation() {
indent++;
}
void decreaseIndentation() {
if (indent > 0)
indent--;
}
void indent() {
for (int i = 0; i < indent; i++) {
pw.print("\t");
}
}
void println(String ln) {
indent();
pw.println(ln);
}
private void dumpSources() {
println("<sources>");
increaseIndentation();
for (Iterator it = finder.getSourceDirectoryList().iterator(); it
.hasNext();) {
String dir = (String) it.next();
dumpSource(dir);
}
decreaseIndentation();
println("</sources>");
}
private void dumpSource(String sourceDirectory) {
println("<source>" + sourceDirectory + "</source>");
}
private void dumpPackages(ProjectData projectData) {
println("<packages>");
increaseIndentation();
Iterator it = projectData.getPackages().iterator();
while (it.hasNext()) {
dumpPackage((PackageData) it.next());
}
decreaseIndentation();
println("</packages>");
}
private void dumpPackage(PackageData packageData) {
logger.debug("Dumping package " + packageData.getName());
println("<package name=\"" + packageData.getName() + "\" line-rate=\""
+ packageData.getLineCoverageRate() + "\" branch-rate=\""
+ packageData.getBranchCoverageRate() + "\" complexity=\""
+ complexity.getCCNForPackage(packageData) + "\"" + ">");
increaseIndentation();
dumpSourceFiles(packageData);
decreaseIndentation();
println("</package>");
}
private void dumpSourceFiles(PackageData packageData) {
println("<classes>");
increaseIndentation();
Iterator it = packageData.getSourceFiles().iterator();
while (it.hasNext()) {
dumpClasses((SourceFileData) it.next());
}
decreaseIndentation();
println("</classes>");
}
private void dumpClasses(SourceFileData sourceFileData) {
Iterator it = sourceFileData.getClasses().iterator();
while (it.hasNext()) {
dumpClass((ClassData) it.next());
}
}
private void dumpClass(ClassData classData) {
logger.debug("Dumping class " + classData.getName());
println("<class name=\"" + classData.getName() + "\" filename=\""
+ classData.getSourceFileName() + "\" line-rate=\""
+ classData.getLineCoverageRate() + "\" branch-rate=\""
+ classData.getBranchCoverageRate() + "\" complexity=\""
+ complexity.getCCNForClass(classData) + "\"" + ">");
increaseIndentation();
dumpMethods(classData);
dumpLines(classData);
decreaseIndentation();
println("</class>");
}
private void dumpMethods(ClassData classData) {
println("<methods>");
increaseIndentation();
SortedSet sortedMethods = new TreeSet();
sortedMethods.addAll(classData.getMethodNamesAndDescriptors());
Iterator iter = sortedMethods.iterator();
while (iter.hasNext()) {
dumpMethod(classData, (String) iter.next());
}
decreaseIndentation();
println("</methods>");
}
private void dumpMethod(ClassData classData, String nameAndSig) {
String name = nameAndSig.substring(0, nameAndSig.indexOf('('));
String signature = nameAndSig.substring(nameAndSig.indexOf('('));
double lineRate = classData.getLineCoverageRate(nameAndSig);
double branchRate = classData.getBranchCoverageRate(nameAndSig);
int methodComplexity = complexity.getCCNForMethod(classData, name, signature);
println("<method name=\"" + xmlEscape(name) + "\" signature=\""
+ xmlEscape(signature) + "\" line-rate=\"" + lineRate
+ "\" branch-rate=\"" + branchRate + "\" complexity=\"" + methodComplexity + "\">");
increaseIndentation();
dumpLines(classData, nameAndSig);
decreaseIndentation();
println("</method>");
}
private static String xmlEscape(String str) {
str = StringUtil.replaceAll(str, "<", "&lt;");
str = StringUtil.replaceAll(str, ">", "&gt;");
return str;
}
private void dumpLines(ClassData classData) {
dumpLines(classData.getLines());
}
private void dumpLines(ClassData classData, String methodNameAndSig) {
dumpLines(classData.getLines(methodNameAndSig));
}
private void dumpLines(Collection lines) {
println("<lines>");
increaseIndentation();
SortedSet sortedLines = new TreeSet();
sortedLines.addAll(lines);
Iterator iter = sortedLines.iterator();
while (iter.hasNext()) {
dumpLine((LineData) iter.next());
}
decreaseIndentation();
println("</lines>");
}
private void dumpLine(LineData lineData) {
int lineNumber = lineData.getLineNumber();
long hitCount = lineData.getHits();
boolean hasBranch = lineData.hasBranch();
String conditionCoverage = lineData.getConditionCoverage();
String lineInfo = "<line number=\"" + lineNumber + "\" hits=\""
+ hitCount + "\" branch=\"" + hasBranch + "\"";
if (hasBranch) {
println(lineInfo + " condition-coverage=\"" + conditionCoverage
+ "\">");
dumpConditions(lineData);
println("</line>");
} else {
println(lineInfo + "/>");
}
}
private void dumpConditions(LineData lineData) {
increaseIndentation();
println("<conditions>");
for (int i = 0; i < lineData.getConditionSize(); i++) {
Object conditionData = lineData.getConditionData(i);
String coverage = lineData.getConditionCoverage(i);
dumpCondition(conditionData, coverage);
}
println("</conditions>");
decreaseIndentation();
}
private void dumpCondition(Object conditionData, String coverage) {
increaseIndentation();
StringBuffer buffer = new StringBuffer("<condition");
if (conditionData instanceof JumpData) {
JumpData jumpData = (JumpData) conditionData;
buffer.append(" number=\"").append(jumpData.getConditionNumber())
.append("\"");
buffer.append(" type=\"").append("jump").append("\"");
buffer.append(" coverage=\"").append(coverage).append("\"");
} else {
SwitchData switchData = (SwitchData) conditionData;
buffer.append(" number=\"").append(switchData.getSwitchNumber())
.append("\"");
buffer.append(" type=\"").append("switch").append("\"");
buffer.append(" coverage=\"").append(coverage).append("\"");
}
buffer.append("/>");
println(buffer.toString());
decreaseIndentation();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment