001: /**
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */package com.tc.test;
004:
005: import org.w3c.dom.Text;
006: import org.w3c.dom.Element;
007: import org.w3c.dom.Document;
008:
009: import org.apache.tools.ant.util.DOMElementWriter;
010: import org.apache.tools.ant.taskdefs.optional.junit.XMLConstants;
011: import org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner;
012: import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;
013: import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter;
014: import org.apache.tools.ant.BuildException;
015:
016: import junit.framework.TestCase;
017: import junit.framework.Test;
018: import junit.framework.AssertionFailedError;
019:
020: import javax.xml.parsers.DocumentBuilderFactory;
021: import javax.xml.parsers.DocumentBuilder;
022: import java.util.Properties;
023: import java.util.Enumeration;
024: import java.io.Writer;
025: import java.io.OutputStreamWriter;
026: import java.io.OutputStream;
027: import java.io.IOException;
028: import java.io.FileOutputStream;
029: import java.io.FileNotFoundException;
030: import java.io.File;
031: import java.io.BufferedWriter;
032:
033: /**
034: * This formatter is used to generate a 'pre-condition' log --- if the TestCase shuts the VM down (eg: deliberately
035: * calling System.exit()) then we'll at least have a log file that indicate that the TestSuite did not complete
036: * gracefully, with a record of which TestCase was last run...
037: *
038: * @author Juris Galang
039: */
040: public class TCXMLJUnitFormatter implements JUnitResultFormatter,
041: XMLConstants {
042:
043: /**
044: */
045: private JUnitTest suite;
046:
047: /**
048: */
049: private File logfile;
050:
051: /**
052: * The XML document.
053: */
054: private Document doc;
055:
056: /**
057: * The wrapper for the whole testsuite.
058: */
059: private Element rootElement;
060:
061: /** constant for unnnamed testsuites/cases */
062: private static final String UNKNOWN = "unknown";
063:
064: /**
065: */
066: public void startTest(Test test) {
067: //logfile = new File("TEST-" + this.suite.getName() + "-" + ((TestCase) test).getName() + ".xml");
068: logfile = new File("TEST-" + this .suite.getName() + ".xml");
069:
070: loadDocument();
071: Throwable t = new TestSuiteAbortedException("TestSuite '"
072: + suite.getName()
073: + "' abnormally terminated in test case: '"
074: + ((TestCase) test).getName() + "'");
075: Element nested = doc.createElement(FAILURE);
076: Element currentTest = rootElement;
077:
078: currentTest.appendChild(nested);
079:
080: String message = t.getMessage();
081: if (message != null && message.length() > 0) {
082: nested.setAttribute(ATTR_MESSAGE, t.getMessage());
083: }
084: nested.setAttribute(ATTR_TYPE, t.getClass().getName());
085:
086: String strace = JUnitTestRunner.getFilteredTrace(t);
087: Text trace = doc.createTextNode(strace);
088: nested.appendChild(trace);
089: saveDocument();
090: }
091:
092: /**
093: */
094: public void endTest(Test test) {
095: logfile.delete();
096: }
097:
098: private void loadDocument() {
099: try {
100: doc = logfile.exists() ? getDocumentBuilder()
101: .parse(logfile) : getDocumentBuilder()
102: .newDocument();
103: if (logfile.exists()) {
104: rootElement = (Element) doc.getElementsByTagName(
105: TESTSUITE).item(0);
106: return;
107: }
108:
109: rootElement = doc.createElement(TESTSUITE);
110: String n = suite.getName();
111: rootElement
112: .setAttribute(ATTR_NAME, n == null ? UNKNOWN : n);
113:
114: Element propsElement = doc.createElement(PROPERTIES);
115: rootElement.appendChild(propsElement);
116: Properties props = suite.getProperties();
117: if (props != null) {
118: Enumeration e = props.propertyNames();
119: while (e.hasMoreElements()) {
120: String name = (String) e.nextElement();
121: Element propElement = doc.createElement(PROPERTY);
122: propElement.setAttribute(ATTR_NAME, name);
123: propElement.setAttribute(ATTR_VALUE, props
124: .getProperty(name));
125: propsElement.appendChild(propElement);
126: }
127: }
128: } catch (java.io.IOException ioe) {
129: throw new BuildException("Unable to append to log file",
130: ioe);
131: } catch (org.xml.sax.SAXException saxe) {
132: throw new BuildException("Unable to append to log file",
133: saxe);
134: }
135: }
136:
137: private void saveDocument() {
138: rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount());
139: rootElement.setAttribute(ATTR_FAILURES, ""
140: + (suite.failureCount() + 1));
141: rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount());
142: rootElement.setAttribute(ATTR_TIME, ""
143: + (suite.getRunTime() / 1000.0));
144: try {
145: FileOutputStream out = new FileOutputStream(logfile, true);
146: if (out != null) {
147: Writer wri = null;
148: try {
149: wri = new BufferedWriter(new OutputStreamWriter(
150: out, "UTF8"));
151: wri
152: .write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
153: (new DOMElementWriter()).write(rootElement, wri, 0,
154: " ");
155: wri.flush();
156: rootElement = null;
157: } catch (IOException exc) {
158: throw new BuildException(
159: "Unable to write log file", exc);
160: } finally {
161: if (wri != null) {
162: try {
163: wri.close();
164: } catch (IOException e) {
165: // ignore
166: }
167: }
168: }
169: }
170: } catch (FileNotFoundException fnfe) {
171: throw new BuildException("Unable to create log file", fnfe);
172: }
173: }
174:
175: /**
176: */
177: public void startTestSuite(JUnitTest test) {
178: this .suite = test;
179: }
180:
181: /**
182: */
183: public void endTestSuite(JUnitTest test) {
184: //
185: }
186:
187: private static DocumentBuilder getDocumentBuilder() {
188: try {
189: return DocumentBuilderFactory.newInstance()
190: .newDocumentBuilder();
191: } catch (Exception exc) {
192: throw new ExceptionInInitializerError(exc);
193: }
194: }
195:
196: private class TestSuiteAbortedException extends Throwable {
197: public TestSuiteAbortedException(String message) {
198: super (message);
199: }
200:
201: public String getMessage() {
202: return super .getMessage();
203: }
204:
205: }
206:
207: public void setOutput(OutputStream out) {
208: //
209: }
210:
211: public void setSystemOutput(String out) {
212: //
213: }
214:
215: public void setSystemError(String out) {
216: //
217: }
218:
219: public void addError(Test test, java.lang.Throwable t) {
220: //
221: }
222:
223: public void addFailure(Test test, AssertionFailedError t) {
224: //
225: }
226: } // TCXMLJUnitFormatter
|