curcuru 01/03/05 07:51:55
Added: test/java/src/org/apache/qetest/xsl MConformanceTest.java Log: Alternate command line conformance test Revision Changes Path 1.1 xml-xalan/test/java/src/org/apache/qetest/xsl/MConformanceTest.java Index: MConformanceTest.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2000-2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xalan" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 2000, Lotus * Development Corporation., http://www.lotus.com. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ /* * * MConformanceTest.java * */ package org.apache.qetest.xsl; import org.apache.qetest.*; import org.apache.qetest.xslwrapper.ProcessorWrapper; // Merely for the ERROR constant import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FilenameFilter; import java.io.InputStream; import java.io.InputStreamReader; import java.io.IOException; import java.util.Properties; import java.util.Vector; //------------------------------------------------------------------------- /** * New! MConformanceTest for alternate command line program. * <p>Iterates over all conformance tests using common functionality, * then shells out a process to TestXSLT.exe for each test. * Automatically validates output files against golds, but may not * validate error or exception conditions yet.</p> * @author [EMAIL PROTECTED] * @version $Id: MConformanceTest.java,v 1.1 2001/03/05 15:51:55 curcuru Exp $ */ public class MConformanceTest extends XSLDirectoryIterator { /** * Convenience method to print out usage information - update if needed. * @return basic usage description */ public String usage() { return ("Common [optional] options supported by MConformanceTest:\n" + " -progName <name.exe>\n" + " -progPath <d:\\path\\to\\prog>\n" + super.usage()); } /** Array of 'command line' args for Process.main(args) calls. */ String[] pargs = null; /** * Parameter: Actual name of external program to call. * <p>Default: msxsl</p> */ String progName = "msxsl"; /** * Parameter: Actual name of external program to call. * <p>Default: TestXSLT</p> */ public static final String OPT_PROGNAME = "progName"; /** * Path to external program to call. * <p>Default: blank string</p> */ String progPath = ""; /** * Path to external program to call. * <p>Default: blank string</p> */ public static final String OPT_PROGPATH = "progPath"; /** * Default constructor - initialize testName, Comment. */ public MConformanceTest() { testName = "MConformanceTest"; testComment = "Iterates over all conf test dirs and validates outputs using cmdline processor"; } /** * Initialize this test - process our input args and construct * array of command line args for processor. * //@todo make this table-driven for the argument names * //@todo update to include all supported args * * @param p unused * @return true, or false if error */ public boolean doTestFileInit(Properties p) { // Validate/setup progName, progPath progName = testProps.getProperty(OPT_PROGNAME, progName); progPath = testProps.getProperty(OPT_PROGPATH, progPath); reporter.logTraceMsg("progPath\\progName= " + progPath + File.separator + progName); // Attempt to check if it exists (but only in certain cases) if ((progPath != null) && (progPath.length() > 0)) { File progF = new File(progPath + File.separator + progName); if (!progF.exists()) { reporter.logErrorMsg("Program may not exist! " + progPath + File.separator + progName); } } else { // No-op: can't easily validate programs (presumably) found on the PATH } reporter.logTraceMsg("Sorry, no additional arguments to cmdline prog supported!"); return true; } /** * Subclassed callback to provide info about the processor you're testing. * * @return brief description of processor used */ public String getDescription() { return "ProcessorVersion;command line msxsl.exe:Windows only"; } /** * Run through the directory given to us and run tests found in subdirs. * * @param p unused * @return true */ public boolean runTestCases(Properties p) { processTestDir(); return true; } /** * Run one xsl/xml file pair through the processor. * <p>We simply call Process.main() with a constructed series * of args[] using Runtime.exec().</p> * <p>Note that timings are in no way comparable to the normal * ConformanceTest since this is C++, not Java, and since we have * the overhead of shelling out the process and processing * the command line.</p> * * @param XMLName path\filename to XML file * @param XSLName path\filename to stylesheet file * @param OutName path\filename to outputfile * * @return UNEXPECTED_EXCEPTION or PROCESS_OK; currently does * not check for expectedExceptions */ public int processSingleFile(String XMLName, String XSLName, String OutName) { long fileTime = ProcessorWrapper.ERROR; try { String args[] = new String[6]; // progName XML XSL -o OUT -t if ((progPath != null) && (progPath.length() > 0)) { args[0] = progPath + File.separator + progName; } else { // Pesume the program is on the PATH already... args[0] = progName; } args[1] = XMLName; args[2] = XSLName; args[3] = "-o"; // flag for outname args[4] = OutName; args[5] = "-t"; // print timings // Note: no other args currently supported! //System.arraycopy(pargs, 0, args, 7, pargs.length); // Declare variables ahead of time to minimize latency long startTime = 0; long endTime = 0; int returnVal = 0; startTime = System.currentTimeMillis(); // Use our worker method to execute the process returnVal = execProcess(args, null); endTime = System.currentTimeMillis(); fileTime = endTime - startTime; // if the execution of the process was basically OK, // then add this file to overall timing info if (returnVal != ProcessorWrapper.ERROR) { dirTime += fileTime; dirFilesProcessed++; reporter.logTraceMsg("processSingleFile(" + XSLName + ") no exceptions; time " + fileTime); reporter.logInfoMsg("processSingleFile(" + XSLName + ") returnValue = " + returnVal); } else { // Do not increment performance counters if there's an error // Note: can this code ever really be executed? reporter.logWarningMsg("processSingleFile(" + XSLName + ") returned ERROR code!"); } } // Catch general Exceptions, check if they're expected, and restart catch (Exception e) { reporter.logStatusMsg("processSingleFile(" + XSLName + ") threw: " + e.toString()); int retVal = checkExpectedException(e, XSLName, OutName); return retVal; } // Catch any Throwable, check if they're expected, and restart catch (Throwable t) { reporter.logStatusMsg("processSingleFile(" + XSLName + ") threw: " + t.toString()); int retVal = checkExpectedException(t, XSLName, OutName); return retVal; } return PROCESS_OK; } /** * Simple child thread for reading an InputStream. * Used to capture the System.err and System.out streams * from the executed process - without hanging or blocking. */ public class ThreadedStreamReader extends Thread { // Begin of inner class /** NEEDSDOC Field is */ BufferedReader is = null; /** NEEDSDOC Field sb */ StringBuffer sb = null; /** * NEEDSDOC Method setInputStream * * * NEEDSDOC @param set */ public void setInputStream(BufferedReader set) { is = set; } /** * NEEDSDOC Method run * */ public void run() { sb = new StringBuffer(); // Note that reporters may not be threadsafe, so we should avoid there use herein if (is == null) { sb.append( "ERROR! ThreadedStreamReader.run() with setInputStream(null)"); return; } sb.append("<tsrbuf>"); String i = null; try { i = is.readLine(); } catch (IOException ioe1) { // Presumably the stream is bad, so just bag out i = null; } while (i != null) { sb.append(i); try { i = is.readLine(); } catch (IOException ioe2) { // Presumably the stream is bad, so just bag out i = null; } } sb.append("</tsrbuf>"); } /** * NEEDSDOC Method getBuffer * * * NEEDSDOC (getBuffer) @return */ public StringBuffer getBuffer() { return sb; } } ; // End of inner class /** * Worker method to shell out an external process. * <p>Does a simple capturing of the out and err streams from * the process. Inherits the same environment that the current * JVM is in.</p> * @param cmdLine actual command line to run, including program name * NEEDSDOC @param environment * @return return value from program * @exception Exception may be thrown by Runtime.exec */ public int execProcess(String[] cmdLine, String[] environment) throws Exception { // @todo check the logic here: will '-1' be a likely // return value from the process anyways? // this is needed in our caller to see if they should // use this process as part of timing data int retVal = (new Long(ProcessorWrapper.ERROR)).intValue(); if ((cmdLine == null) || (cmdLine.length < 1)) { reporter.logErrorMsg( "execProcess called with null/blank arguments!"); return retVal; } int bufSize = 2048; ThreadedStreamReader outReader = new ThreadedStreamReader(); ThreadedStreamReader errReader = new ThreadedStreamReader(); Runtime r = Runtime.getRuntime(); java.lang.Process proc = null; // Fully declare to not conflict with org.apache.xalan.xslt.Process // Actually begin executing the program reporter.logTraceMsg("execProcess starting " + cmdLine[0]); proc = r.exec(cmdLine, environment); // Immediately begin capturing any output therefrom outReader.setInputStream( new BufferedReader( new InputStreamReader(proc.getInputStream()), bufSize)); errReader.setInputStream( new BufferedReader( new InputStreamReader(proc.getErrorStream()), bufSize)); // Start two thread off on reading the System.out and System.err from proc outReader.start(); errReader.start(); try { // Wait for the process to exit normally retVal = proc.waitFor(); } catch (InterruptedException ie1) { reporter.logWarningMsg("execProcess proc.waitFor() threw: " + ie1.toString()); } // Now that we're done, presumably the Readers are also done String sysOut = "No System.out captured"; String sysErr = "No System.err captured"; try { outReader.join(); sysOut = outReader.getBuffer().toString(); } catch (InterruptedException ie2) { reporter.logWarningMsg("Joining outReader threw: " + ie2.toString()); } try { errReader.join(); sysErr = errReader.getBuffer().toString(); } catch (InterruptedException ie3) { reporter.logWarningMsg("Joining errReader threw: " + ie3.toString()); } reporter.logArbitrary(reporter.INFOMSG, "proc.System.out was: " + sysOut); reporter.logArbitrary(reporter.INFOMSG, "proc.System.err was: " + sysErr); reporter.logTraceMsg("execProcess exitVal=" + retVal); return retVal; } /** * Main method to run test from the command line - can be left alone. * @param args command line args */ public static void main(String[] args) { MConformanceTest app = new MConformanceTest(); app.doMain(args); } } // end of class MConformanceTest
