提交 79fbe28b 编写于 作者: C Christoph Kutzinski

Merge pull request #668 from kutzi/maven-testmojo-heuristic

Use 'duck-typing' approach for detecting test mojos
......@@ -27,15 +27,10 @@ import hudson.AbortException;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.Run;
import hudson.tasks.test.AbstractTestResultAction;
import hudson.tasks.test.MetaTabulatedResult;
import hudson.tasks.test.TestObject;
import hudson.tasks.test.AbstractTestResultAction;
import hudson.util.IOException2;
import org.apache.tools.ant.DirectoryScanner;
import org.dom4j.DocumentException;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import java.io.File;
import java.io.IOException;
......@@ -49,6 +44,12 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.tools.ant.DirectoryScanner;
import org.dom4j.DocumentException;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
/**
* Root of all the test results for one build.
*
......@@ -153,15 +154,8 @@ public final class TestResult extends MetaTabulatedResult {
for (String value : reportFiles) {
File reportFile = new File(baseDir, value);
// only count files that were actually updated during this build
if ( (buildTime-3000/*error margin*/ <= reportFile.lastModified()) || !checkTimestamps) {
if(reportFile.length()==0) {
// this is a typical problem when JVM quits abnormally, like OutOfMemoryError during a test.
SuiteResult sr = new SuiteResult(reportFile.getName(), "", "");
sr.addCase(new CaseResult(sr,"<init>","Test report file "+reportFile.getAbsolutePath()+" was length 0"));
add(sr);
} else {
parse(reportFile);
}
if ( (buildTime-3000/*error margin*/ <= reportFile.lastModified())) {
parsePossiblyEmpty(reportFile);
parsed = true;
}
}
......@@ -183,7 +177,60 @@ public final class TestResult extends MetaTabulatedResult {
Util.getTimeSpanString(buildTime-f.lastModified())));
}
}
public void parse(long buildTime, Iterable<File> reportFiles) throws IOException {
boolean parsed=false;
for (File reportFile : reportFiles) {
// only count files that were actually updated during this build
if ( (buildTime-3000/*error margin*/ <= reportFile.lastModified())) {
parsePossiblyEmpty(reportFile);
parsed = true;
}
}
if(!parsed) {
long localTime = System.currentTimeMillis();
if(localTime < buildTime-1000) /*margin*/
// build time is in the the future. clock on this slave must be running behind
throw new AbortException(
"Clock on this slave is out of sync with the master, and therefore \n" +
"I can't figure out what test results are new and what are old.\n" +
"Please keep the slave clock in sync with the master.");
File f = reportFiles.iterator().next();
throw new AbortException(
String.format(
"Test reports were found but none of them are new. Did tests run? %n"+
"For example, %s is %s old%n", f,
Util.getTimeSpanString(buildTime-f.lastModified())));
}
}
/**
* Collect reports from the given report files
*
* @since TODO
*/
public void parse(Iterable<File> reportFiles) throws IOException {
for (File reportFile : reportFiles) {
parsePossiblyEmpty(reportFile);
}
}
private void parsePossiblyEmpty(File reportFile) throws IOException {
if(reportFile.length()==0) {
// this is a typical problem when JVM quits abnormally, like OutOfMemoryError during a test.
SuiteResult sr = new SuiteResult(reportFile.getName(), "", "");
sr.addCase(new CaseResult(sr,"<init>","Test report file "+reportFile.getAbsolutePath()+" was length 0"));
add(sr);
} else {
parse(reportFile);
}
}
private void add(SuiteResult sr) {
for (SuiteResult s : suites) {
// JENKINS-12457: If a testsuite is distributed over multiple files, merge it into a single SuiteResult:
......@@ -588,6 +635,5 @@ public final class TestResult extends MetaTabulatedResult {
}
private static final long serialVersionUID = 1L;
private static final boolean checkTimestamps = true; // TODO: change to System.getProperty
}
......@@ -218,8 +218,10 @@ public class Maven3Builder extends AbstractMavenBuilder implements DelegatingCal
return reporters.get( new ModuleName( mavenProject ) );
}
private void initMojoStartTime( MavenProject mavenProject) {
this.currentMojoStartPerModuleName.put( new ModuleName( mavenProject), System.currentTimeMillis());
private long initMojoStartTime( MavenProject mavenProject) {
long mojoStartTime = System.currentTimeMillis();
this.currentMojoStartPerModuleName.put( new ModuleName( mavenProject), mojoStartTime);
return mojoStartTime;
}
private Long getMojoStartTime(MavenProject mavenProject) {
......@@ -395,10 +397,10 @@ public class Maven3Builder extends AbstractMavenBuilder implements DelegatingCal
}
private void recordMojoStarted(ExecutionEvent event) {
initMojoStartTime( event.getProject() );
long startTime = initMojoStartTime( event.getProject() );
MavenProject mavenProject = event.getProject();
MojoInfo mojoInfo = new MojoInfo(event);
MojoInfo mojoInfo = new MojoInfo(event,startTime);
List<MavenReporter> mavenReporters = getMavenReporters( mavenProject );
......@@ -426,7 +428,7 @@ public class Maven3Builder extends AbstractMavenBuilder implements DelegatingCal
private void recordMojoEnded(ExecutionEvent event, Exception problem) {
MavenProject mavenProject = event.getProject();
MojoInfo mojoInfo = new MojoInfo(event);
MojoInfo mojoInfo = new MojoInfo(event,getMojoStartTime(event.getProject()));
recordExecutionTime(event,mojoInfo);
......
......@@ -43,6 +43,7 @@ import java.text.NumberFormat;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.maven.BuildFailureException;
......@@ -275,6 +276,7 @@ public abstract class MavenBuilder extends AbstractMavenBuilder implements Deleg
private final MavenBuilder listener;
private final AtomicBoolean hasTestFailures = new AtomicBoolean();
private final Map<ModuleName, Long> currentMojoStartPerModuleName = new ConcurrentHashMap<ModuleName, Long>();
/**
* Number of total nanoseconds {@link MavenBuilder} spent.
......@@ -284,6 +286,16 @@ public abstract class MavenBuilder extends AbstractMavenBuilder implements Deleg
public Adapter(MavenBuilder listener) {
this.listener = listener;
}
private long initMojoStartTime( MavenProject mavenProject) {
long mojoStartTime = System.currentTimeMillis();
this.currentMojoStartPerModuleName.put( new ModuleName( mavenProject), mojoStartTime);
return mojoStartTime;
}
private Long getMojoStartTime(MavenProject mavenProject) {
return currentMojoStartPerModuleName.get( new ModuleName(mavenProject) );
}
public void preBuild(MavenSession session, ReactorManager rm, EventDispatcher dispatcher) throws BuildFailureException, LifecycleExecutionException, IOException, InterruptedException {
long startTime = System.nanoTime();
......@@ -312,13 +324,14 @@ public abstract class MavenBuilder extends AbstractMavenBuilder implements Deleg
fireEnterModule(project);
}
listener.preExecute(project, new MojoInfo(exec, mojo, mergedConfig, eval));
long mojoStartTime = initMojoStartTime(project);
listener.preExecute(project, new MojoInfo(exec, mojo, mergedConfig, eval, mojoStartTime));
overheadTime += System.nanoTime()-startTime;
}
public void postExecute(MavenProject project, MojoExecution exec, Mojo mojo, PlexusConfiguration mergedConfig, ExpressionEvaluator eval, Exception exception) throws IOException, InterruptedException {
long startTime = System.nanoTime();
listener.postExecute(project, new MojoInfo(exec, mojo, mergedConfig, eval),exception);
listener.postExecute(project, new MojoInfo(exec, mojo, mergedConfig, eval, getMojoStartTime(project)),exception);
if(listener.hasBuildFailures())
hasTestFailures.compareAndSet(false, true);
overheadTime += System.nanoTime()-startTime;
......@@ -326,7 +339,8 @@ public abstract class MavenBuilder extends AbstractMavenBuilder implements Deleg
public void onReportGenerated(MavenReport report, MojoExecution mojoExecution, PlexusConfiguration mergedConfig, ExpressionEvaluator eval) throws IOException, InterruptedException {
long startTime = System.nanoTime();
listener.onReportGenerated(lastModule,new MavenReportInfo(mojoExecution,report,mergedConfig,eval));
listener.onReportGenerated(lastModule,new MavenReportInfo(mojoExecution,report,mergedConfig,eval,
getMojoStartTime(lastModule)));
overheadTime += System.nanoTime()-startTime;
}
......
......@@ -49,8 +49,9 @@ public final class MavenReportInfo extends MojoInfo {
*/
public final MavenReport report;
public MavenReportInfo(MojoExecution mojoExecution, MavenReport mojo, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator) {
super(mojoExecution, (Mojo)mojo, configuration, expressionEvaluator);
public MavenReportInfo(MojoExecution mojoExecution, MavenReport mojo, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator,
long mojoStartTime) {
super(mojoExecution, (Mojo)mojo, configuration, expressionEvaluator,mojoStartTime);
this.report = mojo;
}
}
......@@ -103,7 +103,10 @@ public class MojoInfo {
*/
private final ConverterLookup converterLookup = new DefaultConverterLookup();
public MojoInfo(MojoExecution mojoExecution, Mojo mojo, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator) {
private long startTime;
public MojoInfo(MojoExecution mojoExecution, Mojo mojo, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator,
long startTime) {
// in Maven3 there's no easy way to get the Mojo instance that's being executed,
// so we just can't pass it in.
if (mojo==null) mojo = new Maven3ProvidesNoAccessToMojo();
......@@ -112,12 +115,13 @@ public class MojoInfo {
this.configuration = configuration;
this.expressionEvaluator = expressionEvaluator;
this.pluginName = new PluginName(mojoExecution.getMojoDescriptor().getPluginDescriptor());
this.startTime = startTime;
}
public MojoInfo(ExecutionEvent event) {
public MojoInfo(ExecutionEvent event, long startTime) {
this(event.getMojoExecution(), null,
new XmlPlexusConfiguration( event.getMojoExecution().getConfiguration() ),
new PluginParameterExpressionEvaluator( event.getSession(), event.getMojoExecution() ));
new PluginParameterExpressionEvaluator( event.getSession(), event.getMojoExecution() ), startTime);
}
/**
......@@ -148,7 +152,7 @@ public class MojoInfo {
* the configuration in POM is syntactically incorrect.
*/
public <T> T getConfigurationValue(String configName, Class<T> type) throws ComponentConfigurationException {
PlexusConfiguration child = configuration.getChild(configName);
PlexusConfiguration child = configuration.getChild(configName,false);
if(child==null) return null; // no such config
final ClassLoader cl;
......@@ -278,4 +282,8 @@ public class MojoInfo {
throw new UnsupportedOperationException();
}
}
public long getStartTime() {
return this.startTime;
}
}
......@@ -25,7 +25,6 @@ package hudson.maven.reporters;
import hudson.Extension;
import hudson.Launcher;
import hudson.Util;
import hudson.maven.Maven3Builder;
import hudson.maven.MavenBuild;
import hudson.maven.MavenBuildInformation;
......@@ -47,6 +46,7 @@ import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.ConcurrentHashMap;
......@@ -55,26 +55,29 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
/**
* Records the surefire test result.
* @author Kohsuke Kawaguchi
* @author Christoph Kutzinski
*/
public class SurefireArchiver extends TestFailureDetector {
private transient TestResult result;
private final AtomicBoolean hasTestFailures = new AtomicBoolean();
/**
* Store the filesets here as we want to track ignores between multiple runs of this class<br/>
* Note: Because this class can be run with different mojo goals with different path settings,
* we track multiple {@link FileSet}s for each encountered <tt>reportsDir</tt>
* Store result files already parsed, so we don't parse them again,
* if a later running mojo specifies the same reports directory.
*/
private transient ConcurrentMap<File, FileSet> fileSets = new ConcurrentHashMap<File,FileSet>();
private transient ConcurrentMap<File, File> parsedFiles = new ConcurrentHashMap<File,File>();
@Override
public boolean hasTestFailures() {
......@@ -83,25 +86,27 @@ public class SurefireArchiver extends TestFailureDetector {
public boolean preExecute(MavenBuildProxy build, MavenProject pom, MojoInfo mojo, BuildListener listener) throws InterruptedException, IOException {
if (isTestMojo(mojo)) {
if (!isSoapUiMojo(mojo)) {
// tell surefire:test to keep going even if there was a failure,
// so that we can record this as yellow.
// note that because of the way Maven works, just updating system property at this point is too late
XmlPlexusConfiguration c = (XmlPlexusConfiguration) mojo.configuration.getChild("testFailureIgnore");
if(c!=null && c.getValue() != null && c.getValue().equals("${maven.test.failure.ignore}") && System.getProperty("maven.test.failure.ignore")==null) {
if (build.getMavenBuildInformation().isMaven3OrLater()) {
String fieldName = "testFailureIgnore";
if (mojo.mojoExecution.getConfiguration().getChild( fieldName ) != null) {
mojo.mojoExecution.getConfiguration().getChild( fieldName ).setValue( Boolean.TRUE.toString() );
} else {
Xpp3Dom child = new Xpp3Dom( fieldName );
child.setValue( Boolean.TRUE.toString() );
mojo.mojoExecution.getConfiguration().addChild( child );
}
// tell test mojo to keep going even if there was a failure,
// so that we can record this as yellow.
// note that because of the way Maven works, just updating system property at this point is too late
// Many test plugins have - as surefire - a configuration key 'testFailureIgnore' which defaults to
// ${maven.test.failure.ignore}, so just try that one and change value to true,
// if it's still at that default:
XmlPlexusConfiguration c = (XmlPlexusConfiguration) mojo.configuration.getChild("testFailureIgnore");
if(c!=null && c.getValue() != null && c.getValue().equals("${maven.test.failure.ignore}") && System.getProperty("maven.test.failure.ignore")==null) {
if (build.getMavenBuildInformation().isMaven3OrLater()) {
String fieldName = "testFailureIgnore";
if (mojo.mojoExecution.getConfiguration().getChild( fieldName ) != null) {
mojo.mojoExecution.getConfiguration().getChild( fieldName ).setValue( Boolean.TRUE.toString() );
} else {
c.setValue(Boolean.TRUE.toString());
Xpp3Dom child = new Xpp3Dom( fieldName );
child.setValue( Boolean.TRUE.toString() );
mojo.mojoExecution.getConfiguration().addChild( child );
}
} else {
c.setValue(Boolean.TRUE.toString());
}
}
}
......@@ -109,41 +114,45 @@ public class SurefireArchiver extends TestFailureDetector {
}
public boolean postExecute(MavenBuildProxy build, MavenProject pom, MojoInfo mojo, final BuildListener listener, Throwable error) throws InterruptedException, IOException {
if (!isTestMojo(mojo)) return true;
TestMojo testMojo = TestMojo.lookup(mojo);
if (testMojo == null) return true;
listener.getLogger().println(Messages.SurefireArchiver_Recording());
File reportsDir;
if (isSurefireOrFailsafeMojo(mojo)) {
try {
reportsDir = mojo.getConfigurationValue("reportsDirectory", File.class);
} catch (ComponentConfigurationException e) {
e.printStackTrace(listener.fatalError(Messages.SurefireArchiver_NoReportsDir()));
build.setResult(Result.FAILURE);
return true;
}
}
else {
reportsDir = new File(pom.getBasedir(), "target/surefire-reports");
Iterable<File> fileSet;
try {
fileSet = testMojo.getReportFiles(pom, mojo);
} catch (ComponentConfigurationException e) {
e.printStackTrace(listener.fatalError(Messages.SurefireArchiver_NoReportsDir()));
build.setResult(Result.FAILURE);
return true;
}
if(reportsDir.exists()) {
// surefire:test just skips itself when the current project is not a java project
if(fileSet != null) {
synchronized (build) {
FileSet fileSet = getFileSet(reportsDir);
DirectoryScanner ds = fileSet.getDirectoryScanner();
if(result==null) result = new TestResult();
if(ds.getIncludedFilesCount()==0)
// no test in this module
// filter all the already parsed files:
fileSet = Iterables.filter(fileSet, new Predicate<File>() {
@Override
public boolean apply(File input) {
return !parsedFiles.containsKey(input);
}
});
if (!fileSet.iterator().hasNext())
return true;
String[] reportFiles = ds.getIncludedFiles();
rememberCheckedFiles(reportsDir, reportFiles);
if(result==null) result = new TestResult();
result.parse(System.currentTimeMillis() - build.getMilliSecsSinceBuildStart(), reportsDir, reportFiles);
result.parse(System.currentTimeMillis() - build.getMilliSecsSinceBuildStart(), fileSet);
// TODO kutzi: the following is a 'more correct' way to get the reports associated to a mojo,
// but needs more testing
// Iterable<File> reportFilesFiltered = getFilesBetween(reportsDir, reportFiles, mojo.getStartTime(), System.currentTimeMillis());
// result.parse(reportFilesFiltered);
rememberCheckedFiles(fileSet);
// final reference in order to serialize it:
final TestResult r = result;
......@@ -199,33 +208,13 @@ public class SurefireArchiver extends TestFailureDetector {
}
}
/**
* Returns the appropriate FileSet for the selected baseDir
* @param baseDir
* @return
*/
FileSet getFileSet(File baseDir) {
FileSet fs = fileSets.get(baseDir);
if (fs == null) {
fs = Util.createFileSet(baseDir, "*.xml","testng-results.xml,testng-failed.xml");
FileSet previous = fileSets.putIfAbsent(baseDir, fs);
if (previous != null) {
return previous;
}
}
return fs;
}
/**
* Add checked files to the exclude list of the fileSet
*/
private void rememberCheckedFiles(File baseDir, String[] reportFiles) {
FileSet fileSet = getFileSet(baseDir);
for (String file : reportFiles) {
fileSet.createExclude().setName(file);
}
private void rememberCheckedFiles(Iterable<File> fileSet) {
for (File f : fileSet) {
this.parsedFiles.put(f, f);
}
}
/**
......@@ -244,6 +233,65 @@ public class SurefireArchiver extends TestFailureDetector {
}
}
// private static Iterable<File> getFilesBetween(final File reportsDir,
// final String[] reportFiles, final long from, final long to) {
// return new FilteredReportsFileIterable(reportsDir, reportFiles, from, to);
// }
/**
* Provides an {@link Iterable} view on the reports files while filtering out all files
* which don't have a lastModified time in between from and to.
*/
static class FilteredReportsFileIterable implements Iterable<File> {
private final File reportsDir;
private final String[] reportFiles;
private final long from;
private final long to;
FilteredReportsFileIterable(File reportsDir,
String[] reportFiles, long from, long to) {
this.reportsDir = reportsDir;
this.reportFiles = reportFiles;
// FAT filesystems have a max resolution of 2 seconds so we need to subtract/add 2 seconds to
// the range borders.
// All other fs should have a equal or better precision
this.from = from - 2000;
this.to = to + 2000;
}
@Override
public Iterator<File> iterator() {
Predicate<File> fileWithinFromAndTo = new Predicate<File>() {
@Override
public boolean apply(File file) {
long lastModified = file.lastModified();
if (lastModified>=from && lastModified<=to) {
return true;
}
return false;
}
};
return Iterators.filter(
Iterators.transform(
Iterators.forArray(reportFiles),
new Function<String, File>() {
@Override
public File apply(String file) {
return getFile(reportsDir,file);
}
}),
fileWithinFromAndTo);
}
// here for mocking purposes:
File getFile(File parent, String child) {
return new File(parent,child);
}
}
/**
* Part of the serialization data attached to {@link MavenBuild}.
*/
......@@ -253,80 +301,21 @@ public class SurefireArchiver extends TestFailureDetector {
}
}
private boolean isTestMojo(MojoInfo mojo) {
if ((!mojo.is("com.sun.maven", "maven-junit-plugin", "test"))
&& (!mojo.is("org.sonatype.flexmojos", "flexmojos-maven-plugin", "test-run"))
&& (!mojo.is("org.eclipse.tycho", "tycho-surefire-plugin", "test"))
&& (!mojo.is("org.sonatype.tycho", "maven-osgi-test-plugin", "test"))
&& (!mojo.is("org.codehaus.mojo", "gwt-maven-plugin", "test"))
&& (!isAndroidMojo(mojo))
&& (!isSurefireOrFailsafeMojo(mojo))
&& (!isSoapUiMojo(mojo)))
return false;
boolean isTestMojo(MojoInfo mojo) {
TestMojo testMojo = TestMojo.lookup(mojo);
if (testMojo == null)
return false;
try {
if (isSurefireOrFailsafeMojo(mojo)) {
Boolean skip = mojo.getConfigurationValue("skip", Boolean.class);
// most test plugins have at least on of the test-skip properties:
String[] skipProperties = {"skip", "skipExec", "skipTests", "skipTest"};
for (String skipProperty : skipProperties) {
Boolean skip = mojo.getConfigurationValue(skipProperty, Boolean.class);
if (((skip != null) && (skip))) {
return false;
}
if (mojo.pluginName.version.compareTo("2.3") >= 0) {
Boolean skipExec = mojo.getConfigurationValue("skipExec", Boolean.class);
if (((skipExec != null) && (skipExec))) {
return false;
}
}
if (mojo.pluginName.version.compareTo("2.4") >= 0) {
Boolean skipTests = mojo.getConfigurationValue("skipTests", Boolean.class);
if (((skipTests != null) && (skipTests))) {
return false;
}
}
}
else if (mojo.is("com.sun.maven", "maven-junit-plugin", "test")) {
Boolean skipTests = mojo.getConfigurationValue("skipTests", Boolean.class);
if (((skipTests != null) && (skipTests))) {
return false;
}
}
else if (mojo.is("org.sonatype.flexmojos", "flexmojos-maven-plugin", "test-run")) {
Boolean skipTests = mojo.getConfigurationValue("skipTest", Boolean.class);
if (((skipTests != null) && (skipTests))) {
return false;
}
} else if (mojo.is("org.sonatype.tycho", "maven-osgi-test-plugin", "test")) {
Boolean skipTests = mojo.getConfigurationValue("skipTest", Boolean.class);
if (((skipTests != null) && (skipTests))) {
return false;
}
} else if (mojo.is("org.eclipse.tycho", "tycho-surefire-plugin", "test")) {
Boolean skipTests = mojo.getConfigurationValue("skipTest", Boolean.class);
if (((skipTests != null) && (skipTests))) {
return false;
}
} else if (isAndroidMojo(mojo)) {
if (mojo.pluginName.version.compareTo("3.0.0-alpha-6") < 0) {
// Earlier versions do not support tests
return false;
} else {
Boolean skipTests = mojo.getConfigurationValue("skipTests", Boolean.class);
if (((skipTests != null) && (skipTests))) {
return false;
}
}
} else if (mojo.is("org.codehaus.mojo", "gwt-maven-plugin", "test") && mojo.pluginName.version.compareTo("1.2") < 0) {
// gwt-maven-plugin < 1.2 does not implement required Surefire option
return false;
} else if (isSoapUiMojo(mojo)) {
Boolean skipTests = mojo.getConfigurationValue("skip", Boolean.class);
if (((skipTests != null) && (skipTests))) {
return false;
}
}
} catch (ComponentConfigurationException e) {
return false;
......@@ -334,26 +323,11 @@ public class SurefireArchiver extends TestFailureDetector {
return true;
}
private boolean isAndroidMojo(MojoInfo mojo) {
return mojo.is("com.jayway.maven.plugins.android.generation2", "maven-android-plugin", "internal-integration-test")
|| mojo.is("com.jayway.maven.plugins.android.generation2", "android-maven-plugin", "internal-integration-test");
}
private boolean isSurefireOrFailsafeMojo(MojoInfo mojo) {
return mojo.is("org.apache.maven.plugins", "maven-surefire-plugin", "test")
|| mojo.is("org.apache.maven.plugins", "maven-failsafe-plugin", "verify");
}
private boolean isSoapUiMojo(MojoInfo mojo) {
return mojo.is("eviware", "maven-soapui-plugin", "test")
|| mojo.is("eviware", "maven-soapui-pro-plugin", "test");
}
// I'm not sure if SurefireArchiver is actually ever (de-)serialized,
// but just to be sure, set fileSets here
protected Object readResolve() {
fileSets = new ConcurrentHashMap<File,FileSet>();
parsedFiles = new ConcurrentHashMap<File,File>();
return this;
}
......
package hudson.maven.reporters;
import hudson.Util;
import hudson.maven.MojoInfo;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import org.apache.maven.project.MavenProject;
import org.apache.tools.ant.types.FileSet;
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import com.google.common.base.Function;
import com.google.common.collect.Iterators;
/**
* Description of a mojo which can run tests.
*
* @author kutzi
*/
enum TestMojo {
/**
* Fallback to this if we have no exact match
*/
FALLBACK("","","","reportsDirectory") {
@Override
protected boolean is(String artifactId, String groupId, String goal) {
// never match anything implicitly
return false;
}
},
MAVEN_SUREFIRE("org.apache.maven.plugins", "maven-surefire-plugin","test","reportsDirectory"),
MAVEN_FAILSAFE("org.apache.maven.plugins", "maven-failsafe-plugin", "verify","reportsDirectory"),
MAVEN_JUNIT("com.sun.maven", "maven-junit-plugin", "test","reportsDirectory"),
FLEXMOJOS("org.sonatype.flexmojos", "flexmojos-maven-plugin", "test-run",null),
MAVEN_OSGI_TEST("org.sonatype.tycho", "maven-osgi-test-plugin", "test","reportsDirectory"),
TYCHO_SUREFIRE("org.eclipse.tycho", "tycho-surefire-plugin", "test","reportsDirectory"),
MAVEN_ANDROID_PLUGIN("com.jayway.maven.plugins.android.generation2", "maven-android-plugin",
"internal-integration-test",null,"3.0.0-alpha-6"),
ANDROID_MAVEN_PLUGIN("com.jayway.maven.plugins.android.generation2", "android-maven-plugin",
"internal-integration-test",null,"3.0.0-alpha-6"),
GWT_MAVEN_PLUGIN("org.codehaus.mojo", "gwt-maven-plugin", "test","reportsDirectory","1.2"),
MAVEN_SOAPUI_PLUGIN("eviware", "maven-soapui-plugin", "test", "outputFolder"),
MAVEN_SOAPUI_PRO_PLUGIN("eviware", "maven-soapui-pro-plugin", "test","outputFolder"),
JASMINE("com.github.searls","jasmine-maven-plugin","test",null) {
@Override
public Collection<File> getReportFiles(MavenProject pom,MojoInfo mojo)
throws ComponentConfigurationException {
// jasmine just creates a single JUnit result file
File reportsDir = mojo.getConfigurationValue("jasmineTargetDir", File.class);
String junitFileName = mojo.getConfigurationValue("junitXmlReportFileName", String.class);
return Collections.singleton(new File(reportsDir,junitFileName));
}
},
TOOLKIT_RESOLVER_PLUGIN("org.terracotta.maven.plugins", "toolkit-resolver-plugin", "toolkit-resolve-test","reportsDirectory");
private String reportDirectoryConfigKey;
private Key key;
private String minimalRequiredVersion;
private TestMojo(String artifactId, String groupId, String goal,
String reportDirectoryConfigKey) {
this.key = new Key(artifactId,groupId,goal);
this.reportDirectoryConfigKey = reportDirectoryConfigKey;
}
private TestMojo(String artifactId, String groupId, String goal,
String reportDirectoryConfigKey,String minimalRequiredVersion) {
this.key = new Key(artifactId,groupId,goal);
this.reportDirectoryConfigKey = reportDirectoryConfigKey;
this.minimalRequiredVersion = minimalRequiredVersion;
}
public Key getKey() {
return this.key;
}
/**
* Says if this mojo can run tests.
* Can e.g. return false if the version of the plugin is too old to create output in JUnit format.
*/
public boolean canRunTests(MojoInfo mojo) {
if (this.minimalRequiredVersion == null) {
return true;
}
return mojo.pluginName.version.compareTo(this.minimalRequiredVersion) >= 0;
}
public Iterable<File> getReportFiles(MavenProject pom, MojoInfo mojo) throws ComponentConfigurationException {
if (this.reportDirectoryConfigKey != null) {
File reportsDir = mojo.getConfigurationValue(this.reportDirectoryConfigKey, File.class);
if (reportsDir.exists()) {
return getReportFiles(reportsDir, getFileSet(reportsDir));
}
}
// some plugins just default to this:
File reportsDir = new File(pom.getBasedir(), pom.getBuild().getDirectory()+File.separator+"surefire-reports");
if (reportsDir.exists()) {
return getReportFiles(reportsDir, getFileSet(reportsDir));
}
return null;
}
private Iterable<File> getReportFiles(final File baseDir, FileSet set) {
final String[] includedFiles = set.getDirectoryScanner().getIncludedFiles();
return new Iterable<File>() {
public Iterator<File> iterator() {
return Iterators.transform(
Iterators.forArray(includedFiles),
new Function<String, File>() {
@Override
public File apply(String file) {
return new File(baseDir,file);
}
});
}
};
}
/**
* Returns the appropriate FileSet for the selected baseDir
* @param baseDir
* @return
*/
private FileSet getFileSet(File baseDir) {
return Util.createFileSet(baseDir, "*.xml","testng-results.xml,testng-failed.xml");
}
protected boolean is(String artifactId, String groupId, String goal) {
return key.artifactId.equals(artifactId) && key.groupId.equals(groupId)
&& key.goal.equals(goal);
}
public static TestMojo lookup(String artifactId, String groupId, String goal) {
for (TestMojo mojo : values()) {
if (mojo.is(artifactId,groupId,goal)) {
return mojo;
}
}
if (goal.equals("test") || goal.equals("test-run")) {
return FALLBACK;
}
return null;
}
public static TestMojo lookup(MojoInfo mojo) {
TestMojo testMojo = lookup(mojo.pluginName.groupId, mojo.pluginName.artifactId, mojo.getGoal());
if (testMojo != null && testMojo.canRunTests(mojo)) {
return testMojo;
}
return null;
}
static class Key {
private String artifactId;
private String groupId;
private String goal;
public Key(String artifactId, String groupId, String goal) {
super();
this.artifactId = artifactId;
this.groupId = groupId;
this.goal = goal;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((artifactId == null) ? 0 : artifactId.hashCode());
result = prime * result + ((goal == null) ? 0 : goal.hashCode());
result = prime * result
+ ((groupId == null) ? 0 : groupId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Key other = (Key) obj;
if (artifactId == null) {
if (other.artifactId != null)
return false;
} else if (!artifactId.equals(other.artifactId))
return false;
if (goal == null) {
if (other.goal != null)
return false;
} else if (!goal.equals(other.goal))
return false;
if (groupId == null) {
if (other.groupId != null)
return false;
} else if (!groupId.equals(other.groupId))
return false;
return true;
}
}
}
......@@ -53,7 +53,7 @@ public class ExecutedMojoTest {
// Faking JUnit's Assert to be the plugin class
this.mojoDescriptor.setImplementation(Assert.class.getName());
MojoExecution execution = new MojoExecution(this.mojoDescriptor);
MojoInfo info = new MojoInfo(execution, null, null, null);
MojoInfo info = new MojoInfo(execution, null, null, null, -1);
ExecutedMojo executedMojo = new ExecutedMojo(info, 1L);
......@@ -66,7 +66,7 @@ public class ExecutedMojoTest {
// Faking this class as the mojo impl:
this.mojoDescriptor.setImplementation(getClass().getName());
MojoExecution execution = new MojoExecution(this.mojoDescriptor);
MojoInfo info = new MojoInfo(execution, null, null, null);
MojoInfo info = new MojoInfo(execution, null, null, null, -1);
ExecutedMojo executedMojo = new ExecutedMojo(info, 1L);
......
package hudson.maven;
import hudson.maven.MojoInfo;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.configuration.DefaultPlexusConfiguration;
import org.codehaus.plexus.configuration.PlexusConfiguration;
public class MojoInfoBuilder {
private String groupId;
private String artifactId;
private String goalName;
private String version = "1.0";
private Map<String, String> configValues = new HashMap<String, String>();
private long startTime = System.currentTimeMillis();
public static MojoInfoBuilder mojoBuilder(String groupId, String artifactId, String goalName) {
return new MojoInfoBuilder(groupId, artifactId, goalName);
}
private MojoInfoBuilder(String groupId, String artifactId, String goalName) {
this.groupId = groupId;
this.artifactId = artifactId;
this.goalName = goalName;
}
public MojoInfoBuilder copy() {
MojoInfoBuilder copy = new MojoInfoBuilder(this.groupId, this.artifactId, this.goalName)
.version(this.version);
copy.configValues.putAll(this.configValues);
return copy;
}
public MojoInfoBuilder version(String version) {
this.version = version;
return this;
}
public MojoInfoBuilder startTime(long startTime) {
this.startTime = startTime;
return this;
}
public MojoInfoBuilder configValue(String key,String value) {
configValues.put(key, value);
return this;
}
public MojoInfo build() {
PluginDescriptor pluginDescriptor = new PluginDescriptor();
pluginDescriptor.setGroupId(groupId);
pluginDescriptor.setArtifactId(artifactId);
pluginDescriptor.setVersion(version);
MojoDescriptor mojoDescriptor = new MojoDescriptor();
mojoDescriptor.setPluginDescriptor(pluginDescriptor);
mojoDescriptor.setGoal(goalName);
MojoExecution mojoExecution = new MojoExecution(mojoDescriptor);
PlexusConfiguration configuration = new DefaultPlexusConfiguration("configuration");
for (Map.Entry<String, String> e : this.configValues.entrySet()) {
configuration.addChild(e.getKey(),e.getValue());
}
ExpressionEvaluator evaluator = new ExpressionEvaluator() {
@Override
public Object evaluate(String expression) {
return expression;
}
@Override
public File alignToBaseDirectory(File file) {
return file;
}
};
MojoInfo info = new MojoInfo(mojoExecution, null, configuration, evaluator, startTime);
return info;
}
}
package hudson.maven.reporters;
import static hudson.maven.MojoInfoBuilder.mojoBuilder;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import hudson.maven.MojoInfo;
import hudson.maven.MojoInfoBuilder;
import org.junit.Before;
import org.junit.Test;
/**
* Regression test for the detection of test mojos in {@link SurefireArchiver}.
*
* @author kutzi
*/
public class SurefireArchiverDetectTestMojosTest {
private SurefireArchiver surefireArchiver;
@Before
public void before() {
this.surefireArchiver = new SurefireArchiver();
}
@Test
public void shouldDetectMavenSurefire() {
MojoInfo mojo = mojoBuilder("org.apache.maven.plugins", "maven-surefire-plugin", "test").build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectMavenFailsafe() {
MojoInfo mojo = mojoBuilder("org.apache.maven.plugins", "maven-failsafe-plugin", "verify").build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectMavenSurefireSkip() {
MojoInfoBuilder builder = mojoBuilder("org.apache.maven.plugins", "maven-surefire-plugin", "test");
MojoInfo mojo = builder.copy()
.configValue("skip", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy()
.version("2.4")
.configValue("skipTests", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy()
.version("2.3")
.configValue("skipExec", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
// That's not a valid skip property:
mojo = builder.copy()
.configValue("skip--Exec", "true").build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectMavenJunitPlugin() {
MojoInfoBuilder builder = mojoBuilder("com.sun.maven", "maven-junit-plugin", "test");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy()
.configValue("skipTests", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectFlexMojoMavenPlugin() {
MojoInfoBuilder builder = mojoBuilder("org.sonatype.flexmojos", "flexmojos-maven-plugin", "test-run");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy()
.configValue("skipTest", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectOsgiTestPlugin() {
MojoInfoBuilder builder = mojoBuilder("org.sonatype.tycho", "maven-osgi-test-plugin", "test");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy().configValue("skipTest", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectTychoSurefirePlugin() {
MojoInfoBuilder builder = mojoBuilder("org.eclipse.tycho", "tycho-surefire-plugin", "test");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy().configValue("skipTest", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectMavenAndroidPlugin() {
MojoInfoBuilder builder = mojoBuilder("com.jayway.maven.plugins.android.generation2", "maven-android-plugin", "internal-integration-test")
.version("3.0.0-alpha-6");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy().configValue("skipTests", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectAndroidMavenPlugin() {
MojoInfoBuilder builder = mojoBuilder("com.jayway.maven.plugins.android.generation2", "android-maven-plugin", "internal-integration-test")
.version("3.0.0-alpha-6");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy().configValue("skipTests", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectGwtMavenPlugin() {
MojoInfoBuilder builder = mojoBuilder("org.codehaus.mojo", "gwt-maven-plugin", "test")
.version("1.2");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
// that version of the plugin is too old
mojo = builder.copy().version("1.1").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectSoapUiMavenPlugin() {
MojoInfoBuilder builder = mojoBuilder("eviware", "maven-soapui-plugin", "test");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy().configValue("skip", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectSoapUiProMavenPlugin() {
MojoInfoBuilder builder = mojoBuilder("eviware", "maven-soapui-pro-plugin", "test");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy().configValue("skip", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectToolkitResolverPlugin() {
MojoInfoBuilder builder = mojoBuilder("org.terracotta.maven.plugins", "toolkit-resolver-plugin", "toolkit-resolve-test");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
mojo = builder.copy().configValue("skipTests", "true").build();
assertFalse(this.surefireArchiver.isTestMojo(mojo));
}
@Test
public void shouldDetectAnyMojoWithATestGoal() {
MojoInfoBuilder builder = mojoBuilder("some.weird.internal","test-mojo", "test");
MojoInfo mojo = builder.build();
assertTrue(this.surefireArchiver.isTestMojo(mojo));
}
}
package hudson.maven.reporters;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import hudson.maven.reporters.SurefireArchiver.FilteredReportsFileIterable;
import java.io.File;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.junit.Test;
public class SurefireArchiverFilterReportsFileTest {
@Test
public void shouldIncludeAllReportFiles() {
File reportsDir = new File("bla");
String[] reportFiles = { "a", "b", "c" };
FilteredReportsFileIterable iterable = new FilteredReportsFileIterable(reportsDir, reportFiles, 0, 1000);
iterable = spy(iterable);
File file = mock(File.class);
when(file.lastModified()).thenReturn(500L);
when(iterable.getFile(any(File.class), anyString())).thenReturn(file);
Iterator<File> iterator = iterable.iterator();
iterator.next();
iterator.next();
iterator.next();
try {
iterator.next();
fail("Iterator should only have 3 elements");
} catch (NoSuchElementException e) {
// expected
}
}
@Test
public void shouldExcludeReportFileTooOld() {
File reportsDir = new File("bla");
String[] reportFiles = { "a", "b", "c" };
FilteredReportsFileIterable iterable = new FilteredReportsFileIterable(reportsDir, reportFiles, 5000, 10000);
iterable = spy(iterable);
File included = mock(File.class);
when(included.lastModified()).thenReturn(6000L);
File tooOld = mock(File.class);
when(tooOld.lastModified()).thenReturn(500L);
when(iterable.getFile(any(File.class), anyString())).thenReturn(included, tooOld, included);
Iterator<File> iterator = iterable.iterator();
iterator.next();
iterator.next();
try {
iterator.next();
fail("Iterator should only have 2 elements");
} catch (NoSuchElementException e) {
// expected
}
}
@Test
public void shouldExcludeReportFileTooYoung() {
File reportsDir = new File("bla");
String[] reportFiles = { "a", "b", "c" };
FilteredReportsFileIterable iterable = new FilteredReportsFileIterable(reportsDir, reportFiles, 5000, 10000);
iterable = spy(iterable);
File included = mock(File.class);
when(included.lastModified()).thenReturn(5000L);
File tooYoung = mock(File.class);
when(tooYoung.lastModified()).thenReturn(20000L);
when(iterable.getFile(any(File.class), anyString())).thenReturn(included, included, tooYoung);
Iterator<File> iterator = iterable.iterator();
iterator.next();
iterator.next();
try {
iterator.next();
fail("Iterator should only have 2 elements");
} catch (NoSuchElementException e) {
// expected
}
}
}
package hudson.maven.reporters;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
......@@ -13,6 +14,7 @@ import hudson.maven.MavenBuildProxy;
import hudson.maven.MavenProjectActionBuilder;
import hudson.maven.MavenReporter;
import hudson.maven.MojoInfo;
import hudson.maven.MojoInfoBuilder;
import hudson.model.BuildListener;
import hudson.model.Cause;
import hudson.model.Result;
......@@ -28,10 +30,6 @@ import java.util.Calendar;
import java.util.List;
import org.apache.commons.io.output.NullOutputStream;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.tools.ant.types.FileSet;
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.junit.Assert;
import org.junit.Before;
......@@ -53,8 +51,6 @@ public class SurefireArchiverUnitTest {
@Before
@SuppressWarnings("unchecked")
public void before() throws ComponentConfigurationException, URISyntaxException {
//suppress(constructor(MavenBuild.class, new Class[0]));
this.archiver = new SurefireArchiver();
this.build = mock(MavenBuild.class);
when(build.getAction(Matchers.any(Class.class))).thenCallRealMethod();
......@@ -69,17 +65,8 @@ public class SurefireArchiverUnitTest {
}
private MojoInfo createMojoInfo() throws ComponentConfigurationException {
PluginDescriptor pluginDescriptor = new PluginDescriptor();
pluginDescriptor.setGroupId("org.apache.maven.plugins");
pluginDescriptor.setArtifactId("maven-surefire-plugin");
pluginDescriptor.setVersion("2.9");
MojoDescriptor mojoDescriptor = new MojoDescriptor();
mojoDescriptor.setPluginDescriptor(pluginDescriptor);
mojoDescriptor.setGoal("test");
MojoExecution mojoExecution = new MojoExecution(mojoDescriptor);
MojoInfo info = new MojoInfo(mojoExecution, null, null, null);
MojoInfo info = MojoInfoBuilder.mojoBuilder("org.apache.maven.plugins", "maven-surefire-plugin", "test")
.version("2.9").build();
MojoInfo spy = spy(info);
......@@ -103,6 +90,7 @@ public class SurefireArchiverUnitTest {
public void testArchiveResults() throws InterruptedException, IOException, URISyntaxException, ComponentConfigurationException {
URL resource = SurefireArchiverUnitTest.class.getResource("/surefire-archiver-test2");
File reportsDir = new File(resource.toURI().getPath());
doReturn(reportsDir).when(this.mojoInfo).getConfigurationValue("reportsDirectory", File.class);
touchReportFiles(reportsDir);
......@@ -130,19 +118,22 @@ public class SurefireArchiverUnitTest {
}
@Test
public void testAlreadyCheckedFilesAreNotParsedAgain() throws InterruptedException, IOException, URISyntaxException, ComponentConfigurationException {
public void testResultsAreNotCountedTwice() throws InterruptedException, IOException, URISyntaxException, ComponentConfigurationException {
URL resource = SurefireArchiverUnitTest.class.getResource("/surefire-archiver-test2");
File reportsDir = new File(resource.toURI().getPath());
doReturn(reportsDir).when(this.mojoInfo).getConfigurationValue("reportsDirectory", File.class);
touchReportFiles(reportsDir);
FileSet fileSet = this.archiver.getFileSet(reportsDir);
Assert.assertEquals(2, fileSet.getDirectoryScanner().getIncludedFilesCount());
this.archiver.postExecute(buildProxy, null, this.mojoInfo, new NullBuildListener(), null);
SurefireReport action = this.build.getAction(SurefireReport.class);
TestResult result = action.getResult();
assertEquals(2658, result.getTotalCount());
// result count shouldn't increase if mojo is called again
this.archiver.postExecute(buildProxy, null, this.mojoInfo, new NullBuildListener(), null);
fileSet = this.archiver.getFileSet(reportsDir);
Assert.assertEquals(0, fileSet.getDirectoryScanner().getIncludedFilesCount());
action = this.build.getAction(SurefireReport.class);
result = action.getResult();
assertEquals(2658, result.getTotalCount());
}
@Test
......@@ -205,7 +196,7 @@ public class SurefireArchiverUnitTest {
private void touchReportFiles(File reportsDir) {
File[] files = reportsDir.listFiles();
for(File f : files) {
f.setLastModified(System.currentTimeMillis());
f.setLastModified(this.mojoInfo.getStartTime());
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册