package hudson.plugins.performance;
import hudson.Extension;
import hudson.model.AbstractBuild;
import hudson.model.TaskListener;
import hudson.util.IOException2;
import org.kohsuke.stapler.DataBoundConstructor;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
/**
* Parser for JUnit.
*
* @author Manuel Carrasco
*/
public class JUnitParser extends JMeterParser {
@Extension
public static class DescriptorImpl extends PerformanceReportParserDescriptor {
@Override
public String getDisplayName() {
return "JUnit";
}
}
@DataBoundConstructor
public JUnitParser(String glob) {
super(glob);
}
@Override
public String getDefaultGlobPattern() {
return "**/TEST-*.xml";
}
@Override
public Collection<PerformanceReport> parse(AbstractBuild<?, ?> build,
Collection<File> reports, TaskListener listener) throws IOException {
List<PerformanceReport> result = new ArrayList<PerformanceReport>();
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(false);
PrintStream logger = listener.getLogger();
for (File f : reports) {
try {
SAXParser parser = factory.newSAXParser();
final PerformanceReport r = new PerformanceReport();
r.setReportFileName(f.getName());
parser.parse(f, new DefaultHandler() {
private HttpSample currentSample;
private int status;
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (("testsuite".equalsIgnoreCase(qName) || "testcase"
.equalsIgnoreCase(qName)) && status != 0) {
r.addSample(currentSample);
status = 0;
}
}
/**
* JUnit XML format is: tag "testcase" with attributes: "name" and
* "time". If there is one error, there is an other tag, "failure"
* inside testcase tag. SOAPUI uses JUnit format
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if ("testcase".equalsIgnoreCase(qName)) {
if (status != 0) {
r.addSample(currentSample);
}
status = 1;
currentSample = new HttpSample();
currentSample.setDate(new Date(0));
String time = attributes.getValue("time");
currentSample.setDuration(parseDuration(time));
currentSample.setSuccessful(true);
currentSample.setUri(attributes.getValue("name"));
currentSample.setErrorObtained(false);
} else if ("failure".equalsIgnoreCase(qName) && status != 0) {
currentSample.setErrorObtained(false);
currentSample.setSuccessful(false);
r.addSample(currentSample);
status = 0;
} else if ("failure".equalsIgnoreCase(qName) && status != 0) {
currentSample.setErrorObtained(true);
r.addSample(currentSample);
status = 0;
}
}
});
result.add(r);
} catch (ParserConfigurationException e) {
throw new IOException2("Failed to create parser ", e);
} catch (SAXException e) {
logger.println("Performance: Failed to parse " + f + ": "
+ e.getMessage());
}
}
return result;
}
/**
* Strips any commas from <code>time</code>, then parses it into a long.
*/
long parseDuration(final String time) {
double duration = Double.parseDouble(time.replaceAll(",", "")); // don't
// want
// commas or
// else will
// break on
// parse
return (long) (duration * 1000);
}
}