1 19 20 package org.apache.geronimo.mavenplugins.geronimo.reporting; 21 22 import java.io.BufferedInputStream ; 23 import java.io.BufferedWriter ; 24 import java.io.File ; 25 import java.io.FileInputStream ; 26 import java.io.FileNotFoundException ; 27 import java.io.FileOutputStream ; 28 import java.io.IOException ; 29 import java.io.InputStream ; 30 import java.io.OutputStreamWriter ; 31 import java.io.PrintWriter ; 32 import java.io.UnsupportedEncodingException ; 33 import java.io.FileWriter ; 34 import java.text.NumberFormat ; 35 import java.util.ArrayList ; 36 import java.util.Collections ; 37 import java.util.Enumeration ; 38 import java.util.Iterator ; 39 import java.util.List ; 40 import java.util.Locale ; 41 import java.util.Properties ; 42 43 import org.apache.commons.logging.Log; 44 import org.apache.commons.logging.LogFactory; 45 46 import org.apache.maven.surefire.report.ReporterException; 47 import org.apache.maven.surefire.util.PrettyPrintXMLWriter; 48 49 import org.codehaus.plexus.util.FileUtils; 50 import org.codehaus.plexus.util.IOUtil; 51 import org.codehaus.plexus.util.StringUtils; 52 import org.codehaus.plexus.util.xml.Xpp3Dom; 53 import org.codehaus.plexus.util.xml.Xpp3DomWriter; 54 55 60 public class SurefireReporter 61 implements Reporter 62 { 63 private static final Log log = LogFactory.getLog(SurefireReporter.class); 64 65 private static final String LS = System.getProperty("line.separator"); 66 67 70 private String testName; 71 72 75 private File logFile; 76 77 80 private Throwable failureCause; 81 82 85 private File reportsDirectory = null; 86 87 90 private File outputFile; 91 92 95 private File reportFile; 96 97 100 private long startTime; 101 102 105 private int numErrors = 0; 106 107 private static final int MS_PER_SEC = 1000; 108 109 private NumberFormat numberFormat = NumberFormat.getInstance(Locale.ENGLISH); 110 111 private List results = Collections.synchronizedList(new ArrayList ()); 112 113 117 public void reportBegin(final Reportable source) { 118 assert source != null; 119 120 logFile = source.getLogFile(); 121 testName = source.getName(); 122 startTime = source.getStartTime().getTime(); 123 124 try { 125 FileUtils.forceMkdir(reportsDirectory); 126 } 127 catch (IOException e) { 128 132 log.error("Failed to make reports directory: " + reportsDirectory, e); 133 } 134 135 outputFile = new File (reportsDirectory, testName + ".txt"); 136 reportFile = new File (reportsDirectory, "TEST-" + testName + ".xml"); 137 if (reportFile.exists()) { 138 reportFile.delete(); 139 } 140 } 141 142 public void reportError(final Throwable cause) { 143 assert cause != null; 144 145 log.debug("Capturing failed report from cause", cause); 146 147 this.failureCause = cause; 148 } 149 150 public void reportEnd() { 151 try { 152 if (logFile.exists()) { 153 FileUtils.copyFile(logFile, outputFile); 154 } 155 } 156 catch (Exception e) { 157 log.warn("Failed to update outputFile", e); 158 } 159 160 if (failureCause != null) { 161 try { 162 boolean append = outputFile.exists(); 163 PrintWriter writer = new PrintWriter (new BufferedWriter (new FileWriter (outputFile, append))); 164 try { 165 writer.println("Exception Detail"); 166 writer.println("================"); 167 failureCause.printStackTrace(writer); 168 writer.flush(); 169 } 170 finally { 171 writer.close(); 172 } 173 } 174 catch (Exception e) { 175 log.warn("Failed to append error detail to outputFile", e); 176 } 177 178 testFailed(); 179 } 180 else { 181 testSucceeded(); 182 } 183 184 try { 185 testSetCompleted(); 186 } 187 catch (ReporterException e) { 188 log.warn("Failed to set test completed", e); 189 } 190 } 191 192 196 private void testSetCompleted() throws ReporterException { 197 long runTime = System.currentTimeMillis() - this.startTime; 198 199 Xpp3Dom testSuite = createTestElement("testsuite", testName, runTime); 200 201 showProperties(testSuite); 202 203 testSuite.setAttribute("tests", "1"); 204 testSuite.setAttribute("errors", String.valueOf(numErrors)); 205 testSuite.setAttribute("skipped", "0"); 206 testSuite.setAttribute("failures", "0"); 207 208 for (Iterator i = results.iterator(); i.hasNext();) { 209 Xpp3Dom testcase = (Xpp3Dom) i.next(); 210 testSuite.addChild(testcase); 211 } 212 213 PrintWriter writer = null; 214 215 try { 216 writer = new PrintWriter (new BufferedWriter (new OutputStreamWriter (new FileOutputStream (reportFile), "UTF-8"))); 217 writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + LS); 218 Xpp3DomWriter.write(new PrettyPrintXMLWriter(writer), testSuite); 219 } 220 catch (UnsupportedEncodingException e) { 221 throw new ReporterException("Unable to use UTF-8 encoding", e); 222 } 223 catch (FileNotFoundException e) { 224 throw new ReporterException("Unable to create file: " + e.getMessage(), e); 225 } 226 finally { 227 IOUtil.close(writer); 228 } 229 } 230 231 private Xpp3Dom createTestElement(String element, String testName, long runTime) { 232 Xpp3Dom testCase = new Xpp3Dom(element); 233 testCase.setAttribute("name", testName); 234 testCase.setAttribute("time", elapsedTimeAsString(runTime)); 235 236 return testCase; 237 } 238 239 private Xpp3Dom createElement(Xpp3Dom element, String testName) { 240 Xpp3Dom component = new Xpp3Dom(testName); 241 element.addChild(component); 242 243 return component; 244 } 245 246 private void testSucceeded() { 247 long runTime = System.currentTimeMillis() - this.startTime; 248 Xpp3Dom testCase = createTestElement("testcase", testName, runTime); 249 results.add(testCase); 250 } 251 252 private void testFailed() { 253 ++numErrors; 254 255 try { 256 InputStream input = new BufferedInputStream (new FileInputStream (outputFile)); 257 int length = input.available(); 258 byte[] b = new byte[length]; 259 input.read(b, 0, length); 260 writeTestProblems(testName, new String (b)); 261 } 262 catch (IOException e) { 263 log.error("Failed to write test problems", e); 264 } 265 } 266 267 private void writeTestProblems(String testName, String stdErr) { 268 long runTime = System.currentTimeMillis() - this.startTime; 269 270 Xpp3Dom testCase = createTestElement("testcase", testName, runTime); 271 Xpp3Dom element = createElement(testCase, "failure"); 272 273 element.setAttribute("message", escapeAttribute(getMessage(stdErr))); 274 element.setAttribute("type", getType(stdErr)); 275 element.setValue(stdErr); 276 277 results.add(testCase); 278 } 279 280 283 private void showProperties(Xpp3Dom testSuite) { 284 Xpp3Dom properties = createElement(testSuite, "properties"); 285 286 Properties systemProperties = System.getProperties(); 287 288 if (systemProperties != null) { 289 Enumeration propertyKeys = systemProperties.propertyNames(); 290 291 while (propertyKeys.hasMoreElements()) { 292 String key = (String ) propertyKeys.nextElement(); 293 String value = systemProperties.getProperty(key); 294 295 if (value == null) { 296 value = "null"; 297 } 298 299 Xpp3Dom property = createElement(properties, "property"); 300 301 property.setAttribute("name", key); 302 property.setAttribute("value", escapeAttribute(value)); 303 } 304 } 305 } 306 307 private static String escapeAttribute(String attribute) { 308 String s = StringUtils.replace(attribute, "<", "<"); 310 return StringUtils.replace(s, ">", ">"); 311 } 312 313 private Iterator getResults() { 314 return results.iterator(); 315 } 316 317 private String elapsedTimeAsString(long runTime) { 318 return numberFormat.format((double) runTime / MS_PER_SEC); 319 } 320 321 324 private String getMessage(String stdErr) { 325 int beginMarker = stdErr.indexOf("Exception:") + 10; 326 int endMarker = stdErr.indexOf("\n", beginMarker); 327 return stdErr.substring(beginMarker, endMarker); 328 } 329 330 333 private String getType(String stdErr) { 334 int endMarker = stdErr.indexOf("Exception:") + 9; 335 int beginMarker = stdErr.lastIndexOf("\n", endMarker) + 1; 336 return stdErr.substring(beginMarker, endMarker); 337 } 338 339 344 public File getReportsFile() { 345 return this.reportFile; 346 } 347 348 353 public File getOutputFile() { 354 return this.outputFile; 355 } 356 } 357 | Popular Tags |