/*******************************************************************************
* Copyright (c) 2007, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Brock Janiczak (brockj@tpg.com.au)
* - https://bugs.eclipse.org/bugs/show_bug.cgi?id=102236: [JUnit] display execution time next to each test
*******************************************************************************/
package org.phpsrc.eclipse.pti.tools.phpunit.core.model;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Assert;
import org.phpsrc.eclipse.pti.tools.phpunit.core.model.ITestElement.FailureTrace;
import org.phpsrc.eclipse.pti.tools.phpunit.core.model.ITestElement.ProgressState;
import org.phpsrc.eclipse.pti.tools.phpunit.core.model.ITestElement.Result;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
public class TestRunSessionSerializer implements XMLReader {
private static final String EMPTY = ""; //$NON-NLS-1$
private static final String CDATA = "CDATA"; //$NON-NLS-1$
private static final Attributes NO_ATTS = new AttributesImpl();
private final TestRunSession fTestRunSession;
private ContentHandler fHandler;
private ErrorHandler fErrorHandler;
private final NumberFormat timeFormat = new DecimalFormat("0.0##", new DecimalFormatSymbols(Locale.US)); //$NON-NLS-1$ // not localized, parseable by Double.parseDouble(..)
/**
* @param testRunSession
* the test run session to serialize
*/
public TestRunSessionSerializer(TestRunSession testRunSession) {
Assert.isNotNull(testRunSession);
fTestRunSession = testRunSession;
}
public void parse(InputSource input) throws IOException, SAXException {
if (fHandler == null)
throw new SAXException("ContentHandler missing"); //$NON-NLS-1$
fHandler.startDocument();
handleTestRun();
fHandler.endDocument();
}
private void handleTestRun() throws SAXException {
AttributesImpl atts = new AttributesImpl();
addCDATA(atts, IXMLTags.ATTR_NAME, fTestRunSession.getTestRunName());
IProject project = fTestRunSession.getLaunchedProject();
if (project != null)
addCDATA(atts, IXMLTags.ATTR_PROJECT, project.getName());
addCDATA(atts, IXMLTags.ATTR_TESTS, fTestRunSession.getTotalCount());
addCDATA(atts, IXMLTags.ATTR_STARTED, fTestRunSession.getStartedCount());
addCDATA(atts, IXMLTags.ATTR_FAILURES, fTestRunSession.getFailureCount());
addCDATA(atts, IXMLTags.ATTR_ERRORS, fTestRunSession.getErrorCount());
addCDATA(atts, IXMLTags.ATTR_IGNORED, fTestRunSession.getIgnoredCount());
startElement(IXMLTags.NODE_TESTRUN, atts);
TestRoot testRoot = fTestRunSession.getTestRoot();
ITestElement[] topSuites = testRoot.getChildren();
for (int i = 0; i < topSuites.length; i++) {
handleTestElement(topSuites[i]);
}
endElement(IXMLTags.NODE_TESTRUN);
}
private void handleTestElement(ITestElement testElement) throws SAXException {
if (testElement instanceof TestSuiteElement) {
TestSuiteElement testSuiteElement = (TestSuiteElement) testElement;
AttributesImpl atts = new AttributesImpl();
addCDATA(atts, IXMLTags.ATTR_NAME, testSuiteElement.getSuiteTypeName());
if (!Double.isNaN(testSuiteElement.getElapsedTimeInSeconds()))
addCDATA(atts, IXMLTags.ATTR_TIME, timeFormat.format(testSuiteElement.getElapsedTimeInSeconds()));
if (testElement.getProgressState() != ProgressState.COMPLETED
|| testElement.getTestResult(false) != Result.UNDEFINED)
addCDATA(atts, IXMLTags.ATTR_INCOMPLETE, Boolean.TRUE.toString());
startElement(IXMLTags.NODE_TESTSUITE, atts);
addFailure(testElement);
ITestElement[] children = testSuiteElement.getChildren();
for (int i = 0; i < children.length; i++) {
handleTestElement(children[i]);
}
endElement(IXMLTags.NODE_TESTSUITE);
} else if (testElement instanceof TestCaseElement) {
TestCaseElement testCaseElement = (TestCaseElement) testElement;
AttributesImpl atts = new AttributesImpl();
addCDATA(atts, IXMLTags.ATTR_NAME, testCaseElement.getTestMethodName());
addCDATA(atts, IXMLTags.ATTR_CLASSNAME, testCaseElement.getClassName());
if (!Double.isNaN(testCaseElement.getElapsedTimeInSeconds()))
addCDATA(atts, IXMLTags.ATTR_TIME, timeFormat.format(testCaseElement.getElapsedTimeInSeconds()));
if (testElement.getProgressState() != ProgressState.COMPLETED)
addCDATA(atts, IXMLTags.ATTR_INCOMPLETE, Boolean.TRUE.toString());
if (testCaseElement.isIgnored())
addCDATA(atts, IXMLTags.ATTR_IGNORED, Boolean.TRUE.toString());
startElement(IXMLTags.NODE_TESTCASE, atts);
addFailure(testElement);
endElement(IXMLTags.NODE_TESTCASE);
} else {
throw new IllegalStateException(String.valueOf(testElement));
}
}
private void addFailure(ITestElement testElement) throws SAXException {
FailureTrace failureTrace = testElement.getFailureTrace();
if (failureTrace != null) {
AttributesImpl failureAtts = new AttributesImpl();
// addCDATA(failureAtts, IXMLTags.ATTR_MESSAGE, xx);
// addCDATA(failureAtts, IXMLTags.ATTR_TYPE, xx);
String failureKind = testElement.getTestResult(false) == Result.ERROR ? IXMLTags.NODE_ERROR
: IXMLTags.NODE_FAILURE;
startElement(failureKind, failureAtts);
String expected = failureTrace.getExpected();
String actual = failureTrace.getActual();
if (expected != null) {
startElement(IXMLTags.NODE_EXPECTED, NO_ATTS);
fHandler.characters(expected.toCharArray(), 0, expected.length());
endElement(IXMLTags.NODE_EXPECTED);
}
if (actual != null) {
startElement(IXMLTags.NODE_ACTUAL, NO_ATTS);
fHandler.characters(actual.toCharArray(), 0, actual.length());
endElement(IXMLTags.NODE_ACTUAL);
}
String trace = failureTrace.getTrace();
fHandler.characters(trace.toCharArray(), 0, trace.length());
endElement(failureKind);
}
}
private void startElement(String name, Attributes atts) throws SAXException {
fHandler.startElement(EMPTY, name, name, atts);
}
private void endElement(String name) throws SAXException {
fHandler.endElement(EMPTY, name, name);
}
private static void addCDATA(AttributesImpl atts, String name, int value) {
addCDATA(atts, name, Integer.toString(value));
}
private static void addCDATA(AttributesImpl atts, String name, String value) {
atts.addAttribute(EMPTY, EMPTY, name, CDATA, value);
}
public void setContentHandler(ContentHandler handler) {
this.fHandler = handler;
}
public ContentHandler getContentHandler() {
return fHandler;
}
public void setErrorHandler(ErrorHandler handler) {
fErrorHandler = handler;
}
public ErrorHandler getErrorHandler() {
return fErrorHandler;
}
// ignored:
public void parse(String systemId) throws IOException, SAXException {
}
public void setDTDHandler(DTDHandler handler) {
}
public DTDHandler getDTDHandler() {
return null;
}
public void setEntityResolver(EntityResolver resolver) {
}
public EntityResolver getEntityResolver() {
return null;
}
public void setProperty(java.lang.String name, java.lang.Object value) {
}
public Object getProperty(java.lang.String name) {
return null;
}
public void setFeature(java.lang.String name, boolean value) {
}
public boolean getFeature(java.lang.String name) {
return false;
}
}