• 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 /*
23  *
24  * StylesheetTestletLocalPaths.java
25  *
26  */
27 package org.apache.qetest.xsl;
28 
29 import java.io.File;
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 import java.util.Hashtable;
33 
34 import org.apache.qetest.CheckService;
35 import org.apache.qetest.Datalet;
36 import org.apache.qetest.Logger;
37 import org.apache.qetest.TestletImpl;
38 import org.apache.qetest.xslwrapper.TransformWrapper;
39 import org.apache.qetest.xslwrapper.TransformWrapperFactory;
40 
41 /**
42  * Testlet for conformance testing of xsl stylesheet files.
43  *
44  * HACK: Forces use of local pathnames.
45  *
46  * This class provides the testing algorithim used for verifying
47  * Xalan's conformance to the XSLT spec.  It works in conjunction
48  * with StylesheetTestletLocalPathsDriver, which supplies the logic for
49  * choosing the testfiles to iterate over, and with
50  * TransformWrapper, which provides an XSL  processor- and
51  * method-independent way to process files (i.e. different
52  * flavors of TransformWrapper may be different products, as well
53  * as different processing models, like SAX, DOM or Streams).
54  *
55  * @author Shane_Curcuru@lotus.com
56  * @version $Id$
57  */
58 public class StylesheetTestletLocalPaths extends TestletImpl
59 {
60     // Initialize our classname for TestletImpl's main() method
61     static { thisClassName = "org.apache.qetest.xsl.StylesheetTestletLocalPaths"; }
62 
63     // Initialize our defaultDatalet
64     { defaultDatalet = (Datalet)new StylesheetDatalet(); }
65 
66     /**
67      * Accesor method for a brief description of this test.
68      *
69      * @return String describing what this StylesheetTestletLocalPaths does.
70      */
getDescription()71     public String getDescription()
72     {
73         return "StylesheetTestletLocalPaths";
74     }
75 
76 
77     /**
78      * Run this StylesheetTestletLocalPaths: execute it's test and return.
79      *
80      * @param Datalet to use as data point for the test.
81      */
execute(Datalet d)82     public void execute(Datalet d)
83 	{
84         StylesheetDatalet datalet = null;
85         try
86         {
87             datalet = (StylesheetDatalet)d;
88         }
89         catch (ClassCastException e)
90         {
91             logger.checkErr("Datalet provided is not a StylesheetDatalet; cannot continue with " + d);
92             return;
93         }
94 
95         logger.logMsg(Logger.STATUSMSG, "About to test: "
96                       + (null == datalet.inputName
97                          ? datalet.xmlName
98                          : datalet.inputName));
99         //@todo validate our Datalet - ensure it has valid
100         //  and/or existing files available.
101 
102         // Cleanup outName only if asked to - delete the file on disk
103         // Optimization: this takes extra time and often is not
104         //  needed, so only do this if the option is set
105         if ("true".equalsIgnoreCase(datalet.options.getProperty("deleteOutFile")))
106         {
107             try
108             {
109                 boolean btmp = (new File(datalet.outputName)).delete();
110                 logger.logMsg(Logger.TRACEMSG, "Deleting OutFile of::" + datalet.outputName
111                                      + " status: " + btmp);
112             }
113             catch (SecurityException se)
114             {
115                 logger.logMsg(Logger.WARNINGMSG, "Deleting OutFile of::" + datalet.outputName
116                                        + " threw: " + se.toString());
117                 // But continue anyways...
118             }
119         }
120 
121         // Create a new TransformWrapper of appropriate flavor
122         //  null arg is unused liaison for TransformWrapper
123         //@todo allow user to pass in pre-created
124         //  TransformWrapper so we don't have lots of objects
125         //  created and destroyed for every file
126         TransformWrapper transformWrapper = null;
127         try
128         {
129             transformWrapper = TransformWrapperFactory.newWrapper(datalet.flavor);
130             transformWrapper.newProcessor(null);
131         }
132         catch (Throwable t)
133         {
134             logThrowable(t, getDescription() + " newWrapper/newProcessor threw");
135             logger.checkErr(getDescription() + " newWrapper/newProcessor threw: " + t.toString());
136             return;
137         }
138 
139         // Test our supplied input file, and compare with gold
140         try
141         {
142             // Store local copies of XSL, XML references for
143             //  potential change to URLs
144             String inputName = datalet.inputName;
145             String xmlName = datalet.xmlName;
146 
147             // * HACK: Forces use of local pathnames.
148 
149             //@todo Should we log a custom logElement here instead?
150             logger.logMsg(Logger.TRACEMSG, "executing with: inputName=" + inputName
151                           + " xmlName=" + xmlName + " outputName=" + datalet.outputName
152                           + " goldName=" + datalet.goldName + " flavor="  + datalet.flavor);
153 
154             // Simply have the wrapper do all the transforming
155             //  or processing for us - we handle either normal .xsl
156             //  stylesheet tests or just .xml embedded tests
157             long retVal = 0L;
158             if (null == datalet.inputName)
159             {
160                 // presume it's an embedded test
161                 long [] times = transformWrapper.transformEmbedded(xmlName, datalet.outputName);
162                 retVal = times[TransformWrapper.IDX_OVERALL];
163             }
164             else
165             {
166                 // presume it's a normal stylesheet test
167                 long[] times = transformWrapper.transform(xmlName, inputName, datalet.outputName);
168                 retVal = times[TransformWrapper.IDX_OVERALL];
169             }
170 
171             // If we get here, attempt to validate the contents of
172             //  the last outputFile created
173             CheckService fileChecker = (CheckService)datalet.options.get("fileCheckerImpl");
174             // Supply default value
175             if (null == fileChecker)
176                 fileChecker = new XHTFileCheckService();
177             if (Logger.PASS_RESULT
178                 != fileChecker.check(logger,
179                                      new File(datalet.outputName),
180                                      new File(datalet.goldName),
181                                      getDescription() + " " + datalet.getDescription())
182                )
183             {
184                 // Log a custom element with all the file refs first
185                 // Closely related to viewResults.xsl select='fileref"
186                 //@todo check that these links are valid when base
187                 //  paths are either relative or absolute!
188                 Hashtable attrs = new Hashtable();
189                 attrs.put("idref", (new File(datalet.inputName)).getName());
190                 attrs.put("inputName", datalet.inputName);
191                 attrs.put("xmlName", datalet.xmlName);
192                 attrs.put("outputName", datalet.outputName);
193                 attrs.put("goldName", datalet.goldName);
194                 logger.logElement(Logger.STATUSMSG, "fileref", attrs, "Conformance test file references");
195                 // Then log the failure reason
196                 logger.logArbitrary(Logger.STATUSMSG, (new File(datalet.inputName)).getName()
197                                     + " failure reason: " + fileChecker.getExtendedInfo());
198             }
199         }
200         // Note that this class can only validate positive test
201         //  cases - we don't handle ExpectedExceptions
202         catch (Throwable t)
203         {
204             // Put the logThrowable first, so it appears before
205             //  the Fail record, and gets color-coded
206             logThrowable(t, getDescription() + " " + datalet.getDescription());
207             logger.checkFail(getDescription() + " " + datalet.getDescription()
208                              + " threw: " + t.toString());
209             return;
210         }
211 	}
212 
213 
214     /**
215      * Logs out throwable.toString() and stack trace to our Logger.
216      * //@todo Copied from Reporter; should probably be moved into Logger.
217      * @param throwable thrown throwable/exception to log out.
218      * @param msg description of the throwable.
219      */
logThrowable(Throwable throwable, String msg)220     protected void logThrowable(Throwable throwable, String msg)
221     {
222         StringWriter sWriter = new StringWriter();
223         sWriter.write(msg + "\n");
224 
225         PrintWriter pWriter = new PrintWriter(sWriter);
226         throwable.printStackTrace(pWriter);
227 
228         logger.logArbitrary(Logger.STATUSMSG, sWriter.toString());
229     }
230 }  // end of class StylesheetTestletLocalPaths
231 
232