Clover coverage report - JFCUnit Test Coverage
Coverage timestamp: Mon Dec 20 2004 23:38:10 MST
file stats: LOC: 403   Methods: 14
NCLOC: 237   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
XMLRoot.java 0% 0% 0% 0%
coverage
 1   
 package junit.extensions.jfcunit.tools;
 2   
 
 3   
 import junit.extensions.jfcunit.xml.XMLRecorder;
 4   
 
 5   
 import junit.extensions.xml.XMLTestSuite;
 6   
 import junit.extensions.xml.XMLUtil;
 7   
 
 8   
 import junit.framework.Test;
 9   
 
 10   
 import junit.textui.TestRunner;
 11   
 
 12   
 import java.io.File;
 13   
 import java.io.FileInputStream;
 14   
 import java.io.FileNotFoundException;
 15   
 import java.io.FileOutputStream;
 16   
 import java.io.IOException;
 17   
 import java.io.InputStream;
 18   
 import java.io.PrintWriter;
 19   
 
 20   
 import java.lang.reflect.InvocationTargetException;
 21   
 import java.lang.reflect.Method;
 22   
 
 23   
 import java.util.StringTokenizer;
 24   
 
 25   
 
 26   
 /**
 27   
  * <p>Title: JFCUnit</p>
 28   
  * <p>Description: This class is a tool class which interfaces
 29   
  * a JUnit test environment to the JFCUnits XML test environment.
 30   
  * The application can be passed through system properties, the constructor,
 31   
  * the static call to get the test suite, or through the main methods arguments.
 32   
  *
 33   
  * When XMLRoot is instanciated with no arguments then the
 34   
  * following system properties are queried.
 35   
  *
 36   
  * jfcunit.xmlroot.classname required main classname.
 37   
  * jfcunit.xmlroot.args      optional parameters to the main method.
 38   
  * jfcunit.xmlroot.testsuite XML test suite to be run.
 39   
  * jfcunit.xmlroot.record    If not specified the record tags will be ignored.
 40   
  * jfcunit.xmlroot.create    Create a new xml file if it does not exist.
 41   
  * </p>
 42   
  * @author kevin wilson
 43   
  * @version 1.0
 44   
  */
 45   
 public class XMLRoot extends XMLTestSuite {
 46   
     /** Document factory to be used as default. */
 47   
     public static final String DOCUMENT_FACTORY = "javax.xml.parsers.DocumentBuilderFactory";
 48   
 
 49   
     /** System property for classname. */
 50   
     public static final String XMLROOT_CLASSNAME = "jfcunit.xmlroot.classname";
 51   
 
 52   
     /** System property for args. */
 53   
     public static final String XMLROOT_ARGS = "jfcunit.xmlroot.args";
 54   
 
 55   
     /** System property for recording. */
 56   
     public static final String XMLROOT_RECORD = "jfcunit.xmlroot.record";
 57   
 
 58   
     /** System property for XML file. */
 59   
     public static final String XMLROOT_TESTSUITE = "jfcunit.xmlroot.testsuite";
 60   
 
 61   
     /** System property for create the xml root. */
 62   
     public static final String XMLROOT_CREATE = "jfcunit.xmlroot.create";
 63   
 
 64   
     /**
 65   
      * Default constructor. Uses system properties to get the classname and
 66   
      * testsuite filename.
 67   
      * @throws Exception may be thrown.
 68   
      */
 69  0
     public XMLRoot() throws Exception {
 70  0
         this(
 71   
             getClassName(),
 72   
             getArgs(),
 73   
             getTestSuite());
 74   
     }
 75   
 
 76   
     /**
 77   
      * Default constructor.
 78   
      * @param classname Class name of the main application class
 79   
      * @param args Arguments to be passed to the main method.
 80   
      * @param filename The filename of the XML test suite specification
 81   
      * @throws Exception may be thrown.
 82   
      */
 83  0
     public XMLRoot(final String classname, final String[] args,
 84   
         final String filename) throws Exception {
 85  0
         super(filename,
 86   
             getInputStream(
 87   
                 classname.trim(),
 88   
                 args,
 89   
                 filename));
 90   
 
 91  0
         Class        applClass = getClass().getClassLoader().loadClass(
 92   
                 classname.trim());
 93  0
         Class[]      parameterSpec = {String[].class};
 94  0
         final Method mainMethod    = applClass.getMethod("main", parameterSpec);
 95  0
         XMLRecorder.setReplay(!getRecord());
 96   
 
 97  0
         final String[] appArgs;
 98   
 
 99  0
         if (args == null) {
 100  0
             appArgs = new String[0];
 101   
         } else {
 102  0
             appArgs = args;
 103   
         }
 104   
 
 105  0
         final Object[] parameters = {appArgs};
 106   
 
 107   
         // Start the main from another thread so this does not block the test case
 108   
         // in cases where the main method does not return.
 109  0
         new Thread(
 110   
             new Runnable() {
 111  0
                 public void run() {
 112  0
                     try {
 113  0
                         mainMethod.invoke(null, parameters);
 114   
                     } catch (IllegalAccessException ex) {
 115  0
                         System.err.println(
 116   
                             "Exception occured while invoking application:"
 117   
                             + classname);
 118  0
                         ex.printStackTrace();
 119   
                     } catch (IllegalArgumentException ex) {
 120  0
                         System.err.println(
 121   
                             "Exception occured while invoking application:"
 122   
                             + classname);
 123  0
                         ex.printStackTrace();
 124   
                     } catch (InvocationTargetException ex) {
 125  0
                         System.err.println(
 126   
                             "Exception occured while invoking application:"
 127   
                             + classname);
 128  0
                         ex.printStackTrace();
 129   
                     }
 130   
                 }
 131   
             }).start();
 132   
     }
 133   
 
 134   
     /**
 135   
      * Application start method. The application takes two arguments:
 136   
      *    &gt;main class&lt; The Main class of the application to test
 137   
      *    &gt;test suite specification&lt; The XML file containing the test suite
 138   
      * @param args classname [args...] xmlfile
 139   
      * @throws Exception may be thrown.
 140   
      */
 141  0
     public static void main(final String[] args) throws Exception {
 142  0
         updateDocFactory();
 143   
 
 144  0
         if (args.length < 2) {
 145  0
             TestRunner.run((Test) XMLRoot.suite());
 146  0
         } else if (args.length >= 2) {
 147  0
             System.out.println("Application Class = " + args[0]);
 148   
 
 149  0
             String[] progArgs = new String[args.length - 2];
 150   
 
 151  0
             for (int i = 1; i < (args.length - 1); i++) {
 152  0
                 progArgs[i - 1] = args[i];
 153   
             }
 154   
 
 155  0
             System.out.println("Test Suite = " + args[args.length - 1]);
 156   
 
 157  0
             TestRunner.run((Test) XMLRoot.suite(args[0], progArgs,
 158   
                     args[args.length - 1]));
 159   
         } else {
 160  0
             System.out.println(
 161   
                 "Usage: junit.extensions.jfcunit.tools.XMLRoot mainclass  [class arguments...] [xml file]");
 162  0
             System.exit(1);
 163   
         }
 164   
     }
 165   
 
 166   
     /**
 167   
      * Creates a new test suite based on the system properties.
 168   
      * @return Test generated from the System properties.
 169   
      * @throws Exception may be thrown.
 170   
      */
 171  0
     public static Test suite() throws Exception {
 172  0
         updateDocFactory();
 173   
 
 174  0
         return new XMLRoot();
 175   
     }
 176   
 
 177   
     /**
 178   
      * Creates a new test suite based on the main class and filename provided.
 179   
      * @param classname Class name of the main application class
 180   
      * @param args Arguments to be passed to the application.
 181   
      * @param filename Name of XML file containing test suite
 182   
      * @return Test created with the given arguments.
 183   
      * @throws Exception may be thrown.
 184   
      */
 185  0
     public static Test suite(final String classname, final String[] args,
 186   
         final String filename) throws Exception {
 187  0
         updateDocFactory();
 188   
 
 189  0
         return new XMLRoot(classname, args, filename);
 190   
     }
 191   
 
 192   
     /**
 193   
      * Get the jfcunit.xmlroot.args system property.
 194   
      * @return Arguments to be run with the command.
 195   
      * Assumes space separated list. May not work for
 196   
      * all cases of program arguments.
 197   
      */
 198  0
     protected static final String[] getArgs() {
 199  0
         String args = System.getProperty(XMLROOT_ARGS);
 200   
 
 201  0
         if (args == null) {
 202  0
             return null;
 203   
         }
 204   
 
 205  0
         StringTokenizer st     = new StringTokenizer(args, " ");
 206  0
         String[]        tokens = new String[st.countTokens()];
 207  0
         int             i      = 0;
 208   
 
 209  0
         while (st.hasMoreTokens()) {
 210  0
             tokens[i++] = st.nextToken();
 211   
         }
 212   
 
 213  0
         return tokens;
 214   
     }
 215   
 
 216   
     /**
 217   
      * Get the jfcunit.xmlroot.classname system property.
 218   
      * @return class name to be executed.
 219   
      */
 220  0
     protected static final String getClassName() {
 221  0
         String classname = System.getProperty(XMLROOT_CLASSNAME);
 222   
 
 223  0
         if (classname == null) {
 224  0
             throw new RuntimeException("Could not find system property:"
 225   
                 + XMLROOT_CLASSNAME);
 226   
         }
 227   
 
 228  0
         return classname;
 229   
     }
 230   
 
 231   
     /**
 232   
      * Assembles the classname and args into one string.
 233   
      * @param classname program name.
 234   
      * @param args Arguments used.
 235   
      * @return Program and arguments.
 236   
      */
 237  0
     protected static final String getCommand(final String classname,
 238   
         final String[] args) {
 239  0
         StringBuffer buf = new StringBuffer(1000);
 240  0
         buf.append(classname);
 241  0
         buf.append(" ");
 242   
 
 243  0
         if (args != null) {
 244  0
             for (int i = 0; i < args.length; i++) {
 245  0
                 buf.append(args[i]);
 246  0
                 buf.append(" ");
 247   
             }
 248   
         }
 249   
 
 250  0
         return buf.toString();
 251   
     }
 252   
 
 253   
     /**
 254   
      * Get the XML file name from the jfcunit.xmlroot.create system property.
 255   
      * @return true if the xml file should be created.
 256   
      */
 257  0
     protected static final boolean getCreate() {
 258  0
         if (getRecord()) {
 259  0
             return Boolean.getBoolean(XMLROOT_CREATE);
 260   
         }
 261   
 
 262  0
         return false;
 263   
     }
 264   
 
 265   
     /**
 266   
      * Get the input stream for the XML file. If a XML file
 267   
      * cannot be found then a template will be generated
 268   
      * for recording.
 269   
      *
 270   
      * @param classname Classname added to template.
 271   
      * @param args      Arguments to be added to the template.
 272   
      * @param fileName  XML file name to be opened or created.
 273   
      * @return Input stream of the file opened.
 274   
      */
 275  0
     protected static InputStream getInputStream(final String classname,
 276   
         final String[] args, final String fileName) {
 277  0
         InputStream is = null;
 278   
 
 279  0
         try {
 280  0
             is = XMLUtil.readFileFromClasspath(fileName);
 281   
         } catch (Exception e) {
 282   
             ; // Ignore exception
 283   
         }
 284   
 
 285  0
         if (is != null) {
 286   
             // If record is turned on then save the file to the
 287   
             // current directory. Then it may be recorded to.
 288  0
             return is;
 289   
         } else {
 290   
             // Look in the local directory.
 291  0
             File file = new File(fileName);
 292   
 
 293  0
             if (file.exists()) {
 294  0
                 try {
 295   
                     // Found the file so we will open the file.
 296  0
                     is = new FileInputStream(file);
 297   
                 } catch (FileNotFoundException ex) {
 298  0
                     System.err.println("Error opening local file." + fileName);
 299  0
                     is = null;
 300   
                 }
 301   
 
 302  0
                 return is;
 303   
             } else {
 304  0
                 if (!getCreate()) {
 305  0
                     System.err.println("File not found:" + fileName);
 306   
                 } else {
 307  0
                     try {
 308   
                         // File was not found so we will create a new file.
 309  0
                         file.createNewFile();
 310   
 
 311  0
                         FileOutputStream os = new FileOutputStream(file);
 312  0
                         PrintWriter      pw = new PrintWriter(os);
 313  0
                         pw.println("<?xml version=\"1.0\" ?>");
 314  0
                         pw.println(
 315   
                             "<!-- An example test suite template              -->");
 316  0
                         pw.println(
 317   
                             "<!-- The first step in creating the test case is -->");
 318  0
                         pw.println(
 319   
                             "<!-- to document what is going to be tested.     -->");
 320  0
                         pw.println(
 321   
                             "<!-- To do this, create the test suites and      -->");
 322  0
                         pw.println(
 323   
                             "<!-- test cases which are to be recorded.        -->");
 324  0
                         pw.println(
 325   
                             "<!-- 2. Setup the JFCXMLTestCase extension,      -->");
 326  0
                         pw.println(
 327   
                             "<!-- to startup your application.                -->");
 328  0
                         pw.println(
 329   
                             "<!-- 3. Run the JFCXMLTestCase defined above.    -->");
 330  0
                         pw.println(
 331   
                             "<!-- 4. While the test case is running each      -->");
 332  0
                         pw.println(
 333   
                             "<!-- \"record\" element will add to the XML.       -->");
 334  0
                         pw.print("<suite name=\"");
 335  0
                         pw.print(getCommand(classname, args));
 336  0
                         pw.println("\">");
 337  0
                         pw.println("    <!-- definition of a local suite -->");
 338  0
                         pw.println("    <suite name=\"Recording test suite\">");
 339  0
                         pw.println(
 340   
                             "        <test name=\"Recording test\" robot=\"true\">");
 341  0
                         pw.print(
 342   
                             "             <record encoding=\"UTF-8\" file=\"");
 343  0
                         pw.print(fileName);
 344  0
                         pw.println("\"/>");
 345  0
                         pw.println("        </test>");
 346  0
                         pw.println("    </suite>");
 347  0
                         pw.println("</suite>");
 348   
 
 349  0
                         pw.close();
 350  0
                         os.close();
 351   
 
 352  0
                         return new FileInputStream(file);
 353   
                     } catch (IOException ex1) {
 354  0
                         System.err.println("Error creating new XML file."
 355   
                             + fileName);
 356  0
                         ex1.printStackTrace();
 357   
                     }
 358   
                 }
 359   
             }
 360   
         }
 361   
 
 362  0
         return null;
 363   
     }
 364   
 
 365   
     /**
 366   
      * Get the state of the jfcunit.xmlroot.record system property.
 367   
      * @return true if the record element is present and set to true.
 368   
      */
 369  0
     protected static final boolean getRecord() {
 370  0
         return Boolean.getBoolean(XMLROOT_RECORD);
 371   
     }
 372   
 
 373   
     /**
 374   
      * Get the XML file name from the jfcunit.xmlroot.testsuite system property.
 375   
      * @return XML file name.
 376   
      */
 377  0
     protected static final String getTestSuite() {
 378  0
         String testsuite = System.getProperty(XMLROOT_TESTSUITE);
 379   
 
 380  0
         if (testsuite == null) {
 381  0
             throw new RuntimeException("Could not find system property: "
 382   
                 + XMLROOT_TESTSUITE);
 383   
         }
 384   
 
 385  0
         return testsuite;
 386   
     }
 387   
 
 388   
     /**
 389   
      * Set the document factory if it is not set for java
 390   
      * versions less than 1.4.
 391   
      */
 392  0
     private static void updateDocFactory() {
 393  0
         String version = System.getProperty("java.version");
 394   
 
 395  0
         if (version.startsWith("1.2") || version.startsWith("1.3")) {
 396  0
             if (System.getProperty(DOCUMENT_FACTORY) == null) {
 397  0
                 System.setProperty(DOCUMENT_FACTORY,
 398   
                     "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
 399   
             }
 400   
         }
 401   
     }
 402   
 }
 403