From 32a5fecb407c19060301d2364d12002135b2aefe Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Mon, 20 Dec 2021 10:49:11 -0600 Subject: [PATCH] SONAR-15836 Language files are not automatically published --- .../src/main/java/org/sonar/xoo/Xoo.java | 5 + .../src/main/java/org/sonar/xoo/Xoo2.java | 5 + .../java/org/sonar/xoo/Xoo3NoAutoPublish.java | 52 ++++ .../xoo/Xoo3QualityProfileDefinition.java | 35 +++ .../main/java/org/sonar/xoo/XooPlugin.java | 2 + .../language/LanguageRepositoryImplTest.java | 5 + .../org/sonar/api/resources/Language.java | 7 + .../api/resources/AbstractLanguageTest.java | 7 +- .../language/DefaultLanguagesRepository.java | 7 +- .../scanner/repository/language/Language.java | 26 +- .../scanner/scan/filesystem/FileIndexer.java | 9 +- .../scan/filesystem/LanguageDetection.java | 44 ++-- .../mediumtest/ScannerMediumTester.java | 2 +- .../mediumtest/fs/FileSystemMediumTest.java | 248 +++++++----------- .../DefaultLanguagesRepositoryTest.java | 118 +++++++++ .../repository/language/LanguageTest.java | 51 ++++ .../filesystem/LanguageDetectionTest.java | 44 ++-- 17 files changed, 465 insertions(+), 202 deletions(-) create mode 100644 plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo3NoAutoPublish.java create mode 100644 plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo3QualityProfileDefinition.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/DefaultLanguagesRepositoryTest.java create mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/LanguageTest.java diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo.java index ca7aaf5d9ab..2d1ce7aec7c 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo.java @@ -49,4 +49,9 @@ public class Xoo implements Language { public String[] getFileSuffixes() { return config.getStringArray(FILE_SUFFIXES_KEY); } + + @Override + public boolean publishAllFiles() { + return true; + } } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo2.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo2.java index f4907b3810b..05af9b85916 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo2.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo2.java @@ -45,4 +45,9 @@ public class Xoo2 implements Language { public String[] getFileSuffixes() { return XOO_SUFFIXES; } + + @Override + public boolean publishAllFiles() { + return true; + } } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo3NoAutoPublish.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo3NoAutoPublish.java new file mode 100644 index 00000000000..f21994eb10b --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo3NoAutoPublish.java @@ -0,0 +1,52 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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.xoo; + +import org.sonar.api.resources.Language; + +public class Xoo3NoAutoPublish implements Language { + public static final String KEY = "xoo3"; + public static final String NAME = "Xoo3"; + public static final String FILE_SUFFIX = ".xoo3"; + + private static final String[] XOO_SUFFIXES = { + FILE_SUFFIX + }; + + @Override + public String getKey() { + return KEY; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public String[] getFileSuffixes() { + return XOO_SUFFIXES; + } + + @Override + public boolean publishAllFiles() { + return false; + } +} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo3QualityProfileDefinition.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo3QualityProfileDefinition.java new file mode 100644 index 00000000000..489790ed1c9 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/Xoo3QualityProfileDefinition.java @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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.xoo; + +import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; + +public class Xoo3QualityProfileDefinition implements BuiltInQualityProfilesDefinition { + + private static final String PROFILE_NAME = "Sonar way"; + + @Override + public void define(Context context) { + NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile(PROFILE_NAME, Xoo3NoAutoPublish.KEY); + profile.setDefault(true); + profile.done(); + } + +} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java index aba5d5bdf11..0ade397f3fd 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java @@ -109,6 +109,8 @@ public class XooPlugin implements Plugin { .build(), Xoo.class, Xoo2.class, + Xoo3NoAutoPublish.class, + Xoo3QualityProfileDefinition.class, XooRulesDefinition.class, XooBuiltInQualityProfilesDefinition.class, XooSonarWayProfile.class, diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/language/LanguageRepositoryImplTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/language/LanguageRepositoryImplTest.java index 745a540ad49..6fefdf2386b 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/language/LanguageRepositoryImplTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/language/LanguageRepositoryImplTest.java @@ -74,6 +74,11 @@ public class LanguageRepositoryImplTest { public String[] getFileSuffixes() { return new String[0]; } + + @Override + public boolean publishAllFiles() { + return true; + } }; } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Language.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Language.java index 18c4f94781e..1dc5e9145e5 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/Language.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/Language.java @@ -53,4 +53,11 @@ public interface Language { */ String[] getFileSuffixes(); + /** + * Whether all files identified with this language should be sent to SonarQube, even if no data is reported for them + * @since 9.3 + */ + default boolean publishAllFiles() { + return true; + } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/resources/AbstractLanguageTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/resources/AbstractLanguageTest.java index d1fd1d782de..73256aace1c 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/resources/AbstractLanguageTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/resources/AbstractLanguageTest.java @@ -52,6 +52,11 @@ public class AbstractLanguageTest { public String[] getFileSuffixes() { return lang1.getFileSuffixes(); } + + @Override + public boolean publishAllFiles() { + return true; + } })).isTrue(); assertThat(lang1) @@ -61,7 +66,7 @@ public class AbstractLanguageTest { @Test public void should_not_define_language_with_too_long_key() { - assertThatThrownBy(() -> new TooLongKeyLanguage()) + assertThatThrownBy(TooLongKeyLanguage::new) .isInstanceOf(IllegalArgumentException.class) .hasMessage("The following language key exceeds 20 characters: 'aKeyWhichIsVeryVeryVeryVeryVeryLong'"); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/DefaultLanguagesRepository.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/DefaultLanguagesRepository.java index f09090b2c0a..bad761dc41d 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/DefaultLanguagesRepository.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/DefaultLanguagesRepository.java @@ -19,12 +19,11 @@ */ package org.sonar.scanner.repository.language; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; - import javax.annotation.CheckForNull; import javax.annotation.concurrent.Immutable; - import org.picocontainer.Startable; import org.sonar.api.resources.Languages; @@ -55,7 +54,7 @@ public class DefaultLanguagesRepository implements LanguagesRepository, Startabl @CheckForNull public Language get(String languageKey) { org.sonar.api.resources.Language language = languages.get(languageKey); - return language != null ? new Language(language.getKey(), language.getName(), language.getFileSuffixes()) : null; + return language != null ? new Language(language.getKey(), language.getName(), language.publishAllFiles(), language.getFileSuffixes()) : null; } /** @@ -66,7 +65,7 @@ public class DefaultLanguagesRepository implements LanguagesRepository, Startabl org.sonar.api.resources.Language[] all = languages.all(); Collection result = new ArrayList<>(all.length); for (org.sonar.api.resources.Language language : all) { - result.add(new Language(language.getKey(), language.getName(), language.getFileSuffixes())); + result.add(new Language(language.getKey(), language.getName(), language.publishAllFiles(), language.getFileSuffixes())); } return result; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/Language.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/Language.java index 0b93551908a..e7e119843b9 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/Language.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/Language.java @@ -21,7 +21,7 @@ package org.sonar.scanner.repository.language; import java.util.Arrays; import java.util.Collection; - +import java.util.Objects; import javax.annotation.concurrent.Immutable; @Immutable @@ -29,11 +29,13 @@ public final class Language { private final String key; private final String name; + private final boolean publishAllFiles; private final String[] fileSuffixes; - public Language(String key, String name, String... fileSuffixes) { + public Language(String key, String name, boolean publishAllFiles, String... fileSuffixes) { this.key = key; this.name = name; + this.publishAllFiles = publishAllFiles; this.fileSuffixes = fileSuffixes; } @@ -58,9 +60,29 @@ public final class Language { return Arrays.asList(fileSuffixes); } + public boolean isPublishAllFiles() { + return publishAllFiles; + } + @Override public String toString() { return name; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Language language = (Language) o; + return Objects.equals(key, language.key); + } + + @Override + public int hashCode() { + return Objects.hash(key); + } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java index 6b94c267464..5223c64cfe6 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java @@ -41,6 +41,7 @@ import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.scanner.issue.ignore.scanner.IssueExclusionsLoader; +import org.sonar.scanner.repository.language.Language; import org.sonar.scanner.scan.ScanProperties; import org.sonar.scanner.util.ProgressReport; @@ -123,7 +124,7 @@ public class FileIndexer { return; } - String language = langDetection.language(realAbsoluteFile, projectRelativePath); + Language language = langDetection.language(realAbsoluteFile, projectRelativePath); if (ignoreCommand != null && ignoreCommand.isIgnored(realAbsoluteFile)) { LOG.debug("File '{}' is excluded by the scm ignore settings.", realAbsoluteFile); @@ -134,10 +135,10 @@ public class FileIndexer { DefaultIndexedFile indexedFile = new DefaultIndexedFile(realAbsoluteFile, project.key(), projectRelativePath.toString(), moduleRelativePath.toString(), - type, language, scannerComponentIdGenerator.getAsInt(), sensorStrategy); + type, language != null ? language.key() : null, scannerComponentIdGenerator.getAsInt(), sensorStrategy); DefaultInputFile inputFile = new DefaultInputFile(indexedFile, f -> metadataGenerator.setMetadata(module.key(), f, module.getEncoding())); - if (language != null) { - inputFile.setPublished(true); + if (language != null && language.isPublishAllFiles()) { + inputFile.setPublished(true); } if (!accept(inputFile)) { return; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java index 51968684585..091076643fb 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/LanguageDetection.java @@ -21,9 +21,7 @@ package org.sonar.scanner.scan.filesystem; import java.nio.file.Path; import java.text.MessageFormat; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -39,6 +37,8 @@ import org.sonar.api.utils.MessageException; import org.sonar.scanner.repository.language.Language; import org.sonar.scanner.repository.language.LanguagesRepository; +import static java.util.Collections.unmodifiableMap; + /** * Detect language of a source file based on its suffix and configured patterns. */ @@ -50,45 +50,45 @@ public class LanguageDetection { /** * Lower-case extension -> languages */ - private final Map patternsByLanguage; - private final List languagesToConsider; + private final Map patternsByLanguage; + private final List languagesToConsider; public LanguageDetection(Configuration settings, LanguagesRepository languages) { - Map patternsByLanguageBuilder = new LinkedHashMap<>(); + Map patternsByLanguageBuilder = new LinkedHashMap<>(); for (Language language : languages.all()) { String[] filePatterns = settings.getStringArray(getFileLangPatternPropKey(language.key())); PathPattern[] pathPatterns = PathPattern.create(filePatterns); if (pathPatterns.length > 0) { - patternsByLanguageBuilder.put(language.key(), pathPatterns); + patternsByLanguageBuilder.put(language, pathPatterns); } else { // If no custom language pattern is defined then fallback to suffixes declared by language - String[] patterns = language.fileSuffixes().toArray(new String[language.fileSuffixes().size()]); + String[] patterns = language.fileSuffixes().toArray(new String[0]); for (int i = 0; i < patterns.length; i++) { String suffix = patterns[i]; String extension = sanitizeExtension(suffix); - patterns[i] = new StringBuilder().append("**/*.").append(extension).toString(); + patterns[i] = "**/*." + extension; } PathPattern[] defaultLanguagePatterns = PathPattern.create(patterns); - patternsByLanguageBuilder.put(language.key(), defaultLanguagePatterns); - LOG.debug("Declared extensions of language {} were converted to {}", language, getDetails(language.key(), defaultLanguagePatterns)); + patternsByLanguageBuilder.put(language, defaultLanguagePatterns); + LOG.debug("Declared extensions of language {} were converted to {}", language, getDetails(language, defaultLanguagePatterns)); } } languagesToConsider = List.copyOf(patternsByLanguageBuilder.keySet()); - patternsByLanguage = Collections.unmodifiableMap(patternsByLanguageBuilder); + patternsByLanguage = unmodifiableMap(patternsByLanguageBuilder); } @CheckForNull - String language(Path absolutePath, Path relativePath) { - String detectedLanguage = null; - for (String languageKey : languagesToConsider) { - if (isCandidateForLanguage(absolutePath, relativePath, languageKey)) { + Language language(Path absolutePath, Path relativePath) { + Language detectedLanguage = null; + for (Language language : languagesToConsider) { + if (isCandidateForLanguage(absolutePath, relativePath, language)) { if (detectedLanguage == null) { - detectedLanguage = languageKey; + detectedLanguage = language; } else { // Language was already forced by another pattern throw MessageException.of(MessageFormat.format("Language of file ''{0}'' can not be decided as the file matches patterns of both {1} and {2}", - relativePath, getDetails(detectedLanguage), getDetails(languageKey))); + relativePath, getDetails(detectedLanguage), getDetails(language))); } } } @@ -96,8 +96,8 @@ public class LanguageDetection { return detectedLanguage; } - private boolean isCandidateForLanguage(Path absolutePath, Path relativePath, String languageKey) { - PathPattern[] patterns = patternsByLanguage.get(languageKey); + private boolean isCandidateForLanguage(Path absolutePath, Path relativePath, Language language) { + PathPattern[] patterns = patternsByLanguage.get(language); if (patterns != null) { for (PathPattern pathPattern : patterns) { if (pathPattern.match(absolutePath, relativePath, false)) { @@ -112,12 +112,12 @@ public class LanguageDetection { return "sonar.lang.patterns." + languageKey; } - private String getDetails(String detectedLanguage) { + private String getDetails(Language detectedLanguage) { return getDetails(detectedLanguage, patternsByLanguage.get(detectedLanguage)); } - private static String getDetails(String detectedLanguage, PathPattern[] patterns) { - return getFileLangPatternPropKey(detectedLanguage) + " : " + + private static String getDetails(Language detectedLanguage, PathPattern[] patterns) { + return getFileLangPatternPropKey(detectedLanguage.key()) + " : " + Arrays.stream(patterns).map(PathPattern::toString).collect(Collectors.joining(",")); } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java index 2cdab7cea2c..68a3e1969a9 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java @@ -87,7 +87,7 @@ import static java.util.Collections.emptySet; public class ScannerMediumTester extends ExternalResource { private static Path userHome = null; - private Map globalProperties = new HashMap<>(); + private final Map globalProperties = new HashMap<>(); private final FakeMetricsRepositoryLoader globalRefProvider = new FakeMetricsRepositoryLoader(); private final FakeBranchConfigurationLoader branchConfigurationLoader = new FakeBranchConfigurationLoader(); private final FakeBranchConfiguration branchConfiguration = new FakeBranchConfiguration(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java index 8ce1a2dcf9b..7d62eed8208 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/FileSystemMediumTest.java @@ -43,6 +43,7 @@ import org.sonar.api.utils.log.LogTester; import org.sonar.api.utils.log.LoggerLevel; import org.sonar.scanner.mediumtest.AnalysisResult; import org.sonar.scanner.mediumtest.ScannerMediumTester; +import org.sonar.scanner.mediumtest.ScannerMediumTester.AnalysisBuilder; import org.sonar.xoo.XooPlugin; import org.sonar.xoo.global.DeprecatedGlobalSensor; import org.sonar.xoo.global.GlobalProjectSensor; @@ -50,6 +51,7 @@ import org.sonar.xoo.rule.XooRulesDefinition; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; import static org.junit.Assume.assumeTrue; public class FileSystemMediumTest { @@ -80,12 +82,11 @@ public class FileSystemMediumTest { } @Test - public void scanProjectWithoutProjectName() throws IOException { + public void scan_project_without_name() throws IOException { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -108,7 +109,7 @@ public class FileSystemMediumTest { } @Test - public void logBranchNameAndType() { + public void log_branch_name_and_type() { builder.put("sonar.branch.name", "my-branch"); File srcDir = new File(baseDir, "src"); assertThat(srcDir.mkdir()).isTrue(); @@ -123,15 +124,12 @@ public class FileSystemMediumTest { } @Test - public void onlyGenerateMetadataIfNeeded() throws IOException { + public void only_generate_metadata_if_needed() throws IOException { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File javaFile = new File(srcDir, "sample.java"); - FileUtils.write(javaFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); + writeFile(srcDir, "sample.java", "Sample xoo\ncontent"); logTester.setLevel(LoggerLevel.DEBUG); @@ -147,17 +145,14 @@ public class FileSystemMediumTest { } @Test - public void preloadFileMetadata() throws IOException { + public void preload_file_metadata() throws IOException { builder.put("sonar.preloadFileMetadata", "true"); File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File javaFile = new File(srcDir, "sample.java"); - FileUtils.write(javaFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); + writeFile(srcDir, "sample.java", "Sample xoo\ncontent"); logTester.setLevel(LoggerLevel.DEBUG); @@ -173,21 +168,16 @@ public class FileSystemMediumTest { } @Test - public void dontPublishFilesWithoutDetectedLanguage() throws IOException { + public void dont_publish_files_without_detected_language() throws IOException { Path mainDir = baseDir.toPath().resolve("src").resolve("main"); Files.createDirectories(mainDir); Path testDir = baseDir.toPath().resolve("src").resolve("test"); Files.createDirectories(testDir); - Path testXooFile = testDir.resolve("sample.java"); - Files.write(testXooFile, "Sample xoo\ncontent".getBytes(StandardCharsets.UTF_8)); - - Path xooFile = mainDir.resolve("sample.xoo"); - Files.write(xooFile, "Sample xoo\ncontent".getBytes(StandardCharsets.UTF_8)); - - Path javaFile = mainDir.resolve("sample.java"); - Files.write(javaFile, "Sample xoo\ncontent".getBytes(StandardCharsets.UTF_8)); + writeFile(testDir.toFile(), "sample.java", "Sample xoo\ncontent"); + writeFile(mainDir.toFile(), "sample.xoo", "Sample xoo\ncontent"); + writeFile(mainDir.toFile(), "sample.java", "Sample xoo\ncontent"); logTester.setLevel(LoggerLevel.DEBUG); @@ -211,7 +201,7 @@ public class FileSystemMediumTest { } @Test - public void createIssueOnAnyFile() throws IOException { + public void create_issue_on_any_file() throws IOException { tester .addRules(new XooRulesDefinition()) .addActiveRule("xoo", "OneIssuePerUnknownFile", null, "OneIssuePerUnknownFile", "MAJOR", null, "xoo"); @@ -219,8 +209,7 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.unknown"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.unknown", "Sample xoo\ncontent"); logTester.setLevel(LoggerLevel.DEBUG); @@ -248,8 +237,7 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); File unknownFile = new File(srcDir, "myfile.binary"); byte[] b = new byte[512]; @@ -277,11 +265,8 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\npattern", StandardCharsets.UTF_8); - - File unknownFile = new File(srcDir, "myfile.binary"); - FileUtils.write(unknownFile, "some text", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\npattern"); + writeFile(srcDir, "myfile.binary", "some text"); logTester.setLevel(LoggerLevel.DEBUG); @@ -304,8 +289,7 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -324,8 +308,7 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -364,8 +347,7 @@ public class FileSystemMediumTest { File test = new File(baseDir, "test"); test.mkdir(); - File xooFile = new File(test, "sampleTest.xoo"); - FileUtils.write(xooFile, "Sample test xoo\ncontent", StandardCharsets.UTF_8); + writeFile(test, "sampleTest.xoo", "Sample test xoo\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -386,20 +368,14 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFile2 = new File(baseDir, "another.xoo"); - FileUtils.write(xooFile2, "Sample xoo 2\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); + writeFile(baseDir, "another.xoo", "Sample xoo 2\ncontent"); File testDir = new File(baseDir, "test"); testDir.mkdir(); - File xooTestFile = new File(baseDir, "sampleTest2.xoo"); - FileUtils.write(xooTestFile, "Sample test xoo\ncontent", StandardCharsets.UTF_8); - - File xooTestFile2 = new File(testDir, "sampleTest.xoo"); - FileUtils.write(xooTestFile2, "Sample test xoo 2\ncontent", StandardCharsets.UTF_8); + writeFile(baseDir, "sampleTest2.xoo", "Sample test xoo\ncontent"); + writeFile(testDir, "sampleTest.xoo", "Sample test xoo 2\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -416,20 +392,14 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFile2 = new File(baseDir, "another.xoo"); - FileUtils.write(xooFile2, "Sample xoo 2\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); + writeFile(baseDir, "another.xoo", "Sample xoo 2\ncontent"); File testDir = new File(baseDir, "test"); testDir.mkdir(); - File xooTestFile = new File(baseDir, "sampleTest2.xoo"); - FileUtils.write(xooTestFile, "Sample test xoo\ncontent"); - - File xooTestFile2 = new File(testDir, "sampleTest.xoo"); - FileUtils.write(xooTestFile2, "Sample test xoo 2\ncontent"); + writeFile(baseDir, "sampleTest2.xoo", "Sample test xoo\ncontent"); + writeFile(testDir, "sampleTest.xoo", "Sample test xoo 2\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -455,11 +425,8 @@ public class FileSystemMediumTest { File srcDirB = new File(baseDirModuleB, "tests"); srcDirB.mkdirs(); - File xooFileA = new File(srcDirA, "sampleTestA.xoo"); - FileUtils.write(xooFileA, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFileB = new File(srcDirB, "sampleTestB.xoo"); - FileUtils.write(xooFileB, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDirA, "sampleTestA.xoo", "Sample xoo\ncontent"); + writeFile(srcDirB, "sampleTestB.xoo", "Sample xoo\ncontent"); final ImmutableMap.Builder builder = ImmutableMap.builder() .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) @@ -505,11 +472,8 @@ public class FileSystemMediumTest { File srcDirB = new File(baseDirModuleB, "src"); srcDirB.mkdirs(); - File xooFileA = new File(srcDirA, "sampleA.xoo"); - FileUtils.write(xooFileA, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFileB = new File(srcDirB, "sampleB.xoo"); - FileUtils.write(xooFileB, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDirA, "sampleA.xoo", "Sample xoo\ncontent"); + writeFile(srcDirB, "sampleB.xoo", "Sample xoo\ncontent"); final ImmutableMap.Builder builder = ImmutableMap.builder() .put("sonar.projectBaseDir", baseDir.getAbsolutePath()) @@ -546,11 +510,8 @@ public class FileSystemMediumTest { File srcDirB = new File(baseDirModuleB, "src"); srcDirB.mkdirs(); - File xooFileA = new File(srcDirA, "sample.xoo"); - FileUtils.write(xooFileA, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFileB = new File(srcDirB, "sample.xoo"); - FileUtils.write(xooFileB, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); + writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(ImmutableMap.builder() @@ -583,11 +544,8 @@ public class FileSystemMediumTest { File srcDirB = new File(baseDirModuleB, "src"); srcDirB.mkdirs(); - File xooFileA = new File(srcDirA, "sample.xoo"); - FileUtils.write(xooFileA, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFileB = new File(srcDirB, "sample.xoo"); - FileUtils.write(xooFileB, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); + writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); tester.addGlobalServerSettings(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, "**/*.xoo"); @@ -617,11 +575,8 @@ public class FileSystemMediumTest { File srcDirB = new File(baseDirModuleB, "src"); srcDirB.mkdirs(); - File xooFileA = new File(srcDirA, "sample.xoo"); - FileUtils.write(xooFileA, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFileB = new File(srcDirB, "sample.xoo"); - FileUtils.write(xooFileB, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); + writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); tester.addGlobalServerSettings(CoreProperties.GLOBAL_EXCLUSIONS_PROPERTY, "**/*.xoo"); @@ -651,11 +606,8 @@ public class FileSystemMediumTest { File srcDirB = new File(baseDirModuleB, "src"); srcDirB.mkdirs(); - File xooFileA = new File(srcDirA, "sample.xoo"); - FileUtils.write(xooFileA, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFileB = new File(srcDirB, "sample.xoo"); - FileUtils.write(xooFileB, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); + writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); tester.addProjectServerSettings("sonar.exclusions", "src/sample.xoo"); @@ -684,8 +636,7 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); assertThatThrownBy(() -> tester.newAnalysis() .properties(builder @@ -702,8 +653,7 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "module1/src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); assertThatThrownBy(() -> tester.newAnalysis() .properties(builder @@ -738,7 +688,7 @@ public class FileSystemMediumTest { public void scanProjectWithWrongCase() { // To please the quality gate, don't use assumeTrue, or the test will be reported as skipped File projectDir = new File("test-resources/mediumtest/xoo/sample"); - ScannerMediumTester.AnalysisBuilder analysis = tester + AnalysisBuilder analysis = tester .newAnalysis(new File(projectDir, "sonar-project.properties")) .property("sonar.sources", "XOURCES") .property("sonar.tests", "TESTX") @@ -782,11 +732,8 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent"); - - File otherFile = new File(srcDir, "sample.other"); - FileUtils.write(otherFile, "Sample other\ncontent"); + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); + writeFile(srcDir, "sample.other", "Sample other\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -843,24 +790,18 @@ public class FileSystemMediumTest { } @Test - public void scanProjectWithCommaInSourcePath() throws IOException { + public void scan_project_with_comma_in_source_path() throws IOException { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample,1.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFile2 = new File(baseDir, "another,2.xoo"); - FileUtils.write(xooFile2, "Sample xoo 2\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample,1.xoo", "Sample xoo\ncontent"); + writeFile(baseDir, "another,2.xoo", "Sample xoo 2\ncontent"); File testDir = new File(baseDir, "test"); testDir.mkdir(); - File xooTestFile = new File(testDir, "sampleTest,1.xoo"); - FileUtils.write(xooTestFile, "Sample test xoo\ncontent", StandardCharsets.UTF_8); - - File xooTestFile2 = new File(baseDir, "sampleTest,2.xoo"); - FileUtils.write(xooTestFile2, "Sample test xoo 2\ncontent", StandardCharsets.UTF_8); + writeFile(testDir, "sampleTest,1.xoo", "Sample test xoo\ncontent"); + writeFile(baseDir, "sampleTest,2.xoo", "Sample test xoo 2\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -873,15 +814,32 @@ public class FileSystemMediumTest { } @Test - public void twoLanguagesWithSameExtension() throws IOException { + public void language_without_publishAllFiles_should_not_auto_publish_files() throws IOException { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample.xoo3", "Sample xoo\ncontent"); + writeFile(srcDir, "sample2.xoo3", "Sample xoo 2\ncontent"); - File xooFile2 = new File(srcDir, "sample.xoo2"); - FileUtils.write(xooFile2, "Sample xoo 2\ncontent", StandardCharsets.UTF_8); + AnalysisResult result = tester.newAnalysis() + .properties(builder + .put("sonar.sources", "src") + .build()) + .execute(); + + assertThat(result.inputFiles()) + .extracting(InputFile::filename, InputFile::language, f -> ((DefaultInputFile) f).isPublished()) + .containsOnly(tuple("sample.xoo3", "xoo3", false), tuple("sample2.xoo3", "xoo3", false)); + assertThat(result.getReportReader().readComponent(result.getReportReader().readMetadata().getRootComponentRef()).getChildRefCount()).isZero(); + } + + @Test + public void two_languages_with_same_extension() throws IOException { + File srcDir = new File(baseDir, "src"); + srcDir.mkdir(); + + writeFile(srcDir, "sample.xoo", "Sample xoo\ncontent"); + writeFile(srcDir, "sample.xoo2", "Sample xoo 2\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -891,19 +849,16 @@ public class FileSystemMediumTest { assertThat(result.inputFiles()).hasSize(2); - try { - result = tester.newAnalysis() - .properties(builder - .put("sonar.lang.patterns.xoo2", "**/*.xoo") - .build()) - .execute(); - } catch (Exception e) { - assertThat(e) - .isInstanceOf(MessageException.class) - .hasMessage( - "Language of file 'src" + File.separator - + "sample.xoo' can not be decided as the file matches patterns of both sonar.lang.patterns.xoo : **/*.xoo and sonar.lang.patterns.xoo2 : **/*.xoo"); - } + AnalysisBuilder analysisBuilder = tester.newAnalysis() + .properties(builder + .put("sonar.lang.patterns.xoo2", "**/*.xoo") + .build()); + + assertThatThrownBy(analysisBuilder::execute) + .isInstanceOf(MessageException.class) + .hasMessage( + "Language of file 'src" + File.separator + + "sample.xoo' can not be decided as the file matches patterns of both sonar.lang.patterns.xoo : **/*.xoo and sonar.lang.patterns.xoo2 : **/*.xoo"); // SONAR-9561 result = tester.newAnalysis() @@ -925,11 +880,8 @@ public class FileSystemMediumTest { File srcDirB = new File(baseDirModuleB, "src"); srcDirB.mkdirs(); - File xooFileA = new File(srcDirA, "sample.xoo"); - FileUtils.write(xooFileA, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFileB = new File(srcDirB, "sample.xoo"); - FileUtils.write(xooFileB, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDirA, "sample.xoo", "Sample xoo\ncontent"); + writeFile(srcDirB, "sample.xoo", "Sample xoo\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(ImmutableMap.builder() @@ -987,12 +939,10 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample1.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample1.xoo", "Sample xoo\ncontent"); File outsideBaseDir = temp.newFolder().getCanonicalFile(); - File xooFile2 = new File(outsideBaseDir, "another.xoo"); - FileUtils.write(xooFile2, "Sample xoo 2\ncontent", StandardCharsets.UTF_8); + File xooFile2 = writeFile(outsideBaseDir, "another.xoo", "Sample xoo 2\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -1009,8 +959,7 @@ public class FileSystemMediumTest { File srcDir = new File(baseDir, "src"); srcDir.mkdir(); - File xooFile = new File(srcDir, "sample1.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); + writeFile(srcDir, "sample1.xoo", "Sample xoo\ncontent"); File outsideBaseDir = temp.newFolder().getCanonicalFile(); File xooFile2 = new File(outsideBaseDir, "another.xoo"); @@ -1032,11 +981,8 @@ public class FileSystemMediumTest { File moduleA = new File(baseDir, "moduleA"); moduleA.mkdir(); - File xooFileA = new File(moduleA, "src/sampleA.xoo"); - FileUtils.write(xooFileA, "Sample xoo\ncontent", StandardCharsets.UTF_8); - - File xooFile2 = new File(baseDir, "another.xoo"); - FileUtils.write(xooFile2, "Sample xoo 2\ncontent", StandardCharsets.UTF_8); + writeFile(moduleA, "src/sampleA.xoo", "Sample xoo\ncontent"); + File xooFile2 = writeFile(baseDir, "another.xoo", "Sample xoo 2\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder @@ -1086,9 +1032,7 @@ public class FileSystemMediumTest { @Test public void index_basedir_by_default() throws IOException { - File xooFile = new File(baseDir, "sample.xoo"); - FileUtils.write(xooFile, "Sample xoo\ncontent", StandardCharsets.UTF_8); - + writeFile(baseDir, "sample.xoo", "Sample xoo\ncontent"); AnalysisResult result = tester.newAnalysis() .properties(builder .build()) @@ -1097,4 +1041,10 @@ public class FileSystemMediumTest { assertThat(logTester.logs()).contains("1 file indexed"); assertThat(result.inputFile("sample.xoo")).isNotNull(); } + + private File writeFile(File parent, String name, String content) throws IOException { + File file = new File(parent, name); + FileUtils.write(file, content, StandardCharsets.UTF_8); + return file; + } } 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 new file mode 100644 index 00000000000..b19da449aa7 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/DefaultLanguagesRepositoryTest.java @@ -0,0 +1,118 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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.language; + +import org.junit.Test; +import org.sonar.api.resources.Language; +import org.sonar.api.resources.Languages; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DefaultLanguagesRepositoryTest { + private final Languages languages = mock(Languages.class); + private final DefaultLanguagesRepository underTest = new DefaultLanguagesRepository(languages); + + @Test + public void returns_all_languages() { + when(languages.all()).thenReturn(new Language[] {new TestLanguage("k1", true), new TestLanguage("k2", false)}); + assertThat(underTest.all()) + .extracting("key", "name", "fileSuffixes", "publishAllFiles") + .containsOnly( + tuple("k1", "name k1", new String[] {"k1"}, true), + tuple("k2", "name k2", new String[] {"k2"}, false) + ); + } + + @Test + public void publishAllFiles_by_default() { + when(languages.all()).thenReturn(new Language[] {new TestLanguage2("k1"), new TestLanguage2("k2")}); + assertThat(underTest.all()) + .extracting("key", "name", "fileSuffixes", "publishAllFiles") + .containsOnly( + tuple("k1", "name k1", new String[] {"k1"}, true), + tuple("k2", "name k2", new String[] {"k2"}, true) + ); + } + + @Test + public void get_find_language_by_key() { + when(languages.get("k1")).thenReturn(new TestLanguage2("k1")); + assertThat(underTest.get("k1")) + .extracting("key", "name", "fileSuffixes", "publishAllFiles") + .containsOnly("k1", "name k1", new String[] {"k1"}, true); + } + + private static class TestLanguage implements Language { + private final String key; + private final boolean publishAllFiles; + + public TestLanguage(String key, boolean publishAllFiles) { + this.key = key; + this.publishAllFiles = publishAllFiles; + } + + @Override + public String getKey() { + return key; + } + + @Override + public String getName() { + return "name " + key; + } + + @Override + public String[] getFileSuffixes() { + return new String[] {key}; + } + + @Override + public boolean publishAllFiles() { + return publishAllFiles; + } + } + + private static class TestLanguage2 implements Language { + private final String key; + + public TestLanguage2(String key) { + this.key = key; + } + + @Override + public String getKey() { + return key; + } + + @Override + public String getName() { + return "name " + key; + } + + @Override + public String[] getFileSuffixes() { + return new String[] {key}; + } + } + +} 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 new file mode 100644 index 00000000000..ae115bc45b0 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/language/LanguageTest.java @@ -0,0 +1,51 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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.language; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LanguageTest { + @Test + public void hashCode_and_equals_depends_on_key() { + Language lang1 = new Language("key1", "name1", true, "f1"); + Language lang2 = new Language("key1", "name2", false, "f2"); + Language lang3 = new Language("key2", "name1", true, "f1"); + assertThat(lang1) + .hasSameHashCodeAs(lang2) + .doesNotHaveSameHashCodeAs(lang3); + assertThat(lang2).doesNotHaveSameHashCodeAs(lang3); + + assertThat(lang1) + .isEqualTo(lang2) + .isNotEqualTo(lang3); + assertThat(lang2).isNotEqualTo(lang3); + } + + @Test + public void getters_match_constructor() { + Language lang1 = new Language("key1", "name1", true, "f1"); + assertThat(lang1.key()).isEqualTo("key1"); + assertThat(lang1.name()).isEqualTo("name1"); + assertThat(lang1.isPublishAllFiles()).isTrue(); + assertThat(lang1.fileSuffixes()).containsOnly("f1"); + } +} 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 fc141f30ff7..c93179ee63d 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 @@ -62,23 +62,23 @@ public class LanguageDetectionTest { LanguagesRepository languages = new DefaultLanguagesRepository(new Languages(new MockLanguage("java", "java", "jav"), new MockLanguage("cobol", "cbl", "cob"))); LanguageDetection detection = new LanguageDetection(settings.asConfig(), languages); - assertThat(detectLanguage(detection, "Foo.java")).isEqualTo("java"); - assertThat(detectLanguage(detection, "src/Foo.java")).isEqualTo("java"); - assertThat(detectLanguage(detection, "Foo.JAVA")).isEqualTo("java"); - assertThat(detectLanguage(detection, "Foo.jav")).isEqualTo("java"); - assertThat(detectLanguage(detection, "Foo.Jav")).isEqualTo("java"); + assertThat(detectLanguageKey(detection, "Foo.java")).isEqualTo("java"); + assertThat(detectLanguageKey(detection, "src/Foo.java")).isEqualTo("java"); + assertThat(detectLanguageKey(detection, "Foo.JAVA")).isEqualTo("java"); + assertThat(detectLanguageKey(detection, "Foo.jav")).isEqualTo("java"); + assertThat(detectLanguageKey(detection, "Foo.Jav")).isEqualTo("java"); - assertThat(detectLanguage(detection, "abc.cbl")).isEqualTo("cobol"); - assertThat(detectLanguage(detection, "abc.CBL")).isEqualTo("cobol"); + assertThat(detectLanguageKey(detection, "abc.cbl")).isEqualTo("cobol"); + assertThat(detectLanguageKey(detection, "abc.CBL")).isEqualTo("cobol"); - assertThat(detectLanguage(detection, "abc.php")).isNull(); - assertThat(detectLanguage(detection, "abc")).isNull(); + assertThat(detectLanguageKey(detection, "abc.php")).isNull(); + assertThat(detectLanguageKey(detection, "abc")).isNull(); } @Test public void should_not_fail_if_no_language() { LanguageDetection detection = spy(new LanguageDetection(settings.asConfig(), new DefaultLanguagesRepository(new Languages()))); - assertThat(detectLanguage(detection, "Foo.java")).isNull(); + assertThat(detectLanguageKey(detection, "Foo.java")).isNull(); } @Test @@ -86,7 +86,7 @@ public class LanguageDetectionTest { LanguagesRepository languages = new DefaultLanguagesRepository(new Languages(new MockLanguage("abap", "abap", "ABAP"))); LanguageDetection detection = new LanguageDetection(settings.asConfig(), languages); - assertThat(detectLanguage(detection, "abc.abap")).isEqualTo("abap"); + assertThat(detectLanguageKey(detection, "abc.abap")).isEqualTo("abap"); } @Test @@ -94,7 +94,7 @@ public class LanguageDetectionTest { LanguagesRepository languages = new DefaultLanguagesRepository(new Languages(new MockLanguage("xml", "xhtml"), new MockLanguage("web", "xhtml"))); LanguageDetection detection = new LanguageDetection(settings.asConfig(), languages); try { - detectLanguage(detection, "abc.xhtml"); + detectLanguageKey(detection, "abc.xhtml"); fail(); } catch (MessageException e) { assertThat(e.getMessage()) @@ -111,8 +111,8 @@ public class LanguageDetectionTest { settings.setProperty("sonar.lang.patterns.xml", "xml/**"); settings.setProperty("sonar.lang.patterns.web", "web/**"); LanguageDetection detection = new LanguageDetection(settings.asConfig(), languages); - assertThat(detectLanguage(detection, "xml/abc.xhtml")).isEqualTo("xml"); - assertThat(detectLanguage(detection, "web/abc.xhtml")).isEqualTo("web"); + assertThat(detectLanguageKey(detection, "xml/abc.xhtml")).isEqualTo("xml"); + assertThat(detectLanguageKey(detection, "web/abc.xhtml")).isEqualTo("web"); } @Test @@ -123,10 +123,10 @@ public class LanguageDetectionTest { LanguageDetection detection = new LanguageDetection(settings.asConfig(), languages); - assertThat(detectLanguage(detection, "abc.abap")).isEqualTo("abap"); - assertThat(detectLanguage(detection, "abc.cobol")).isEqualTo("cobol"); + assertThat(detectLanguageKey(detection, "abc.abap")).isEqualTo("abap"); + assertThat(detectLanguageKey(detection, "abc.cobol")).isEqualTo("cobol"); try { - detectLanguage(detection, "abc.txt"); + detectLanguageKey(detection, "abc.txt"); fail(); } catch (MessageException e) { assertThat(e.getMessage()) @@ -136,8 +136,9 @@ public class LanguageDetectionTest { } } - private String detectLanguage(LanguageDetection detection, String path) { - return detection.language(new File(temp.getRoot(), path).toPath(), Paths.get(path)); + private String detectLanguageKey(LanguageDetection detection, String path) { + org.sonar.scanner.repository.language.Language language = detection.language(new File(temp.getRoot(), path).toPath(), Paths.get(path)); + return language != null ? language.key() : null; } static class MockLanguage implements Language { @@ -163,5 +164,10 @@ public class LanguageDetectionTest { public String[] getFileSuffixes() { return extensions; } + + @Override + public boolean publishAllFiles() { + return true; + } } } -- 2.39.5