KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > mavenplugins > geronimo > reporting > SurefireReporter


1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */

19
20 package org.apache.geronimo.mavenplugins.geronimo.reporting;
21
22 import java.io.BufferedInputStream JavaDoc;
23 import java.io.BufferedWriter JavaDoc;
24 import java.io.File JavaDoc;
25 import java.io.FileInputStream JavaDoc;
26 import java.io.FileNotFoundException JavaDoc;
27 import java.io.FileOutputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.InputStream JavaDoc;
30 import java.io.OutputStreamWriter JavaDoc;
31 import java.io.PrintWriter JavaDoc;
32 import java.io.UnsupportedEncodingException JavaDoc;
33 import java.io.FileWriter JavaDoc;
34 import java.text.NumberFormat JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.util.Collections JavaDoc;
37 import java.util.Enumeration JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.List JavaDoc;
40 import java.util.Locale JavaDoc;
41 import java.util.Properties JavaDoc;
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 /**
56  * A reporter that generates Surefire result data, so the Surefire report can be used.
57  *
58  * @version $Rev: 476061 $ $Date: 2006-11-17 01:36:50 -0500 (Fri, 17 Nov 2006) $
59  */

60 public class SurefireReporter
61     implements Reporter
62 {
63     private static final Log log = LogFactory.getLog(SurefireReporter.class);
64
65     private static final String JavaDoc LS = System.getProperty("line.separator");
66
67     /**
68      * The name of the test (goal name).
69      */

70     private String JavaDoc testName;
71
72     /**
73      * The input log file, may or may not exist.
74      */

75     private File JavaDoc logFile;
76
77     /**
78      * The failure cause.
79      */

80     private Throwable JavaDoc failureCause;
81
82     /**
83      * @parameter expression="${project.build.directory}/surefire-reports"
84      */

85     private File JavaDoc reportsDirectory = null;
86     
87     /**
88      * The file where the test output text will be written.
89      */

90     private File JavaDoc outputFile;
91
92     /**
93      * The file where the text result xml will be written.
94      */

95     private File JavaDoc reportFile;
96
97     /**
98      * The time when the test started.
99      */

100     private long startTime;
101
102     /**
103      * The number of errors.
104      */

105     private int numErrors = 0;
106
107     private static final int MS_PER_SEC = 1000;
108
109     private NumberFormat JavaDoc numberFormat = NumberFormat.getInstance(Locale.ENGLISH);
110
111     private List JavaDoc results = Collections.synchronizedList(new ArrayList JavaDoc());
112
113     //
114
// Reporter
115
//
116

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 JavaDoc e) {
128             //
129
// HACK: Maybe need to add a throws to beginReport() ?
130
//
131

132             log.error("Failed to make reports directory: " + reportsDirectory, e);
133         }
134
135         outputFile = new File JavaDoc(reportsDirectory, testName + ".txt");
136         reportFile = new File JavaDoc(reportsDirectory, "TEST-" + testName + ".xml");
137         if (reportFile.exists()) {
138             reportFile.delete();
139         }
140     }
141
142     public void reportError(final Throwable JavaDoc 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 JavaDoc e) {
157             log.warn("Failed to update outputFile", e);
158         }
159         
160         if (failureCause != null) {
161             try {
162                 boolean append = outputFile.exists();
163                 PrintWriter JavaDoc writer = new PrintWriter JavaDoc(new BufferedWriter JavaDoc(new FileWriter JavaDoc(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 JavaDoc 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     //
193
// Surefire Support
194
//
195

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 JavaDoc i = results.iterator(); i.hasNext();) {
209             Xpp3Dom testcase = (Xpp3Dom) i.next();
210             testSuite.addChild(testcase);
211         }
212
213         PrintWriter JavaDoc writer = null;
214
215         try {
216             writer = new PrintWriter JavaDoc(new BufferedWriter JavaDoc(new OutputStreamWriter JavaDoc(new FileOutputStream JavaDoc(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 JavaDoc e) {
221             throw new ReporterException("Unable to use UTF-8 encoding", e);
222         }
223         catch (FileNotFoundException JavaDoc 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 JavaDoc element, String JavaDoc 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 JavaDoc 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 JavaDoc input = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(outputFile));
257             int length = input.available();
258             byte[] b = new byte[length];
259             input.read(b, 0, length);
260             writeTestProblems(testName, new String JavaDoc(b));
261         }
262         catch (IOException JavaDoc e) {
263             log.error("Failed to write test problems", e);
264         }
265     }
266
267     private void writeTestProblems(String JavaDoc testName, String JavaDoc 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     /**
281      * Adds system properties to the XML report.
282      */

283     private void showProperties(Xpp3Dom testSuite) {
284         Xpp3Dom properties = createElement(testSuite, "properties");
285
286         Properties JavaDoc systemProperties = System.getProperties();
287
288         if (systemProperties != null) {
289             Enumeration JavaDoc propertyKeys = systemProperties.propertyNames();
290
291             while (propertyKeys.hasMoreElements()) {
292                 String JavaDoc key = (String JavaDoc) propertyKeys.nextElement();
293                 String JavaDoc 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 JavaDoc escapeAttribute(String JavaDoc attribute) {
308         // Shouldn't Xpp3Dom do this itself?
309
String JavaDoc s = StringUtils.replace(attribute, "<", "&lt;");
310         return StringUtils.replace(s, ">", "&gt;");
311     }
312
313     private Iterator JavaDoc getResults() {
314         return results.iterator();
315     }
316
317     private String JavaDoc elapsedTimeAsString(long runTime) {
318         return numberFormat.format((double) runTime / MS_PER_SEC);
319     }
320
321     /**
322      * Gets the messages following the exception type.
323      */

324     private String JavaDoc getMessage(String JavaDoc stdErr) {
325         int beginMarker = stdErr.indexOf("Exception:") + 10;
326         int endMarker = stdErr.indexOf("\n", beginMarker);
327         return stdErr.substring(beginMarker, endMarker);
328     }
329
330     /**
331      * Gets the type of exception from the stacktrace.
332      */

333     private String JavaDoc getType(String JavaDoc 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     /**
340      * The generated reports xml file for surefire..
341      *
342      * @return generated reports xml file
343      */

344     public File JavaDoc getReportsFile() {
345         return this.reportFile;
346     }
347
348     /**
349      * The text file which holds the stdout or stderr.
350      *
351      * @return File
352      */

353     public File JavaDoc getOutputFile() {
354         return this.outputFile;
355     }
356 }
357
Popular Tags