You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by cu...@apache.org on 2001/02/09 02:55:24 UTC

cvs commit: xml-xalan/test/java/src/org/apache/qetest/xsl PerformanceDatalet.java PerformanceTestlet.java

curcuru     01/02/08 17:55:24

  Modified:    test/java/src/org/apache/qetest/trax TransformerAPITest.java
  Added:       test/java/src/org/apache/qetest Datalet.java
                        NullDatalet.java Testlet.java TestletImpl.java
               test/java/src/org/apache/qetest/xsl PerformanceDatalet.java
                        PerformanceTestlet.java
  Log:
  New Testlet/Datalet classes for a whole new kind of data-driven testing
  
  Revision  Changes    Path
  1.1                  xml-xalan/test/java/src/org/apache/qetest/Datalet.java
  
  Index: Datalet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 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 apache@apache.org.
   *
   * 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/>.
   */
  
  /*
   *
   * Datalet.java
   *
   */
  package org.apache.qetest;
  
  import java.util.Hashtable;
  
  /**
   * Minimal interface defining a datalet, a single set of data 
   * for a simple test case.
   * <p>A Datalet defines a single group of data that a matching 
   * Testlet needs to execute it's simple test case.  Normally,
   * Testlets and Datalets are matched.</p>
   *
   * <p>This makes creating data-driven tests simpler, by separating 
   * the test algorithim from the definition of the test data.  Note 
   * that logging what happened during the test is already separated 
   * out into the Logger interface.</p>
   *
   * <p>Normally Datalets will simply be collections of public members
   * that can be written or read by anyone.  An enclosing test can 
   * simply create or load a number of Datalets and then pass them 
   * to a Testlet to execute the whole bunch of them.</p>
   *
   * <p>One way to look at a Datalet is basically an intelligent 
   * Properties / Hashtable / InputSource, designed for a 
   * specific set of data.  They can be loaded from a variety of 
   * inputs and will intelligently create the right kind of data 
   * that their corresponding Testlet is expecting.
   * For example, and DOM-based InputSource Datalet might be 
   * loaded from a number of Strings denoting filenames or URLs.
   * The Datalet would then know how to parse each of the files 
   * into a DOM, which a Testlet could then use directly.</p>
   *
   * <p>//@todo what metaphor is best? I.e. Should Datalets break OO
   * paradigms and just have public members, or should they work more 
   * like a Hashtable with some Properties-like features thrown in?
   * Or: what are the most important 
   * things to optimize: syntactic sugar-like simplicity for callers; 
   * more functionality for different datatypes; ease of use by 
   * inexperienced coders (perhaps testers who are just learning Java);
   * ease of use by experienced coders?</p>
   * 
   *
   * <p>//@todo Should we add a getParameterInfo() method?</p>
   * @author Shane_Curcuru@lotus.com
   * @version $Id: Datalet.java,v 1.1 2001/02/09 01:55:22 curcuru Exp $
   */
  public interface Datalet
  {
  
      /**
       * Accesor method for a brief description of this Datalet.  
       *
       * @return String describing the specific set of data 
       * this Datalet contains (can often be used as the description
       * of any check() calls made from the Testlet).
       */
      public abstract String getDescription();
  
  
      /**
       * Accesor method for a brief description of this Datalet.  
       * Datalets must have this as a read/write property, since many 
       * users will programmatically construct Datalets.
       *
       * @param s description to use for this Datalet.
       */
      public abstract void setDescription(String s);
  
  
      /**
       * Load fields of this Datalet from a Hashtable.
       * Note many datalets might take in a Properties block 
       * instead for simple String-valued data.
       *
       * @param Hashtable to load; Datalet should attempt to fill 
       * in as many member variables as possible from this, leaving 
       * any non-specified variables null or some default; behavior 
       * if null is passed is undefined
       */
      public abstract void load(Hashtable h);
  
  
      /**
       * Load fields of this Datalet from an array.
       * This allows most Datalets to be initialized from a main()
       * command line or the like.  For any String-valued types, or 
       * types that can easily be derived from a String, this makes 
       * running ad-hoc tests very easy.
       *
       * @param args array of Strings, as if from the command line;
       * Datalet should attempt to fill in as many member variables 
       * as possible from this, defining the order itself, leaving 
       * any non-specified variables null or some default; behavior 
       * if null is passed is undefined
       */
      public abstract void load(String[] args);
  
  }  // end of class Datalet
  
  
  
  
  1.1                  xml-xalan/test/java/src/org/apache/qetest/NullDatalet.java
  
  Index: NullDatalet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 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 apache@apache.org.
   *
   * 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/>.
   */
  
  /*
   *
   * NullDatalet.java
   *
   */
  package org.apache.qetest;
  
  import java.util.Hashtable;
  
  /**
   * A default implementation of a Datalet with no data points.  
   * "Conversation... is the art of never appearing a bore, of 
   * knowing how to say everything interestingly, to entertain with 
   * no matter what, to be charming with nothing at all."  
   * -- Guy de Maupassant, <u>Sur l'Eau</u>
   * 
   * @author Shane_Curcuru@lotus.com
   * @version $Id: NullDatalet.java,v 1.1 2001/02/09 01:55:22 curcuru Exp $
   */
  public class NullDatalet implements Datalet
  {
  
      /**
       * Default no-arg, no-op constructor.  
       */
      public NullDatalet() { } // no-op
  
  
      /**
       * Accesor method for a brief description of this NullDatalet.  
       *
       * @return String "NullDatalet: no data contained".
       */
      public String getDescription()
      {
          return "NullDatalet: no data contained";
      }
  
  
      /**
       * Accesor method for a brief description of this NullDatalet.  
       *
       * @param s unused, you cannot set our description
       */
      public void setDescription(String s) { } // no-op
  
  
      /**
       * Load fields of this NullDatalet from a Hashtable.
       *
       * @param Hashtable unused, you cannot set our fields
       */
      public void load(Hashtable h) { } // no-op
  
  
      /**
       * Load fields of this NullDatalet from an array.
       *
       * @param args unused, you cannot set our fields
       */
      public void load(String[] args) { } // no-op
  
  
  }  // end of class NullDatalet
  
  
  
  
  1.1                  xml-xalan/test/java/src/org/apache/qetest/Testlet.java
  
  Index: Testlet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 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 apache@apache.org.
   *
   * 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/>.
   */
  
  /*
   *
   * Testlet.java
   *
   */
  package org.apache.qetest;
  
  /**
   * Minimal interface defining a testlet, a sort of mini-test.
   * A Testlet defines a single, simple test case that is completely
   * independent.  Commonly a Testlet will perform a single 
   * test operation and verify it, usually given a set of test 
   * data to perform the operation on.  
   *
   * <p>This makes creating data-driven tests simpler, by separating 
   * the test algorithim from the definition of the test data.  Note 
   * that logging what happened during the test is already separated 
   * out into the Logger interface.</p>
   * 
   * <p>Testlets are used with Datalets, which provide a single set 
   * of data to execute this test case with.
   * For example:</p>
   * <ul>
   *   <li>We define a Testlet that processes an XML file with a 
   *   stylesheet in a certain manner - perhaps using a specific 
   *   set of SAX calls.</li>
   *   <li>The Testlet takes as an argument a matching Datalet, that 
   *   defines any parameters that may change  - like the names 
   *   of the XML file and the stylesheet file to use.</li>
   *   <li>Test authors or users running a harness or the like can 
   *   then easily define a large set of Datalets for various 
   *   types of input files that they want to test, and simply 
   *   iterate over the set of Datalets, repeatedly calling 
   *   Testlet.execute().  Each execution of the Testlet will 
   *   be independent.</li>
   * </ul>
   * 
   * <p>Testlets may provide additional worker methods that allow them 
   * to be easily run in varying situations; for example, a 
   * testwriter may have a Test object that calls a number of Testlets 
   * for it's test cases.  If one of the Testlets finds a bug, the 
   * testwriter can simply reference the single Testlet and it's 
   * current Datalet in the bug report, without having to reference 
   * the enclosing Test file.  This makes it easier for others to 
   * reproduce the problem with a minimum of overhead.</p>
   *
   * @author Shane_Curcuru@lotus.com
   * @version $Id: Testlet.java,v 1.1 2001/02/09 01:55:22 curcuru Exp $
   */
  public interface Testlet
  {
  
      /**
       * Accesor method for a brief description of this Testlet.  
       * <p>Testlet implementers should provide a brief, one line 
       * description of the algorithim of their test case.</p>
       * //@todo do we need to define a setDescription() method?
       * Since Testlets are pretty self-sufficient, implementers 
       * should always just define this, and not let callers 
       * re-set them.
       *
       * @return String describing what this Testlet does.
       */
      public abstract String getDescription();
  
  
      /**
       * Accesor methods for our Logger.
       * <p>Testlets use simple Loggers that they rely on the caller 
       * to have setup.  This frees the Testlet and the Logger from 
       * having to store any other state about the Testlet.  It is 
       * the caller's responsibility to do any overall rolling-up 
       * or aggregating of results reporting, if needed.</p>
       *
       * @param l the Logger to have this test use for logging 
       * results; or null to use a default logger
       */
      public abstract void setLogger(Logger l);
  
  
      /**
       * Accesor methods for our Logger.  
       *
       * @return Logger we tell all our secrets to; may be null
       */
      public abstract Logger getLogger();
  
  
      /**
       * Get a default Logger for use with this Testlet.  
       * <p>Provided to allow subclasses to override this in different 
       * ways.  This would probably be called when setLogger(null) 
       * is called.  The most common implementation would be to 
       * return a Logger.DEFAULT_LOGGER (which simply 
       * logs things to the console).</p>
       *
       * //@todo this sort of functionality should really be provided 
       * by the Logger class itself - any caller should be able to ask 
       * Logger (or a Logger factory, if you want to get fancy) for a 
       * default Logger for use without having to supply any params.
       *
       * @return Logger suitable for passing to setLogger()
       */
      public abstract Logger getDefaultLogger();
  
  
      /**
       * Return this Testlet's default Datalet.  
       * <p>Every Testlet should have created a default Datalet that can 
       * be used with this test: i.e. the test case itself has a 
       * default, or sample set of data to execute the test with. This 
       * way a user can simply execute the Testlet on the fly without 
       * having to provide any input data.</p>
       * <p>If the Testlet can't provide a default Datalet, either 
       * the user must provide one somehow, or an error message 
       * should be printed out.  Note that the Testlet must still 
       * return a Datalet of the correct class from this method, even 
       * if the Datalet returned has no data set into it.  This would 
       * allow a harness with random test data generation capabilities 
       * to discover this Testlet, and then generate random Datalets to 
       * pass to it.</p>
       *
       * @return Datalet this Testlet can use as a default test case.
       */
      public abstract Datalet getDefaultDatalet();
  
  
      /**
       * Run this Testlet: execute it's test and return.
       * <p>The Testlet should perform it's test operation, logging 
       * information as needed to it's Logger, using the provided 
       * Datalet as a test point.</p>
       * <p>If the Datalet passed is null, the Testlet should use 
       * it's default Datalet as the test point data.</p>
       * <p>Testlets should not throw exceptions and should not 
       * return anything nor worry about checking their state or 
       * rolling up any overall results to their Logger.  Testlets 
       * should simply focus on performing their one test operation 
       * and outputting any simple pass/fail/other results to their 
       * Logger.  It is the responsibility of the caller to do any 
       * overall or rolled-up reporting that is desired.</p>
       *
       * @author Shane_Curcuru@lotus.com
       * @param Datalet to use as data points for the test; if null, 
       * will attempt to use getDefaultDatalet()
       */
      public abstract void execute(Datalet datalet);
  
  
  }  // end of class Testlet
  
  
  
  
  1.1                  xml-xalan/test/java/src/org/apache/qetest/TestletImpl.java
  
  Index: TestletImpl.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 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 apache@apache.org.
   *
   * 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/>.
   */
  
  /*
   *
   * TestletImpl.java
   *
   */
  package org.apache.qetest;
  
  import java.lang.reflect.Constructor;
  
  /**
   * Simple implementation of a testlet, a sort of mini-test.
   * <p>A TestletImpl defines some common implementations that 
   * may be useful, including sample implementations that 
   * can be copied if you don't want to exend this class.</p>
   *
   * <p>The most useful implementation is of main(String[]), which 
   * allows a Testlet to be executed independently from the command 
   * line.  See the code comments for a way to get this behavior in 
   * your testlet without having to re-implement the whole main 
   * method - by just including a static{} initializer with the 
   * fully qualified classname of your class.</p>
   *
   * <b>Note:</b> Testlets based on this class are probably 
   * not threadsafe, and must be executed singly! 
   * See comments for thisClassName.
   * 
   * @author Shane_Curcuru@lotus.com
   * @version $Id: TestletImpl.java,v 1.1 2001/02/09 01:55:22 curcuru Exp $
   */
  public class TestletImpl implements Testlet
  {
  
      //-----------------------------------------------------
      //---- Implement Testlet interface methods
      //-----------------------------------------------------
  
      /**
       * Accesor method for a brief description of this test.  
       *
       * @return String "TestletImpl: default implementation, does nothing"
       */
      public String getDescription()
      {
          return "TestletImpl: default implementation, does nothing";
      }
  
  
      /**
       * Accesor methods for our Logger.
       *
       * @param l the Logger to have this test use for logging 
       * results; or null to use a default logger
       */
      public void setLogger(Logger l)
  	{
          // if null, set a default one
          if (null == l)
              logger = getDefaultLogger();
          else
              logger = l;
  	}
  
  
      /**
       * Accesor methods for our Logger.  
       *
       * @return Logger we tell all our secrets to.
       */
      public Logger getLogger()
  	{
          return logger;
  	}
  
  
      /**
       * Get a default Logger for use with this Testlet.  
       * Gets a default ConsoleLogger (only if a Logger isn't 
       * currently set!).  
       *
       * @return current logger; if null, then creates a 
       * Logger.DEFAULT_LOGGER and returns that; if it cannot
       * create one, throws a RuntimeException
       */
      public Logger getDefaultLogger()
      {
          if (logger != null)
              return logger;
  
          try
          {
              Class rClass = Class.forName(Logger.DEFAULT_LOGGER);
              return (Logger)rClass.newInstance();
          } 
          catch (Exception e)
          {
              // Must re-throw the exception, since returning 
              //  null or the like could lead to recursion
              e.printStackTrace();
              throw new RuntimeException(e.toString());
          }
      }
  
  
      /**
       * Return this TestletImpl's default Datalet.  
       * 
       * @return Datalet <code>defaultDatalet</code>.
       */
      public Datalet getDefaultDatalet()
  	{
          return defaultDatalet;
  	}
  
  
      /**
       * Run this TestletImpl: execute it's test and return.
       * This must (obviously) be overriden by subclasses.  Here, 
       * we simply log a message for debugging purposes.
       *
       * @param Datalet to use as data points for the test.
       */
      public void execute(Datalet datalet)
  	{
          logger.logMsg(Logger.STATUSMSG, "TestletImpl.execute(" + datalet + ")");
  	}
  
  
      //-----------------------------------------------------
      //---- Implement useful worker methods and main()
      //-----------------------------------------------------
  
      /**
       * Process default command line args.  
       * Provides simple usage functionality: given a first arg of 
       * -h, -H, -?, prints a usage statement based on getDescription()
       * and on getDefaultDatalet().getDescription()
       * 
       * @param args command line args from the JVM
       * @return true if we got and handled any default command line 
       * args (i.e. you can quit now); false otherwise (i.e. you 
       * should go ahead and execute)
       */
      protected boolean handledDefaultArgs(String[] args)
      {
          // We don't handle null or blank args
          if ((null == args) || (0 == args.length))
              return false;
  
          // Provide basic processing for help, usage cases
          if ("-h".equals(args[0])
              || "-H".equals(args[0])
              || "-?".equals(args[0])
             )
          {
              logger.logMsg(Logger.STATUSMSG, thisClassName + " usage:");
              logger.logMsg(Logger.STATUSMSG, "    Testlet: " + getDescription());
              logger.logMsg(Logger.STATUSMSG, "    Datalet: " + getDefaultDatalet().getDescription());
              return true;
          }
  
          // Otherwise, don't handle any other args
          return false;
      }
  
  
      /**
       * Default implementation for command line use.  
       * Note subclasses can easily get the functionality we provide 
       * here without having to copy this method merely by copying the 
       * static initalization block shown above, replacing the 
       * "thisClassName" with their own FQCN.
       *
       * This default implementation installs a default Logger, then 
       * checks for and handles a few default command line args, and 
       * then executes the Testlet.
       *
       * //@todo How do we easily specify alternate Datalets or 
       * data to load a Datalet from?  What about the Datalet that 
       * actually wants the first arg to be -h?
       *
       * @param args command line args from the JVM
       */
      public static void main(String[] args)
      {
          if (true)
              System.out.println("TestletImpl.main");
          TestletImpl t = null;
          try
          {
              // Create an instance of the specific class at runtime
              //  This relies on subclasses to reset 'thisClassName'
              //  in their own static[] initialization block!
              t = (TestletImpl)Class.forName(thisClassName).newInstance();
  
              // Set a default logger automatically
              t.setLogger(t.getDefaultLogger());
  
              // Process default -h, etc. args
              if (!t.handledDefaultArgs(args))
              {
                  if (args.length > 0)
                  {
                      // If we do have any args, then attempt to 
                      //  load the correct-typed Datalet from the args
                      Class dataletClass = t.getDefaultDatalet().getClass();
                      t.logger.logMsg(Logger.TRACEMSG, "Loading Datalet " 
                                    +  dataletClass.getName() + " from args");
                      Datalet d = (Datalet)dataletClass.newInstance();
                      d.load(args);
                      t.execute(d);
                  }
                  else
                  {
                      // Otherwise, use the defaultDatalet for that Testlet
                      t.logger.logMsg(Logger.TRACEMSG, "Using defaultDatalet");
                      t.execute(t.getDefaultDatalet());
                  }
              }
          }
          catch (Exception e)
          {
              if ((null != t) && (null != t.logger))
              {
                  // Use the logger which is (hopefully) OK
                  t.logger.checkErr("TestletImpl threw: " + e.toString());
                  java.io.StringWriter sw = new java.io.StringWriter();
                  java.io.PrintWriter pw = new java.io.PrintWriter(sw);
                  e.printStackTrace(pw);
                  t.logger.logArbitrary(Logger.ERRORMSG, sw.toString());
              }
              else
              {
                  // Otherwise, just dump to System.err
                  System.err.println("TestletImpl threw: " + e.toString());
                  e.printStackTrace();
              }
          }
      }
  
  
      /**
       * The FQCN of the current class.  
       * See comments in main() and in the static initializer.
       * <b>Note:</b> Testlets based on this class are probably 
       * not threadsafe, and must be executed singly! 
       */
      protected static String thisClassName = null;
  
  
      /**
       * A static initializer setting the value of thisClassName.  
       * Subclasses must copy this static block, and replace the 
       * name of "...TestletImpl" with their own name.  Then, when 
       * a user executes the subclassed Testlet on the command line 
       * or calls it's main() method, the correct thing will happen.
       */
      static { thisClassName = "org.apache.qetest.TestletImpl"; }
  
  
      /**
       * Our Logger, who we tell all our secrets to.  
       */
      protected Logger logger = null;
  
  
      /**
       * Our deafult Datalet: in this case, not very interesting.  
       * Provide a default 'null' datalet so unsuspecting callers 
       * don't get NullPointerExceptions.
       */
      protected Datalet defaultDatalet = new NullDatalet();
  
  }  // end of class TestletImpl
  
  
  
  1.10      +227 -21   xml-xalan/test/java/src/org/apache/qetest/trax/TransformerAPITest.java
  
  Index: TransformerAPITest.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/test/java/src/org/apache/qetest/trax/TransformerAPITest.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- TransformerAPITest.java	2001/02/08 17:49:04	1.9
  +++ TransformerAPITest.java	2001/02/09 01:55:23	1.10
  @@ -92,6 +92,7 @@
   import java.io.FileOutputStream;
   import java.util.Enumeration;
   import java.util.Properties;
  +import java.util.Hashtable;
   
   //-------------------------------------------------------------------------
   
  @@ -168,7 +169,7 @@
       public TransformerAPITest()
       {
   
  -        numTestCases = 3;  // REPLACE_num
  +        numTestCases = 5;  // REPLACE_num
           testName = "TransformerAPITest";
           testComment = "Basic API coverage test for the Transformer class";
       }
  @@ -276,7 +277,7 @@
        * functional test coverage on setting different kinds 
        * and types of parameters, etc.
        * 
  -     * NEEDSDOC ($objectName$) @return
  +     * @return false if we should abort the test
        */
       public boolean testCase1()
       {
  @@ -487,18 +488,15 @@
   
   
       /**
  -     * TRAX Transformer: cover basic get/setOutputFormat APIs.
  -     * See {@link OutputFormatTest} for more coverage on setting 
  +     * API coverage test of Transformer.set/getOutputProperty()
  +     * See {@link OutputPropertiesTest} for more coverage on setting 
        * different kinds of outputs, etc.
        * 
  -     * NEEDSDOC ($objectName$) @return
  +     * @return false if we should abort the test
        */
       public boolean testCase2()
       {
  -
  -        reporter.testCaseInit(
  -            "TRAX Transformer: cover basic get/setOutputFormat APIs");
  -
  +        reporter.testCaseInit("API coverage test of Transformer.set/getOutputProperty()");
           TransformerFactory factory = null;
           Templates outputTemplates = null;
           Transformer outputTransformer = null;
  @@ -511,9 +509,9 @@
           }
           catch (Throwable t)
           {
  -            reporter.checkFail("Problem creating Templates; cannot continue testcase");
  +            reporter.checkFail("Problem creating Templates; cannot continue");
               reporter.logThrowable(reporter.ERRORMSG, t, 
  -                                  "Problem creating Templates; cannot continue testcase");
  +                                  "Problem creating Templates; cannot continue");
               return true;
           }
   
  @@ -532,9 +530,9 @@
           } 
           catch (Exception e)
           {
  -            reporter.checkFail("Problem with identity output properties", "SCUU4RXQYH");
  +            reporter.checkFail("Problem with identity output property", "SCUU4RXQYH");
               reporter.logThrowable(reporter.ERRORMSG, e,
  -                                  "Problem with identity output properties");
  +                                  "Problem with identity output property");
           }
   
           try
  @@ -698,12 +696,121 @@
                                     "Problem with set/get output properties(0)");
           }
   
  -        reporter.testCaseClose();
  +        // Negative testing: various illegal arguments, etc.
  +        try
  +        {
  +            Transformer negTransformer = outputTemplates.newTransformer();
   
  +        } 
  +        catch (Exception e)
  +        {
  +            reporter.checkFail("Problem with negative setOutputProperty/ies tests");
  +            reporter.logThrowable(reporter.ERRORMSG, e,
  +                                  "Problem with negative setOutputProperty/ies tests");
  +        }
  +        reporter.testCaseClose();
           return true;
       }
   
       /**
  +     * API coverage test of Transformer.set/getOutputProperties()
  +     * See {@link OutputPropertiesTest} for more coverage on setting 
  +     * different kinds of outputs, etc.
  +     * 
  +     * @return false if we should abort the test
  +     */
  +    public boolean testCase3()
  +    {
  +        reporter.testCaseInit("API coverage test of Transformer.set/getOutputProperties()");
  +        TransformerFactory factory = null;
  +        Templates outputTemplates = null;
  +        Transformer outputTransformer = null;
  +        Transformer identityTransformer = null;
  +        try
  +        {
  +            factory = TransformerFactory.newInstance();
  +            identityTransformer = factory.newTransformer();
  +            outputTemplates = factory.newTemplates(new StreamSource(outputFormatTest.inputName));
  +        }
  +        catch (Throwable t)
  +        {
  +            reporter.checkFail("Problem creating Templates; cannot continue");
  +            reporter.logThrowable(reporter.ERRORMSG, t, 
  +                                  "Problem creating Templates; cannot continue");
  +            return true;
  +        }
  +        try
  +        {
  +            // See what the default 'identity' transform has by default
  +            Properties identityProps = identityTransformer.getOutputProperties(); // SPR SCUU4RXQYH throws npe
  +            reporter.check((null != identityProps), true, "identityTransformer.getOutputProperties() is non-null");
  +            reporter.logHashtable(reporter.STATUSMSG, identityProps, 
  +                                  "default identityTransformer.getOutputProperties()");
  +        } 
  +        catch (Exception e)
  +        {
  +            reporter.checkFail("Problem with identity OutputProperties", "SCUU4RXQYH");
  +            reporter.logThrowable(reporter.ERRORMSG, e,
  +                                  "Problem with identity OutputProperties");
  +        }
  +
  +        reporter.logTraceMsg("More work to be done here!");
  +        reporter.testCaseClose();
  +        return true;
  +    } // end testCase3
  +
  +
  +    /**
  +     * Negative tests of Transformer.set/getOutputProperty/ies()
  +     * 
  +     * @return false if we should abort the test
  +     */
  +    public boolean testCase4()
  +    {
  +        reporter.testCaseInit("Negative tests of Transformer.set/getOutputProperty/ies()");
  +        TransformerFactory factory = null;
  +        Templates outputTemplates = null;
  +        Transformer outputTransformer = null;
  +        Transformer identityTransformer = null;
  +        try
  +        {
  +            factory = TransformerFactory.newInstance();
  +            identityTransformer = factory.newTransformer();
  +            outputTemplates = factory.newTemplates(new StreamSource(outputFormatTest.inputName));
  +        }
  +        catch (Throwable t)
  +        {
  +            reporter.checkFail("Problem creating Templates; cannot continue");
  +            reporter.logThrowable(reporter.ERRORMSG, t, 
  +                                  "Problem creating Templates; cannot continue");
  +            return true;
  +        }
  +
  +        // Negative tests of getOutputProperty()
  +        String testDesc = "getOutputProperty of bogus-name";
  +        try
  +        {
  +            Transformer t = factory.newTransformer();
  +            String val = t.getOutputProperty("bogus-name");
  +            reporter.checkFail(testDesc);
  +        }
  +        catch (IllegalArgumentException iae)
  +        {
  +            reporter.checkPass(testDesc + ", threw: " + iae.toString());
  +        }
  +        catch (Throwable t)
  +        {
  +            reporter.checkFail(testDesc + ", threw: " + t.toString());
  +        }
  +
  +
  +
  +        reporter.testCaseClose();
  +        return true;
  +    } // end testCase4
  +
  +
  +    /**
        * TRAX Transformer: cover transform() API and basic 
        * functionality; plus set/getURIResolver() API; 
        * plus set/getErrorListener() API; .
  @@ -715,9 +822,9 @@
        * 
        * @todo should the Features.SAX and Features.DOM tests be in 
        * this file, or should they be in sax/dom subdirectory tests?
  -     * NEEDSDOC ($objectName$) @return
  +     * @return false if we should abort the test
        */
  -    public boolean testCase3()
  +    public boolean testCase5()
       {
           reporter.testCaseInit(
               "TRAX Transformer: cover transform() and set/getURIResolver API and functionality");
  @@ -812,7 +919,7 @@
           reporter.testCaseClose();
   
           return true;
  -    }
  +    } // end testCase5
   
   
       /**
  @@ -839,11 +946,112 @@
           }
       }
   
  +    public class GetOutputPropertyDatalet implements Datalet
  +    {
  +        public GetOutputPropertyDatalet(String[] args)
  +        {
  +            load(args);
  +        }
  +        public final String IDENTITY = "identity";
  +        protected String description = "no data";
  +        public String getDescription() { return description; }
  +        public void setDescription(String d) { description = d; }
  +        public Transformer transformer = null;
  +        public String propName = null;
  +        public String expectedValue = null;
  +        public String expectedException = null;
  +        public void load(String[] args)
  +        {
  +            try
  +            {
  +                if (IDENTITY.equals(args[0]))
  +                    transformer = (TransformerFactory.newInstance()).newTransformer();
  +                else
  +                    transformer = (TransformerFactory.newInstance()).newTransformer(new StreamSource(args[0]));
  +                propName = args[1];
  +                String tmp = args[2];
  +                // Semi-hack: if it looks like the FQCN of a 
  +                //  Throwable derivative, then use one 
  +                //  of those; otherwise, assume it's the expected 
  +                //  value to get back from getOutputProperty
  +                if ((tmp.indexOf("Exception") >= 0) || (tmp.indexOf("Error") >= 0))
  +                    expectedException = tmp;
  +                else
  +                    expectedValue = tmp;
  +            }
  +            catch (Throwable t)
  +            { /* no-op, let it fail elsewhere */
  +            }
  +        }
  +        public void load(Hashtable h)
  +        {
  +            transformer = (Transformer)h.get("transformer");
  +            propName = (String)h.get("propName");
  +            expectedValue  = (String)h.get("expectedValue ");
  +            expectedException = (String)h.get("expectedException");
  +        }
  +        
  +    } // end class GetOutputPropertyTestlet
  +
  +    /** 
  +     * Calls getOutputProperty() on the Transformer supplied, and 
  +     * then either validates the returned String, or the classname 
  +     * of any exception thrown.
  +     *
  +     * This is almost more complex to implement as a Testlet than
  +     * is really worth it, but I wanted to experiment with using one.
  +     */
  +    public class GetOutputPropertyTestlet extends TestletImpl
  +    {
  +        { thisClassName = "org.apache.qetest.xsl.GetOutputPropertyTestlet"; }
  +        public String getDescription() { return "gets OutputProperty and validates"; }
  +        public Datalet getDefaultDatalet()
  +        {
  +            return new GetOutputPropertyDatalet(new String[] { "identity", "method", "xml" });
  +        }
  +        public void execute(Datalet d)
  +        {
  +            GetOutputPropertyDatalet datalet = null;
  +            try
  +            {
  +                datalet = (GetOutputPropertyDatalet)d;
  +            }
  +            catch (ClassCastException e)
  +            {
  +                logger.checkErr("Datalet provided is not a GetOutputPropertyDatalet; cannot continue");
  +                return;
  +            }
  +            try
  +            {
  +                String val = datalet.transformer.getOutputProperty(datalet.propName);
  +                if (null != datalet.expectedValue)
  +                {
  +                    if (datalet.expectedValue.equals(val))
  +                        logger.checkPass(datalet.getDescription());
  +                    else
  +                        logger.checkFail(datalet.getDescription());
  +                }
  +                else if (null != datalet.expectedException)
  +                   logger.checkFail(datalet.getDescription());
  +            }
  +            catch (Throwable t)
  +            {
  +                if (null != datalet.expectedException)
  +                {
  +                    if (datalet.expectedException.equals(t.getClass().getName()))
  +                        logger.checkPass(datalet.getDescription());
  +                    else
  +                        logger.checkFail(datalet.getDescription());
  +                }
  +                else
  +                    logger.checkFail(datalet.getDescription() + ", threw: " + t.toString());
  +            }
  +        }
  +    } // end class GetOutputPropertyTestlet
   
       /**
        * Convenience method to print out usage information - update if needed.  
  -     *
  -     * NEEDSDOC ($objectName$) @return
  +     * @return usage string
        */
       public String usage()
       {
  @@ -859,9 +1067,7 @@
        */
       public static void main(String[] args)
       {
  -
           TransformerAPITest app = new TransformerAPITest();
  -
           app.doMain(args);
       }
   }
  
  
  
  1.1                  xml-xalan/test/java/src/org/apache/qetest/xsl/PerformanceDatalet.java
  
  Index: PerformanceDatalet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 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 apache@apache.org.
   *
   * 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/>.
   */
  
  /*
   *
   * Datalet.java
   *
   */
  package org.apache.qetest.xsl;
  import org.apache.qetest.*;
  
  import java.util.Hashtable;
  
  /**
   * Minimal interface defining a datalet, a single set of data 
   * for a simple test case.
   * A Datalet defines a single group of data that a matching 
   * Testlet needs to execute it's simple test case.
   * For example:
   *  - We define a Datalet that processes an XML file with a 
   *    stylesheet in a certain manner - perhaps using a specific 
   *    set of SAX calls.  
   *  - The Datalet takes as an argument a matching Datalet, that 
   *    defines any parameters that may change  - like the names 
   *    of the XML file and the stylesheet file to use.
   *  - Test authors or users running a harness or the like can 
   *    then easily define a large set of Datalets for various 
   *    types of input files that they want to test, and simply 
   *    pass a list or Vector of the Datalets to the Datalet to 
   *    be iterated over.
   * Normally Datalets will simply be collections of public members
   * that can be written or read by anyone.  An enclosing test can 
   * simply
   * @author Shane_Curcuru@lotus.com
   * @version $Id: PerformanceDatalet.java,v 1.1 2001/02/09 01:55:23 curcuru Exp $
   */
  public class PerformanceDatalet extends DataletImpl
  {
      /** URL of the stylesheet.  */
      public String inputName = "identity.xsl";
  
      /** URL of the xml document.  */
      public String xmlName = "identity.xml";
  
      /** URL to put output into.  */
      public String outputName = "identity.out";
  
      /** URL of the a gold file or data.  */
      public String goldName = "identity.gold";
  
      /** Flavor of a ProcessorWrapper to use.  */
      public String flavor = "trax";
  
      /** Number of loops to perform.  */
      public int iterations = 10;
  
      /** if we should preload a single process first.  */
      public boolean preload = true;
  
      /** Description of what this Datalet tests.  */
      protected String description = "PerformanceDatalet: String inputName, String xmlName, String outputName, String goldName, int iterations, boolean preload";
  
      /**
       * Accesor method for a brief description of this Datalet.  
       *
       * @return String describing the specific set of data 
       * this Datalet contains (can often be used as the description
       * of any check() calls made from the Testlet).
       */
      public String getDescription()
      {
          return description;
      }
  
  
      /**
       * Accesor method for a brief description of this Datalet.  
       *
       * @param s description to use for this Datalet.
       */
      public void setDescription(String s)
      {
          description = s;
      }
  
  
      /**
       * Load fields of this Datalet from a Hashtable.  
       * Caller must provide data for all of our fields.
       * 
       * @param Hashtable to load
       */
      public void load(Hashtable p)
      {
          if (null == p)
              return; //@todo should this have a return val or exception?
  
          inputName = (String)p.get("inputName");
          xmlName = (String)p.get("xmlName");
          outputName = (String)p.get("outputName");
          goldName = (String)p.get("goldName");
          flavor = (String)p.get("flavor");
          iterations = ((Integer)p.get("iterations")).intValue();
          try
          {
              // Check string value first
              String tmp = (String)p.get("preload");
              // Only check for non-default case
              if ("false".equalsIgnoreCase(tmp) || "no".equalsIgnoreCase(tmp))
                  preload = false;
          }
          catch (ClassCastException cce1)
          {
              try
              {
                  // Check boolean value next
                  Boolean tmp2 = (Boolean)p.get("preload");
                  preload = tmp2.booleanValue();
              }
              catch (ClassCastException cce2) 
              {
                  // No-op, leave as default
              }
          }
      }
  
      /**
       * Load fields of this Datalet from an array.  
       * Order: inputName, xmlName, outputName, goldName, flavor, iterations, preload
       * If too few args, then fields at end of list are left at default value.
       * @param args array of Strings
       */
      public void load(String[] args)
      {
          if (null == args)
              return; //@todo should this have a return val or exception?
  
          try
          {
              inputName = args[0];
              xmlName = args[1];
              outputName = args[2];
              goldName = args[3];
              flavor = args[4];
              try
              {
                  iterations = Integer.parseInt(args[5]);
              }
              catch (NumberFormatException  nfe)
              {
                  // No-op, leave as default and continue
              }
              String tmp = args[6];
              // Only check for non-default case
              if ("false".equalsIgnoreCase(tmp) || "no".equalsIgnoreCase(tmp))
                  preload = false;
          }
          catch (ArrayIndexOutOfBoundsException  aioobe)
          {
              // No-op, leave remaining items as default
          }
      }
  
  }  // end of class PerformanceDatalet
  
  
  
  
  1.1                  xml-xalan/test/java/src/org/apache/qetest/xsl/PerformanceTestlet.java
  
  Index: PerformanceTestlet.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 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 apache@apache.org.
   *
   * 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/>.
   */
  
  /*
   *
   * PerformanceTestlet.java
   *
   */
  package org.apache.qetest.xsl;
  import org.apache.qetest.*;
  import org.apache.qetest.xslwrapper.ProcessorWrapper;
  
  import java.io.File;
  
  /**
   * Testlet to capture basic timing performance data.
   *
   * @author Shane_Curcuru@lotus.com
   * @version $Id: PerformanceTestlet.java,v 1.1 2001/02/09 01:55:23 curcuru Exp $
   */
  public class PerformanceTestlet extends TestletImpl
  {
      // Initialize our classname for TestletImpl's main() method
      static { thisClassName = "org.apache.qetest.xsl.PerformanceTestlet"; }
  
      // Initialize our defaultDatalet
      { defaultDatalet = new PerformanceDatalet(); }
  
      /**
       * Accesor method for a brief description of this test.  
       *
       * @return String describing what this PerformanceTestlet does.
       */
      public String getDescription()
      {
          return "PerformanceTestlet: processes supplied file over multiple iterations and logs timing data";
      }
  
  
      /** Markers for performance logging - Preload time. */
      public static final String PERF_PRELOAD = "UPre;";
  
      /** Markers for performance logging - single iteration time. */
      public static final String PERF_ITERATION = "UItr;";
  
      /** Markers for performance logging - average of iteration times. */
      public static final String PERF_AVERAGE = "UAvg;";
  
      /** Markers for memory logging. */
      public static final String PERF_MEMORY = "UMem;";
  
      /**
       * Run this PerformanceTestlet: execute it's test and return.
       *
       * @param Datalet to use as data point for the test.
       */
      public void execute(Datalet d)
  	{
          PerformanceDatalet datalet = null;
          try
          {
              datalet = (PerformanceDatalet)d;
              
          }
          catch (ClassCastException e)
          {
              logger.checkErr("Datalet provided is not a PerformanceDatalet; cannot continue");
              return;
          }
          
          // Cleanup outName - delete the file on disk
          try
          {
              File outFile = new File(datalet.outputName);
              boolean btmp = outFile.delete();
              logger.logMsg(Logger.TRACEMSG, "Deleting OutFile of::" + datalet.outputName
                                   + " status: " + btmp);
          }
          catch (SecurityException se)
          {
              logger.logMsg(Logger.WARNINGMSG, "Deleting OutFile of::" + datalet.outputName
                                     + " threw: " + se.toString());
              // But continue anyways...
          }
  
          // Go do performance stuff!
          try
          {
              // Create a new ProcessorWrapper of appropriate flavor
              ProcessorWrapper processorWrapper = ProcessorWrapper.getWrapper(datalet.flavor);
              if (null == processorWrapper.createNewProcessor(null))
              {
                  logger.checkErr("ERROR: could not create processorWrapper, aborting.");
                  return;
              }
  
              logger.logMsg(Logger.TRACEMSG, "executing with: inputName=" + datalet.inputName
                            + " xmlName=" + datalet.xmlName + " outputName=" + datalet.outputName
                            + " goldName=" + datalet.goldName + " flavor="  + datalet.flavor
                            + " iterations=" + datalet.iterations + " preload=" + datalet.preload);
              // Prime the pump, so to speak, if desired
              if (datalet.preload)
              {
                  logMemory(true);  // dumps Runtime.freeMemory/totalMemory
                  long preloadTime = processorWrapper.processToFile(datalet.xmlName, datalet.inputName,
                                                      datalet.outputName);
  
                  if (preloadTime == ProcessorWrapper.ERROR)
                  {
                      logger.checkFail("ERROR: Preload process had a problem of::"
                                       + datalet.inputName);
                      return;
                  }
  
                  logger.logStatistic(Logger.STATUSMSG, preloadTime, 0, 
                                      PERF_PRELOAD + "Preload process of::" + datalet.inputName);
                  // @todo add verification of output file
              }
  
              logMemory(true);  // dumps Runtime.freeMemory/totalMemory
  
              long aggregate = 0L;
              int ctr;
              for (ctr = 1; ctr <= datalet.iterations; ctr++)
              {
                  long retVal;
  
                  // Note: We re-write the same output file each time, so 
                  //       I suppose in theory that could affect future iterations
                  retVal = processorWrapper.processToFile(datalet.xmlName, datalet.inputName, datalet.outputName);
  
                  if (retVal == ProcessorWrapper.ERROR)
                  {
                      logger.checkFail("ERROR: PerformanceTestlet problem on iteration(" 
                                       + ctr + ") of::" + datalet.inputName);
  
                      return;
                  }
  
                  // Increment our overall counter
                  aggregate += retVal;
                  // Log this particular iteration's time
                  logger.logStatistic(Logger.STATUSMSG, retVal, 0,
                                      PERF_ITERATION + "processToFile(" + ctr + ") of::"
                                      + datalet.inputName);
                  // Should really make this optional
                  logMemory(false);
              }
  
              logger.logStatistic(Logger.STATUSMSG, (aggregate / datalet.iterations), 0, 
                                  PERF_AVERAGE + "Average of (" + datalet.iterations
                                  + ") iterations of::" + datalet.inputName);
                                  
          }
          catch (Throwable t)
          {
              logger.checkFail("PerformanceTestlet of::" + datalet.inputName
                                   + " threw: " + t.toString());
              java.io.StringWriter sw = new java.io.StringWriter();
              java.io.PrintWriter pw = new java.io.PrintWriter(sw);
              t.printStackTrace(pw);
              logger.logArbitrary(Logger.ERRORMSG, sw.toString());
              return;
          }
  
          // If we get here, attempt to validate the contents of 
          //  the last outputFile created
          CheckService fileChecker = new XHTFileCheckService();
          if (Logger.PASS_RESULT
              != fileChecker.check(logger,
                                   new File(datalet.outputName), 
                                   new File(datalet.goldName), 
                                   getDescription() + ", " + datalet.getDescription())
             )
              logger.logMsg(Logger.WARNINGMSG, "Failure reason: " + fileChecker.getExtendedInfo());
  	}
  
  
      /**
       * Worker method: just reports Runtime.totalMemory/freeMemory.  
       */
      protected void logMemory(boolean doGC)
      {
          if (doGC)
          {
              Runtime.getRuntime().gc();
          }
          logger.logStatistic(Logger.STATUSMSG, Runtime.getRuntime().freeMemory(), 0, PERF_MEMORY + "freeMemory");
          logger.logStatistic(Logger.STATUSMSG, Runtime.getRuntime().totalMemory(), 0, PERF_MEMORY + "totalMemory");
      }
  
  }  // end of class PerformanceTestlet