diff --git a/src/main/java/com/blackduck/integration/detect/configuration/enumeration/ExitCodeType.java b/src/main/java/com/blackduck/integration/detect/configuration/enumeration/ExitCodeType.java index df49d04746..da978ecbaf 100644 --- a/src/main/java/com/blackduck/integration/detect/configuration/enumeration/ExitCodeType.java +++ b/src/main/java/com/blackduck/integration/detect/configuration/enumeration/ExitCodeType.java @@ -25,6 +25,7 @@ public enum ExitCodeType { ), FAILURE_ACCURACY_NOT_MET(15, "Detect was unable to meet the required accuracy."), + FAILURE_OUT_OF_MEMORY(16, "Detect encountered an Out of Memory error. Please review memory settings and system resources.", 0.5), FAILURE_IMAGE_NOT_AVAILABLE(20, "Image scan attempted but no return data available."), @@ -35,14 +36,22 @@ public enum ExitCodeType { private final int exitCode; private final String description; + private final double priority; ExitCodeType(int exitCode, String description) { + this(exitCode, description, (double) exitCode); + } + + ExitCodeType(int exitCode, String description, double priority) { this.exitCode = exitCode; this.description = description; + this.priority = priority; } /** - * A failure always beats a success and a failure with a lower exit code beats a failure with a higher exit code. + * A failure always beats a success. Among failures: + * - The one with a lower priority wins. + * - If priorities are equal, the one with a lower exit code wins. */ public static ExitCodeType getWinningExitCodeType(ExitCodeType first, ExitCodeType second) { if (first.isSuccess()) { @@ -50,11 +59,7 @@ public static ExitCodeType getWinningExitCodeType(ExitCodeType first, ExitCodeTy } else if (second.isSuccess()) { return first; } else { - if (first.getExitCode() < second.getExitCode()) { - return first; - } else { - return second; - } + return (first.getPriority() < second.getPriority()) ? first : second; } } @@ -69,4 +74,6 @@ public boolean isSuccess() { public String getDescription() { return description; } + + public double getPriority() { return priority; } } diff --git a/src/main/java/com/blackduck/integration/detect/tool/detector/DetectorIssuePublisher.java b/src/main/java/com/blackduck/integration/detect/tool/detector/DetectorIssuePublisher.java index eab40d6e66..41f0e56957 100644 --- a/src/main/java/com/blackduck/integration/detect/tool/detector/DetectorIssuePublisher.java +++ b/src/main/java/com/blackduck/integration/detect/tool/detector/DetectorIssuePublisher.java @@ -7,6 +7,9 @@ import com.blackduck.integration.detect.workflow.status.DetectIssue; import com.blackduck.integration.detect.workflow.status.DetectIssueType; import com.blackduck.integration.detect.workflow.status.StatusEventPublisher; +import com.blackduck.integration.detector.base.DetectorStatusCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DetectorIssuePublisher { public void publishIssues(StatusEventPublisher statusEventPublisher, List reports) { @@ -25,4 +28,12 @@ public void publishIssues(StatusEventPublisher statusEventPublisher, List reports) { + return reports.stream() + .flatMap(report -> report.getNotExtractedDetectors().stream()) + .flatMap(notExtracted -> notExtracted.getAttemptedDetectables().stream()) + .anyMatch(attemptedDetectableReport -> { + return attemptedDetectableReport.getStatusCode() == DetectorStatusCode.EXECUTABLE_TERMINATED_LIKELY_OUT_OF_MEMORY; + }); + } } diff --git a/src/main/java/com/blackduck/integration/detect/tool/detector/DetectorTool.java b/src/main/java/com/blackduck/integration/detect/tool/detector/DetectorTool.java index 7ec4588155..dfb14067f7 100644 --- a/src/main/java/com/blackduck/integration/detect/tool/detector/DetectorTool.java +++ b/src/main/java/com/blackduck/integration/detect/tool/detector/DetectorTool.java @@ -12,6 +12,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; +import com.blackduck.integration.detector.base.DetectorStatusCode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -108,6 +109,8 @@ public DetectorToolResult performDetectors( List reports = new DetectorReporter().generateReport(evaluation); DetectorToolResult toolResult = publishAllResults(reports, directory, projectDetector, requiredDetectors, requiredAccuracyTypes); + checkAndHandleOutOfMemoryIssue(reports); + //Completed. logger.debug("Finished running detectors."); detectorEventPublisher.publishDetectorsComplete(toolResult); @@ -115,6 +118,13 @@ public DetectorToolResult performDetectors( return toolResult; } + private void checkAndHandleOutOfMemoryIssue(List reports) { + if (detectorIssuePublisher.hasOutOfMemoryIssue(reports)) { + logger.error("Detected an issue. " + DetectorStatusCode.EXECUTABLE_TERMINATED_LIKELY_OUT_OF_MEMORY.getDescription()); + exitCodePublisher.publishExitCode(ExitCodeType.FAILURE_OUT_OF_MEMORY, "Executable terminated likely due to out of memory."); + } + } + private DetectorToolResult publishAllResults( List reports, File directory, diff --git a/src/test/java/com/blackduck/integration/detect/configuration/ExitCodeTypeTest.java b/src/test/java/com/blackduck/integration/detect/configuration/ExitCodeTypeTest.java new file mode 100644 index 0000000000..930451ea13 --- /dev/null +++ b/src/test/java/com/blackduck/integration/detect/configuration/ExitCodeTypeTest.java @@ -0,0 +1,28 @@ +package com.blackduck.integration.detect.configuration; + +import com.blackduck.integration.detect.configuration.enumeration.ExitCodeType; +import org.junit.jupiter.api.Test; +import java.util.HashSet; +import java.util.Set; +import static org.junit.jupiter.api.Assertions.*; + +class ExitCodeTypeTest { + + @Test + void testUniquePriorities() { + Set priorities = new HashSet<>(); + for (ExitCodeType exitCode : ExitCodeType.values()) { + assertTrue(priorities.add(exitCode.getPriority()), + "Duplicate priority found: " + exitCode.getPriority()); + } + } + + @Test + void testUniqueExitCodes() { + Set exitCodes = new HashSet<>(); + for (ExitCodeType exitCode : ExitCodeType.values()) { + assertTrue(exitCodes.add(exitCode.getExitCode()), + "Duplicate exit code found: " + exitCode.getExitCode()); + } + } +}