diff --git a/plugin/pom.xml b/plugin/pom.xml index d86bd9566..c798423a3 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -5,7 +5,7 @@ org.jvnet.hudson.plugins analysis-pom - 6.7.0 + 6.8.0 @@ -34,7 +34,7 @@ 0.24.0 2.0.0 - 1.29.0-4 + 1.29.0-6 1.7.8 diff --git a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/PathResolver.java b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/PathResolver.java index 44fe887f6..e0dfe4c4d 100644 --- a/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/PathResolver.java +++ b/plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/PathResolver.java @@ -2,14 +2,12 @@ import java.io.File; import java.io.IOException; -import java.io.Serializable; import java.nio.file.InvalidPathException; import java.util.AbstractMap.SimpleEntry; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -25,6 +23,7 @@ import io.jenkins.plugins.prism.PermittedSourceCodeDirectory; import io.jenkins.plugins.prism.PrismConfiguration; import io.jenkins.plugins.prism.SourceDirectoryFilter; +import io.jenkins.plugins.util.RemoteResultWrapper; /** * Resolves source code files on the agent using the stored paths of the coverage reports. Since these paths are @@ -199,57 +198,4 @@ private boolean isWithinWorkspace(final String fileName, final FilePath workspac return PATH_UTIL.getAbsolutePath(fileName).startsWith(workspacePath); } } - - /** - * A serializable result combined with a logger. Enables remote calls to return a result and a corresponding log. - * - * @param - * the type of the result - * - * @author Ullrich Hafner - */ - // FIXME: replace with plugin-util class once released - static final class RemoteResultWrapper extends FilteredLog { - private static final long serialVersionUID = -6411417555105688927L; - - private final T result; - - /** - * Creates a new instance of {@link RemoteResultWrapper}. - * - * @param result - * the wrapped result - * @param title - * the title of the error messages - */ - RemoteResultWrapper(final T result, final String title) { - super(title); - - this.result = result; - } - - public T getResult() { - return result; - } - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - RemoteResultWrapper that = (RemoteResultWrapper) o; - return Objects.equals(result, that.result); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), result); - } - } } diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeITest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeITest.java index 5efaea627..02ff0912d 100644 --- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeITest.java +++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeITest.java @@ -7,6 +7,8 @@ import java.util.Optional; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import edu.hm.hafner.coverage.Coverage.CoverageBuilder; import edu.hm.hafner.coverage.FileNode; @@ -29,7 +31,7 @@ import static org.assertj.core.api.Assertions.*; /** - * Verifies if source code copying and rendering works on agents. + * Verifies the source code copying and rendering on agents. * * @author Ullrich Hafner */ @@ -50,32 +52,32 @@ abstract class SourceCodeITest extends AbstractCoverageITest { static final String AGENT_LABEL = "coverage-agent"; private static final PathUtil UTIL = new PathUtil(); - /** Verifies that the plugin reads source code from the workspace root. */ - @Test - void coveragePluginPipelineWithSourceCode() throws IOException { - runCoverageWithSourceCode(""); + @ParameterizedTest(name = "Entries of `sourceDirectories` use absolute paths: {0}") + @ValueSource(booleans = {true, false}) + void verifySourcesInWorkspaceRoot(final boolean useAbsolutePath) throws IOException { + runCoverageWithSourceCode("", useAbsolutePath); } - /** Verifies that the plugin reads source code in subdirectories of the workspace. */ - @Test - void coveragePluginPipelineWithSourceCodeInSubdirectory() throws IOException { - runCoverageWithSourceCode("sub-dir"); + @ParameterizedTest(name = "Entries of `sourceDirectories` use absolute paths: {0}") + @ValueSource(booleans = {true, false}) + void verifySourcesInWorkspaceSubFolder(final boolean useAbsolutePath) throws IOException { + runCoverageWithSourceCode("sub-dir", useAbsolutePath); } - /** Verifies that the plugin reads source code in external but approved directories. */ @Test - void coveragePluginPipelineWithSourceCodeInPermittedDirectory() throws IOException { + void verifySourcesInApprovedExternalFolder() throws IOException { String directory = createExternalFolder(); PrismConfiguration.getInstance().setSourceDirectories(List.of(new PermittedSourceCodeDirectory(directory))); - Run externalDirectory = runCoverageWithSourceCode(directory); + Run externalDirectory = runCoverageWithSourceCode(directory, false); assertThat(getConsoleLog(externalDirectory)) .contains("Searching for source code files in:", "-> " + directory); } - /** Verifies that the plugin refuses source code in directories that are not approved in Jenkins' configuration. */ @Test - void coveragePluginPipelineNotRegisteredSourceCodeDirectory() throws IOException { + void refuseSourceCodePaintingInNotApprovedExternalFolder() throws IOException { + PrismConfiguration.getInstance().setSourceDirectories(List.of()); + var localAgent = crateCoverageAgent(); String sourceDirectory = createExternalFolder(); @@ -92,15 +94,13 @@ void coveragePluginPipelineNotRegisteredSourceCodeDirectory() throws IOException .contains("-> finished resolving of absolute paths (found: 0, not found: 1)") .contains("-> finished painting (0 files have been painted, 1 files failed)") .contains(String.format( - "[-ERROR-] Removing source directory '%s' - it has not been approved in Jenkins' global configuration.", + "[-ERROR-] Removing non-workspace source directory '%s' - it has not been approved in Jenkins' global configuration.", sourceDirectory)) .contains("- Source file '" + ACU_COBOL_PARSER_SOURCE_FILE_PATH + "' not found"); - - verifySourceCodeInBuild("", firstBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available localAgent.setLabelString(""); } - private Run runCoverageWithSourceCode(final String sourceDir) + private Run runCoverageWithSourceCode(final String sourceDir, final boolean useAbsolutePath) throws IOException { var localAgent = crateCoverageAgent(); @@ -114,7 +114,14 @@ void coveragePluginPipelineNotRegisteredSourceCodeDirectory() throws IOException assertThat(temporaryDirectory.isDirectory()).isTrue(); File[] temporaryFiles = temporaryDirectory.listFiles(); - job.setDefinition(createPipelineWithSourceCode(EVERY_BUILD, sourceDir)); + String requestedSourceFolder; + if (useAbsolutePath) { + requestedSourceFolder = new PathUtil().getAbsolutePath(getAgentWorkspace(localAgent, job).child(sourceDir).getRemote()); + } + else { + requestedSourceFolder = sourceDir; + } + job.setDefinition(createPipelineWithSourceCode(EVERY_BUILD, requestedSourceFolder)); Run firstBuild = buildSuccessfully(job); assertThat(getConsoleLog(firstBuild)) .contains("-> resolved absolute paths for all 1 source files") diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/PathResolverTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/PathResolverTest.java deleted file mode 100644 index 1876e1d88..000000000 --- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/PathResolverTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.jenkins.plugins.coverage.metrics.steps; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import nl.jqno.equalsverifier.EqualsVerifier; -import nl.jqno.equalsverifier.Warning; - -import io.jenkins.plugins.coverage.metrics.steps.PathResolver.RemoteResultWrapper; - -import static org.assertj.core.api.Assertions.*; - -class PathResolverTest { - @Nested - class RemoteResultWrapperTest { - @Test - void shouldCreateWrapper() { - var result = "result"; - - var wrapper = new RemoteResultWrapper<>(result, "title"); - - assertThat(wrapper.getResult()).isEqualTo(result); - - wrapper.logInfo("Hello %s", "World"); - assertThat(wrapper.getInfoMessages()).containsExactly("Hello World"); - } - - @Test - void shouldAdhereToEquals() { - EqualsVerifier.simple().forClass(RemoteResultWrapper.class) - .suppress(Warning.NULL_FIELDS) - .verify(); - } - } -} diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/model/CoveragePluginSourceITest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/model/CoveragePluginSourceITest.java index 5fa8e5f39..d124980b7 100644 --- a/plugin/src/test/java/io/jenkins/plugins/coverage/model/CoveragePluginSourceITest.java +++ b/plugin/src/test/java/io/jenkins/plugins/coverage/model/CoveragePluginSourceITest.java @@ -98,7 +98,7 @@ void coveragePluginPipelineNotRegisteredSourceCodeDirectory() throws IOException assertThat(getConsoleLog(firstBuild)) .contains("-> finished painting (0 files have been painted, 1 files failed)") .contains(String.format( - "[-ERROR-] Removing source directory '%s' - it has not been approved in Jenkins' global configuration.", + "[-ERROR-] Removing non-workspace source directory '%s' - it has not been approved in Jenkins' global configuration.", sourceDirectory)); verifySourceCodeInBuild(firstBuild, NO_SOURCE_CODE); // should be still available