diff options
Diffstat (limited to 'sonar-scanner-engine/src/test/java')
202 files changed, 2412 insertions, 522 deletions
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/BatchTest.java b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/BatchTest.java index aedaef25432..d19d6e8c51e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/BatchTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/BatchTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/EnvironmentInformationTest.java b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/EnvironmentInformationTest.java index abfb64b85e0..c1aec9a17ea 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/EnvironmentInformationTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/EnvironmentInformationTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LogCallbackAppenderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LogCallbackAppenderTest.java index a108517c36d..5cb8bdafa8d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LogCallbackAppenderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LogCallbackAppenderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LoggingConfigurationTest.java b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LoggingConfigurationTest.java index e29ad5ae14a..57f3e3d20f1 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LoggingConfigurationTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LoggingConfigurationTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LoggingConfiguratorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LoggingConfiguratorTest.java index d2291439908..785a2be7b68 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LoggingConfiguratorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/batch/bootstrapper/LoggingConfiguratorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java index f386dc40d5c..a9f21841de0 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/FakeJava.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/FakeJava.java index 99554f11e72..7a9a478f3c0 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/FakeJava.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/FakeJava.java @@ -1,6 +1,6 @@ /*
* SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
+ * Copyright (C) 2009-2025 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java index 47139b3e9de..e297649b7d7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/WsTestUtil.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/WsTestUtil.java index 6fb5829eb80..a781dd1b630 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/WsTestUtil.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/WsTestUtil.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisTempFolderProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisTempFolderProviderTest.java index 91dc27af6f3..5cad06cd4b0 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisTempFolderProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisTempFolderProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/EnvironmentConfigTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/EnvironmentConfigTest.java index 26f62d4f6d0..1c649cf975f 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/EnvironmentConfigTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/EnvironmentConfigTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java index e8159ed92ba..9e730b38827 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionUtilsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionUtilsTest.java index 3e5211bc6d4..0099106d60a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionUtilsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionUtilsTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalConfigurationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalConfigurationProviderTest.java index ba85eda6c1b..29c8ade3e30 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalConfigurationProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalConfigurationProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalTempFolderProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalTempFolderProviderTest.java index 2a27b7c5653..22b5f531cff 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalTempFolderProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalTempFolderProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionaryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionaryTest.java index 28adaaabec6..381af30f4e0 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionaryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionaryTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java index 30472694f71..7340e55e565 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionaryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionaryTest.java index 68aad3353ec..3593e6a97b8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionaryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionaryTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerLogbackEncoderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerLogbackEncoderTest.java index ea0028bf90a..a050bad9551 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerLogbackEncoderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerLogbackEncoderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginInstallerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginInstallerTest.java index 210c5228bd9..c6636483ec8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginInstallerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginInstallerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploderTest.java index 4ded7fb0901..8e10268145a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginJarExploderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginRepositoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginRepositoryTest.java index 131c0a1aa3b..05f04823a03 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginRepositoryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPluginRepositoryTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPropertiesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPropertiesTest.java index cb218245de4..32cf45c475a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPropertiesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerPropertiesTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -34,7 +34,7 @@ class ScannerPropertiesTest { LogTesterJUnit5 logTester = new LogTesterJUnit5(); @Test - public void initialization() { + void initialization() { ImmutableMap<String, String> map = ImmutableMap.<String, String>builder() .put("prop-1", "{b64}Zm9v") .put("sonar.projectKey", "my-project") @@ -49,7 +49,7 @@ class ScannerPropertiesTest { } @Test - public void encryption_fail() { + void encryption_fail() { ImmutableMap<String, String> map = ImmutableMap.<String, String>builder() .put("prop-1", "{aes}Zm9vzxc") .build(); @@ -59,7 +59,7 @@ class ScannerPropertiesTest { } @Test - public void encryption_ok() { + void encryption_ok() { ImmutableMap<String, String> map = ImmutableMap.<String, String>builder() .put("prop-1", "{b64}Zm9v") .build(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SonarUserHomeProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SonarUserHomeProviderTest.java index e499029b6bc..12cc65c5d86 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SonarUserHomeProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SonarUserHomeProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringGlobalContainerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringGlobalContainerTest.java index 5380b90947b..f3e55481520 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringGlobalContainerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringGlobalContainerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheEnabledTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheEnabledTest.java index 38d9885dd75..72b4b99baa9 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheEnabledTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheEnabledTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorageTest.java index 4ae89272f93..df728f72b59 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorageTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheMemoryStorageTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheProviderTest.java index 8b60acf8e29..c38e1e4bf7a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/AnalysisCacheProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoaderTest.java index aaf4783ac61..757b898b209 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/DefaultAnalysisCacheLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/ReadCacheImplTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/ReadCacheImplTest.java index e5690f1d481..b2be88587d1 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/ReadCacheImplTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/ReadCacheImplTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/WriteCacheImplTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/WriteCacheImplTest.java index 242b2b5009d..291ab34a5bc 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/WriteCacheImplTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cache/WriteCacheImplTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationImplTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationImplTest.java index 719b50e7236..1c03bb67608 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationImplTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationImplTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationProviderTest.java index 33439b0c2a2..d6839abfdf4 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AppVeyorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AppVeyorTest.java index 0f87e5d9071..1298127169e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AppVeyorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AppVeyorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AwsCodeBuildTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AwsCodeBuildTest.java index 3463d082f8d..df6fd4a27f6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AwsCodeBuildTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AwsCodeBuildTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AzureDevopsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AzureDevopsTest.java index 85096070faa..8d739a75562 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AzureDevopsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AzureDevopsTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BambooTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BambooTest.java index 91f6fc4af4f..9c11e2c8a98 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BambooTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BambooTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitbucketPipelinesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitbucketPipelinesTest.java index a13a894670f..c3f89ff9bc3 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitbucketPipelinesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitbucketPipelinesTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitriseTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitriseTest.java index 668896aba1b..93b6e295e15 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitriseTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitriseTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BuildkiteTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BuildkiteTest.java index 09c07c954b3..4438d1bf31e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BuildkiteTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BuildkiteTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CircleCiTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CircleCiTest.java index 9d4c403e099..5ea3d922963 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CircleCiTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CircleCiTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CirrusCiTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CirrusCiTest.java index a6574822819..0683fda34a5 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CirrusCiTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CirrusCiTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CodeMagicTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CodeMagicTest.java index c4afbe739b7..abdd007f8da 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CodeMagicTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/CodeMagicTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/DroneCiTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/DroneCiTest.java index eb960e671f5..066e6fea41d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/DroneCiTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/DroneCiTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/GithubActionsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/GithubActionsTest.java index 57a1b3cc4c1..6e1cb07416c 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/GithubActionsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/GithubActionsTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/GitlabCiTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/GitlabCiTest.java index 45808ab403d..7dada4e12c5 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/GitlabCiTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/GitlabCiTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/JenkinsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/JenkinsTest.java index ccaf4dcb41a..c4bb8a4ceb6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/JenkinsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/JenkinsTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/SemaphoreCiTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/SemaphoreCiTest.java index 058ca88fe0c..40743479d16 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/SemaphoreCiTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/SemaphoreCiTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/TravisCiTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/TravisCiTest.java index 9f85306b173..8634e22511a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/TravisCiTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/TravisCiTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/config/DefaultConfigurationTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/config/DefaultConfigurationTest.java index c1e638fb764..79f9b7bab33 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/config/DefaultConfigurationTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/config/DefaultConfigurationTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java index 8d31c0342d0..b64fe6d2710 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdExecutorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdSettingsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdSettingsTest.java index 8120d711e6f..28b12fa36c1 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdSettingsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/CpdSettingsTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/DuplicationPredicatesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/DuplicationPredicatesTest.java index 9a7788e105c..57b70f098b3 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/DuplicationPredicatesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/DuplicationPredicatesTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/JavaCpdBlockIndexerSensorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/JavaCpdBlockIndexerSensorTest.java index b1074bc99d1..5800ee87031 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/JavaCpdBlockIndexerSensorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/cpd/JavaCpdBlockIndexerSensorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/deprecated/test/DefaultTestCaseTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/deprecated/test/DefaultTestCaseTest.java index e7770a9aaf1..5f23bb2761f 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/deprecated/test/DefaultTestCaseTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/deprecated/test/DefaultTestCaseTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/extension/ScannerCoreExtensionsInstallerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/extension/ScannerCoreExtensionsInstallerTest.java index d044ee5fc79..104c66707a7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/extension/ScannerCoreExtensionsInstallerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/extension/ScannerCoreExtensionsInstallerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueImporterTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueImporterTest.java index b5794aeea43..4f318a488e8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueImporterTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueImporterTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueReportParserTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueReportParserTest.java index a207bde260e..63885295f3b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueReportParserTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueReportParserTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueReportValidatorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueReportValidatorTest.java index 0cdacfbf2c5..1d7eb5927d1 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueReportValidatorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/ExternalIssueReportValidatorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/DefaultSarif210ImporterTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/DefaultSarif210ImporterTest.java index 689e3671af1..2bd129235ca 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/DefaultSarif210ImporterTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/DefaultSarif210ImporterTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/LocationMapperTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/LocationMapperTest.java index 01a9222699a..338490b90b3 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/LocationMapperTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/LocationMapperTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RegionMapperTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RegionMapperTest.java index 6417ba175f5..f61a007e9b7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RegionMapperTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RegionMapperTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/ResultMapperTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/ResultMapperTest.java index 3efc8c51228..cbdb2def0b5 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/ResultMapperTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/ResultMapperTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RuleMapperTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RuleMapperTest.java index 5dbf2c36aad..ef833fdcaa5 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RuleMapperTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RuleMapperTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RulesSeverityDetectorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/RulesSeverityDetectorTest.java index e0bc3df54b0..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -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 407c229e31b..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -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/externalissue/sarif/SarifIssuesImportSensorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/SarifIssuesImportSensorTest.java index d5d458118d1..0f34825be27 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/SarifIssuesImportSensorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/externalissue/sarif/SarifIssuesImportSensorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericCoverageReportParserTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericCoverageReportParserTest.java index 46e75360b6f..3d8fdd6b569 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericCoverageReportParserTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericCoverageReportParserTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericCoverageSensorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericCoverageSensorTest.java index be46d38ab9e..5f30363972d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericCoverageSensorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericCoverageSensorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -19,19 +19,28 @@ */ package org.sonar.scanner.genericcoverage; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.junit.Rule; import org.junit.Test; +import org.slf4j.event.Level; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultFileSystem; +import org.sonar.api.batch.sensor.internal.SensorContextTester; import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.config.internal.Encryption; -import org.sonar.api.utils.System2; import org.sonar.api.testfixtures.log.LogTester; +import org.sonar.api.utils.System2; import org.sonar.scanner.config.DefaultConfiguration; import org.sonar.scanner.scan.ProjectConfiguration; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class GenericCoverageSensorTest { @@ -49,4 +58,38 @@ public class GenericCoverageSensorTest { assertThat(reportPaths).containsOnly("report.xml", "report2.xml"); } + + @Test + public void should_log_info_message_when_unknown_files_exist() throws Exception { + logTester.setLevel(Level.INFO); + DefaultConfiguration config = mock(DefaultConfiguration.class); + + // Create a temporary file to simulate the report file + Path tempReportFile = Files.createTempFile("report", ".xml"); + // Write valid content with version information to the temporary file + Files.write(tempReportFile, "<coverage version=\"1\"><file path=\"unknownFile\"/></coverage>".getBytes()); + + // Use the temporary file path in the configuration mock + when(config.getStringArray(GenericCoverageSensor.REPORT_PATHS_PROPERTY_KEY)).thenReturn(new String[] {tempReportFile.toString()}); + + GenericCoverageSensor sensor = new GenericCoverageSensor(config); + SensorContextTester context = SensorContextTester.create(new File(".")); + DefaultFileSystem fileSystem = context.fileSystem(); + + // Mock the input file instead of using DefaultInputFile + InputFile inputFile = mock(InputFile.class); + when(inputFile.language()).thenReturn("java"); + when(inputFile.type()).thenReturn(InputFile.Type.MAIN); + when(inputFile.filename()).thenReturn("unknownFile"); + + fileSystem.add(inputFile); + + sensor.execute(context); + + assertThat(logTester.logs(Level.INFO)).contains("Coverage data ignored for 1 unknown files, including:\nunknownFile"); + + // Clean up the temporary file + Files.delete(tempReportFile); + } + } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionReportParserTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionReportParserTest.java index caad591b76d..2e903a9af2a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionReportParserTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionReportParserTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionSensorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionSensorTest.java index cebfab7585d..fb4fb130425 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionSensorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/GenericTestExecutionSensorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/StaxParserTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/StaxParserTest.java index dd9e744a1a2..feaeaa7318d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/StaxParserTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/genericcoverage/StaxParserTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/DefaultScannerWsClientTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/DefaultScannerWsClientTest.java index 35b5f356f93..a833986c940 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/DefaultScannerWsClientTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/DefaultScannerWsClientTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -145,7 +145,7 @@ public class DefaultScannerWsClientTest { assertThatThrownBy(() -> client.call(request)) .isInstanceOf(MessageException.class) .hasMessage("Not authorized. Analyzing this project requires authentication. Please check the user token in the property 'sonar.token' " + - "or the credentials in the properties 'sonar.login' and 'sonar.password'."); + "or 'sonar.login' (deprecated)."); List<String> debugLogs = logTester.logs(Level.DEBUG); assertThat(debugLogs).hasSize(3); @@ -165,7 +165,7 @@ public class DefaultScannerWsClientTest { assertThatThrownBy(() -> client.call(request)) .isInstanceOf(MessageException.class) .hasMessage("Not authorized. Analyzing this project requires authentication. Please check the user token in the property 'sonar.token' " + - "or the credentials in the properties 'sonar.login' and 'sonar.password'."); + "or 'sonar.login' (deprecated)."); } @Test @@ -180,7 +180,7 @@ public class DefaultScannerWsClientTest { new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), analysisWarnings); assertThatThrownBy(() -> client.call(request)) .isInstanceOf(MessageException.class) - .hasMessage("Not authorized. Please check the user token in the property 'sonar.token' or the credentials in the properties 'sonar.login' and 'sonar.password'."); + .hasMessage("Not authorized. Please check the user token in the property 'sonar.token' or 'sonar.login' (deprecated)."); } @Test diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/ScannerWsClientProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/ScannerWsClientProviderTest.java index 63a52e51cd7..f4f492f11c1 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/ScannerWsClientProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/ScannerWsClientProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java index 6145aec1c11..094b53880d8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -23,7 +23,6 @@ import org.junit.Before; import org.junit.Test; import org.sonar.api.batch.fs.InputComponent; import org.sonar.api.batch.fs.internal.DefaultInputProject; -import org.sonar.scanner.protocol.Constants.Severity; import org.sonar.scanner.protocol.output.ScannerReport.Issue; import org.sonar.scanner.protocol.output.ScannerReport.TextRange; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultIssueFilterChainTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultIssueFilterChainTest.java index 3957b01c45c..e6604609ba6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultIssueFilterChainTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultIssueFilterChainTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ImpactMapperTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ImpactMapperTest.java index f543b023c75..394c1c24bae 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ImpactMapperTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ImpactMapperTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java index 0132e1d7ecc..24ce368bd7e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -19,14 +19,15 @@ */ package org.sonar.scanner.issue; -import java.io.IOException; +import java.io.File; import java.util.Collections; import java.util.HashSet; import java.util.List; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.junit.MockitoJUnitRunner; @@ -65,14 +66,13 @@ import static org.sonar.api.issue.impact.SoftwareQuality.MAINTAINABILITY; import static org.sonar.api.issue.impact.SoftwareQuality.RELIABILITY; @RunWith(MockitoJUnitRunner.class) -public class IssuePublisherTest { +class IssuePublisherTest { private static final RuleKey JAVA_RULE_KEY = RuleKey.of("java", "AvoidCycle"); - private static final RuleKey NOSONAR_RULE_KEY = RuleKey.of("java", "NoSonarCheck"); private DefaultInputProject project; - @Rule - public TemporaryFolder temp = new TemporaryFolder(); + @TempDir + public File temp; public IssueFilters filters = mock(IssueFilters.class); private final ActiveRulesBuilder activeRulesBuilder = new ActiveRulesBuilder(); @@ -80,12 +80,12 @@ public class IssuePublisherTest { private final DefaultInputFile file = new TestInputFileBuilder("foo", "src/Foo.php").initMetadata("Foo\nBar\nBiz\n").build(); private final ReportPublisher reportPublisher = mock(ReportPublisher.class, RETURNS_DEEP_STUBS); - @Before - public void prepare() throws IOException { + @BeforeEach + void prepare() { project = new DefaultInputProject(ProjectDefinition.create() .setKey("foo") - .setBaseDir(temp.newFolder()) - .setWorkDir(temp.newFolder())); + .setBaseDir(temp) + .setWorkDir(temp)); activeRulesBuilder.addRule(new NewActiveRule.Builder() .setRuleKey(JAVA_RULE_KEY) @@ -96,12 +96,12 @@ public class IssuePublisherTest { } @Test - public void ignore_null_active_rule() { - RuleKey INACTIVE_RULE_KEY = RuleKey.of("repo", "inactive"); + void ignore_null_active_rule() { + RuleKey inactiveRuleKey = RuleKey.of("repo", "inactive"); initModuleIssues(); DefaultIssue issue = new DefaultIssue(project) .at(new DefaultIssueLocation().on(file).at(file.selectLine(3)).message("Foo")) - .forRule(INACTIVE_RULE_KEY); + .forRule(inactiveRuleKey); boolean added = moduleIssues.initAndAddIssue(issue); assertThat(added).isFalse(); @@ -109,7 +109,7 @@ public class IssuePublisherTest { } @Test - public void ignore_null_rule_of_active_rule() { + void ignore_null_rule_of_active_rule() { initModuleIssues(); DefaultIssue issue = new DefaultIssue(project) @@ -122,7 +122,7 @@ public class IssuePublisherTest { } @Test - public void add_issue_to_cache() { + void add_issue_to_cache() { initModuleIssues(); final String ruleDescriptionContextKey = "spring"; @@ -156,7 +156,7 @@ public class IssuePublisherTest { } @Test - public void add_issue_flows_to_cache() { + void add_issue_flows_to_cache() { initModuleIssues(); DefaultMessageFormatting messageFormatting = new DefaultMessageFormatting().start(0).end(4).type(CODE); @@ -198,7 +198,7 @@ public class IssuePublisherTest { } @Test - public void add_external_issue_to_cache() { + void add_external_issue_to_cache() { initModuleIssues(); DefaultExternalIssue issue = new DefaultExternalIssue(project) @@ -215,7 +215,7 @@ public class IssuePublisherTest { } @Test - public void initAndAddExternalIssue_whenImpactAndCleanCodeAttributeProvided_shouldPopulateReportFields() { + void initAndAddExternalIssue_whenImpactAndCleanCodeAttributeProvided_shouldPopulateReportFields() { initModuleIssues(); DefaultExternalIssue issue = new DefaultExternalIssue(project) @@ -234,7 +234,7 @@ public class IssuePublisherTest { } @Test - public void dont_store_severity_if_no_severity_override_on_issue() { + void dont_store_severity_if_no_severity_override_on_issue() { initModuleIssues(); DefaultIssue issue = new DefaultIssue(project) @@ -250,7 +250,7 @@ public class IssuePublisherTest { } @Test - public void filter_issue() { + void filter_issue() { DefaultIssue issue = new DefaultIssue(project) .at(new DefaultIssueLocation().on(file).at(file.selectLine(3)).message("")) .forRule(JAVA_RULE_KEY); @@ -264,7 +264,7 @@ public class IssuePublisherTest { } @Test - public void should_ignore_lines_commented_with_nosonar() { + void should_ignore_lines_commented_with_nosonar() { initModuleIssues(); DefaultIssue issue = new DefaultIssue(project) @@ -279,11 +279,13 @@ public class IssuePublisherTest { verifyNoInteractions(reportPublisher); } - @Test - public void should_accept_issues_on_no_sonar_rules() { + @ParameterizedTest + @ValueSource(strings = {"NoSonarCheck", "S1291", "S1291Check"}) + void should_accept_issues_on_no_sonar_rules(String noSonarRule) { + RuleKey noSonarRuleKey = RuleKey.of("java", noSonarRule); // The "No Sonar" rule logs violations on the lines that are flagged with "NOSONAR" !! activeRulesBuilder.addRule(new NewActiveRule.Builder() - .setRuleKey(NOSONAR_RULE_KEY) + .setRuleKey(noSonarRuleKey) .setSeverity(Severity.INFO) .setQProfileKey("qp-1") .build()); @@ -293,7 +295,7 @@ public class IssuePublisherTest { DefaultIssue issue = new DefaultIssue(project) .at(new DefaultIssueLocation().on(file).at(file.selectLine(3)).message("")) - .forRule(NOSONAR_RULE_KEY); + .forRule(noSonarRuleKey); when(filters.accept(any(InputComponent.class), any(ScannerReport.Issue.class), anyString())).thenReturn(true); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/EnforceIssuesFilterTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/EnforceIssuesFilterTest.java index 955ad6d31ef..faffd2ffc71 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/EnforceIssuesFilterTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/EnforceIssuesFilterTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/IgnoreIssuesFilterTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/IgnoreIssuesFilterTest.java index 208fdc7c93f..3a36ce87077 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/IgnoreIssuesFilterTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/IgnoreIssuesFilterTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java index 0f6bcfb30f2..8a6162b9119 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java index e83f810b44c..dc72e720d1c 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssuePatternTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssuePatternTest.java index 29c84925d13..0d9bbb00492 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssuePatternTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/IssuePatternTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/LineRangeTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/LineRangeTest.java index a9eb896166e..0fc2f514140 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/LineRangeTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/pattern/LineRangeTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsLoaderTest.java index 88abb67c747..5be7449d83b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java index e22128143f7..b9dc87dffad 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/notifications/DefaultAnalysisWarningsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/notifications/DefaultAnalysisWarningsTest.java index c3dc7622211..415d09a9fd0 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/notifications/DefaultAnalysisWarningsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/notifications/DefaultAnalysisWarningsTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleCoverageAndDuplicationExclusionsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleCoverageAndDuplicationExclusionsTest.java index 48b77adf39b..2c3ad211e3a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleCoverageAndDuplicationExclusionsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleCoverageAndDuplicationExclusionsTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleSensorsExecutorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleSensorsExecutorTest.java index bfdecc89e49..3b81d77d641 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleSensorsExecutorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ModuleSensorsExecutorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/PostJobsExecutorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/PostJobsExecutorTest.java index 6bd64e7f4cd..1b376bb78e2 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/PostJobsExecutorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/PostJobsExecutorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ProjectCoverageExclusionsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ProjectCoverageExclusionsTest.java index 0623a21b316..d4c70a6c660 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ProjectCoverageExclusionsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/phases/ProjectCoverageExclusionsTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/platform/DefaultServerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/platform/DefaultServerTest.java index b9bb8f112b8..c8873310661 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/platform/DefaultServerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/platform/DefaultServerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/DefaultPostJobContextTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/DefaultPostJobContextTest.java index 7a4f74f8a25..6557254d85e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/DefaultPostJobContextTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/DefaultPostJobContextTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/PostJobOptimizerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/PostJobOptimizerTest.java index 5e72e68cb0d..4ceee858858 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/PostJobOptimizerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/postjob/PostJobOptimizerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/qualitygate/QualityGateCheckTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/qualitygate/QualityGateCheckTest.java index b31249ff815..15f465a804e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/qualitygate/QualityGateCheckTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/qualitygate/QualityGateCheckTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ActiveRulesPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ActiveRulesPublisherTest.java index 8c4db588240..11c933362d2 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ActiveRulesPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ActiveRulesPublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisCachePublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisCachePublisherTest.java index f54ac6231bd..3e8c512935b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisCachePublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisCachePublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisContextReportPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisContextReportPublisherTest.java index 0d7b061ccb4..c40699de708 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisContextReportPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisContextReportPublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisWarningsPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisWarningsPublisherTest.java index fd14aec52d0..0704f797093 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisWarningsPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/AnalysisWarningsPublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CeTaskReportDataHolderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CeTaskReportDataHolderTest.java index eb8854804fc..b99dab0aa34 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CeTaskReportDataHolderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/CeTaskReportDataHolderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java index 47f191d99c1..a81c62629f8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ChangedLinesPublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java index 06d692f2950..0e13c5929c8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java index 746d98be7fa..88c31e3eb43 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/JavaArchitectureInformationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/JavaArchitectureInformationProviderTest.java index 4977c3b0b3b..7841e58be0b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/JavaArchitectureInformationProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/JavaArchitectureInformationProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java index 129a3c79450..65fbabb8309 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java index 40910a0f364..416867a29a5 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java index d426aeffe13..36911cdb33e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/SourcePublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/TelemetryPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/TelemetryPublisherTest.java index f71e9a8f8c5..1b235e8c0bc 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/TelemetryPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/TelemetryPublisherTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ContextPropertiesCacheTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ContextPropertiesCacheTest.java index 936c0665220..8ed3100fc47 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ContextPropertiesCacheTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ContextPropertiesCacheTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultMetricsRepositoryLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultMetricsRepositoryLoaderTest.java index f0b61cf71dd..9af77efa829 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultMetricsRepositoryLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultMetricsRepositoryLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultNewCodePeriodLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultNewCodePeriodLoaderTest.java index 856bb82823a..7ddc6634113 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultNewCodePeriodLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultNewCodePeriodLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoaderTest.java index e55fb9880d0..dac5c93c71a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultProjectRepositoriesLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java index 8c0253fbe9d..0354656baa4 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/DefaultQualityProfileLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/MultiModuleProjectRepositoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/MultiModuleProjectRepositoryTest.java index f937379af8d..2ff3e8dadeb 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/MultiModuleProjectRepositoryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/MultiModuleProjectRepositoryTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesProviderTest.java index 0538cb6f0a8..2a46bb205fc 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ProjectRepositoriesProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/QualityProfileProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/QualityProfileProviderTest.java index d89d5e2222c..5250b0dbdc6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/QualityProfileProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/QualityProfileProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ReferenceBranchSupplierTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ReferenceBranchSupplierTest.java index d8807130d2c..7f242dd2d5d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ReferenceBranchSupplierTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ReferenceBranchSupplierTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/SingleProjectRepositoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/SingleProjectRepositoryTest.java index 6164d465986..d184dddaaa6 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/SingleProjectRepositoryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/SingleProjectRepositoryTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/TelemetryCacheTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/TelemetryCacheTest.java index dc6fe24b18b..20d0589aa61 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/TelemetryCacheTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/TelemetryCacheTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/featureflags/DefaultFeatureFlagsLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/featureflags/DefaultFeatureFlagsLoaderTest.java new file mode 100644 index 00000000000..59a73e86f16 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/featureflags/DefaultFeatureFlagsLoaderTest.java @@ -0,0 +1,85 @@ +/* + * 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.repository.featureflags; + +import com.google.gson.Gson; +import java.io.Reader; +import java.io.StringReader; +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.sonar.api.utils.MessageException; +import org.sonar.scanner.WsTestUtil; +import org.sonar.scanner.http.DefaultScannerWsClient; +import org.sonar.scanner.scan.branch.BranchConfiguration; +import wiremock.org.apache.hc.core5.http.HttpException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatException; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +class DefaultFeatureFlagsLoaderTest { + + private DefaultFeatureFlagsLoader loader; + private DefaultScannerWsClient wsClient; + + @BeforeEach + void setUp() { + wsClient = mock(DefaultScannerWsClient.class); + BranchConfiguration branchConfig = mock(BranchConfiguration.class); + when(branchConfig.isPullRequest()).thenReturn(false); + loader = new DefaultFeatureFlagsLoader(wsClient); + } + + @Test + void load_shouldRequestFeatureFlagsAndParseResponse() { + WsTestUtil.mockReader(wsClient, "/api/features/list", response()); + + Set<String> features = loader.load(); + assertThat(features).containsExactlyInAnyOrder("feature1", "feature2"); + + WsTestUtil.verifyCall(wsClient, "/api/features/list"); + + verifyNoMoreInteractions(wsClient); + } + + @Test + void load_whenHasSomeError_shouldThrowIllegalStateException() { + when(wsClient.call(any())).thenThrow(MessageException.of("You're not authorized")); + + assertThatException().isThrownBy(loader::load) + .isInstanceOf(IllegalStateException.class) + .withMessage("Unable to load feature flags"); + } + + private Reader response() { + return toReader(List.of("feature1", "feature2")); + } + + private static Reader toReader(List<String> featureFlags) { + String json = new Gson().toJson(featureFlags); + return new StringReader(json); + } + +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/featureflags/DefaultFeatureFlagsRepositoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/featureflags/DefaultFeatureFlagsRepositoryTest.java new file mode 100644 index 00000000000..e043fcfdd2f --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/featureflags/DefaultFeatureFlagsRepositoryTest.java @@ -0,0 +1,49 @@ +/* + * 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.repository.featureflags; + +import java.util.Set; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class DefaultFeatureFlagsRepositoryTest { + + private DefaultFeatureFlagsRepository underTest; + + @BeforeEach + void prepare() { + var loader = mock(FeatureFlagsLoader.class); + when(loader.load()).thenReturn(Set.of("feature1")); + underTest = new DefaultFeatureFlagsRepository(loader); + } + + @Test + void start_shouldReturnFlagStatus() { + underTest.start(); + + assertThat(underTest.isEnabled("feature1")).isTrue(); + assertThat(underTest.isEnabled("feature2")).isFalse(); + } + +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/DefaultLanguagesRepositoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/DefaultLanguagesRepositoryTest.java index 294e4763d2e..8a2149c5a75 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/DefaultLanguagesRepositoryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/DefaultLanguagesRepositoryTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/LanguageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/LanguageTest.java index 84e6654bcd0..6db64e4debb 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/LanguageTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/LanguageTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/AbstractSettingsLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/AbstractSettingsLoaderTest.java index 1510a90ccf0..4928d6b6720 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/AbstractSettingsLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/AbstractSettingsLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoaderTest.java index 0b3d1bb23b1..3f3843ffb3b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultProjectSettingsLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultProjectSettingsLoaderTest.java index c1694faa9a1..819a595f415 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultProjectSettingsLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/settings/DefaultProjectSettingsLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesBuilderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesBuilderTest.java index e4ad8642286..db4be9b680e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesBuilderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesBuilderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java index c5f3fceedbc..d118234f1ec 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java index cf66faeb655..23ac91da048 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/LoadedActiveRuleTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/LoadedActiveRuleTest.java index 735e48e9473..4b22dfdf441 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/LoadedActiveRuleTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/LoadedActiveRuleTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileTest.java index cfc0cc30e84..4cd1ba67dda 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileVerifierTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileVerifierTest.java index b029707f107..519f9de5726 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileVerifierTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/QProfileVerifierTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliCacheServiceTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliCacheServiceTest.java new file mode 100644 index 00000000000..6615ba4e4e4 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliCacheServiceTest.java @@ -0,0 +1,307 @@ +/* + * 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.sca; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.nio.charset.Charset; +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; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.event.Level; +import org.sonar.api.testfixtures.log.LogTesterJUnit5; +import org.sonar.api.utils.System2; +import org.sonar.scanner.WsTestUtil; +import org.sonar.scanner.bootstrap.SonarUserHome; +import org.sonar.scanner.http.DefaultScannerWsClient; +import org.sonar.scanner.repository.TelemetryCache; +import org.sonarqube.ws.client.HttpException; +import org.sonarqube.ws.client.WsResponse; + +import static java.lang.String.format; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.sonar.scanner.sca.CliCacheService.CLI_WS_URL; + +@ExtendWith(MockitoExtension.class) +class CliCacheServiceTest { + @Mock + private SonarUserHome sonarUserHome; + @Mock + private DefaultScannerWsClient scannerWsClient; + @Mock + private System2 system2; + @Mock + private TelemetryCache telemetryCache; + @RegisterExtension + private final LogTesterJUnit5 logTester = new LogTesterJUnit5(); + @TempDir + public Path cacheDir; + + private CliCacheService underTest; + + @BeforeEach + void setup() { + lenient().when(sonarUserHome.getPath()).thenReturn(cacheDir); + lenient().when(telemetryCache.put(any(), any())).thenReturn(telemetryCache); + + underTest = new CliCacheService(sonarUserHome, scannerWsClient, telemetryCache, system2); + } + + @Test + void cacheCli_shouldDownloadCli_whenCacheDoesNotExist() { + String checksum = "checksum"; + String id = "tidelift"; + WsTestUtil.mockReader(scannerWsClient, CLI_WS_URL, new StringReader(""" + [ + { + "id": "%s", + "filename": "tidelift_darwin", + "sha256": "%s", + "os": "mac", + "arch": "x64_86" + } + ]""".formatted(id, checksum))); + + WsTestUtil.mockStream(scannerWsClient, CLI_WS_URL + "/" + id, new ByteArrayInputStream("cli content".getBytes())); + + assertThat(cacheDir).isEmptyDirectory(); + + File generatedFile = underTest.cacheCli(); + + assertThat(generatedFile).exists().isExecutable(); + assertThat(cacheDir.resolve("cache").resolve(checksum)).exists().isNotEmptyDirectory(); + + verify(telemetryCache).put(eq("scanner.sca.download.cli.duration"), any()); + verify(telemetryCache).put("scanner.sca.download.cli.success", "true"); + verify(telemetryCache).put("scanner.sca.get.cli.cache.hit", "false"); + verify(telemetryCache).put("scanner.sca.get.cli.success", "true"); + } + + @Test + void cacheCli_shouldThrowException_whenMultipleMetadatas() { + WsTestUtil.mockReader(scannerWsClient, CLI_WS_URL, new StringReader(""" + [ + { + "id": "tidelift", + "filename": "tidelift_darwin", + "sha256": "1", + "os": "mac", + "arch": "x64_86" + }, + { + "id": "tidelift_other", + "filename": "tidelift", + "sha256": "2", + "os": "mac", + "arch": "x64_86" + } + ]""")); + + assertThatThrownBy(underTest::cacheCli).isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Multiple CLI matches found. Unable to correctly cache CLI."); + + verify(telemetryCache).put("scanner.sca.get.cli.success", "false"); + + } + + @Test + void cacheCli_shouldThrowException_whenNoMetadata() { + WsTestUtil.mockReader(scannerWsClient, CLI_WS_URL, new StringReader("[]")); + + assertThatThrownBy(underTest::cacheCli).isInstanceOf(IllegalStateException.class) + .hasMessageMatching("Could not find CLI for .+ .+"); + + verify(telemetryCache).put("scanner.sca.get.cli.success", "false"); + + } + + @Test + void cacheCli_shouldThrowException_whenServerError() { + HttpException http = new HttpException("url", 500, "some error message"); + IllegalStateException e = new IllegalStateException("http error", http); + WsTestUtil.mockException(scannerWsClient, e); + + assertThatThrownBy(underTest::cacheCli).isInstanceOf(IllegalStateException.class) + .hasMessageContaining("http error"); + + verify(telemetryCache).put("scanner.sca.get.cli.success", "false"); + } + + @Test + void cacheCli_shouldNotOverwrite_whenCachedFileExists() throws IOException { + String checksum = "checksum"; + WsTestUtil.mockReader(scannerWsClient, CLI_WS_URL, new StringReader(""" + [ + { + "id": "tidelift", + "filename": "tidelift_darwin", + "sha256": "%s", + "os": "mac", + "arch": "x64_86" + } + ]""".formatted(checksum))); + when(system2.isOsWindows()).thenReturn(false); + + String fileContent = "test content"; + File existingFile = underTest.cacheDir().resolve(checksum).resolve("tidelift").toFile(); + FileUtils.createParentDirectories(existingFile); + FileUtils.writeStringToFile(existingFile, fileContent, Charset.defaultCharset()); + + assertThat(existingFile).exists(); + 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(); + 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"); + verify(telemetryCache).put("scanner.sca.get.cli.success", "true"); + } + + @Test + void cacheCli_shouldAllowLocationOverride(@TempDir Path tempDir) throws IOException { + File alternateCliFile = tempDir.resolve("alternate_cli").toFile(); + FileUtils.writeStringToFile(alternateCliFile, "alternate cli content", Charset.defaultCharset()); + when(system2.envVariable("TIDELIFT_CLI_LOCATION")).thenReturn(alternateCliFile.getAbsolutePath()); + + var returnedFile = underTest.cacheCli(); + + assertThat(returnedFile.getAbsolutePath()).isEqualTo(alternateCliFile.getAbsolutePath()); + assertThat(logTester.logs(Level.INFO)).contains("Using alternate location for Tidelift CLI: " + alternateCliFile.getAbsolutePath()); + verify(scannerWsClient, never()).call(any()); + } + + @Test + void cacheCli_whenOverrideDoesntExist_shouldRaiseError() { + var location = "incorrect_location"; + when(system2.envVariable("TIDELIFT_CLI_LOCATION")).thenReturn(location); + + assertThatThrownBy(underTest::cacheCli).isInstanceOf(IllegalStateException.class) + .hasMessageMatching("Alternate location for Tidelift CLI has been set but no file was found at " + location); + + assertThat(logTester.logs(Level.INFO)).contains("Using alternate location for Tidelift CLI: " + location); + verify(scannerWsClient, never()).call(any()); + } + + @Test + void apiOsName_shouldReturnApiCompatibleName() { + when(system2.isOsWindows()).thenReturn(true); + when(system2.isOsMac()).thenReturn(false); + assertThat(underTest.apiOsName()).isEqualTo("windows"); + reset(system2); + + when(system2.isOsWindows()).thenReturn(false); + when(system2.isOsMac()).thenReturn(true); + assertThat(underTest.apiOsName()).isEqualTo("mac"); + + reset(system2); + when(system2.isOsWindows()).thenReturn(false); + when(system2.isOsMac()).thenReturn(false); + assertThat(underTest.apiOsName()).isEqualTo("linux"); + } + + @Test + void createTempDir_shouldReturnExistingDir() throws IOException { + Path dir = sonarUserHome.getPath().resolve("_tmp"); + Files.createDirectory(dir); + + assertThat(underTest.createTempDir()).isEqualTo(dir); + } + + @Test + void createTempDir_shouldHandleIOException() { + try (MockedStatic<Files> mockFilesClass = mockStatic(Files.class)) { + mockFilesClass.when(() -> Files.createDirectory(any(Path.class))).thenThrow(IOException.class); + + Path expectedDir = sonarUserHome.getPath().resolve("_tmp"); + assertThatThrownBy(underTest::createTempDir).isInstanceOf(IllegalStateException.class) + .hasMessageContaining(format("Unable to create temp directory at %s", expectedDir)); + } + } + + @Test + void moveFile_shouldHandleIOException(@TempDir Path sourceFile, @TempDir Path targetFile) { + try (MockedStatic<Files> mockFilesClass = mockStatic(Files.class)) { + mockFilesClass.when(() -> Files.move(sourceFile, targetFile, StandardCopyOption.ATOMIC_MOVE)).thenThrow(IOException.class); + mockFilesClass.when(() -> Files.move(sourceFile, targetFile)).thenThrow(IOException.class); + + assertThatThrownBy(() -> CliCacheService.moveFile(sourceFile, targetFile)).isInstanceOf(IllegalStateException.class) + .hasMessageContaining(format("Fail to move %s to %s", sourceFile, targetFile)); + + assertThat(logTester.logs(Level.WARN)).contains(format("Unable to rename %s to %s", sourceFile, targetFile)); + assertThat(logTester.logs(Level.WARN)).contains("A copy/delete will be tempted but with no guarantee of atomicity"); + } + } + + @Test + void mkdir_shouldHandleIOException(@TempDir Path dir) { + try (MockedStatic<Files> mockFilesClass = mockStatic(Files.class)) { + mockFilesClass.when(() -> Files.createDirectories(dir)).thenThrow(IOException.class); + + assertThatThrownBy(() -> CliCacheService.mkdir(dir)).isInstanceOf(IllegalStateException.class) + .hasMessageContaining(format("Fail to create cache directory: %s", dir)); + } + } + + @Test + void downloadBinaryTo_shouldHandleIOException(@TempDir Path downloadLocation) { + WsResponse mockResponse = mock(WsResponse.class); + InputStream mockStream = mock(InputStream.class); + when(mockResponse.contentStream()).thenReturn(mockStream); + + try (MockedStatic<FileUtils> mockFileUtils = mockStatic(FileUtils.class)) { + mockFileUtils.when(() -> FileUtils.copyInputStreamToFile(mockStream, downloadLocation.toFile())).thenThrow(IOException.class); + + assertThatThrownBy(() -> CliCacheService.downloadBinaryTo(downloadLocation, mockResponse)).isInstanceOf(IllegalStateException.class) + .hasMessageContaining(format("Fail to download SCA CLI into %s", downloadLocation)); + } + } +} 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 new file mode 100644 index 00000000000..33cf6c146e6 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/CliServiceTest.java @@ -0,0 +1,376 @@ +/* + * 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.sca; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.SystemUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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; +import org.sonar.api.testfixtures.log.LogTesterJUnit5; +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; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.slf4j.event.Level.DEBUG; +import static org.slf4j.event.Level.INFO; + +class CliServiceTest { + private TelemetryCache telemetryCache; + private DefaultInputModule rootInputModule; + private final Server server = mock(Server.class); + @RegisterExtension + private final LogTesterJUnit5 logTester = new LogTesterJUnit5(); + @TempDir + Path rootModuleDir; + private final ScmConfiguration scmConfiguration = mock(ScmConfiguration.class); + private final ScmProvider scmProvider = mock(GitScmProvider.class); + 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; + + @BeforeEach + void setup() throws IOException { + telemetryCache = new TelemetryCache(); + Path workDir = rootModuleDir.resolve(".scannerwork"); + Files.createDirectories(workDir); + rootInputModule = new DefaultInputModule( + ProjectDefinition.create().setBaseDir(rootModuleDir.toFile()).setWorkDir(workDir.toFile())); + when(scmConfiguration.provider()).thenReturn(scmProvider); + when(scmProvider.key()).thenReturn("git"); + when(scmConfiguration.isExclusionDisabled()).thenReturn(false); + jGitUtilsMock = org.mockito.Mockito.mockStatic(JGitUtils.class); + jGitUtilsMock.when(() -> JGitUtils.getAllIgnoredPaths(any(Path.class))).thenReturn(List.of("ignored.txt")); + when(server.getVersion()).thenReturn("1.0.0"); + logTester.setLevel(INFO); + 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, projectExclusionFilters); + } + + @AfterEach + void teardown() { + if (jGitUtilsMock != null) { + jGitUtilsMock.close(); + } + } + + @Test + void generateManifestsArchive_shouldCallProcessCorrectly_andRegisterTelemetry() throws IOException, URISyntaxException { + assertThat(rootModuleDir.resolve("test_file").toFile().createNewFile()).isTrue(); + + 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 producedArchive = underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + assertThat(producedArchive).exists(); + + var expectedArguments = List.of( + "projects", + "save-lockfiles", + "--xz", + "--xz-filename", + rootInputModule.getWorkDir().resolve("dependency-files.tar.xz").toString(), + "--directory", + rootInputModule.getBaseDir().toString(), + "--recursive", + "--exclude", + "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("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 generateManifestsArchive_whenDebugLogLevelAndScaDebugNotEnabled_shouldWriteDebugLogsToDebugStream() throws IOException, URISyntaxException { + logTester.setLevel(DEBUG); + + assertThat(rootModuleDir.resolve("test_file").toFile().createNewFile()).isTrue(); + + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + var expectedArguments = List.of( + "projects", + "save-lockfiles", + "--xz", + "--xz-filename", + rootInputModule.getWorkDir().resolve("dependency-files.tar.xz").toString(), + "--directory", + rootInputModule.getBaseDir().toString(), + "--recursive", + "--exclude", + "ignored.txt,.scannerwork/**", + "--debug"); + + assertThat(logTester.logs(INFO)) + .contains("Arguments Passed In: " + String.join(" ", expectedArguments)); + } + + @Test + void generateManifestsArchive_whenScaDebugEnabled_shouldWriteDebugLogsToInfoStream() throws IOException, URISyntaxException { + assertThat(rootModuleDir.resolve("test_file").toFile().createNewFile()).isTrue(); + + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + var expectedArguments = List.of( + "projects", + "save-lockfiles", + "--xz", + "--xz-filename", + rootInputModule.getWorkDir().resolve("dependency-files.tar.xz").toString(), + "--directory", + rootInputModule.getBaseDir().toString(), + "--recursive", + "--exclude", + "ignored.txt,.scannerwork/**"); + + assertThat(logTester.logs(INFO)) + .contains("Arguments Passed In: " + String.join(" ", expectedArguments)); + } + + @Test + void generateManifestsArchive_shouldSendSQEnvVars() throws IOException, URISyntaxException { + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + assertThat(logTester.logs(INFO)) + .contains("TIDELIFT_CLI_INSIDE_SCANNER_ENGINE=1") + .contains("TIDELIFT_CLI_SQ_SERVER_VERSION=1.0.0"); + } + + @Test + void generateManifestsArchive_includesIgnoredPathsFromGitProvider() throws Exception { + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + var expectedArguments = List.of( + "projects", + "save-lockfiles", + "--xz", + "--xz-filename", + rootInputModule.getWorkDir().resolve("dependency-files.tar.xz").toString(), + "--directory", + rootInputModule.getBaseDir().toString(), + "--recursive", + "--exclude", + "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_CLI_INSIDE_SCANNER_ENGINE=1") + .contains("TIDELIFT_CLI_SQ_SERVER_VERSION=1.0.0"); + + } + + @Test + void generateManifestsArchive_withNoScm_doesNotIncludeScmIgnoredPaths() throws Exception { + when(scmConfiguration.provider()).thenReturn(null); + + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); + assertThat(capturedArgs).contains("--exclude .scannerwork/**"); + } + + @Test + void generateManifestsArchive_withNonGit_doesNotIncludeScmIgnoredPaths() throws Exception { + when(scmProvider.key()).thenReturn("notgit"); + + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); + assertThat(capturedArgs).contains("--exclude .scannerwork/**"); + } + + @Test + void generateManifestsArchive_withScmExclusionDisabled_doesNotIncludeScmIgnoredPaths() throws Exception { + when(scmConfiguration.isExclusionDisabled()).thenReturn(true); + + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); + assertThat(capturedArgs).contains("--exclude .scannerwork/**"); + } + + @Test + void generateManifestsArchive_withNoScmIgnores_doesNotIncludeScmIgnoredPaths() throws Exception { + jGitUtilsMock.when(() -> JGitUtils.getAllIgnoredPaths(any(Path.class))).thenReturn(List.of()); + + underTest.generateManifestsArchive(rootInputModule, scriptDir(), configuration); + + String capturedArgs = logTester.logs().stream().filter(log -> log.contains("Arguments Passed In:")).findFirst().get(); + assertThat(capturedArgs).contains("--exclude .scannerwork/**"); + } + + @Test + void generateManifestsArchive_withExcludedManifests_appendsScmIgnoredPaths() throws Exception { + when(configuration.getStringArray(CliService.SCA_EXCLUSIONS_KEY)).thenReturn(new String[] {"**/test/**"}); + + 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 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.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'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 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'quotes/**", "**/path\"with\"double\"quotes/**")); + + 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'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 generateManifestsArchive_withIgnoredDirectories_GlobifiesDirectories() throws Exception { + String ignoredDirectory = "directory1"; + Files.createDirectories(rootModuleDir.resolve(ignoredDirectory)); + String ignoredFile = "directory2/file.txt"; + Path ignoredFilePath = rootModuleDir.resolve(ignoredFile); + Files.createDirectories(ignoredFilePath.getParent()); + Files.createFile(ignoredFilePath); + + jGitUtilsMock.when(() -> JGitUtils.getAllIgnoredPaths(any(Path.class))).thenReturn(List.of(ignoredDirectory, ignoredFile)); + 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 generateManifestsArchive_withExternalWorkDir_DoesNotExcludeWorkingDir() throws URISyntaxException, IOException { + Path externalWorkDir = Files.createTempDirectory("externalWorkDir"); + try { + rootInputModule = new DefaultInputModule(ProjectDefinition.create().setBaseDir(rootModuleDir.toFile()).setWorkDir(externalWorkDir.toFile())); + 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"); + } finally { + externalWorkDir.toFile().delete(); + } + } + + 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 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(); + return scriptUrl; + } + + private File scriptDir() throws URISyntaxException { + return new File(scriptUrl().toURI()); + } +} 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 new file mode 100644 index 00000000000..ebe6007a1c1 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaExecutorTest.java @@ -0,0 +1,180 @@ +/* + * 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.sca; + +import java.io.File; +import java.io.IOException; +import java.util.Optional; +import org.assertj.core.util.Files; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.io.TempDir; +import org.slf4j.event.Level; +import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.batch.fs.internal.DefaultInputModule; +import org.sonar.api.testfixtures.log.LogTesterJUnit5; +import org.sonar.scanner.config.DefaultConfiguration; +import org.sonar.scanner.protocol.output.ScannerReportWriter; +import org.sonar.scanner.report.ReportPublisher; +import org.sonar.scanner.repository.featureflags.FeatureFlagsRepository; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +class ScaExecutorTest { + private final CliService cliService = mock(CliService.class); + private final CliCacheService cliCacheService = mock(CliCacheService.class); + private final ReportPublisher reportPublisher = mock(ReportPublisher.class); + private final FeatureFlagsRepository featureFlagsRepository = mock(FeatureFlagsRepository.class); + private final DefaultConfiguration configuration = mock(DefaultConfiguration.class); + @RegisterExtension + private final LogTesterJUnit5 logTester = new LogTesterJUnit5(); + private final ScaExecutor underTest = new ScaExecutor(cliCacheService, cliService, reportPublisher, featureFlagsRepository, configuration); + @TempDir + File rootModuleDir; + private DefaultInputModule root; + + @BeforeEach + void before() { + when(featureFlagsRepository.isEnabled("sca")).thenReturn(true); + root = new DefaultInputModule( + ProjectDefinition.create().setBaseDir(rootModuleDir).setWorkDir(rootModuleDir.toPath().getRoot().toFile())); + } + + @Test + void execute_shouldCallCliAndPublisher() 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.DEBUG); + + underTest.execute(root); + + 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_whenIOException_shouldHandleException() throws IOException { + File mockCliFile = Files.newTemporaryFile(); + when(cliCacheService.cacheCli()).thenReturn(mockCliFile); + doThrow(IOException.class).when(cliService).generateManifestsArchive(root, mockCliFile, configuration); + + logTester.setLevel(Level.INFO); + + underTest.execute(root); + + verify(cliService).generateManifestsArchive(root, mockCliFile, configuration); + assertThat(logTester.logs(Level.ERROR)).contains("Error gathering manifests"); + } + + @Test + void execute_whenIllegalStateException_shouldHandleException() throws IOException { + File mockCliFile = Files.newTemporaryFile(); + when(cliCacheService.cacheCli()).thenReturn(mockCliFile); + doThrow(IllegalStateException.class).when(cliService).generateManifestsArchive(root, mockCliFile, configuration); + + logTester.setLevel(Level.INFO); + + underTest.execute(root); + + verify(cliService).generateManifestsArchive(root, mockCliFile, configuration); + assertThat(logTester.logs(Level.ERROR)).contains("Error gathering manifests"); + } + + @Test + void execute_whenNoCliFound_shouldSkipAnalysis() throws IOException { + File mockCliFile = new File(""); + when(cliCacheService.cacheCli()).thenReturn(mockCliFile); + + underTest.execute(root); + + verify(cliService, never()).generateManifestsArchive(root, mockCliFile, configuration); + } + + @Test + void execute_whenGlobalFeatureDisabled_skips() { + when(featureFlagsRepository.isEnabled("sca")).thenReturn(false); + logTester.setLevel(Level.DEBUG); + + underTest.execute(root); + + assertThat(logTester.logs()).contains("Dependency analysis skipped"); + verifyNoInteractions(cliService, cliCacheService); + } + + @Test + void execute_whenProjectPropertyDisabled_skips() { + when(configuration.getBoolean("sonar.sca.enabled")).thenReturn(Optional.of(false)); + logTester.setLevel(Level.DEBUG); + + underTest.execute(root); + + assertThat(logTester.logs()).contains("Dependency analysis disabled for this project"); + verifyNoInteractions(cliService, cliCacheService); + } + + @Test + void execute_whenProjectPropertyExplicitlyEnabled_CallsCli() throws IOException { + when(configuration.getBoolean("sonar.sca.enabled")).thenReturn(Optional.of(true)); + 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.DEBUG); + + underTest.execute(root); + + 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 new file mode 100644 index 00000000000..70e7a6b6e53 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sca/ScaPropertiesTest.java @@ -0,0 +1,100 @@ +/* + * 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.sca; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import org.junit.jupiter.api.Test; +import org.sonar.scanner.config.DefaultConfiguration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class ScaPropertiesTest { + private final DefaultConfiguration configuration = mock(DefaultConfiguration.class); + + @Test + void buildFromScannerProperties_withNoProperties_returnsEmptyMap() { + when(configuration.get(anyString())).thenReturn(Optional.empty()); + + var result = ScaProperties.buildFromScannerProperties(configuration); + + assertThat(result).isEqualTo(Map.of()); + } + + @Test + void buildFromScannerProperties_withUnmappedProperties_ignoresProperties() { + var inputProperties = new HashMap<String, String>(); + 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.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); + + assertThat(result).containsExactly( + Map.entry("TIDELIFT_PYTHON_BINARY", "/usr/bin/python3"), + Map.entry("TIDELIFT_UNKNOWN_PROPERTY", "value")); + } + + @Test + void buildFromScannerProperties_withLotsOfProperties_mapsAllProperties() { + var inputProperties = new HashMap<String, String>(); + inputProperties.put("sonar.sca.goNoResolve", "true"); + inputProperties.put("sonar.sca.gradleConfigurationPattern", "pattern"); + inputProperties.put("sonar.sca.gradleNoResolve", "false"); + inputProperties.put("sonar.sca.mavenForceDepPlugin", "plugin"); + inputProperties.put("sonar.sca.mavenNoResolve", "true"); + inputProperties.put("sonar.sca.mavenIgnoreWrapper", "false"); + inputProperties.put("sonar.sca.mavenOptions", "-DskipTests"); + inputProperties.put("sonar.sca.npmEnableScripts", "true"); + inputProperties.put("sonar.sca.npmNoResolve", "true"); + inputProperties.put("sonar.sca.nugetNoResolve", "false"); + inputProperties.put("sonar.sca.pythonBinary", "/usr/bin/python3"); + inputProperties.put("sonar.sca.pythonNoResolve", "true"); + inputProperties.put("sonar.sca.pythonResolveLocal", "false"); + when(configuration.getProperties()).thenReturn(inputProperties); + when(configuration.get(anyString())).thenAnswer(i -> Optional.ofNullable(inputProperties.get(i.getArgument(0, String.class)))); + + var expectedProperties = new HashMap<String, String>(); + expectedProperties.put("TIDELIFT_GO_NO_RESOLVE", "true"); + expectedProperties.put("TIDELIFT_GRADLE_CONFIGURATION_PATTERN", "pattern"); + expectedProperties.put("TIDELIFT_GRADLE_NO_RESOLVE", "false"); + expectedProperties.put("TIDELIFT_MAVEN_FORCE_DEP_PLUGIN", "plugin"); + expectedProperties.put("TIDELIFT_MAVEN_NO_RESOLVE", "true"); + expectedProperties.put("TIDELIFT_MAVEN_IGNORE_WRAPPER", "false"); + expectedProperties.put("TIDELIFT_MAVEN_OPTIONS", "-DskipTests"); + expectedProperties.put("TIDELIFT_NPM_ENABLE_SCRIPTS", "true"); + expectedProperties.put("TIDELIFT_NPM_NO_RESOLVE", "true"); + expectedProperties.put("TIDELIFT_NUGET_NO_RESOLVE", "false"); + expectedProperties.put("TIDELIFT_PYTHON_BINARY", "/usr/bin/python3"); + expectedProperties.put("TIDELIFT_PYTHON_NO_RESOLVE", "true"); + expectedProperties.put("TIDELIFT_PYTHON_RESOLVE_LOCAL", "false"); + + var result = ScaProperties.buildFromScannerProperties(configuration); + + assertThat(result).containsExactlyInAnyOrderEntriesOf(expectedProperties); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java index b1f7b42910e..3eab59b4c47 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DefaultInputModuleHierarchyTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DeprecatedPropertiesWarningGeneratorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DeprecatedPropertiesWarningGeneratorTest.java index 3e9a49706c5..97697a601dd 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DeprecatedPropertiesWarningGeneratorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DeprecatedPropertiesWarningGeneratorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -36,7 +36,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import static org.sonar.scanner.scan.DeprecatedPropertiesWarningGenerator.LOGIN_WARN_MESSAGE; -import static org.sonar.scanner.scan.DeprecatedPropertiesWarningGenerator.PASSWORD_WARN_MESSAGE; import static org.sonar.scanner.scan.DeprecatedPropertiesWarningGenerator.SCANNER_DOTNET_WARN_MESSAGE; public class DeprecatedPropertiesWarningGeneratorTest { @@ -54,7 +53,6 @@ public class DeprecatedPropertiesWarningGeneratorTest { @Before public void setUp() throws Exception { settings.removeProperty(CoreProperties.LOGIN); - settings.removeProperty(CoreProperties.PASSWORD); when(environmentInformation.getKey()).thenReturn("ScannerCLI"); } @@ -69,17 +67,6 @@ public class DeprecatedPropertiesWarningGeneratorTest { } @Test - public void execute_whenUsingPassword_shouldAddWarning() { - settings.setProperty(CoreProperties.LOGIN, "test"); - settings.setProperty(CoreProperties.PASSWORD, "winner winner chicken dinner"); - - underTest.execute(); - - verify(analysisWarnings, times(1)).addUnique(PASSWORD_WARN_MESSAGE); - Assertions.assertThat(logger.logs(Level.WARN)).contains(PASSWORD_WARN_MESSAGE); - } - - @Test public void execute_whenUsingLoginAndDotNetScanner_shouldAddWarning() { settings.setProperty(CoreProperties.LOGIN, "test"); when(environmentInformation.getKey()).thenReturn("ScannerMSBuild"); @@ -91,18 +78,6 @@ public class DeprecatedPropertiesWarningGeneratorTest { } @Test - public void execute_whenUsingPasswordAndDotNetScanner_shouldAddWarning() { - settings.setProperty(CoreProperties.LOGIN, "test"); - settings.setProperty(CoreProperties.PASSWORD, "winner winner chicken dinner"); - when(environmentInformation.getKey()).thenReturn("ScannerMSBuild"); - - underTest.execute(); - - verify(analysisWarnings, times(1)).addUnique(PASSWORD_WARN_MESSAGE + SCANNER_DOTNET_WARN_MESSAGE); - Assertions.assertThat(logger.logs(Level.WARN)).contains(PASSWORD_WARN_MESSAGE + SCANNER_DOTNET_WARN_MESSAGE); - } - - @Test public void execute_whenNotUsingLoginOrPassword_shouldNotAddWarning() { underTest.execute(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DirectoryLockTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DirectoryLockTest.java index 62a5dbf33cc..e247685c8a0 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DirectoryLockTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DirectoryLockTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleConfigurationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleConfigurationProviderTest.java index 80cab3a8a5c..338d553629d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleConfigurationProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleConfigurationProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java index a66ed1f1456..0f586d09513 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ModuleIndexerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectBuildersExecutorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectBuildersExecutorTest.java index 347c8072810..b755d6a882b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectBuildersExecutorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectBuildersExecutorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectConfigurationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectConfigurationProviderTest.java index e2e1b9d84cd..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -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/ProjectLockTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectLockTest.java index efe60b25106..d84723632a7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectLockTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectLockTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorBuilderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorBuilderTest.java index 4092d2f7e0f..ae4d32d4456 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorBuilderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorBuilderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java index 40d785b4c51..4fd7165ce77 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ScanPropertiesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ScanPropertiesTest.java index 37f15a87a71..3de53c7a56a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ScanPropertiesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ScanPropertiesTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -99,4 +99,24 @@ public class ScanPropertiesTest { .isInstanceOf(MessageException.class) .hasMessage("Property 'sonar.scanner.metadataFilePath' must point to an absolute path: relative"); } + + @Test + public void validate_fails_if_sonar_branch_is_set() { + settings.setProperty("sonar.branch", "anything"); + + assertThatThrownBy(underTest::validate) + .isInstanceOf(MessageException.class) + .hasMessage("The 'sonar.branch' parameter is no longer supported. You should stop using it. " + + "Branch analysis is available in Developer Edition and above. See https://www.sonarsource.com/plans-and-pricing/developer/ for more information."); + } + + @Test + public void validate_fails_if_sonar_password_is_set() { + settings.setProperty("sonar.password", "anything"); + + assertThatThrownBy(underTest::validate) + .isInstanceOf(MessageException.class) + .hasMessage("The property 'sonar.password' is no longer supported. " + + "Please pass a token with the 'sonar.token' property instead."); + } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SonarGlobalPropertiesFilterTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SonarGlobalPropertiesFilterTest.java index 5f08e31817c..6a09d11947f 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SonarGlobalPropertiesFilterTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SonarGlobalPropertiesFilterTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SpringProjectScanContainerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SpringProjectScanContainerTest.java index 3f02637c302..4a0d8210400 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SpringProjectScanContainerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SpringProjectScanContainerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java index d402acc42bb..542a50c4e9c 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java index 7dc853b3b23..9b96e828e37 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesProviderTest.java index 6e11f10364d..89dd5f16146 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesTest.java index 050dddafbdd..4ccd66fb6d5 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFiltersTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFiltersTest.java index fc039bc675c..faea9c001fe 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFiltersTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AbstractExclusionFiltersTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java index 03759916869..270cd42dbf8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/AdditionalFilePredicatesTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ByteCharsetDetectorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ByteCharsetDetectorTest.java index 59d0a292e35..d5f384440c3 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ByteCharsetDetectorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ByteCharsetDetectorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/CharsetDetectorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/CharsetDetectorTest.java index 64d7a67e1f3..5cfeb8f1851 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/CharsetDetectorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/CharsetDetectorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/CharsetValidationTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/CharsetValidationTest.java index 382eae972e8..437e7ab2014 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/CharsetValidationTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/CharsetValidationTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/DirectoryFileVisitorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/DirectoryFileVisitorTest.java index 59bc00a3654..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -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/InputComponentStoreTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java index 91b1695a0ef..ddabaaeeb1e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputComponentStoreTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileFilterRepositoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileFilterRepositoryTest.java index 7be01e0a79f..41c54320025 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileFilterRepositoryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/InputFileFilterRepositoryTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java index 1bf8599da5d..4a368f4b1c5 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/LanguageDetectionTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java index 2f5e5c75df5..53009584158 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/MetadataGeneratorTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ModuleInputComponentStoreTest.java index 24b17271be5..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -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 89a01da4130..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -28,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/scan/filesystem/ProjectExclusionFiltersTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ProjectExclusionFiltersTest.java index 995b0f1ac17..7b3520b0abb 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ProjectExclusionFiltersTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/ProjectExclusionFiltersTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java index 22ca2771b06..bb0f515152f 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/filesystem/StatusDetectionTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/DefaultBlameOutputTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/DefaultBlameOutputTest.java index d52e21bc110..6dffc938113 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/DefaultBlameOutputTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/DefaultBlameOutputTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java index 49e91a6dc88..146b9943f6f 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesTest.java index be8b214bd73..7461f20061a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmConfigurationTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmConfigurationTest.java index 9250b6680e9..a4d9ba0ca4d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmConfigurationTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmConfigurationTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmRevisionImplTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmRevisionImplTest.java index 28cec113cd8..bf1615d493a 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmRevisionImplTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmRevisionImplTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/AbstractSensorOptimizerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/AbstractSensorOptimizerTest.java index a0a81ede6a5..7f41d12af57 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/AbstractSensorOptimizerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/AbstractSensorOptimizerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java index 5a6f8f66a1f..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -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(); @@ -112,8 +111,9 @@ class DefaultSensorStorageTest { branchConfiguration = mock(BranchConfiguration.class); - underTest = new DefaultSensorStorage(metricFinder, - moduleIssues, settings.asConfig(), reportPublisher, mock(SonarCpdBlockIndex.class), contextPropertiesCache, telemetryCache, new ScannerMetrics(), branchConfiguration); + underTest = new DefaultSensorStorage( + metricFinder, moduleIssues, settings.asConfig(), reportPublisher, mock(SonarCpdBlockIndex.class), contextPropertiesCache, telemetryCache, new ScannerMetrics(), + branchConfiguration); project = new DefaultInputProject(ProjectDefinition.create() .setKey("foo") 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 feb5c1ddb17..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -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/ModuleSensorOptimizerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorOptimizerTest.java index 12a04d50098..448e5104f72 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorOptimizerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorOptimizerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ProjectSensorContextTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ProjectSensorContextTest.java index 5d25250e8bb..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -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/scanner/sensor/SensorIdTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/SensorIdTest.java index 11660111479..66130ee3fc7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/SensorIdTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/SensorIdTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/UnchangedFilesHandlerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/UnchangedFilesHandlerTest.java index 71cd70f8f74..51336d5e5e1 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/UnchangedFilesHandlerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/UnchangedFilesHandlerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/util/ProgressReportTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/util/ProgressReportTest.java index 71a3fd644a1..c064e517551 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/util/ProgressReportTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/util/ProgressReportTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -42,7 +42,7 @@ public class ProgressReportTest { @Rule public LogTester logTester = new LogTester(); - private ProgressReport underTest = new ProgressReport(THREAD_NAME, 1); + private final ProgressReport underTest = new ProgressReport(THREAD_NAME, 1); @Test public void stop_thread_on_stop() { @@ -66,15 +66,28 @@ public class ProgressReportTest { underTest.message("Some message"); boolean logged = false; while (!logged) { - logged = containsWithRetry("Some message"); + logged = waitForMessageStartingWith("Some message"); } underTest.stop("stop"); - assertThat(containsWithRetry("stop")).isTrue(); + assertThat(waitForMessageStartingWith("stop")).isTrue(); } - private boolean containsWithRetry(String message) { + @Test + public void do_log_message_supplier() { + logTester.setLevel(Level.DEBUG); + underTest.start("start"); + underTest.message(() -> "Some message " + System.currentTimeMillis()); + boolean logged = false; + while (!logged) { + logged = waitForMessageStartingWith("Some message "); + } + underTest.stop("stop"); + assertThat(waitForMessageStartingWith("stop")).isTrue(); + } + + private boolean waitForMessageStartingWith(String message) { try { - Awaitility.await().atMost(5, TimeUnit.SECONDS).until(() -> logTester.logs().contains(message)); + Awaitility.await().atMost(5, TimeUnit.SECONDS).until(() -> logTester.logs().stream().anyMatch(s -> s.startsWith(message))); } catch (ConditionTimeoutException e) { return false; } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/util/ScannerUtilsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/util/ScannerUtilsTest.java index cfbd153c5b4..72185c83416 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/util/ScannerUtilsTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/util/ScannerUtilsTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedFileTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedFileTest.java index d6e7fef0d5e..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -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/ChangedLinesComputerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedLinesComputerTest.java index 346f35af705..502482b275d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedLinesComputerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ChangedLinesComputerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/CompositeBlameCommandIT.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/CompositeBlameCommandIT.java index ca666a6d866..775fe3d05b2 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/CompositeBlameCommandIT.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/CompositeBlameCommandIT.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -47,6 +47,7 @@ import org.sonar.api.batch.scm.BlameLine; import org.sonar.api.notifications.AnalysisWarnings; import org.sonar.api.scan.filesystem.PathResolver; import org.sonar.api.utils.System2; +import org.sonar.core.util.ProcessWrapperFactory; import org.sonar.scm.git.strategy.DefaultBlameStrategy.BlameAlgorithmEnum; import static org.assertj.core.api.Assertions.assertThat; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/CompositeBlameCommandTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/CompositeBlameCommandTest.java index f628ef8a5ac..a1a4cae8b4d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/CompositeBlameCommandTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/CompositeBlameCommandTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -54,6 +54,7 @@ import org.sonar.api.testfixtures.log.LogTester; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.System2; +import org.sonar.core.util.ProcessWrapperFactory; import org.sonar.scm.git.strategy.BlameStrategy; import org.sonar.scm.git.strategy.DefaultBlameStrategy.BlameAlgorithmEnum; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitIgnoreCommandTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitIgnoreCommandTest.java index 8ede2a9739d..e725b201b98 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitIgnoreCommandTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitIgnoreCommandTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmProviderTest.java index 884253a7e4f..058c274013d 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -52,6 +52,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.slf4j.event.Level; import org.sonar.api.config.Configuration; import org.sonar.api.notifications.AnalysisWarnings; import org.sonar.api.scan.filesystem.PathResolver; @@ -60,6 +61,7 @@ import org.sonar.api.testfixtures.log.LogTester; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.System2; import org.sonar.core.documentation.DocumentationLinkGenerator; +import org.sonar.core.util.ProcessWrapperFactory; import org.sonar.scm.git.strategy.DefaultBlameStrategy; import static java.lang.String.format; @@ -246,6 +248,36 @@ public class GitScmProviderTest { } @Test + public void branchChangedLinesWithFileMovementDetection_should_return_null_when_mergeBaseCommit_is_empty() throws IOException, GitAPIException { + logs.setLevel(Level.WARN); + + git.checkout().setOrphan(true).setName("orphan-branch").call(); + createAndCommitFile("file3.txt"); + + Map<Path, ChangedFile> changedFiles = Map.of( + worktree.resolve("file1.txt"), ChangedFile.of(worktree.resolve("file1.txt"), null), + worktree.resolve("file2-renamed.txt"), ChangedFile.of(worktree.resolve("file2-renamed.txt"), "file2.txt")); + + Map<Path, Set<Integer>> result = newScmProvider().branchChangedLinesWithFileMovementDetection("master", worktree, changedFiles); + + assertThat(logs.logs(Level.WARN)).contains("No merge base found between HEAD and refs/heads/master"); + assertThat(result).isNull(); + } + + @Test + public void branchChangedFilesWithFileMovementDetection_should_return_null_when_mergeBaseCommit_is_empty() throws IOException, GitAPIException { + logs.setLevel(Level.WARN); + + git.checkout().setOrphan(true).setName("orphan-branch").call(); + createAndCommitFile("file3.txt"); + + Set<ChangedFile> result = newScmProvider().branchChangedFilesWithFileMovementDetection("master", worktree); + + assertThat(logs.logs(Level.WARN)).contains("No merge base found between HEAD and refs/heads/master"); + assertThat(result).isNull(); + } + + @Test public void branchChangedFiles_should_not_fail_with_patience_diff_algo() throws IOException { Path gitConfig = worktree.resolve(".git").resolve("config"); Files.write(gitConfig, "[diff]\nalgorithm = patience\n".getBytes(StandardCharsets.UTF_8)); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmSupportTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmSupportTest.java index 27ec0629aca..d89657a7ba0 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmSupportTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitScmSupportTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitThreadFactoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitThreadFactoryTest.java index 59297f25461..4593909cf3e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitThreadFactoryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitThreadFactoryTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitUtils.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitUtils.java index 9e70db06250..f64cd1de741 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitUtils.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/GitUtils.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitBlameCommandTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitBlameCommandTest.java index a5a028702bb..9ddfb3ac968 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitBlameCommandTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitBlameCommandTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitUtilsTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitUtilsTest.java new file mode 100644 index 00000000000..d8264a5745b --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/JGitUtilsTest.java @@ -0,0 +1,101 @@ +/* + * 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.scm.git; + +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; +import org.junit.jupiter.api.io.TempDir; +import org.sonar.api.utils.MessageException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class JGitUtilsTest { + + @TempDir + Path rootModuleDir; + + @Test + void getAllIgnoredPaths_ReturnsIgnoredFiles() throws Exception { + setupTestDirectory(); + + List<String> result = JGitUtils.getAllIgnoredPaths(rootModuleDir); + + // 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 + 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 + void getIgnoredPaths_WithNonGitDirectory_ThrowsException() { + assertThatThrownBy(() -> JGitUtils.getAllIgnoredPaths(rootModuleDir)) + .isInstanceOf(MessageException.class) + .hasMessageStartingWith("Not inside a Git work tree: "); + } + + @Test + void getIgnoredPaths_WithDifferentBaseDir_ReturnsIgnoredFilesRelativeToBaseDir() throws Exception { + Path baseDir = rootModuleDir.resolve("directory2"); + setupTestDirectory(); + + List<String> result = JGitUtils.getAllIgnoredPaths(baseDir); + + assertThat(result).isEqualTo(List.of("file_a.txt")); + } + + @Test + void getIgnoredPaths_WithSubDirBaseDirContainingGitIgnore_ReturnsIgnoredFilesRelativeToBaseDir() throws Exception { + Path baseDir = rootModuleDir.resolve("directory3"); + setupTestDirectory(); + + List<String> result = JGitUtils.getAllIgnoredPaths(baseDir); + + assertThat(result).isEqualTo(List.of("file_b.txt")); + } + + private void setupTestDirectory() throws GitAPIException, IOException { + Git.init().setDirectory(rootModuleDir.toFile()).call(); + + var directories = List.of("directory1", "directory2", "directory3"); + var fileNames = List.of("file_a.txt", "file_b.txt"); + + for (String dir : directories) { + Path directoryPath = rootModuleDir.resolve(dir); + Files.createDirectories(directoryPath); + for (String fileName : fileNames) { + Files.write(directoryPath.resolve(fileName), "content".getBytes()); + } + } + + Files.write(rootModuleDir.resolve(".gitignore"), "ignored.txt\ndirectory1\ndirectory2/file_a.txt".getBytes()); + Files.write(rootModuleDir.resolve("directory3/.gitignore"), "file_b.txt".getBytes()); + } +} 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 bec6e0425f8..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 @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or @@ -19,7 +19,6 @@ */ package org.sonar.scm.git; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -32,21 +31,21 @@ import java.util.function.Consumer; import java.util.stream.Stream; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.api.io.TempDir; import org.slf4j.event.Level; import org.sonar.api.batch.scm.BlameLine; +import org.sonar.api.testfixtures.log.LogTesterJUnit5; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.System2; -import org.sonar.api.testfixtures.log.LogTester; -import org.sonar.scm.git.ProcessWrapperFactory.ProcessWrapper; +import org.sonar.core.util.ProcessWrapperFactory; +import org.sonar.core.util.ProcessWrapperFactory.ProcessWrapper; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assume.assumeTrue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -54,32 +53,31 @@ import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.sonar.scm.git.GitUtils.createFile; +import static org.sonar.scm.git.GitUtils.createRepository; import static org.sonar.scm.git.NativeGitBlameCommand.BLAME_COMMAND; import static org.sonar.scm.git.NativeGitBlameCommand.GIT_DIR_ARGUMENT; import static org.sonar.scm.git.NativeGitBlameCommand.GIT_DIR_FLAG; import static org.sonar.scm.git.NativeGitBlameCommand.GIT_DIR_FORCE_FLAG; -import static org.sonar.scm.git.GitUtils.createFile; -import static org.sonar.scm.git.GitUtils.createRepository; import static org.sonar.scm.git.Utils.javaUnzip; -@RunWith(DataProviderRunner.class) -public class NativeGitBlameCommandTest { +class NativeGitBlameCommandTest { private static final String DUMMY_JAVA = "src/main/java/org/dummy/Dummy.java"; - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - @Rule - public LogTester logTester = new LogTester(); + @TempDir + private Path tempDir; + @RegisterExtension + private final LogTesterJUnit5 logTester = new LogTesterJUnit5(); private final ProcessWrapperFactory processWrapperFactory = new ProcessWrapperFactory(); private final NativeGitBlameCommand blameCommand = new NativeGitBlameCommand(System2.INSTANCE, processWrapperFactory); - @Before - public void skipTestsIfNoGitFound() { + @BeforeEach + void skipTestsIfNoGitFound() { assumeTrue(blameCommand.checkIfEnabled()); } @Test - public void should_read_lines_only_based_on_new_line() throws Exception { + void should_read_lines_only_based_on_new_line() throws Exception { Path baseDir = createNewTempFolder().toPath(); String filePath = "file.txt"; createFile(filePath, "test1\rtest2\r\ttest3", baseDir); @@ -92,7 +90,7 @@ public class NativeGitBlameCommandTest { } @Test - public void blame_collects_all_lines() throws Exception { + void blame_collects_all_lines() throws Exception { File projectDir = createNewTempFolder(); javaUnzip("dummy-git.zip", projectDir); File baseDir = new File(projectDir, "dummy-git"); @@ -123,7 +121,7 @@ public class NativeGitBlameCommandTest { } @Test - public void blame_different_author_and_committer() throws Exception { + void blame_different_author_and_committer() throws Exception { File projectDir = createNewTempFolder(); javaUnzip("dummy-git-different-committer.zip", projectDir); File baseDir = new File(projectDir, "dummy-git"); @@ -154,21 +152,21 @@ public class NativeGitBlameCommandTest { } @Test - public void git_blame_uses_safe_local_repository() throws Exception { + void git_blame_uses_safe_local_repository() throws Exception { File projectDir = createNewTempFolder(); File baseDir = new File(projectDir, "dummy-git"); 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), @@ -178,7 +176,7 @@ public class NativeGitBlameCommandTest { } @Test - public void modified_file_returns_no_blame() throws Exception { + void modified_file_returns_no_blame() throws Exception { File projectDir = createNewTempFolder(); javaUnzip("dummy-git.zip", projectDir); @@ -191,9 +189,8 @@ public class NativeGitBlameCommandTest { } @Test - public void throw_exception_if_symlink_found() throws Exception { + void throw_exception_if_symlink_found(@TempDir File projectDir) throws Exception { assumeTrue(!System2.INSTANCE.isOsWindows()); - File projectDir = temp.newFolder(); javaUnzip("dummy-git.zip", projectDir); Path baseDir = projectDir.toPath().resolve("dummy-git"); @@ -207,69 +204,66 @@ public class NativeGitBlameCommandTest { } @Test - public void git_should_be_detected() { + void git_should_be_detected() { NativeGitBlameCommand blameCommand = new NativeGitBlameCommand(System2.INSTANCE, processWrapperFactory); assertThat(blameCommand.checkIfEnabled()).isTrue(); } @Test - public void git_should_not_be_detected() { + void git_should_not_be_detected() { NativeGitBlameCommand blameCommand = new NativeGitBlameCommand("randomcmdthatwillneverbefound", System2.INSTANCE, processWrapperFactory); assertThat(blameCommand.checkIfEnabled()).isFalse(); } @Test - public void git_should_not_be_enabled_if_version_command_is_not_found() { + void git_should_not_be_enabled_if_version_command_is_not_found() { ProcessWrapperFactory mockedCmd = mockGitVersionCommand("error: unknown option `version'"); NativeGitBlameCommand blameCommand = new NativeGitBlameCommand(System2.INSTANCE, mockedCmd); assertThat(blameCommand.checkIfEnabled()).isFalse(); } @Test - public void git_should_not_be_enabled_if_version_command_does_not_return_string_output() { + void git_should_not_be_enabled_if_version_command_does_not_return_string_output() { ProcessWrapperFactory mockedCmd = mockGitVersionCommand(null); NativeGitBlameCommand blameCommand = new NativeGitBlameCommand(System2.INSTANCE, mockedCmd); assertThat(blameCommand.checkIfEnabled()).isFalse(); } @Test - public void git_should_be_enabled_if_version_is_equal_or_greater_than_required_minimum() { + void git_should_be_enabled_if_version_is_equal_or_greater_than_required_minimum() { Stream.of( "git version 2.24.0", "git version 2.25.2.1", "git version 2.24.1.1.windows.2", - "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 -> { - var argument = (Consumer<String>) invocation.getArgument(1); - argument.accept(output); - return mock(ProcessWrapper.class); + "git version 2.25.1.msysgit.2").forEach(output -> { + ProcessWrapperFactory mockedCmd = mockGitVersionCommand(output); + mockGitWhereOnWindows(mockedCmd); + 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); + }); + + NativeGitBlameCommand blameCommand = new NativeGitBlameCommand(System2.INSTANCE, mockedCmd); + assertThat(blameCommand.checkIfEnabled()).isTrue(); }); - - NativeGitBlameCommand blameCommand = new NativeGitBlameCommand(System2.INSTANCE, mockedCmd); - assertThat(blameCommand.checkIfEnabled()).isTrue(); - }); } @Test - public void git_should_not_be_enabled_if_version_is_less_than_required_minimum() { + void git_should_not_be_enabled_if_version_is_less_than_required_minimum() { ProcessWrapperFactory mockFactory = mockGitVersionCommand("git version 1.9.0"); NativeGitBlameCommand blameCommand = new NativeGitBlameCommand(System2.INSTANCE, mockFactory); assertThat(blameCommand.checkIfEnabled()).isFalse(); } @Test - public void throw_exception_if_command_fails() throws Exception { - Path baseDir = temp.newFolder().toPath(); + void throw_exception_if_command_fails(@TempDir Path baseDir) { NativeGitBlameCommand blameCommand = new NativeGitBlameCommand("randomcmdthatwillneverbefound", System2.INSTANCE, processWrapperFactory); assertThatThrownBy(() -> blameCommand.blame(baseDir, "file")).isInstanceOf(IOException.class); } @Test - public void blame_without_email_doesnt_fail() throws Exception { - Path baseDir = temp.newFolder().toPath(); + void blame_without_email_doesnt_fail(@TempDir Path baseDir) throws Exception { Git git = createRepository(baseDir); String filePath = "file.txt"; createFile(filePath, "line", baseDir); @@ -286,8 +280,7 @@ public class NativeGitBlameCommandTest { } @Test - public void blame_mail_with_spaces_doesnt_fail() throws Exception { - Path baseDir = temp.newFolder().toPath(); + void blame_mail_with_spaces_doesnt_fail(@TempDir Path baseDir) throws Exception { Git git = createRepository(baseDir); String filePath = "file.txt"; createFile(filePath, "line", baseDir); @@ -301,25 +294,7 @@ public class NativeGitBlameCommandTest { } @Test - public void do_not_execute() throws Exception { - Path baseDir = temp.newFolder().toPath(); - Git git = createRepository(baseDir); - String filePath = "file.txt"; - createFile(filePath, "line", baseDir); - commitWithNoEmail(git, filePath); - - NativeGitBlameCommand blameCommand = new NativeGitBlameCommand(System2.INSTANCE, processWrapperFactory); - assertThat(blameCommand.checkIfEnabled()).isTrue(); - List<BlameLine> blame = blameCommand.blame(baseDir, filePath); - assertThat(blame).hasSize(1); - BlameLine blameLine = blame.get(0); - assertThat(blameLine.author()).isNull(); - assertThat(blameLine.revision()).isNotNull(); - assertThat(blameLine.date()).isNotNull(); - } - - @Test - public void execution_on_windows_should_fallback_to_full_path() { + void execution_on_windows_should_fallback_to_full_path() { logTester.setLevel(Level.DEBUG); System2 system2 = mock(System2.class); when(system2.isOsWindows()).thenReturn(true); @@ -328,7 +303,7 @@ public 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; @@ -340,7 +315,7 @@ public class NativeGitBlameCommandTest { } @Test - public void execution_on_windows_is_disabled_if_git_not_on_path() { + void execution_on_windows_is_disabled_if_git_not_on_path() { System2 system2 = mock(System2.class); when(system2.isOsWindows()).thenReturn(true); when(system2.property("PATH")).thenReturn("C:\\some-path;C:\\some-another-path"); @@ -367,11 +342,11 @@ public class NativeGitBlameCommandTest { private File createNewTempFolder() throws IOException { // This is needed for Windows, otherwise the created File point to invalid (shortened by Windows) temp folder path - return temp.newFolder().toPath().toRealPath(LinkOption.NOFOLLOW_LINKS).toFile(); + return tempDir.toRealPath(LinkOption.NOFOLLOW_LINKS).toFile(); } 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); @@ -382,7 +357,7 @@ public 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; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ProcessWrapperFactoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ProcessWrapperFactoryTest.java deleted file mode 100644 index ed7b600cd25..00000000000 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/ProcessWrapperFactoryTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2024 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.scm.git; - -import java.io.IOException; -import java.util.Map; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.slf4j.event.Level; -import org.sonar.api.testfixtures.log.LogTester; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class ProcessWrapperFactoryTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - @Rule - public LogTester logTester = new LogTester(); - private final ProcessWrapperFactory underTest = new ProcessWrapperFactory(); - - @Test - public void should_log_error_output_in_debug_mode() throws IOException { - logTester.setLevel(Level.DEBUG); - var root = temp.newFolder().toPath(); - var processWrapper = underTest.create(root, v -> {}, Map.of("LANG", "en_US"), "git", "blame"); - assertThatThrownBy(processWrapper::execute) - .isInstanceOf(IllegalStateException.class); - - assertThat(logTester.logs(Level.DEBUG).get(0)).startsWith("fatal:"); - } - -} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/Utils.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/Utils.java index d81394769af..0c6dae20923 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/Utils.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/Utils.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/strategy/DefaultBlameStrategyTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/strategy/DefaultBlameStrategyTest.java index 46c6b38272f..b15b95a9290 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/git/strategy/DefaultBlameStrategyTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/git/strategy/DefaultBlameStrategyTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/ChangedLinesComputerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/ChangedLinesComputerTest.java index f55ba21efc7..c6e0d6b0f56 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/ChangedLinesComputerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/ChangedLinesComputerTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnConfigurationTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnConfigurationTest.java index c7c3b597fd6..8759cf6a8a7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnConfigurationTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnConfigurationTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmProviderTest.java index 89dc17cf905..0ce98997831 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmProviderTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmSupportTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmSupportTest.java index 9b7d75a9da7..59534340fa2 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmSupportTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scm/svn/SvnScmSupportTest.java @@ -1,6 +1,6 @@ /* * SonarQube - * Copyright (C) 2009-2024 SonarSource SA + * Copyright (C) 2009-2025 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or |