• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  "License");
7  * you may not use this file except in compliance with the License.
8  * 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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id$
20  */
21 
22 package org.apache.qetest.xsl;
23 import java.io.File;
24 import java.io.FileNotFoundException;
25 import java.io.FileOutputStream;
26 import java.io.FilenameFilter;
27 import java.io.PrintWriter;
28 
29 import javax.xml.transform.Templates;
30 import javax.xml.transform.Transformer;
31 import javax.xml.transform.TransformerException;
32 import javax.xml.transform.TransformerFactory;
33 import javax.xml.transform.stream.StreamResult;
34 import javax.xml.transform.stream.StreamSource;
35 
36 /**
37  * Scans a directory tree of result.xml and assorted files
38  * and creates a rolled-up overview of test problems.
39  *
40  * <p>Currently fairly tightly coupled to it's stylesheet and to
41  * XMLFileLogger and Reporter.  Scans a directory tree (default is
42  * results-alltest) looking for Pass-/Fail-*.xml results marker
43  * files from test runs.  Then runs the stylesheet over those,
44  * which produces a single output .html file that lists just fails
45  * and related messages.</p>
46  *
47  * @author shane_curcuru@lotus.com
48  * @version $Id$
49  */
50 public class ResultScanner
51 {
52 
53     /**
54      * Scan a directory tree for result files and create report.
55      *
56      * @param resultDir directory to start scanning in
57      * @param baseName of output filename (.xml/.html added)
58      * @throws any underlying exceptions, including
59      * FileNotFoundException if if can't find any results
60      */
scanResults(String resultName, String baseName)61     public void scanResults(String resultName, String baseName)
62             throws Exception
63     {
64         File resultDir = new File(resultName);
65         if (!resultDir.exists() || !resultDir.isDirectory())
66         {
67             throw new FileNotFoundException("ResultScanner: resultDir " + resultDir + " does not exist!");
68         }
69 
70         // Create file to hold list of all results found
71         String listFilename = baseName + ".xml";
72         FileOutputStream fos = new FileOutputStream(listFilename);
73         PrintWriter writer = new PrintWriter(fos);
74 
75         // Scan for result files in the dir tree
76         try
77         {
78             logStartTag(writer, listFilename);
79             scanDir(resultDir, writer, 1);  // 1 = starting recursion
80         }
81         catch (Exception e)
82         {
83             logError(writer, "scanResults threw: " + e.toString());
84         }
85         finally
86         {
87             logEndTag(writer);
88             writer.close();
89         }
90 
91         // Transform the list into a master overview of fails
92         transformScan(resultDir, listFilename, baseName + ".html");
93     }
94 
95 
96     /**
97      * Scan a directory tree for result files and create report.
98      *
99      *
100      * @param resultDir directory to start scanning in
101      * @param writer to println results to
102      * @param recursion depth of this method
103      * @throws any underlying exceptions, including
104      * FileNotFoundException if if can't find any results
105      */
scanDir(File resultDir, PrintWriter writer, int depth)106     protected void scanDir(File resultDir, PrintWriter writer, int depth)
107             throws Exception
108     {
109         depth++;
110         if (depth > MAX_DEPTH)
111         {
112             logError(writer, "scanDir: MAX_DEPTH exceeded, returning!");
113             return;
114         }
115 
116         if (!resultDir.exists() || !resultDir.isDirectory())
117         {
118             logError(writer, "scanDir: attempt to scan non-directory, returning!");
119             return;
120         }
121 
122         // Get list of teststatus files that definitely have problems
123         String badResults[] = resultDir.list(
124                 new FilenameFilter() // anonymous class
125                 {
126                     public boolean accept(File dir, String name)
127                     {
128                         // Shortcuts for bogus filenames and dirs
129                         if (name == null || dir == null)
130                             return false;
131                         // Skip already-rolledup Harness reports
132                         if (name.endsWith("Harness.xml"))
133                             return false;
134                         return (name.startsWith("Fail-")
135                                 || name.startsWith("Errr-")
136                                 || name.startsWith("Incp-"));
137                     }
138                 }
139             );
140 
141         // Get list of teststatus files that passed or were
142         //  ambiguous, which means they didn't fail
143         String okResults[] = resultDir.list(
144                 new FilenameFilter() // anonymous class
145                 {
146                     public boolean accept(File dir, String name)
147                     {
148                         // Shortcuts for bogus filenames and dirs
149                         if (name == null || dir == null)
150                             return false;
151                         return (name.startsWith("Pass-")
152                                 || name.startsWith("Ambg-"));
153                     }
154                 }
155             );
156 
157         // Output references to both sets of files if needed
158         if ((null != okResults) && (null != badResults)
159             && (okResults.length + badResults.length > 0))
160         {
161             logTestGroup(writer, resultDir.getPath(), okResults, badResults);
162         }
163 
164         // Traverse down directories
165         String subdirs[] = resultDir.list(
166                 new FilenameFilter() // anonymous class
167                 {
168                     public boolean accept(File dir, String name)
169                     {
170                         // Shortcuts for bogus filenames and dirs and CVS junk
171                         if (null == name || null == dir || "CVS".equals(name))
172                             return false;
173                         return (new File(dir, name)).isDirectory();
174                     }
175                 }
176             );
177         if (null != subdirs)
178         {
179             for (int i=0; i < subdirs.length; i++)
180             {
181                 scanDir(new File(resultDir, subdirs[i]), writer, depth + 1);
182             }
183         }
184 
185     }
186 
187 
188     /**
189      * Transform a resultfilelist into a real report.
190      *
191      *
192      * @param resultDir directory to start scanning in
193      * @param filename name of listfile
194      * @throws any underlying exceptions
195      */
transformScan(File resultDir, String xmlName, String outName)196     protected void transformScan(File resultDir, String xmlName, String outName)
197             throws TransformerException
198     {
199         Templates templates = getTemplates();
200         Transformer transformer = templates.newTransformer();
201         transformer.transform(new StreamSource(xmlName),
202                               new StreamResult(outName));
203     }
204 
205 
206     /**
207      * Find the appropriate stylesheet to use.
208      *
209      * Worker method for future expansion
210      *
211      * @return Templates object to use for transform
212      * @throws any underlying TransformerException
213      */
getTemplates()214     public Templates getTemplates()
215             throws TransformerException
216     {
217         //@todo assumption: it's in current dir
218         String xslName = "ResultScanner.xsl";
219         StreamSource xslSource = new StreamSource(xslName);
220         TransformerFactory factory = TransformerFactory.newInstance();
221         return factory.newTemplates(xslSource);
222     }
223 
224 
225     /**
226      * Write an xml decl and start tag to our list file.
227      *
228      * @param writer where to write to
229      */
logStartTag(PrintWriter writer, String name)230     public static void logStartTag(PrintWriter writer, String name)
231     {
232         writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
233         writer.println("<resultfilelist logFile=\"" + name + "\">");
234         writer.flush();
235     }
236 
237 
238     /**
239      * Write the end tag to our list file.
240      *
241      * @param writer where to write to
242      */
logEndTag(PrintWriter writer)243     public static void logEndTag(PrintWriter writer)
244     {
245         writer.println("</resultfilelist>");
246         writer.flush();
247     }
248 
249 
250     /**
251      * Write an group of tests to our list file.
252      *
253      * @param writer where to write to
254      * @param base basedir where these are found
255      * @param okTests list of passing tests to write
256      * @param badTests list of failing tests to write
257      */
logTestGroup(PrintWriter writer, String base, String[] okTests, String[] badTests)258     public static void logTestGroup(PrintWriter writer, String base,
259             String[] okTests, String[] badTests)
260     {
261         writer.println("<testgroup href=\"" + base + "\" >");
262         if ((null != okTests) && (okTests.length > 0))
263         {
264             for (int i = 0; i < okTests.length; i++)
265             {
266                 writer.println("<teststatus href=\"" + okTests[i] + "\" status=\"ok\" />");
267             }
268         }
269         if ((null != badTests) && (badTests.length > 0))
270         {
271             for (int i = 0; i < badTests.length; i++)
272             {
273                 writer.println("<teststatus href=\"" + badTests[i] + "\" status=\"notok\" />");
274             }
275         }
276         writer.println("</testgroup>");
277     }
278 
279 
280     /**
281      * Write an error message to our list file.
282      *
283      * @param writer where to write to
284      * @param error string to write out
285      */
logError(PrintWriter writer, String error)286     public static void logError(PrintWriter writer, String error)
287     {
288         writer.println("<error>" + error + "</error>");
289         writer.flush();
290     }
291 
292 
293     /**
294      * Defensive coding: limit directory depth recursion.
295      */
296     protected static final int MAX_DEPTH = 10;
297 
298 
299     /**
300      * Bottleneck output for future redirection.
301      */
302     protected PrintWriter outWriter = new PrintWriter(System.out);
303 
304 
305     /**
306      * Main method to run from the command line; sample usage.
307      * @param args cmd line arguments
308      */
main(String[] args)309     public static void main(String[] args)
310     {
311         String resultDir = "results-alltest";
312         if (args.length >= 1)
313         {
314             resultDir = args[0];
315         }
316         String logFile = resultDir + File.separator + "ResultReport";
317         if (args.length >= 2)
318         {
319             logFile = args[1];
320         }
321         //@todo add more arguments; filtering, options
322         //  to pass to stylesheets etc.
323         try
324         {
325             ResultScanner app = new ResultScanner();
326             app.scanResults(resultDir, logFile);
327             System.out.println("ResultScanner of " + resultDir + " complete in: " + logFile + ".html");
328         }
329         catch (Exception e)
330         {
331             System.out.println("ResultScanner error on: " + resultDir);
332             e.printStackTrace();
333         }
334     }
335 
336 }
337