import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.Map;
import java.util.Random;
-import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.junit.rules.TemporaryFolder;
import org.slf4j.event.Level;
import org.sonar.api.CoreProperties;
-import org.sonar.api.Plugin;
import org.sonar.api.SonarEdition;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputFileFilter;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.testfixtures.log.LogTester;
import org.sonar.api.utils.MessageException;
import static org.assertj.core.api.Assertions.tuple;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
-import static org.sonar.core.config.ScannerProperties.PLUGIN_LOADING_OPTIMIZATION_KEY;
public class FileSystemMediumIT {
public ScannerMediumTester tester = new ScannerMediumTester()
.setEdition(SonarEdition.COMMUNITY)
.registerPlugin("xoo", new XooPlugin())
- .registerOptionalPlugin("optional-xoo", Set.of("xoo"), new OptionalXooPlugin())
.addDefaultQProfile("xoo", "Sonar Way")
.addDefaultQProfile("xoo2", "Sonar Way");
.hasMessageEndingWith(format("Failed to preprocess files"));
}
- @Test
- public void should_load_input_file_filters_for_required_and_optional_plugins() throws IOException {
- File projectDir = new File("test-resources/mediumtest/xoo/sample-with-input-file-filters");
- AnalysisResult result = tester
- .newAnalysis(new File(projectDir, "sonar-project.properties"))
- .properties(Map.of(PLUGIN_LOADING_OPTIMIZATION_KEY, "true"))
- .execute();
-
- assertThat(result.inputFiles()).hasSize(1);
-
- assertThat(logTester.logs()).contains("'xources/hello/xoo_exclude2.xoo' excluded by org.sonar.scanner.mediumtest.fs" +
- ".FileSystemMediumIT$OptionalXooPlugin$OptionalXooFileFilter");
- assertThat(logTester.logs()).contains("'xources/hello/xoo_exclude.xoo' excluded by org.sonar.xoo.extensions.XooExcludeFileFilter");
- assertThat(logTester.logs()).contains("'xources/hello/HelloJava.xoo' indexed with language 'xoo'");
-
- assertThat(result.inputFile("xources/hello/xoo_exclude.xoo")).isNull();
- assertThat(result.inputFile("xources/hello/xoo_exclude2.xoo")).isNull();
- assertThat(result.inputFile("xources/hello/HelloJava.xoo")).isNotNull();
- }
-
- public static class OptionalXooPlugin implements Plugin {
-
- @Override
- public void define(Context context) {
- context.addExtension(OptionalXooFileFilter.class);
- }
-
- public static class OptionalXooFileFilter implements InputFileFilter {
-
- @Override
- public boolean accept(InputFile f) {
- return !f.filename().endsWith("_exclude2.xoo");
- }
- }
- }
-
private static void assertAnalysedFiles(AnalysisResult result, String... files) {
assertThat(result.inputFiles().stream().map(InputFile::toString).toList()).contains(files);
}
--- /dev/null
+/*
+ * SonarQube
+ * 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.scanner.mediumtest.optionalplugins;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.io.FileUtils;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.slf4j.event.Level;
+import org.sonar.api.Plugin;
+import org.sonar.api.SonarEdition;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.InputFileFilter;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.FileLinesContextFactory;
+import org.sonar.api.scan.issue.filter.FilterableIssue;
+import org.sonar.api.scan.issue.filter.IssueFilter;
+import org.sonar.api.scan.issue.filter.IssueFilterChain;
+import org.sonar.api.scanner.sensor.ProjectSensor;
+import org.sonar.api.testfixtures.log.LogTester;
+import org.sonar.scanner.mediumtest.AnalysisResult;
+import org.sonar.scanner.mediumtest.ScannerMediumTester;
+import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.xoo.XooPlugin;
+import org.sonar.xoo.rule.XooRulesDefinition;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.sonar.core.config.ScannerProperties.PLUGIN_LOADING_OPTIMIZATION_KEY;
+
+public class OptionalPluginsMediumIT {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Rule
+ public LogTester logTester = new LogTester();
+
+ @Rule
+ public ScannerMediumTester tester = new ScannerMediumTester()
+ .setEdition(SonarEdition.COMMUNITY)
+ .registerPlugin("xoo", new XooPlugin())
+ .registerPlugin("nonoptional-plugin", new NonOptionalPlugin())
+ .registerOptionalPlugin("optional-plugin", Set.of("xoo"), new OptionalPlugin())
+ .addDefaultQProfile("xoo", "Sonar Way")
+ .addRules(new XooRulesDefinition())
+ .addActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", "OneIssuePerLine.internal", "xoo");
+
+ @Before
+ public void prepare() throws IOException {
+ logTester.setLevel(Level.DEBUG);
+ }
+
+ @Test
+ public void should_load_input_file_filters_for_required_and_optional_plugins() {
+ File projectDir = new File("test-resources/mediumtest/xoo/sample-with-input-file-filters");
+ AnalysisResult result = tester
+ .newAnalysis(new File(projectDir, "sonar-project.properties"))
+ .properties(Map.of(PLUGIN_LOADING_OPTIMIZATION_KEY, "true"))
+ .execute();
+
+ assertThat(result.inputFiles()).hasSize(1);
+
+ assertThat(logTester.logs()).contains("'xources/hello/xoo_exclude2.xoo' excluded by org.sonar.scanner.mediumtest.optionalplugins" +
+ ".OptionalPluginsMediumIT$NonOptionalPlugin$NonOptionalXooFileFilter");
+ assertThat(logTester.logs()).contains("'xources/hello/xoo_exclude3.xoo' excluded by org.sonar.scanner.mediumtest.optionalplugins" +
+ ".OptionalPluginsMediumIT$OptionalPlugin$OptionalXooFileFilter");
+ assertThat(logTester.logs()).contains("'xources/hello/xoo_exclude.xoo' excluded by org.sonar.xoo.extensions.XooExcludeFileFilter");
+ assertThat(logTester.logs()).contains("'xources/hello/HelloJava.xoo' indexed with language 'xoo'");
+
+ assertThat(result.inputFile("xources/hello/xoo_exclude.xoo")).isNull();
+ assertThat(result.inputFile("xources/hello/xoo_exclude2.xoo")).isNull();
+ assertThat(result.inputFile("xources/hello/xoo_exclude3.xoo")).isNull();
+ assertThat(result.inputFile("xources/hello/HelloJava.xoo")).isNotNull();
+ }
+
+ @Test
+ public void should_load_issue_filters_for_optional_plugins() throws Exception {
+ File projectDir = new File("test-resources/mediumtest/xoo/sample");
+ File tmpDir = temp.newFolder();
+ FileUtils.copyDirectory(projectDir, tmpDir);
+
+ AnalysisResult result = tester
+ .newAnalysis(new File(tmpDir, "sonar-project.properties"))
+ .properties(Map.of(PLUGIN_LOADING_OPTIMIZATION_KEY, "true"))
+ .execute();
+
+ List<ScannerReport.Issue> issues = result.issuesFor(result.inputFile("xources/hello/HelloJava.xoo"));
+ assertThat(issues).hasSize(8 - 1 /* line 2 excluded by NonOptionalIssueFiler*/ - 1 /* line 3 excluded by OptionalIssueFiler*/);
+ }
+
+ @Test
+ public void should_save_measures_for_optional_plugins() throws Exception {
+ File projectDir = new File("test-resources/mediumtest/xoo/sample");
+ File tmpDir = temp.newFolder();
+ FileUtils.copyDirectory(projectDir, tmpDir);
+
+ AnalysisResult result = tester
+ .newAnalysis(new File(tmpDir, "sonar-project.properties"))
+ .properties(Map.of(PLUGIN_LOADING_OPTIMIZATION_KEY, "true"))
+ .execute();
+
+ assertThat(result.allMeasures().get(result.project().key()))
+ .extracting(ScannerReport.Measure::getMetricKey, m -> m.getIntValue().getValue())
+ .containsExactlyInAnyOrder(
+ tuple(CoreMetrics.CLASSES_KEY, 1),
+ tuple(CoreMetrics.FUNCTIONS_KEY, 2));
+ }
+
+ public static class NonOptionalPlugin implements Plugin {
+
+ @Override
+ public void define(Context context) {
+ context.addExtensions(
+ NonOptionalXooFileFilter.class,
+ NonOptionalIssueFilter.class,
+ NonOptionalSensor.class);
+ }
+
+ public static class NonOptionalXooFileFilter implements InputFileFilter {
+
+ @Override
+ public boolean accept(InputFile f) {
+ return !f.filename().endsWith("_exclude2.xoo");
+ }
+ }
+
+ public static class NonOptionalIssueFilter implements IssueFilter {
+
+ @Override
+ public boolean accept(FilterableIssue filterableIssue, IssueFilterChain issueFilterChain) {
+ if (!issueFilterChain.accept(filterableIssue)) {
+ return false;
+ }
+ // Suppress issues on line 2
+ var line = filterableIssue.line();
+ return line == null || line != 2;
+ }
+ }
+
+ public static class NonOptionalSensor implements ProjectSensor {
+
+ private final MetricFinder metricFinder;
+ private final FileLinesContextFactory fileLinesContextFactory;
+
+ public NonOptionalSensor(MetricFinder metricFinder, FileLinesContextFactory fileLinesContextFactory) {
+ this.metricFinder = metricFinder;
+ // Simply verify that FileLinesContextFactory is correctly injected
+ this.fileLinesContextFactory = fileLinesContextFactory;
+ }
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor.name("NonOptionalSensor");
+ }
+
+ @Override
+ public void execute(SensorContext context) {
+ var metric = metricFinder.findByKey(CoreMetrics.CLASSES_KEY);
+ context.newMeasure().forMetric(metric).withValue(1).on(context.project()).save();
+ }
+ }
+ }
+
+ public static class OptionalPlugin implements Plugin {
+
+ @Override
+ public void define(Context context) {
+ context.addExtensions(
+ OptionalXooFileFilter.class,
+ OptionalIssueFilter.class,
+ OptionalSensor.class);
+ }
+
+ public static class OptionalXooFileFilter implements InputFileFilter {
+
+ @Override
+ public boolean accept(InputFile f) {
+ return !f.filename().endsWith("_exclude3.xoo");
+ }
+ }
+
+ public static class OptionalIssueFilter implements IssueFilter {
+
+ @Override
+ public boolean accept(FilterableIssue filterableIssue, IssueFilterChain issueFilterChain) {
+ if (!issueFilterChain.accept(filterableIssue)) {
+ return false;
+ }
+ // Suppress issues on line 3
+ var line = filterableIssue.line();
+ return line == null || line != 3;
+ }
+ }
+
+ public static class OptionalSensor implements ProjectSensor {
+
+ private final MetricFinder metricFinder;
+ private final FileLinesContextFactory fileLinesContextFactory;
+
+ public OptionalSensor(MetricFinder metricFinder, FileLinesContextFactory fileLinesContextFactory) {
+ this.metricFinder = metricFinder;
+ // Simply verify that FileLinesContextFactory is correctly injected
+ this.fileLinesContextFactory = fileLinesContextFactory;
+ }
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor.name("OptionalSensor");
+ }
+
+ @Override
+ public void execute(SensorContext context) {
+ var metric = metricFinder.findByKey(CoreMetrics.FUNCTIONS_KEY);
+ context.newMeasure().forMetric(metric).withValue(2).on(context.project()).save();
+ }
+ }
+ }
+
+
+}