PageRenderTime 70ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unit/org/apache/cassandra/CassandraXMLJUnitResultFormatter.java

https://github.com/beobal/cassandra
Java | 391 lines | 224 code | 51 blank | 116 comment | 44 complexity | 3e28a6f18b3cf84dc650239b0e521a6d MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.cassandra;
  19. import java.io.BufferedWriter;
  20. import java.io.IOException;
  21. import java.io.OutputStream;
  22. import java.io.OutputStreamWriter;
  23. import java.io.Writer;
  24. import java.net.InetAddress;
  25. import java.net.UnknownHostException;
  26. import java.util.Date;
  27. import java.util.Enumeration;
  28. import java.util.Hashtable;
  29. import java.util.Properties;
  30. import javax.xml.parsers.DocumentBuilder;
  31. import javax.xml.parsers.DocumentBuilderFactory;
  32. import junit.framework.AssertionFailedError;
  33. import junit.framework.Test;
  34. import org.apache.tools.ant.BuildException;
  35. import org.apache.tools.ant.taskdefs.optional.junit.IgnoredTestListener;
  36. import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter;
  37. import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;
  38. import org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner;
  39. import org.apache.tools.ant.taskdefs.optional.junit.JUnitVersionHelper;
  40. import org.apache.tools.ant.taskdefs.optional.junit.XMLConstants;
  41. import org.apache.tools.ant.util.DOMElementWriter;
  42. import org.apache.tools.ant.util.DateUtils;
  43. import org.apache.tools.ant.util.FileUtils;
  44. import org.w3c.dom.Document;
  45. import org.w3c.dom.Element;
  46. import org.w3c.dom.Text;
  47. /**
  48. * Prints XML output of the test to a specified Writer.
  49. *
  50. * @see FormatterElement
  51. */
  52. public class CassandraXMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants, IgnoredTestListener {
  53. private static final double ONE_SECOND = 1000.0;
  54. /** constant for unnnamed testsuites/cases */
  55. private static final String UNKNOWN = "unknown";
  56. private static DocumentBuilder getDocumentBuilder() {
  57. try {
  58. return DocumentBuilderFactory.newInstance().newDocumentBuilder();
  59. } catch (final Exception exc) {
  60. throw new ExceptionInInitializerError(exc);
  61. }
  62. }
  63. private static final String tag = System.getProperty("cassandra.testtag", "");
  64. /*
  65. * Set the property for the test suite name so that log configuration can pick it up
  66. * and log to a file specific to this test suite
  67. */
  68. static
  69. {
  70. String command = System.getProperty("sun.java.command");
  71. String args[] = command.split(" ");
  72. System.setProperty("suitename", args[1]);
  73. }
  74. /**
  75. * The XML document.
  76. */
  77. private Document doc;
  78. /**
  79. * The wrapper for the whole testsuite.
  80. */
  81. private Element rootElement;
  82. /**
  83. * Element for the current test.
  84. *
  85. * The keying of this map is a bit of a hack: tests are keyed by caseName(className) since
  86. * the Test we get for Test-start isn't the same as the Test we get during test-assumption-fail,
  87. * so we can't easily match Test objects without manually iterating over all keys and checking
  88. * individual fields.
  89. */
  90. private final Hashtable<String, Element> testElements = new Hashtable<String, Element>();
  91. /**
  92. * tests that failed.
  93. */
  94. private final Hashtable failedTests = new Hashtable();
  95. /**
  96. * Tests that were skipped.
  97. */
  98. private final Hashtable<String, Test> skippedTests = new Hashtable<String, Test>();
  99. /**
  100. * Tests that were ignored. See the note above about the key being a bit of a hack.
  101. */
  102. private final Hashtable<String, Test> ignoredTests = new Hashtable<String, Test>();
  103. /**
  104. * Timing helper.
  105. */
  106. private final Hashtable<String, Long> testStarts = new Hashtable<String, Long>();
  107. /**
  108. * Where to write the log to.
  109. */
  110. private OutputStream out;
  111. /** No arg constructor. */
  112. public CassandraXMLJUnitResultFormatter() {
  113. }
  114. /** {@inheritDoc}. */
  115. public void setOutput(final OutputStream out) {
  116. this.out = out;
  117. }
  118. /** {@inheritDoc}. */
  119. public void setSystemOutput(final String out) {
  120. formatOutput(SYSTEM_OUT, out);
  121. }
  122. /** {@inheritDoc}. */
  123. public void setSystemError(final String out) {
  124. formatOutput(SYSTEM_ERR, out);
  125. }
  126. /**
  127. * The whole testsuite started.
  128. * @param suite the testsuite.
  129. */
  130. public void startTestSuite(final JUnitTest suite) {
  131. doc = getDocumentBuilder().newDocument();
  132. rootElement = doc.createElement(TESTSUITE);
  133. String n = suite.getName();
  134. if (n != null && !tag.isEmpty())
  135. n = n + "-" + tag;
  136. rootElement.setAttribute(ATTR_NAME, n == null ? UNKNOWN : n);
  137. //add the timestamp
  138. final String timestamp = DateUtils.format(new Date(),
  139. DateUtils.ISO8601_DATETIME_PATTERN);
  140. rootElement.setAttribute(TIMESTAMP, timestamp);
  141. //and the hostname.
  142. rootElement.setAttribute(HOSTNAME, getHostname());
  143. // Output properties
  144. final Element propsElement = doc.createElement(PROPERTIES);
  145. rootElement.appendChild(propsElement);
  146. final Properties props = suite.getProperties();
  147. if (props != null) {
  148. final Enumeration e = props.propertyNames();
  149. while (e.hasMoreElements()) {
  150. final String name = (String) e.nextElement();
  151. final Element propElement = doc.createElement(PROPERTY);
  152. propElement.setAttribute(ATTR_NAME, name);
  153. propElement.setAttribute(ATTR_VALUE, props.getProperty(name));
  154. propsElement.appendChild(propElement);
  155. }
  156. }
  157. }
  158. /**
  159. * get the local hostname
  160. * @return the name of the local host, or "localhost" if we cannot work it out
  161. */
  162. private String getHostname() {
  163. String hostname = "localhost";
  164. try {
  165. final InetAddress localHost = InetAddress.getLocalHost();
  166. if (localHost != null) {
  167. hostname = localHost.getHostName();
  168. }
  169. } catch (final UnknownHostException e) {
  170. // fall back to default 'localhost'
  171. }
  172. return hostname;
  173. }
  174. /**
  175. * The whole testsuite ended.
  176. * @param suite the testsuite.
  177. * @throws BuildException on error.
  178. */
  179. public void endTestSuite(final JUnitTest suite) throws BuildException {
  180. rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount());
  181. rootElement.setAttribute(ATTR_FAILURES, "" + suite.failureCount());
  182. rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount());
  183. rootElement.setAttribute(ATTR_SKIPPED, "" + suite.skipCount());
  184. rootElement.setAttribute(
  185. ATTR_TIME, "" + (suite.getRunTime() / ONE_SECOND));
  186. if (out != null) {
  187. Writer wri = null;
  188. try {
  189. wri = new BufferedWriter(new OutputStreamWriter(out, "UTF8"));
  190. wri.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
  191. (new DOMElementWriter()).write(rootElement, wri, 0, " ");
  192. } catch (final IOException exc) {
  193. throw new BuildException("Unable to write log file", exc);
  194. } finally {
  195. if (wri != null) {
  196. try {
  197. wri.flush();
  198. } catch (final IOException ex) {
  199. // ignore
  200. }
  201. }
  202. if (out != System.out && out != System.err) {
  203. FileUtils.close(wri);
  204. }
  205. }
  206. }
  207. }
  208. /**
  209. * Interface TestListener.
  210. *
  211. * <p>A new Test is started.
  212. * @param t the test.
  213. */
  214. public void startTest(final Test t) {
  215. testStarts.put(createDescription(t), System.currentTimeMillis());
  216. }
  217. private static String createDescription(final Test test) throws BuildException {
  218. if (!tag.isEmpty())
  219. return JUnitVersionHelper.getTestCaseName(test) + "-" + tag +"(" + JUnitVersionHelper.getTestCaseClassName(test) + ")";
  220. return JUnitVersionHelper.getTestCaseName(test) + "(" + JUnitVersionHelper.getTestCaseClassName(test) + ")";
  221. }
  222. /**
  223. * Interface TestListener.
  224. *
  225. * <p>A Test is finished.
  226. * @param test the test.
  227. */
  228. public void endTest(final Test test) {
  229. final String testDescription = createDescription(test);
  230. // Fix for bug #5637 - if a junit.extensions.TestSetup is
  231. // used and throws an exception during setUp then startTest
  232. // would never have been called
  233. if (!testStarts.containsKey(testDescription)) {
  234. startTest(test);
  235. }
  236. Element currentTest;
  237. if (!failedTests.containsKey(test) && !skippedTests.containsKey(testDescription) && !ignoredTests.containsKey(testDescription)) {
  238. currentTest = doc.createElement(TESTCASE);
  239. String n = JUnitVersionHelper.getTestCaseName(test);
  240. if (n != null && !tag.isEmpty())
  241. n = n + "-" + tag;
  242. currentTest.setAttribute(ATTR_NAME,
  243. n == null ? UNKNOWN : n);
  244. // a TestSuite can contain Tests from multiple classes,
  245. // even tests with the same name - disambiguate them.
  246. currentTest.setAttribute(ATTR_CLASSNAME,
  247. JUnitVersionHelper.getTestCaseClassName(test));
  248. rootElement.appendChild(currentTest);
  249. testElements.put(createDescription(test), currentTest);
  250. } else {
  251. currentTest = testElements.get(testDescription);
  252. }
  253. final Long l = testStarts.get(createDescription(test));
  254. currentTest.setAttribute(ATTR_TIME,
  255. "" + ((System.currentTimeMillis() - l) / ONE_SECOND));
  256. }
  257. /**
  258. * Interface TestListener for JUnit &lt;= 3.4.
  259. *
  260. * <p>A Test failed.
  261. * @param test the test.
  262. * @param t the exception.
  263. */
  264. public void addFailure(final Test test, final Throwable t) {
  265. formatError(FAILURE, test, t);
  266. }
  267. /**
  268. * Interface TestListener for JUnit &gt; 3.4.
  269. *
  270. * <p>A Test failed.
  271. * @param test the test.
  272. * @param t the assertion.
  273. */
  274. public void addFailure(final Test test, final AssertionFailedError t) {
  275. addFailure(test, (Throwable) t);
  276. }
  277. /**
  278. * Interface TestListener.
  279. *
  280. * <p>An error occurred while running the test.
  281. * @param test the test.
  282. * @param t the error.
  283. */
  284. public void addError(final Test test, final Throwable t) {
  285. formatError(ERROR, test, t);
  286. }
  287. private void formatError(final String type, final Test test, final Throwable t) {
  288. if (test != null) {
  289. endTest(test);
  290. failedTests.put(test, test);
  291. }
  292. final Element nested = doc.createElement(type);
  293. Element currentTest;
  294. if (test != null) {
  295. currentTest = testElements.get(createDescription(test));
  296. } else {
  297. currentTest = rootElement;
  298. }
  299. currentTest.appendChild(nested);
  300. final String message = t.getMessage();
  301. if (message != null && message.length() > 0) {
  302. nested.setAttribute(ATTR_MESSAGE, t.getMessage());
  303. }
  304. nested.setAttribute(ATTR_TYPE, t.getClass().getName());
  305. final String strace = JUnitTestRunner.getFilteredTrace(t);
  306. final Text trace = doc.createTextNode(strace);
  307. nested.appendChild(trace);
  308. }
  309. private void formatOutput(final String type, final String output) {
  310. final Element nested = doc.createElement(type);
  311. rootElement.appendChild(nested);
  312. nested.appendChild(doc.createCDATASection(output));
  313. }
  314. public void testIgnored(final Test test) {
  315. formatSkip(test, JUnitVersionHelper.getIgnoreMessage(test));
  316. if (test != null) {
  317. ignoredTests.put(createDescription(test), test);
  318. }
  319. }
  320. public void formatSkip(final Test test, final String message) {
  321. if (test != null) {
  322. endTest(test);
  323. }
  324. final Element nested = doc.createElement("skipped");
  325. if (message != null) {
  326. nested.setAttribute("message", message);
  327. }
  328. Element currentTest;
  329. if (test != null) {
  330. currentTest = testElements.get(createDescription(test));
  331. } else {
  332. currentTest = rootElement;
  333. }
  334. currentTest.appendChild(nested);
  335. }
  336. public void testAssumptionFailure(final Test test, final Throwable failure) {
  337. formatSkip(test, failure.getMessage());
  338. skippedTests.put(createDescription(test), test);
  339. }
  340. } // XMLJUnitResultFormatter