Permalink
Browse files

[JENKINS-48945] Testreport lacks of those test in which the hashcode …

…of two different testsuite name coincide

Use UUID instead the hashcode of the file to generate a unique converted test report.
By default java provides a version 4 UUID that ensure be unique in the same JVM instance. Since there are no more JVM that works with the same workspace is enough. A version 1 UUID that use MAC address to ensure file is unique over Jenkins nodes is not needed since XUnitProcessor does not copy slave node report files back to master.
  • Loading branch information...
nfalco79 committed Apr 25, 2018
1 parent a46fe62 commit 2885f4f57ceaa1e816db07ca414285935b83c783
@@ -33,5 +33,10 @@

public static final int MODE_PERCENT = 2;

public static final int TEST_REPORT_TIME_MARGING = 3000; //default to 3000ms
}
public static final int TEST_REPORT_TIME_MARGING = 3000; // default to 3000

public static final String JUNIT_FILE_PREFIX = "TEST-";

public static final String JUNIT_FILE_EXTENSION = ".xml";

}
@@ -28,19 +28,20 @@
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;

import javax.inject.Inject;

import org.jenkinsci.lib.dtkit.model.InputMetric;
import org.jenkinsci.lib.dtkit.model.InputMetricXSL;
import org.jenkinsci.lib.dtkit.util.converter.ConversionException;
import org.jenkinsci.plugins.xunit.XUnitDefaultValues;
import org.jenkinsci.plugins.xunit.exception.XUnitException;
import org.jenkinsci.plugins.xunit.types.CustomInputMetric;

import com.google.inject.Inject;

import hudson.FilePath;

public class XUnitConversionService extends XUnitService implements Serializable {

private XUnitLog xUnitLog;

@Inject
@@ -51,29 +52,29 @@ void load(XUnitLog xUnitLog) {
/**
* Converts the inputFile into a JUnit output file
*
* @param xUnitToolInfo the xUnit info wrapper object
* @param inputFile the input file to be converted
* @param workspace the workspace
* @param junitOutputDirectory the output parent directory that contains the JUnit output file
* @param xUnitToolInfo
* the xUnit info wrapper object
* @param inputFile
* the input file to be converted
* @param junitOutputDirectory
* the output parent directory that contains the JUnit output
* file
* @return the converted file
* @throws org.jenkinsci.plugins.xunit.exception.XUnitException an XUnitException is thrown if there is a conversion error.
* @throws org.jenkinsci.plugins.xunit.exception.XUnitException
* in case of conversion error.
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public File convert(XUnitToolInfo xUnitToolInfo, File inputFile, File workspace, File junitOutputDirectory) throws XUnitException {

public File convert(XUnitToolInfo xUnitToolInfo, File inputFile, File junitOutputDirectory) throws XUnitException {
InputMetric inputMetric = xUnitToolInfo.getInputMetric();

final String JUNIT_FILE_POSTFIX = ".xml";
final String JUNIT_FILE_PREFIX = "TEST-";
File parent = new File(junitOutputDirectory, inputMetric.getToolName());
if (!parent.exists() && !parent.mkdirs()) {
throw new XUnitException("Can't create " + parent);
}
File junitTargetFile = new File(parent, JUNIT_FILE_PREFIX + inputFile.hashCode() + JUNIT_FILE_POSTFIX);
try {

File junitTargetFile = getTargetFile(parent, inputFile);
try {
if (inputMetric instanceof CustomInputMetric) {
return convertCustomInputMetric(xUnitToolInfo, inputFile, workspace, inputMetric, junitTargetFile);
return convertCustomInputMetric(xUnitToolInfo, inputFile, inputMetric, junitTargetFile);
}

if (inputMetric instanceof InputMetricXSL) {
@@ -92,7 +93,24 @@ public File convert(XUnitToolInfo xUnitToolInfo, File inputFile, File workspace,
}
}

private File convertCustomInputMetric(XUnitToolInfo xUnitToolInfo, File inputFile, File workspace, InputMetric inputMetric, File junitTargetFile) throws IOException, InterruptedException, XUnitException {
/**
* Provides a unique target file name given an input report.The same input
* file is intended not be converted twice time.
* <p>
* By default java >= 6 provides a version 4 UUID that ensure be unique in
* the same JVM instance. Since there are no more JVM that works with the
* same workspace is enough. Version 1 UUID use MAC address but since
* {@code XUnitProcessor} does not copy slave node report files back to
* master is not necessary ensure file be globally unique.
*
* @return a node workspace unique file name
*/
private File getTargetFile(File parent, File inputFile) {
String uniqueTestName = UUID.randomUUID().toString();
return new File(parent, XUnitDefaultValues.JUNIT_FILE_PREFIX + uniqueTestName + XUnitDefaultValues.JUNIT_FILE_EXTENSION);
}

private File convertCustomInputMetric(XUnitToolInfo xUnitToolInfo, File inputFile, InputMetric inputMetric, File junitTargetFile) throws IOException, InterruptedException, XUnitException {
CustomInputMetric customInputMetric = (CustomInputMetric) inputMetric;
customInputMetric.setCustomXSLFile(new File(xUnitToolInfo.getCusXSLFile().getRemote()));
inputMetric.convert(inputFile, junitTargetFile);
@@ -29,15 +29,15 @@
import java.io.Serializable;
import java.util.List;

import javax.inject.Inject;

import org.jenkinsci.lib.dtkit.util.validator.ValidationError;
import org.jenkinsci.plugins.xunit.NoFoundTestException;
import org.jenkinsci.plugins.xunit.OldTestReportException;
import org.jenkinsci.plugins.xunit.SkipTestException;
import org.jenkinsci.plugins.xunit.XUnitDefaultValues;
import org.jenkinsci.remoting.RoleChecker;

import com.google.inject.Inject;

import hudson.FilePath;
import hudson.remoting.VirtualChannel;
import jenkins.security.Roles;
@@ -144,7 +144,7 @@ public Boolean invoke(File ws, VirtualChannel channel) throws IOException, Inter
}

//Convert the input file
File junitTargetFile = xUnitConversionService.convert(xUnitToolInfo, curFile, ws, junitOutputDir);
File junitTargetFile = xUnitConversionService.convert(xUnitToolInfo, curFile, junitOutputDir);

//Validates converted file
if (!xUnitValidationService.validateOutputFile(xUnitToolInfo, curFile, junitTargetFile)) {
@@ -24,11 +24,12 @@

package org.jenkinsci.plugins.xunit.types;

import hudson.Extension;
import org.jenkinsci.lib.dtkit.descriptor.TestTypeDescriptor;
import org.jenkinsci.lib.dtkit.type.TestType;
import org.kohsuke.stapler.DataBoundConstructor;

import hudson.Extension;

/**
* @author Gregory Boissinot
*/
@@ -37,13 +38,11 @@
private String customXSL;

@DataBoundConstructor
@SuppressWarnings("unused")
public CustomType(String pattern, String customXSL, boolean skipNoTestFiles, boolean failIfNotNew, boolean deleteOutputFiles, boolean stopProcessingIfError) {
super(pattern, skipNoTestFiles, failIfNotNew, deleteOutputFiles, stopProcessingIfError);
this.customXSL = customXSL;
}

@SuppressWarnings("unused")
public String getCustomXSL() {
return customXSL;
}
@@ -0,0 +1,33 @@
package org.jenkinsci.plugins.xunit.service;

import static org.mockito.Mockito.*;

import java.io.File;

import org.jenkinsci.plugins.xunit.types.JUnitInputMetric;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.jvnet.hudson.test.Issue;

public class XUnitConversionServiceTest {

@Rule
public TemporaryFolder folder = new TemporaryFolder();

@Issue("JENKINS-48945")
@Test
public void verify_that_report_file_name_does_clashes() throws Exception {
File destFolder = folder.newFolder();
File inputFile = folder.newFile("com.acme.EKOM02XTest");

XUnitToolInfo toolInfo = mock(XUnitToolInfo.class);
when(toolInfo.getInputMetric()).thenReturn(new JUnitInputMetric());

XUnitConversionService service = new XUnitConversionService();
File reportFile = service.convert(toolInfo, inputFile, destFolder);
File reportFile2 = service.convert(toolInfo, inputFile, destFolder);
Assert.assertNotEquals(reportFile.getAbsolutePath(), reportFile2.getAbsolutePath());
}
}
Oops, something went wrong.

0 comments on commit 2885f4f

Please sign in to comment.