/*
* Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved.
*/
package jsystem.extensions.report.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import jsystem.extensions.report.html.HtmlTestReporter;
import jsystem.framework.FrameworkOptions;
import jsystem.framework.JSystemProperties;
import jsystem.framework.RunProperties;
import jsystem.framework.report.ExtendTestListener;
import jsystem.framework.report.ExtendTestReporter;
import jsystem.framework.report.Reporter;
import jsystem.framework.report.TestInfo;
import jsystem.framework.scenario.JTestContainer;
import jsystem.framework.scenario.Parameter;
import jsystem.framework.scenario.Scenario;
import jsystem.framework.scenario.ScenarioChangeType;
import jsystem.framework.scenario.ScenarioListener;
import jsystem.framework.scenario.flow_control.AntForLoop;
import jsystem.framework.sut.SutFactory;
import jsystem.framework.sut.SutListener;
import jsystem.utils.FileUtils;
import jsystem.utils.StringUtils;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
/**
* This reporter is used to create xml structured report. This report can be
* read and publish by the publisher.
*
* @author guy.arieli
*
*/
public class XmlReporter implements ExtendTestReporter, ExtendTestListener, SutListener, ScenarioListener {
static Logger log = Logger.getLogger(XmlReporter.class.getName());
public static final String DESCRIPTION = "Description";
public static final String VERSION = "Version";
public static final String BUILD = "Build";
public static final String INIT_REPORT = "init_report";
public static final String ACTION_TYPE = "action_type";
public static final String SCENARIO_NAME = "Scenario";
public static final String STATION = "Station";
public static final String SETUP = "Setup";
public static final String UPLOAD_FILES="UploadFiles";
public static final String USER = "User";
public static final String START_TIME = "startTime";
public static final String EXECUTION_PROPERTIES = "properties";
Document doc;
DocumentBuilder db;
// HashMap packages;
File reportFile;
Reader reader;
int fileMaxSize = 50000000;
int fileCount = -1;
int lastTestStatus = Reporter.PASS;
private TestInfo lastTestInfo;
public XmlReporter() {
try {
db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e) {
log.log(Level.WARNING, "problem creating document builder");
}
start();
}
public void initReporterManager() throws IOException {
}
public boolean asUI() {
return false;
}
public synchronized void report(String title, String message, boolean isPass, boolean bold) {
}
public String getName() {
return "XML reporter";
}
public void addError(Test test, Throwable t) {
lastTestStatus = Reporter.FAIL;
}
public void addFailure(Test test, AssertionFailedError t) {
lastTestStatus = Reporter.FAIL;
}
public synchronized void endTest(Test test) {
if (lastTestInfo.isHiddenInHTML && lastTestStatus == Reporter.PASS) {
reader.removeLastTest();
return;
}
reader.endTest(test, lastTestStatus);
lastTestStatus = Reporter.PASS;
if (reportFile.length() > fileMaxSize) {
start();
}
}
public void startTest(Test test) {
}
public void startTest(TestInfo testInfo) {
lastTestStatus = Reporter.PASS;
lastTestInfo = testInfo;
reader.startTest(testInfo);
sutChanged(SutFactory.getInstance().getSutInstance().getSetupName());
}
protected Element getReportElement(String title, String message, String isPass, boolean bold, boolean html,
boolean link) {
Element report = doc.createElement("step");
report.setAttribute("name", title);
if (message != null) {
report.setAttribute("message", String.valueOf(message));
}
report.setAttribute("status", isPass);
report.setAttribute("bold", (new Boolean(bold)).toString());
report.setAttribute("html", (new Boolean(html)).toString());
report.setAttribute("link", (new Boolean(link)).toString());
report.setAttribute("time", Long.toString(System.currentTimeMillis()));
return report;
}
private void start() {
reportFile = getFileName();
doc = db.newDocument();
try {
reader = new Reader(reportFile, doc);
} catch (Exception e) {
log.log(Level.SEVERE, "creating a Reader failed");
return;
}
}
public void init() {
// XML reporter takes some of it's data from the
// run properties. Deleting run properties when reporter is initialized.
//If this will be removed the scenario name and other parameters will not be published
RunProperties.getInstance().resetRunProperties();
fileCount = -1;
start();
}
protected File getFileName() {
String reportDir = JSystemProperties.getInstance().getPreference(FrameworkOptions.LOG_FOLDER);
if (reportDir == null) {
reportDir = "log";
}
File current = new File(reportDir, "current");
fileCount++;
return new File(current.getAbsolutePath(), "reports." + fileCount + ".xml");
}
/*
* (non-Javadoc)
*
* @see
* jsystem.framework.report.ExtendTestReporter#saveFile(java.lang.String,
* byte[])
*/
public void saveFile(String fileName, byte[] content) {
Element report = doc.createElement("save");
report.setAttribute("fileName", fileName);
report.appendChild(doc.createTextNode(StringUtils.bytesToString(content)));
}
/*
* (non-Javadoc)
*
* @see jsystem.framework.report.ExtendTestReporter#report(java.lang.String,
* java.lang.String, int, boolean)
*/
public synchronized void report(String title, String message, int status, boolean bold, boolean html, boolean link) {
switch (status) {
case Reporter.FAIL:
lastTestStatus = Reporter.FAIL;
break;
case Reporter.PASS:
break;
default:
if (lastTestStatus == Reporter.PASS) {
lastTestStatus = Reporter.WARNING;
}
}
}
/*
* (non-Javadoc)
*
* @see jsystem.framework.report.ExtendTestReporter#startSection()
*/
public void startSection() {
}
/*
* (non-Javadoc)
*
* @see jsystem.framework.report.ExtendTestReporter#endSection()
*/
public void endSection() {
}
public static void generate(File tempDir, File[] xmls) throws Exception {
if (tempDir.exists()) {
FileUtils.deltree(tempDir);
} else {
tempDir.mkdirs();
}
HtmlTestReporter reporter = new HtmlTestReporter(tempDir.getPath(), true);
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
for (int i = 0; i < xmls.length; i++) {
System.out.println("Load file: " + xmls[i].getName());
XMLReader reader = saxParser.getXMLReader();
reader.setContentHandler(new ReportCreator(reporter, tempDir));
reader.parse(new InputSource(xmls[i].getAbsolutePath()));
}
reporter = null;
}
public void setData(String data) {
}
public void addWarning(Test test) {
}
public void sutChanged(String sutName) {
if (reader != null) {
reader.setSut(sutName);
}
}
public void scenarioChanged(Scenario current, ScenarioChangeType changeType) {
if (reader != null && changeType.equals(ScenarioChangeType.CURRENT)) {
reader.setScenario(current.getName());
}
}
public void scenarioDirectoryChanged(File directory) {
}
public void endRun() {
}
final public static void main(final String[] args) throws Exception {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
XMLReader reader = saxParser.getXMLReader();
reader.setContentHandler(new ReportCreator(new HtmlTestReporter("c:\\xxx", true), new File("c:\\xxx")));
reader.parse(new InputSource("c:\\reports.0.xml"));
}
public void addProperty(String key, String value) {
if ((value != null) && !value.isEmpty()) {
reader.addProperty(key, value);
}
}
public void readElements() {
reader.readElements();
}
public void report(String title, String message, int status, boolean bold) {
report(title, message, status == Reporter.PASS, bold);
}
@Override
public void endContainer(JTestContainer container) {
// TODO Auto-generated method stub
}
@Override
public void endLoop(AntForLoop loop, int count) {
// TODO Auto-generated method stub
}
@Override
public void startContainer(JTestContainer container) {
if (container.isRoot()) {
init();
}
}
@Override
public void startLoop(AntForLoop loop, int count) {
// TODO Auto-generated method stub
}
@Override
public void scenarioDirtyStateChanged(Scenario s, boolean isDirty) {
// TODO Auto-generated method stub
}
@Override
public void testParametersChanged(String testIIUUD, Parameter[] oldValues, Parameter[] newValues) {
// TODO Auto-generated method stub
}
public void flush() throws Exception {
reader.readElements();
}
@Override
public void setContainerProperties(int property, String key, String value) {
// Ignore property
reader.addExecutionProperty(key, value);
}
}
/** an example sink for content events. It simply prints what it sees. */
class ReportCreator extends DefaultHandler implements ContentHandler {
HtmlTestReporter reporter;
String currentPackage = null;
File tmpDir;
FileOutputStream writer = null;
long startTime = 0;
long endTime = 0;
String[] name = null;
char lastChar;
boolean isCharLeft = false;
public ReportCreator(HtmlTestReporter reporter, File tmpDir) {
this.reporter = reporter;
this.tmpDir = tmpDir;
}
public void startElement(final String namespace, final String localname, final String type,
final Attributes attributes) throws SAXException {
XmlReporter.log.log(Level.INFO, StringUtils.getStackTrace(Thread.currentThread()));
if (type.equals("package")) {
currentPackage = attributes.getValue("name");
} else if (type.equals("test")) {
String params = attributes.getValue("params");
int count = 1;
String scount = attributes.getValue("count");
String tname = attributes.getValue("name");
if (scount != null) {
try {
count = Integer.parseInt(scount);
} catch (Throwable t) {
XmlReporter.log.log(Level.WARNING, "Fail to get test count for test: " + tname);
}
}
name = tname.split("\\.");
TestInfo ti = new TestInfo();
ti.className = currentPackage + "." + name[0];
ti.methodName = name[1];
ti.meaningfulName = null;
ti.comment = null;
ti.parameters = params;
ti.count = count;
ti.fullUuid = "";
reporter.startTest(ti);
if (attributes.getValue("status").equals("false")) {
reporter.addError(null, null);
}
String testMessage = attributes.getValue("message");
if (testMessage != null && testMessage.equals("")) {
testMessage = null;
}
if (testMessage != null) {
reporter.report(testMessage, null, true, true, false);
}
startTime = Long.parseLong(attributes.getValue("startTime"));
// /// temporary patch for fixing runner halt problem //////
endTime = 1111111111111L;
if (attributes.getValue("endTime") != "") {
try {
endTime = Long.parseLong(attributes.getValue("endTime"));
} catch (Throwable ignore) {
}
}
// //////////////////////////
} else if (type.equals("step")) {
String title = attributes.getValue("name");
String message = attributes.getValue("message");
if (message != null && message.equals("")) {
message = null;
}
String sStatus = attributes.getValue("status");
boolean bold = attributes.getValue("bold").toLowerCase().equals("true");
boolean html = attributes.getValue("html").toLowerCase().equals("true");
boolean link = attributes.getValue("link").toLowerCase().equals("true");
if (link) {
reporter.report(title, message, 0, false, false, true);
} else if (html) {
int stat = Reporter.FAIL;
if (sStatus.toLowerCase().equals("true")) {
stat = Reporter.PASS;
}
reporter.report(title, message, stat, false, true, false);
} else {
int status;
if (sStatus.toLowerCase().equals("true")) {
status = Reporter.PASS;
} else if (sStatus.toLowerCase().equals("false")) {
status = Reporter.FAIL;
} else {
status = Reporter.WARNING;
}
reporter.report(title, message, status, bold, false, false);
}
} else if (type.equals("section")) {
if (attributes.getValue("start").equals("true")) {
reporter.startSection();
} else {
reporter.endSection();
}
} else if (type.equals("save")) {
String fileName = attributes.getValue("fileName");
File f = new File(tmpDir, "current");
File file = new File(f, fileName);
try {
writer = new FileOutputStream(file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void endElement(final String namespace, final String localname, final String type) throws SAXException {
if (type.equals("save")) {
if (writer != null) {
try {
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
writer = null;
} else if (type.equals("test")) {
long runningTime = endTime - startTime;
if (runningTime < 0) {
runningTime = 0;
}
reporter.endTest(currentPackage, name[0], name[1], runningTime);
}
}
public void characters(final char[] ch, int start, int len) {
if (ch != null && ch.length > 0) {
if (writer != null) {
int i = 0;
try {
if (isCharLeft) {
writer.write((char) (getCharVal(lastChar) * 16 + getCharVal(ch[start])));
isCharLeft = false;
start++;
len--;
}
if (len % 2 != 0) {
lastChar = ch[start + len - 1];
len--;
isCharLeft = true;
}
for (i = 0; i < len; i = i + 2) {
writer.write((char) (getCharVal(ch[start + i]) * 16 + getCharVal(ch[start + i + 1])));
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
private int getCharVal(char c1) {
switch (c1) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'a':
return 10;
case 'b':
return 11;
case 'c':
return 12;
case 'd':
return 13;
case 'e':
return 14;
case 'f':
return 15;
default:
return -1;
}
}
}