diff --git a/its/plugin/pom.xml b/its/plugin/pom.xml
index b23513f23c1..3589c6d12ab 100644
--- a/its/plugin/pom.xml
+++ b/its/plugin/pom.xml
@@ -24,6 +24,38 @@
false
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.junit.platform
+ junit-platform-suite
+ test
+
+
+ org.sonarsource.sonarlint.core
+ sonarlint-core-test-utils
+ ${sonarlint.plugin.api.version}
+ test
+
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.test.version}
+ test
+
+
+ org.awaitility
+ awaitility
+ 4.3.0
+ test
+
+
+
it-plugin
diff --git a/its/plugin/tests/src/test/java/com/sonar/it/java/suite/JavaTestSuite.java b/its/plugin/tests/src/test/java/com/sonar/it/java/suite/JavaTestSuite.java
index 4a8d5cb099e..5df38098276 100644
--- a/its/plugin/tests/src/test/java/com/sonar/it/java/suite/JavaTestSuite.java
+++ b/its/plugin/tests/src/test/java/com/sonar/it/java/suite/JavaTestSuite.java
@@ -48,7 +48,7 @@
Struts139Test.class,
JavaClasspathTest.class,
SuppressWarningTest.class,
- SonarLintTest.class,
+ SonarLintIntegrationTest.class,
ExternalReportTest.class,
DuplicationTest.class,
MultiModuleTelemetryTest.class
diff --git a/its/plugin/tests/src/test/java/com/sonar/it/java/suite/SonarLintIntegrationTest.java b/its/plugin/tests/src/test/java/com/sonar/it/java/suite/SonarLintIntegrationTest.java
new file mode 100644
index 00000000000..438c7d76797
--- /dev/null
+++ b/its/plugin/tests/src/test/java/com/sonar/it/java/suite/SonarLintIntegrationTest.java
@@ -0,0 +1,90 @@
+/*
+ * SonarQube Java
+ * Copyright (C) SonarSource Sàrl
+ * mailto:info AT sonarsource DOT com
+ *
+ * You can redistribute and/or modify this program under the terms of
+ * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl.
+ *
+ * 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 Sonar Source-Available License for more details.
+ *
+ * You should have received a copy of the Sonar Source-Available License
+ * along with this program; if not, see https://sonarsource.com/license/ssal/
+ */
+package com.sonar.it.java.suite;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import org.sonarsource.sonarlint.core.rpc.protocol.backend.analysis.AnalyzeFilesAndTrackParams;
+import org.sonarsource.sonarlint.core.rpc.protocol.backend.analysis.AnalyzeFilesResponse;
+import org.sonarsource.sonarlint.core.rpc.protocol.client.issue.RaisedIssueDto;
+import org.sonarsource.sonarlint.core.rpc.protocol.common.ClientFileDto;
+import org.sonarsource.sonarlint.core.rpc.protocol.common.Language;
+import org.sonarsource.sonarlint.core.test.utils.SonarLintBackendFixture;
+import org.sonarsource.sonarlint.core.test.utils.SonarLintTestRpcServer;
+import org.sonarsource.sonarlint.core.test.utils.junit5.SonarLintTest;
+import org.sonarsource.sonarlint.core.test.utils.junit5.SonarLintTestHarness;
+import org.sonarsource.sonarlint.core.test.utils.plugins.Plugin;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+import static org.junit.Assert.fail;
+
+public class SonarLintIntegrationTest {
+ private static final String CONFIG_SCOPE_ID = "CONFIG_SCOPE_ID";
+
+ private static Path pluginPath;
+
+ private SonarLintBackendFixture.FakeSonarLintRpcClient client;
+ private SonarLintTestRpcServer backend;
+
+ @SonarLintTest
+ void test() {
+ fail("fail () in SLIT");
+ }
+
+ private List analyzeFileAndGetIssues(URI fileUri) {
+ UUID analysisId = UUID.randomUUID();
+ AnalyzeFilesAndTrackParams params = new AnalyzeFilesAndTrackParams(CONFIG_SCOPE_ID, analysisId, List.of(fileUri), Map.of(), false);
+ AnalyzeFilesResponse analysisResult =
+ backend
+ .getAnalysisService()
+ .analyzeFilesAndTrack(params)
+ .join();
+ assertThat(analysisResult.getFailedAnalysisFiles()).isEmpty();
+ await()
+ .atMost(15, TimeUnit.SECONDS)
+ .untilAsserted(() -> assertThat(client.getRaisedIssuesForScopeIdAsList(CONFIG_SCOPE_ID)).isNotEmpty());
+ return client.getRaisedIssuesForScopeId(CONFIG_SCOPE_ID).get(fileUri);
+ }
+
+ private void initWithFiles(SonarLintTestHarness harness, Path baseDir, ClientFileDto fileDTOs) {
+ client = harness
+ .newFakeClient()
+ .withInitialFs(CONFIG_SCOPE_ID, baseDir, List.of(fileDTOs))
+ .build();
+
+ backend = harness
+ .newBackend()
+ .withStandaloneEmbeddedPluginAndEnabledLanguage(new Plugin(Set.of(Language.RUBY), pluginPath, "", ""))
+ .withUnboundConfigScope(CONFIG_SCOPE_ID)
+ .start(client);
+ }
+
+ private static ClientFileDto createFile(Path folderPath, String fileName, String content) throws IOException {
+ Path filePath = folderPath.resolve(fileName);
+ Files.writeString(filePath, content);
+ return new ClientFileDto(
+ filePath.toUri(), folderPath.relativize(filePath), CONFIG_SCOPE_ID, false, null, filePath, null, Language.RUBY, true);
+ }
+}
diff --git a/its/plugin/tests/src/test/java/com/sonar/it/java/suite/SonarLintTest.java b/its/plugin/tests/src/test/java/com/sonar/it/java/suite/SonarLintTest.java
deleted file mode 100644
index 9734109709c..00000000000
--- a/its/plugin/tests/src/test/java/com/sonar/it/java/suite/SonarLintTest.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * SonarQube Java
- * Copyright (C) SonarSource Sàrl
- * mailto:info AT sonarsource DOT com
- *
- * You can redistribute and/or modify this program under the terms of
- * the Sonar Source-Available License Version 1, as published by SonarSource Sàrl.
- *
- * 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 Sonar Source-Available License for more details.
- *
- * You should have received a copy of the Sonar Source-Available License
- * along with this program; if not, see https://sonarsource.com/license/ssal/
- */
-package com.sonar.it.java.suite;
-
-import com.google.common.io.Files;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-import org.apache.commons.io.FileUtils;
-import org.jetbrains.annotations.Nullable;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonarsource.sonarlint.core.analysis.AnalysisEngine;
-import org.sonarsource.sonarlint.core.analysis.api.ActiveRule;
-import org.sonarsource.sonarlint.core.analysis.api.AnalysisConfiguration;
-import org.sonarsource.sonarlint.core.analysis.api.AnalysisEngineConfiguration;
-import org.sonarsource.sonarlint.core.analysis.api.AnalysisResults;
-import org.sonarsource.sonarlint.core.analysis.api.ClientInputFile;
-import org.sonarsource.sonarlint.core.analysis.api.ClientModuleFileSystem;
-import org.sonarsource.sonarlint.core.analysis.api.ClientModuleInfo;
-import org.sonarsource.sonarlint.core.analysis.api.Issue;
-import org.sonarsource.sonarlint.core.analysis.command.AnalyzeCommand;
-import org.sonarsource.sonarlint.core.analysis.command.RegisterModuleCommand;
-import org.sonarsource.sonarlint.core.commons.api.SonarLanguage;
-import org.sonarsource.sonarlint.core.commons.log.LogOutput;
-import org.sonarsource.sonarlint.core.commons.log.SonarLintLogger;
-import org.sonarsource.sonarlint.core.commons.progress.ProgressMonitor;
-import org.sonarsource.sonarlint.core.plugin.commons.PluginsLoader;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
-
-public class SonarLintTest {
- private static final LogOutput NOOP_LOG_OUTPUT = new LogOutput() {
- @Override
- public void log(@Nullable String formattedMessage, Level level, @Nullable String stacktrace) {
- /*Don't pollute logs*/
- }
- };
-
- @ClassRule
- public static TemporaryFolder temp = new TemporaryFolder();
-
- private static AnalysisEngine sonarlintEngine;
- private static File baseDir;
-
- private final ProgressMonitor progressMonitor = new ProgressMonitor(null);
-
- @BeforeClass
- public static void prepare() throws Exception {
- AnalysisEngineConfiguration config = AnalysisEngineConfiguration.builder()
- .setWorkDir(temp.getRoot().toPath())
- .build();
-
- SonarLintLogger.setTarget(NOOP_LOG_OUTPUT);
- var pluginJarLocation = Set.of(JavaTestSuite.JAVA_PLUGIN_LOCATION.getFile().toPath());
- var enabledLanguages = Set.of(SonarLanguage.JAVA);
- var pluginConfiguration = new PluginsLoader.Configuration(pluginJarLocation, enabledLanguages, false, Optional.empty());
- var loadedPlugins = new PluginsLoader().load(pluginConfiguration, Set.of()).getLoadedPlugins();
-
- sonarlintEngine = new AnalysisEngine(config, loadedPlugins, NOOP_LOG_OUTPUT);
- baseDir = temp.newFolder();
- }
-
- @AfterClass
- public static void stop() {
- SonarLintLogger.setTarget(null);
- sonarlintEngine.stop();
- }
-
- @Test
- public void simpleJava() throws Exception {
- ClientInputFile inputFile = prepareInputFile("Foo.java", """
- public class Foo {
- public void foo() {
- int x;
- System.out.println("Foo");
- System.out.println("Foo"); //NOSONAR
- }
- }
- """,
- false);
-
- final List issues = new ArrayList<>();
- AnalysisConfiguration configuration = AnalysisConfiguration.builder()
- .setBaseDir(baseDir.toPath())
- .addInputFile(inputFile)
- .addActiveRules(
- new ActiveRule("java:S106", SonarLanguage.JAVA.name()),
- new ActiveRule("java:S1220", SonarLanguage.JAVA.name()),
- new ActiveRule("java:S1481", SonarLanguage.JAVA.name())
- ).build();
-
- ClientModuleFileSystem clientFileSystem = getClientModuleFileSystem(inputFile);
- sonarlintEngine.post(new RegisterModuleCommand(new ClientModuleInfo("myModule", clientFileSystem)), progressMonitor).get();
- var command = new AnalyzeCommand("myModule", configuration, issues::add, NOOP_LOG_OUTPUT);
- sonarlintEngine.post(command, progressMonitor).get();
-
- assertThat(issues).extracting("ruleKey", "startLine", "inputFile.path", "overriddenImpacts").containsExactlyInAnyOrder(
- tuple("java:S106", 4, inputFile.getPath(), Map.of()),
- tuple("java:S1220", null, inputFile.getPath(), Map.of()),
- tuple("java:S1481", 3, inputFile.getPath(), Map.of())
- );
- }
-
- @Test
- public void simpleTestFileJava() throws Exception {
- ClientInputFile inputFile = prepareInputFile("FooTest.java",
- "public class FooTest {\n"
- + " @org.junit.Test\n"
- + " @org.junit.Ignore\n"
- + " public void testName() throws Exception {\n" // S1607(ignored test)
- + " Foo foo = new Foo();\n"
- + " org.assertj.core.api.Assertions.assertThat(foo.isFooActive());\n" // S2970(incomplete assertions) - requires semantic
- + " java.lang.Thread.sleep(Long.MAX_VALUE);" // S2925(thread.sleep in test)
- + " }\n\n"
-
- + " private static class Foo {"
- + " public boolean isFooActive() {"
- + " return false;"
- + " }"
- + " }"
- + "}",
- true);
-
- final List issues = new ArrayList<>();
- AnalysisConfiguration configuration = AnalysisConfiguration.builder()
- .setBaseDir(baseDir.toPath())
- .addInputFile(inputFile)
- .addActiveRules(
- new ActiveRule("java:S1220", SonarLanguage.JAVA.name()),
- new ActiveRule("java:S2925", SonarLanguage.JAVA.name())
- ).build();
- ClientModuleFileSystem clientFileSystem = getClientModuleFileSystem(inputFile);
-
- sonarlintEngine.post(new RegisterModuleCommand(new ClientModuleInfo("myModule", clientFileSystem)), progressMonitor).get();
- var command = new AnalyzeCommand("myModule", configuration, issues::add, NOOP_LOG_OUTPUT);
- sonarlintEngine.post(command, progressMonitor).get();
-
- assertThat(issues).extracting("ruleKey", "startLine", "inputFile.path", "overriddenImpacts").containsOnly(
- tuple("java:S2925", 7, inputFile.getPath(), Map.of()),
- // expected issue
- tuple("java:S1220", null, inputFile.getPath(), Map.of()));
- }
-
- @Test
- public void supportJavaSuppressWarning() throws Exception {
- ClientInputFile inputFile = prepareInputFile("Foo.java", """
- public class Foo {
- @SuppressWarnings("java:S106")
- public void foo() {
- int x;
- System.out.println("Foo");
- System.out.println("Foo"); //NOSONAR
- }
- }
- """,
- false);
-
- final List issues = new ArrayList<>();
- AnalysisConfiguration configuration = AnalysisConfiguration.builder()
- .setBaseDir(baseDir.toPath())
- .addInputFile(inputFile)
- .addActiveRules(
- new ActiveRule("java:S1220", SonarLanguage.JAVA.name()),
- new ActiveRule("java:S1481", SonarLanguage.JAVA.name())
- )
- .build();
-
-
- ClientModuleFileSystem clientFileSystem = getClientModuleFileSystem(inputFile);
-
- sonarlintEngine.post(new RegisterModuleCommand(new ClientModuleInfo("myModule", clientFileSystem)), progressMonitor).get();
- var command = new AnalyzeCommand("myModule", configuration, issues::add, NOOP_LOG_OUTPUT);
- sonarlintEngine.post(command, progressMonitor).get();
-
- assertThat(issues).extracting("ruleKey", "startLine", "inputFile.path", "overriddenImpacts").containsOnly(
- tuple("java:S1220", null, inputFile.getPath(), Map.of()),
- tuple("java:S1481", 4, inputFile.getPath(), Map.of()));
- }
-
- @Test
- public void parse_error_should_report_analysis_error() throws Exception {
- ClientInputFile inputFile = prepareInputFile("ParseError.java", "class ParseError {", false);
- final List issues = new ArrayList<>();
- AnalysisConfiguration configuration = AnalysisConfiguration.builder()
- .setBaseDir(baseDir.toPath())
- .addInputFile(inputFile)
- .build();
-
- ClientModuleFileSystem clientFileSystem = getClientModuleFileSystem(inputFile);
-
- sonarlintEngine.post(new RegisterModuleCommand(new ClientModuleInfo("myModule", clientFileSystem)), progressMonitor).get();
- var command = new AnalyzeCommand("myModule", configuration, issues::add, NOOP_LOG_OUTPUT);
- AnalysisResults analysisResults = sonarlintEngine.post(command, progressMonitor).get();
-
- assertThat(issues).isEmpty();
- assertThat(analysisResults.failedAnalysisFiles()).hasSize(1);
- }
-
- @Test
- public void sonarlint_cancelled_analysis_logs_but_does_not_rethrow_exception() throws Exception {
- List logLevels = new ArrayList<>();
- List errorLogs = new ArrayList<>();
-
- AnalysisEngineConfiguration engineConfiguration = AnalysisEngineConfiguration.builder()
- .setWorkDir(temp.getRoot().toPath())
- .build();
-
- LogOutput levelCollector = new LogOutput() {
- @Override
- public void log(String formattedMessage, Level level, @Nullable String stacktrace) {
- logLevels.add(level);
- }
- };
- SonarLintLogger.setTarget(levelCollector);
- var pluginJarLocation = Set.of(JavaTestSuite.JAVA_PLUGIN_LOCATION.getFile().toPath());
- var enabledLanguages = Set.of(SonarLanguage.JAVA);
- var pluginConfiguration = new PluginsLoader.Configuration(pluginJarLocation, enabledLanguages, false, Optional.empty());
- var loadedPlugins = new PluginsLoader().load(pluginConfiguration, Set.of()).getLoadedPlugins();
-
- AnalysisEngine specificSonarlintEngine = new AnalysisEngine(engineConfiguration, loadedPlugins, NOOP_LOG_OUTPUT);
-
- ClientInputFile inputFile = prepareInputFile("Foo.java", """
- public class Foo {
- @SuppressWarnings("java:S106")
- public void foo() {
- int x;
- System.out.println("Foo");
- System.out.println("Foo"); //NOSONAR
- }
- }
- """,
- false);
-
- AnalysisConfiguration analysisConfiguration = AnalysisConfiguration.builder()
- .setBaseDir(baseDir.toPath())
- .addActiveRules(
- new ActiveRule("java:S1220", SonarLanguage.JAVA.name()),
- new ActiveRule("java:S1481", SonarLanguage.JAVA.name())
- )
- .addInputFile(inputFile)
- .build();
-
- final List issues = new ArrayList<>();
-
- CancellableProgressMonitor cancellableProgressMonitor = new CancellableProgressMonitor();
-
- ClientModuleFileSystem clientFileSystem = getClientModuleFileSystem(inputFile);
-
- specificSonarlintEngine.post(new RegisterModuleCommand(new ClientModuleInfo("myModule", clientFileSystem)), progressMonitor).get();
- Consumer issueListener = issue -> {
- if (!issues.isEmpty()) {
- cancellableProgressMonitor.isCanceled = true;
- throw new MyCancelException();
- }
- issues.add(issue);
- };
- LogOutput errorCollector = new LogOutput() {
- @Override
- public void log(@Nullable String formattedMessage, Level level, @Nullable String stacktrace) {
- if (level == LogOutput.Level.ERROR) {
- errorLogs.add(formattedMessage);
- }
- }
- };
- var command = new AnalyzeCommand("myModule",
- analysisConfiguration,
- issueListener,
- errorCollector
- );
- specificSonarlintEngine.post(command, cancellableProgressMonitor).get();
-
- // Check that there were no error logs prior to the analysis, as the log levels are not collected DURING the analysis
- assertThat(logLevels).doesNotContain(LogOutput.Level.ERROR);
- assertThat(errorLogs)
- .containsOnly("Error executing sensor: 'JavaSensor'");
- assertThat(issues).hasSize(1);
- }
-
- private ClientInputFile prepareInputFile(String relativePath, String content, final boolean isTest) throws IOException {
- final File file = new File(baseDir, relativePath);
- FileUtils.write(file, content, StandardCharsets.UTF_8);
- return createInputFile(file.toPath(), isTest);
- }
-
- private ClientInputFile createInputFile(final Path path, final boolean isTest) {
- return new ClientInputFile() {
-
- @Override
- public String getPath() {
- return path.toString();
- }
-
- @Override
- public String relativePath() {
- return baseDir.toPath().relativize(path).toString();
- }
-
- @Override
- public URI uri() {
- return path.toUri();
- }
-
- @Override
- public boolean isTest() {
- return isTest;
- }
-
- @Override
- public Charset getCharset() {
- return StandardCharsets.UTF_8;
- }
-
- @Override
- public G getClientObject() {
- return null;
- }
-
- @Override
- public InputStream inputStream() throws IOException {
- return new FileInputStream(path.toFile());
- }
-
- @Override
- public String contents() throws IOException {
- return Files.asCharSource(path.toFile(), StandardCharsets.UTF_8).read();
- }
- };
- }
-
- private static ClientModuleFileSystem getClientModuleFileSystem(ClientInputFile inputFile) {
- return new ClientModuleFileSystem() {
- @Override
- public Stream files(String s, InputFile.Type type) {
- return Stream.of(inputFile);
- }
-
- @Override
- public Stream files() {
- return Stream.of(inputFile);
- }
- };
- }
-
- static class MyCancelException extends RuntimeException {
- }
-
- static class CancellableProgressMonitor extends ProgressMonitor {
- boolean isCanceled = false;
-
- CancellableProgressMonitor() {
- super(null);
- }
-
- @Override
- public boolean isCanceled() {
- return isCanceled;
- }
- }
-}
diff --git a/pom.xml b/pom.xml
index 0d14f365ebf..4aafcd1a639 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,7 +94,7 @@
at SonarSource/sonarqube/gradle.properties
-->
13.0.0.3026
- 10.13.0.79996
+ 11.3.0.85510
its/**,java-checks-test-sources/**
2.22.0.4796
6.1.0.3962
@@ -114,7 +114,10 @@
org.jacoco.agent-${version.jacoco.plugin}-runtime.jar
mockito-core-${mockito-core.version}.jar
+
1.7.30
+
+ 2.0.18