Skip to content

Commit

Permalink
SCANMAVEN-237 Test sensor context config, system properties, and envi…
Browse files Browse the repository at this point in the history
…ronment variables passed to the bootstrapped JRE (#246)
  • Loading branch information
alban-auzeill authored Oct 29, 2024
1 parent 52c4e6d commit 993000d
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 15 deletions.
16 changes: 14 additions & 2 deletions its/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,22 @@
</properties>

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.11.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.sonarsource.orchestrator</groupId>
<artifactId>sonar-orchestrator-junit5</artifactId>
<version>4.8.0.1898</version>
<version>5.0.0.2065</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -41,7 +53,7 @@
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.9.0</version>
<version>3.26.3</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
16 changes: 16 additions & 0 deletions its/projects/maven/bootstrap-small-project/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<sonar.java.fileByFile>true</sonar.java.fileByFile>
<!--
This property will be ignored because:
- We will run sonar:sonar with the SONAR_SCANNER_JAVA_OPTS environment variable that has priority on pom.xml properties
- We will run sonar:sonar with the -Dsonar.scanner.javaOpts command line argument that has priority on everything
-->
<sonar.scanner.javaOpts>-Dhttp.proxyUser=my-custom-user-from-pom-xml</sonar.scanner.javaOpts>
</properties>

<dependencies>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.example;

public interface Hello {
}
89 changes: 83 additions & 6 deletions its/src/test/java/com/sonar/maven/it/suite/BootstrapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Properties;
import org.assertj.core.api.SoftAssertions;
import org.assertj.core.api.StringAssert;
import org.junit.jupiter.api.Test;

import static com.sonar.maven.it.ItUtils.locateProjectDir;
import static org.assertj.core.api.Assertions.assertThat;

public class BootstrapTest extends AbstractMavenTest {
class BootstrapTest extends AbstractMavenTest {

@Test
void test_unsupported_platform() {
Expand Down Expand Up @@ -65,28 +68,102 @@ void test_supported_arch_to_assert_jre_used() throws IOException {
MavenBuild build = MavenBuild.create(ItUtils.locateProjectPom(projectName))
.setProperty("sonar.login", ORCHESTRATOR.getDefaultAdminToken())
.setProperty("sonar.host.url", ORCHESTRATOR.getServer().getUrl())
.setEnvironmentVariable("DUMP_SENSOR_PROPERTIES", "" +
"any.property.name," +
"sonar.java.fileByFile," +
"sonar.java.file.suffixes," +
"sonar.projectKey," +
"sonar.projectBaseDir," +
"sonar.sources," +
"sonar.working.directory," +
"sonar.java.libraries," +
"sonar.java.source," +
"sonar.java.target," +
"sonar.java.test.libraries," +
"sonar.java.jdkHome")
.setEnvironmentVariable("DUMP_ENV_PROPERTIES", "" +
"ANY_ENV_VAR")
.setEnvironmentVariable("DUMP_SYSTEM_PROPERTIES", "" +
"http.proxyUser,"+
"http.nonProxyHosts," +
"java.home")
.setEnvironmentVariable("ANY_ENV_VAR", "42")
// http.nonProxyHosts will only be present in the maven context and not in the provisioned JRE
.setProperty("http.nonProxyHosts", "localhost|my-custom-non-proxy.server.com")
// Any property will be passed to the sensorContext.config()
.setProperty("any.property.name", "foo42")
// This property will be ignored because of the bellow "sonar.scanner.javaOpts" property that has priority
.setEnvironmentVariable("SONAR_SCANNER_JAVA_OPTS", "-Dhttp.proxyUser=my-custom-user-from-env")
// Set system property on the provisioned JRE
.setProperty("sonar.scanner.javaOpts", "-Dhttp.proxyUser=my-custom-user-from-system-properties")
.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));

Path smallProjectDir = locateProjectDir("maven").getAbsoluteFile().toPath().resolve("bootstrap-small-project");

SoftAssertions softly = new SoftAssertions();

// Environment variables
softly.assertThat(props.getProperty("ANY_ENV_VAR")).isEqualTo( "42");

// User defined in its/projects/maven/bootstrap-small-project/pom.xml properties
softly.assertThat(props.getProperty("sonar.java.fileByFile")).isEqualTo( "true");

// SonarQube properties
softly.assertThat(props.getProperty("sonar.java.file.suffixes")).isEqualTo( ".java,.jav");

// Project properties
softly.assertThat(props.getProperty("sonar.projectKey")).isEqualTo( "org.sonarsource.maven.its:bootstrap-small-project");
softly.assertThat(props.getProperty("sonar.projectBaseDir")).isEqualTo( smallProjectDir.toString());
softly.assertThat(props.getProperty("sonar.sources")).isEqualTo( smallProjectDir.resolve("pom.xml") + "," + smallProjectDir.resolve("src").resolve("main").resolve("java"));
softly.assertThat(props.getProperty("sonar.working.directory")).isEqualTo( smallProjectDir.resolve("target").resolve("sonar").toString());

// Any properties are present in the sensor context
softly.assertThat(props.getProperty("any.property.name")).contains("foo42");

// Java analyzers properties
softly.assertThat(props.getProperty("sonar.java.libraries")).contains("jsr305-3.0.2.jar");
softly.assertThat(props.getProperty("sonar.java.source")).isEqualTo( "11");
softly.assertThat(props.getProperty("sonar.java.target")).isEqualTo( "11");
softly.assertThat(props.getProperty("sonar.java.test.libraries")).contains("jsr305-3.0.2.jar");
// sonar.java.jdkHome should be the one used by "mvn sonar:sonar", by default maven uses JAVA_HOME
String javaHome = System.getenv("JAVA_HOME");
if (javaHome == null) {
javaHome = System.getProperty("java.home");
}
softly.assertThat(props.getProperty("sonar.java.jdkHome")).isEqualTo( new File(javaHome).getCanonicalPath());

StringAssert javaHomeAssertion = softly.assertThat(props.getProperty("java.home")).isNotEmpty();
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()
javaHomeAssertion
.isNotEqualTo(System.getProperty("java.home"))
.contains(".sonar" + File.separator + "cache");

// System properties of the initial JRE are intentionally not set on the provisioned JRE
softly.assertThat(props.getProperty("http.nonProxyHosts"))
.isEmpty();

// System properties defined in "sonar.scanner.javaOpts" are set on the provisioned JRE
softly.assertThat(props.getProperty("http.proxyUser")).isEqualTo("my-custom-user-from-system-properties");
} else {
//we test that we are using the system JRE
assertThat(props.getProperty("java.home"))
.isNotEmpty()
javaHomeAssertion
.isEqualTo(System.getProperty("java.home"))
.doesNotContain(".sonar" + File.separator + "cache");

softly.assertThat(props.getProperty("http.nonProxyHosts"))
.isEqualTo("localhost|my-custom-non-proxy.server.com");

// System properties defined in "sonar.scanner.javaOpts" are ignored outside the provisioned JRE
softly.assertThat(props.getProperty("http.proxyUser")).isEmpty();
}
softly.assertAll();
}

}
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<version>3.26.3</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,17 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
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;
import org.sonar.api.config.Configuration;

public class PropertyDumpPlugin implements Plugin, Sensor {

Expand All @@ -45,17 +50,37 @@ public void describe(SensorDescriptor sensorDescriptor) {

@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)));
LOG.info("Dumping sensorContext properties, environment variables, and system properties to {}", filePath);
var props = new Properties();
Configuration config = sensorContext.config();
getPropertyKeys("DUMP_SENSOR_PROPERTIES").forEach(key -> props.setProperty(key, nonNull(config.get(key))));
getPropertyKeys("DUMP_ENV_PROPERTIES").forEach(key -> props.setProperty(key, nonNull(System.getenv(key))));
getPropertyKeys("DUMP_SYSTEM_PROPERTIES").forEach(key -> props.setProperty(key, nonNull(System.getProperty(key, ""))));
props.stringPropertyNames().forEach(key -> LOG.info("{}={}", key, props.getProperty(key)));
props.store(Files.newOutputStream(filePath), null);
} catch (IOException e) {
throw new RuntimeException(e);
throw new IllegalStateException(e.getClass().getSimpleName() + ": " + e.getMessage(), e);
}
}

private static String nonNull(Object value) {
if (value instanceof Optional<?> opt) {
value = opt.orElse(null);
}
if (value != null) {
return value.toString();
}
return "";
}

private static List<String> getPropertyKeys(String envName) {
String list = System.getenv(envName);
if (list == null) {
return List.of();
}
return Arrays.asList(list.replace(" ", "").split(",", -1));
}

}

0 comments on commit 993000d

Please sign in to comment.