package at.ac.tuwien.iter.services.impl.assertions;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import at.ac.tuwien.iter.data.TestReport;
import at.ac.tuwien.iter.data.TestResult;
import at.ac.tuwien.iter.services.AssertionService;
import at.ac.tuwien.iter.services.impl.datacollector.DatabaseManagerService;
public class RelativeFailedRequestAssertion implements AssertionService {
private Logger logger;
private DatabaseManagerService dbService;
private String assertionName = "relative-failed-requests";
private double threshold;
public RelativeFailedRequestAssertion(Logger logger,
DatabaseManagerService dbService, double threshold) {
this.logger = logger;
this.dbService = dbService;
if (threshold > 1.0 || threshold < 0.0) {
throw new IllegalArgumentException(
"Relative threshold must be between 0.0 and 1.0!");
}
this.threshold = threshold;
assertionName = assertionName + "-" + (threshold * 100.0) + "%";
}
private double getFailedOverTotalRatio(File xmlFile) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder;
Document doc = null;
XPathExpression expr = null;
builder = factory.newDocumentBuilder();
doc = builder.parse(xmlFile);
// Count the requests
// <testResults version="1.2">
// <httpSample
XPathFactory xFactory = XPathFactory.newInstance();
XPath xpath = xFactory.newXPath();
expr = xpath.compile("//httpSample");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
int total = nodes.getLength();
expr = xpath.compile("//httpSample[@s='false']");
result = expr.evaluate(doc, XPathConstants.NODESET);
nodes = (NodeList) result;
int failed = nodes.getLength();
if (total != 0) {
return ((double) failed / (double) total);
} else {
throw new RuntimeException(
"Cannot compute ratio failed/total requests: No requests at all!");
}
} catch (XPathExpressionException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
throw new RuntimeException("Cannot compute ratio failed/total requests");
}
// Better testability
protected TestReport check(String _xmlFile) {
TestReport testReport = new TestReport();
testReport.setTestedProperty(assertionName);
try {
File xmlFile = new File(_xmlFile);
// Read the file into a string a pass it to the method
double ratio = getFailedOverTotalRatio(xmlFile);
if (ratio < threshold) {
logger.info(assertionName + " PASSED");
testReport.setTestOutcome("PASSED");
} else {
logger.info(assertionName + " FAILED");
testReport.setTestOutcome("FAILED");
testReport.setReason(String.format(
"%.2f%% of requests failed. Max is %.2f%%",
(ratio * 100), (threshold * 100)));
}
} catch (Throwable e) {
logger.warn("Exception while checking" + assertionName
+ " : ERROR !", e);
testReport.setTestOutcome("ERROR");
testReport.setReason(e.getMessage());
}
return testReport;
}
public void check(TestResult testResult) {
try {
// TODO There is something wrong while doing the bootstrap !
String xmlFile = null;
if (testResult.getClientsDB() != null) {
xmlFile = testResult.getClientsDB();
} else {
xmlFile = dbService.getClientDBnameForTest(testResult);
}
testResult.addTestReport(check(xmlFile));
} catch (Throwable e) {
logger.error(
"Got exception. Catch it to avoid breaking the chain !", e);
TestReport testReport = new TestReport();
testReport.setTestedProperty(assertionName);
testReport.setTestOutcome("ERROR");
testReport.setReason(e.getMessage());
testResult.addTestReport(testReport);
}
}
}