Browse Source

Making progress to collect JUnit tests.

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270673 13f79535-47bb-0310-9956-ffa450edef68
master
Stephane Bailliez 23 years ago
parent
commit
a25bca9c14
5 changed files with 574 additions and 6 deletions
  1. +99
    -0
      proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTestElement.java
  2. +176
    -0
      proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/ClasspathTestCollector.java
  3. +36
    -6
      proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
  4. +70
    -0
      proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestElement.java
  5. +193
    -0
      proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/ZipScanner.java

+ 99
- 0
proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTestElement.java View File

@@ -0,0 +1,99 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 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 acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", 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 names without prior written
* permission of the Apache Group.
*
* 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. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.taskdefs.optional.junit;

import java.util.Enumeration;

import junit.runner.TestCollector;

import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.PatternSet;

/**
* A test element where tests files are specified by include/exclude
* patterns. tests files location are specified by one ore multiple
* path elements. (directory or archive).
*
* <pre>
* <!ELEMENT batchtest>
* <!ATTLIST batchtest path CDATA required>
* </pre>
*
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
*/
public class BatchTestElement implements TestCollector {

private ClasspathTestCollector collector = new ClasspathTestCollector();

// Test collector implementation

public Enumeration collectTests() {
return collector.collectTests();
}

// Ant bean accessors

public void setPath(Path path) {
collector.setPath(path);
}

public PatternSet.NameEntry createInclude() {
return collector.createInclude();
}

public PatternSet.NameEntry createExclude() {
return collector.createExclude();
}

}

+ 176
- 0
proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/ClasspathTestCollector.java View File

@@ -0,0 +1,176 @@
/*
* 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 acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", 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 names without prior written
* permission of the Apache Group.
*
* 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. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.taskdefs.optional.junit;

import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;
import java.io.File;

import junit.runner.TestCollector;

import org.apache.tools.ant.types.PatternSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;

/**
* A rough implementation of a test collector that will collect tests
* using include/exclude patterns in a set of paths. A path can either
* be a directory or an archive. (zip or jar file)
*
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
*/
public class ClasspathTestCollector extends ProjectComponent
implements TestCollector {

private final static int SUFFIX_LENGTH= ".class".length();

private PatternSet patterns = new PatternSet();

private Path path = null;

public Enumeration collectTests() {
Hashtable collected = new Hashtable();
// start from last, so that first elements
// override last one in case there are duplicates.
// ie mimic classpath behavior.
String[] paths = path.list();
for (int i = paths.length; i >= 0; i--){
File f = new File(paths[i]);
Vector included = null;
if ( f.isDirectory() ){
included = gatherFromDirectory(f);
} else if ( f.getName().endsWith(".zip")
|| f.getName().endsWith(".jar") ) {
included = gatherFromArchive(f);
} else {
continue;
}
// add tests to the already collected one
final int includedCount = included.size();
for (int j = 0; j < includedCount; j++){
String testname = (String)included.elementAt(i);
collected.put(testname, "");
}
}
return collected.keys();
}


protected Vector gatherFromDirectory(File dir){
Project project = getProject();
DirectoryScanner ds = new DirectoryScanner();
ds.setBasedir(dir);
ds.setIncludes(patterns.getIncludePatterns(project));
ds.setExcludes(patterns.getExcludePatterns(project));
ds.scan();
String[] included = ds.getIncludedFiles();
return testClassNameFromFile(included);
}

protected Vector gatherFromArchive(File zip){
ZipScanner zs = new ZipScanner();
zs.setBasedir(zip);
zs.setIncludes(patterns.getIncludePatterns(project));
zs.setExcludes(patterns.getExcludePatterns(project));
zs.scan();
String[] included = zs.getIncludedFiles();
return testClassNameFromFile(included);
}

protected Vector testClassNameFromFile(String[] classFileNames){
Vector tests = new Vector(classFileNames.length);
for (int i = 0; i < classFileNames.length; i++){
String file = classFileNames[i];
if ( isTestClass(file) ){
String classname = classNameFromFile(file);
tests.addElement(classname);
}
}
return tests;
}

protected boolean isTestClass(String classFileName) {
return classFileName.endsWith(".class");
}

protected String classNameFromFile(String classFileName) {
// convert /a/b.class to a.b
String s= classFileName.substring(0, classFileName.length()-SUFFIX_LENGTH);
String s2= s.replace(File.separatorChar, '.');
if ( s2.startsWith(".") ){
s2 = s2.substring(1);
}
return s2;
}

// Ant bean accessors

public void setPath(Path path){
this.path = path;
}

public PatternSet.NameEntry createInclude(){
return patterns.createInclude();
}

public PatternSet.NameEntry createExclude(){
return patterns.createExclude();
}

}

+ 36
- 6
proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java View File

@@ -60,6 +60,9 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.Vector;
import java.util.Enumeration;

import junit.runner.TestCollector;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
@@ -73,6 +76,7 @@ import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.FileUtils;

/**
* The core JUnit task.
*
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
*/
@@ -87,6 +91,9 @@ public class JUnitTask extends Task {
/** formatters that write the tests results */
private Vector formatters = new Vector();

/** test collector elements */
private Vector testCollectors = new Vector();

/** stop the test run if a failure occurs */
private boolean haltOnFailure = false;

@@ -126,13 +133,14 @@ public class JUnitTask extends Task {
props.setProperty("debug", "true");
props.setProperty("host", "127.0.0.1");
props.setProperty("port", String.valueOf(port));
StringBuffer classnames = new StringBuffer();
//@fixme get all test classes to run...
final int testcount = 0;
for (int i = 0; i < testcount; i++) {
classnames.append("<classname>").append("\n");
// get all test classes to run...
StringBuffer buf = new StringBuffer(10240);
Enumeration classnames = collectTests();
while ( classnames.hasMoreElements() ){
String classname = (String)classnames.nextElement();
buf.append(classname).append(" ");
}
props.setProperty("classnames", classnames.toString());
props.setProperty("classnames", buf.toString());

// dump the properties to a temporary file.
FileUtils futils = FileUtils.newFileUtils();
@@ -159,6 +167,18 @@ public class JUnitTask extends Task {
return f;
}

/**
* @return all collected tests specified with test elements.
*/
protected Enumeration collectTests(){
Enumeration[] tests = new Enumeration[testCollectors.size()];
for (int i = 0; i < testCollectors.size(); i++){
TestCollector te = (TestCollector)testCollectors.elementAt(i);
tests[i] = te.collectTests();
}
return Enumerations.fromCompound(tests);
}

// Ant bean accessors

public void setPort(int port) {
@@ -183,6 +203,16 @@ public class JUnitTask extends Task {
this.formatters.addElement(f);
}

/** add a single test element */
public void addTest(TestElement te) {
this.testCollectors.addElement(te);
}

/** add a batch test element */
public void addBatchTest(BatchTestElement bte) {
this.testCollectors.addElement(bte);
}

/**
* Set the maximum memory to be used by the TestRunner
* @param max the value as defined by <tt>-mx</tt> or <tt>-Xmx</tt>


+ 70
- 0
proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/TestElement.java View File

@@ -0,0 +1,70 @@
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 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 acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", 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 names without prior written
* permission of the Apache Group.
*
* 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. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.taskdefs.optional.junit;

import java.util.Enumeration;

import junit.runner.TestCollector;

/**
* A simple test element.
*
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
*/
public class TestElement implements TestCollector {

public Enumeration collectTests() {
return null;
}
}

+ 193
- 0
proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/ZipScanner.java View File

@@ -0,0 +1,193 @@
/*
* 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 acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Ant", 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 names without prior written
* permission of the Apache Group.
*
* 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. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.tools.ant.taskdefs.optional.junit;

import java.io.File;
import java.io.IOException;
import java.util.Vector;
import java.util.Enumeration;
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;

import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.FileScanner;
import org.apache.tools.ant.BuildException;

/**
* Provide a way to scan entries in a zip file. Note that it extends
* DirectoryScanner to make use of protected methods but implementation
* may not be valid for some methods.
* <p>
* the setBaseDir() must be called to set the reference to the archive
* file (.jar or .zip).
* </p>
*
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
*/
public class ZipScanner extends DirectoryScanner {
public ZipScanner() {
}

public void setExcludes(String[] excludes) {
super.setExcludes(excludes);
normalize(this.excludes);
}

public void setIncludes(String[] includes) {
super.setIncludes(includes);
normalize(this.includes);
}

/**
* normalize a set of paths so that it uses / otherwise matching will
* fail beautifully since archives use / to denote a path.
*/
protected void normalize(String[] files){
if (files != null){
for (int i = 0; i < files.length; i++){
files[i] = files[i].replace('\\','/');
}
}
}

/**
* Scans the archive for files that match at least one include
* pattern, and don't match any exclude patterns.
*
* @exception IllegalStateException when the zip file was set incorrecly
*/
public void scan() {
if (basedir == null) {
throw new IllegalStateException("No zipfile set");
}
if (!basedir.exists()) {
throw new IllegalStateException("zipfile " + basedir
+ " does not exist");
}
if (basedir.isDirectory()) {
throw new IllegalStateException("zipfile " + basedir
+ " is not a file");
}

if (includes == null) {
// No includes supplied, so set it to 'matches all'
includes = new String[1];
includes[0] = "**";
}
if (excludes == null) {
excludes = new String[0];
}

filesIncluded = new Vector();
filesNotIncluded = new Vector();
filesExcluded = new Vector();
dirsIncluded = new Vector();
dirsNotIncluded = new Vector();
dirsExcluded = new Vector();

if (isIncluded("")) {
if (!isExcluded("")) {
dirsIncluded.addElement("");
} else {
dirsExcluded.addElement("");
}
} else {
dirsNotIncluded.addElement("");
}
scandir(basedir, "", true);
}

protected void scandir(File file, String vpath, boolean fast) {
ZipFile zip = null;
try {
zip = new ZipFile(file);
} catch (IOException e){
throw new IllegalStateException(e.getMessage());
}

Enumeration entries = zip.entries();
while ( entries.hasMoreElements() ) {
ZipEntry entry = (ZipEntry)entries.nextElement();
String name = entry.getName();
// @fixme do we need to strip out entries that starts
// with . or ./ ?
if (entry.isDirectory()) {
if (isIncluded(name)) {
if (!isExcluded(name)) {
dirsIncluded.addElement(name);
} else {
everythingIncluded = false;
dirsExcluded.addElement(name);
}
} else {
everythingIncluded = false;
dirsNotIncluded.addElement(name);
}
} else {
if (isIncluded(name)) {
if (!isExcluded(name)) {
filesIncluded.addElement(name);
} else {
everythingIncluded = false;
filesExcluded.addElement(name);
}
} else {
everythingIncluded = false;
filesNotIncluded.addElement(name);
}
}
}
}

}

Loading…
Cancel
Save