Skip to content

Commit

Permalink
Merge pull request #291 from MicroFocus/abangau_cpe_2451038
Browse files Browse the repository at this point in the history
defect #2451038 Octane cannot correctly open test run report
  • Loading branch information
andreibangau99 authored Jun 5, 2024
2 parents 43da521 + 5bc1e7c commit 219f05e
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
Expand Down Expand Up @@ -125,6 +125,37 @@ public static FilePath getWorkspace(Run<?, ?> run) {
logger.error("BuildHandlerUtils.getWorkspace - run is not handled. Run type : " + run.getClass());
return null;
}
public static Set<FilePath> getWorkspaces(Run<?, ?> run) {
if (run.getExecutor() != null && run.getExecutor().getCurrentWorkspace() != null) {
return Collections.singleton(run.getExecutor().getCurrentWorkspace());
}
if (run instanceof AbstractBuild) {
return Collections.singleton(((AbstractBuild) run).getWorkspace());
}
Set<FilePath> workspaces = new HashSet<>();
if (run instanceof WorkflowRun) {
FlowExecution fe = ((WorkflowRun) run).getExecution();
if (fe != null) {
FlowGraphWalker w = new FlowGraphWalker(fe);
for (FlowNode n : w) {
WorkspaceAction action = n.getAction(WorkspaceAction.class);
if (action != null) {
FilePath workspace = action.getWorkspace();
if (workspace == null) {
workspace = handleWorkspaceActionWithoutWorkspace(action);
}
workspaces.add(workspace);
}
}
}
}

if(workspaces.isEmpty()) {
logger.error("BuildHandlerUtils.getWorkspaces - run is not handled. Run type : " + run.getClass());
}

return workspaces;
}

private static FilePath handleWorkspaceActionWithoutWorkspace(WorkspaceAction action) {
logger.error("Found WorkspaceAction without workspace");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.hp.octane.integrations.utils.SdkConstants.JobParameters.OCTANE_CONFIG_ID_PARAMETER_NAME;

Expand Down Expand Up @@ -194,21 +195,23 @@ private static class GetJUnitTestResults implements FilePath.FileCallable<FilePa
private List<ModuleDetection> moduleDetection;
private long buildStarted;
private FilePath workspace;
private Set<FilePath> allWorkspaces;
private boolean stripPackageAndClass;
private String sharedCheckOutDirectory;
private Pattern testParserRegEx;
private boolean octaneSupportsSteps;

//this class is run on master and JUnitXmlIterator is runnning on slave.
//this object pass some master2slave data
private Object additionalContext;
private String nodeName;
private Object additionalContext;
private final Set<String> nodeNames = new HashSet<>();

public GetJUnitTestResults(Run<?, ?> build, HPRunnerType hpRunnerType, List<FilePath> reports, boolean stripPackageAndClass, String jenkinsRootUrl) throws IOException, InterruptedException {
this.reports = reports;
this.filePath = new FilePath(build.getRootDir()).createTempFile(TEMP_TEST_RESULTS_FILE_NAME_PREFIX, null);
this.buildStarted = build.getStartTimeInMillis();
this.workspace = BuildHandlerUtils.getWorkspace(build);
this.allWorkspaces = BuildHandlerUtils.getWorkspaces(build);
this.stripPackageAndClass = stripPackageAndClass;
this.hpRunnerType = hpRunnerType;
this.jenkinsRootUrl = jenkinsRootUrl;
Expand All @@ -230,22 +233,31 @@ public GetJUnitTestResults(Run<?, ?> build, HPRunnerType hpRunnerType, List<File


if (HPRunnerType.UFT.equals(hpRunnerType) || HPRunnerType.UFT_MBT.equals(hpRunnerType)) {
Node node = JenkinsUtils.getCurrentNode(workspace);
this.nodeName = node != null && !node.getNodeName().isEmpty() ? node.getNodeName() : "";

List<Node> nodes = allWorkspaces.stream()
.map(JenkinsUtils::getCurrentNode)
.collect(Collectors.toList());
nodes.forEach(node -> this.nodeNames.add(node != null && !node.getNodeName().isEmpty() ? node.getNodeName() : ""));
//extract folder names for created tests
String reportFolder = buildRootDir + "/archive/UFTReport" +
(StringUtils.isNotEmpty(this.nodeName) ? "/" + this.nodeName : "");

List<String> reportFolders = new ArrayList<>();
this.nodeNames.forEach(nodeName ->
reportFolders.add(buildRootDir + "/archive/UFTReport" + (StringUtils.isNotEmpty(nodeName) ? "/" + nodeName : "")));

List<String> testFolderNames = new ArrayList<>();
testFolderNames.add(build.getRootDir().getAbsolutePath());
File reportFolderFile = new File(reportFolder);
if (reportFolderFile.exists()) {
File[] children = reportFolderFile.listFiles();
if (children != null) {
for (File child : children) {
testFolderNames.add(child.getName());
reportFolders.forEach(reportFolder ->{
File reportFolderFile = new File(reportFolder);
if (reportFolderFile.exists()) {
File[] children = reportFolderFile.listFiles();
if (children != null) {
for (File child : children) {
testFolderNames.add(child.getParentFile().getName() + "/" + child.getName());
}
}
}
}
});

additionalContext = testFolderNames;
}
if (HPRunnerType.StormRunnerLoad.equals(hpRunnerType)) {
Expand Down Expand Up @@ -292,7 +304,9 @@ public FilePath invoke(File f, VirtualChannel channel) throws IOException, Inter

try {
for (FilePath report : reports) {
JUnitXmlIterator iterator = new JUnitXmlIterator(report.read(), moduleDetection, workspace, sharedCheckOutDirectory, jobName, buildId, buildStarted, stripPackageAndClass, hpRunnerType, jenkinsRootUrl, additionalContext,testParserRegEx, octaneSupportsSteps,nodeName);
JUnitXmlIterator iterator = new JUnitXmlIterator(report.read(), moduleDetection, workspace, sharedCheckOutDirectory, jobName,
buildId, buildStarted, stripPackageAndClass, hpRunnerType, jenkinsRootUrl, additionalContext,
testParserRegEx, octaneSupportsSteps, nodeNames);
while (iterator.hasNext()) {
oos.writeObject(iterator.next());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,13 @@ public class JUnitXmlIterator extends AbstractXmlIterator<JUnitTestResult> {
private String stepName;
private ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
private Map<String, CodelessResult> testNameToCodelessResultMap = new HashMap<>();
private String nodeName;
private Set<String> nodeNames;

private final int ERROR_MESSAGE_MAX_SIZE = System.getProperty("octane.sdk.tests.error_message_max_size") != null ? Integer.parseInt(System.getProperty("octane.sdk.tests.error_message_max_size")) : 512*512;
private final int ERROR_DETAILS_MAX_SIZE = System.getProperty("octane.sdk.tests.error_details_max_size") != null ? Integer.parseInt(System.getProperty("octane.sdk.tests.error_details_max_size")) : 512*512;


public JUnitXmlIterator(InputStream read, List<ModuleDetection> moduleDetection, FilePath workspace, String sharedCheckOutDirectory, String jobName, String buildId, long buildStarted, boolean stripPackageAndClass, HPRunnerType hpRunnerType, String jenkinsRootUrl, Object additionalContext, Pattern testParserRegEx, boolean octaneSupportsSteps,String nodeName) throws XMLStreamException {
public JUnitXmlIterator(InputStream read, List<ModuleDetection> moduleDetection, FilePath workspace, String sharedCheckOutDirectory, String jobName, String buildId, long buildStarted, boolean stripPackageAndClass, HPRunnerType hpRunnerType, String jenkinsRootUrl, Object additionalContext, Pattern testParserRegEx, boolean octaneSupportsSteps,Set<String> nodeNames) throws XMLStreamException {
super(read);
this.stripPackageAndClass = stripPackageAndClass;
this.moduleDetection = moduleDetection;
Expand All @@ -139,7 +139,7 @@ public JUnitXmlIterator(InputStream read, List<ModuleDetection> moduleDetection,
this.additionalContext = additionalContext;
this.testParserRegEx = testParserRegEx;
this.octaneSupportsSteps = octaneSupportsSteps;
this.nodeName = nodeName;
this.nodeNames = nodeNames;
}

private static long parseTime(String timeString) {
Expand Down Expand Up @@ -261,24 +261,37 @@ private void handleJUnitTest(XMLEvent event) throws XMLStreamException, IOExcept
}

String cleanedTestName = cleanTestName(testName);
String nodeName = "";
if(!nodeNames.isEmpty()){
nodeName = nodeNames.stream().findFirst().get();
}
boolean testReportCreated = true;
if (additionalContext != null && additionalContext instanceof List) {
//test folders are appear in the following format GUITest1[1], while [1] number of test. It possible that tests with the same name executed in the same job
//by adding [1] or [2] we can differentiate between different instances.
//We assume that test folders are sorted so in this section, once we found the test folder, we remove it from collection , in order to find the second instance in next iteration
List<String> createdTests = (List<String>) additionalContext;
String searchFor = cleanedTestName + "[";
Optional<String> optional = createdTests.stream().filter(str -> str.startsWith(searchFor)).findFirst();
Optional<String> optional = createdTests.stream().filter(str -> str.contains(searchFor)).findFirst();
if (optional.isPresent()) {
cleanedTestName = optional.get();
createdTests.remove(cleanedTestName);
String nodeTestString = optional.get();
if(nodeTestString.contains("/")){
String node = nodeTestString.split("/")[0];
if (nodeNames.contains(node)) {
nodeName = node;
}

cleanedTestName = nodeTestString.split("/")[1];
createdTests.remove(nodeTestString);
}

}
testReportCreated = optional.isPresent();
}

if (testReportCreated) {
final String basePath = ((List<String>) additionalContext).get(0);
String nodeNameSubFolder = StringUtils.isNotEmpty(this.nodeName) ? nodeName +"/" : "";
String nodeNameSubFolder = StringUtils.isNotEmpty(nodeName) ? nodeName +"/" : "";
uftResultFilePath = Paths.get(basePath, "archive", "UFTReport", nodeNameSubFolder, cleanedTestName, "/Result/run_results.xml").toFile().getCanonicalPath();
externalURL = jenkinsRootUrl + "job/" + jobName + "/" + buildId + "/artifact/UFTReport/" + nodeNameSubFolder + cleanedTestName + "/Result/run_results.html";
} else {
Expand Down

0 comments on commit 219f05e

Please sign in to comment.