diff options
Diffstat (limited to 'sonar-scanner-engine/src/it')
31 files changed, 556 insertions, 110 deletions
diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/analysisdata/AnalysisDataIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/analysisdata/AnalysisDataIT.java new file mode 100644 index 00000000000..94ccedfa946 --- /dev/null +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/analysisdata/AnalysisDataIT.java @@ -0,0 +1,68 @@ +/* + * SonarQube + * Copyright (C) 2009-2025 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.analysisdata; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.util.List; +import org.apache.commons.io.FileUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.testfixtures.log.LogTester; +import org.sonar.core.platform.PluginInfo; +import org.sonar.scanner.mediumtest.AnalysisResult; +import org.sonar.scanner.mediumtest.ScannerMediumTester; +import org.sonar.scanner.protocol.output.ScannerReport; +import org.sonar.xoo.Xoo; +import org.sonar.xoo.XooPlugin; + +public class AnalysisDataIT { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Rule + public LogTester logTester = new LogTester(); + + @Rule + public ScannerMediumTester tester = new ScannerMediumTester() + .registerPlugin(new PluginInfo("xoo").setOrganizationName("SonarSource"), new XooPlugin()) + .addDefaultQProfile("xoo", "Sonar Way"); + + @Test + public void whenScanningWithXoo_thenArchitectureGraphIsInReport() throws Exception { + // given + File projectDir = new File("test-resources/mediumtest/xoo/sample"); + File tmpDir = temp.newFolder(); + FileUtils.copyDirectory(projectDir, tmpDir); + + // when + AnalysisResult result = tester + .newAnalysis(new File(tmpDir, "sonar-project.properties")) + .execute(); + + // then + List<ScannerReport.AnalysisData> analysisData = result.analysisData(); + assertThat(analysisData) + .anyMatch(data -> data.getKey().startsWith("architecture.graph.")); + } +} diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/bootstrap/BootstrapMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/bootstrap/BootstrapMediumIT.java index 5df0d03b111..6cfd6ea5f94 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/bootstrap/BootstrapMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/bootstrap/BootstrapMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -92,6 +92,11 @@ class BootstrapMediumIT { } """))); + sonarqube.stubFor(get("/api/features/list") + .willReturn(okJson(""" + [] + """))); + sonarqube.stubFor(get("/api/metrics/search?ps=500&p=1") .willReturn(okJson(""" { @@ -112,7 +117,7 @@ class BootstrapMediumIT { void should_fail_if_invalid_json_input() { var in = new ByteArrayInputStream("}".getBytes()); - var exitCode = ScannerMain.run(in); + var exitCode = ScannerMain.run(in, System.out); assertThat(exitCode).isEqualTo(1); assertThat(logTester.getLogs(Level.ERROR)).hasSize(1); @@ -123,7 +128,7 @@ class BootstrapMediumIT { @Test void should_warn_if_null_property_key() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"value": "aValueWithoutKey"}]}""".getBytes())); + {"scannerProperties": [{"value": "aValueWithoutKey"}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring property with null key. Value='aValueWithoutKey'"); } @@ -131,7 +136,7 @@ class BootstrapMediumIT { @Test void should_warn_if_null_property_value() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"key": "aKey", "value": null}]}""".getBytes())); + {"scannerProperties": [{"key": "aKey", "value": null}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring property with null value. Key='aKey'"); } @@ -139,7 +144,7 @@ class BootstrapMediumIT { @Test void should_warn_if_not_provided_property_value() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"key": "aKey"}]}""".getBytes())); + {"scannerProperties": [{"key": "aKey"}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring property with null value. Key='aKey'"); } @@ -147,7 +152,7 @@ class BootstrapMediumIT { @Test void should_warn_if_duplicate_property_keys() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"key": "aKey", "value": "aValue"}, {"key": "aKey", "value": "aValue"}]}""".getBytes())); + {"scannerProperties": [{"key": "aKey", "value": "aValue"}, {"key": "aKey", "value": "aValue"}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Duplicated properties. Key='aKey'"); } @@ -155,7 +160,7 @@ class BootstrapMediumIT { @Test void should_warn_if_null_property() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"key": "aKey", "value": "aValue"},]}""".getBytes())); + {"scannerProperties": [{"key": "aKey", "value": "aValue"},]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring null or empty property"); } @@ -163,7 +168,7 @@ class BootstrapMediumIT { @Test void should_warn_if_empty_property() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{}]}""".getBytes())); + {"scannerProperties": [{}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring null or empty property"); } @@ -224,7 +229,7 @@ class BootstrapMediumIT { } private int runScannerEngine(ScannerProperties scannerProperties) { - return ScannerMain.run(new ByteArrayInputStream(scannerProperties.toJson().getBytes())); + return ScannerMain.run(new ByteArrayInputStream(scannerProperties.toJson().getBytes()), System.out); } static class ScannerProperties { diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/branch/BranchMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/branch/BranchMediumIT.java index 31f2bcbfef0..b1322c5af39 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/branch/BranchMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/branch/BranchMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/coverage/CoverageMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/coverage/CoverageMediumIT.java index 2d0c1852d2c..c3ebea00518 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/coverage/CoverageMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/coverage/CoverageMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumIT.java index 188ee29016d..7f2eaab77f1 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/coverage/GenericCoverageMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/cpd/CpdMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/cpd/CpdMediumIT.java index 27df471d1f0..a4ee3d6647d 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/cpd/CpdMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/cpd/CpdMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumIT.java index dc7057f85fc..babeadf518e 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -28,14 +28,21 @@ import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; +import java.util.Map; import java.util.Random; +import java.util.Set; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.slf4j.event.Level; import org.sonar.api.CoreProperties; import org.sonar.api.SonarEdition; @@ -49,17 +56,17 @@ import org.sonar.api.utils.System2; import org.sonar.scanner.mediumtest.AnalysisResult; import org.sonar.scanner.mediumtest.ScannerMediumTester; import org.sonar.scanner.mediumtest.ScannerMediumTester.AnalysisBuilder; +import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.xoo.XooPlugin; import org.sonar.xoo.global.DeprecatedGlobalSensor; import org.sonar.xoo.global.GlobalProjectSensor; import org.sonar.xoo.rule.XooRulesDefinition; -import static java.lang.String.format; import static java.nio.file.Files.createDirectory; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.tuple; -import static org.junit.jupiter.api.Assumptions.assumeFalse; +import static org.assertj.core.api.AssertionsForClassTypes.catchThrowableOfType; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.slf4j.event.Level.DEBUG; @@ -150,7 +157,7 @@ class FileSystemMediumIT { .build()) .execute(); - assertThat(logTester.logs()).contains("2 files indexed"); + assertThat(logTester.logs()).anyMatch(log -> log.startsWith("2 files indexed (done) | time=")); assertThat(logTester.logs()).contains("'src/sample.xoo' generated metadata with charset 'UTF-8'"); assertThat(String.join("\n", logTester.logs())).doesNotContain("'src/sample.java' generated metadata"); } @@ -173,7 +180,7 @@ class FileSystemMediumIT { .build()) .execute(); - assertThat(logTester.logs()).contains("2 files indexed"); + assertThat(logTester.logs()).anyMatch(log -> log.startsWith("2 files indexed (done) | time=")); assertThat(logTester.logs()).contains("'src/sample.xoo' generated metadata with charset 'UTF-8'"); assertThat(logTester.logs()).contains("'src/sample.java' generated metadata with charset 'UTF-8'"); } @@ -200,7 +207,7 @@ class FileSystemMediumIT { .execute(); assertThat(logTester.logs()).containsAnyOf("'src/main/sample.java' indexed with no language", "'src\\main\\sample.java' indexed with no language"); - assertThat(logTester.logs()).contains("3 files indexed"); + assertThat(logTester.logs()).anyMatch(log -> log.startsWith("3 files indexed (done) | time=")); assertThat(logTester.logs()).contains("'src/main/sample.xoo' generated metadata with charset 'UTF-8'"); assertThat(logTester.logs()).doesNotContain("'src/main/sample.java' generated metadata", "'src\\main\\sample.java' generated metadata"); assertThat(logTester.logs()).doesNotContain("'src/test/sample.java' generated metadata", "'src\\test\\sample.java' generated metadata"); @@ -231,7 +238,7 @@ class FileSystemMediumIT { .build()) .execute(); - assertThat(logTester.logs()).contains("1 file indexed"); + assertThat(logTester.logs()).anyMatch(log -> log.startsWith("1 file indexed (done) | time=")); assertThat(logTester.logs()).contains("'src/sample.unknown' indexed with no language"); assertThat(logTester.logs()).contains("'src/sample.unknown' generated metadata with charset 'UTF-8'"); DefaultInputFile inputFile = (DefaultInputFile) result.inputFile("src/sample.unknown"); @@ -456,32 +463,130 @@ class FileSystemMediumIT { } @Test - void analysisFailsSymbolicLinkWithoutTargetIsInTheFolder() throws IOException { - assumeFalse(SystemUtils.IS_OS_WINDOWS); + @DisabledOnOs(OS.WINDOWS) + void analysisDoesNotFailOnBrokenSymlink() throws IOException { + prepareBrokenSymlinkTestScenario(); + + AnalysisBuilder analysisBuilder = tester.newAnalysis().properties(builder.build()); + + assertThat(catchThrowableOfType(Exception.class, analysisBuilder::execute)).isNull(); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void analysisWarnsAndIgnoresBrokenSymlink() throws IOException { + Path link = prepareBrokenSymlinkTestScenario(); + + AnalysisResult result = tester.newAnalysis().properties(builder.build()).execute(); + + String logMessage = String.format("File '%s' is ignored. It is a symbolic link targeting a file that does not exist.", link.toRealPath(LinkOption.NOFOLLOW_LINKS)); + assertThat(logTester.logs(Level.WARN)).contains(logMessage); + InputFile fileA = result.inputFile("src/target_link.xoo"); + assertThat(fileA).isNull(); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void analysisIgnoresSymbolicLinkWithTargetOutsideBaseDir() throws IOException { File srcDir = new File(baseDir, "src"); assertThat(srcDir.mkdir()).isTrue(); - File target = writeFile(srcDir, "target.xoo"); + File otherDir = createDirectory(temp.toPath().resolve("other_dir")).toFile(); + File targetOutside = writeFile(otherDir, "target_outside.xoo"); + Path link = Paths.get(srcDir.getPath(), "target_link.xoo"); + Files.createSymbolicLink(link, targetOutside.toPath()); + + AnalysisResult result = tester.newAnalysis().properties(builder.build()).execute(); + + String logMessage = String.format("File '%s' is ignored. It is a symbolic link targeting a file not located in project basedir.", link.toRealPath(LinkOption.NOFOLLOW_LINKS)); + assertThat(logTester.logs(Level.WARN)).contains(logMessage); + InputFile fileA = result.inputFile("src/target_link.xoo"); + assertThat(fileA).isNull(); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void analysisIgnoresSymbolicLinkWithRelativeTargetOutsideBaseDir() throws IOException { + File srcDir = new File(baseDir, "src"); + assertThat(srcDir.mkdir()).isTrue(); + + File otherDir = createDirectory(temp.toPath().resolve("other_dir")).toFile(); + writeFile(otherDir, "target_outside.xoo"); + + Path linkPath = srcDir.toPath().resolve("target_link"); + Path link = Files.createSymbolicLink(linkPath, Paths.get("../../other_dir/target_outside.xoo")); + + tester.newAnalysis().properties(builder.build()).execute(); + + String logMessage = String.format("File '%s' is ignored. It is a symbolic link targeting a file not located in project basedir.", link.toRealPath(LinkOption.NOFOLLOW_LINKS)); + assertThat(logTester.logs(Level.WARN)).contains(logMessage); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void analysisIgnoresSymbolicLinkWithTargetOutsideModule() throws IOException { + File srcDirA = createModuleWithSubdirectory("module_a", "src"); + File srcDirB = createModuleWithSubdirectory("module_b", "src"); + + File target = writeFile(srcDirA, "target.xoo", "Sample xoo\ncontent"); + Path link = Paths.get(srcDirB.getPath(), "target_link.xoo"); Files.createSymbolicLink(link, target.toPath()); - Files.delete(target.toPath()); - AnalysisBuilder analysis = tester.newAnalysis() - .properties(builder.build()); + builder.put("sonar.modules", "module_a,module_b"); - assertThatThrownBy(analysis::execute) - .isExactlyInstanceOf(IllegalStateException.class) - .hasMessageEndingWith(format("Unable to read file %s", link)); + AnalysisResult result = tester.newAnalysis().properties(builder.build()).execute(); + + String logMessage = String.format("File '%s' is ignored. It is a symbolic link targeting a file not located in module basedir.", link.toRealPath(LinkOption.NOFOLLOW_LINKS)); + assertThat(logTester.logs(Level.INFO)).contains(logMessage); + InputFile fileA = result.inputFile("module_b/src/target_link.xoo"); + assertThat(fileA).isNull(); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void analysisIgnoresSymbolicLinkWithRelativeTargetOutsideModule() throws IOException { + File srcA = createModuleWithSubdirectory("module_a", "src"); + File srcB = createModuleWithSubdirectory("module_b", "src"); + + Path target = srcB.toPath().resolve("target.xoo"); + FileUtils.write(target.toFile(), "Sample xoo\ncontent", StandardCharsets.UTF_8); + Path link = srcA.toPath().resolve("target_link"); + Files.createSymbolicLink(link, Paths.get("../../module_b/src/target.xoo")); + + builder.put("sonar.modules", "module_a,module_b"); + + AnalysisResult result = tester.newAnalysis().properties(builder.build()).execute(); + + String logMessage = String.format("File '%s' is ignored. It is a symbolic link targeting a file not located in module basedir.", link.toRealPath(LinkOption.NOFOLLOW_LINKS)); + assertThat(logTester.logs(Level.INFO)).contains(logMessage); + InputFile fileA = result.inputFile("module_b/src/target.xoo"); + assertThat(fileA).isNotNull(); + } + + @Test + @DisabledOnOs(OS.WINDOWS) + void analysisDoesNotIgnoreSymbolicLinkWithRelativePath() throws IOException { + File src = createModuleWithSubdirectory("module_a", "src"); + Path target = src.toPath().resolve("target.xoo"); + FileUtils.write(target.toFile(), "Sample xoo\ncontent", StandardCharsets.UTF_8); + Path link = src.toPath().resolve("target_link"); + Files.createSymbolicLink(link, Paths.get("target.xoo")); + + builder.put("sonar.modules", "module_a"); + + AnalysisResult result = tester.newAnalysis().properties(builder.build()).execute(); + + InputFile targetFile = result.inputFile("module_a/src/target.xoo"); + assertThat(targetFile).isNotNull(); + String logMessage = String.format("File '%s' is ignored. It is a symbolic link targeting a file that does not exist.", link.toRealPath(LinkOption.NOFOLLOW_LINKS)); + assertThat(logTester.logs(Level.WARN)).doesNotContain(logMessage); } @Test void test_inclusions_on_multi_modules() throws IOException { - File baseDirModuleA = new File(baseDir, "moduleA"); - File baseDirModuleB = new File(baseDir, "moduleB"); - File srcDirA = new File(baseDirModuleA, "tests"); - assertThat(srcDirA.mkdirs()).isTrue(); - File srcDirB = new File(baseDirModuleB, "tests"); - assertThat(srcDirB.mkdirs()).isTrue(); + File srcDirA = createModuleWithSubdirectory("moduleA", "tests"); + File srcDirB = createModuleWithSubdirectory("moduleB", "tests"); writeFile(srcDirA, "sampleTestA.xoo", "Sample xoo\ncontent"); writeFile(srcDirB, "sampleTestB.xoo", "Sample xoo\ncontent"); @@ -522,12 +627,8 @@ class FileSystemMediumIT { @Test void test_module_level_inclusions_override_parent_on_multi_modules() throws IOException { - File baseDirModuleA = new File(baseDir, "moduleA"); - File baseDirModuleB = new File(baseDir, "moduleB"); - File srcDirA = new File(baseDirModuleA, "src"); - assertThat(srcDirA.mkdirs()).isTrue(); - File srcDirB = new File(baseDirModuleB, "src"); - assertThat(srcDirB.mkdirs()).isTrue(); + File srcDirA = createModuleWithSubdirectory("moduleA", "src"); + File srcDirB = createModuleWithSubdirectory("moduleB", "src"); writeFile(srcDirA, "sampleA.xoo", "Sample xoo\ncontent"); writeFile(srcDirB, "sampleB.xoo", "Sample xoo\ncontent"); @@ -559,12 +660,8 @@ class FileSystemMediumIT { @Test void warn_user_for_outdated_scanner_side_inherited_exclusions_for_multi_module_project() throws IOException { - File baseDirModuleA = new File(baseDir, "moduleA"); - File baseDirModuleB = new File(baseDir, "moduleB"); - File srcDirA = new File(baseDirModuleA, "src"); - assertThat(srcDirA.mkdirs()).isTrue(); - File srcDirB = new File(baseDirModuleB, "src"); - assertThat(srcDirB.mkdirs()).isTrue(); + File srcDirA = createModuleWithSubdirectory("moduleA", "src"); + File srcDirB = createModuleWithSubdirectory("moduleB", "src"); writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); @@ -592,12 +689,8 @@ class FileSystemMediumIT { @Test void support_global_server_side_exclusions_for_multi_module_project() throws IOException { - File baseDirModuleA = new File(baseDir, "moduleA"); - File baseDirModuleB = new File(baseDir, "moduleB"); - File srcDirA = new File(baseDirModuleA, "src"); - assertThat(srcDirA.mkdirs()).isTrue(); - File srcDirB = new File(baseDirModuleB, "src"); - assertThat(srcDirB.mkdirs()).isTrue(); + File srcDirA = createModuleWithSubdirectory("moduleA", "src"); + File srcDirB = createModuleWithSubdirectory("moduleB", "src"); writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); @@ -622,12 +715,8 @@ class FileSystemMediumIT { @Test void support_global_server_side_global_exclusions_for_multi_module_project() throws IOException { - File baseDirModuleA = new File(baseDir, "moduleA"); - File baseDirModuleB = new File(baseDir, "moduleB"); - File srcDirA = new File(baseDirModuleA, "src"); - assertThat(srcDirA.mkdirs()).isTrue(); - File srcDirB = new File(baseDirModuleB, "src"); - assertThat(srcDirB.mkdirs()).isTrue(); + File srcDirA = createModuleWithSubdirectory("moduleA", "src"); + File srcDirB = createModuleWithSubdirectory("moduleB", "src"); writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); @@ -652,12 +741,8 @@ class FileSystemMediumIT { @Test void warn_user_for_outdated_server_side_inherited_exclusions_for_multi_module_project() throws IOException { - File baseDirModuleA = new File(baseDir, "moduleA"); - File baseDirModuleB = new File(baseDir, "moduleB"); - File srcDirA = new File(baseDirModuleA, "src"); - assertThat(srcDirA.mkdirs()).isTrue(); - File srcDirB = new File(baseDirModuleB, "src"); - assertThat(srcDirB.mkdirs()).isTrue(); + File srcDirA = createModuleWithSubdirectory("moduleA", "src"); + File srcDirB = createModuleWithSubdirectory("moduleB", "src"); writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); @@ -930,12 +1015,8 @@ class FileSystemMediumIT { @Test void log_all_exclusions_properties_per_modules() throws IOException { - File baseDirModuleA = new File(baseDir, "moduleA"); - File baseDirModuleB = new File(baseDir, "moduleB"); - File srcDirA = new File(baseDirModuleA, "src"); - assertThat(srcDirA.mkdirs()).isTrue(); - File srcDirB = new File(baseDirModuleB, "src"); - assertThat(srcDirB.mkdirs()).isTrue(); + File srcDirA = createModuleWithSubdirectory("moduleA", "src"); + File srcDirB = createModuleWithSubdirectory("moduleB", "src"); writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); @@ -964,7 +1045,7 @@ class FileSystemMediumIT { " Excluded sources for coverage: **/coverage.exclusions", " Excluded sources for duplication: **/cpd.exclusions", "Indexing files of module 'moduleA'", - " Base dir: " + baseDirModuleA.toPath().toRealPath(LinkOption.NOFOLLOW_LINKS), + " Base dir: " + srcDirA.toPath().getParent().toRealPath(LinkOption.NOFOLLOW_LINKS), " Included sources: **/global.inclusions", " Excluded sources: **/global.exclusions, **/global.test.inclusions", " Included tests: **/global.test.inclusions", @@ -972,7 +1053,7 @@ class FileSystemMediumIT { " Excluded sources for coverage: **/coverage.exclusions", " Excluded sources for duplication: **/cpd.exclusions", "Indexing files of module 'moduleB'", - " Base dir: " + baseDirModuleB.toPath().toRealPath(LinkOption.NOFOLLOW_LINKS), + " Base dir: " + srcDirB.toPath().getParent().toRealPath(LinkOption.NOFOLLOW_LINKS), " Included sources: **/global.inclusions", " Excluded sources: **/global.exclusions, **/global.test.inclusions", " Included tests: **/global.test.inclusions", @@ -1098,7 +1179,7 @@ class FileSystemMediumIT { .build()) .execute(); - assertThat(logTester.logs()).contains("1 file indexed"); + assertThat(logTester.logs()).anyMatch(log -> log.startsWith("1 file indexed (done) | time=")); assertThat(result.inputFile("sample.xoo")).isNotNull(); } @@ -1265,6 +1346,200 @@ class FileSystemMediumIT { .hasMessageEndingWith("Failed to preprocess files"); } + @ParameterizedTest + @ValueSource(booleans = { + true, + false + }) + void shouldScanAndAnalyzeAllHiddenFiles(boolean setHiddenFileScanningExplicitly) throws IOException { + prepareHiddenFileProject(); + File projectDir = new File("test-resources/mediumtest/xoo/sample-with-hidden-files"); + AnalysisBuilder analysisBuilder = tester + .addRules(new XooRulesDefinition()) + .addActiveRule("xoo", "OneIssuePerFile", null, "Issue Per File", "MAJOR", null, "xoo") + .newAnalysis(new File(projectDir, "sonar-project.properties")) + .property("sonar.exclusions", "**/*.ignore") + .property("sonar.oneIssuePerFile.enableHiddenFileProcessing", "true"); + + if (setHiddenFileScanningExplicitly) { + // default is assumed to be false, here we set it explicitly + analysisBuilder.property("sonar.scanner.excludeHiddenFiles", "false"); + } + + AnalysisResult result = analysisBuilder.execute(); + + for (Map.Entry<String, Boolean> pathToHiddenStatus : hiddenFileProjectExpectedHiddenStatus().entrySet()) { + String filePath = pathToHiddenStatus.getKey(); + boolean expectedIsHidden = pathToHiddenStatus.getValue(); + assertHiddenFileScan(result, filePath, expectedIsHidden, true); + // we expect the sensor to process all files, regardless of visibility + assertFileIssue(result, filePath, true); + } + assertThat(result.inputFiles()).hasSize(10); + } + + @Test + void shouldScanAllFilesAndOnlyAnalyzeNonHiddenFiles() throws IOException { + prepareHiddenFileProject(); + File projectDir = new File("test-resources/mediumtest/xoo/sample-with-hidden-files"); + AnalysisResult result = tester + .addRules(new XooRulesDefinition()) + .addActiveRule("xoo", "OneIssuePerFile", null, "Issue Per File", "MAJOR", null, "xoo") + .newAnalysis(new File(projectDir, "sonar-project.properties")) + .property("sonar.exclusions", "**/*.ignore") + .property("sonar.oneIssuePerFile.enableHiddenFileProcessing", "false") + .execute(); + + for (Map.Entry<String, Boolean> pathToHiddenStatus : hiddenFileProjectExpectedHiddenStatus().entrySet()) { + String filePath = pathToHiddenStatus.getKey(); + boolean expectedHiddenStatus = pathToHiddenStatus.getValue(); + assertHiddenFileScan(result, filePath, expectedHiddenStatus, true); + // sensor should not process hidden files, we only expect issues on non-hidden files + assertFileIssue(result, filePath, !expectedHiddenStatus); + } + assertThat(result.inputFiles()).hasSize(10); + } + + @ParameterizedTest + @ValueSource(booleans = { + true, + false + }) + void shouldNotScanAndAnalyzeHiddenFilesWhenHiddenFileScanningIsDisabled(boolean sensorHiddenFileProcessingEnabled) throws IOException { + prepareHiddenFileProject(); + File projectDir = new File("test-resources/mediumtest/xoo/sample-with-hidden-files"); + AnalysisResult result = tester + .addRules(new XooRulesDefinition()) + .addActiveRule("xoo", "OneIssuePerFile", null, "Issue Per File", "MAJOR", null, "xoo") + .newAnalysis(new File(projectDir, "sonar-project.properties")) + .property("sonar.exclusions", "**/*.ignore") + .property("sonar.scanner.excludeHiddenFiles", "true") + // hidden files are not scanned, so issues can't be raised on them regardless if the sensor wants to process them + .property("sonar.oneIssuePerFile.enableHiddenFileProcessing", String.valueOf(sensorHiddenFileProcessingEnabled)) + .execute(); + + for (Map.Entry<String, Boolean> pathToHiddenStatus : hiddenFileProjectExpectedHiddenStatus().entrySet()) { + String filePath = pathToHiddenStatus.getKey(); + boolean expectedHiddenStatus = pathToHiddenStatus.getValue(); + assertHiddenFileScan(result, filePath, expectedHiddenStatus, false); + if (!expectedHiddenStatus) { + assertFileIssue(result, filePath, true); + } + } + assertThat(result.inputFiles()).hasSize(1); + } + + @Test + void hiddenFilesAssignedToALanguageShouldNotBePublishedByDefault() throws IOException { + tester + .addRules(new XooRulesDefinition()); + + File srcDir = new File(baseDir, "src"); + assertThat(srcDir.mkdir()).isTrue(); + + File hiddenFile = writeFile(srcDir, ".xoo", "Sample xoo\ncontent"); + setFileAsHiddenOnWindows(hiddenFile.toPath()); + File hiddenFileWithoutLanguage = writeFile(srcDir, ".bar", "Sample bar\ncontent"); + setFileAsHiddenOnWindows(hiddenFileWithoutLanguage.toPath()); + writeFile(srcDir, "file.xoo", "Sample xoo\ncontent"); + + AnalysisResult result = tester.newAnalysis() + .properties(builder + .put("sonar.sources", "src") + .build()) + .execute(); + + DefaultInputFile hiddenInputFile = (DefaultInputFile) result.inputFile("src/.xoo"); + + assertThat(hiddenInputFile).isNotNull(); + assertThat(hiddenInputFile.isPublished()).isFalse(); + assertThatThrownBy(() -> result.getReportComponent(hiddenInputFile)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Unable to find report for component"); + + DefaultInputFile hiddenInputFileWithoutLanguage = (DefaultInputFile) result.inputFile("src/.bar"); + assertThat(hiddenInputFileWithoutLanguage).isNotNull(); + assertThat(hiddenInputFileWithoutLanguage.isPublished()).isFalse(); + assertThatThrownBy(() -> result.getReportComponent(hiddenInputFileWithoutLanguage)) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Unable to find report for component"); + + DefaultInputFile visibleInputFile = (DefaultInputFile) result.inputFile("src/file.xoo"); + assertThat(visibleInputFile).isNotNull(); + assertThat(visibleInputFile.isPublished()).isTrue(); + assertThat(result.getReportComponent(visibleInputFile)).isNotNull(); + } + + @Test + void shouldDetectHiddenFilesFromMultipleModules() throws IOException { + File srcDirA = createModuleWithSubdirectory("moduleA", "src"); + File srcDirB = createModuleWithSubdirectory("moduleB", "src"); + + File fileModuleA = writeFile(srcDirA, ".xoo", "Sample xoo\ncontent"); + setFileAsHiddenOnWindows(fileModuleA.toPath()); + File fileModuleB = writeFile(srcDirB, ".xoo", "Sample xoo\ncontent"); + setFileAsHiddenOnWindows(fileModuleB.toPath()); + + AnalysisResult result = tester.newAnalysis() + .properties(ImmutableMap.<String, String>builder() + .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) + .put("sonar.projectKey", "com.foo.project") + .put("sonar.sources", "src") + .put("sonar.modules", "moduleA,moduleB") + .build()) + .execute(); + + assertHiddenFileScan(result, "moduleA/src/.xoo", true, true); + assertHiddenFileScan(result, "moduleB/src/.xoo", true, true); + } + + @Test + void shouldScanAndAnalyzeAllHiddenFilesWithRespectToExclusions() throws IOException { + prepareHiddenFileProject(); + File projectDir = new File("test-resources/mediumtest/xoo/sample-with-hidden-files"); + + + AnalysisResult result = tester + .addRules(new XooRulesDefinition()) + .addActiveRule("xoo", "OneIssuePerFile", null, "Issue Per File", "MAJOR", null, "xoo") + .newAnalysis(new File(projectDir, "sonar-project.properties")) + .property("sonar.scm.provider", "xoo") + .property("sonar.oneIssuePerFile.enableHiddenFileProcessing", "true") + .property("sonar.exclusions", "**/.nestedHidden/**,**/*.ignore") + .execute(); + + Set<String> excludedFiles = Set.of( + // sonar.exclusions + "xources/.hidden/.nestedHidden/.xoo", + "xources/.hidden/.nestedHidden/Class.xoo", + "xources/.hidden/.nestedHidden/visibleInHiddenFolder/.xoo", + "xources/.hidden/.nestedHidden/visibleInHiddenFolder/.xoo.ignore", + "xources/.hidden/.nestedHidden/visibleInHiddenFolder/Class.xoo", + // scm ignore + "xources/nonHidden/.hiddenInVisibleFolder/.xoo"); + + for (Map.Entry<String, Boolean> pathToHiddenStatus : hiddenFileProjectExpectedHiddenStatus().entrySet()) { + String filePath = pathToHiddenStatus.getKey(); + boolean expectedIsHidden = pathToHiddenStatus.getValue(); + + if (excludedFiles.contains(filePath)) { + assertThat(result.inputFile(filePath)).isNull(); + } else { + assertHiddenFileScan(result, filePath, expectedIsHidden, true); + // we expect the sensor to process all non-excluded files, regardless of visibility + assertFileIssue(result, filePath, true); + } + } + assertThat(result.inputFiles()).hasSize(5); + } + + private File createModuleWithSubdirectory(String moduleName, String subDirName) { + File moduleBaseDir = new File(baseDir, moduleName); + File srcDir = moduleBaseDir.toPath().resolve(subDirName).toFile(); + assertThat(srcDir.mkdirs()).isTrue(); + return srcDir; + } + private static void assertAnalysedFiles(AnalysisResult result, String... files) { assertThat(result.inputFiles().stream().map(InputFile::toString).toList()).contains(files); } @@ -1291,4 +1566,81 @@ class FileSystemMediumIT { return file; } + private Path prepareBrokenSymlinkTestScenario() throws IOException { + File srcDir = new File(baseDir, "src"); + assertThat(srcDir.mkdir()).isTrue(); + + File target = writeFile(srcDir, "target.xoo"); + Path link = Paths.get(srcDir.getPath(), "target_link.xoo"); + Files.createSymbolicLink(link, target.toPath()); + Files.delete(target.toPath()); + + return link; + } + + private Map<String, Boolean> hiddenFileProjectExpectedHiddenStatus() { + return Map.of( + "xources/.hidden/.xoo", true, + "xources/.hidden/Class.xoo", true, + "xources/.hidden/.nestedHidden/.xoo", true, + "xources/.hidden/.nestedHidden/Class.xoo", true, + "xources/.hidden/.nestedHidden/visibleInHiddenFolder/.xoo", true, + "xources/.hidden/.nestedHidden/visibleInHiddenFolder/Class.xoo", true, + "xources/nonHidden/.xoo", true, + "xources/nonHidden/Class.xoo", false, + "xources/nonHidden/.hiddenInVisibleFolder/.xoo", true, + "xources/nonHidden/.hiddenInVisibleFolder/Class.xoo", true); + } + + private static void prepareHiddenFileProject() throws IOException { + if (!SystemUtils.IS_OS_WINDOWS) { + return; + } + + // On Windows, we need to set the hidden attribute on the file system + Set<String> dirAndFilesToHideOnWindows = Set.of( + "xources/.hidden", + "xources/.hidden/.xoo", + "xources/.hidden/.nestedHidden", + "xources/.hidden/.nestedHidden/.xoo", + "xources/.hidden/.nestedHidden/visibleInHiddenFolder/.xoo", + "xources/nonHidden/.xoo", + "xources/nonHidden/.hiddenInVisibleFolder", + "xources/nonHidden/.hiddenInVisibleFolder/.xoo"); + + for (String path : dirAndFilesToHideOnWindows) { + Path pathFromResources = Path.of("test-resources/mediumtest/xoo/sample-with-hidden-files", path); + setFileAsHiddenOnWindows(pathFromResources); + } + } + + private static void setFileAsHiddenOnWindows(Path path) throws IOException { + if (SystemUtils.IS_OS_WINDOWS) { + Files.setAttribute(path, "dos:hidden", true, LinkOption.NOFOLLOW_LINKS); + } + } + + private static void assertHiddenFileScan(AnalysisResult result, String filePath, boolean expectedHiddenStatus, boolean hiddenFilesShouldBeScanned) { + InputFile file = result.inputFile(filePath); + + if (!hiddenFilesShouldBeScanned && expectedHiddenStatus) { + assertThat(file).isNull(); + } else { + assertThat(file).withFailMessage(String.format("File \"%s\" was not analyzed", filePath)).isNotNull(); + assertThat(file.isHidden()) + .withFailMessage(String.format("Expected file \"%s\" hidden status to be \"%s\", however was \"%s\"", filePath, expectedHiddenStatus, file.isHidden())) + .isEqualTo(expectedHiddenStatus); + } + } + + private static void assertFileIssue(AnalysisResult result, String filePath, boolean expectToHaveIssue) { + InputFile file = result.inputFile(filePath); + assertThat(file).isNotNull(); + List<ScannerReport.Issue> issues = result.issuesFor(file); + if (expectToHaveIssue) { + assertThat(issues).hasSize(1); + } else { + assertThat(issues).isEmpty(); + } + } } diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/NoLanguagesPluginsMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/NoLanguagesPluginsMediumIT.java index db2d45e5904..a18ba763ab8 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/NoLanguagesPluginsMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/NoLanguagesPluginsMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/ProjectBuilderMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/ProjectBuilderMediumIT.java index ca7cc3134be..1041bd4219a 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/ProjectBuilderMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/fs/ProjectBuilderMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/highlighting/HighlightingMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/highlighting/HighlightingMediumIT.java index 87d2350f476..11e190911a3 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/highlighting/HighlightingMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/highlighting/HighlightingMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/ChecksMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/ChecksMediumIT.java index 035267f43fe..8b1d525c9fe 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/ChecksMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/ChecksMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/ExternalIssuesMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/ExternalIssuesMediumIT.java index a660aa0ec7d..d2e70483145 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/ExternalIssuesMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/ExternalIssuesMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesMediumIT.java index 2ae6379db66..74742eea9d0 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesOnDirMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesOnDirMediumIT.java index d000e03239d..0cbd5e1e340 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesOnDirMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesOnDirMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesOnModuleMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesOnModuleMediumIT.java index 0edc7d06e97..63588eff056 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesOnModuleMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/IssuesOnModuleMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/MultilineIssuesMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/MultilineIssuesMediumIT.java index 1a3535d858d..ecfabaad3b4 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/MultilineIssuesMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/MultilineIssuesMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/PreviewMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/PreviewMediumIT.java index f28dc028da1..1ad2bb24e13 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/PreviewMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/issues/PreviewMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/log/ExceptionHandlingMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/log/ExceptionHandlingMediumIT.java index 5b7cd7d631b..b5dbc404cbe 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/log/ExceptionHandlingMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/log/ExceptionHandlingMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/log/LogListenerIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/log/LogListenerIT.java index e574be69487..588181a456d 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/log/LogListenerIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/log/LogListenerIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -124,7 +124,7 @@ public class LogListenerIT { } Matcher matcher = simpleTimePattern.matcher(msg); - assertThat(matcher.find()).isFalse(); + assertThat(matcher.find()).as("Offending log message: " + msg).isFalse(); } @Test diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumIT.java index 7c43370d423..727d1dc5a58 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/measures/MeasuresMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/optionalplugins/OptionalPluginsMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/optionalplugins/OptionalPluginsMediumIT.java index e618719d72d..54b71f52d23 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/optionalplugins/OptionalPluginsMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/optionalplugins/OptionalPluginsMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/properties/PropertiesMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/properties/PropertiesMediumIT.java index fe54129e805..0e615e9b628 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/properties/PropertiesMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/properties/PropertiesMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/branch/DeprecatedBranchMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/properties/UnsupportedPropertiesMediumIT.java index a8ccd819f7d..bf05151bb3c 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/branch/DeprecatedBranchMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/properties/UnsupportedPropertiesMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -17,7 +17,7 @@ * 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.branch; +package org.sonar.scanner.mediumtest.properties; import com.google.common.collect.ImmutableMap; import java.io.File; @@ -33,9 +33,10 @@ import org.sonar.scanner.mediumtest.ScannerMediumTester; import org.sonar.xoo.XooPlugin; import org.sonar.xoo.rule.XooRulesDefinition; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThatThrownBy; -class DeprecatedBranchMediumIT { +class UnsupportedPropertiesMediumIT { @TempDir private File temp; @@ -69,20 +70,40 @@ class DeprecatedBranchMediumIT { @Test void scanProjectWithBranch() throws IOException { - File srcDir = new File(baseDir, "src"); - srcDir.mkdir(); + prepareContent(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent"); - - assertThatThrownBy(() -> tester.newAnalysis() + ScannerMediumTester.AnalysisBuilder analysisBuilder = tester.newAnalysis() .properties(ImmutableMap.<String, String>builder() .putAll(commonProps) .put("sonar.branch", "branch") - .build()) - .execute()) + .build()); + + assertThatThrownBy(analysisBuilder::execute) .isInstanceOf(MessageException.class) .hasMessage("The 'sonar.branch' parameter is no longer supported. You should stop using it. " + "Branch analysis is available in Developer Edition and above. See https://www.sonarsource.com/plans-and-pricing/developer/ for more information."); } + + @Test + void scanProjectWithPassword() throws IOException { + prepareContent(); + + ScannerMediumTester.AnalysisBuilder analysisBuilder = tester.newAnalysis() + .properties(ImmutableMap.<String, String>builder() + .putAll(commonProps) + .put("sonar.password", "anything") + .build()); + + assertThatThrownBy(analysisBuilder::execute) + .isInstanceOf(MessageException.class) + .hasMessage("The property 'sonar.password' is no longer supported. Please pass a token with the 'sonar.token' property instead."); + } + + private void prepareContent() throws IOException { + File srcDir = new File(baseDir, "src"); + srcDir.mkdir(); + + File xooFile = new File(srcDir, "sample.xoo"); + FileUtils.write(xooFile, "Sample xoo\ncontent", UTF_8); + } } diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/scm/ScmMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/scm/ScmMediumIT.java index 59ee1ee8f81..904e09cc5c5 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/scm/ScmMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/scm/ScmMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -241,7 +241,7 @@ public class ScmMediumIT { assertThat(getChangesets(baseDir, NO_BLAME_SCM_ON_SERVER_XOO)).isNull(); // 5 .xoo files + 3 .scm files, but only 4 marked for publishing. 1 file is SAME so not included in the total - assertThat(logTester.logs()).containsSubsequence("8 files indexed"); + assertThat(logTester.logs()).anyMatch(s -> s.startsWith("8 files indexed (done) | time=")); assertThat(logTester.logs()).containsSubsequence("SCM Publisher 4 source files to be analyzed"); assertThat(logTester.logs().stream().anyMatch(s -> Pattern.matches("SCM Publisher 3/4 source files have been analyzed \\(done\\) \\| time=[0-9]+ms", s))).isTrue(); assertThat(logTester.logs()).containsSubsequence(MISSING_BLAME_INFORMATION_FOR_THE_FOLLOWING_FILES, " * src/no_blame_scm_on_server.xoo"); diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/symbol/SymbolMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/symbol/SymbolMediumIT.java index 27a2bec551e..aad8278c66b 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/symbol/SymbolMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/symbol/SymbolMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/tasks/TasksMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/tasks/TasksMediumIT.java index 117a5c18761..22e58f2cdc3 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/tasks/TasksMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/tasks/TasksMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/tests/GenericTestExecutionMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/tests/GenericTestExecutionMediumIT.java index a6393e54b2c..50a05bb5438 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/tests/GenericTestExecutionMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/tests/GenericTestExecutionMediumIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnBlameCommandIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnBlameCommandIT.java index 808b98537e5..b86dc641e4d 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnBlameCommandIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnBlameCommandIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnTester.java b/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnTester.java index 43df806b0de..b5ba8d5c59d 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnTester.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnTester.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnTesterIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnTesterIT.java index 09093e7fe95..47b21c98399 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnTesterIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scm/svn/SvnTesterIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/it/java/testutils/TestUtils.java b/sonar-scanner-engine/src/it/java/testutils/TestUtils.java index 9240d366256..838881854e6 100644 --- a/sonar-scanner-engine/src/it/java/testutils/TestUtils.java +++ b/sonar-scanner-engine/src/it/java/testutils/TestUtils.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or |