aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-scanner-engine/src/test/java
diff options
context:
space:
mode:
Diffstat (limited to 'sonar-scanner-engine/src/test/java')
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RulesSeverityDetectorTest.java59
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java70
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliCacheServiceTest.java11
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java173
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaExecutorTest.java34
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaPropertiesTest.java45
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectConfigurationProviderTest.java14
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/DirectoryFileVisitorTest.java53
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/HiddenFilesProjectDataTest.java160
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/HiddenFilesVisitorHelperTest.java315
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java157
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MutableFileSystemTest.java99
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java21
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java4
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ProjectSensorContextTest.java14
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedFileTest.java2
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitUtilsTest.java7
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scm/git/NativeGitBlameCommandTest.java14
18 files changed, 980 insertions, 272 deletions
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RulesSeverityDetectorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RulesSeverityDetectorTest.java
index 5091dcf5a3a..f5d88016944 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RulesSeverityDetectorTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RulesSeverityDetectorTest.java
@@ -22,12 +22,16 @@ package org.sonar.scanner.externalissue.sarif;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.annotation.Nullable;
import org.assertj.core.api.Assertions;
import org.assertj.core.groups.Tuple;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
import org.slf4j.event.Level;
-import org.sonar.api.testfixtures.log.LogTester;
+import org.sonar.api.testfixtures.log.LogTesterJUnit5;
import org.sonar.sarif.pojo.ReportingConfiguration;
import org.sonar.sarif.pojo.ReportingDescriptor;
import org.sonar.sarif.pojo.Result;
@@ -44,12 +48,12 @@ import static org.sonar.sarif.pojo.Result.Level.WARNING;
import static org.sonar.scanner.externalissue.sarif.ResultMapper.DEFAULT_IMPACT_SEVERITY;
import static org.sonar.scanner.externalissue.sarif.ResultMapper.DEFAULT_SEVERITY;
-public class RulesSeverityDetectorTest {
+class RulesSeverityDetectorTest {
private static final String DRIVER_NAME = "Test";
private static final String RULE_ID = "RULE_ID";
- @org.junit.Rule
- public LogTester logTester = new LogTester().setLevel(Level.TRACE);
+ @RegisterExtension
+ private final LogTesterJUnit5 logTester = new LogTesterJUnit5();
private final Run run = mock(Run.class);
private final ReportingDescriptor rule = mock(ReportingDescriptor.class);
@@ -59,8 +63,8 @@ public class RulesSeverityDetectorTest {
private final ToolComponent extension = mock(ToolComponent.class);
private final ReportingConfiguration defaultConfiguration = mock(ReportingConfiguration.class);
- @Before
- public void setUp() {
+ @BeforeEach
+ void setUp() {
when(run.getResults()).thenReturn(List.of(result));
when(run.getTool()).thenReturn(tool);
when(tool.getDriver()).thenReturn(driver);
@@ -68,8 +72,8 @@ public class RulesSeverityDetectorTest {
// We keep this test for backward compatibility until we remove the deprecated severity
@Test
- public void detectRulesSeverities_detectsCorrectlyResultDefinedRuleSeverities() {
- Run run = mockResultDefinedRuleSeverities();
+ void detectRulesSeverities_detectsCorrectlyResultDefinedRuleSeverities() {
+ mockResultDefinedRuleSeverities();
Map<String, Result.Level> rulesSeveritiesByRuleId = RulesSeverityDetector.detectRulesSeverities(run, DRIVER_NAME);
@@ -78,8 +82,8 @@ public class RulesSeverityDetectorTest {
}
@Test
- public void detectRulesSeveritiesForNewTaxonomy_shouldReturnsEmptyMapAndLogsWarning_whenOnlyResultDefinedRuleSeverities() {
- Run run = mockResultDefinedRuleSeverities();
+ void detectRulesSeveritiesForNewTaxonomy_shouldReturnsEmptyMapAndLogsWarning_whenOnlyResultDefinedRuleSeverities() {
+ mockResultDefinedRuleSeverities();
Map<String, Result.Level> rulesSeveritiesByRuleId = RulesSeverityDetector.detectRulesSeveritiesForNewTaxonomy(run, DRIVER_NAME);
@@ -88,8 +92,8 @@ public class RulesSeverityDetectorTest {
}
@Test
- public void detectRulesSeverities_detectsCorrectlyDriverDefinedRuleSeverities() {
- Run run = mockDriverDefinedRuleSeverities();
+ void detectRulesSeverities_detectsCorrectlyDriverDefinedRuleSeverities() {
+ mockDriverDefinedRuleSeverities();
Map<String, Result.Level> rulesSeveritiesByRuleId = RulesSeverityDetector.detectRulesSeveritiesForNewTaxonomy(run, DRIVER_NAME);
@@ -103,9 +107,13 @@ public class RulesSeverityDetectorTest {
assertDetectedRuleSeverities(rulesSeveritiesByRuleId, tuple(RULE_ID, WARNING));
}
- @Test
- public void detectRulesSeverities_detectsCorrectlyExtensionsDefinedRuleSeverities() {
- Run run = mockExtensionsDefinedRuleSeverities();
+
+
+ @ParameterizedTest
+ @NullAndEmptySource
+ void detectRulesSeverities_detectsCorrectlyExtensionsDefinedRuleSeverities(@Nullable Set<ReportingDescriptor> rules) {
+ when(driver.getRules()).thenReturn(rules);
+ mockExtensionsDefinedRuleSeverities();
Map<String, Result.Level> rulesSeveritiesByRuleId = RulesSeverityDetector.detectRulesSeveritiesForNewTaxonomy(run, DRIVER_NAME);
@@ -120,8 +128,8 @@ public class RulesSeverityDetectorTest {
}
@Test
- public void detectRulesSeverities_returnsEmptyMapAndLogsWarning_whenUnableToDetectSeverities() {
- Run run = mockUnsupportedRuleSeveritiesDefinition();
+ void detectRulesSeverities_returnsEmptyMapAndLogsWarning_whenUnableToDetectSeverities() {
+ mockUnsupportedRuleSeveritiesDefinition();
Map<String, Result.Level> rulesSeveritiesByRuleId = RulesSeverityDetector.detectRulesSeveritiesForNewTaxonomy(run, DRIVER_NAME);
@@ -135,38 +143,33 @@ public class RulesSeverityDetectorTest {
assertDetectedRuleSeverities(rulesSeveritiesByRuleId);
}
- private Run mockResultDefinedRuleSeverities() {
+ private void mockResultDefinedRuleSeverities() {
when(run.getResults()).thenReturn(List.of(result));
when(result.getLevel()).thenReturn(WARNING);
when(result.getRuleId()).thenReturn(RULE_ID);
- return run;
}
- private Run mockDriverDefinedRuleSeverities() {
+ private void mockDriverDefinedRuleSeverities() {
when(driver.getRules()).thenReturn(Set.of(rule));
when(rule.getId()).thenReturn(RULE_ID);
when(rule.getDefaultConfiguration()).thenReturn(defaultConfiguration);
when(defaultConfiguration.getLevel()).thenReturn(ReportingConfiguration.Level.WARNING);
- return run;
}
- private Run mockExtensionsDefinedRuleSeverities() {
- when(driver.getRules()).thenReturn(Set.of());
+ private void mockExtensionsDefinedRuleSeverities() {
when(tool.getExtensions()).thenReturn(Set.of(extension));
when(extension.getRules()).thenReturn(Set.of(rule));
when(rule.getId()).thenReturn(RULE_ID);
when(rule.getDefaultConfiguration()).thenReturn(defaultConfiguration);
when(defaultConfiguration.getLevel()).thenReturn(ReportingConfiguration.Level.WARNING);
- return run;
}
- private Run mockUnsupportedRuleSeveritiesDefinition() {
+ private void mockUnsupportedRuleSeveritiesDefinition() {
when(run.getTool()).thenReturn(tool);
when(tool.getDriver()).thenReturn(driver);
when(driver.getRules()).thenReturn(Set.of());
when(tool.getExtensions()).thenReturn(Set.of(extension));
when(extension.getRules()).thenReturn(Set.of());
- return run;
}
private void assertNoLogs() {
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java
index 90ddfadd9f3..164787f8cde 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RunMapperTest.java
@@ -22,19 +22,19 @@ package org.sonar.scanner.externalissue.sarif;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.Answers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.slf4j.event.Level;
import org.sonar.api.batch.sensor.issue.NewExternalIssue;
import org.sonar.api.batch.sensor.rule.NewAdHocRule;
-import org.sonar.api.testfixtures.log.LogTester;
+import org.sonar.api.testfixtures.log.LogTesterJUnit5;
import org.sonar.sarif.pojo.ReportingDescriptor;
import org.sonar.sarif.pojo.Result;
import org.sonar.sarif.pojo.Run;
@@ -44,13 +44,14 @@ import org.sonar.scanner.externalissue.sarif.RunMapper.RunMapperResult;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import static org.sonar.sarif.pojo.Result.Level.WARNING;
-@RunWith(MockitoJUnitRunner.class)
-public class RunMapperTest {
+@ExtendWith(MockitoExtension.class)
+class RunMapperTest {
private static final String TEST_DRIVER = "Test driver";
public static final String RULE_ID = "ruleId";
@@ -66,21 +67,21 @@ public class RunMapperTest {
@Mock
private ReportingDescriptor rule;
- @Rule
- public LogTester logTester = new LogTester();
+ @RegisterExtension
+ public LogTesterJUnit5 logTester = new LogTesterJUnit5();
@InjectMocks
private RunMapper runMapper;
- @Before
- public void setUp() {
- when(run.getTool().getDriver().getName()).thenReturn(TEST_DRIVER);
- when(run.getTool().getExtensions()).thenReturn(null);
- when(rule.getId()).thenReturn(RULE_ID);
+ @BeforeEach
+ void setUp() {
+ lenient().when(run.getTool().getDriver().getName()).thenReturn(TEST_DRIVER);
+ lenient().when(run.getTool().getExtensions()).thenReturn(null);
+ lenient().when(rule.getId()).thenReturn(RULE_ID);
}
@Test
- public void mapRun_shouldMapExternalIssues() {
+ void mapRun_shouldMapExternalIssues() {
Result result1 = mock(Result.class);
Result result2 = mock(Result.class);
when(run.getResults()).thenReturn(List.of(result1, result2));
@@ -99,7 +100,7 @@ public class RunMapperTest {
}
@Test
- public void mapRun_shouldMapExternalRules_whenDriverHasRulesAndNoExtensions() {
+ void mapRun_shouldMapExternalRules_whenDriverHasRulesAndNoExtensions() {
when(run.getTool().getDriver().getRules()).thenReturn(Set.of(rule));
NewAdHocRule externalRule = mockMappedExternalRule();
@@ -115,7 +116,7 @@ public class RunMapperTest {
}
@Test
- public void mapRun_shouldMapExternalRules_whenRulesInExtensions() {
+ void mapRun_shouldMapExternalRules_whenRulesInExtensions() {
when(run.getTool().getDriver().getRules()).thenReturn(Set.of());
ToolComponent extension = mock(ToolComponent.class);
when(extension.getRules()).thenReturn(Set.of(rule));
@@ -134,7 +135,7 @@ public class RunMapperTest {
}
@Test
- public void mapRun_shouldNotFail_whenExtensionsDontHaveRules() {
+ void mapRun_shouldNotFail_whenExtensionsDontHaveRules() {
when(run.getTool().getDriver().getRules()).thenReturn(Set.of(rule));
ToolComponent extension = mock(ToolComponent.class);
when(extension.getRules()).thenReturn(null);
@@ -149,7 +150,7 @@ public class RunMapperTest {
}
@Test
- public void mapRun_shouldNotFail_whenExtensionsHaveEmptyRules() {
+ void mapRun_shouldNotFail_whenExtensionsHaveEmptyRules() {
when(run.getTool().getDriver().getRules()).thenReturn(Set.of(rule));
ToolComponent extension = mock(ToolComponent.class);
when(extension.getRules()).thenReturn(Set.of());
@@ -164,7 +165,7 @@ public class RunMapperTest {
}
@Test
- public void mapRun_ifRunIsEmpty_returnsEmptyList() {
+ void mapRun_ifRunIsEmpty_returnsEmptyList() {
when(run.getResults()).thenReturn(List.of());
RunMapperResult runMapperResult = runMapper.mapRun(run);
@@ -173,7 +174,7 @@ public class RunMapperTest {
}
@Test
- public void mapRun_ifExceptionThrownByResultMapper_logsThemAndContinueProcessing() {
+ void mapRun_ifExceptionThrownByResultMapper_logsThemAndContinueProcessing() {
Result result1 = mock(Result.class);
Result result2 = mock(Result.class);
when(run.getResults()).thenReturn(List.of(result1, result2));
@@ -194,7 +195,7 @@ public class RunMapperTest {
}
@Test
- public void mapRun_failsIfToolNotSet() {
+ void mapRun_failsIfToolNotSet() {
when(run.getTool()).thenReturn(null);
assertThatIllegalArgumentException()
@@ -203,7 +204,7 @@ public class RunMapperTest {
}
@Test
- public void mapRun_failsIfDriverNotSet() {
+ void mapRun_failsIfDriverNotSet() {
when(run.getTool().getDriver()).thenReturn(null);
assertThatIllegalArgumentException()
@@ -212,7 +213,7 @@ public class RunMapperTest {
}
@Test
- public void mapRun_failsIfDriverNameIsNotSet() {
+ void mapRun_failsIfDriverNameIsNotSet() {
when(run.getTool().getDriver().getName()).thenReturn(null);
assertThatIllegalArgumentException()
@@ -220,6 +221,25 @@ public class RunMapperTest {
.withMessage("The run does not have a tool driver name defined.");
}
+ @Test
+ void mapRun_shouldNotFail_whenDriverRulesNullAndExtensionsRulesNotNull() {
+ when(run.getTool().getDriver().getRules()).thenReturn(null);
+ ToolComponent extension = mock(ToolComponent.class);
+ when(extension.getRules()).thenReturn(Set.of(rule));
+ when(run.getTool().getExtensions()).thenReturn(Set.of(extension));
+ NewAdHocRule expectedRule = mock(NewAdHocRule.class);
+ when(ruleMapper.mapRule(rule, TEST_DRIVER, WARNING, WARNING)).thenReturn(expectedRule);
+
+ try (MockedStatic<RulesSeverityDetector> detector = mockStatic(RulesSeverityDetector.class)) {
+ detector.when(() -> RulesSeverityDetector.detectRulesSeverities(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING));
+ detector.when(() -> RulesSeverityDetector.detectRulesSeveritiesForNewTaxonomy(run, TEST_DRIVER)).thenReturn(Map.of(RULE_ID, WARNING));
+
+ RunMapperResult runMapperResult = runMapper.mapRun(run);
+ assertThat(runMapperResult.getNewAdHocRules()).hasSize(1);
+ assertThat(runMapperResult.getNewAdHocRules().get(0)).isEqualTo(expectedRule);
+ }
+ }
+
private NewExternalIssue mockMappedExternalIssue(Result result) {
NewExternalIssue externalIssue = mock(NewExternalIssue.class);
when(result.getRuleId()).thenReturn(RULE_ID);
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliCacheServiceTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliCacheServiceTest.java
index 9193157e213..6615ba4e4e4 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliCacheServiceTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliCacheServiceTest.java
@@ -29,6 +29,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.SystemUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -161,7 +162,7 @@ class CliCacheServiceTest {
WsTestUtil.mockException(scannerWsClient, e);
assertThatThrownBy(underTest::cacheCli).isInstanceOf(IllegalStateException.class)
- .hasMessageContaining("Unable to load CLI metadata");
+ .hasMessageContaining("http error");
verify(telemetryCache).put("scanner.sca.get.cli.success", "false");
}
@@ -187,14 +188,18 @@ class CliCacheServiceTest {
FileUtils.writeStringToFile(existingFile, fileContent, Charset.defaultCharset());
assertThat(existingFile).exists();
- assertThat(existingFile.canExecute()).isFalse();
+ if (!SystemUtils.IS_OS_WINDOWS) {
+ assertThat(existingFile.canExecute()).isFalse();
+ }
assertThat(FileUtils.readFileToString(existingFile, Charset.defaultCharset())).isEqualTo(fileContent);
underTest.cacheCli();
WsTestUtil.verifyCall(scannerWsClient, CLI_WS_URL);
assertThat(existingFile).exists();
- assertThat(existingFile.canExecute()).isFalse();
+ if (!SystemUtils.IS_OS_WINDOWS) {
+ assertThat(existingFile.canExecute()).isFalse();
+ }
assertThat(FileUtils.readFileToString(existingFile, Charset.defaultCharset())).isEqualTo(fileContent);
verify(telemetryCache).put("scanner.sca.get.cli.cache.hit", "true");
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();
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaExecutorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaExecutorTest.java
index aecbc7011a9..ebe6007a1c1 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaExecutorTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaExecutorTest.java
@@ -70,14 +70,14 @@ class ScaExecutorTest {
File mockManifestZip = Files.newTemporaryFile();
ScannerReportWriter mockReportWriter = mock(ScannerReportWriter.class);
when(cliCacheService.cacheCli()).thenReturn(mockCliFile);
- when(cliService.generateManifestsZip(root, mockCliFile, configuration)).thenReturn(mockManifestZip);
+ when(cliService.generateManifestsArchive(root, mockCliFile, configuration)).thenReturn(mockManifestZip);
when(reportPublisher.getWriter()).thenReturn(mockReportWriter);
logTester.setLevel(Level.DEBUG);
underTest.execute(root);
- verify(cliService).generateManifestsZip(root, mockCliFile, configuration);
+ verify(cliService).generateManifestsArchive(root, mockCliFile, configuration);
verify(mockReportWriter).writeScaFile(mockManifestZip);
assertThat(logTester.logs(Level.DEBUG)).contains("Zip ready for report: " + mockManifestZip);
assertThat(logTester.logs(Level.DEBUG)).contains("Manifest zip written to report");
@@ -87,13 +87,13 @@ class ScaExecutorTest {
void execute_whenIOException_shouldHandleException() throws IOException {
File mockCliFile = Files.newTemporaryFile();
when(cliCacheService.cacheCli()).thenReturn(mockCliFile);
- doThrow(IOException.class).when(cliService).generateManifestsZip(root, mockCliFile, configuration);
+ doThrow(IOException.class).when(cliService).generateManifestsArchive(root, mockCliFile, configuration);
logTester.setLevel(Level.INFO);
underTest.execute(root);
- verify(cliService).generateManifestsZip(root, mockCliFile, configuration);
+ verify(cliService).generateManifestsArchive(root, mockCliFile, configuration);
assertThat(logTester.logs(Level.ERROR)).contains("Error gathering manifests");
}
@@ -101,13 +101,13 @@ class ScaExecutorTest {
void execute_whenIllegalStateException_shouldHandleException() throws IOException {
File mockCliFile = Files.newTemporaryFile();
when(cliCacheService.cacheCli()).thenReturn(mockCliFile);
- doThrow(IllegalStateException.class).when(cliService).generateManifestsZip(root, mockCliFile, configuration);
+ doThrow(IllegalStateException.class).when(cliService).generateManifestsArchive(root, mockCliFile, configuration);
logTester.setLevel(Level.INFO);
underTest.execute(root);
- verify(cliService).generateManifestsZip(root, mockCliFile, configuration);
+ verify(cliService).generateManifestsArchive(root, mockCliFile, configuration);
assertThat(logTester.logs(Level.ERROR)).contains("Error gathering manifests");
}
@@ -118,7 +118,7 @@ class ScaExecutorTest {
underTest.execute(root);
- verify(cliService, never()).generateManifestsZip(root, mockCliFile, configuration);
+ verify(cliService, never()).generateManifestsArchive(root, mockCliFile, configuration);
}
@Test
@@ -150,15 +150,31 @@ class ScaExecutorTest {
File mockManifestZip = Files.newTemporaryFile();
ScannerReportWriter mockReportWriter = mock(ScannerReportWriter.class);
when(cliCacheService.cacheCli()).thenReturn(mockCliFile);
- when(cliService.generateManifestsZip(root, mockCliFile, configuration)).thenReturn(mockManifestZip);
+ when(cliService.generateManifestsArchive(root, mockCliFile, configuration)).thenReturn(mockManifestZip);
when(reportPublisher.getWriter()).thenReturn(mockReportWriter);
logTester.setLevel(Level.DEBUG);
underTest.execute(root);
- verify(cliService).generateManifestsZip(root, mockCliFile, configuration);
+ verify(cliService).generateManifestsArchive(root, mockCliFile, configuration);
verify(mockReportWriter).writeScaFile(mockManifestZip);
assertThat(logTester.logs(Level.DEBUG)).contains("Zip ready for report: " + mockManifestZip);
assertThat(logTester.logs(Level.DEBUG)).contains("Manifest zip written to report");
}
+
+ @Test
+ void execute_printsRuntime() throws IOException {
+ File mockCliFile = Files.newTemporaryFile();
+ File mockManifestZip = Files.newTemporaryFile();
+ ScannerReportWriter mockReportWriter = mock(ScannerReportWriter.class);
+ when(cliCacheService.cacheCli()).thenReturn(mockCliFile);
+ when(cliService.generateManifestsArchive(root, mockCliFile, configuration)).thenReturn(mockManifestZip);
+ when(reportPublisher.getWriter()).thenReturn(mockReportWriter);
+
+ logTester.setLevel(Level.INFO);
+
+ underTest.execute(root);
+
+ assertThat(logTester.logs(Level.INFO)).anyMatch(l -> l.matches("Load SCA project dependencies \\(done\\) \\| time=\\d+ms"));
+ }
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaPropertiesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaPropertiesTest.java
index e598a225b9c..70e7a6b6e53 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaPropertiesTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaPropertiesTest.java
@@ -19,11 +19,9 @@
*/
package org.sonar.scanner.sca;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
-import java.util.Set;
import org.junit.jupiter.api.Test;
import org.sonar.scanner.config.DefaultConfiguration;
@@ -36,13 +34,12 @@ class ScaPropertiesTest {
private final DefaultConfiguration configuration = mock(DefaultConfiguration.class);
@Test
- void buildFromScannerProperties_withNoProperties_returnsDefaultMap() {
+ void buildFromScannerProperties_withNoProperties_returnsEmptyMap() {
when(configuration.get(anyString())).thenReturn(Optional.empty());
- var result = ScaProperties.buildFromScannerProperties(configuration, Collections.emptySet());
+ var result = ScaProperties.buildFromScannerProperties(configuration);
- assertThat(result).containsExactly(
- Map.entry("TIDELIFT_RECURSIVE_MANIFEST_SEARCH", "true"));
+ assertThat(result).isEqualTo(Map.of());
}
@Test
@@ -51,14 +48,13 @@ class ScaPropertiesTest {
inputProperties.put("sonar.sca.pythonBinary", "/usr/bin/python3");
inputProperties.put("sonar.sca.unknownProperty", "value");
inputProperties.put("sonar.somethingElse", "dont-include-non-sca");
- inputProperties.put("sonar.sca.ignoredProperty", "ignore-me");
+ inputProperties.put("sonar.sca.recursiveManifestSearch", "ignore-me");
when(configuration.getProperties()).thenReturn(inputProperties);
when(configuration.get(anyString())).thenAnswer(i -> Optional.ofNullable(inputProperties.get(i.getArgument(0, String.class))));
- var result = ScaProperties.buildFromScannerProperties(configuration, Set.of("sonar.sca.ignoredProperty"));
+ var result = ScaProperties.buildFromScannerProperties(configuration);
assertThat(result).containsExactly(
- Map.entry("TIDELIFT_RECURSIVE_MANIFEST_SEARCH", "true"),
Map.entry("TIDELIFT_PYTHON_BINARY", "/usr/bin/python3"),
Map.entry("TIDELIFT_UNKNOWN_PROPERTY", "value"));
}
@@ -79,7 +75,6 @@ class ScaPropertiesTest {
inputProperties.put("sonar.sca.pythonBinary", "/usr/bin/python3");
inputProperties.put("sonar.sca.pythonNoResolve", "true");
inputProperties.put("sonar.sca.pythonResolveLocal", "false");
- inputProperties.put("sonar.sca.recursiveManifestSearch", "true");
when(configuration.getProperties()).thenReturn(inputProperties);
when(configuration.get(anyString())).thenAnswer(i -> Optional.ofNullable(inputProperties.get(i.getArgument(0, String.class))));
@@ -97,37 +92,9 @@ class ScaPropertiesTest {
expectedProperties.put("TIDELIFT_PYTHON_BINARY", "/usr/bin/python3");
expectedProperties.put("TIDELIFT_PYTHON_NO_RESOLVE", "true");
expectedProperties.put("TIDELIFT_PYTHON_RESOLVE_LOCAL", "false");
- expectedProperties.put("TIDELIFT_RECURSIVE_MANIFEST_SEARCH", "true");
- var result = ScaProperties.buildFromScannerProperties(configuration, Collections.emptySet());
+ var result = ScaProperties.buildFromScannerProperties(configuration);
assertThat(result).containsExactlyInAnyOrderEntriesOf(expectedProperties);
}
-
-
- @Test
- void buildFromScannerProperties_withoutRecursiveModeProp_defaultsRecursiveModeTrue() {
- var inputProperties = new HashMap<String, String>();
- when(configuration.getProperties()).thenReturn(inputProperties);
- when(configuration.get(anyString())).thenAnswer(i -> Optional.ofNullable(inputProperties.get(i.getArgument(0, String.class))));
-
- var result = ScaProperties.buildFromScannerProperties(configuration, Collections.emptySet());
-
- assertThat(result).containsExactly(
- Map.entry("TIDELIFT_RECURSIVE_MANIFEST_SEARCH", "true"));
- }
-
- @Test
- void buildFromScannerProperties_withRecursiveModeProp_usesPropAsOverride() {
- var inputProperties = new HashMap<String, String>();
- inputProperties.put("sonar.sca.recursiveManifestSearch", "false");
- when(configuration.getProperties()).thenReturn(inputProperties);
- when(configuration.get(anyString())).thenAnswer(i -> Optional.ofNullable(inputProperties.get(i.getArgument(0, String.class))));
-
- var result = ScaProperties.buildFromScannerProperties(configuration, Collections.emptySet());
-
- assertThat(result).containsExactly(
- Map.entry("TIDELIFT_RECURSIVE_MANIFEST_SEARCH", "false"));
- }
-
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectConfigurationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectConfigurationProviderTest.java
index 21dcf58b114..3e3066e76e2 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectConfigurationProviderTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectConfigurationProviderTest.java
@@ -52,10 +52,9 @@ public class ProjectConfigurationProviderTest {
private static final Map<String, String> PROJECT_SERVER_PROPERTIES = Map.of(NON_GLOBAL_KEY_PROPERTIES_1, NON_GLOBAL_VALUE_PROPERTIES_1);
private static final Map<String, String> DEFAULT_PROJECT_PROPERTIES = Map.of(DEFAULT_KEY_PROPERTIES_1, DEFAULT_VALUE_1);
- private static final Map<String, String> ALL_PROPERTIES_MAP =
- Stream.of(GLOBAL_SERVER_PROPERTIES, PROJECT_SERVER_PROPERTIES, DEFAULT_PROJECT_PROPERTIES)
- .flatMap(map -> map.entrySet().stream())
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+ private static final Map<String, String> ALL_PROPERTIES_MAP = Stream.of(GLOBAL_SERVER_PROPERTIES, PROJECT_SERVER_PROPERTIES, DEFAULT_PROJECT_PROPERTIES)
+ .flatMap(map -> map.entrySet().stream())
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
private static final Map<String, String> PROPERTIES_AFTER_FILTERING = Map.of("aKey", "aValue");
@@ -66,8 +65,6 @@ public class ProjectConfigurationProviderTest {
@Mock
private GlobalConfiguration globalConfiguration;
@Mock
- private MutableProjectSettings mutableProjectSettings;
- @Mock
private DefaultInputProject defaultInputProject;
@Mock
private SonarGlobalPropertiesFilter sonarGlobalPropertiesFilter;
@@ -75,7 +72,6 @@ public class ProjectConfigurationProviderTest {
@InjectMocks
private ProjectConfigurationProvider provider;
-
@Before
public void init() {
when(globalConfiguration.getDefinitions()).thenReturn(new PropertyDefinitions(System2.INSTANCE));
@@ -89,11 +85,11 @@ public class ProjectConfigurationProviderTest {
when(sonarGlobalPropertiesFilter.enforceOnlyServerSideSonarGlobalPropertiesAreUsed(ALL_PROPERTIES_MAP, GLOBAL_SERVER_PROPERTIES))
.thenReturn(PROPERTIES_AFTER_FILTERING);
- ProjectConfiguration provide = provider.provide(defaultInputProject, globalConfiguration, globalServerSettings, projectServerSettings, mutableProjectSettings);
+ ProjectConfiguration provide = provider.provide(defaultInputProject, globalConfiguration, globalServerSettings, projectServerSettings);
verify(sonarGlobalPropertiesFilter).enforceOnlyServerSideSonarGlobalPropertiesAreUsed(ALL_PROPERTIES_MAP, GLOBAL_SERVER_PROPERTIES);
assertThat(provide.getOriginalProperties()).containsExactlyEntriesOf(PROPERTIES_AFTER_FILTERING);
}
-} \ No newline at end of file
+}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/DirectoryFileVisitorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/DirectoryFileVisitorTest.java
index 01cb7d1bccf..277fc0dc68a 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/DirectoryFileVisitorTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/DirectoryFileVisitorTest.java
@@ -27,20 +27,26 @@ import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Optional;
import org.apache.commons.lang3.SystemUtils;
+import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.scanner.bootstrap.SonarUserHome;
import org.sonar.scanner.fs.InputModuleHierarchy;
+import org.sonar.scanner.scan.ModuleConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class DirectoryFileVisitorTest {
@@ -48,33 +54,57 @@ public class DirectoryFileVisitorTest {
public static TemporaryFolder temp = new TemporaryFolder();
private final DefaultInputModule module = mock();
+ private final ModuleConfiguration moduleConfiguration = mock();
private final ModuleExclusionFilters moduleExclusionFilters = mock();
private final InputModuleHierarchy inputModuleHierarchy = mock();
private final InputFile.Type type = mock();
+ private final SonarUserHome sonarUserHome = mock();
+ private HiddenFilesProjectData hiddenFilesProjectData;
+
+ @Before
+ public void before() throws IOException {
+ Path sonarUserHomePath = temp.newFolder().toPath();
+ when(sonarUserHome.getPath()).thenReturn(sonarUserHomePath);
+ File workDir = temp.newFolder();
+ when(module.getWorkDir()).thenReturn(workDir.toPath());
+ hiddenFilesProjectData = spy(new HiddenFilesProjectData(sonarUserHome));
+ }
@Test
- public void visit_hidden_file() throws IOException {
+ public void should_not_visit_hidden_file() throws IOException {
+ when(moduleConfiguration.getBoolean("sonar.scanner.excludeHiddenFiles")).thenReturn(Optional.of(true));
DirectoryFileVisitor.FileVisitAction action = mock(DirectoryFileVisitor.FileVisitAction.class);
- File hidden = temp.newFile(".hidden");
- if (SystemUtils.IS_OS_WINDOWS) {
- Files.setAttribute(hidden.toPath(), "dos:hidden", true, LinkOption.NOFOLLOW_LINKS);
- }
-
+ File hidden = temp.newFile(".hiddenNotVisited");
+ setAsHiddenOnWindows(hidden);
- DirectoryFileVisitor underTest = new DirectoryFileVisitor(action, module, moduleExclusionFilters, inputModuleHierarchy, type);
+ DirectoryFileVisitor underTest = new DirectoryFileVisitor(action, module, moduleConfiguration, moduleExclusionFilters, inputModuleHierarchy, type, hiddenFilesProjectData);
underTest.visitFile(hidden.toPath(), Files.readAttributes(hidden.toPath(), BasicFileAttributes.class));
verify(action, never()).execute(any(Path.class));
}
@Test
+ public void should_visit_hidden_file() throws IOException {
+ when(moduleConfiguration.getBoolean("sonar.scanner.excludeHiddenFiles")).thenReturn(Optional.of(false));
+ DirectoryFileVisitor.FileVisitAction action = mock(DirectoryFileVisitor.FileVisitAction.class);
+
+ File hidden = temp.newFile(".hiddenVisited");
+ setAsHiddenOnWindows(hidden);
+
+ DirectoryFileVisitor underTest = new DirectoryFileVisitor(action, module, moduleConfiguration, moduleExclusionFilters, inputModuleHierarchy, type, hiddenFilesProjectData);
+ underTest.visitFile(hidden.toPath(), Files.readAttributes(hidden.toPath(), BasicFileAttributes.class));
+
+ verify(action).execute(any(Path.class));
+ }
+
+ @Test
public void test_visit_file_failed_generic_io_exception() throws IOException {
DirectoryFileVisitor.FileVisitAction action = mock(DirectoryFileVisitor.FileVisitAction.class);
File file = temp.newFile("failed");
- DirectoryFileVisitor underTest = new DirectoryFileVisitor(action, module, moduleExclusionFilters, inputModuleHierarchy, type);
+ DirectoryFileVisitor underTest = new DirectoryFileVisitor(action, module, moduleConfiguration, moduleExclusionFilters, inputModuleHierarchy, type, hiddenFilesProjectData);
assertThrows(IOException.class, () -> underTest.visitFileFailed(file.toPath(), new IOException()));
}
@@ -84,10 +114,15 @@ public class DirectoryFileVisitorTest {
File file = temp.newFile("symlink");
- DirectoryFileVisitor underTest = new DirectoryFileVisitor(action, module, moduleExclusionFilters, inputModuleHierarchy, type);
+ DirectoryFileVisitor underTest = new DirectoryFileVisitor(action, module, moduleConfiguration, moduleExclusionFilters, inputModuleHierarchy, type, hiddenFilesProjectData);
FileVisitResult result = underTest.visitFileFailed(file.toPath(), new FileSystemLoopException(file.getPath()));
assertThat(result).isEqualTo(FileVisitResult.CONTINUE);
}
+ private static void setAsHiddenOnWindows(File file) throws IOException {
+ if (SystemUtils.IS_OS_WINDOWS) {
+ Files.setAttribute(file.toPath(), "dos:hidden", true, LinkOption.NOFOLLOW_LINKS);
+ }
+ }
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/HiddenFilesProjectDataTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/HiddenFilesProjectDataTest.java
new file mode 100644
index 00000000000..d5a6e4ff843
--- /dev/null
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/HiddenFilesProjectDataTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.scan.filesystem;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import org.apache.commons.lang3.SystemUtils;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.scanner.bootstrap.SonarUserHome;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+public class HiddenFilesProjectDataTest {
+
+ @ClassRule
+ public static TemporaryFolder temp = new TemporaryFolder();
+
+ private static final SonarUserHome sonarUserHome = mock(SonarUserHome.class);
+ private final DefaultInputModule inputModule = mock(DefaultInputModule.class);
+ private final DefaultInputModule secondInputModule = mock(DefaultInputModule.class);
+ private HiddenFilesProjectData underTest;
+
+ @BeforeClass
+ public static void setUp() throws IOException {
+ File userHomeFolder = temp.newFolder(".userhome");
+ setAsHiddenOnWindows(userHomeFolder);
+ when(sonarUserHome.getPath()).thenReturn(userHomeFolder.toPath());
+ }
+
+ @Before
+ public void before() {
+ underTest = spy(new HiddenFilesProjectData(sonarUserHome));
+ }
+
+ @Test
+ public void shouldContainNoMarkedHiddenFileOnConstruction() {
+ assertThat(underTest.hiddenFilesByModule).isEmpty();
+ }
+
+ @Test
+ public void shouldMarkWithCorrectAssociatedInputModule() {
+ Path myFile = Path.of("myFile");
+ Path myFile2 = Path.of("myFile2");
+ underTest.markAsHiddenFile(myFile, inputModule);
+ underTest.markAsHiddenFile(myFile2, inputModule);
+
+ assertThat(underTest.hiddenFilesByModule).hasSize(1);
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile, inputModule)).isTrue();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile2, inputModule)).isTrue();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile, secondInputModule)).isFalse();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile2, secondInputModule)).isFalse();
+ }
+
+ @Test
+ public void shouldMarkWithCorrectAssociatedInputModuleForTwoDifferentModules() {
+ Path myFile = Path.of("myFile");
+ Path myFile2 = Path.of("myFile2");
+ underTest.markAsHiddenFile(myFile, inputModule);
+ underTest.markAsHiddenFile(myFile2, secondInputModule);
+
+ assertThat(underTest.hiddenFilesByModule).hasSize(2);
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile, inputModule)).isTrue();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile2, inputModule)).isFalse();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile, secondInputModule)).isFalse();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile2, secondInputModule)).isTrue();
+ }
+
+ @Test
+ public void shouldNotShowAsHiddenFileWhenInputModuleIsNotExistingInData() {
+ Path myFile = Path.of("myFile");
+ Path notMarkedFile = Path.of("notMarkedFile");
+ underTest.markAsHiddenFile(myFile, inputModule);
+
+ assertThat(underTest.hiddenFilesByModule).isNotEmpty();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(notMarkedFile, secondInputModule)).isFalse();
+ }
+
+ @Test
+ public void shouldClearMap() {
+ Path myFile = Path.of("myFile");
+ Path myFile2 = Path.of("myFile2");
+ underTest.markAsHiddenFile(myFile, inputModule);
+ underTest.markAsHiddenFile(myFile2, secondInputModule);
+
+ assertThat(underTest.hiddenFilesByModule).hasSize(2);
+
+ underTest.clearHiddenFilesData();
+ assertThat(underTest.hiddenFilesByModule).isEmpty();
+ }
+
+ @Test
+ public void shouldRemoveVisibilityAfterQuerying() {
+ Path myFile = Path.of("myFile");
+ Path myFile2 = Path.of("myFile2");
+ underTest.markAsHiddenFile(myFile, inputModule);
+ underTest.markAsHiddenFile(myFile2, inputModule);
+
+ assertThat(underTest.hiddenFilesByModule).hasSize(1);
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile, inputModule)).isTrue();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile2, inputModule)).isTrue();
+
+ assertThat(underTest.hiddenFilesByModule).hasSize(1);
+ assertThat(underTest.hiddenFilesByModule.get(inputModule)).isEmpty();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile, inputModule)).isFalse();
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile2, inputModule)).isFalse();
+ }
+
+ @Test
+ public void shouldOnlyRemoveModuleIfAllFilesAreRemoved() {
+ Path myFile = Path.of("myFile");
+ Path myFile2 = Path.of("myFile2");
+ underTest.markAsHiddenFile(myFile, inputModule);
+ underTest.markAsHiddenFile(myFile2, inputModule);
+
+ assertThat(underTest.hiddenFilesByModule).hasSize(1);
+ assertThat(underTest.getIsMarkedAsHiddenFileAndRemoveVisibilityInformation(myFile, inputModule)).isTrue();
+
+ assertThat(underTest.hiddenFilesByModule).isNotEmpty();
+ }
+
+ @Test
+ public void shouldNotFailOnUserPathResolving() throws IOException {
+ Path expectedPath = sonarUserHome.getPath().toRealPath(LinkOption.NOFOLLOW_LINKS).toAbsolutePath().normalize();
+ assertThat(underTest.getCachedSonarUserHomePath()).isEqualTo(expectedPath);
+ }
+
+ private static void setAsHiddenOnWindows(File file) throws IOException {
+ if (SystemUtils.IS_OS_WINDOWS) {
+ Files.setAttribute(file.toPath(), "dos:hidden", true, LinkOption.NOFOLLOW_LINKS);
+ }
+ }
+}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/HiddenFilesVisitorHelperTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/HiddenFilesVisitorHelperTest.java
new file mode 100644
index 00000000000..8c111c7ea15
--- /dev/null
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/HiddenFilesVisitorHelperTest.java
@@ -0,0 +1,315 @@
+/*
+ * 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.scan.filesystem;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.util.Optional;
+import org.apache.commons.lang3.SystemUtils;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.scanner.bootstrap.SonarUserHome;
+import org.sonar.scanner.scan.ModuleConfiguration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class HiddenFilesVisitorHelperTest {
+
+ @ClassRule
+ public static TemporaryFolder temp = new TemporaryFolder();
+
+ private static final SonarUserHome sonarUserHome = mock(SonarUserHome.class);
+ private static final DefaultInputModule inputModule = mock(DefaultInputModule.class);
+
+ private final ModuleConfiguration moduleConfig = mock(ModuleConfiguration.class);
+ private final HiddenFilesProjectData hiddenFilesProjectData = spy(new HiddenFilesProjectData(sonarUserHome));
+ private HiddenFilesVisitorHelper underTest;
+
+ @BeforeClass
+ public static void setUp() throws IOException {
+ File userHomeFolder = temp.newFolder(".userhome");
+ setAsHiddenOnWindows(userHomeFolder);
+ when(sonarUserHome.getPath()).thenReturn(userHomeFolder.toPath());
+
+ File workDir = temp.newFolder(".sonar");
+ setAsHiddenOnWindows(workDir);
+ when(inputModule.getWorkDir()).thenReturn(workDir.toPath());
+ }
+
+ @Before
+ public void before() {
+ hiddenFilesProjectData.clearHiddenFilesData();
+ underTest = spy(new HiddenFilesVisitorHelper(hiddenFilesProjectData, inputModule, moduleConfig));
+ }
+
+ @Test
+ public void verifyDefaultOnConstruction() {
+ assertThat(underTest.excludeHiddenFiles).isFalse();
+ assertThat(underTest.rootHiddenDir).isNull();
+ }
+
+ @Test
+ public void excludeHiddenFilesShouldBeSetToFalseFromConfigurationWhenNotConfigured() {
+ when(moduleConfig.getBoolean("sonar.scanner.excludeHiddenFiles")).thenReturn(Optional.empty());
+ HiddenFilesVisitorHelper configuredVisitorHelper = spy(new HiddenFilesVisitorHelper(hiddenFilesProjectData, inputModule, moduleConfig));
+
+ assertThat(configuredVisitorHelper.excludeHiddenFiles).isFalse();
+ }
+
+ @Test
+ public void excludeHiddenFilesShouldBeSetToFalseFromConfigurationWhenDisabled() {
+ when(moduleConfig.getBoolean("sonar.scanner.excludeHiddenFiles")).thenReturn(Optional.of(false));
+ HiddenFilesVisitorHelper configuredVisitorHelper = spy(new HiddenFilesVisitorHelper(hiddenFilesProjectData, inputModule, moduleConfig));
+
+ assertThat(configuredVisitorHelper.excludeHiddenFiles).isFalse();
+ }
+
+ @Test
+ public void excludeHiddenFilesShouldBeSetToTrueFromConfigurationWhenEnabled() {
+ when(moduleConfig.getBoolean("sonar.scanner.excludeHiddenFiles")).thenReturn(Optional.of(true));
+ HiddenFilesVisitorHelper configuredVisitorHelper = spy(new HiddenFilesVisitorHelper(hiddenFilesProjectData, inputModule, moduleConfig));
+
+ assertThat(configuredVisitorHelper.excludeHiddenFiles).isTrue();
+ }
+
+ @Test
+ public void shouldVisitHiddenDirectory() throws IOException {
+ File hiddenDir = temp.newFolder(".hiddenVisited");
+ setAsHiddenOnWindows(hiddenDir);
+
+ boolean visitDir = underTest.shouldVisitDir(hiddenDir.toPath());
+
+ assertThat(visitDir).isTrue();
+ assertThat(underTest.insideHiddenDirectory()).isTrue();
+ assertThat(underTest.rootHiddenDir).isEqualTo(hiddenDir.toPath());
+ verify(underTest).enterHiddenDirectory(hiddenDir.toPath());
+ }
+
+ @Test
+ public void shouldNotVisitHiddenDirectoryWhenHiddenFilesVisitIsExcluded() throws IOException {
+ when(moduleConfig.getBoolean("sonar.scanner.excludeHiddenFiles")).thenReturn(Optional.of(true));
+ HiddenFilesVisitorHelper configuredVisitorHelper = spy(new HiddenFilesVisitorHelper(hiddenFilesProjectData, inputModule, moduleConfig));
+
+ File hidden = temp.newFolder(".hiddenNotVisited");
+ setAsHiddenOnWindows(hidden);
+
+ boolean visitDir = configuredVisitorHelper.shouldVisitDir(hidden.toPath());
+
+ assertThat(visitDir).isFalse();
+ assertThat(configuredVisitorHelper.insideHiddenDirectory()).isFalse();
+ verify(configuredVisitorHelper, never()).enterHiddenDirectory(any());
+ }
+
+ @Test
+ public void shouldVisitNonHiddenDirectoryWhenHiddenFilesVisitIsExcluded() throws IOException {
+ when(moduleConfig.getBoolean("sonar.scanner.excludeHiddenFiles")).thenReturn(Optional.of(true));
+ HiddenFilesVisitorHelper configuredVisitorHelper = spy(new HiddenFilesVisitorHelper(hiddenFilesProjectData, inputModule, moduleConfig));
+
+ File nonHiddenFolder = temp.newFolder();
+
+ boolean visitDir = configuredVisitorHelper.shouldVisitDir(nonHiddenFolder.toPath());
+
+ assertThat(visitDir).isTrue();
+ assertThat(configuredVisitorHelper.insideHiddenDirectory()).isFalse();
+ verify(configuredVisitorHelper, never()).enterHiddenDirectory(any());
+ }
+
+ @Test
+ public void shouldVisitNonHiddenDirectory() throws IOException {
+ File nonHiddenFolder = temp.newFolder();
+
+ boolean visitDir = underTest.shouldVisitDir(nonHiddenFolder.toPath());
+
+ assertThat(visitDir).isTrue();
+ assertThat(underTest.insideHiddenDirectory()).isFalse();
+ verify(underTest, never()).enterHiddenDirectory(any());
+ assertThat(underTest.excludeHiddenFiles).isFalse();
+ }
+
+ @Test
+ public void shouldNotVisitModuleWorkDir() throws IOException {
+ Path workingDirectory = inputModule.getWorkDir().toRealPath(LinkOption.NOFOLLOW_LINKS).toAbsolutePath().normalize();
+ boolean visitDir = underTest.shouldVisitDir(workingDirectory);
+
+ assertThat(visitDir).isFalse();
+ assertThat(underTest.insideHiddenDirectory()).isFalse();
+ verify(underTest, never()).enterHiddenDirectory(any());
+ }
+
+ @Test
+ public void shouldNotVisitSonarUserHome() throws IOException {
+ Path userHome = sonarUserHome.getPath().toRealPath(LinkOption.NOFOLLOW_LINKS).toAbsolutePath().normalize();
+ boolean visitDir = underTest.shouldVisitDir(userHome);
+
+ assertThat(visitDir).isFalse();
+ assertThat(underTest.insideHiddenDirectory()).isFalse();
+ verify(underTest, never()).enterHiddenDirectory(any());
+ }
+
+ @Test
+ public void hiddenFileShouldBeVisited() throws IOException {
+ File hiddenFile = temp.newFile(".hiddenFileShouldBeVisited");
+ setAsHiddenOnWindows(hiddenFile);
+
+ assertThat(underTest.insideHiddenDirectory()).isFalse();
+ boolean visitFile = underTest.shouldVisitFile(hiddenFile.toPath());
+
+ assertThat(visitFile).isTrue();
+ verify(hiddenFilesProjectData).markAsHiddenFile(hiddenFile.toPath(), inputModule);
+ }
+
+ @Test
+ public void nonHiddenFileShouldBeVisitedInHiddenFolder() throws IOException {
+ File hidden = temp.newFolder(".hiddenFolder");
+ setAsHiddenOnWindows(hidden);
+
+ File nonHiddenFile = temp.newFile();
+
+ underTest.shouldVisitDir(hidden.toPath());
+ assertThat(underTest.insideHiddenDirectory()).isTrue();
+
+ boolean shouldVisitFile = underTest.shouldVisitFile(nonHiddenFile.toPath());
+
+ assertThat(shouldVisitFile).isTrue();
+ verify(hiddenFilesProjectData).markAsHiddenFile(nonHiddenFile.toPath(), inputModule);
+ }
+
+ @Test
+ public void shouldNotSetAsRootHiddenDirectoryWhenAlreadyEnteredHiddenDirectory() throws IOException {
+ File hidden = temp.newFolder(".outerHiddenFolder");
+ File nestedHiddenFolder = temp.newFolder(".outerHiddenFolder", ".nestedHiddenFolder");
+ setAsHiddenOnWindows(hidden);
+ setAsHiddenOnWindows(nestedHiddenFolder);
+
+ underTest.shouldVisitDir(hidden.toPath());
+ assertThat(underTest.insideHiddenDirectory()).isTrue();
+
+ boolean shouldVisitNestedDir = underTest.shouldVisitDir(nestedHiddenFolder.toPath());
+
+ assertThat(shouldVisitNestedDir).isTrue();
+ assertThat(underTest.rootHiddenDir).isEqualTo(hidden.toPath());
+ verify(underTest).enterHiddenDirectory(nestedHiddenFolder.toPath());
+ }
+
+ @Test
+ public void hiddenFileShouldNotBeVisitedWhenHiddenFileVisitExcluded() throws IOException {
+ when(moduleConfig.getBoolean("sonar.scanner.excludeHiddenFiles")).thenReturn(Optional.of(true));
+ HiddenFilesVisitorHelper configuredVisitorHelper = spy(new HiddenFilesVisitorHelper(hiddenFilesProjectData, inputModule, moduleConfig));
+
+ File hiddenFile = temp.newFile(".hiddenFileNotVisited");
+ setAsHiddenOnWindows(hiddenFile);
+
+ assertThat(configuredVisitorHelper.insideHiddenDirectory()).isFalse();
+
+ configuredVisitorHelper.shouldVisitFile(hiddenFile.toPath());
+ boolean shouldVisitFile = configuredVisitorHelper.shouldVisitFile(hiddenFile.toPath());
+
+ assertThat(shouldVisitFile).isFalse();
+ verify(hiddenFilesProjectData, never()).markAsHiddenFile(hiddenFile.toPath(), inputModule);
+ }
+
+ @Test
+ public void shouldCorrectlyExitHiddenFolderOnlyOnHiddenFolderThatEntered() throws IOException {
+ File hiddenFolder = temp.newFolder(".hiddenRootFolder");
+ setAsHiddenOnWindows(hiddenFolder);
+
+ boolean shouldVisitDir = underTest.shouldVisitDir(hiddenFolder.toPath());
+
+ assertThat(shouldVisitDir).isTrue();
+ assertThat(underTest.insideHiddenDirectory()).isTrue();
+ assertThat(underTest.rootHiddenDir).isEqualTo(hiddenFolder.toPath());
+ verify(underTest).enterHiddenDirectory(hiddenFolder.toPath());
+
+ File folder1 = temp.newFolder(".hiddenRootFolder", "myFolderExit");
+ File folder2 = temp.newFolder("myFolderExit");
+ File folder3 = temp.newFolder(".myFolderExit");
+ setAsHiddenOnWindows(folder3);
+
+ underTest.exitDirectory(folder1.toPath());
+ underTest.exitDirectory(folder2.toPath());
+ underTest.exitDirectory(folder3.toPath());
+
+ assertThat(underTest.insideHiddenDirectory()).isTrue();
+ assertThat(underTest.rootHiddenDir).isEqualTo(hiddenFolder.toPath());
+ verify(underTest, never()).resetRootHiddenDir();
+
+ underTest.exitDirectory(hiddenFolder.toPath());
+ assertThat(underTest.insideHiddenDirectory()).isFalse();
+ assertThat(underTest.rootHiddenDir).isNull();
+ verify(underTest).resetRootHiddenDir();
+ }
+
+ @Test
+ public void shouldNotInitiateResetRootDirWhenNotInHiddenDirectory() throws IOException {
+ File hiddenFolder = temp.newFolder(".hiddenFolderNonRoot");
+ setAsHiddenOnWindows(hiddenFolder);
+
+ underTest.exitDirectory(hiddenFolder.toPath());
+
+ verify(underTest, never()).resetRootHiddenDir();
+ }
+
+ @Test
+ public void filesShouldBeCorrectlyMarkedAsHidden() throws IOException {
+ File hiddenFolder = temp.newFolder(".hiddenFolderRoot");
+ setAsHiddenOnWindows(hiddenFolder);
+
+ File file1 = temp.newFile();
+ File file2 = temp.newFile();
+ File file3 = temp.newFile(".markedHiddenFile");
+ setAsHiddenOnWindows(file3);
+ File file4 = temp.newFile();
+ File file5 = temp.newFile(".markedHiddenFile2");
+ setAsHiddenOnWindows(file5);
+
+ underTest.shouldVisitFile(file1.toPath());
+ underTest.shouldVisitDir(hiddenFolder.toPath());
+ underTest.shouldVisitFile(file2.toPath());
+ underTest.shouldVisitFile(file3.toPath());
+ underTest.exitDirectory(hiddenFolder.toPath());
+ underTest.shouldVisitFile(file4.toPath());
+ underTest.shouldVisitFile(file5.toPath());
+
+ verify(hiddenFilesProjectData, never()).markAsHiddenFile(file1.toPath(), inputModule);
+ verify(hiddenFilesProjectData).markAsHiddenFile(file2.toPath(), inputModule);
+ verify(hiddenFilesProjectData).markAsHiddenFile(file3.toPath(), inputModule);
+ verify(hiddenFilesProjectData, never()).markAsHiddenFile(file4.toPath(), inputModule);
+ verify(hiddenFilesProjectData).markAsHiddenFile(file5.toPath(), inputModule);
+ }
+
+ private static void setAsHiddenOnWindows(File file) throws IOException {
+ if (SystemUtils.IS_OS_WINDOWS) {
+ Files.setAttribute(file.toPath(), "dos:hidden", true, LinkOption.NOFOLLOW_LINKS);
+ }
+ }
+}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java
index a0031f77633..07f7afec036 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java
@@ -19,80 +19,151 @@
*/
package org.sonar.scanner.scan.filesystem;
-import java.io.IOException;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import java.io.File;
+import java.util.List;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.sonar.api.SonarRuntime;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputModule;
import org.sonar.api.batch.fs.internal.SensorStrategy;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-public class ModuleInputComponentStoreTest {
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
+@ExtendWith(MockitoExtension.class)
+class ModuleInputComponentStoreTest {
+
+ @TempDir
+ private File projectBaseDir;
+
+ @Mock
+ BranchConfiguration branchConfiguration;
+
+ @Mock
+ SonarRuntime sonarRuntime;
+
+ @Mock
+ InputComponentStore mockedInputComponentStore;
private InputComponentStore componentStore;
+ private SensorContextTester sensorContextTester;
private final String projectKey = "dummy key";
- @Before
- public void setUp() throws IOException {
- DefaultInputProject root = TestInputFileBuilder.newDefaultInputProject(projectKey, temp.newFolder());
- componentStore = new InputComponentStore(mock(BranchConfiguration.class), mock(SonarRuntime.class));
+ @BeforeEach
+ void setUp() {
+ TestInputFileBuilder.newDefaultInputProject(projectKey, projectBaseDir);
+ File moduleBaseDir = new File(projectBaseDir, "module");
+ moduleBaseDir.mkdir();
+ sensorContextTester = SensorContextTester.create(moduleBaseDir);
+ componentStore = spy(new InputComponentStore(branchConfiguration, sonarRuntime));
}
@Test
- public void should_cache_files_by_filename() {
+ void should_cache_module_files_by_filename() {
ModuleInputComponentStore store = newModuleInputComponentStore();
String filename = "some name";
- InputFile inputFile1 = new TestInputFileBuilder(projectKey, "some/path/" + filename).build();
+ InputFile inputFile1 = new TestInputFileBuilder(projectKey, "module/some/path/" + filename).build();
store.doAdd(inputFile1);
- InputFile inputFile2 = new TestInputFileBuilder(projectKey, "other/path/" + filename).build();
+ InputFile inputFile2 = new TestInputFileBuilder(projectKey, "module/other/path/" + filename).build();
store.doAdd(inputFile2);
- InputFile dummyInputFile = new TestInputFileBuilder(projectKey, "some/path/Dummy.java").build();
+ InputFile dummyInputFile = new TestInputFileBuilder(projectKey, "module/some/path/Dummy.java").build();
store.doAdd(dummyInputFile);
assertThat(store.getFilesByName(filename)).containsExactlyInAnyOrder(inputFile1, inputFile2);
}
@Test
- public void should_cache_files_by_extension() {
+ void should_cache_filtered_module_files_by_filename() {
+ ModuleInputComponentStore store = newModuleInputComponentStore();
+
+ String filename = "some name";
+ InputFile inputFile1 = new TestInputFileBuilder(projectKey, "some/path/" + filename).build();
+ InputFile inputFile2 = new TestInputFileBuilder(projectKey, "module/other/path/" + filename).build();
+ store.doAdd(inputFile2);
+
+ when(componentStore.getFilesByName(filename)).thenReturn(List.of(inputFile1, inputFile2));
+
+ assertThat(store.getFilesByName(filename)).containsOnly(inputFile2);
+ }
+
+ @Test
+ void should_cache_module_files_by_filename_global_strategy() {
+ ModuleInputComponentStore store = new ModuleInputComponentStore(sensorContextTester.module(), componentStore, new SensorStrategy());
+
+ String filename = "some name";
+ // None in the module
+ InputFile inputFile1 = new TestInputFileBuilder(projectKey, "some/path/" + filename).build();
+ InputFile inputFile2 = new TestInputFileBuilder(projectKey, "other/path/" + filename).build();
+
+ when(componentStore.getFilesByName(filename)).thenReturn(List.of(inputFile1, inputFile2));
+
+ assertThat(store.getFilesByName(filename)).containsExactlyInAnyOrder(inputFile1, inputFile2);
+ }
+
+ @Test
+ void should_cache_module_files_by_extension() {
ModuleInputComponentStore store = newModuleInputComponentStore();
- InputFile inputFile1 = new TestInputFileBuilder(projectKey, "some/path/Program.java").build();
+ InputFile inputFile1 = new TestInputFileBuilder(projectKey, "module/some/path/Program.java").build();
store.doAdd(inputFile1);
- InputFile inputFile2 = new TestInputFileBuilder(projectKey, "other/path/Utils.java").build();
+ InputFile inputFile2 = new TestInputFileBuilder(projectKey, "module/other/path/Utils.java").build();
store.doAdd(inputFile2);
- InputFile dummyInputFile = new TestInputFileBuilder(projectKey, "some/path/NotJava.cpp").build();
+ InputFile dummyInputFile = new TestInputFileBuilder(projectKey, "module/some/path/NotJava.cpp").build();
store.doAdd(dummyInputFile);
assertThat(store.getFilesByExtension("java")).containsExactlyInAnyOrder(inputFile1, inputFile2);
}
@Test
- public void should_not_cache_duplicates() {
+ void should_cache_filtered_module_files_by_extension() {
+ ModuleInputComponentStore store = newModuleInputComponentStore();
+
+ InputFile inputFile1 = new TestInputFileBuilder(projectKey, "some/path/NotInModule.java").build();
+ InputFile inputFile2 = new TestInputFileBuilder(projectKey, "module/some/path/Other.java").build();
+ store.doAdd(inputFile2);
+
+ when(componentStore.getFilesByExtension("java")).thenReturn(List.of(inputFile1, inputFile2));
+
+ assertThat(store.getFilesByExtension("java")).containsOnly(inputFile2);
+ }
+
+ @Test
+ void should_cache_module_files_by_extension_global_strategy() {
+ ModuleInputComponentStore store = new ModuleInputComponentStore(sensorContextTester.module(), componentStore, new SensorStrategy());
+
+ // None in the module
+ InputFile inputFile1 = new TestInputFileBuilder(projectKey, "some/path/NotInModule.java").build();
+ InputFile inputFile2 = new TestInputFileBuilder(projectKey, "some/path/Other.java").build();
+
+ when(componentStore.getFilesByExtension("java")).thenReturn(List.of(inputFile1, inputFile2));
+
+ assertThat(store.getFilesByExtension("java")).containsExactlyInAnyOrder(inputFile1, inputFile2);
+ }
+
+ @Test
+ void should_not_cache_duplicates() {
ModuleInputComponentStore store = newModuleInputComponentStore();
String ext = "java";
String filename = "Program." + ext;
- InputFile inputFile = new TestInputFileBuilder(projectKey, "some/path/" + filename).build();
+ InputFile inputFile = new TestInputFileBuilder(projectKey, "module/some/path/" + filename).build();
store.doAdd(inputFile);
store.doAdd(inputFile);
store.doAdd(inputFile);
@@ -102,12 +173,12 @@ public class ModuleInputComponentStoreTest {
}
@Test
- public void should_get_empty_iterable_on_cache_miss() {
+ void should_get_empty_iterable_on_cache_miss() {
ModuleInputComponentStore store = newModuleInputComponentStore();
String ext = "java";
String filename = "Program." + ext;
- InputFile inputFile = new TestInputFileBuilder(projectKey, "some/path/" + filename).build();
+ InputFile inputFile = new TestInputFileBuilder(projectKey, "module/some/path/" + filename).build();
store.doAdd(inputFile);
assertThat(store.getFilesByName("nonexistent")).isEmpty();
@@ -115,48 +186,42 @@ public class ModuleInputComponentStoreTest {
}
private ModuleInputComponentStore newModuleInputComponentStore() {
- InputModule module = mock(InputModule.class);
- when(module.key()).thenReturn("moduleKey");
- return new ModuleInputComponentStore(module, componentStore, mock(SensorStrategy.class));
+ SensorStrategy strategy = new SensorStrategy();
+ strategy.setGlobal(false);
+ return new ModuleInputComponentStore(sensorContextTester.module(), componentStore, strategy);
}
@Test
- public void should_find_module_components_with_non_global_strategy() {
- InputComponentStore inputComponentStore = mock(InputComponentStore.class);
+ void should_find_module_components_with_non_global_strategy() {
SensorStrategy strategy = new SensorStrategy();
- InputModule module = mock(InputModule.class);
- when(module.key()).thenReturn("foo");
- ModuleInputComponentStore store = new ModuleInputComponentStore(module, inputComponentStore, strategy);
+ ModuleInputComponentStore store = new ModuleInputComponentStore(sensorContextTester.module(), mockedInputComponentStore, strategy);
strategy.setGlobal(false);
store.inputFiles();
- verify(inputComponentStore).filesByModule("foo");
+ verify(mockedInputComponentStore).filesByModule(sensorContextTester.module().key());
String relativePath = "somepath";
store.inputFile(relativePath);
- verify(inputComponentStore).getFile(any(String.class), eq(relativePath));
+ verify(mockedInputComponentStore).getFile(any(String.class), eq(relativePath));
store.languages();
- verify(inputComponentStore).languages(any(String.class));
+ verify(mockedInputComponentStore).languages(any(String.class));
}
@Test
- public void should_find_all_components_with_global_strategy() {
- InputComponentStore inputComponentStore = mock(InputComponentStore.class);
+ void should_find_all_components_with_global_strategy() {
SensorStrategy strategy = new SensorStrategy();
- ModuleInputComponentStore store = new ModuleInputComponentStore(mock(InputModule.class), inputComponentStore, strategy);
-
- strategy.setGlobal(true);
+ ModuleInputComponentStore store = new ModuleInputComponentStore(sensorContextTester.module(), mockedInputComponentStore, strategy);
store.inputFiles();
- verify(inputComponentStore).inputFiles();
+ verify(mockedInputComponentStore).inputFiles();
String relativePath = "somepath";
store.inputFile(relativePath);
- verify(inputComponentStore).inputFile(relativePath);
+ verify(mockedInputComponentStore).inputFile(relativePath);
store.languages();
- verify(inputComponentStore).languages();
+ verify(mockedInputComponentStore).languages();
}
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MutableFileSystemTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MutableFileSystemTest.java
index 31d3312853b..485708c9936 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MutableFileSystemTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MutableFileSystemTest.java
@@ -28,6 +28,9 @@ import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
public class MutableFileSystemTest {
@@ -44,9 +47,15 @@ public class MutableFileSystemTest {
}
@Test
- public void return_all_files_when_not_restricted() {
+ public void restriction_and_hidden_file_should_be_disabled_on_default() {
+ assertThat(underTest.restrictToChangedFiles).isFalse();
+ assertThat(underTest.allowHiddenFileAnalysis).isFalse();
+ }
+
+ @Test
+ public void return_all_non_hidden_files_when_not_restricted_and_disabled() {
assertThat(underTest.inputFiles(underTest.predicates().all())).isEmpty();
- addFileWithAllStatus();
+ addFilesWithAllStatus();
underTest.setRestrictToChangedFiles(false);
assertThat(underTest.inputFiles(underTest.predicates().all())).hasSize(3);
@@ -58,7 +67,7 @@ public class MutableFileSystemTest {
@Test
public void return_only_changed_files_when_restricted() {
assertThat(underTest.inputFiles(underTest.predicates().all())).isEmpty();
- addFileWithAllStatus();
+ addFilesWithAllStatus();
underTest.setRestrictToChangedFiles(true);
assertThat(underTest.inputFiles(underTest.predicates().all())).hasSize(2);
@@ -67,19 +76,95 @@ public class MutableFileSystemTest {
assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(InputFile.Status.CHANGED)))).isNotNull();
}
- private void addFileWithAllStatus() {
+ @Test
+ public void return_all_files_when_allowing_hidden_files_analysis() {
+ assertThat(underTest.inputFiles(underTest.predicates().all())).isEmpty();
+ addFilesWithVisibility();
+ underTest.setAllowHiddenFileAnalysis(true);
+
+ assertThat(underTest.inputFiles(underTest.predicates().all())).hasSize(2);
+ assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(true)))).isNotNull();
+ assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(false)))).isNotNull();
+ }
+
+ @Test
+ public void return_only_non_hidden_files_when_not_allowing_hidden_files_analysis() {
+ assertThat(underTest.inputFiles(underTest.predicates().all())).isEmpty();
+ addFilesWithVisibility();
+ underTest.setAllowHiddenFileAnalysis(false);
+
+ assertThat(underTest.inputFiles(underTest.predicates().all())).hasSize(1);
+ assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(true)))).isNull();
+ assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(false)))).isNotNull();
+ }
+
+ @Test
+ public void hidden_file_predicate_should_preserve_predicate_optimization() {
+ addFilesWithVisibility();
+ var anotherHiddenFile = spy(new TestInputFileBuilder("foo", String.format("src/%s", ".myHiddenFile.txt"))
+ .setLanguage(LANGUAGE).setStatus(InputFile.Status.ADDED).setHidden(true).build());
+ underTest.add(anotherHiddenFile);
+ underTest.setAllowHiddenFileAnalysis(false);
+
+ assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(true)))).isNull();
+ assertThat(underTest.inputFile(underTest.predicates().hasFilename(generateFilename(false)))).isNotNull();
+ // Verify that predicate optimization is still effective
+ verify(anotherHiddenFile, never()).isHidden();
+
+ // This predicate can't be optimized
+ assertThat(underTest.inputFiles(underTest.predicates().all())).hasSize(1);
+ verify(anotherHiddenFile).isHidden();
+ }
+
+ @Test
+ public void hidden_file_predicate_should_be_applied_first_for_non_optimized_predicates() {
+ // Checking the file type is not very costly, but it is not optimized. In real life, something more costly would be reading the file
+ // content, for example.
+ addFilesWithVisibility();
+ var anotherHiddenFile = spy(new TestInputFileBuilder("foo", String.format("src/%s", ".myHiddenFile." + LANGUAGE))
+ .setLanguage(LANGUAGE).setType(InputFile.Type.MAIN).setStatus(InputFile.Status.ADDED).setHidden(true).build());
+ underTest.add(anotherHiddenFile);
+ underTest.setAllowHiddenFileAnalysis(false);
+
+ assertThat(underTest.inputFiles(underTest.predicates().hasType(InputFile.Type.MAIN))).hasSize(1);
+ // Verify that the file type has not been evaluated
+ verify(anotherHiddenFile, never()).type();
+ }
+
+ private void addFilesWithVisibility() {
+ addFile(true);
+ addFile(false);
+ }
+
+ private void addFilesWithAllStatus() {
addFile(InputFile.Status.ADDED);
addFile(InputFile.Status.CHANGED);
addFile(InputFile.Status.SAME);
}
private void addFile(InputFile.Status status) {
- underTest.add(new TestInputFileBuilder("foo", String.format("src/%s", generateFilename(status)))
- .setLanguage(LANGUAGE).setStatus(status).build());
+ addFile(status, false);
+ }
+
+ private void addFile(boolean hidden) {
+ addFile(InputFile.Status.SAME, hidden);
+ }
+
+ private void addFile(InputFile.Status status, boolean hidden) {
+ underTest.add(new TestInputFileBuilder("foo", String.format("src/%s", generateFilename(status, hidden)))
+ .setLanguage(LANGUAGE).setType(InputFile.Type.MAIN).setStatus(status).setHidden(hidden).build());
+ }
+
+ private String generateFilename(boolean hidden) {
+ return generateFilename(InputFile.Status.SAME, hidden);
}
private String generateFilename(InputFile.Status status) {
- return String.format("%s.%s", status.name().toLowerCase(Locale.ROOT), LANGUAGE);
+ return generateFilename(status, false);
+ }
+
+ private String generateFilename(InputFile.Status status, boolean hidden) {
+ return String.format("%s.%s.%s", status.name().toLowerCase(Locale.ROOT), hidden, LANGUAGE);
}
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
index e769e0d6451..355fb2cde0e 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
@@ -19,16 +19,6 @@
*/
package org.sonar.scanner.sensor;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.assertj.core.data.MapEntry.entry;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@@ -77,6 +67,16 @@ import org.sonar.scanner.repository.ContextPropertiesCache;
import org.sonar.scanner.repository.TelemetryCache;
import org.sonar.scanner.scan.branch.BranchConfiguration;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.data.MapEntry.entry;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
class DefaultSensorStorageTest {
@TempDir
@@ -97,7 +97,6 @@ class DefaultSensorStorageTest {
public void prepare() {
MetricFinder metricFinder = mock(MetricFinder.class);
when(metricFinder.<Integer>findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
- when(metricFinder.<String>findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
when(metricFinder.<Integer>findByKey(CoreMetrics.LINES_TO_COVER_KEY)).thenReturn(CoreMetrics.LINES_TO_COVER);
settings = new MapSettings();
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java
index 4ab9f46fb4a..3a0ff7fb4c2 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java
@@ -68,7 +68,7 @@ class ModuleSensorContextTest {
@BeforeEach
void prepare() {
fs = new DefaultFileSystem(temp);
- underTest = new ModuleSensorContext(mock(DefaultInputProject.class), mock(InputModule.class), settings.asConfig(), settings, fs, activeRules, sensorStorage, runtime,
+ underTest = new ModuleSensorContext(mock(DefaultInputProject.class), mock(InputModule.class), settings.asConfig(), fs, activeRules, sensorStorage, runtime,
branchConfiguration, writeCache, readCache, analysisCacheEnabled, unchangedFilesHandler, executingSensorContext, pluginRepository);
}
@@ -104,7 +104,7 @@ class ModuleSensorContextTest {
@Test
void pull_request_can_skip_unchanged_files() {
when(branchConfiguration.isPullRequest()).thenReturn(true);
- underTest = new ModuleSensorContext(mock(DefaultInputProject.class), mock(InputModule.class), settings.asConfig(), settings, fs, activeRules, sensorStorage, runtime,
+ underTest = new ModuleSensorContext(mock(DefaultInputProject.class), mock(InputModule.class), settings.asConfig(), fs, activeRules, sensorStorage, runtime,
branchConfiguration, writeCache, readCache, analysisCacheEnabled, unchangedFilesHandler, executingSensorContext, pluginRepository);
assertThat(underTest.canSkipUnchangedFiles()).isTrue();
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ProjectSensorContextTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ProjectSensorContextTest.java
index 3c7f3d36793..01c337a5ed0 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ProjectSensorContextTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ProjectSensorContextTest.java
@@ -59,8 +59,8 @@ class ProjectSensorContextTest {
private ExecutingSensorContext executingSensorContext = mock(ExecutingSensorContext.class);
private ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class);
- private ProjectSensorContext underTest = new ProjectSensorContext(mock(DefaultInputProject.class), settings.asConfig(), settings, fs, activeRules, sensorStorage, runtime,
- branchConfiguration, writeCache, readCache, analysisCacheEnabled, unchangedFilesHandler, executingSensorContext, pluginRepository);
+ private ProjectSensorContext underTest = new ProjectSensorContext(mock(DefaultInputProject.class), settings.asConfig(), fs, activeRules, sensorStorage, runtime,
+ branchConfiguration, writeCache, readCache, analysisCacheEnabled, unchangedFilesHandler, executingSensorContext, pluginRepository);
private static final String PLUGIN_KEY = "org.sonarsource.pluginKey";
@@ -69,7 +69,6 @@ class ProjectSensorContextTest {
when(executingSensorContext.getSensorExecuting()).thenReturn(new SensorId(PLUGIN_KEY, "sensorName"));
}
-
@Test
void addTelemetryProperty_whenTheOrganizationIsSonarSource_mustStoreTheTelemetry() {
@@ -77,16 +76,21 @@ class ProjectSensorContextTest {
underTest.addTelemetryProperty("key", "value");
- //then verify that the defaultStorage is called with the telemetry property once
+ // then verify that the defaultStorage is called with the telemetry property once
verify(sensorStorage).storeTelemetry("key", "value");
}
@Test
- void addTelemetryProperty_whenTheOrganizationIsNotSonarSource_mustThrowExcaption() {
+ void addTelemetryProperty_whenTheOrganizationIsNotSonarSource_mustThrowException() {
when(pluginRepository.getPluginInfo(PLUGIN_KEY)).thenReturn(new PluginInfo(PLUGIN_KEY).setOrganizationName("notSonarsource"));
assertThrows(IllegalStateException.class, () -> underTest.addTelemetryProperty("key", "value"));
verifyNoInteractions(sensorStorage);
}
+
+ @Test
+ void settings_throwsUnsupportedOperationException() {
+ assertThrows(UnsupportedOperationException.class, () -> underTest.settings());
+ }
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedFileTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedFileTest.java
index fe637015ed7..91f59b964b9 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedFileTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedFileTest.java
@@ -88,7 +88,7 @@ public class ChangedFileTest {
secure().next(5),
Integer.parseInt(secure().nextNumeric(5)),
new SensorStrategy(),
- oldRelativePath);
+ oldRelativePath, false);
}
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitUtilsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitUtilsTest.java
index 383e2a1d643..d8264a5745b 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitUtilsTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitUtilsTest.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
+import org.apache.commons.lang.SystemUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.junit.jupiter.api.Test;
@@ -46,7 +47,11 @@ class JGitUtilsTest {
// in directory1, the entire directory is ignored without listing each file
// in directory2, specific files are ignored, so those files are listed
// in directory3, specific files are ignored via a separate .gitignore file
- assertThat(result).isEqualTo(List.of("directory1", "directory2/file_a.txt", "directory3/file_b.txt"));
+ if (SystemUtils.IS_OS_WINDOWS) {
+ assertThat(result).isEqualTo(List.of("directory1", "directory2\\file_a.txt", "directory3\\file_b.txt"));
+ } else {
+ assertThat(result).isEqualTo(List.of("directory1", "directory2/file_a.txt", "directory3/file_b.txt"));
+ }
}
@Test
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/NativeGitBlameCommandTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/NativeGitBlameCommandTest.java
index 68b7e1b7bd2..23d5e6ca5f0 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/NativeGitBlameCommandTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/NativeGitBlameCommandTest.java
@@ -159,14 +159,14 @@ class NativeGitBlameCommandTest {
ProcessWrapperFactory mockFactory = mock(ProcessWrapperFactory.class);
ProcessWrapper mockProcess = mock(ProcessWrapper.class);
String gitCommand = "git";
- when(mockFactory.create(any(), any(), anyString(), anyString(), anyString(), anyString(),
+ when(mockFactory.create(any(), any(), any(), anyString(), anyString(), anyString(), anyString(),
anyString(), anyString(), anyString(), anyString(), anyString(), anyString()))
- .then(invocation -> mockProcess);
+ .then(invocation -> mockProcess);
NativeGitBlameCommand blameCommand = new NativeGitBlameCommand(gitCommand, System2.INSTANCE, mockFactory);
blameCommand.blame(baseDir.toPath(), DUMMY_JAVA);
- verify(mockFactory).create(any(), any(), eq(gitCommand),
+ verify(mockFactory).create(any(), any(), any(), eq(gitCommand),
eq(GIT_DIR_FLAG),
eq(String.format(GIT_DIR_ARGUMENT, baseDir.toPath())),
eq(GIT_DIR_FORCE_FLAG),
@@ -238,7 +238,7 @@ class NativeGitBlameCommandTest {
"git version 2.25.1.msysgit.2").forEach(output -> {
ProcessWrapperFactory mockedCmd = mockGitVersionCommand(output);
mockGitWhereOnWindows(mockedCmd);
- when(mockedCmd.create(isNull(), any(), eq("C:\\mockGit.exe"), eq("--version"))).then(invocation -> {
+ when(mockedCmd.create(isNull(), any(), any(), eq("C:\\mockGit.exe"), eq("--version"))).then(invocation -> {
var argument = (Consumer<String>) invocation.getArgument(1);
argument.accept(output);
return mock(ProcessWrapper.class);
@@ -303,7 +303,7 @@ class NativeGitBlameCommandTest {
ProcessWrapper mockProcess = mock(ProcessWrapper.class);
mockGitWhereOnWindows(mockFactory);
- when(mockFactory.create(isNull(), any(), eq("C:\\mockGit.exe"), eq("--version"))).then(invocation -> {
+ when(mockFactory.create(isNull(), any(), any(), eq("C:\\mockGit.exe"), eq("--version"))).then(invocation -> {
var argument = (Consumer<String>) invocation.getArgument(1);
argument.accept("git version 2.30.1");
return mockProcess;
@@ -346,7 +346,7 @@ class NativeGitBlameCommandTest {
}
private void mockGitWhereOnWindows(ProcessWrapperFactory processWrapperFactory) {
- when(processWrapperFactory.create(isNull(), any(), eq("C:\\Windows\\System32\\where.exe"), eq("$PATH:git.exe"))).then(invocation -> {
+ when(processWrapperFactory.create(isNull(), any(), any(), eq("C:\\Windows\\System32\\where.exe"), eq("$PATH:git.exe"))).then(invocation -> {
var argument = (Consumer<String>) invocation.getArgument(1);
argument.accept("C:\\mockGit.exe");
return mock(ProcessWrapper.class);
@@ -357,7 +357,7 @@ class NativeGitBlameCommandTest {
ProcessWrapperFactory mockFactory = mock(ProcessWrapperFactory.class);
ProcessWrapper mockProcess = mock(ProcessWrapper.class);
- when(mockFactory.create(isNull(), any(), eq("git"), eq("--version"))).then(invocation -> {
+ when(mockFactory.create(isNull(), any(), any(), eq("git"), eq("--version"))).then(invocation -> {
var argument = (Consumer<String>) invocation.getArgument(1);
argument.accept(commandOutput);
return mockProcess;