Skip to content

Commit

Permalink
Fix JENKINS-18098
Browse files Browse the repository at this point in the history
  • Loading branch information
gboissinot committed Jan 1, 2014
1 parent b25b257 commit 7c05311
Show file tree
Hide file tree
Showing 13 changed files with 163 additions and 60 deletions.
17 changes: 17 additions & 0 deletions src/main/java/org/jenkinsci/plugins/xunit/ExtraConfiguration.java
@@ -0,0 +1,17 @@
package org.jenkinsci.plugins.xunit;

/**
* @author Gregory Boissinot
*/
public class ExtraConfiguration {

private final long testTimeMargin;

public ExtraConfiguration(long testTimeMargin) {
this.testTimeMargin = testTimeMargin;
}

public long getTestTimeMargin() {
return testTimeMargin;
}
}
Expand Up @@ -3,5 +3,5 @@
/**
* @author Gregory Boissinot
*/
public class NoTestException extends InterruptedException {
public class NoFoundTestException extends InterruptedException {
}
@@ -0,0 +1,7 @@
package org.jenkinsci.plugins.xunit;

/**
* @author Gregory Boissinot
*/
public class OldTestReportException extends InterruptedException {
}
19 changes: 16 additions & 3 deletions src/main/java/org/jenkinsci/plugins/xunit/XUnitBuilder.java
Expand Up @@ -26,6 +26,7 @@ public class XUnitBuilder extends Builder {
private TestType[] types;
private XUnitThreshold[] thresholds;
private int thresholdMode;
private ExtraConfiguration extraConfiguration;

/**
* Computed
Expand All @@ -39,10 +40,15 @@ public XUnitBuilder(TestType[] types, XUnitThreshold[] thresholds) {
}

@DataBoundConstructor
public XUnitBuilder(TestType[] tools, XUnitThreshold[] thresholds, int thresholdMode) {
public XUnitBuilder(TestType[] tools, XUnitThreshold[] thresholds, int thresholdMode, String testTimeMargin) {
this.types = tools;
this.thresholds = thresholds;
this.thresholdMode = thresholdMode;
long longTestTimeMargin = XUnitDefaultValues.TEST_REPORT_TIME_MARGING;
if (testTimeMargin != null && testTimeMargin.trim().length() != 0) {
longTestTimeMargin = Long.parseLong(testTimeMargin);
}
this.extraConfiguration = new ExtraConfiguration(longTestTimeMargin);
}

public TestType[] getTypes() {
Expand All @@ -57,17 +63,24 @@ public int getThresholdMode() {
return thresholdMode;
}

public ExtraConfiguration getExtraConfiguration() {
if (extraConfiguration == null) {
extraConfiguration = new ExtraConfiguration(XUnitDefaultValues.TEST_REPORT_TIME_MARGING);
}
return extraConfiguration;
}

@Override
public boolean perform(final AbstractBuild<?, ?> build, Launcher launcher, final BuildListener listener)
throws InterruptedException, IOException {
XUnitProcessor xUnitProcessor = new XUnitProcessor(types, thresholds, thresholdMode);
XUnitProcessor xUnitProcessor = new XUnitProcessor(getTypes(), getThresholds(), getThresholdMode(), getExtraConfiguration());
return xUnitProcessor.performXUnit(false, build, listener);
}

public boolean performDryRun(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
try {
XUnitProcessor xUnitProcessor = new XUnitProcessor(types, thresholds, thresholdMode);
XUnitProcessor xUnitProcessor = new XUnitProcessor(getTypes(), getThresholds(), getThresholdMode(), getExtraConfiguration());
xUnitProcessor.performXUnit(true, build, listener);
} catch (Throwable t) {
listener.getLogger().println("[ERROR] - There is an error: " + t.getCause().getMessage());
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/org/jenkinsci/plugins/xunit/XUnitDefaultValues.java
@@ -0,0 +1,13 @@
package org.jenkinsci.plugins.xunit;

/**
* @author Gregory Boissinot
*/
public class XUnitDefaultValues {

public static final String GENERATED_JUNIT_DIR = "generatedJUnitFiles";

public static final int MODE_PERCENT = 2;

public static final int TEST_REPORT_TIME_MARGING = 3000; //default to 3000ms
}
26 changes: 14 additions & 12 deletions src/main/java/org/jenkinsci/plugins/xunit/XUnitProcessor.java
Expand Up @@ -29,18 +29,16 @@
*/
public class XUnitProcessor {

public static final String GENERATED_JUNIT_DIR = "generatedJUnitFiles";

private static final int MODE_PERCENT = 2;

private TestType[] types;
private XUnitThreshold[] thresholds;
private int thresholdMode;
private ExtraConfiguration extraConfiguration;

public XUnitProcessor(TestType[] types, XUnitThreshold[] thresholds, int thresholdMode) {
public XUnitProcessor(TestType[] types, XUnitThreshold[] thresholds, int thresholdMode, ExtraConfiguration extraConfiguration) {
this.types = types;
this.thresholds = thresholds;
this.thresholdMode = thresholdMode;
this.extraConfiguration = extraConfiguration;
}

public boolean performXUnit(boolean dryRun, AbstractBuild<?, ?> build, BuildListener listener)
Expand Down Expand Up @@ -111,16 +109,19 @@ private boolean performTests(XUnitLog xUnitLog, AbstractBuild<?, ?> build, Build
try {
result = getWorkspace(build).act(xUnitTransformer);
findTest = true;
} catch (NoTestException ne) {
xUnitLog.infoConsoleLogger("Fail BUILD.");
} catch (NoFoundTestException ne) {
xUnitLog.infoConsoleLogger("Failing BUILD.");
throw new StopTestProcessingException();
} catch (SkipTestException se) {
xUnitLog.infoConsoleLogger("Skipping the metric tool processing.");
continue;
} catch (OldTestReportException se) {
xUnitLog.infoConsoleLogger("Failing BUILD.");
throw new StopTestProcessingException();
}

if (!result && xUnitToolInfo.isStopProcessingIfError()) {
xUnitLog.infoConsoleLogger("Fail BUILD because 'set build failed if errors' option is activated.");
xUnitLog.infoConsoleLogger("Failing BUILD because 'set build failed if errors' option is activated.");
throw new StopTestProcessingException();
}
}
Expand Down Expand Up @@ -173,6 +174,7 @@ protected void configure() {
tool.isFailIfNotNew(),
tool.isDeleteOutputFiles(), tool.isStopProcessingIfError(),
build.getTimeInMillis(),
this.extraConfiguration.getTestTimeMargin(),
(tool instanceof CustomType) ? getCustomStylesheet(tool, build, listener) : null);

}
Expand Down Expand Up @@ -282,7 +284,7 @@ private TestResult getTestResult(final AbstractBuild<?, ?> build,

public TestResult invoke(File ws, VirtualChannel channel) throws IOException {
final long nowSlave = System.currentTimeMillis();
File generatedJunitDir = new File(ws, GENERATED_JUNIT_DIR);
File generatedJunitDir = new File(ws, XUnitDefaultValues.GENERATED_JUNIT_DIR);
//Ignore return value
generatedJunitDir.mkdirs();
FileSet fs = Util.createFileSet(generatedJunitDir, junitFilePattern);
Expand Down Expand Up @@ -349,7 +351,7 @@ private Result processResultThreshold(XUnitLog log,
for (XUnitThreshold threshold : thresholds) {
log.infoConsoleLogger(String.format("Check '%s' threshold.", threshold.getDescriptor().getDisplayName()));
Result result;
if (MODE_PERCENT == thresholdMode) {
if (XUnitDefaultValues.MODE_PERCENT == thresholdMode) {
result = threshold.getResultThresholdPercent(log, build, testResultAction, previousTestResultAction);
} else {
result = threshold.getResultThresholdNumber(log, build, testResultAction, previousTestResultAction);
Expand All @@ -371,14 +373,14 @@ private void processDeletion(boolean dryRun, AbstractBuild<?, ?> build, XUnitLog
InputMetric inputMetric = tool.getInputMetric();

if (dryRun || tool.isDeleteOutputFiles()) {
getWorkspace(build).child(GENERATED_JUNIT_DIR + "/" + inputMetric.getToolName()).deleteRecursive();
getWorkspace(build).child(XUnitDefaultValues.GENERATED_JUNIT_DIR + "/" + inputMetric.getToolName()).deleteRecursive();
} else {
//Mark the tool file parent directory to no deletion
keepJUnitDirectory = true;
}
}
if (!keepJUnitDirectory) {
getWorkspace(build).child(GENERATED_JUNIT_DIR).deleteRecursive();
getWorkspace(build).child(XUnitDefaultValues.GENERATED_JUNIT_DIR).deleteRecursive();
}
} catch (IOException ioe) {
throw new XUnitException("Problem on deletion", ioe);
Expand Down
19 changes: 16 additions & 3 deletions src/main/java/org/jenkinsci/plugins/xunit/XUnitPublisher.java
Expand Up @@ -33,6 +33,7 @@ public class XUnitPublisher extends Recorder implements DryRun, Serializable {
private TestType[] types;
private XUnitThreshold[] thresholds;
private int thresholdMode;
private ExtraConfiguration extraConfiguration;

public XUnitPublisher(TestType[] types, XUnitThreshold[] thresholds) {
this.types = types;
Expand All @@ -41,10 +42,15 @@ public XUnitPublisher(TestType[] types, XUnitThreshold[] thresholds) {
}

@DataBoundConstructor
public XUnitPublisher(TestType[] tools, XUnitThreshold[] thresholds, int thresholdMode) {
public XUnitPublisher(TestType[] tools, XUnitThreshold[] thresholds, int thresholdMode, String testTimeMargin) {
this.types = tools;
this.thresholds = thresholds;
this.thresholdMode = thresholdMode;
long longTestTimeMargin = XUnitDefaultValues.TEST_REPORT_TIME_MARGING;
if (testTimeMargin != null && testTimeMargin.trim().length() != 0) {
longTestTimeMargin = Long.parseLong(testTimeMargin);
}
this.extraConfiguration = new ExtraConfiguration(longTestTimeMargin);
}

public TestType[] getTypes() {
Expand All @@ -59,6 +65,13 @@ public int getThresholdMode() {
return thresholdMode;
}

public ExtraConfiguration getExtraConfiguration() {
if (extraConfiguration == null) {
extraConfiguration = new ExtraConfiguration(XUnitDefaultValues.TEST_REPORT_TIME_MARGING);
}
return extraConfiguration;
}

@Override
public Action getProjectAction(AbstractProject<?, ?> project) {
JUnitResultArchiver jUnitResultArchiver = project.getPublishersList().get(JUnitResultArchiver.class);
Expand All @@ -71,14 +84,14 @@ public Action getProjectAction(AbstractProject<?, ?> project) {
@Override
public boolean perform(final AbstractBuild<?, ?> build, Launcher launcher, final BuildListener listener)
throws InterruptedException, IOException {
XUnitProcessor xUnitProcessor = new XUnitProcessor(types, thresholds, thresholdMode);
XUnitProcessor xUnitProcessor = new XUnitProcessor(getTypes(), getThresholds(), getThresholdMode(), getExtraConfiguration());
return xUnitProcessor.performXUnit(false, build, listener);
}

public boolean performDryRun(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
try {
XUnitProcessor xUnitProcessor = new XUnitProcessor(types, thresholds, thresholdMode);
XUnitProcessor xUnitProcessor = new XUnitProcessor(getTypes(), getThresholds(), getThresholdMode(), getExtraConfiguration());
xUnitProcessor.performXUnit(true, build, listener);
} catch (Throwable t) {
listener.getLogger().println("[ERROR] - There is an error: " + t.getCause().getMessage());
Expand Down
Expand Up @@ -4,6 +4,7 @@
import hudson.Util;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.jenkinsci.plugins.xunit.OldTestReportException;

import java.io.File;
import java.io.Serializable;
Expand Down Expand Up @@ -73,14 +74,14 @@ public List<String> findReports(XUnitToolInfo xUnitToolInfo, File parentPath, St
* @param workspace the root location of the file list
* @return true if all files are new, false otherwise
*/
public boolean checkIfFindsFilesNewFiles(XUnitToolInfo xUnitToolInfo, List<String> files, File workspace) {
public void checkIfFindsFilesNewFiles(XUnitToolInfo xUnitToolInfo, List<String> files, File workspace) throws OldTestReportException {

if (xUnitToolInfo.isFailIfNotNew()) {
ArrayList<File> oldResults = new ArrayList<File>();
for (String value : files) {
File reportFile = new File(workspace, value);
// if the file was not updated this build, that is a problem
if (xUnitToolInfo.getBuildTime() - 3000 > reportFile.lastModified()) {
if (xUnitToolInfo.getBuildTime() - xUnitToolInfo.getTestTimeMargin() > reportFile.lastModified()) {
oldResults.add(reportFile);
}
}
Expand All @@ -94,7 +95,7 @@ public boolean checkIfFindsFilesNewFiles(XUnitToolInfo xUnitToolInfo, List<Strin
"Please keep the slave clock in sync with the master.";
xUnitLog.errorConsoleLogger(msg);
errorSystemLogger(msg);
return false;
throw new OldTestReportException();
}

StringBuilder stringBuilder = new StringBuilder();
Expand All @@ -108,11 +109,9 @@ public boolean checkIfFindsFilesNewFiles(XUnitToolInfo xUnitToolInfo, List<Strin
String msg = stringBuilder.toString();
xUnitLog.errorConsoleLogger(msg);
errorSystemLogger(msg);
return false;
throw new OldTestReportException();
}
}

return true;
}

/**
Expand Down
Expand Up @@ -24,9 +24,14 @@ public class XUnitToolInfo implements Serializable {

private final long buildTime;

private final long testTimeMargin;

private FilePath cusXSLFile;

public XUnitToolInfo(FilePath userContentRoot, InputMetric inputMetric, String expandedPattern, Boolean skipNoTestFiles, Boolean failIfNotNew, Boolean deleteOutputFiles, Boolean stopProcessingIfError, long buildTime, FilePath cusXSLFile) {
public XUnitToolInfo(FilePath userContentRoot, InputMetric inputMetric,
String expandedPattern, Boolean skipNoTestFiles, Boolean failIfNotNew,
Boolean deleteOutputFiles, Boolean stopProcessingIfError,
long buildTime, long testTimeMargin, FilePath cusXSLFile) {
this.userContentRoot = userContentRoot;
this.inputMetric = inputMetric;
this.expandedPattern = expandedPattern;
Expand All @@ -35,6 +40,7 @@ public XUnitToolInfo(FilePath userContentRoot, InputMetric inputMetric, String e
this.deleteOutputFiles = deleteOutputFiles;
this.stopProcessingIfError = stopProcessingIfError;
this.buildTime = buildTime;
this.testTimeMargin = testTimeMargin;
this.cusXSLFile = cusXSLFile;
}

Expand Down Expand Up @@ -73,4 +79,8 @@ public boolean isStopProcessingIfError() {
public FilePath getUserContentRoot() {
return userContentRoot;
}

public long getTestTimeMargin() {
return testTimeMargin;
}
}
Expand Up @@ -4,9 +4,10 @@
import hudson.FilePath;
import hudson.remoting.VirtualChannel;
import hudson.util.IOException2;
import org.jenkinsci.plugins.xunit.NoTestException;
import org.jenkinsci.plugins.xunit.NoFoundTestException;
import org.jenkinsci.plugins.xunit.OldTestReportException;
import org.jenkinsci.plugins.xunit.SkipTestException;
import org.jenkinsci.plugins.xunit.XUnitProcessor;
import org.jenkinsci.plugins.xunit.XUnitDefaultValues;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -51,7 +52,7 @@ void load(
public Boolean invoke(File ws, VirtualChannel channel) throws IOException, InterruptedException {
try {

File junitOutputDir = new File(ws, XUnitProcessor.GENERATED_JUNIT_DIR);
File junitOutputDir = new File(ws, XUnitDefaultValues.GENERATED_JUNIT_DIR);
if (!junitOutputDir.exists() && !junitOutputDir.mkdirs()) {
String msg = "Can't create the path " + junitOutputDir + ". Maybe the directory already exists.";
xUnitLog.warningConsoleLogger(msg);
Expand All @@ -73,14 +74,11 @@ public Boolean invoke(File ws, VirtualChannel channel) throws IOException, Inter
String msg = "No test reports found for the metric '" + metricName + "' with the resolved pattern '" + xUnitToolInfo.getExpandedPattern() + "'. Configuration error?.";
xUnitLog.errorConsoleLogger(msg);
errorSystemLogger(msg);
throw new NoTestException();
throw new NoFoundTestException();
}

//Checks the timestamp for each test file if the UI option is checked (true by default)
if (!xUnitReportProcessorService.checkIfFindsFilesNewFiles(xUnitToolInfo, resultFiles, ws)) {
return false;
}

xUnitReportProcessorService.checkIfFindsFilesNewFiles(xUnitToolInfo, resultFiles, ws);

boolean atLeastOneWarningOrError = false;
for (String curFileName : resultFiles) {
Expand Down Expand Up @@ -142,8 +140,10 @@ public Boolean invoke(File ws, VirtualChannel channel) throws IOException, Inter

} catch (SkipTestException se) {
throw new SkipTestException();
} catch (NoTestException se) {
throw new NoTestException();
} catch (NoFoundTestException se) {
throw new NoFoundTestException();
} catch (OldTestReportException oe) {
throw new OldTestReportException();
} catch (Exception xe) {
String msg = xe.getMessage();
if (msg != null) {
Expand Down

0 comments on commit 7c05311

Please sign in to comment.