diff --git a/.cirrus.yml b/.cirrus.yml index 9537825b..96ce6213 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -49,6 +49,7 @@ build_task: folder: ${CIRRUS_WORKING_DIR}/.m2/repository script: - source cirrus-env BUILD + - mvn -f property-dump-plugin/pom.xml -B install - regular_mvn_build_deploy_analyze cleanup_before_cache_script: - cleanup_maven_repository @@ -72,7 +73,7 @@ mend_scan_task: mend_script: - source cirrus-env QA - source set_maven_build_version $BUILD_NUMBER - - mvn clean install -DskipTests + - mvn clean install -DskipTests -B - source ws_scan.sh cleanup_before_cache_script: cleanup_maven_repository allow_failures: "true" @@ -86,7 +87,7 @@ qa_task: <<: *ONLY_SONARSOURCE_QA eks_container: <<: *CONTAINER_DEFINITION - cpu: 2 + cpu: 6 memory: 4G env: matrix: diff --git a/cirrus/cirrus-qa.sh b/cirrus/cirrus-qa.sh index c8d93cba..2072a3b7 100755 --- a/cirrus/cirrus-qa.sh +++ b/cirrus/cirrus-qa.sh @@ -10,6 +10,9 @@ mkdir -p $MAVEN_HOME_IT curl -sSL https://repo1.maven.org/maven2/org/apache/maven/apache-maven/$MAVEN_VERSION/apache-maven-$MAVEN_VERSION-bin.tar.gz | tar zx --strip-components 1 -C $MAVEN_HOME_IT cp -f ~/.m2/settings.xml $MAVEN_HOME_IT/conf/ +# We need to build this small plugin first, that will dump the analysis properties in a local file +mvn -f property-dump-plugin/pom.xml --batch-mode -Dmaven.home=$MAVEN_HOME_IT install + # Run ITs. cd its mvn -B -e -Dsonar.runtimeVersion=$SQ_VERSION -Dmaven.test.redirectTestOutputToFile=false -Dmaven.home=$MAVEN_HOME_IT verify diff --git a/its/pom.xml b/its/pom.xml index 82aa302c..e8a28480 100644 --- a/its/pom.xml +++ b/its/pom.xml @@ -38,12 +38,6 @@ 2.5.1 test - - junit - junit - 4.13.1 - test - org.assertj assertj-core @@ -87,13 +81,25 @@ provided - + org.apache.maven.plugins maven-surefire-plugin + 3.5.1 + + + + junit.jupiter.execution.parallel.enabled = true + junit.jupiter.execution.parallel.mode.default = same_thread + junit.jupiter.execution.parallel.mode.classes.default = concurrent + junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$ClassName + junit.jupiter.testmethod.order.default=org.junit.jupiter.api.MethodOrderer$MethodName + + + diff --git a/its/projects/maven/aggregator-inherit-parent-and-bind-to-verify/pom.xml b/its/projects/maven/aggregator-inherit-parent-and-bind-to-verify/pom.xml index 69320fd8..f4d51a6e 100644 --- a/its/projects/maven/aggregator-inherit-parent-and-bind-to-verify/pom.xml +++ b/its/projects/maven/aggregator-inherit-parent-and-bind-to-verify/pom.xml @@ -7,7 +7,7 @@ 1.0-SNAPSHOT parent/pom.xml - aggregator + aggregator-inherit-parent 1.0-SNAPSHOT pom diff --git a/its/projects/maven/bootstrap-small-project/pom.xml b/its/projects/maven/bootstrap-small-project/pom.xml new file mode 100644 index 00000000..47913a2e --- /dev/null +++ b/its/projects/maven/bootstrap-small-project/pom.xml @@ -0,0 +1,13 @@ + + 4.0.0 + org.sonarsource.maven.its + bootstrap-small-project + 1.0-SNAPSHOT + + + 11 + 11 + + + diff --git a/its/projects/project-default-config/pom.xml b/its/projects/project-default-config/pom.xml index a2ce5327..350aaed8 100644 --- a/its/projects/project-default-config/pom.xml +++ b/its/projects/project-default-config/pom.xml @@ -21,8 +21,8 @@ maven-compiler-plugin 3.3 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/its/projects/version/compilerPluginConfig/pom.xml b/its/projects/version/compilerPluginConfig/pom.xml index bf4d5476..5ae578cf 100644 --- a/its/projects/version/compilerPluginConfig/pom.xml +++ b/its/projects/version/compilerPluginConfig/pom.xml @@ -23,7 +23,7 @@ maven-compiler-plugin 3.3 - 1.7 + 1.8 1.8 diff --git a/its/projects/version/properties/pom.xml b/its/projects/version/properties/pom.xml index eabe5320..723fd9c8 100644 --- a/its/projects/version/properties/pom.xml +++ b/its/projects/version/properties/pom.xml @@ -6,7 +6,7 @@ Sonar :: Integration Tests :: Java Version - 1.7 + 1.8 1.8 diff --git a/its/src/test/java/com/sonar/maven/it/suite/AbstractMavenTest.java b/its/src/test/java/com/sonar/maven/it/suite/AbstractMavenTest.java index bb820d24..6faba933 100644 --- a/its/src/test/java/com/sonar/maven/it/suite/AbstractMavenTest.java +++ b/its/src/test/java/com/sonar/maven/it/suite/AbstractMavenTest.java @@ -19,31 +19,29 @@ */ package com.sonar.maven.it.suite; -import com.eclipsesource.json.Json; -import com.eclipsesource.json.JsonValue; +import com.sonar.orchestrator.build.Build; import com.sonar.orchestrator.build.BuildResult; import com.sonar.orchestrator.build.MavenBuild; import com.sonar.orchestrator.container.Server; -import com.sonar.orchestrator.http.HttpMethod; -import com.sonar.orchestrator.http.HttpResponse; import com.sonar.orchestrator.junit5.OrchestratorExtension; +import com.sonar.orchestrator.locator.FileLocation; import com.sonar.orchestrator.version.Version; - import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; import javax.annotation.CheckForNull; - import org.apache.commons.lang.StringUtils; -import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.extension.RegisterExtension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonarqube.ws.Ce.TaskStatus; import org.sonarqube.ws.Components.Component; import org.sonarqube.ws.Measures; import org.sonarqube.ws.Measures.Measure; @@ -51,30 +49,64 @@ import org.sonarqube.ws.client.HttpException; import org.sonarqube.ws.client.WsClient; import org.sonarqube.ws.client.WsClientFactories; +import org.sonarqube.ws.client.ce.TaskRequest; import org.sonarqube.ws.client.components.ShowRequest; -import org.sonarqube.ws.client.components.TreeRequest; import org.sonarqube.ws.client.measures.ComponentRequest; import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; + public abstract class AbstractMavenTest { + private static final Logger LOG = LoggerFactory.getLogger(AbstractMavenTest.class); + + public static final int EXEC_SUCCESS = 0; + public static final int EXEC_FAILED = 1; + private static final Pattern VERSION_REGEX = Pattern.compile("Apache Maven\\s(\\d+\\.\\d+(?:\\.\\d+)?)(?:-\\S+)?\\s"); private static Version mojoVersion; - @RegisterExtension + private static int orchestratorAccessingClassCount = 0; + + // @RegisterExtension was removed because it did not properly support parallel execution public static final OrchestratorExtension ORCHESTRATOR = OrchestratorExtension.builderEnv() .setSonarVersion(getSonarVersion()) .useDefaultAdminCredentialsForBuilds(true) .addBundledPluginToKeep("sonar-java-plugin") .addBundledPluginToKeep("sonar-xml-plugin") .addBundledPluginToKeep("sonar-html-plugin") + // This plugin should have been built locally from the property-dump-plugin module + .addPlugin(FileLocation.of("../property-dump-plugin/target/property-dump-plugin-1-SNAPSHOT.jar")) .build(); protected HttpConnector wsConnector; protected WsClient wsClient; + @BeforeAll + public static void setUp() { + synchronized (AbstractMavenTest.class) { + orchestratorAccessingClassCount++; + if (orchestratorAccessingClassCount == 1) { + ORCHESTRATOR.start(); + } + } + } + + @AfterAll + public static void tearDown() { + synchronized (AbstractMavenTest.class) { + orchestratorAccessingClassCount--; + if (orchestratorAccessingClassCount < 0) { + throw new IllegalStateException("tearDown called too many times"); + } + if (orchestratorAccessingClassCount == 0) { + ORCHESTRATOR.stop(); + } + } + } + protected static String[] cleanInstallSonarGoal() { return new String[]{"clean install " + sonarGoal()}; } @@ -91,10 +123,6 @@ protected static String[] cleanPackageSonarGoal() { return new String[]{"clean package " + sonarGoal()}; } - protected static String[] cleanVerifySonarGoal() { - return new String[]{"clean verify " + sonarGoal()}; - } - @BeforeEach public void setUpWsClient() { wsConnector = HttpConnector.newBuilder() @@ -104,40 +132,6 @@ public void setUpWsClient() { wsClient = WsClientFactories.getDefault().newClient(wsConnector); } - @AfterEach - public void resetData() { - Set projectKeys = getProjectKeysToDelete(); - - if (!projectKeys.isEmpty()) { - ORCHESTRATOR.getServer() - .newHttpCall("/api/projects/bulk_delete") - .setAdminCredentials() - .setMethod(HttpMethod.POST) - .setParams("projects", String.join(",", projectKeys)) - .execute(); - } - } - - private Set getProjectKeysToDelete() { - HttpResponse ps = ORCHESTRATOR.getServer() - .newHttpCall("api/projects/search") - .setAdminCredentials() - .setMethod(HttpMethod.GET) - .setParam("ps", "100") - .execute(); - - return Json.parse(ps.getBodyAsString()) - .asObject() - .get("components") - .asArray() - .values() - .stream() - .map(JsonValue::asObject) - .map(members -> members.getString("key", "")) - .filter(s -> !s.isEmpty()) - .collect(Collectors.toSet()); - } - protected static Version mojoVersion() { if (mojoVersion == null) { try { @@ -184,13 +178,16 @@ static Component getComponent(String componentKey) { } } - static List getModules(String projectKey) { - return newWsClient().components().tree(new TreeRequest().setComponent(projectKey).setQualifiers(singletonList("BRC"))).getComponentsList(); + static WsClient newWsClient() { + return WsClientFactories.getDefault().newClient(HttpConnector.newBuilder() + .url(ORCHESTRATOR.getServer().getUrl()) + .build()); } - static WsClient newWsClient() { + static WsClient newAuthenticatedWsClient() { return WsClientFactories.getDefault().newClient(HttpConnector.newBuilder() .url(ORCHESTRATOR.getServer().getUrl()) + .credentials(Server.ADMIN_LOGIN, Server.ADMIN_PASSWORD) .build()); } @@ -204,7 +201,7 @@ protected Version getMavenVersion() { MavenBuild build = MavenBuild.create() .setGoals("-version"); - BuildResult result = ORCHESTRATOR.executeBuild(build); + BuildResult result = assertBuildResultStatuses( ORCHESTRATOR.executeBuild(build), 0); String logs = result.getLogs(); Matcher matcher = VERSION_REGEX.matcher(logs); @@ -218,7 +215,89 @@ protected Version getMavenVersion() { private static String getSonarVersion() { String versionProperty = System.getProperty("sonar.runtimeVersion"); - return versionProperty != null ? versionProperty : "DEV"; + return versionProperty != null ? versionProperty : "LATEST_RELEASE"; + } + + public BuildResult executeBuildAndValidateWithCE(Build build) { + return validateBuildWithCE(ORCHESTRATOR.executeBuild(build)); + } + + public static BuildResult validateBuildWithCE(BuildResult result) { + assertBuildResultStatuses(result, 0); + List ceTaskIds = extractCETaskIds(result); + if (ceTaskIds.isEmpty()) { + throw new AssertionError("No CE task id found in logs, can't wait for the CE task to be finished"); + } + for (String ceTaskId : ceTaskIds) { + waitForCeTaskToBeFinished(ceTaskId); + } + return result; + } + + public BuildResult executeBuildAndValidateWithoutCE(Build build) { + return validateBuildWithoutCE(ORCHESTRATOR.executeBuild(build)); + } + + public static BuildResult validateBuildWithoutCE(BuildResult result) { + return validateBuildWithoutCE(result, EXEC_SUCCESS); + } + + public static BuildResult validateBuildWithoutCE(BuildResult result, int expectedStatus) { + assertBuildResultStatuses(result, expectedStatus); + assertThat(extractCETaskIds(result)) + .withFailMessage("The build result contains unexpected CE task ids") + .isEmpty(); + return result; + } + + public static BuildResult assertBuildResultStatuses(BuildResult result, int expectedStatus) { + for (Integer status : result.getStatuses()) { + assertThat(status).isEqualTo(expectedStatus); + } + return result; + } + + // [INFO] More about the report processing at http://127.0.0.1:63532/api/ce/task?id=bedf3100-4d72-497b-8103-68402821e49c + private static final Pattern CE_TASK_ID_PATTERN = Pattern.compile("More about the report processing at[^?]++\\?id=([\\w\\-]++)"); + + public static List extractCETaskIds(BuildResult result) { + Matcher matcher = CE_TASK_ID_PATTERN.matcher(result.getLogs()); + List ids = new ArrayList<>(); + while (matcher.find()) { + ids.add(matcher.group(1)); + } + return ids; + } + + private static final long POLLING_TIME = 500; // 0.5 second + private static final long MAX_WAIT_TIME = 20_000; // 20 seconds + + private static void waitForCeTaskToBeFinished(String ceTaskId) { + LOG.info("Waiting for CE task {} to be finished", ceTaskId); + try { + WsClient wsClient = newAuthenticatedWsClient(); + long start = System.currentTimeMillis(); + while (true) { + TaskStatus status = wsClient.ce().task(new TaskRequest().setId(ceTaskId)).getTask().getStatus(); + if (status == TaskStatus.PENDING || status == TaskStatus.IN_PROGRESS) { + long duration = System.currentTimeMillis() - start; + if (duration > MAX_WAIT_TIME) { + throw new AssertionError("CE task " + ceTaskId + " did not finish after " + (MAX_WAIT_TIME / 1000) + " seconds"); + } + LOG.info("CE task {} has status {}, wait duration {} ms", ceTaskId, status.name(), duration); + Thread.sleep(POLLING_TIME); + } else if (status == TaskStatus.SUCCESS) { + LOG.info("CE task {} succeeded", ceTaskId); + return; + } else { + // FAILED or CANCELED + throw new AssertionError("CE task " + ceTaskId + " failed: " + status.name()); + } + + } + } catch (InterruptedException e) { + throw new AssertionError("Interrupted while waiting for CE task to be finished", e); + } } } diff --git a/its/src/test/java/com/sonar/maven/it/suite/BootstrapTest.java b/its/src/test/java/com/sonar/maven/it/suite/BootstrapTest.java new file mode 100644 index 00000000..9b88f24e --- /dev/null +++ b/its/src/test/java/com/sonar/maven/it/suite/BootstrapTest.java @@ -0,0 +1,92 @@ +/* + * SonarSource :: IT :: SonarQube Maven + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package com.sonar.maven.it.suite; + +import com.sonar.maven.it.ItUtils; +import com.sonar.orchestrator.build.BuildResult; +import com.sonar.orchestrator.build.BuildRunner; +import com.sonar.orchestrator.build.MavenBuild; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Properties; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BootstrapTest extends AbstractMavenTest { + + @Test + void test_unsupported_platform() { + String unsupportedOS = "unsupportedOS"; + String arch = "amd64"; + + BuildRunner runner = new BuildRunner(ORCHESTRATOR.getConfiguration()); + MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/bootstrap-small-project")) + .setProperty("sonar.scanner.os", unsupportedOS) + .setProperty("sonar.scanner.arch", arch) + .setProperty("sonar.login", ORCHESTRATOR.getDefaultAdminToken()) + .setProperty("sonar.host.url", ORCHESTRATOR.getServer().getUrl()) + .setGoals(cleanSonarGoal()); + + boolean sonarQubeThatSupportJREProvisioning = ORCHESTRATOR.getServer().version().isGreaterThanOrEquals(10, 6); + if (sonarQubeThatSupportJREProvisioning) { + BuildResult result = validateBuildWithoutCE(runner.runQuietly(null, build), EXEC_FAILED); + String url = ORCHESTRATOR.getServer().getUrl() + String.format("/api/v2/analysis/jres?os=%s&arch=%s", unsupportedOS, arch); + String expectedLog = String.format("Error status returned by url [%s]: 400", url); + assertThat(result.getLogs()).contains(expectedLog); + } else { + validateBuildWithCE(runner.runQuietly(null, build)); + } + } + + @Test + void test_supported_arch_to_assert_jre_used() throws IOException { + BuildRunner runner = new BuildRunner(ORCHESTRATOR.getConfiguration()); + String projectName = "maven/bootstrap-small-project"; + MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom(projectName)) + .setProperty("sonar.login", ORCHESTRATOR.getDefaultAdminToken()) + .setProperty("sonar.host.url", ORCHESTRATOR.getServer().getUrl()) + .setGoals(cleanSonarGoal()); + + + BuildResult result = validateBuildWithCE(runner.runQuietly(null, build)); + assertThat(result.isSuccess()).isTrue(); + Path propertiesFile = ItUtils.locateProjectDir(projectName).toPath().resolve("target/sonar/dumpSensor.system.properties"); + Properties props = new Properties(); + props.load(Files.newInputStream(propertiesFile)); + + if (ORCHESTRATOR.getServer().version().isGreaterThanOrEquals(10, 6)) { + //we test that we are actually using the JRE downloaded from SQ + assertThat(props.getProperty("java.home")) + .isNotEmpty() + .isNotEqualTo(System.getProperty("java.home")) + .contains(".sonar" + File.separator + "cache"); + } else { + //we test that we are using the system JRE + assertThat(props.getProperty("java.home")) + .isNotEmpty() + .isEqualTo(System.getProperty("java.home")) + .doesNotContain(".sonar" + File.separator + "cache"); + } + } + +} diff --git a/its/src/test/java/com/sonar/maven/it/suite/JavaTest.java b/its/src/test/java/com/sonar/maven/it/suite/JavaTest.java index 7e4f1386..31c4b583 100644 --- a/its/src/test/java/com/sonar/maven/it/suite/JavaTest.java +++ b/its/src/test/java/com/sonar/maven/it/suite/JavaTest.java @@ -57,8 +57,8 @@ void shouldPopulateLibraries() throws IOException { File projectPom = ItUtils.locateProjectPom("shared/struts-1.3.9-diet"); MavenBuild build = MavenBuild.create(projectPom) .setGoals(cleanPackageSonarGoal()) - .setProperty("sonar.scanner.dumpToFile", outputProps.getAbsolutePath()); - ORCHESTRATOR.executeBuild(build); + .setProperty("sonar.scanner.internal.dumpToFile", outputProps.getAbsolutePath()); + executeBuildAndValidateWithoutCE(build); Properties generatedProps = getProps(outputProps); String[] moduleIds = generatedProps.getProperty("sonar.modules").split(","); @@ -84,15 +84,15 @@ void read_default_from_plugins_config() throws Exception { File pom = ItUtils.locateProjectPom("project-default-config"); MavenBuild build = MavenBuild.create(pom) .setGoals(cleanPackageSonarGoal()) - .setProperty("sonar.scanner.dumpToFile", outputProps.getAbsolutePath()); - ORCHESTRATOR.executeBuild(build); + .setProperty("sonar.scanner.internal.dumpToFile", outputProps.getAbsolutePath()); + executeBuildAndValidateWithoutCE(build); Properties props = getProps(outputProps); assertThat(props).contains( entry("sonar.findbugs.excludeFilters", new File(pom.getParentFile(), "findbugs-filter.xml").toString()), entry("sonar.junit.reportsPath", new File(pom.getParentFile(), "target/surefire-output").toString()), entry("sonar.junit.reportPaths", new File(pom.getParentFile(), "target/surefire-output").toString()), - entry("sonar.java.source", "1.7")); + entry("sonar.java.source", "1.8")); } @Test @@ -103,12 +103,12 @@ void setJavaVersionCompilerConfiguration() throws IOException { File pom = ItUtils.locateProjectPom("version/compilerPluginConfig"); MavenBuild build = MavenBuild.create(pom) .setGoals(cleanPackageSonarGoal()) - .setProperty("sonar.scanner.dumpToFile", outputProps.getAbsolutePath()); - ORCHESTRATOR.executeBuild(build); + .setProperty("sonar.scanner.internal.dumpToFile", outputProps.getAbsolutePath()); + executeBuildAndValidateWithoutCE(build); Properties props = getProps(outputProps); assertThat(props).contains( - entry("sonar.java.source", "1.7"), + entry("sonar.java.source", "1.8"), entry("sonar.java.target", "1.8")); } @@ -120,12 +120,12 @@ void setJavaVersionProperties() throws IOException { File pom = ItUtils.locateProjectPom("version/properties"); MavenBuild build = MavenBuild.create(pom) .setGoals(cleanPackageSonarGoal()) - .setProperty("sonar.scanner.dumpToFile", outputProps.getAbsolutePath()); - ORCHESTRATOR.executeBuild(build); + .setProperty("sonar.scanner.internal.dumpToFile", outputProps.getAbsolutePath()); + executeBuildAndValidateWithoutCE(build); Properties props = getProps(outputProps); assertThat(props).contains( - entry("sonar.java.source", "1.7"), + entry("sonar.java.source", "1.8"), entry("sonar.java.target", "1.8")); } @@ -137,11 +137,12 @@ void setJdkHomeFromCompilerExecutableConfiguration() throws IOException { File pom = ItUtils.locateProjectPom("jdkHome/compilerPluginConfigExecutable"); MavenBuild build = MavenBuild.create(pom) .setGoals(sonarGoal()) - .setProperty("sonar.scanner.dumpToFile", outputProps.getAbsolutePath()); - ORCHESTRATOR.executeBuild(build); + .setProperty("sonar.scanner.internal.dumpToFile", outputProps.getAbsolutePath()); + executeBuildAndValidateWithoutCE(build); Properties props = getProps(outputProps); - assertThat(props).contains(entry("sonar.java.jdkHome", "path/to/java_executable")); + String expected = "path/to/java_executable".replace('/', File.separatorChar); + assertThat(props).contains(entry("sonar.java.jdkHome", expected)); } @Test @@ -155,8 +156,8 @@ void setJdkHomeFromGlobalToolchainsPlugin() throws IOException { // Run only the toolchain goal + sonar. Can't run a true build since our toolchains paths are fake .setGoals("toolchains:toolchain " + sonarGoal()) .addArguments("--toolchains", new File(pom.getParent(), "toolchains.xml").getAbsolutePath()) - .setProperty("sonar.scanner.dumpToFile", outputProps.getAbsolutePath()); - ORCHESTRATOR.executeBuild(build); + .setProperty("sonar.scanner.internal.dumpToFile", outputProps.getAbsolutePath()); + executeBuildAndValidateWithoutCE(build); Properties props = getProps(outputProps); assertThat(props).contains(entry("sonar.java.jdkHome", "fake_jdk_1.5")); @@ -175,8 +176,8 @@ void setJdkHomeFromCompilerToolchainsConfiguration() throws IOException { .setExecutionDir(pom.getParentFile()) .setGoals(sonarGoal()) .addArguments("--toolchains", new File(pom.getParent(), "toolchains.xml").getAbsolutePath()) - .setProperty("sonar.scanner.dumpToFile", outputProps.getAbsolutePath()); - ORCHESTRATOR.executeBuild(build); + .setProperty("sonar.scanner.internal.dumpToFile", outputProps.getAbsolutePath()); + executeBuildAndValidateWithoutCE(build); Properties props = getProps(outputProps); assertThat(props).contains(entry("sonar.java.jdkHome", "fake_jdk_1.6")); @@ -195,8 +196,8 @@ void takeFirstToolchainIfMultipleExecutions() throws IOException { .setExecutionDir(pom.getParentFile()) .setGoals(sonarGoal()) .addArguments("--toolchains", new File(pom.getParent(), "toolchains.xml").getAbsolutePath()) - .setProperty("sonar.scanner.dumpToFile", outputProps.getAbsolutePath()); - ORCHESTRATOR.executeBuild(build); + .setProperty("sonar.scanner.internal.dumpToFile", outputProps.getAbsolutePath()); + executeBuildAndValidateWithoutCE(build); Properties props = getProps(outputProps); assertThat(props).contains(entry("sonar.java.jdkHome", "fake_jdk_9")); diff --git a/its/src/test/java/com/sonar/maven/it/suite/LinksTest.java b/its/src/test/java/com/sonar/maven/it/suite/LinksTest.java index 30c8e908..f1006104 100644 --- a/its/src/test/java/com/sonar/maven/it/suite/LinksTest.java +++ b/its/src/test/java/com/sonar/maven/it/suite/LinksTest.java @@ -44,17 +44,14 @@ void shouldUseLinkPropertiesOverPomLinksInMaven() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("batch/links-project")) .setGoals(cleanPackageSonarGoal()) .setProperty("sonar.scm.disabled", "true"); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); checkLinks(); } private void checkLinks() { Server server = ORCHESTRATOR.getServer(); - WsClient client = WsClientFactories.getDefault().newClient(HttpConnector.newBuilder() - .url(server.getUrl()) - .credentials(Server.ADMIN_LOGIN, Server.ADMIN_PASSWORD) - .build()); + WsClient client = newAuthenticatedWsClient(); SearchWsResponse response = client.projectLinks().search(new SearchRequest().setProjectKey("com.sonarsource.it.samples:simple-sample")); if (server.version().isGreaterThanOrEquals(7, 1)) { // SONAR-10299 diff --git a/its/src/test/java/com/sonar/maven/it/suite/MavenTest.java b/its/src/test/java/com/sonar/maven/it/suite/MavenTest.java index bd302661..573092ff 100644 --- a/its/src/test/java/com/sonar/maven/it/suite/MavenTest.java +++ b/its/src/test/java/com/sonar/maven/it/suite/MavenTest.java @@ -24,9 +24,7 @@ import com.sonar.orchestrator.build.BuildRunner; import com.sonar.orchestrator.build.MavenBuild; import java.io.File; -import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Map; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.AfterEach; @@ -88,10 +86,9 @@ void supportSonarHostURLParam() { .setEnvironmentVariable("SONAR_HOST_URL", "http://from-env.org:9000") .setGoals(cleanSonarGoal()); - BuildResult result = runner.runQuietly(null, build); + BuildResult result = validateBuildWithoutCE(runner.runQuietly(null, build), EXEC_FAILED); - assertThat(result.isSuccess()).isFalse(); - assertThat(result.getLogs()).contains("http://dummy-url.org"); + assertThat(result.getLogs()).contains("java.net.UnknownHostException: from-env.org"); } /** @@ -104,9 +101,7 @@ void supportSonarHostURLParamFromEnvironmentVariable() { .setEnvironmentVariable("SONAR_HOST_URL", "http://from-env.org:9000") .setGoals(cleanSonarGoal()); - BuildResult result = runner.runQuietly(null, build); - - assertThat(result.isSuccess()).isFalse(); + BuildResult result = validateBuildWithoutCE(runner.runQuietly(null, build), EXEC_FAILED); assertThat(result.getLogs()).contains("http://from-env.org:9000"); } @@ -117,7 +112,7 @@ void supportSonarHostURLParamFromEnvironmentVariable() { void structureWithRelativePaths() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/maven-structure-relative-paths")) .setGoals(cleanSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); } /** @@ -127,14 +122,14 @@ void structureWithRelativePaths() { void flatStructure() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/maven-flat-layout/parent")) .setGoals(cleanSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); } @Test void aggregatorInheritParent() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/aggregator-inherit-parent")) .setGoals(cleanSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getMeasureAsInteger("org.sonarsource.maven.its:aggregator", "files")).isEqualTo(4); // 4 x pom.xml } @@ -143,15 +138,15 @@ void aggregatorInheritParentAndSonarAttachedToPhase() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/aggregator-inherit-parent-and-bind-to-verify")) .setGoals("clean verify") .setProperty("sonar.maven.it.mojoVersion", mojoVersion().toString()); - ORCHESTRATOR.executeBuild(build); - assertThat(getMeasureAsInteger("org.sonarsource.maven.its:aggregator", "files")).isEqualTo(4); // 4 x pom.xml + executeBuildAndValidateWithCE(build); + assertThat(getMeasureAsInteger("org.sonarsource.maven.its:aggregator-inherit-parent", "files")).isEqualTo(4); // 4 x pom.xml } @Test void shouldSupportJarWithoutSources() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/project-with-module-without-sources")) .setGoals(cleanSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getMeasureAsInteger("com.sonarsource.it.samples.project-with-module-without-sources:parent", "files")).isEqualTo(4); assertThat(getComponent("com.sonarsource.it.samples.project-with-module-without-sources:parent:without-sources")).isNotNull(); @@ -164,7 +159,7 @@ void shouldSupportJarWithoutSources() { void shouldSupportJeeProjects() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/jee")) .setGoals(cleanInstallSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); // src/main/webapp is analyzed by web and xml plugin assertThat(getMeasureAsInteger("com.sonarsource.it.samples.jee:parent", "files")).isEqualTo(9); @@ -177,7 +172,7 @@ void shouldSupportJeeProjects() { void shouldSupportMavenExtensions() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/maven-extensions")) .setGoals(cleanSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getMeasureAsInteger("com.sonarsource.it.samples:maven-extensions", "files")).isEqualTo(2); } @@ -190,7 +185,7 @@ void testBadMavenParameters() { // should not fail MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/maven-bad-parameters")) .setGoals(cleanSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getMeasureAsInteger("com.sonarsource.it.samples.maven-bad-parameters:parent", "files")).isPositive(); } @@ -199,7 +194,7 @@ void testBadMavenParameters() { void shouldAnalyzeMultiModules() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/modules-order")) .setGoals(cleanSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getComponent("org.sonar.tests.modules-order:root").getName()).isEqualTo("Sonar tests - modules order"); @@ -216,7 +211,7 @@ void shouldAnalyzeMultiModules() { void shouldEvaluateSourceVersionOnEachModule() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/modules-source-versions")) .setGoals(cleanSonarGoal()); - BuildResult buildResult = ORCHESTRATOR.executeBuild(build); + BuildResult buildResult = executeBuildAndValidateWithCE(build); assertThat(findScanSectionOfModule(buildResult.getLogs(), "higher-version")).contains("Configured Java source version (sonar.java.source): 8"); assertThat(findScanSectionOfModule(buildResult.getLogs(), "same-version")).contains("Configured Java source version (sonar.java.source): 6"); @@ -239,7 +234,7 @@ void shouldAnalyzeMultiModulesAttachedToPhase() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/attach-sonar-to-verify")) .setGoals("clean verify") .setProperty("sonar.maven.it.mojoVersion", mojoVersion().toString()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getComponent("com.sonarsource.it.samples:attach-sonar-to-verify")).isNotNull(); assertThat(getMeasureAsInteger("com.sonarsource.it.samples:attach-sonar-to-verify", "files")).isEqualTo(11); @@ -252,7 +247,7 @@ void shouldAnalyzeMultiModulesAttachedToPhase() { void shouldSupportDifferentDeclarationsForModules() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/modules-declaration")) .setGoals(cleanSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getComponent("org.sonar.tests.modules-declaration:root").getName()).isEqualTo("Root"); @@ -288,7 +283,7 @@ void should_support_shade_with_dependency_reduced_pom_with_clean_package_sonar_g MavenBuild build = MavenBuild.create(projectLocation) .setGoals(cleanPackageSonarGoal()); - BuildResult result = ORCHESTRATOR.executeBuildQuietly(build); + BuildResult result = executeBuildAndValidateWithCE(build); // Test a reduced pom has peen produced as a result of clean package assertThat(dependencyReducedPom).exists(); @@ -321,7 +316,7 @@ void should_support_shade_with_dependency_reduced_pom_with_clean_package_sonar_g void maven_project_with_only_test_dir() { // Need package to have test execution MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/maven-only-test-dir")).setGoals(cleanPackageSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getMeasureAsInteger("com.sonarsource.it.samples:maven-only-test-dir", "tests")).isEqualTo(1); assertThat(getMeasureAsInteger("com.sonarsource.it.samples:maven-only-test-dir", "files")).isEqualTo(1); @@ -333,7 +328,7 @@ void maven_project_with_only_test_dir() { @Test void override_sources() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/maven-override-sources")).setGoals(sonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getMeasureAsInteger("com.sonarsource.it.samples:maven-override-sources", "files")).isEqualTo(1); assertThat(getComponent("com.sonarsource.it.samples:maven-override-sources:src/main/java2/Hello2.java")).isNotNull(); @@ -345,7 +340,7 @@ void override_sources() { @Test void override_sources_in_multi_module() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/multi-modules-override-sources")).setGoals(sonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getMeasureAsInteger("com.sonarsource.it.samples:multi-modules-sample:module_a", "files")).isEqualTo(2); @@ -358,7 +353,7 @@ void override_sources_in_multi_module() { void override_sources_in_multi_module_aggregator() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/multi-module-aggregator")) .setGoals(sonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getMeasureAsInteger("edu.marcelo:multi-module-aggregator:module-web/src/main/webapp", "files")).isEqualTo(2); } @@ -369,7 +364,7 @@ void override_sources_in_multi_module_aggregator() { @Test void inclusions_apply_to_source_dirs() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/inclusions_apply_to_source_dirs")).setGoals(sonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getMeasureAsInteger("com.sonarsource.it.samples:inclusions_apply_to_source_dirs", "files")).isEqualTo(1); assertThat(getComponent("com.sonarsource.it.samples:inclusions_apply_to_source_dirs:src/main/java/Hello2.java")).isNotNull(); @@ -381,8 +376,7 @@ void inclusions_apply_to_source_dirs() { @Test void fail_if_bad_value_of_sonar_sources_property() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/maven-bad-sources-property")).setGoals(sonarGoal()); - BuildResult result = ORCHESTRATOR.executeBuildQuietly(build); - assertThat(result.getLastStatus()).isNotZero(); + BuildResult result = validateBuildWithoutCE(ORCHESTRATOR.executeBuildQuietly(build), EXEC_FAILED); assertThat(result.getLogs()).contains( "java2' does not exist for Maven module com.sonarsource.it.samples:maven-bad-sources-property:jar:1.0-SNAPSHOT. Please check the property sonar.sources"); } @@ -393,8 +387,7 @@ void fail_if_bad_value_of_sonar_sources_property() { @Test void fail_if_bad_value_of_sonar_tests_property() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("maven/maven-bad-tests-property")).setGoals(sonarGoal()); - BuildResult result = ORCHESTRATOR.executeBuildQuietly(build); - assertThat(result.getLastStatus()).isNotZero(); + BuildResult result = validateBuildWithoutCE(ORCHESTRATOR.executeBuildQuietly(build), EXEC_FAILED); assertThat(result.getLogs()).contains( "java2' does not exist for Maven module com.sonarsource.it.samples:maven-bad-tests-property:jar:1.0-SNAPSHOT. Please check the property sonar.tests"); } @@ -404,7 +397,7 @@ void fail_if_bad_value_of_sonar_tests_property() { void shouldSkipModules() { MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom("exclusions/skip-one-module")) .setGoals(cleanSonarGoal()); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); assertThat(getComponent("com.sonarsource.it.samples:multi-modules-sample:module_a/module_a1")).isNull(); assertThat(getComponent("com.sonarsource.it.samples:multi-modules-sample:module_a/module_a2").getName()).isEqualTo("module_a2"); @@ -418,8 +411,9 @@ void shouldSkipWithEnvVar() { .setGoals(cleanSonarGoal()) .setProperties("sonar.host.url", "invalid") .setEnvironmentVariable("SONARQUBE_SCANNER_PARAMS", "{ \"sonar.scanner.skip\" : \"true\" }"); - BuildResult result = ORCHESTRATOR.executeBuild(build); + BuildResult result = executeBuildAndValidateWithoutCE(build); assertThat(result.getLogs()).contains("SonarQube Scanner analysis skipped"); + assertThat(extractCETaskIds(result)).isEmpty(); } /** @@ -442,7 +436,7 @@ void supportMavenEncryption() throws Exception { build.addArgument("-Dsettings.security=" + securityXml.getAbsolutePath()); build.setProperty("sonar.login", "julien"); build.addArgument("-Psonar-password"); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); }); } @@ -462,7 +456,7 @@ void supportMavenEncryptionWithDefaultSecuritySettings() throws Exception { build.setProperty("sonar.login", "julien3"); build.addArgument("-Psonar-password"); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); }); Assertions.assertDoesNotThrow(() -> { @@ -475,16 +469,11 @@ void supportMavenEncryptionWithDefaultSecuritySettings() throws Exception { File securityXml = new File(this.getClass().getResource("/security-settings.xml").toURI()); File settingsXml = new File(this.getClass().getResource("/settings-with-encrypted-sonar-password.xml").toURI()); - // Adding ~/.m2/settings-security.xml - String userHomeDir = System.getProperty("user.home"); - Path defaultPath = Paths.get(userHomeDir, ".m2", "settings-security.xml"); - Files.copy(securityXml.toPath(), defaultPath); - build.addArgument("--settings=" + settingsXml.getAbsolutePath()); - + build.addArgument("-Dsettings.security=" + securityXml.getAbsolutePath()); build.setProperty("sonar.login", "julien2"); build.addArgument("-Psonar-password"); - ORCHESTRATOR.executeBuild(build); + executeBuildAndValidateWithCE(build); }); } } diff --git a/its/src/test/java/com/sonar/maven/it/suite/ProxyTest.java b/its/src/test/java/com/sonar/maven/it/suite/ProxyTest.java index 821d8cb0..dbc838e6 100644 --- a/its/src/test/java/com/sonar/maven/it/suite/ProxyTest.java +++ b/its/src/test/java/com/sonar/maven/it/suite/ProxyTest.java @@ -71,7 +71,7 @@ void useActiveProxyInSettings() throws IOException, URISyntaxException, Interrup build.addArgument("--settings=" + proxyXmlPatched.toAbsolutePath().toString()); build.addArgument("-X"); build.addArgument("-U"); - BuildResult result = ORCHESTRATOR.executeBuildQuietly(build); + BuildResult result = executeBuildAndValidateWithCE(build); assertThat(result.getLogs()).contains("Setting proxy properties"); assertThat(proxy.seen()).isNotEmpty(); diff --git a/pom.xml b/pom.xml index 54943931..0854da97 100644 --- a/pom.xml +++ b/pom.xml @@ -4,8 +4,7 @@ org.sonarsource.parent parent - 74.0.0.1768 - + 80.0.0.2205 org.sonarsource.scanner.maven @@ -128,9 +127,9 @@ - org.sonarsource.scanner.api - sonar-scanner-api - 2.16.3.1081 + org.sonarsource.scanner.lib + sonar-scanner-java-library + 3.1.1.261 diff --git a/property-dump-plugin/pom.xml b/property-dump-plugin/pom.xml new file mode 100644 index 00000000..8ada7edd --- /dev/null +++ b/property-dump-plugin/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + + org.sonarsource.parent + parent + 80.0.0.2205 + + + org.sonarsource.scanner.maven + property-dump-plugin + 1-SNAPSHOT + sonar-plugin + + + 17 + + + + + org.sonarsource.api.plugin + sonar-plugin-api + 10.12.0.2522 + provided + + + org.slf4j + slf4j-api + 1.7.30 + provided + + + + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.23.0.740 + true + + Property Dump Plugin + true + org.sonar.dump.PropertyDumpPlugin + true + 9.14.0.375 + 17 + + + + + + diff --git a/property-dump-plugin/src/main/java/org/sonar/dump/PropertyDumpPlugin.java b/property-dump-plugin/src/main/java/org/sonar/dump/PropertyDumpPlugin.java new file mode 100644 index 00000000..3d49148a --- /dev/null +++ b/property-dump-plugin/src/main/java/org/sonar/dump/PropertyDumpPlugin.java @@ -0,0 +1,61 @@ +/* + * property-dump-plugin + * Copyright (C) 2009-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.dump; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.Plugin; +import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.SensorDescriptor; + +public class PropertyDumpPlugin implements Plugin, Sensor { + + private static final Logger LOG = LoggerFactory.getLogger(PropertyDumpPlugin.class); + + @Override + public void define(Context context) { + context.addExtension(this); + } + + @Override + public void describe(SensorDescriptor sensorDescriptor) { + sensorDescriptor.name("Property Dump Sensor"); + } + + @Override + public void execute(SensorContext sensorContext) { + var props = System.getProperties(); + try { + Path filePath = sensorContext.fileSystem().workDir().toPath().resolve("dumpSensor.system.properties"); + LOG.info("Dumping system properties to {}", filePath); + props.stringPropertyNames().stream() + .filter(key -> key.startsWith("java.")) + .forEach(key -> LOG.info("{}={}", key, props.getProperty(key))); + props.store(Files.newOutputStream(filePath), null); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/it/invoker.properties b/src/it/invoker.properties index 90d453f0..8aca53b2 100644 --- a/src/it/invoker.properties +++ b/src/it/invoker.properties @@ -1 +1 @@ -invoker.goals = ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.dumpToFile=out.properties \ No newline at end of file +invoker.goals = ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.internal.dumpToFile=out.properties \ No newline at end of file diff --git a/src/it/java-compiler-context-toolchain/invoker.properties b/src/it/java-compiler-context-toolchain/invoker.properties index cccf07f2..4c1cefe4 100644 --- a/src/it/java-compiler-context-toolchain/invoker.properties +++ b/src/it/java-compiler-context-toolchain/invoker.properties @@ -1,3 +1,3 @@ -invoker.goals = --toolchains toolchains.xml toolchains:toolchain ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.dumpToFile=out.properties +invoker.goals = --toolchains toolchains.xml toolchains:toolchain ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.internal.dumpToFile=out.properties # cannot run this IT with Maven 2 since required --toolchains option was added in 3.0-alpha-3: see MNG-3714 invoker.maven.version = 3.0+ \ No newline at end of file diff --git a/src/it/java-compiler-plugin-multi-toolchain/invoker.properties b/src/it/java-compiler-plugin-multi-toolchain/invoker.properties index 112e9038..bc8cf5b8 100644 --- a/src/it/java-compiler-plugin-multi-toolchain/invoker.properties +++ b/src/it/java-compiler-plugin-multi-toolchain/invoker.properties @@ -1,3 +1,3 @@ -invoker.goals = --toolchains toolchains.xml ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.dumpToFile=out.properties +invoker.goals = --toolchains toolchains.xml ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.internal.dumpToFile=out.properties # Due to toolchain support invoker.maven.version = 3.3.1+ \ No newline at end of file diff --git a/src/it/java-compiler-plugin-toolchain/invoker.properties b/src/it/java-compiler-plugin-toolchain/invoker.properties index fb6308bb..dd05b71e 100644 --- a/src/it/java-compiler-plugin-toolchain/invoker.properties +++ b/src/it/java-compiler-plugin-toolchain/invoker.properties @@ -1,3 +1,3 @@ -invoker.goals = --toolchains toolchains.xml toolchains:toolchain ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.dumpToFile=out.properties +invoker.goals = --toolchains toolchains.xml toolchains:toolchain ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.internal.dumpToFile=out.properties # Due to toolchain support invoker.maven.version = 3.3.1+ \ No newline at end of file diff --git a/src/it/java-multi-module-with-scanAll-enabled/invoker.properties b/src/it/java-multi-module-with-scanAll-enabled/invoker.properties index 8913264c..d0a044f1 100644 --- a/src/it/java-multi-module-with-scanAll-enabled/invoker.properties +++ b/src/it/java-multi-module-with-scanAll-enabled/invoker.properties @@ -1 +1 @@ -invoker.goals = ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.dumpToFile=out.properties -Dsonar.maven.scanAll=true \ No newline at end of file +invoker.goals = ${project.groupId}:${project.artifactId}:${project.version}:sonar -Dsonar.scanner.internal.dumpToFile=out.properties -Dsonar.maven.scanAll=true \ No newline at end of file diff --git a/src/it/java-multi-module-with-scanAll-enabled/verify.groovy b/src/it/java-multi-module-with-scanAll-enabled/verify.groovy index 823d0118..5e8c096e 100644 --- a/src/it/java-multi-module-with-scanAll-enabled/verify.groovy +++ b/src/it/java-multi-module-with-scanAll-enabled/verify.groovy @@ -7,10 +7,11 @@ propertiesFile.withInputStream { def projectBaseDir = 'sonar.projectBaseDir' def sources = 'sonar.sources' def module1Sources = "org.codehaus.sonar:sample-project-module1.$sources" +def sep = File.separator -assert properties."$module1Sources" == properties."$projectBaseDir" + "/module1/pom.xml" +assert properties."$module1Sources" == properties."$projectBaseDir" + "${sep}module1${sep}pom.xml" def sourceDirs = properties."$sources".split(",") assert sourceDirs.length == 3 -assert properties."$sources".contains(properties."$projectBaseDir" + "/pom.xml") -assert properties."$sources".contains(properties."$projectBaseDir" + "/verify.groovy") -assert properties."$sources".contains(properties."$projectBaseDir" + "/invoker.properties") \ No newline at end of file +assert properties."$sources".contains(properties."$projectBaseDir" + "${sep}pom.xml") +assert properties."$sources".contains(properties."$projectBaseDir" + "${sep}verify.groovy") +assert properties."$sources".contains(properties."$projectBaseDir" + "${sep}invoker.properties") \ No newline at end of file diff --git a/src/it/java-multi-module/verify.groovy b/src/it/java-multi-module/verify.groovy index 312a79d4..7e1156e8 100644 --- a/src/it/java-multi-module/verify.groovy +++ b/src/it/java-multi-module/verify.groovy @@ -7,6 +7,7 @@ propertiesFile.withInputStream { def projectBaseDir = 'sonar.projectBaseDir' def sources = 'sonar.sources' def module1Sources = "org.codehaus.sonar:sample-project-module1.$sources" +def sep = File.separator -assert properties."$module1Sources" == properties."$projectBaseDir" + "/module1/pom.xml" -assert properties."$sources" == properties."$projectBaseDir" + "/pom.xml" \ No newline at end of file +assert properties."$module1Sources" == properties."$projectBaseDir" + "${sep}module1${sep}pom.xml" +assert properties."$sources" == properties."$projectBaseDir" + "${sep}pom.xml" \ No newline at end of file diff --git a/src/it/java-multivalued-sources/verify.groovy b/src/it/java-multivalued-sources/verify.groovy index cca5a429..9b06c15d 100644 --- a/src/it/java-multivalued-sources/verify.groovy +++ b/src/it/java-multivalued-sources/verify.groovy @@ -6,6 +6,7 @@ propertiesFile.withInputStream { def projectBaseDir = 'sonar.projectBaseDir' def sources = 'sonar.sources' +def sep = File.separator // testing that sources with commas in the name are escaped as double-quoted strings -assert properties."$sources".contains(properties."$projectBaseDir" + '/pom.xml') -assert properties."$sources".contains('"' + properties."$projectBaseDir" + '/src/main/my,src,0' + '"') \ No newline at end of file +assert properties."$sources".contains(properties."$projectBaseDir" + "${sep}pom.xml") +assert properties."$sources".contains('"' + properties."$projectBaseDir" + "${sep}src${sep}main${sep}my,src,0" + '"') \ No newline at end of file diff --git a/src/main/java/org/sonarsource/scanner/maven/SonarQubeMojo.java b/src/main/java/org/sonarsource/scanner/maven/SonarQubeMojo.java index 37dd7322..26dcf3e9 100644 --- a/src/main/java/org/sonarsource/scanner/maven/SonarQubeMojo.java +++ b/src/main/java/org/sonarsource/scanner/maven/SonarQubeMojo.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.stream.Stream; import org.apache.maven.execution.MavenSession; import org.apache.maven.lifecycle.LifecycleExecutor; @@ -40,15 +39,14 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.toolchain.ToolchainManager; -import org.sonarsource.scanner.api.EmbeddedScanner; -import org.sonarsource.scanner.api.ScanProperties; -import org.sonarsource.scanner.api.Utils; +import org.sonarsource.scanner.lib.EnvironmentConfig; +import org.sonarsource.scanner.lib.ScannerEngineBootstrapper; +import org.sonarsource.scanner.lib.ScannerProperties; import org.sonarsource.scanner.maven.bootstrap.MavenCompilerResolver; -import org.sonarsource.scanner.maven.bootstrap.LogHandler; import org.sonarsource.scanner.maven.bootstrap.MavenProjectConverter; import org.sonarsource.scanner.maven.bootstrap.PropertyDecryptor; import org.sonarsource.scanner.maven.bootstrap.ScannerBootstrapper; -import org.sonarsource.scanner.maven.bootstrap.ScannerFactory; +import org.sonarsource.scanner.maven.bootstrap.ScannerBootstrapperFactory; import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; /** @@ -86,7 +84,6 @@ public class SonarQubeMojo extends AbstractMojo { @Override public void execute() throws MojoExecutionException, MojoFailureException { - setLog(new TimestampLogger(getLog())); if (shouldDelayExecution()) { getLog().info("Delaying SonarQube Scanner to the end of multi-module project"); @@ -95,22 +92,24 @@ public void execute() throws MojoExecutionException, MojoFailureException { warnAboutUnspecifiedSonarPluginVersion(); - Properties envProps = Utils.loadEnvironmentProperties(System.getenv()); + Map envProps = EnvironmentConfig.load(System.getenv()); MavenCompilerResolver mavenCompilerResolver = new MavenCompilerResolver(session, lifecycleExecutor, getLog(), toolchainManager); MavenProjectConverter mavenProjectConverter = new MavenProjectConverter(getLog(), mavenCompilerResolver, envProps); - LogHandler logHandler = new LogHandler(getLog()); PropertyDecryptor propertyDecryptor = new PropertyDecryptor(getLog(), securityDispatcher); - ScannerFactory runnerFactory = new ScannerFactory(logHandler, getLog(), runtimeInformation, mojoExecution, session, envProps, propertyDecryptor); + ScannerBootstrapperFactory bootstrapperFactory = new ScannerBootstrapperFactory(getLog(), runtimeInformation, mojoExecution, session, envProps, propertyDecryptor); - if (isSkip(runnerFactory.createGlobalProperties())) { + if (isSkip(bootstrapperFactory.createGlobalProperties())) { return; } - EmbeddedScanner runner = runnerFactory.create(); - new ScannerBootstrapper(getLog(), session, runner, mavenProjectConverter, propertyDecryptor).execute(); + ScannerEngineBootstrapper bootstrapper = bootstrapperFactory.create(); + boolean success = new ScannerBootstrapper(getLog(), session, bootstrapper, mavenProjectConverter, propertyDecryptor).execute(); + if (!success) { + throw new MojoFailureException("Analysis failed"); + } } private void warnAboutUnspecifiedSonarPluginVersion() { @@ -153,6 +152,7 @@ private static boolean isVersionMissingFromSonarGoal(List goals, String /** * Should scanner be delayed? + * * @return true if goal is attached to phase and not last in a multi-module project */ private boolean shouldDelayExecution() { @@ -161,9 +161,9 @@ private boolean shouldDelayExecution() { /** * Is this execution a 'detached' goal run from the cli. e.g. mvn sonar:sonar - * + *

* See - Default executionIds for Implied Executions + * Default executionIds for Implied Executions * for explanation of command line execution id. * * @return true if this execution is from the command line @@ -198,7 +198,7 @@ private boolean isSkip(Map properties) { return true; } - if ("true".equalsIgnoreCase(properties.get(ScanProperties.SKIP))) { + if ("true".equalsIgnoreCase(properties.get(ScannerProperties.SKIP))) { getLog().info("SonarQube Scanner analysis skipped"); return true; } diff --git a/src/main/java/org/sonarsource/scanner/maven/bootstrap/LogHandler.java b/src/main/java/org/sonarsource/scanner/maven/bootstrap/LogHandler.java deleted file mode 100644 index 6ff5ed54..00000000 --- a/src/main/java/org/sonarsource/scanner/maven/bootstrap/LogHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SonarQube Scanner for Maven - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonarsource.scanner.maven.bootstrap; - -import org.apache.maven.plugin.logging.Log; -import org.sonarsource.scanner.api.LogOutput; - -public class LogHandler implements LogOutput { - private Log mavenLog; - - public LogHandler(Log mavenLog) { - this.mavenLog = mavenLog; - } - - @Override - public void log(String log, Level level) { - switch (level) { - case TRACE: - case DEBUG: - mavenLog.debug(log); - break; - case WARN: - mavenLog.warn(log); - break; - case ERROR: - mavenLog.error(log); - break; - case INFO: - default: - mavenLog.info(log); - break; - } - } -} diff --git a/src/main/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverter.java b/src/main/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverter.java index 532e0055..526c3f7c 100644 --- a/src/main/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverter.java +++ b/src/main/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverter.java @@ -48,8 +48,8 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; -import org.sonarsource.scanner.api.ScanProperties; -import org.sonarsource.scanner.api.ScannerProperties; +import org.sonarsource.scanner.lib.AnalysisProperties; +import org.sonarsource.scanner.lib.ScannerProperties; import org.sonarsource.scanner.maven.bootstrap.MavenCompilerResolver.MavenCompilerConfiguration; public class MavenProjectConverter { @@ -121,7 +121,7 @@ public class MavenProjectConverter { @Nullable private String specifiedProjectKey; - private final Properties envProperties; + private final Map envProperties; private final MavenCompilerResolver mavenCompilerResolver; @@ -136,7 +136,7 @@ public class MavenProjectConverter { */ private MavenProject root; - public MavenProjectConverter(Log log, MavenCompilerResolver mavenCompilerResolver, Properties envProperties) { + public MavenProjectConverter(Log log, MavenCompilerResolver mavenCompilerResolver, Map envProperties) { this.log = log; this.mavenCompilerResolver = mavenCompilerResolver; this.envProperties = envProperties; @@ -154,8 +154,8 @@ public boolean isTestDirsOverridden() { return testDirsIsOverridden; } - public Properties getEnvProperties() { - return new Properties(envProperties); + public Map getEnvProperties() { + return new HashMap<>(envProperties); } Map configure(List mavenProjects, MavenProject root, Properties userProperties) throws MojoExecutionException { @@ -167,9 +167,9 @@ Map configure(List mavenProjects, MavenProject roo this.root = root; configureModules(mavenProjects, propsByModule); Map props = new HashMap<>(); - props.put(ScanProperties.PROJECT_KEY, getArtifactKey(root)); + props.put(AnalysisProperties.PROJECT_KEY, getArtifactKey(root)); Path topLevelDir = rebuildModuleHierarchy(props, propsByModule, root, ""); - props.put(ScanProperties.PROJECT_BASEDIR, topLevelDir.toString()); + props.put(AnalysisProperties.PROJECT_BASEDIR, topLevelDir.toString()); if (!propsByModule.isEmpty()) { throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE + " \"" + propsByModule.keySet().iterator().next().getName() + "\" is orphan"); @@ -269,11 +269,11 @@ private static MavenProject findMavenProject(final File modulePath, Collection computeSonarQubeProperties(MavenProject pom) throws MojoExecutionException { Map props = new HashMap<>(); defineModuleKey(pom, props); - props.put(ScanProperties.PROJECT_VERSION, pom.getVersion()); - props.put(ScanProperties.PROJECT_NAME, pom.getName()); + props.put(AnalysisProperties.PROJECT_VERSION, pom.getVersion()); + props.put(AnalysisProperties.PROJECT_NAME, pom.getName()); String description = pom.getDescription(); if (description != null) { - props.put(ScanProperties.PROJECT_DESCRIPTION, description); + props.put(AnalysisProperties.PROJECT_DESCRIPTION, description); } populateJavaAnalyzerProperties(pom, props); @@ -286,9 +286,9 @@ private Map computeSonarQubeProperties(MavenProject pom) throws @CheckForNull private static String specifiedProjectKey(Properties userProperties, MavenProject root) { - String projectKey = userProperties.getProperty(ScanProperties.PROJECT_KEY); + String projectKey = userProperties.getProperty(AnalysisProperties.PROJECT_KEY); if (projectKey == null) { - projectKey = root.getModel().getProperties().getProperty(ScanProperties.PROJECT_KEY); + projectKey = root.getModel().getProperties().getProperty(AnalysisProperties.PROJECT_KEY); } if (projectKey == null || projectKey.isEmpty()) { return null; @@ -302,7 +302,7 @@ private static String specifiedProjectKey(Properties userProperties, MavenProjec * Otherwise, we use the artifact key ({@link MavenProjectConverter#getArtifactKey(MavenProject)}. * * @param project The maven submodule for which a key must be generated - * @param props The existing properties where the module key will be added + * @param props The existing properties where the module key will be added * @return The generated module key */ private String defineModuleKey(MavenProject project, Map props) { @@ -324,7 +324,7 @@ private static void guessEncoding(MavenProject pom, Map props) { // See http://jira.codehaus.org/browse/SONAR-2151 String encoding = MavenUtils.getSourceEncoding(pom); if (encoding != null) { - props.put(ScanProperties.PROJECT_SOURCE_ENCODING, encoding); + props.put(AnalysisProperties.PROJECT_SOURCE_ENCODING, encoding); } } @@ -401,7 +401,7 @@ private static void setPropertyIfNotAlreadyExists(Map props, Str private void synchronizeFileSystemAndOtherProps(MavenProject pom, Map props) throws MojoExecutionException { - props.put(ScanProperties.PROJECT_BASEDIR, pom.getBasedir().getAbsolutePath()); + props.put(AnalysisProperties.PROJECT_BASEDIR, pom.getBasedir().getAbsolutePath()); File buildDir = getBuildDir(pom); if (buildDir != null) { props.put(PROPERTY_PROJECT_BUILDDIR, buildDir.getAbsolutePath()); @@ -417,24 +417,24 @@ private void synchronizeFileSystemAndOtherProps(MavenProject pom, Map mainDirs = mainSources(pom); - props.put(ScanProperties.PROJECT_SOURCE_DIRS, MavenUtils.joinAsCsv(toPaths(mainDirs))); + props.put(AnalysisProperties.PROJECT_SOURCE_DIRS, MavenUtils.joinAsCsv(toPaths(mainDirs))); List testDirs = testSources(pom); if (!testDirs.isEmpty()) { - props.put(ScanProperties.PROJECT_TEST_DIRS, MavenUtils.joinAsCsv(toPaths(testDirs))); + props.put(AnalysisProperties.PROJECT_TEST_DIRS, MavenUtils.joinAsCsv(toPaths(testDirs))); } else { - props.remove(ScanProperties.PROJECT_TEST_DIRS); + props.remove(AnalysisProperties.PROJECT_TEST_DIRS); } } @@ -558,7 +558,7 @@ private List mainSources(MavenProject pom) throws MojoExecutionException { .forEach(sources::add); } - return sourcePaths(pom, ScanProperties.PROJECT_SOURCE_DIRS, sources); + return sourcePaths(pom, AnalysisProperties.PROJECT_SOURCE_DIRS, sources); } /** @@ -576,7 +576,7 @@ static Collection getPathsToPoms(MavenProject project) { } private List testSources(MavenProject pom) throws MojoExecutionException { - return sourcePaths(pom, ScanProperties.PROJECT_TEST_DIRS, pom.getTestCompileSourceRoots()); + return sourcePaths(pom, AnalysisProperties.PROJECT_TEST_DIRS, pom.getTestCompileSourceRoots()); } private List sourcePaths(MavenProject pom, String propertyKey, Collection mavenPaths) throws MojoExecutionException { @@ -590,8 +590,8 @@ private List sourcePaths(MavenProject pom, String propertyKey, Collection< List paths = Arrays.asList(StringUtils.split(prop, ",")); filesOrDirs = resolvePaths(paths, pom.getBasedir()); userDefined = true; - sourceDirsIsOverridden |= propertyKey.equals(ScanProperties.PROJECT_SOURCE_DIRS); - testDirsIsOverridden |= propertyKey.equals(ScanProperties.PROJECT_TEST_DIRS); + sourceDirsIsOverridden |= propertyKey.equals(AnalysisProperties.PROJECT_SOURCE_DIRS); + testDirsIsOverridden |= propertyKey.equals(AnalysisProperties.PROJECT_TEST_DIRS); } else { removeTarget(pom, mavenPaths); filesOrDirs = resolvePaths(mavenPaths, pom.getBasedir()); @@ -611,8 +611,8 @@ private String getPropertyByKey(String propertyKey, MavenProject pom) { return getPropertyByKey(propertyKey, pom, userProperties, envProperties); } - public static String getPropertyByKey(String propertyKey, MavenProject pom, Properties userProperties, Properties envProperties) { - String prop = StringUtils.defaultIfEmpty(userProperties.getProperty(propertyKey), envProperties.getProperty(propertyKey)); + public static String getPropertyByKey(String propertyKey, MavenProject pom, Properties userProperties, Map envProperties) { + String prop = StringUtils.defaultIfEmpty(userProperties.getProperty(propertyKey), envProperties.get(propertyKey)); prop = StringUtils.defaultIfEmpty(prop, pom.getProperties().getProperty(propertyKey)); return prop; } diff --git a/src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapper.java b/src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapper.java index 75ccf964..d71dce36 100644 --- a/src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapper.java +++ b/src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapper.java @@ -27,7 +27,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.regex.Pattern; @@ -37,11 +36,9 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; -import org.sonarsource.scanner.api.EmbeddedScanner; -import org.sonarsource.scanner.api.ScanProperties; -import org.sonarsource.scanner.api.ScannerProperties; - -import static org.sonarsource.scanner.maven.bootstrap.MavenProjectConverter.getPropertyByKey; +import org.sonarsource.scanner.lib.AnalysisProperties; +import org.sonarsource.scanner.lib.ScannerEngineBootstrapper; +import org.sonarsource.scanner.lib.ScannerEngineFacade; /** * Configure properties and bootstrap using SonarQube scanner API @@ -49,62 +46,41 @@ public class ScannerBootstrapper { static final String UNSUPPORTED_BELOW_SONARQUBE_56_MESSAGE = "With SonarQube server prior to 5.6, use sonar-maven-plugin <= 3.3"; - private static final String SONARCLOUD_HOST_URL = "https://sonarcloud.io"; private static final Pattern REPORT_PROPERTY_PATTERN = Pattern.compile("^sonar\\..*[rR]eportPaths?$"); private final Log log; private final MavenSession session; - private final EmbeddedScanner scanner; + private final ScannerEngineBootstrapper bootstrapper; private final MavenProjectConverter mavenProjectConverter; private String serverVersion; - private PropertyDecryptor propertyDecryptor; + private final PropertyDecryptor propertyDecryptor; - public ScannerBootstrapper(Log log, MavenSession session, EmbeddedScanner scanner, MavenProjectConverter mavenProjectConverter, PropertyDecryptor propertyDecryptor) { + public ScannerBootstrapper(Log log, MavenSession session, ScannerEngineBootstrapper bootstrapper, MavenProjectConverter mavenProjectConverter, + PropertyDecryptor propertyDecryptor) { this.log = log; this.session = session; - this.scanner = scanner; + this.bootstrapper = bootstrapper; this.mavenProjectConverter = mavenProjectConverter; this.propertyDecryptor = propertyDecryptor; } - public void execute() throws MojoExecutionException { - try { - logEnvironmentInformation(); - scanner.start(); - serverVersion = scanner.serverVersion(); + public boolean execute() throws MojoExecutionException { + logEnvironmentInformation(); + try (ScannerEngineFacade engineFacade = bootstrapper.bootstrap()) { - if (isSonarCloudUsed()) { + if (engineFacade.isSonarCloud()) { log.info("Communicating with SonarCloud"); } else { - if (serverVersion != null) { - log.info("Communicating with SonarQube Server " + serverVersion); - } + serverVersion = engineFacade.getServerVersion(); + log.info("Communicating with SonarQube Server " + serverVersion); checkSQVersion(); } - - if (log.isDebugEnabled()) { - scanner.setGlobalProperty("sonar.verbose", "true"); - } - - scanner.execute(collectProperties()); + return engineFacade.analyze(collectProperties()); } catch (Exception e) { throw new MojoExecutionException(e.getMessage(), e); } } - // TODO remove this workaround when discovering if the sevrer is SC or SQ is available through the API - private boolean isSonarCloudUsed() { - return session.getProjects().stream() - // We can use EnvProperties from MavenProjectConverter as they are initialized at construction time, - // but we can't use UserProperties from the MavenProjectConverter as they are only initialized - // in the "collectProperties" method. - .map(project -> - getPropertyByKey(ScannerProperties.HOST_URL, project, session.getUserProperties(), mavenProjectConverter.getEnvProperties()) - ) - .filter(Objects::nonNull) - .anyMatch(hostUrl -> hostUrl.startsWith(SONARCLOUD_HOST_URL)); - } - @VisibleForTesting Map collectProperties() throws MojoExecutionException { @@ -127,9 +103,9 @@ Map collectProperties() if (shouldCollectAllSources(userProperties)) { log.info("Parameter " + MavenScannerProperties.PROJECT_SCAN_ALL_SOURCES + " is enabled. The scanner will attempt to collect additional sources."); if (mavenProjectConverter.isSourceDirsOverridden()) { - log.warn(notCollectingAdditionalSourcesBecauseOf(ScanProperties.PROJECT_SOURCE_DIRS)); + log.warn(notCollectingAdditionalSourcesBecauseOf(AnalysisProperties.PROJECT_SOURCE_DIRS)); } else if (mavenProjectConverter.isTestDirsOverridden()) { - log.warn(notCollectingAdditionalSourcesBecauseOf(ScanProperties.PROJECT_TEST_DIRS)); + log.warn(notCollectingAdditionalSourcesBecauseOf(AnalysisProperties.PROJECT_TEST_DIRS)); } else { boolean shouldCollectJavaAndKotlinSources = isUserDefinedJavaBinaries(userProperties); collectAllSources(props, shouldCollectJavaAndKotlinSources); @@ -162,11 +138,11 @@ private static Set excludedReportFiles(Map props) { @VisibleForTesting void collectAllSources(Map props, boolean shouldCollectJavaAndKotlinSources) { - String projectBasedir = props.get(ScanProperties.PROJECT_BASEDIR); + String projectBasedir = props.get(AnalysisProperties.PROJECT_BASEDIR); // Exclude the files and folders covered by sonar.sources and sonar.tests (and sonar.exclusions) as computed by the MavenConverter // Combine all the sonar.sources at the top-level and by module List coveredSources = props.entrySet().stream() - .filter(k -> k.getKey().endsWith(ScanProperties.PROJECT_SOURCE_DIRS) || k.getKey().endsWith(ScanProperties.PROJECT_TEST_DIRS)) + .filter(k -> k.getKey().endsWith(AnalysisProperties.PROJECT_SOURCE_DIRS) || k.getKey().endsWith(AnalysisProperties.PROJECT_TEST_DIRS)) .map(Map.Entry::getValue) .filter(value -> !value.isEmpty()) .flatMap(value -> MavenUtils.splitAsCsv(value).stream()) @@ -183,9 +159,9 @@ void collectAllSources(Map props, boolean shouldCollectJavaAndKo .map(file -> file.toAbsolutePath().toString()) .collect(Collectors.toList()); List mergedSources = new ArrayList<>(); - mergedSources.addAll(MavenUtils.splitAsCsv(props.get(ScanProperties.PROJECT_SOURCE_DIRS))); + mergedSources.addAll(MavenUtils.splitAsCsv(props.get(AnalysisProperties.PROJECT_SOURCE_DIRS))); mergedSources.addAll(collectedSources); - props.put(ScanProperties.PROJECT_SOURCE_DIRS, MavenUtils.joinAsCsv(mergedSources)); + props.put(AnalysisProperties.PROJECT_SOURCE_DIRS, MavenUtils.joinAsCsv(mergedSources)); } catch (IOException e) { log.warn(e); } diff --git a/src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerFactory.java b/src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperFactory.java similarity index 82% rename from src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerFactory.java rename to src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperFactory.java index 480af008..e4563bc8 100644 --- a/src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerFactory.java +++ b/src/main/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperFactory.java @@ -24,7 +24,6 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; -import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; import org.apache.maven.execution.MavenSession; @@ -32,51 +31,48 @@ import org.apache.maven.plugin.logging.Log; import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.settings.Proxy; -import org.sonarsource.scanner.api.EmbeddedScanner; -import org.sonarsource.scanner.api.LogOutput; +import org.sonarsource.scanner.lib.ScannerEngineBootstrapper; -public class ScannerFactory { +public class ScannerBootstrapperFactory { private static final String UNKNOWN_PROXY_PROTOCOL_MESSAGE = "Setting proxy properties:" + " one or multiple protocols of the active proxy (id: %s) are not supported (protocols: %s)."; - private final LogOutput logOutput; private final RuntimeInformation runtimeInformation; private final MavenSession session; - private final boolean debugEnabled; private final PropertyDecryptor propertyDecryptor; - private final Properties envProps; + private final Map envProps; private final Log log; private final MojoExecution mojoExecution; - public ScannerFactory(LogOutput logOutput, Log log, RuntimeInformation runtimeInformation, MojoExecution mojoExecution, MavenSession session, - Properties envProps, PropertyDecryptor propertyDecryptor) { - this.logOutput = logOutput; + public ScannerBootstrapperFactory(Log log, RuntimeInformation runtimeInformation, MojoExecution mojoExecution, MavenSession session, + Map envProps, PropertyDecryptor propertyDecryptor) { this.log = log; this.runtimeInformation = runtimeInformation; this.mojoExecution = mojoExecution; this.session = session; - this.debugEnabled = log.isDebugEnabled(); this.envProps = envProps; this.propertyDecryptor = propertyDecryptor; } - public EmbeddedScanner create() { + public ScannerEngineBootstrapper create() { setProxySystemProperties(); - EmbeddedScanner scanner = EmbeddedScanner.create("ScannerMaven", mojoExecution.getVersion() + "/" + runtimeInformation.getMavenVersion(), logOutput); - - scanner.addGlobalProperties(createGlobalProperties()); - - if (debugEnabled) { - scanner.setGlobalProperty("sonar.verbose", "true"); + ScannerEngineBootstrapper scanner = createScannerEngineBootstrapper("ScannerMaven", mojoExecution.getVersion() + "/" + runtimeInformation.getMavenVersion()); + scanner.addBootstrapProperties(createGlobalProperties()); + if (log.isDebugEnabled()) { + scanner.setBootstrapProperty("sonar.verbose", "true"); } return scanner; } + ScannerEngineBootstrapper createScannerEngineBootstrapper(String app, String version) { + return ScannerEngineBootstrapper.create(app, version); + } + public Map createGlobalProperties() { Map p = new HashMap<>(); MavenUtils.putAll(session.getCurrentProject().getProperties(), p); - MavenUtils.putAll(envProps, p); + p.putAll(envProps); MavenUtils.putAll(session.getSystemProperties(), p); MavenUtils.putAll(session.getUserProperties(), p); p.putAll(propertyDecryptor.decryptProperties(p)); diff --git a/src/test/java/org/sonarsource/scanner/maven/SonarQubeMojoTest.java b/src/test/java/org/sonarsource/scanner/maven/SonarQubeMojoTest.java index 997e2322..b3263603 100644 --- a/src/test/java/org/sonarsource/scanner/maven/SonarQubeMojoTest.java +++ b/src/test/java/org/sonarsource/scanner/maven/SonarQubeMojoTest.java @@ -45,7 +45,6 @@ import org.assertj.core.data.MapEntry; import org.junit.Rule; import org.junit.Test; -import org.sonarsource.scanner.maven.TimestampLoggerTest.TestLog; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; @@ -321,10 +320,10 @@ private File executeProject(String projectName, String goal, String... propertie private Plugin createSonarPluginFrom(PluginDescriptor pluginDescriptor, String goal, MavenProject project) { String version = null; Pattern versionPattern = Pattern.compile("(?:" + - "sonar|" + - "org\\.codehaus\\.mojo:sonar-maven-plugin|" + - "org\\.sonarsource\\.scanner\\.maven:sonar-maven-plugin" + - "):([^:]+):sonar"); + "sonar|" + + "org\\.codehaus\\.mojo:sonar-maven-plugin|" + + "org\\.sonarsource\\.scanner\\.maven:sonar-maven-plugin" + + "):([^:]+):sonar"); Matcher matcher = versionPattern.matcher(goal); if (matcher.matches()) { version = matcher.group(1); @@ -339,7 +338,7 @@ private Plugin createSonarPluginFrom(PluginDescriptor pluginDescriptor, String g String pluginGroupId = plugin.getGroupId(); if ((pluginGroupId == null || pluginGroupId.equals(pluginDescriptor.getGroupId())) && pluginDescriptor.getArtifactId().equals(plugin.getArtifactId()) && - plugin.getVersion() != null){ + plugin.getVersion() != null) { version = plugin.getVersion(); break; } diff --git a/src/main/java/org/sonarsource/scanner/maven/TimestampLogger.java b/src/test/java/org/sonarsource/scanner/maven/TestLog.java similarity index 62% rename from src/main/java/org/sonarsource/scanner/maven/TimestampLogger.java rename to src/test/java/org/sonarsource/scanner/maven/TestLog.java index e76bdee1..5a98d788 100644 --- a/src/main/java/org/sonarsource/scanner/maven/TimestampLogger.java +++ b/src/test/java/org/sonarsource/scanner/maven/TestLog.java @@ -19,102 +19,106 @@ */ package org.sonarsource.scanner.maven; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; - +import java.util.ArrayList; +import java.util.List; import org.apache.maven.plugin.logging.Log; -public class TimestampLogger implements Log { - private final DateTimeFormatter timeFormatter; - private final Log log; +public class TestLog implements Log { + public void setLogLevel(LogLevel logLevel) { + this.logLevel = logLevel; + } - public TimestampLogger(Log log) { - this.log = log; - this.timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS "); + public enum LogLevel { + DEBUG, + INFO, + WARN, + ERROR, } - @Override - public void debug(CharSequence content) { - log.debug(getCurrentTimeStamp() + content); + private LogLevel logLevel; + public final List logs = new ArrayList<>(); + + public TestLog(LogLevel logLevel) { + this.logLevel = logLevel; } @Override - public void debug(CharSequence content, Throwable error) { - log.debug(getCurrentTimeStamp() + content, error); + public boolean isDebugEnabled() { + return logLevel == LogLevel.DEBUG; } @Override - public void info(CharSequence content) { - log.info(getCurrentTimeStamp() + content); + public void debug(CharSequence content) { + logs.add("[DEBUG] " + content); } @Override - public void info(CharSequence content, Throwable error) { - log.info(getCurrentTimeStamp() + content, error); + public void debug(CharSequence content, Throwable error) { + debug(content); } @Override - public void warn(CharSequence content) { - log.warn(getCurrentTimeStamp() + content); + public void debug(Throwable error) { + debug(error.getMessage()); } @Override - public void warn(CharSequence content, Throwable error) { - log.warn(getCurrentTimeStamp() + content, error); + public boolean isInfoEnabled() { + return logLevel == LogLevel.INFO; } @Override - public void error(CharSequence content) { - log.error(getCurrentTimeStamp() + content); + public void info(CharSequence content) { + logs.add("[INFO] " + content); } @Override - public void error(CharSequence content, Throwable error) { - log.error(getCurrentTimeStamp() + content, error); + public void info(CharSequence content, Throwable error) { + info(content); } - private String getCurrentTimeStamp() { - LocalTime currentTime = LocalTime.now(); - return currentTime.format(timeFormatter); + @Override + public void info(Throwable error) { + info(error.getMessage()); } @Override - public boolean isDebugEnabled() { - return log.isDebugEnabled(); + public boolean isWarnEnabled() { + return logLevel == LogLevel.WARN; } @Override - public void debug(Throwable error) { - log.debug(getCurrentTimeStamp(), error); + public void warn(CharSequence content) { + logs.add("[WARN] " + content); } @Override - public boolean isInfoEnabled() { - return log.isInfoEnabled(); + public void warn(CharSequence content, Throwable error) { + warn(content); } @Override - public void info(Throwable error) { - log.info(getCurrentTimeStamp(), error); + public void warn(Throwable error) { + warn(error.getMessage()); } @Override - public boolean isWarnEnabled() { - return log.isWarnEnabled(); + public boolean isErrorEnabled() { + return logLevel == LogLevel.ERROR; } @Override - public void warn(Throwable error) { - log.warn(getCurrentTimeStamp(), error); + public void error(CharSequence content) { + logs.add("[ERROR] " + content); } @Override - public boolean isErrorEnabled() { - return log.isErrorEnabled(); + public void error(CharSequence content, Throwable error) { + error(content); } @Override public void error(Throwable error) { - log.error(getCurrentTimeStamp(), error); + error(error.getMessage()); } } diff --git a/src/test/java/org/sonarsource/scanner/maven/TimestampLoggerTest.java b/src/test/java/org/sonarsource/scanner/maven/TimestampLoggerTest.java deleted file mode 100644 index 53f91911..00000000 --- a/src/test/java/org/sonarsource/scanner/maven/TimestampLoggerTest.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * SonarQube Scanner for Maven - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonarsource.scanner.maven; - -import java.time.LocalTime; -import java.util.ArrayList; -import java.util.List; -import org.apache.maven.plugin.logging.Log; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; - -import static org.assertj.core.api.Assertions.assertThat; - -class TimestampLoggerTest { - - @Test - void all_messages_are_timestamped() { - TestLog mavenLog = new TestLog(TestLog.LogLevel.DEBUG); - TimestampLogger logger = new TimestampLogger(mavenLog); - - LocalTime expectedCurrentTime = LocalTime.of(10, 10, 30); - - try (MockedStatic localTimeMockedStatic = Mockito.mockStatic(LocalTime.class)) { - localTimeMockedStatic.when(LocalTime::now).thenReturn(expectedCurrentTime); - - logger.debug("My debug message"); - logger.debug("My debug message", new IllegalArgumentException()); - logger.debug(new IllegalArgumentException()); - logger.info("My info message"); - logger.info("My info message", new IllegalArgumentException()); - logger.info(new IllegalArgumentException()); - logger.warn("My warn message"); - logger.warn("My warn message", new IllegalArgumentException()); - logger.warn(new IllegalArgumentException()); - logger.error("My error message"); - logger.error("My error message", new IllegalArgumentException()); - logger.error(new IllegalArgumentException()); - } - - - assertThat(mavenLog.logs).containsOnly( - "[DEBUG] 10:10:30.000 My debug message", - "[DEBUG] 10:10:30.000 My debug message", - "[DEBUG] 10:10:30.000 ", - "[INFO] 10:10:30.000 My info message", - "[INFO] 10:10:30.000 My info message", - "[INFO] 10:10:30.000 ", - "[WARN] 10:10:30.000 My warn message", - "[WARN] 10:10:30.000 My warn message", - "[WARN] 10:10:30.000 ", - "[ERROR] 10:10:30.000 My error message", - "[ERROR] 10:10:30.000 My error message", - "[ERROR] 10:10:30.000 " - ); - } - - @Test - void log_level_matches_underlying_maven_log_level() { - TestLog debugLevelLog = new TestLog(TestLog.LogLevel.DEBUG); - TestLog infoLevelLog = new TestLog(TestLog.LogLevel.INFO); - TestLog warnLevelLog = new TestLog(TestLog.LogLevel.WARN); - TestLog errorLevelLog = new TestLog(TestLog.LogLevel.ERROR); - - assertThat(new TimestampLogger(debugLevelLog).isDebugEnabled()).isTrue(); - assertThat(new TimestampLogger(debugLevelLog).isInfoEnabled()).isFalse(); - assertThat(new TimestampLogger(debugLevelLog).isWarnEnabled()).isFalse(); - assertThat(new TimestampLogger(debugLevelLog).isErrorEnabled()).isFalse(); - - assertThat(new TimestampLogger(infoLevelLog).isDebugEnabled()).isFalse(); - assertThat(new TimestampLogger(infoLevelLog).isInfoEnabled()).isTrue(); - assertThat(new TimestampLogger(infoLevelLog).isWarnEnabled()).isFalse(); - assertThat(new TimestampLogger(infoLevelLog).isErrorEnabled()).isFalse(); - - assertThat(new TimestampLogger(warnLevelLog).isDebugEnabled()).isFalse(); - assertThat(new TimestampLogger(warnLevelLog).isInfoEnabled()).isFalse(); - assertThat(new TimestampLogger(warnLevelLog).isWarnEnabled()).isTrue(); - assertThat(new TimestampLogger(warnLevelLog).isErrorEnabled()).isFalse(); - - assertThat(new TimestampLogger(errorLevelLog).isDebugEnabled()).isFalse(); - assertThat(new TimestampLogger(errorLevelLog).isInfoEnabled()).isFalse(); - assertThat(new TimestampLogger(errorLevelLog).isWarnEnabled()).isFalse(); - assertThat(new TimestampLogger(errorLevelLog).isErrorEnabled()).isTrue(); - } - - public static class TestLog implements Log { - public enum LogLevel { - DEBUG, - INFO, - WARN, - ERROR, - } - - public LogLevel logLevel; - public final List logs = new ArrayList<>(); - - public TestLog(LogLevel logLevel) { - this.logLevel = logLevel; - } - - public void setLogLevel(LogLevel logLevel) { - this.logLevel = logLevel; - } - - @Override - public boolean isDebugEnabled() { - return logLevel == LogLevel.DEBUG; - } - - @Override - public void debug(CharSequence content) { - logs.add("[DEBUG] " + content); - } - - @Override - public void debug(CharSequence content, Throwable error) { - debug(content); - } - - @Override - public void debug(Throwable error) { - debug(error.getMessage()); - } - - @Override - public boolean isInfoEnabled() { - return logLevel == LogLevel.INFO; - } - - @Override - public void info(CharSequence content) { - logs.add("[INFO] " + content); - } - - @Override - public void info(CharSequence content, Throwable error) { - info(content); - } - - @Override - public void info(Throwable error) { - info(error.getMessage()); - } - - @Override - public boolean isWarnEnabled() { - return logLevel == LogLevel.WARN; - } - - @Override - public void warn(CharSequence content) { - logs.add("[WARN] " + content); - } - - @Override - public void warn(CharSequence content, Throwable error) { - warn(content); - } - - @Override - public void warn(Throwable error) { - warn(error.getMessage()); - } - - @Override - public boolean isErrorEnabled() { - return logLevel == LogLevel.ERROR; - } - - @Override - public void error(CharSequence content) { - logs.add("[ERROR] " + content); - } - - @Override - public void error(CharSequence content, Throwable error) { - error(content); - } - - @Override - public void error(Throwable error) { - error(error.getMessage()); - } - } -} diff --git a/src/test/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverterTest.java b/src/test/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverterTest.java index 4804d97a..25758e0f 100644 --- a/src/test/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverterTest.java +++ b/src/test/java/org/sonarsource/scanner/maven/bootstrap/MavenProjectConverterTest.java @@ -26,6 +26,7 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.Properties; @@ -35,7 +36,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.sonarsource.scanner.api.ScanProperties; +import org.sonarsource.scanner.lib.AnalysisProperties; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertThrows; @@ -51,7 +52,7 @@ class MavenProjectConverterTest { private Log log; - private Properties env; + private final Map env = new HashMap<>(); private MavenProjectConverter projectConverter; @@ -60,14 +61,13 @@ public void prepare() { log = mock(Log.class); MavenCompilerResolver mavenCompilerResolver = mock(MavenCompilerResolver.class); when(mavenCompilerResolver.extractConfiguration(any())).thenReturn(Optional.empty()); - env = new Properties(); projectConverter = new MavenProjectConverter(log, mavenCompilerResolver, env); } @Test void convertSingleModuleProject() throws Exception { MavenProject project = createProject(new Properties(), "jar"); - + assertThat(projectConverter.getEnvProperties()).isEmpty(); Map props = projectConverter.configure(Collections.singletonList(project), project, new Properties()); assertThat(props) @@ -110,7 +110,9 @@ void shouldIncludePomIfRequested() throws Exception { @Test void shouldUseEnvironment() throws Exception { env.put("sonar.projectKey", "com.foo:anotherProject"); - MavenProject project = createProject(new Properties(), "jar"); + var projectProps = new Properties(); + projectProps.put("project.build.sourceEncoding", "UTF-8"); + MavenProject project = createProject(projectProps, "jar"); Map props = projectConverter.configure(Collections.singletonList(project), project, new Properties()); assertThat(props).containsEntry("sonar.projectKey", "com.foo:anotherProject") @@ -221,14 +223,14 @@ void convertMultiModuleProject() throws Exception { Properties userProperties = new Properties(); String userProjectKey = "user-project-key"; - userProperties.put(ScanProperties.PROJECT_KEY, userProjectKey); + userProperties.put(AnalysisProperties.PROJECT_KEY, userProjectKey); Map propsWithUserProjectKey = projectConverter.configure(Arrays.asList(module12, module11, module1, module2, root), root, userProperties); assertThat(propsWithUserProjectKey).containsEntry("sonar.projectKey", userProjectKey); String customProjectKey = "custom-project-key"; - root.getModel().getProperties().setProperty(ScanProperties.PROJECT_KEY, customProjectKey); + root.getModel().getProperties().setProperty(AnalysisProperties.PROJECT_KEY, customProjectKey); Map propsWithCustomProjectKey = projectConverter.configure(Arrays.asList(module12, module11, module1, module2, root), root, new Properties()); @@ -640,7 +642,7 @@ void two_modules_in_same_folder() throws Exception { @Test void submodules_are_not_assigned_user_provided_project_key_from_parent() throws MojoExecutionException, IOException { Properties rootPomProperties = new Properties(); - rootPomProperties.put(ScanProperties.PROJECT_KEY, "the_greatest_project_key_there_ever_was"); + rootPomProperties.put(AnalysisProperties.PROJECT_KEY, "the_greatest_project_key_there_ever_was"); File baseDir = temp.toFile(); baseDir.mkdirs(); MavenProject root = createProject(rootPomProperties, "pom"); @@ -662,11 +664,11 @@ void submodules_are_not_assigned_user_provided_project_key_from_parent() throws new Properties() ); - assertThat(properties.get(ScanProperties.PROJECT_KEY)) + assertThat(properties.get(AnalysisProperties.PROJECT_KEY)) .isNotNull() .isEqualTo("the_greatest_project_key_there_ever_was"); String keyPrefixForModule1 = module1.getGroupId() + ":" + module1.getArtifactId() + "."; - assertThat(properties).doesNotContainKey(keyPrefixForModule1 + ScanProperties.PROJECT_KEY); + assertThat(properties).doesNotContainKey(keyPrefixForModule1 + AnalysisProperties.PROJECT_KEY); } @Test diff --git a/src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerFactoryTest.java b/src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperFactoryTest.java similarity index 66% rename from src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerFactoryTest.java rename to src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperFactoryTest.java index d7508557..6a6f7c3d 100644 --- a/src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerFactoryTest.java +++ b/src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperFactoryTest.java @@ -20,6 +20,8 @@ package org.sonarsource.scanner.maven.bootstrap; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; import org.apache.maven.execution.MavenSession; import org.apache.maven.monitor.logging.DefaultLog; @@ -33,38 +35,37 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mockito; -import org.sonarsource.scanner.api.EmbeddedScanner; -import org.sonarsource.scanner.api.LogOutput; +import org.sonarsource.scanner.lib.ScannerEngineBootstrapper; import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -class ScannerFactoryTest { - private LogOutput logOutput; - private RuntimeInformation runtimeInformation; - private MojoExecution mojoExecution; - private MavenSession mavenSession; - private MavenProject rootProject; - private PropertyDecryptor propertyDecryptor; - private Properties envProps; +class ScannerBootstrapperFactoryTest { + private final RuntimeInformation runtimeInformation = mock(RuntimeInformation.class, Mockito.RETURNS_DEEP_STUBS); + private final MojoExecution mojoExecution = mock(MojoExecution.class); + private final MavenSession mavenSession = mock(MavenSession.class); + private final MavenProject rootProject = mock(MavenProject.class); + private final PropertyDecryptor propertyDecryptor = new PropertyDecryptor(mock(Log.class), mock(SecDispatcher.class)); + private final Map envProps = new HashMap<>(); + + private final Log log = mock(Log.class); + private final ScannerBootstrapperFactory underTest = spy(new ScannerBootstrapperFactory(log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor)); + private final ScannerEngineBootstrapper mockBootstrapper = mock(ScannerEngineBootstrapper.class); private Proxy httpsProxy; @BeforeEach public void setUp() { - logOutput = mock(LogOutput.class); - runtimeInformation = mock(RuntimeInformation.class, Mockito.RETURNS_DEEP_STUBS); - mavenSession = mock(MavenSession.class); - rootProject = mock(MavenProject.class); - mojoExecution = mock(MojoExecution.class); - envProps = new Properties(); Properties system = new Properties(); system.put("system", "value"); @@ -80,7 +81,7 @@ public void setUp() { when(mavenSession.getSettings()).thenReturn(new Settings()); when(rootProject.getProperties()).thenReturn(root); when(mavenSession.getCurrentProject()).thenReturn(rootProject); - propertyDecryptor = new PropertyDecryptor(mock(Log.class), mock(SecDispatcher.class)); + when(underTest.createScannerEngineBootstrapper(anyString(), anyString())).thenReturn(mockBootstrapper); // Set up default proxy httpsProxy = new Proxy(); @@ -115,9 +116,7 @@ void http_proxy_properties_are_derived_from_maven_settings() { settings.setProxies(Collections.singletonList(proxy)); when(mavenSession.getSettings()).thenReturn(settings); - Log log = mock(Log.class); - ScannerFactory factory = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - factory.create(); + underTest.create(); assertThat(System.getProperty("http.proxyHost")).isEqualTo("myhost"); assertThat(System.getProperty("https.proxyHost")).isNull(); } @@ -128,9 +127,7 @@ void https_proxy_properties_are_derived_from_maven_settings() { settings.setProxies(Collections.singletonList(httpsProxy)); when(mavenSession.getSettings()).thenReturn(settings); - Log log = mock(Log.class); - ScannerFactory factory = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - factory.create(); + underTest.create(); assertThat(System.getProperty("https.proxyHost")).isEqualTo("myhost"); assertThat(System.getProperty("https.proxyPort")).isEqualTo("443"); assertThat(System.getProperty("http.proxyUser")).isEqualTo("toto"); @@ -150,9 +147,7 @@ void http_and_https_proxy_properties_are_derived_from_maven_settings() { settings.setProxies(Collections.singletonList(proxyWithBothProtocols)); when(mavenSession.getSettings()).thenReturn(settings); - Log log = mock(Log.class); - ScannerFactory factory = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - factory.create(); + underTest.create(); assertThat(System.getProperty("https.proxyHost")).isEqualTo("myhost"); assertThat(System.getProperty("https.proxyPort")).isEqualTo("443"); assertThat(System.getProperty("http.proxyHost")).isEqualTo("myhost"); @@ -167,13 +162,13 @@ void proxy_properties_are_not_set_when_no_active_proxy_is_provided() { Settings settings = new Settings(); when(mavenSession.getSettings()).thenReturn(settings); - Log log = spy(new DefaultLog(new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG, "no-proxy"))); - ScannerFactory factory = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - factory.create(); + Log specificLog = spy(new DefaultLog(new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG, "unrecognizable-protocol"))); + var specificUnderTest = spy(new ScannerBootstrapperFactory(specificLog, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor)); + specificUnderTest.create(); assertProxySettingsAreNotSet(); - verify(log, times(1)).debug("Skipping proxy settings: No active proxy detected."); + verify(specificLog, times(1)).debug("Skipping proxy settings: No active proxy detected."); } @Test @@ -186,13 +181,13 @@ void proxy_properties_are_not_set_when_protocol_is_null() { settings.setProxies(Collections.singletonList(proxyWithNullProtocol)); when(mavenSession.getSettings()).thenReturn(settings); - Log log = spy(new DefaultLog(new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG, "null-protocol-proxy"))); - ScannerFactory factory = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - factory.create(); + Log specificLog = spy(new DefaultLog(new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG, "null-protocol-proxy"))); + ScannerBootstrapperFactory specificUnderTest = spy(new ScannerBootstrapperFactory(specificLog, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor)); + specificUnderTest.create(); assertProxySettingsAreNotSet(); - verify(log, times(1)).warn("Skipping proxy settings: an active proxy was detected (id: null-protocol-proxy) but the protocol is null."); + verify(specificLog, times(1)).warn("Skipping proxy settings: an active proxy was detected (id: null-protocol-proxy) but the protocol is null."); } @Test @@ -205,13 +200,13 @@ void proxy_properties_are_not_set_when_protocol_is_blank() { settings.setProxies(Collections.singletonList(proxyWithNullProtocol)); when(mavenSession.getSettings()).thenReturn(settings); - Log log = spy(new DefaultLog(new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG, "null-protocol-proxy"))); - ScannerFactory factory = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - factory.create(); + Log specificLog = spy(new DefaultLog(new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG, "unrecognizable-protocol"))); + var specificUnderTest = spy(new ScannerBootstrapperFactory(specificLog, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor)); + specificUnderTest.create(); assertProxySettingsAreNotSet(); - verify(log, times(1)).warn("Skipping proxy settings: an active proxy was detected (id: null-protocol-proxy) but the protocol was not recognized."); + verify(specificLog, times(1)).warn("Skipping proxy settings: an active proxy was detected (id: null-protocol-proxy) but the protocol was not recognized."); } @Test @@ -223,9 +218,9 @@ void a_warning_is_logged_when_a_proxy_protocol_is_not_supported() { settings.setProxies(Collections.singletonList(proxyWithUnrecognizableProtocol)); when(mavenSession.getSettings()).thenReturn(settings); - Log log = spy(new DefaultLog(new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG, "unrecognizable-protocol"))); - ScannerFactory factory = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - factory.create(); + Log specificLog = spy(new DefaultLog(new ConsoleLogger(ConsoleLogger.LEVEL_DEBUG, "unrecognizable-protocol"))); + var specificUnderTest = spy(new ScannerBootstrapperFactory(specificLog, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor)); + specificUnderTest.create(); assertThat(System.getProperty("https.proxyHost")).isEqualTo("myhost"); assertThat(System.getProperty("https.proxyPort")).isEqualTo("443"); @@ -233,37 +228,38 @@ void a_warning_is_logged_when_a_proxy_protocol_is_not_supported() { assertThat(System.getProperty("http.proxyPassword")).isEqualTo("some-secret"); assertThat(System.getProperty("http.nonProxyHosts")).isEqualTo("sonarcloud.io|*.sonarsource.com"); - verify(log, times(1)).isDebugEnabled(); - verify(log, times(1)).debug("Setting proxy properties"); - verify(log, times(1)).warn("Setting proxy properties: one or multiple protocols of the active proxy (id: unknown-protocol-proxy) are not supported (protocols: unknown-proto)."); + verify(specificLog, times(1)).isDebugEnabled(); + verify(specificLog, times(1)).debug("Setting proxy properties"); + verify(specificLog, times(1)).warn("Setting proxy properties: one or multiple protocols of the active proxy (id: unknown-protocol-proxy) are not supported (protocols: unknown-proto)."); } @Test void testProperties() { - Log log = mock(Log.class); - ScannerFactory factory = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - EmbeddedScanner scanner = factory.create(); + underTest.create(); + verify(underTest).createScannerEngineBootstrapper("ScannerMaven", "2.0/1.0"); + ArgumentCaptor> captor = ArgumentCaptor.forClass(Map.class); + verify(mockBootstrapper).addBootstrapProperties(captor.capture()); + assertThat(captor.getValue()).contains(entry("system", "value"), entry("user", "value"), entry("root", "value"), entry("env", "value")); verify(mavenSession).getSystemProperties(); verify(rootProject).getProperties(); - - assertThat(scanner.appVersion()).isEqualTo("2.0/1.0"); - assertThat(scanner.app()).isEqualTo("ScannerMaven"); - assertThat(scanner.globalProperties()).contains(entry("system", "value"), entry("user", "value"), entry("root", "value"), entry("env", "value")); } @Test - void testDebug() { - Log log = mock(Log.class); + void testDebugEnabled() { when(log.isDebugEnabled()).thenReturn(true); - ScannerFactory factoryDebug = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - EmbeddedScanner scannerDebug = factoryDebug.create(); + underTest.create(); + verify(mockBootstrapper).setBootstrapProperty("sonar.verbose", "true"); + + when(log.isDebugEnabled()).thenReturn(false); + } + + @Test + void testDebugDisabled() { when(log.isDebugEnabled()).thenReturn(false); - ScannerFactory factory = new ScannerFactory(logOutput, log, runtimeInformation, mojoExecution, mavenSession, envProps, propertyDecryptor); - EmbeddedScanner scanner = factory.create(); + underTest.create(); - assertThat(scannerDebug.globalProperties()).contains(entry("sonar.verbose", "true")); - assertThat(scanner.globalProperties()).doesNotContain(entry("sonar.verbose", "true")); + verify(mockBootstrapper, never()).setBootstrapProperty(anyString(), anyString()); } static void assertProxySettingsAreNotSet() { diff --git a/src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperTest.java b/src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperTest.java index 568f6391..6c0d19f3 100644 --- a/src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperTest.java +++ b/src/test/java/org/sonarsource/scanner/maven/bootstrap/ScannerBootstrapperTest.java @@ -29,24 +29,36 @@ import java.util.Map; import java.util.Properties; import java.util.function.Consumer; - import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.mockito.*; -import org.sonarsource.scanner.api.EmbeddedScanner; -import org.sonarsource.scanner.api.ScanProperties; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.sonarsource.scanner.lib.AnalysisProperties; +import org.sonarsource.scanner.lib.ScannerEngineBootstrapper; +import org.sonarsource.scanner.lib.ScannerEngineFacade; import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.contains; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.sonarsource.scanner.maven.bootstrap.ScannerBootstrapper.UNSUPPORTED_BELOW_SONARQUBE_56_MESSAGE; class ScannerBootstrapperTest { @@ -60,7 +72,7 @@ class ScannerBootstrapperTest { private SecDispatcher securityDispatcher; @Mock - private EmbeddedScanner scanner; + private ScannerEngineBootstrapper scannerEngineBootstrapper; @Mock private MavenProjectConverter mavenProjectConverter; @@ -72,6 +84,9 @@ class ScannerBootstrapperTest { private Map projectProperties; + @Mock + ScannerEngineFacade scannerEngineFacade; + @BeforeEach public void setUp() throws MojoExecutionException, IOException { @@ -83,31 +98,33 @@ public void setUp() when(session.getUserProperties()).thenReturn(new Properties()); projectProperties = new HashMap<>(); - projectProperties.put(ScanProperties.PROJECT_BASEDIR, tmpFolder.toAbsolutePath().toString()); + projectProperties.put(AnalysisProperties.PROJECT_BASEDIR, tmpFolder.toAbsolutePath().toString()); // Create folders Path pom = tmpFolder.resolve("pom.xml"); pom.toFile().createNewFile(); Path sourceMainDirs = tmpFolder.resolve(Paths.get("src", "main", "java")); sourceMainDirs.toFile().mkdirs(); + Path sourceTestDirs = tmpFolder.resolve(Paths.get("src", "test", "java")); + sourceTestDirs.toFile().mkdirs(); Path sourceResourceDirs = tmpFolder.resolve(Paths.get("src", "main", "resources")); sourceResourceDirs.toFile().mkdirs(); Path javascriptResource = sourceResourceDirs.resolve("index.js"); javascriptResource.toFile().createNewFile(); - projectProperties.put(ScanProperties.PROJECT_SOURCE_DIRS, sourceMainDirs.toFile().toString() + "," + pom.toFile().toString()); + projectProperties.put(AnalysisProperties.PROJECT_SOURCE_DIRS, sourceMainDirs.toFile() + "," + pom.toFile()); + projectProperties.put(AnalysisProperties.PROJECT_TEST_DIRS, sourceTestDirs.toFile() + "," + pom.toFile()); when(mavenProjectConverter.configure(any(), any(), any())).thenReturn(projectProperties); - when(mavenProjectConverter.getEnvProperties()).thenReturn(new Properties()); + when(mavenProjectConverter.getEnvProperties()).thenReturn(new HashMap<>()); when(rootProject.getProperties()).thenReturn(new Properties()); - when(scanner.mask(anyString())).thenReturn(scanner); - when(scanner.unmask(anyString())).thenReturn(scanner); - ScannerBootstrapper scannerBootstrapperTmp = new ScannerBootstrapper(log, session, scanner, mavenProjectConverter, new PropertyDecryptor(log, securityDispatcher)); - scannerBootstrapper = spy(scannerBootstrapperTmp); + when(scannerEngineBootstrapper.bootstrap()).thenReturn(scannerEngineFacade); + scannerBootstrapper = new ScannerBootstrapper(log, session, scannerEngineBootstrapper, mavenProjectConverter, new PropertyDecryptor(log, securityDispatcher)); } @Test void testSQBefore56() { - when(scanner.serverVersion()).thenReturn("5.1"); + when(scannerEngineFacade.isSonarCloud()).thenReturn(false); + when(scannerEngineFacade.getServerVersion()).thenReturn("5.1"); MojoExecutionException exception = assertThrows(MojoExecutionException.class, () -> scannerBootstrapper.execute()); @@ -119,19 +136,17 @@ void testSQBefore56() { @Test void testSQ56() throws MojoExecutionException { - when(scanner.serverVersion()).thenReturn("5.6"); - ScannerBootstrapper mocked = Mockito.mock(ScannerBootstrapper.class); + when(scannerEngineFacade.isSonarCloud()).thenReturn(false); + when(scannerEngineFacade.getServerVersion()).thenReturn("5.6"); scannerBootstrapper.execute(); verifyCommonCalls(); - - // no extensions, mask or unmask - verifyNoMoreInteractions(scanner); } @Test void testVersionComparisonWithBuildNumber() throws MojoExecutionException { - when(scanner.serverVersion()).thenReturn("6.3.0.12345"); + when(scannerEngineFacade.isSonarCloud()).thenReturn(false); + when(scannerEngineFacade.getServerVersion()).thenReturn("6.3.0.12345"); scannerBootstrapper.execute(); assertThat(scannerBootstrapper.isVersionPriorTo("4.5")).isFalse(); @@ -139,21 +154,9 @@ void testVersionComparisonWithBuildNumber() throws MojoExecutionException { assertThat(scannerBootstrapper.isVersionPriorTo("6.4")).isTrue(); } - @Test - void testNullServerVersion() { - when(scanner.serverVersion()).thenReturn(null); - - MojoExecutionException exception = assertThrows(MojoExecutionException.class, - () -> scannerBootstrapper.execute()); - - assertThat(exception) - .hasCauseExactlyInstanceOf(UnsupportedOperationException.class) - .hasMessage(UNSUPPORTED_BELOW_SONARQUBE_56_MESSAGE); - } - @Test void scanAll_property_is_not_applied_by_default() throws MojoExecutionException { - // When sonar.scanner.scanAll is not set + // When sonar.scannerEngineFacade.scanAll is not set verifyCollectedSources(sourceDirs -> { assertThat(sourceDirs).hasSize(2); assertThat(sourceDirs[0]).endsWith(Paths.get("src", "main", "java").toString()); @@ -161,7 +164,6 @@ void scanAll_property_is_not_applied_by_default() throws MojoExecutionException }); verify(log, never()).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources."); - verify(scannerBootstrapper, never()).collectAllSources(any(), anyBoolean()); } @Test @@ -175,7 +177,6 @@ void scanAll_property_is_not_applied_when_set_explicitly() throws MojoExecutionE }); verify(log, never()).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources."); - verify(scannerBootstrapper, never()).collectAllSources(any(), eq(false)); } @Test @@ -190,7 +191,6 @@ void scanAll_property_is_applied_when_set_explicitly() throws MojoExecutionExcep }); verify(log, times(1)).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources."); - verify(scannerBootstrapper, times(1)).collectAllSources(any(), eq(false)); } @Test @@ -205,7 +205,6 @@ void scanAll_should_also_collect_java_and_kotlin_sources_when_binaries_and_libra }); verify(log, times(1)).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources."); - verify(scannerBootstrapper, times(1)).collectAllSources(any(), eq(true)); } @Test @@ -213,7 +212,7 @@ void should_not_collect_all_sources_when_sonar_sources_is_overridden() throws Mo setSonarScannerScanAllTo("true"); // Return the expected directory and notify of overriding - projectProperties.put(ScanProperties.PROJECT_SOURCE_DIRS, Paths.get("src", "main", "resources").toFile().toString()); + projectProperties.put(AnalysisProperties.PROJECT_SOURCE_DIRS, Paths.get("src", "main", "resources").toFile().toString()); when(mavenProjectConverter.isSourceDirsOverridden()).thenReturn(true); verifyCollectedSources(sourceDirs -> { @@ -223,7 +222,6 @@ void should_not_collect_all_sources_when_sonar_sources_is_overridden() throws Mo verify(log, times(1)).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources."); verify(log, times(1)).warn("Parameter sonar.maven.scanAll is enabled but the scanner will not collect additional sources because sonar.sources has been overridden."); - verify(scannerBootstrapper, never()).collectAllSources(any(), eq(false)); } @Test @@ -231,22 +229,21 @@ void should_not_collect_all_sources_when_sonar_tests_is_overridden() throws Mojo setSonarScannerScanAllTo("true"); // Return the expected directory and notify of overriding - projectProperties.put(ScanProperties.PROJECT_TEST_DIRS, Paths.get("src", "test", "resources").toFile().toString()); + projectProperties.put(AnalysisProperties.PROJECT_TEST_DIRS, Paths.get("src", "test", "resources").toFile().toString()); when(mavenProjectConverter.isTestDirsOverridden()).thenReturn(true); Map collectedProperties = scannerBootstrapper.collectProperties(); - assertThat(collectedProperties).containsKey(ScanProperties.PROJECT_TEST_DIRS); - String[] sourceDirs = collectedProperties.get(ScanProperties.PROJECT_TEST_DIRS).split(","); + assertThat(collectedProperties).containsKey(AnalysisProperties.PROJECT_TEST_DIRS); + String[] sourceDirs = collectedProperties.get(AnalysisProperties.PROJECT_TEST_DIRS).split(","); assertThat(sourceDirs).hasSize(1); assertThat(sourceDirs[0]).endsWith(Paths.get("src", "test", "resources").toString()); verify(log, times(1)).info("Parameter sonar.maven.scanAll is enabled. The scanner will attempt to collect additional sources."); verify(log, times(1)).warn("Parameter sonar.maven.scanAll is enabled but the scanner will not collect additional sources because sonar.tests has been overridden."); - verify(scannerBootstrapper, never()).collectAllSources(any(), eq(false)); } @Test - void an_exception_is_logged_at_warning_level_when_failing_to_crawl_the_filesystem_to_scan_all_sources() throws MojoExecutionException, IOException { + void an_exception_is_logged_at_warning_level_when_failing_to_crawl_the_filesystem_to_scan_all_sources() throws MojoExecutionException { setSonarScannerScanAllTo("true"); IOException expectedException = new IOException("This is what we expected"); @@ -269,14 +266,15 @@ void can_collect_sources_with_commas_in_paths() throws MojoExecutionException, I file.toFile().createNewFile(); Map collectedProperties = scannerBootstrapper.collectProperties(); - assertThat(collectedProperties).containsKey(ScanProperties.PROJECT_SOURCE_DIRS); - List values = MavenUtils.splitAsCsv(collectedProperties.get(ScanProperties.PROJECT_SOURCE_DIRS)); + assertThat(collectedProperties).containsKey(AnalysisProperties.PROJECT_SOURCE_DIRS); + List values = MavenUtils.splitAsCsv(collectedProperties.get(AnalysisProperties.PROJECT_SOURCE_DIRS)); assertThat(values).hasSize(4); } @Test void test_logging_SQ_version() throws MojoExecutionException { - when(scanner.serverVersion()).thenReturn("10.5"); + when(scannerEngineFacade.isSonarCloud()).thenReturn(false); + when(scannerEngineFacade.getServerVersion()).thenReturn("10.5"); scannerBootstrapper.execute(); verify(log).info("Communicating with SonarQube Server 10.5"); @@ -284,12 +282,7 @@ void test_logging_SQ_version() throws MojoExecutionException { @Test void test_not_logging_the_version_when_sonarcloud_is_used() throws MojoExecutionException { - // if SC is the server this property value should be ignored - when(scanner.serverVersion()).thenReturn("8.0"); - - Properties withSonarCloudHost = new Properties(); - withSonarCloudHost.put("sonar.host.url", "https://sonarcloud.io"); - when(session.getUserProperties()).thenReturn(withSonarCloudHost); + when(scannerEngineFacade.isSonarCloud()).thenReturn(true); scannerBootstrapper.execute(); verify(log).info("Communicating with SonarCloud"); @@ -302,7 +295,8 @@ class EnvironmentInformation { @BeforeEach void before() { - when(scanner.serverVersion()).thenReturn("9.9"); + when(scannerEngineFacade.getServerVersion()).thenReturn("9.9"); + when(scannerEngineFacade.isSonarCloud()).thenReturn(false); mockedSystem = mockStatic(SystemWrapper.class); } @@ -355,14 +349,13 @@ private void setSonarScannerScanAllAndBinariesAndLibraries() { private void verifyCollectedSources(Consumer sourceDirsAssertions) throws MojoExecutionException { Map collectedProperties = scannerBootstrapper.collectProperties(); - assertThat(collectedProperties).containsKey(ScanProperties.PROJECT_SOURCE_DIRS); - String[] sourceDirs = collectedProperties.get(ScanProperties.PROJECT_SOURCE_DIRS).split(","); + assertThat(collectedProperties).containsKey(AnalysisProperties.PROJECT_SOURCE_DIRS); + String[] sourceDirs = collectedProperties.get(AnalysisProperties.PROJECT_SOURCE_DIRS).split(","); sourceDirsAssertions.accept(sourceDirs); } private void verifyCommonCalls() { - verify(scanner).start(); - verify(scanner).serverVersion(); - verify(scanner).execute(projectProperties); + verify(scannerEngineFacade).isSonarCloud(); + verify(scannerEngineFacade).analyze(projectProperties); } } diff --git a/src/test/projects/project-with-external-reports/pom.xml b/src/test/projects/project-with-external-reports/pom.xml index d31279c4..aa0f3eed 100644 --- a/src/test/projects/project-with-external-reports/pom.xml +++ b/src/test/projects/project-with-external-reports/pom.xml @@ -8,7 +8,7 @@ 1.0-SNAPSHOT - target/dump.properties + target/dump.properties src/test/projects/project-with-external-reports/report1.xml src/test/projects/project-with-external-reports/report2.xml src/test/projects/project-with-external-reports/report3.xml,src/test/projects/project-with-external-reports/subdir/report4.xml diff --git a/src/test/projects/project-with-findbugs-build/pom.xml b/src/test/projects/project-with-findbugs-build/pom.xml index 1b6c1be6..2102286a 100644 --- a/src/test/projects/project-with-findbugs-build/pom.xml +++ b/src/test/projects/project-with-findbugs-build/pom.xml @@ -9,8 +9,8 @@ Test project - target/dump.properties - 5.6 + target/dump.properties + 5.6 diff --git a/src/test/projects/project-with-findbugs-plugin-management/pom.xml b/src/test/projects/project-with-findbugs-plugin-management/pom.xml index 61488241..24241da6 100644 --- a/src/test/projects/project-with-findbugs-plugin-management/pom.xml +++ b/src/test/projects/project-with-findbugs-plugin-management/pom.xml @@ -9,8 +9,8 @@ Test project - target/dump.properties - 5.6 + target/dump.properties + 5.6 diff --git a/src/test/projects/project-with-findbugs-reporting/pom.xml b/src/test/projects/project-with-findbugs-reporting/pom.xml index 1996356f..b0332595 100644 --- a/src/test/projects/project-with-findbugs-reporting/pom.xml +++ b/src/test/projects/project-with-findbugs-reporting/pom.xml @@ -9,8 +9,8 @@ Test project - target/dump.properties - 5.6 + target/dump.properties + 5.6 diff --git a/src/test/projects/project-with-java-files-not-in-src/pom.xml b/src/test/projects/project-with-java-files-not-in-src/pom.xml index bae60ec6..57a73eda 100644 --- a/src/test/projects/project-with-java-files-not-in-src/pom.xml +++ b/src/test/projects/project-with-java-files-not-in-src/pom.xml @@ -8,7 +8,7 @@ 1.0-SNAPSHOT - target/dump.properties + target/dump.properties diff --git a/src/test/projects/project-with-sonar-plugin-configuration/pom.xml b/src/test/projects/project-with-sonar-plugin-configuration/pom.xml index 3f635c3c..8fe957e9 100644 --- a/src/test/projects/project-with-sonar-plugin-configuration/pom.xml +++ b/src/test/projects/project-with-sonar-plugin-configuration/pom.xml @@ -9,7 +9,7 @@ Test project - target/dump.properties + target/dump.properties diff --git a/src/test/projects/project-with-sonar-plugin-management-configuration/pom.xml b/src/test/projects/project-with-sonar-plugin-management-configuration/pom.xml index c32c148e..6647feda 100644 --- a/src/test/projects/project-with-sonar-plugin-management-configuration/pom.xml +++ b/src/test/projects/project-with-sonar-plugin-management-configuration/pom.xml @@ -9,7 +9,7 @@ Test project - target/dump.properties + target/dump.properties diff --git a/src/test/projects/sample-project-with-custom-surefire-path/pom.xml b/src/test/projects/sample-project-with-custom-surefire-path/pom.xml index 174d8d94..bc97488e 100644 --- a/src/test/projects/sample-project-with-custom-surefire-path/pom.xml +++ b/src/test/projects/sample-project-with-custom-surefire-path/pom.xml @@ -9,8 +9,8 @@ Test project - target/dump.properties - 5.6 + target/dump.properties + 5.6 diff --git a/src/test/projects/sample-project-with-surefire/pom.xml b/src/test/projects/sample-project-with-surefire/pom.xml index 0aaf9e20..850e1eb3 100644 --- a/src/test/projects/sample-project-with-surefire/pom.xml +++ b/src/test/projects/sample-project-with-surefire/pom.xml @@ -9,8 +9,8 @@ Test project - target/dump.properties - 5.6 + target/dump.properties + 5.6 diff --git a/src/test/projects/sample-project/pom.xml b/src/test/projects/sample-project/pom.xml index 2996805a..e989a94f 100644 --- a/src/test/projects/sample-project/pom.xml +++ b/src/test/projects/sample-project/pom.xml @@ -9,8 +9,8 @@ Test project - target/dump.properties - 5.6 + target/dump.properties + 5.6 http://myserver:9000 diff --git a/src/test/projects/sample-war-project/pom.xml b/src/test/projects/sample-war-project/pom.xml index 89e18f7c..9729c7a6 100644 --- a/src/test/projects/sample-war-project/pom.xml +++ b/src/test/projects/sample-war-project/pom.xml @@ -10,8 +10,8 @@ war - target/dump.properties - 5.6 + target/dump.properties + 5.6 diff --git a/src/test/projects/war-project-override-web-dir/pom.xml b/src/test/projects/war-project-override-web-dir/pom.xml index cbb3c806..329d23de 100644 --- a/src/test/projects/war-project-override-web-dir/pom.xml +++ b/src/test/projects/war-project-override-web-dir/pom.xml @@ -10,8 +10,8 @@ war - target/dump.properties - 5.6 + target/dump.properties + 5.6