• 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.trax;
23 
24 import java.io.File;
25 import java.io.FileOutputStream;
26 import java.util.Enumeration;
27 import java.util.Hashtable;
28 import java.util.Properties;
29 import java.util.Vector;
30 
31 import javax.xml.transform.Templates;
32 import javax.xml.transform.Transformer;
33 import javax.xml.transform.TransformerFactory;
34 import javax.xml.transform.stream.StreamResult;
35 import javax.xml.transform.stream.StreamSource;
36 
37 import org.apache.qetest.FileBasedTest;
38 import org.apache.qetest.Logger;
39 import org.apache.qetest.OutputNameManager;
40 import org.apache.qetest.QetestUtils;
41 import org.apache.qetest.xsl.XSLTestfileInfo;
42 import org.apache.qetest.xslwrapper.TransformWrapper;
43 import org.apache.qetest.xslwrapper.TransformWrapperFactory;
44 import org.apache.qetest.xslwrapper.TransformWrapperHelper;
45 
46 /**
47  * Minitest - developer check-in test for Xalan-J 2.x.
48  *
49  * <p>Developers should always run either the minitest or smoketest
50  * target before checking any code into the xml-xalan CVS
51  * repository.  Running the minitest before checking in ensures
52  * that the Xalan CVS tree will always be in a compileable and
53  * at least basically functional state, thus ensuring a workable
54  * product for your fellow Xalan developers.  Ensuring your code
55  * passes the smoketest target will also help the nightly GUMP
56  * runs to pass the smoketest as well and avoid 'nag' emails.</p>
57  *
58  * <p>If you really need to make a checkin that will temporarily
59  * break or fail the minitest, then <b>please</b> be sure to send
60  * email to xalan-dev@xml.apache.org letting everyone know.</p>
61  *
62  * <p>For more information, please see the
63  * <a href="http://xml.apache.org/xalan-j/test/overview.html">
64  * testing docs</a> and the nightly
65  * <a href="http://jakarta.apache.org/builds/gump/">
66  * GUMP build page</a>.</p>
67  *
68  * @author shane_curcuru@us.ibm.com
69  * @version $Id$
70  */
71 public class Minitest extends FileBasedTest
72 {
73 
74     /**
75      * Provides nextName(), currentName() functionality for tests
76      * that may produce any number of output files.
77      */
78     protected OutputNameManager outNames;
79 
80     /**
81      * Basic output name root used throughout tests.
82      */
83     protected String baseOutName;
84 
85     /** The Minitest.xsl/.xml file; note goldName is version-specific.  */
86     protected XSLTestfileInfo testFileInfo = new XSLTestfileInfo();
87 
88     /** The MinitestParam.xsl/.xml file.  */
89     protected XSLTestfileInfo paramFileInfo = new XSLTestfileInfo();
90 
91     /** The MinitestPerf.xsl/.xml file.  */
92     protected XSLTestfileInfo perfFileInfo = new XSLTestfileInfo();
93 
94 
95     /** Constants matching parameter names/values in paramFileInfo.  */
96     public static final String PARAM1S = "param1s";
97     public static final String PARAM2S = "param2s";
98     public static final String PARAM1N = "param1n";
99     public static final String PARAM2N = "param2n";
100 
101     /** Just initialize test name, comment, numTestCases. */
Minitest()102     public Minitest()
103     {
104         numTestCases = 5;  // REPLACE_num
105         testName = "Minitest";
106         testComment = "Minitest - developer check-in test for Xalan-J 2.x.";
107     }
108 
109 
110     /**
111      * Initialize this test - Set names of xml/xsl test files, etc.
112      *
113      * Also cleans up any Pass-Minitest.xml file that is checked
114      * for in test.properties' minitest.passfile and generated by
115      * Reporter.writeResultsStatus().
116      *
117      * @param p Properties to initialize from (if needed)
118      * @return false if we should abort the test; true otherwise
119      * @see Reporter.writeResultsStatus(boolean)
120      */
doTestFileInit(Properties p)121     public boolean doTestFileInit(Properties p)
122     {
123         // Used for all tests; just dump files in outputDir
124         File outSubDir = new File(outputDir);
125         if (!outSubDir.mkdirs())
126         {
127             if (!outSubDir.exists())
128                 reporter.logErrorMsg("Problem creating output dir: " + outSubDir);
129         }
130         // Initialize an output name manager to that dir with .out extension
131         baseOutName = outputDir + File.separator + testName;
132         outNames = new OutputNameManager(baseOutName, ".out");
133 
134         String testBasePath = inputDir
135                               + File.separator;
136         String goldBasePath = goldDir
137                               + File.separator;
138 
139         testFileInfo.inputName = testBasePath + "Minitest.xsl";
140         testFileInfo.xmlName = testBasePath + "Minitest.xml";
141         // Use separate output files for different versions, since
142         //  some indenting rules are implemented differently 1.x/2.x
143         testFileInfo.goldName = goldBasePath + "Minitest-xalanj2.out";
144         testFileInfo.description = "General minitest, covers many xsl: elems";
145 
146         paramFileInfo.inputName = testBasePath + "MinitestParam.xsl";
147         paramFileInfo.xmlName = testBasePath + "MinitestParam.xml";
148         paramFileInfo.goldName = goldBasePath + "MinitestParam.out";
149         paramFileInfo.description = "Simple string and int params";
150 
151         perfFileInfo.inputName = testBasePath + "MinitestPerf.xsl";
152         perfFileInfo.xmlName = testBasePath + "MinitestPerf.xml";
153         perfFileInfo.goldName = goldBasePath + "MinitestPerf.out";
154         perfFileInfo.description = "Simple performance test";
155 
156         try
157         {
158             // Clean up any Pass files for the minitest that exist
159             //@see Reporter.writeResultsStatus(boolean)
160             String logFileBase = (new File(testProps.getProperty(Logger.OPT_LOGFILE, "ResultsSummary.xml"))).getAbsolutePath();
161             logFileBase = (new File(logFileBase)).getParent();
162 
163             File f = new File(logFileBase, Logger.PASS + "-" + testName + ".xml");
164             reporter.logTraceMsg("Deleting previous file: " + f);
165             f.delete();
166         }
167         catch (Exception e)
168         {
169             reporter.logThrowable(reporter.ERRORMSG, e, "Deleting Pass-Minitest file threw");
170             reporter.logErrorMsg("Deleting Pass-Minitest file threw: " + e.toString());
171         }
172 
173         return true;
174     }
175 
176 
177     /**
178      * Basic systemId transforms and params plus API coverage.
179      *
180      * @return false if we should abort the test; true otherwise
181      */
testCase1()182     public boolean testCase1()
183     {
184         reporter.testCaseInit("Basic systemId transforms and params plus API coverage");
185 
186         TransformerFactory factory = null;
187         Templates templates = null;
188         Transformer transformer = null;
189         try
190         {
191             factory = TransformerFactory.newInstance();
192             templates = factory.newTemplates(new StreamSource(QetestUtils.filenameToURL(testFileInfo.inputName)));
193             reporter.check((templates != null), true, "factory.newTemplates(StreamSource) is non-null");
194         }
195         catch (Throwable t)
196         {
197             reporter.logThrowable(reporter.ERRORMSG, t,
198                                   "Problem creating Templates; cannot continue testcase");
199             reporter.checkErr("Problem creating Templates; cannot continue testcase");
200             return true;
201         }
202         try
203         {
204             // Validate a systemId transform
205             reporter.logTraceMsg("Basic stream transform(1)(" + QetestUtils.filenameToURL(testFileInfo.xmlName) + ", "
206                                  + QetestUtils.filenameToURL(testFileInfo.inputName)  + ", "
207                                  + outNames.nextName());
208             transformer = templates.newTransformer();
209             FileOutputStream fos = new FileOutputStream(outNames.currentName());
210             transformer.transform(new StreamSource(QetestUtils.filenameToURL(testFileInfo.xmlName)),
211                                   new StreamResult(fos));
212             fos.close();
213             int fileCheckStatus = fileChecker.check(reporter,
214                               new File(outNames.currentName()),
215                               new File(testFileInfo.goldName),
216                               "Basic stream transform(1) into: " + outNames.currentName());
217             if (fileCheckStatus != reporter.PASS_RESULT)
218             {
219                 reporter.logWarningMsg("Basic stream transform(1) into: " + outNames.currentName()
220                                        + fileChecker.getExtendedInfo());
221             }
222 
223             // Validate transformer reuse
224             reporter.logTraceMsg("Basic stream transform(2)(" + QetestUtils.filenameToURL(testFileInfo.xmlName) + ", "
225                                  + QetestUtils.filenameToURL(testFileInfo.inputName)  + ", "
226                                  + outNames.nextName());
227             fos = new FileOutputStream(outNames.currentName());
228             transformer.transform(new StreamSource(QetestUtils.filenameToURL(testFileInfo.xmlName)),
229                                   new StreamResult(fos));
230             fos.close();
231             fileCheckStatus = fileChecker.check(reporter,
232                               new File(outNames.currentName()),
233                               new File(testFileInfo.goldName),
234                               "Basic stream transform(2) into: " + outNames.currentName());
235             if (fileCheckStatus != reporter.PASS_RESULT)
236             {
237                 reporter.logWarningMsg("Basic stream transform(2) into: " + outNames.currentName()
238                                        + fileChecker.getExtendedInfo());
239             }
240         }
241         catch (Throwable t)
242         {
243             reporter.checkFail("Problem with simple stream transform");
244             reporter.logThrowable(reporter.ERRORMSG, t, "Problem with simple stream transform");
245         }
246 
247         try
248         {
249             // Validate selected API's - primarily Parameters
250             Templates paramTemplates = factory.newTemplates(new StreamSource(QetestUtils.filenameToURL(paramFileInfo.inputName)));
251             Transformer paramTransformer = paramTemplates.newTransformer();
252             String paramStr = "paramVal";
253             paramTransformer.setParameter(PARAM1S, paramStr);
254             reporter.logTraceMsg("Just set " + PARAM1S + " to " + paramStr);
255             Object tmp = paramTransformer.getParameter(PARAM1S);    // SPR SCUU4QWTVZ - returns an XObject - fixed
256             if (tmp == null)
257             {
258                 reporter.checkFail(PARAM1S + " is still set to null!");
259             }
260             else
261             {   // Validate SPR SCUU4QWTVZ - should return the same type you set
262                 if (tmp instanceof String)
263                 {
264                     reporter.checkObject(tmp, paramStr, PARAM1S + " is now set to ?" + tmp + "?");
265                 }
266                 else
267                 {
268                     reporter.checkFail(PARAM1S + " is now ?" + tmp + "?, isa " + tmp.getClass().getName());
269                 }
270             }
271 
272             // Verify simple re-set/get of a single parameter - new Integer
273             Integer paramInteger = new Integer(1234);
274             paramTransformer.setParameter(PARAM1S, paramInteger);   // SPR SCUU4R3JGY - can't re-set
275             reporter.logTraceMsg("Just reset " + PARAM1S + " to new Integer(99)");
276             tmp = null;
277             tmp = paramTransformer.getParameter(PARAM1S);
278             if (tmp == null)
279             {
280                 reporter.checkFail(PARAM1S + " is still set to null!");
281             }
282             else
283             {   // Validate SPR SCUU4QWTVZ - should return the same type you set
284                 if (tmp instanceof Integer)
285                 {
286                     reporter.checkObject(tmp, paramInteger, PARAM1S + " is now set to ?" + tmp + "?");
287                 }
288                 else
289                 {
290                     reporter.checkFail(PARAM1S + " is now ?" + tmp + "?, isa " + tmp.getClass().getName());
291                 }
292             }
293             // Validate a transform with two params set
294             paramTransformer.setParameter(PARAM1N, "new-param1n-value");
295             reporter.logTraceMsg("Just reset " + PARAM1N + " to new-param1n-value");
296 
297             reporter.logTraceMsg("Stream-param transform(" + QetestUtils.filenameToURL(paramFileInfo.xmlName) + ", "
298                                  + QetestUtils.filenameToURL(paramFileInfo.inputName)  + ", "
299                                  + outNames.nextName());
300             FileOutputStream fos = new FileOutputStream(outNames.currentName());
301             paramTransformer.transform(new StreamSource(QetestUtils.filenameToURL(paramFileInfo.xmlName)),
302                                   new StreamResult(fos));
303             fos.close();
304             int fileCheckStatus = fileChecker.check(reporter,
305                               new File(outNames.currentName()),
306                               new File(paramFileInfo.goldName),
307                               "Stream transform with params into: " + outNames.currentName());
308             if (fileCheckStatus != reporter.PASS_RESULT)
309             {
310                 reporter.logWarningMsg("Stream transform with params into: " + outNames.currentName()
311                                        + fileChecker.getExtendedInfo());
312             }
313             // Validate params are still set after transform
314             tmp = paramTransformer.getParameter(PARAM1S);
315             reporter.checkObject(tmp, paramInteger, PARAM1S + " is now set to ?" + tmp + "?");
316             tmp = paramTransformer.getParameter(PARAM1N);
317             reporter.checkObject(tmp, "new-param1n-value", PARAM1N + " is now set to ?" + tmp + "?");
318         }
319         catch (Throwable t)
320         {
321             reporter.checkFail("Problem with parameters");
322             reporter.logThrowable(reporter.ERRORMSG, t, "Problem with parameters");
323         }
324         reporter.testCaseClose();
325         return true;
326     }
327 
328 
329     /**
330      * Basic trax.dom transformWrapper.
331      *
332      * @return false if we should abort the test; true otherwise
333      */
testCase2()334     public boolean testCase2()
335     {
336         final String FLAVOR = "trax.dom";
337         final String DESC = "Basic " + FLAVOR + " transformWrapper";
338         reporter.testCaseInit(DESC);
339         try
340         {
341             testFileInfo.outputName = outNames.nextName();
342             transformUsingFlavor(testFileInfo, FLAVOR);
343             fileChecker.check(reporter,
344                               new File(testFileInfo.outputName),
345                               new File(testFileInfo.goldName),
346                               DESC +" into: " + testFileInfo.outputName);
347 
348         }
349         catch (Throwable t)
350         {
351             reporter.logThrowable(reporter.ERRORMSG, t, DESC + " threw: ");
352             reporter.checkErr(DESC + " threw: " + t.toString());
353         }
354         return true;
355     }
356 
357 
358     /**
359      * Basic trax.sax transformWrapper.
360      *
361      * @return false if we should abort the test; true otherwise
362      */
testCase3()363     public boolean testCase3()
364     {
365         final String FLAVOR = "trax.sax";
366         final String DESC = "Basic " + FLAVOR + " transformWrapper";
367         reporter.testCaseInit(DESC);
368         try
369         {
370             testFileInfo.outputName = outNames.nextName();
371             transformUsingFlavor(testFileInfo, FLAVOR);
372             fileChecker.check(reporter,
373                               new File(testFileInfo.outputName),
374                               new File(testFileInfo.goldName),
375                               DESC +" into: " + testFileInfo.outputName);
376         }
377         catch (Throwable t)
378         {
379             reporter.logThrowable(reporter.ERRORMSG, t, DESC + " threw: ");
380             reporter.checkErr(DESC + " threw: " + t.toString());
381         }
382         reporter.testCaseClose();
383         return true;
384     }
385 
386 
387     /**
388      * Basic trax.stream transformWrapper.
389      *
390      * @return false if we should abort the test; true otherwise
391      */
testCase4()392     public boolean testCase4()
393     {
394         final String FLAVOR = "trax.stream";
395         final String DESC = "Basic " + FLAVOR + " transformWrapper";
396         reporter.testCaseInit(DESC);
397         try
398         {
399             testFileInfo.outputName = outNames.nextName();
400             transformUsingFlavor(testFileInfo, FLAVOR);
401             fileChecker.check(reporter,
402                               new File(testFileInfo.outputName),
403                               new File(testFileInfo.goldName),
404                               DESC +" into: " + testFileInfo.outputName);
405         }
406         catch (Throwable t)
407         {
408             reporter.logThrowable(reporter.ERRORMSG, t, DESC + " threw: ");
409             reporter.checkErr(DESC + " threw: " + t.toString());
410         }
411         reporter.testCaseClose();
412         return true;
413     }
414 
415 
416     /**
417      * Basic performance measurements of sample files.
418      * @return false if we should abort the test; true otherwise
419      */
testCase5()420     public boolean testCase5()
421     {
422         String flavor = null;
423         final String DESC = "Simple performance measurement ";
424         reporter.testCaseInit(DESC);
425         // Reset the counting for outputNames for this testcase
426         outNames = new OutputNameManager(baseOutName + "Perf", ".out");
427         try
428         {
429             long[] times = null;
430             Vector streamTimes = new Vector();
431             Vector domTimes = new Vector();
432             TransformWrapper transformWrapper = null;
433 
434             flavor = "trax.stream";
435             transformWrapper = TransformWrapperFactory.newWrapper(flavor);
436             transformWrapper.newProcessor(testProps);
437             reporter.logHashtable(Logger.TRACEMSG, transformWrapper.getProcessorInfo(), "wrapper.getProcessorInfo() for next transforms");
438 
439             // Repeat a few times with streams
440             for (int i = 1; i <= 5; i++)
441             {
442                 perfFileInfo.outputName = outNames.nextName();
443                 reporter.logInfoMsg("perf-stream transform into " + perfFileInfo.outputName);
444                 times = transformWrapper.transform(perfFileInfo.xmlName, perfFileInfo.inputName, perfFileInfo.outputName);
445                 logPerfElem(times, perfFileInfo, flavor);
446                 streamTimes.addElement(new Long(times[TransformWrapper.IDX_OVERALL]));
447             }
448             // Only bother checking the *last* iteration of perfs
449             fileChecker.check(reporter,
450                               new File(perfFileInfo.outputName),
451                               new File(perfFileInfo.goldName),
452                               DESC + flavor + " into: " + perfFileInfo.outputName);
453 
454             flavor = "trax.dom";
455             transformWrapper = TransformWrapperFactory.newWrapper(flavor);
456             transformWrapper.newProcessor(testProps);
457             reporter.logHashtable(Logger.TRACEMSG, transformWrapper.getProcessorInfo(), "wrapper.getProcessorInfo() for next transforms");
458 
459             // Repeat a few times with DOMs
460             for (int i = 1; i <= 5; i++)
461             {
462                 perfFileInfo.outputName = outNames.nextName();
463                 reporter.logInfoMsg("perf-dom transform into " + perfFileInfo.outputName);
464                 times = transformWrapper.transform(perfFileInfo.xmlName, perfFileInfo.inputName, perfFileInfo.outputName);
465                 logPerfElem(times, perfFileInfo, flavor);
466                 domTimes.addElement(new Long(times[TransformWrapper.IDX_OVERALL]));
467             }
468             // Only bother checking the *last* iteration of perfs
469             fileChecker.check(reporter,
470                               new File(perfFileInfo.outputName),
471                               new File(perfFileInfo.goldName),
472                               DESC + flavor + " into: " + perfFileInfo.outputName);
473 
474             // Log a big message at the very end to make it easier to see
475             StringBuffer buf = new StringBuffer("Minitest.testCase5 PERFORMANCE NUMBERS\n");
476             buf.append("        STREAM OVERALL TIMES: ");
477             for (Enumeration elements = streamTimes.elements();
478                     elements.hasMoreElements(); /* no increment portion */ )
479             {
480                 buf.append(elements.nextElement());
481                 buf.append(", ");
482             }
483             buf.append("\n");
484             buf.append("           DOM OVERALL TIMES: ");
485             for (Enumeration elements = domTimes.elements();
486                     elements.hasMoreElements(); /* no increment portion */ )
487             {
488                 buf.append(elements.nextElement());
489                 buf.append(", ");
490             }
491             buf.append("\n");
492             reporter.logArbitrary(Logger.CRITICALMSG, buf.toString());
493         }
494         catch (Throwable t)
495         {
496             reporter.logThrowable(reporter.ERRORMSG, t, DESC + flavor + " threw: ");
497             reporter.checkErr(DESC + flavor + " threw: " + t.toString());
498         }
499         reporter.testCaseClose();
500         return true;
501     }
502 
503 
504     /**
505      * Worker method to use a TransformWrapper to transform a file.
506      *
507      * @param fileInfo inputName, xmlName of file to test
508      * @param flavor of TransformWrapper to use
509      * @return log number of overall millisec for transform.
510      */
transformUsingFlavor(XSLTestfileInfo fileInfo, String flavor)511     public void transformUsingFlavor(XSLTestfileInfo fileInfo, String flavor)
512             throws Exception
513     {
514         TransformWrapper transformWrapper = TransformWrapperFactory.newWrapper(flavor);
515         transformWrapper.newProcessor(testProps);
516         reporter.logHashtable(Logger.TRACEMSG, transformWrapper.getProcessorInfo(), "wrapper.getProcessorInfo() for next transform");
517         if (null == fileInfo.inputName)
518         {
519             // presume it's an embedded test
520             reporter.logInfoMsg("transformEmbedded(" + fileInfo.xmlName + ", " + fileInfo.outputName + ")");
521             long[] times = transformWrapper.transformEmbedded(fileInfo.xmlName, fileInfo.outputName);
522             logPerfElem(times, fileInfo, flavor);
523         }
524         else
525         {
526             // presume it's a normal stylesheet test
527             reporter.logInfoMsg("transform(" + fileInfo.xmlName + ", " + fileInfo.inputName + ", " + fileInfo.outputName + ")");
528             long[] times = transformWrapper.transform(fileInfo.xmlName, fileInfo.inputName, fileInfo.outputName);
529             logPerfElem(times, fileInfo, flavor);
530         }
531 
532     }
533 
534 
535     /**
536      * Worker method to output a &lt;perf&gt; element.
537      * @return false if we should abort the test; true otherwise
538      */
logPerfElem(long[] times, XSLTestfileInfo fileInfo, String flavor)539     public void logPerfElem(long[] times, XSLTestfileInfo fileInfo, String flavor)
540     {
541         Hashtable attrs = new Hashtable();
542         // Add general information about this perf elem
543         attrs.put("UniqRunid", testProps.getProperty("runId", "runId;none"));
544         attrs.put("processor", flavor);
545         // idref is the individual filename
546         attrs.put("idref", (new File(fileInfo.inputName)).getName());
547         // inputName is the actual name we gave to the processor
548         attrs.put("inputName", fileInfo.inputName);
549 
550         // Add all available specific timing data as well
551         for (int i = 0; i < times.length; i++)
552         {
553             // Only log items that have actual timing data
554             if (TransformWrapper.TIME_UNUSED != times[i])
555             {
556                 attrs.put(TransformWrapperHelper.getTimeArrayDesc(i),
557                           new Long(times[i]));
558             }
559         }
560 
561         // Log the element out; note formatting matches
562         reporter.logElement(Logger.STATUSMSG, "perf", attrs, fileInfo.description);
563     }
564 
565 
566     /**
567      * Convenience method to print out usage information - update if needed.
568      * @return String denoting usage of this test class
569      */
usage()570     public String usage()
571     {
572         return ("Common [optional] options supported by Minitest:\n"
573                 + "(Note: assumes inputDir=.\\tests\\api)\n"
574                 + super.usage());   // Grab our parent classes usage as well
575     }
576 
577 
578     /**
579      * Main method to run test from the command line - can be left alone.
580      * @param args command line argument array
581      */
main(String[] args)582     public static void main(String[] args)
583     {
584         Minitest app = new Minitest();
585         app.doMain(args);
586     }
587 }
588