Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(report-aggregate) Fix report aggregation #625

Merged
merged 4 commits into from
Feb 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
package org.pitest.aggregate;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.pitest.classinfo.ClassName;
import org.pitest.coverage.BlockCoverage;
Expand All @@ -12,10 +22,13 @@

class BlockCoverageDataLoader extends DataLoader<BlockCoverage> {

private static final String BLOCK = "block";
private static final String TESTS = "tests";
private static final String TEST = "test";
private static final String NAME = "name";
private static final String METHOD = "method";
private static final String CLASSNAME = "classname";
private static final String NUMBER = "number";
private static final String TESTS = "tests";
private static final String FIRST_INSN = "firstInstruction";
private static final String LAST_INSN = "lastInstruction";

Expand All @@ -24,20 +37,61 @@ class BlockCoverageDataLoader extends DataLoader<BlockCoverage> {
BlockCoverageDataLoader(final Collection<File> filesToLoad) {
super(filesToLoad);
}

@Override
protected BlockCoverage mapToData(final Map<String, Object> map) {
final String method = (String) map.get(METHOD);
final Location location = new Location(ClassName.fromString((String) map.get(CLASSNAME)),
MethodName.fromString(method.substring(0, method.indexOf(OPEN_PAREN))), method.substring(method.indexOf(OPEN_PAREN)));
protected Set<BlockCoverage> mapToData(XMLEventReader doc) throws XMLStreamException {
final Set<BlockCoverage> data = new HashSet<>();
List<String> tests = new ArrayList<>();
StartElement enclosingNode = null;
BlockLocation block = null;
while (doc.hasNext()) {
XMLEvent next = doc.peek();
if (next.isStartElement()) {
enclosingNode = next.asStartElement();
String nodeName = next.asStartElement().getName().getLocalPart();
if (nodeName.equals(BLOCK)) {
block = toBlockLocation(enclosingNode);
}
if (nodeName.equals(TESTS)) {
tests = new ArrayList<>();
}
if (nodeName.equals(TEST)) {
tests.add(getAttributeValue(enclosingNode, NAME));
}
}
if (next.isEndElement()) {
String nodeName = next.asEndElement().getName().getLocalPart();
if (nodeName.equals(BLOCK)) {
data.add(new BlockCoverage(block, tests.isEmpty() ? null : tests));
}
}
doc.next();
}
return data;
}

final BlockLocation blockLocation = new BlockLocation(location, Integer.parseInt((String) map.get(NUMBER)),
Integer.parseInt((String) map.get(FIRST_INSN)),Integer.parseInt((String) map.get(LAST_INSN)));
private BlockLocation toBlockLocation(StartElement enclosingNode) {
BlockLocation block;
ClassName className = ClassName.fromString(getAttributeValue(enclosingNode, CLASSNAME));
String method = getAttributeValue(enclosingNode, METHOD);
MethodName methodName = MethodName.fromString(method.substring(0, method.indexOf(OPEN_PAREN)));
int blockNum = getAttributeValueAsInt(enclosingNode, NUMBER);
int firstInstruction = getAttributeValueAsInt(enclosingNode, FIRST_INSN);
int lastInstruction = getAttributeValueAsInt(enclosingNode, LAST_INSN);
String methodDesc = method.substring(method.indexOf(OPEN_PAREN));
Location location = new Location(className, methodName, methodDesc);
block = new BlockLocation(location, blockNum, firstInstruction, lastInstruction);
return block;
}

@SuppressWarnings("unchecked")
final Collection<String> tests = (Collection<String>) map.get(TESTS);
private String getAttributeValue(StartElement enclosingNode, String attributeName) {
Attribute attribute = enclosingNode.getAttributeByName(QName.valueOf(attributeName));
return attribute == null ? null : attribute.getValue();
}

return new BlockCoverage(blockLocation, tests);
private int getAttributeValueAsInt(StartElement enclosingNode, String attributeName) {
String value = getAttributeValue(enclosingNode, attributeName);
return value == null ? 0 : Integer.parseInt(value);
}

}
117 changes: 19 additions & 98 deletions pitest-aggregator/src/main/java/org/pitest/aggregate/DataLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,17 @@
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;

abstract class DataLoader<T> {

Expand All @@ -47,104 +38,34 @@ public Set<T> loadData() throws ReportAggregationException {
return data;
}

protected abstract T mapToData(Map<String, Object> map);
protected abstract Set<T> mapToData(XMLEventReader doc) throws XMLStreamException;

Set<T> loadData(final File dataLocation) throws ReportAggregationException {
if (!dataLocation.exists() || !dataLocation.isFile()) {
throw new ReportAggregationException(dataLocation.getAbsolutePath() + " does not exist or is not a file");
}
final Set<T> data = new HashSet<>();
try {
final InputStream inputStream = new BufferedInputStream(new FileInputStream(dataLocation));

final Document doc = readDocument(inputStream);

final Node docNode = doc.getFirstChild();
final NodeList nodeList = docNode.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
final Node itemNode = nodeList.item(i);
if (itemNode.getNodeType() == Node.ELEMENT_NODE) {
data.add(mapToData(nodeMap(itemNode)));
}
}
return data;
} catch (final IOException e) {
return loadData(new BufferedInputStream(new FileInputStream(dataLocation)), dataLocation);
} catch (FileNotFoundException e) {
throw new ReportAggregationException("Could not read file: " + dataLocation.getAbsolutePath(), e);
}
}

/**
* Reads the input stream into a document and closes the input stream when
* finished.
*/
static Document readDocument(final InputStream inputStream) throws ReportAggregationException {
DocumentBuilder docBuilder;

Set<T> loadData(final InputStream inputStream, final File dataLocation) throws ReportAggregationException {
try {
docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
return docBuilder.parse(inputStream);
} catch (final IOException e) {
throw new ReportAggregationException(e.getMessage(), e);
} catch (final SAXException e) {
throw new ReportAggregationException(e.getMessage(), e);
} catch (final ParserConfigurationException e) {
throw new ReportAggregationException(e.getMessage(), e);
final XMLEventReader doc = XMLInputFactory.newInstance().createXMLEventReader(inputStream);
return mapToData(doc);
} catch (final XMLStreamException e) {
throw new ReportAggregationException("Could not parse file: " + dataLocation.getAbsolutePath(), e);
} finally {
try {
inputStream.close();
} catch (final IOException e) {
throw new ReportAggregationException(CANNOT_CLOSE_ERR, e);
}
}
}

// converts the contents of a node into a map
static Map<String, Object> nodeMap(final Node node) {
final HashMap<String, Object> map = new HashMap<>();

final NamedNodeMap attrs = node.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
final Node attr = attrs.item(i);
final String tc = attr.getTextContent().trim();

if (!tc.isEmpty()) {
map.put(attr.getNodeName(), tc);
}
}

final NodeList children = node.getChildNodes();

for (int i = 0; i < children.getLength(); i++) {
final Node child = children.item(i);

if (child.getNodeType() == Node.ELEMENT_NODE) {
final String tc = child.getTextContent().trim();
if (!tc.isEmpty()) {
map.put(child.getNodeName(), tc);
} else {
// may have test nodes
final List<String> tests = new ArrayList<>();
final NodeList testNodeList = child.getChildNodes();
for (int j = 0; j < testNodeList.getLength(); j++) {
final Node testNode = testNodeList.item(j);
if (testNode.getNodeType() == Node.ELEMENT_NODE) {
final NamedNodeMap testAttrs = testNode.getAttributes();
for (int k = 0; k < testAttrs.getLength(); k++) {
final Node attr = testAttrs.item(k);
final String tn = attr.getTextContent().trim();

if (!tn.isEmpty()) {
tests.add(tn);
}
}
}
}
if (!tests.isEmpty()) {
map.put(child.getNodeName(), tests);
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
throw new ReportAggregationException(CANNOT_CLOSE_ERR, e);
}
}
}

return map;
}

}
Loading