diff options
Diffstat (limited to 'sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java')
-rw-r--r-- | sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java | 173 |
1 files changed, 103 insertions, 70 deletions
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java index 597fafa833c..33cf6c146e6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java @@ -27,7 +27,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Map; -import java.util.Optional; import org.apache.commons.lang3.SystemUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -36,6 +35,7 @@ import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.io.TempDir; import org.mockito.MockedStatic; import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.scm.ScmProvider; import org.sonar.api.platform.Server; @@ -44,6 +44,7 @@ import org.sonar.api.utils.System2; import org.sonar.core.util.ProcessWrapperFactory; import org.sonar.scanner.config.DefaultConfiguration; import org.sonar.scanner.repository.TelemetryCache; +import org.sonar.scanner.scan.filesystem.ProjectExclusionFilters; import org.sonar.scanner.scm.ScmConfiguration; import org.sonar.scm.git.GitScmProvider; import org.sonar.scm.git.JGitUtils; @@ -69,6 +70,7 @@ class CliServiceTest { ProcessWrapperFactory processWrapperFactory = mock(ProcessWrapperFactory.class, CALLS_REAL_METHODS); private MockedStatic<JGitUtils> jGitUtilsMock; DefaultConfiguration configuration = mock(DefaultConfiguration.class); + ProjectExclusionFilters projectExclusionFilters = mock(ProjectExclusionFilters.class); private CliService underTest; @@ -86,9 +88,11 @@ class CliServiceTest { jGitUtilsMock.when(() -> JGitUtils.getAllIgnoredPaths(any(Path.class))).thenReturn(List.of("ignored.txt")); when(server.getVersion()).thenReturn("1.0.0"); logTester.setLevel(INFO); - when(configuration.getBoolean("sonar.sca.debug")).thenReturn(Optional.of(true)); + when(projectExclusionFilters.getExclusionsConfig(InputFile.Type.MAIN)).thenReturn(new String[0]); + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[0]); + when(configuration.getStringArray(CliService.LEGACY_SCA_EXCLUSIONS_KEY)).thenReturn(new String[0]); - underTest = new CliService(processWrapperFactory, telemetryCache, System2.INSTANCE, server, scmConfiguration); + underTest = new CliService(processWrapperFactory, telemetryCache, System2.INSTANCE, server, scmConfiguration, projectExclusionFilters); } @AfterEach @@ -99,57 +103,55 @@ class CliServiceTest { } @Test - void generateZip_shouldCallProcessCorrectly_andRegisterTelemetry() throws IOException, URISyntaxException { + void generateManifestsArchive_shouldCallProcessCorrectly_andRegisterTelemetry() throws IOException, URISyntaxException { assertThat(rootModuleDir.resolve("test_file").toFile().createNewFile()).isTrue(); - when(configuration.getProperties()).thenReturn(Map.of("sonar.sca.recursiveManifestSearch", "true", CliService.EXCLUDED_MANIFESTS_PROP_KEY, "foo,bar,baz/**")); - when(configuration.get("sonar.sca.recursiveManifestSearch")).thenReturn(Optional.of("true")); - when(configuration.getStringArray(CliService.EXCLUDED_MANIFESTS_PROP_KEY)).thenReturn(new String[] {"foo", "bar", "baz/**"}); + when(configuration.getProperties()).thenReturn(Map.of(CliService.SCA_EXCLUSIONS_KEY, "foo,bar,baz/**")); + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"foo", "bar", "baz/**"}); - File producedZip = underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + File producedArchive = underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); - assertThat(producedZip).exists(); + assertThat(producedArchive).exists(); var expectedArguments = List.of( "projects", "save-lockfiles", - "--zip", - "--zip-filename", - rootInputModule.getWorkDir().resolve("dependency-files.zip").toString(), + "--xz", + "--xz-filename", + rootInputModule.getWorkDir().resolve("dependency-files.tar.xz").toString(), "--directory", rootInputModule.getBaseDir().toString(), + "--recursive", "--exclude", - "foo,bar,baz/**,ignored.txt,.scannerwork/**", - "--debug"); + "foo,bar,baz/**,ignored.txt,.scannerwork/**"); assertThat(logTester.logs(INFO)) .contains("Arguments Passed In: " + String.join(" ", expectedArguments)) .contains("TIDELIFT_SKIP_UPDATE_CHECK=1") .contains("TIDELIFT_ALLOW_MANIFEST_FAILURES=1") - .contains("TIDELIFT_RECURSIVE_MANIFEST_SEARCH=true") - .contains("Generated manifests zip file: " + producedZip.getName()); + .contains("Generated manifests archive file: " + producedArchive.getName()); assertThat(telemetryCache.getAll()).containsKey("scanner.sca.execution.cli.duration").isNotNull(); assertThat(telemetryCache.getAll()).containsEntry("scanner.sca.execution.cli.success", "true"); } @Test - void generateZip_whenDebugLogLevelAndScaDebugNotEnabled_shouldWriteDebugLogsToDebugStream() throws IOException, URISyntaxException { + void generateManifestsArchive_whenDebugLogLevelAndScaDebugNotEnabled_shouldWriteDebugLogsToDebugStream() throws IOException, URISyntaxException { logTester.setLevel(DEBUG); - when(configuration.getBoolean("sonar.sca.debug")).thenReturn(Optional.of(false)); assertThat(rootModuleDir.resolve("test_file").toFile().createNewFile()).isTrue(); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); var expectedArguments = List.of( "projects", "save-lockfiles", - "--zip", - "--zip-filename", - rootInputModule.getWorkDir().resolve("dependency-files.zip").toString(), + "--xz", + "--xz-filename", + rootInputModule.getWorkDir().resolve("dependency-files.tar.xz").toString(), "--directory", rootInputModule.getBaseDir().toString(), + "--recursive", "--exclude", "ignored.txt,.scannerwork/**", "--debug"); @@ -159,32 +161,30 @@ class CliServiceTest { } @Test - void generateZip_whenScaDebugEnabled_shouldWriteDebugLogsToInfoStream() throws IOException, URISyntaxException { - when(configuration.getBoolean("sonar.sca.debug")).thenReturn(Optional.of(true)); - + void generateManifestsArchive_whenScaDebugEnabled_shouldWriteDebugLogsToInfoStream() throws IOException, URISyntaxException { assertThat(rootModuleDir.resolve("test_file").toFile().createNewFile()).isTrue(); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); var expectedArguments = List.of( "projects", "save-lockfiles", - "--zip", - "--zip-filename", - rootInputModule.getWorkDir().resolve("dependency-files.zip").toString(), + "--xz", + "--xz-filename", + rootInputModule.getWorkDir().resolve("dependency-files.tar.xz").toString(), "--directory", rootInputModule.getBaseDir().toString(), + "--recursive", "--exclude", - "ignored.txt,.scannerwork/**", - "--debug"); + "ignored.txt,.scannerwork/**"); assertThat(logTester.logs(INFO)) .contains("Arguments Passed In: " + String.join(" ", expectedArguments)); } @Test - void generateZip_shouldSendSQEnvVars() throws IOException, URISyntaxException { - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + void generateManifestsArchive_shouldSendSQEnvVars() throws IOException, URISyntaxException { + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); assertThat(logTester.logs(INFO)) .contains("TIDELIFT_CLI_INSIDE_SCANNER_ENGINE=1") @@ -192,20 +192,20 @@ class CliServiceTest { } @Test - void generateZip_includesIgnoredPathsFromGitProvider() throws Exception { - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + void generateManifestsArchive_includesIgnoredPathsFromGitProvider() throws Exception { + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); var expectedArguments = List.of( "projects", "save-lockfiles", - "--zip", - "--zip-filename", - rootInputModule.getWorkDir().resolve("dependency-files.zip").toString(), + "--xz", + "--xz-filename", + rootInputModule.getWorkDir().resolve("dependency-files.tar.xz").toString(), "--directory", rootInputModule.getBaseDir().toString(), + "--recursive", "--exclude", - "ignored.txt,.scannerwork/**", - "--debug"); + "ignored.txt,.scannerwork/**"); assertThat(logTester.logs(INFO)) .contains("Arguments Passed In: " + String.join(" ", expectedArguments)) @@ -217,87 +217,120 @@ class CliServiceTest { } @Test - void generateZip_withNoScm_doesNotIncludeScmIgnoredPaths() throws Exception { + void generateManifestsArchive_withNoScm_doesNotIncludeScmIgnoredPaths() throws Exception { when(scmConfiguration.provider()).thenReturn(null); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); - assertThat(capturedArgs).contains("--exclude .scannerwork/** --debug"); + assertThat(capturedArgs).contains("--exclude .scannerwork/**"); } @Test - void generateZip_withNonGit_doesNotIncludeScmIgnoredPaths() throws Exception { + void generateManifestsArchive_withNonGit_doesNotIncludeScmIgnoredPaths() throws Exception { when(scmProvider.key()).thenReturn("notgit"); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); - assertThat(capturedArgs).contains("--exclude .scannerwork/** --debug"); + assertThat(capturedArgs).contains("--exclude .scannerwork/**"); } @Test - void generateZip_withExclusionDisabled_doesNotIncludeScmIgnoredPaths() throws Exception { + void generateManifestsArchive_withScmExclusionDisabled_doesNotIncludeScmIgnoredPaths() throws Exception { when(scmConfiguration.isExclusionDisabled()).thenReturn(true); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); - assertThat(capturedArgs).contains("--exclude .scannerwork/** --debug"); + assertThat(capturedArgs).contains("--exclude .scannerwork/**"); } @Test - void generateZip_withNoScmIgnores_doesNotIncludeScmIgnoredPaths() throws Exception { + void generateManifestsArchive_withNoScmIgnores_doesNotIncludeScmIgnoredPaths() throws Exception { jGitUtilsMock.when(() -> JGitUtils.getAllIgnoredPaths(any(Path.class))).thenReturn(List.of()); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); - assertThat(capturedArgs).contains("--exclude .scannerwork/** --debug"); + assertThat(capturedArgs).contains("--exclude .scannerwork/**"); } @Test - void generateZip_withExistingExcludedManifests_appendsScmIgnoredPaths() throws Exception { - when(configuration.getStringArray(CliService.EXCLUDED_MANIFESTS_PROP_KEY)).thenReturn(new String[] {"**/test/**"}); + void generateManifestsArchive_withExcludedManifests_appendsScmIgnoredPaths() throws Exception { + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test/**"}); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); assertThat(capturedArgs).contains("--exclude **/test/**,ignored.txt,.scannerwork/**"); } @Test - void generateZip_withExcludedManifestsSettingContainingBadCharacters_handlesTheBadCharacters() throws Exception { - when(configuration.getStringArray(CliService.EXCLUDED_MANIFESTS_PROP_KEY)).thenReturn(new String[] { - "**/test/**", "**/path with spaces/**", "**/path,with,commas/**", "**/path'with'quotes/**", "**/path\"with\"double\"quotes/**"}); + void generateManifestsArchive_withExcludedManifestsContainingBadCharacters_handlesTheBadCharacters() throws Exception { + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] { + "**/test/**", "**/path with spaces/**", "**/path'with'quotes/**", "**/path\"with\"double\"quotes/**"}); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); String expectedExcludeFlag = """ - --exclude **/test/**,**/path with spaces/**,"**/path,with,commas/**",**/path'with'quotes/**,"**/path""with""double""quotes/**",ignored.txt + --exclude **/test/**,**/path with spaces/**,**/path'with'quotes/**,"**/path""with""double""quotes/**",ignored.txt """.strip(); + if (SystemUtils.IS_OS_WINDOWS) { + expectedExcludeFlag = """ + --exclude "**/test/**,**/path with spaces/**,**/path'with'quotes/**,"**/path""with""double""quotes/**",ignored.txt + """.strip(); + } assertThat(capturedArgs).contains(expectedExcludeFlag); } @Test - void generateZip_withScmIgnoresContainingBadCharacters_handlesTheBadCharacters() throws Exception { + void generateManifestsArchive_withExcludedManifestsContainingDupes_dedupes() throws Exception { + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test1/**", "**/test2/**", "**/test1/**"}); + when(configuration.getStringArray(CliService.LEGACY_SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test1/**", "**/test3/**"}); + + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); + assertThat(capturedArgs).contains("--exclude **/test1/**,**/test2/**,**/test3/**,ignored.txt,.scannerwork/**"); + } + + @Test + void generateManifestsArchive_withExcludedManifestsAndSonarExcludesContainingDupes_mergesAndDedupes() throws Exception { + when(projectExclusionFilters.getExclusionsConfig(InputFile.Type.MAIN)).thenReturn(new String[] {"**/test1/**", "**/test4/**"}); + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test1/**", "**/test2/**", "**/test1/**"}); + when(configuration.getStringArray(CliService.LEGACY_SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test1/**", "**/test3/**"}); + + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); + assertThat(capturedArgs).contains("--exclude **/test1/**,**/test4/**,**/test2/**,**/test3/**,ignored.txt,.scannerwork/**"); + } + + @Test + void generateManifestsArchive_withScmIgnoresContainingBadCharacters_handlesTheBadCharacters() throws Exception { jGitUtilsMock.when(() -> JGitUtils.getAllIgnoredPaths(any(Path.class))) - .thenReturn(List.of("**/test/**", "**/path with spaces/**", "**/path,with,commas/**", "**/path'with'quotes/**", "**/path\"with\"double\"quotes/**")); + .thenReturn(List.of("**/test/**", "**/path with spaces/**", "**/path'with'quotes/**", "**/path\"with\"double\"quotes/**")); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); String expectedExcludeFlag = """ - --exclude **/test/**,**/path with spaces/**,"**/path,with,commas/**",**/path'with'quotes/**,"**/path""with""double""quotes/**" + --exclude **/test/**,**/path with spaces/**,**/path'with'quotes/**,"**/path""with""double""quotes/**" """.strip(); + if (SystemUtils.IS_OS_WINDOWS) { + expectedExcludeFlag = """ + --exclude "**/test/**,**/path with spaces/**,**/path'with'quotes/**,"**/path""with""double""quotes/**" + """.strip(); + } assertThat(capturedArgs).contains(expectedExcludeFlag); } @Test - void generateZip_withIgnoredDirectories_GlobifiesDirectories() throws Exception { + void generateManifestsArchive_withIgnoredDirectories_GlobifiesDirectories() throws Exception { String ignoredDirectory = "directory1"; Files.createDirectories(rootModuleDir.resolve(ignoredDirectory)); String ignoredFile = "directory2/file.txt"; @@ -306,22 +339,22 @@ class CliServiceTest { Files.createFile(ignoredFilePath); jGitUtilsMock.when(() -> JGitUtils.getAllIgnoredPaths(any(Path.class))).thenReturn(List.of(ignoredDirectory, ignoredFile)); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); assertThat(capturedArgs).contains("--exclude directory1/**,directory2/file.txt"); } @Test - void generateZip_withExternalWorkDir_DoesNotExcludeWorkingDir() throws URISyntaxException, IOException { + void generateManifestsArchive_withExternalWorkDir_DoesNotExcludeWorkingDir() throws URISyntaxException, IOException { Path externalWorkDir = Files.createTempDirectory("externalWorkDir"); try { rootInputModule = new DefaultInputModule(ProjectDefinition.create().setBaseDir(rootModuleDir.toFile()).setWorkDir(externalWorkDir.toFile())); - underTest.generateManifestsZip(rootInputModule, scriptDir(), configuration); + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); // externalWorkDir is not present in the exclude flag - assertThat(capturedArgs).contains("--exclude ignored.txt --debug"); + assertThat(capturedArgs).contains("--exclude ignored.txt"); } finally { externalWorkDir.toFile().delete(); } @@ -330,7 +363,7 @@ class CliServiceTest { private URL scriptUrl() { // There is a custom test Bash script available in src/test/resources/org/sonar/scanner/sca that // will serve as our "CLI". This script will output some messages about what arguments were passed - // to it and will try to generate a zip file in the location the process specifies. This allows us + // to it and will try to generate an archive file in the location the process specifies. This allows us // to simulate a real CLI call without needing an OS specific CLI executable to run on a real project. URL scriptUrl = CliServiceTest.class.getResource(SystemUtils.IS_OS_WINDOWS ? "echo_args.bat" : "echo_args.sh"); assertThat(scriptUrl).isNotNull(); |