Clover coverage report - gsbase - 2.0.1
Coverage timestamp: Sat Jan 1 2005 12:30:02 EST
file stats: LOC: 295   Methods: 7
NCLOC: 153   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
RecursiveTestSuite.java 15.4% 10.1% 14.3% 11.8%
coverage coverage
 1    /*
 2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
 3    *
 4    * Redistribution and use in source and binary forms, with or without
 5    * modification, are permitted provided that the following conditions are met:
 6    *
 7    * 1. Redistributions of source code must retain the above copyright notice,
 8    * this list of conditions and the following disclaimer.
 9    * 2. Redistributions in binary form must reproduce the above copyright notice,
 10    * this list of conditions and the following disclaimer in the documentation
 11    * and/or other materials provided with the distribution.
 12    * 3. The end-user documentation included with the redistribution, if any, must
 13    * include the following acknowledgment:
 14    *
 15    * "This product includes software developed by Gargoyle Software Inc.
 16    * (http://www.GargoyleSoftware.com/)."
 17    *
 18    * Alternately, this acknowledgment may appear in the software itself, if
 19    * and wherever such third-party acknowledgments normally appear.
 20    * 4. The name "Gargoyle Software" must not be used to endorse or promote
 21    * products derived from this software without prior written permission.
 22    * For written permission, please contact info@GargoyleSoftware.com.
 23    * 5. Products derived from this software may not be called "GSBase", nor may
 24    * "GSBase" appear in their name, without prior written permission of
 25    * Gargoyle Software Inc.
 26    *
 27    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 28    * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 29    * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
 30    * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 31    * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 32    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 33    * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 34    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 35    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 36    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 37    */
 38    package com.gargoylesoftware.base.testing;
 39   
 40    import com.gargoylesoftware.base.collections.StringComparator;
 41    import com.gargoylesoftware.base.trace.Trace;
 42    import com.gargoylesoftware.base.util.DetailedIllegalArgumentException;
 43    import java.io.File;
 44    import java.io.IOException;
 45    import java.lang.reflect.Method;
 46    import java.util.ArrayList;
 47    import java.util.Iterator;
 48    import java.util.List;
 49    import java.util.Locale;
 50    import java.util.Set;
 51    import java.util.SortedSet;
 52    import java.util.TreeSet;
 53    import junit.framework.Test;
 54    import junit.framework.TestCase;
 55    import junit.framework.TestSuite;
 56    import junit.textui.TestRunner;
 57   
 58    /**
 59    * A launching point for executing test cases. This recusively walks through
 60    * the directory structure looking for classes that end in Test.class. It then
 61    * loads these classes to see if they are instances of TestCase. If so, they
 62    * are added to the test suite. Once all directories have been scanned, the
 63    * test cases are executed.
 64    *
 65    * @version $Revision: 1.4 $
 66    * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
 67    */
 68    public class RecursiveTestSuite extends TestSuite {
 69   
 70    private final TestFilter testFilter_;
 71   
 72   
 73    /**
 74    * Create a new instance
 75    *
 76    * @param testFilter The object that will filter out tests that we don't
 77    * wish to run
 78    * @param startingPath The directory that we will start our descent in.
 79    * @exception IOException If anything goes wrong during the directory
 80    * scanning.
 81    */
 82  0 public RecursiveTestSuite(
 83    final String startingPath,
 84    final TestFilter testFilter )
 85    throws
 86    IOException {
 87   
 88  0 this( new File( startingPath ), testFilter );
 89    }
 90   
 91   
 92    /**
 93    * Create an instance
 94    *
 95    * @param testFilter The object that will filter out tests that we don't
 96    * wish to run
 97    * @param startingPath The directory that we will start our descent in.
 98    * @exception IOException If anything goes wrong during the directory
 99    * scanning.
 100    */
 101  3 public RecursiveTestSuite(
 102    final File startingPath,
 103    final TestFilter testFilter )
 104    throws
 105    IOException {
 106   
 107  3 super( "RecursiveTestSuite(" + startingPath + ")" );
 108   
 109  3 if( testFilter == null ) {
 110  1 throw new NullPointerException( "testFilter" );
 111    }
 112  2 if( startingPath == null ) {
 113  0 throw new NullPointerException( "startingPath" );
 114    }
 115  2 testFilter_ = testFilter;
 116   
 117  2 if( startingPath.exists() == false ) {
 118  2 throw new DetailedIllegalArgumentException( "startingPath", startingPath, "Doesn't exist");
 119    }
 120  0 if( startingPath.isDirectory() == false ) {
 121  0 throw new DetailedIllegalArgumentException( "startingPath", startingPath, "Isn't a directory" );
 122    }
 123   
 124  0 final long startTime = System.currentTimeMillis();
 125  0 final Set classNames = findAllTestClasses( startingPath );
 126  0 final long endTime = System.currentTimeMillis();
 127  0 System.out.println( "Scanning for classes: Time=["
 128    + ( ( endTime - startTime ) / 1000F )
 129    + " seconds] Found=["
 130    + classNames.size()
 131    + " classes]" );
 132   
 133  0 final Iterator iterator = classNames.iterator();
 134   
 135  0 while( iterator.hasNext() ) {
 136  0 addTest( getTestForClass( (Class)iterator.next() ) );
 137    }
 138    }
 139   
 140   
 141    /**
 142    * Main entry point.
 143    *
 144    * @param args The arguments
 145    */
 146  0 public static void main( final String args[] ) {
 147   
 148  0 Trace.getController().setOutRedirected( true );
 149  0 Trace.getController().setErrRedirected( true );
 150   
 151    // Force the load of AWT
 152  0 new javax.swing.JPanel();
 153   
 154  0 try {
 155  0 final String startingPath;
 156  0 if( args.length == 0 ) {
 157  0 startingPath = ".";
 158    }
 159    else {
 160  0 startingPath = args[0];
 161    }
 162  0 final RecursiveTestSuite suite = new RecursiveTestSuite( startingPath, new AcceptAllTestFilter() );
 163   
 164    // TestRunner.run() will invoke System.exit() so we have
 165    // to disable the buffering now.
 166  0 Trace.getController().setBufferingEnabled( false );
 167   
 168  0 if( suite.testCount() == 0 ) {
 169  0 Trace.println( "Nothing to do." );
 170    }
 171    else {
 172  0 TestRunner.run( suite );
 173    }
 174    }
 175    catch( final Throwable t ) {
 176  0 Trace.printStackTrace( Trace.out, t );
 177    }
 178  0 Trace.exit( 0 );
 179    }
 180   
 181   
 182    /**
 183    * Dummy test so that JUnit doesn't complain that this suite doesn't have
 184    * any tests.
 185    */
 186  0 public void testFoo() {
 187    }
 188   
 189   
 190    // protected Collection findPotentialClasses() {
 191    // final DirectoryWalker walker = new DirectoryWalker( "." );
 192    // return Collections.EMPTY_LIST;
 193    // }
 194   
 195   
 196    /**
 197    * Return a test suite containing all the tests for the specified class. If
 198    * the class has a suite() method then it will be used to get the tests,
 199    * otherwise reflection will be used.
 200    *
 201    * @param clazz Description of Parameter
 202    * @return The testSuiteForClass value
 203    */
 204  0 private Test getTestForClass( final Class clazz ) {
 205  0 try {
 206  0 final Method method = clazz.getDeclaredMethod( "suite", new Class[0] );
 207  0 return (Test)method.invoke( null, new Object[0] );
 208    }
 209    catch( final NoSuchMethodException e ) {
 210    // Fall through
 211    }
 212    catch( final Exception e ) {
 213  0 e.printStackTrace();
 214    }
 215   
 216  0 return new TestSuite( clazz );
 217    }
 218   
 219   
 220    /**
 221    * @param startingDirectory Description of Parameter
 222    * @return Description of the Returned Value
 223    * @exception IOException Description of Exception
 224    */
 225  0 private Set findAllTestClasses( final File startingDirectory )
 226    throws IOException {
 227   
 228  0 final List list = new ArrayList();
 229  0 final SortedSet set
 230    = new TreeSet( new StringComparator( Locale.getDefault() ) );
 231   
 232  0 findAllTestClasses( startingDirectory, list );
 233   
 234  0 final String startingDirectoryFullPath
 235    = startingDirectory.getCanonicalPath();
 236  0 final int startingDirLength
 237    = startingDirectoryFullPath.length() + File.separator.length();
 238   
 239  0 String className;
 240  0 Class clazz;
 241   
 242  0 final Iterator iterator = list.iterator();
 243  0 while( iterator.hasNext() ) {
 244  0 className = ( (String)iterator.next() );
 245  0 className = className.substring( startingDirLength,
 246    className.length() - ".class".length() );
 247  0 className = className.replace( File.separatorChar, '.' );
 248   
 249  0 try {
 250  0 clazz = Class.forName( className );
 251  0 if( TestCase.class.isAssignableFrom( clazz )
 252    && testFilter_.accept( clazz ) ) {
 253  0 set.add( clazz );
 254    }
 255    }
 256    catch( final ClassNotFoundException e ) {
 257  0 Trace.printStackTrace( Trace.out, e );
 258    }
 259    }
 260  0 return set;
 261    }
 262   
 263   
 264    /**
 265    * @param directory Description of Parameter
 266    * @param list Description of Parameter
 267    * @exception IOException Description of Exception
 268    */
 269  0 private void findAllTestClasses( final File directory, final List list )
 270    throws IOException {
 271   
 272  0 final String files[] = directory.list();
 273  0 if( files == null ) {
 274  0 return;
 275    }
 276   
 277  0 final String directoryName = directory.getCanonicalPath();
 278  0 String fileName;
 279   
 280  0 int i;
 281  0 for( i = 0; i < files.length; i++ ) {
 282  0 fileName = directoryName + File.separator + files[i];
 283  0 if( files[i].endsWith( "Test.class" ) ) {
 284  0 list.add( fileName );
 285    }
 286    else {
 287  0 final File file = new File( fileName );
 288  0 if( file.isDirectory() ) {
 289  0 findAllTestClasses( file, list );
 290    }
 291    }
 292    }
 293    }
 294    }
 295