From: Janos Gyerik Date: Thu, 20 Sep 2018 16:03:32 +0000 (+0200) Subject: SONAR-11244 Record warning when SCM provider cannot be detected X-Git-Tag: 7.5~365 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=322d31c6f65117d58f793865bedc597e30ac8be8;p=sonarqube.git SONAR-11244 Record warning when SCM provider cannot be detected --- diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java index 56957d3befd..b8bced98aa3 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java @@ -35,11 +35,14 @@ import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.fs.internal.InputModuleHierarchy; import org.sonar.api.batch.scm.ScmProvider; import org.sonar.api.config.Configuration; +import org.sonar.api.notifications.AnalysisWarnings; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.core.config.ScannerProperties; +import static org.sonar.api.CoreProperties.SCM_PROVIDER_KEY; + @Properties({ @Property( key = ScmConfiguration.FORCE_RELOAD_KEY, @@ -59,24 +62,28 @@ public class ScmConfiguration implements Startable { public static final String FORCE_RELOAD_KEY = "sonar.scm.forceReloadAll"; + static final String MESSAGE_SCM_STEP_IS_DISABLED_BY_CONFIGURATION = "SCM Step is disabled by configuration"; + private final Configuration settings; + private final AnalysisWarnings analysisWarnings; private final Map providerPerKey = new LinkedHashMap<>(); private final AnalysisMode analysisMode; private final InputModuleHierarchy moduleHierarchy; private ScmProvider provider; - public ScmConfiguration(InputModuleHierarchy moduleHierarchy, AnalysisMode analysisMode, Configuration settings, ScmProvider... providers) { + public ScmConfiguration(InputModuleHierarchy moduleHierarchy, AnalysisMode analysisMode, Configuration settings, AnalysisWarnings analysisWarnings, ScmProvider... providers) { this.moduleHierarchy = moduleHierarchy; this.analysisMode = analysisMode; this.settings = settings; + this.analysisWarnings = analysisWarnings; for (ScmProvider scmProvider : providers) { providerPerKey.put(scmProvider.key(), scmProvider); } } - public ScmConfiguration(InputModuleHierarchy moduleHierarchy, AnalysisMode analysisMode, Configuration settings) { - this(moduleHierarchy, analysisMode, settings, new ScmProvider[0]); + public ScmConfiguration(InputModuleHierarchy moduleHierarchy, AnalysisMode analysisMode, Configuration settings, AnalysisWarnings analysisWarnings) { + this(moduleHierarchy, analysisMode, settings, analysisWarnings, new ScmProvider[0]); } @Override @@ -85,19 +92,21 @@ public class ScmConfiguration implements Startable { return; } if (isDisabled()) { - LOG.debug("SCM Step is disabled by configuration"); + LOG.debug(MESSAGE_SCM_STEP_IS_DISABLED_BY_CONFIGURATION); return; } - if (settings.hasKey(CoreProperties.SCM_PROVIDER_KEY)) { - settings.get(CoreProperties.SCM_PROVIDER_KEY).ifPresent(this::setProviderIfSupported); + if (settings.hasKey(SCM_PROVIDER_KEY)) { + settings.get(SCM_PROVIDER_KEY).ifPresent(this::setProviderIfSupported); } else { autodetection(); if (this.provider == null) { considerOldScmUrl(); } if (this.provider == null) { - LOG.warn("SCM provider autodetection failed. No SCM provider claims to support this project. Please use " + CoreProperties.SCM_PROVIDER_KEY - + " to define SCM of your project."); + String message = "SCM provider autodetection failed. Please use \"" + SCM_PROVIDER_KEY + "\" to define SCM of " + + "your project, or disable the SCM Sensor in the project settings."; + LOG.warn(message); + analysisWarnings.addUnique(message); } } } @@ -130,7 +139,7 @@ public class ScmConfiguration implements Startable { this.provider = installedProvider; } else { throw MessageException.of("SCM provider autodetection failed. Both " + this.provider.key() + " and " + installedProvider.key() - + " claim to support this project. Please use " + CoreProperties.SCM_PROVIDER_KEY + " to define SCM of your project."); + + " claim to support this project. Please use \"" + SCM_PROVIDER_KEY + "\" to define SCM of your project."); } } } 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 new file mode 100644 index 00000000000..c4fbeacb211 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmConfigurationTest.java @@ -0,0 +1,181 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.scm; + +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; +import java.util.Optional; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.sonar.api.CoreProperties; +import org.sonar.api.batch.AnalysisMode; +import org.sonar.api.batch.fs.internal.InputModuleHierarchy; +import org.sonar.api.batch.scm.ScmProvider; +import org.sonar.api.config.Configuration; +import org.sonar.api.notifications.AnalysisWarnings; +import org.sonar.api.utils.MessageException; +import org.sonar.api.utils.log.LogTester; +import org.sonar.core.config.ScannerProperties; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; +import static org.sonar.scanner.scm.ScmConfiguration.MESSAGE_SCM_STEP_IS_DISABLED_BY_CONFIGURATION; + +@RunWith(DataProviderRunner.class) +public class ScmConfigurationTest { + + private final InputModuleHierarchy inputModuleHierarchy = mock(InputModuleHierarchy.class, withSettings().defaultAnswer(Answers.RETURNS_MOCKS)); + private final AnalysisMode analysisMode = mock(AnalysisMode.class); + private final AnalysisWarnings analysisWarnings = mock(AnalysisWarnings.class); + private final Configuration settings = mock(Configuration.class); + + private final String scmProviderKey = "dummyScmProviderKey"; + private final ScmProvider scmProvider = mock(ScmProvider.class); + + private final ScmConfiguration underTest; + + @Rule + public LogTester logTester = new LogTester(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + public ScmConfigurationTest() { + when(analysisMode.isIssues()).thenReturn(false); + when(scmProvider.key()).thenReturn(scmProviderKey); + + underTest = new ScmConfiguration(inputModuleHierarchy, analysisMode, settings, analysisWarnings, scmProvider); + } + + @Test + public void do_not_register_warning_when_success_to_autodetect_scm_provider() { + when(scmProvider.supports(any())).thenReturn(true); + + underTest.start(); + + assertThat(underTest.provider()).isNotNull(); + verifyZeroInteractions(analysisWarnings); + } + + @Test + public void register_warning_when_fail_to_detect_scm_provider() { + underTest.start(); + + assertThat(underTest.provider()).isNull(); + verify(analysisWarnings).addUnique(anyString()); + } + + @Test + public void log_when_disabled() { + when(settings.getBoolean(CoreProperties.SCM_DISABLED_KEY)).thenReturn(Optional.of(true)); + + underTest.start(); + + assertThat(logTester.logs()).contains(MESSAGE_SCM_STEP_IS_DISABLED_BY_CONFIGURATION); + } + + @Test + public void return_early_from_start_in_issues_mode() { + // return early = doesn't reach the logging when disabled + when(settings.getBoolean(CoreProperties.SCM_DISABLED_KEY)).thenReturn(Optional.of(true)); + when(analysisMode.isIssues()).thenReturn(true); + + underTest.start(); + + assertThat(logTester.logs()).isEmpty(); + } + + @Test + public void fail_when_multiple_scm_providers_claim_support() { + when(scmProvider.supports(any())).thenReturn(true); + when(scmProvider.key()).thenReturn("key1", "key2"); + + ScmProvider[] providers = {scmProvider, scmProvider}; + ScmConfiguration underTest = new ScmConfiguration(inputModuleHierarchy, analysisMode, settings, analysisWarnings, providers); + + thrown.expect(MessageException.class); + thrown.expectMessage( + new BaseMatcher() { + @Override + public void describeTo(Description description) { + + } + + @Override + public boolean matches(Object item) { + return ((String) item).matches("SCM provider autodetection failed. " + + "Both .* and .* claim to support this project. " + + "Please use \"sonar.scm.provider\" to define SCM of your project."); + } + }); + + underTest.start(); + } + + @Test + public void fail_when_considerOldScmUrl_finds_invalid_provider_in_link() { + when(settings.get(ScannerProperties.LINKS_SOURCES_DEV)).thenReturn(Optional.of("scm:invalid")); + + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("no SCM provider found for this key"); + + underTest.start(); + } + + @Test + public void set_provider_from_valid_link() { + when(settings.get(ScannerProperties.LINKS_SOURCES_DEV)).thenReturn(Optional.of("scm:" + scmProviderKey)); + + underTest.start(); + + assertThat(underTest.provider()).isSameAs(scmProvider); + } + + @Test + @UseDataProvider("malformedScmLinks") + public void dont_set_provider_from_links_if_malformed(String link) { + when(settings.get(ScannerProperties.LINKS_SOURCES_DEV)).thenReturn(Optional.of(link)); + + underTest.start(); + + assertThat(underTest.provider()).isNull(); + } + + @DataProvider + public static Object[][] malformedScmLinks() { + return new Object[][] { + {"invalid prefix"}, + {"scm"}, + {"scm:"} + }; + } +}