aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2018-06-07 16:59:49 +0200
committerSonarTech <sonartech@sonarsource.com>2018-06-11 20:20:48 +0200
commit03692a7deed5cd6d3558946458c3e4af95248b1b (patch)
tree6023cab50e5684891ec34df21637c14f7aacc68b
parent4ce3f21921ceda09e54d4c43e7b09169ab375df9 (diff)
downloadsonarqube-03692a7deed5cd6d3558946458c3e4af95248b1b.tar.gz
sonarqube-03692a7deed5cd6d3558946458c3e4af95248b1b.zip
SONAR-10283 Fail fast at startup when a language is missing a default built in quality profile
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java24
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java7
-rw-r--r--settings.gradle1
-rw-r--r--tests/build.gradle1
-rw-r--r--tests/plugins/foo-plugin-without-qprofile/build.gradle29
-rw-r--r--tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/Foo.java43
-rw-r--r--tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/FooPlugin.java35
-rw-r--r--tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/package-info.java23
-rw-r--r--tests/src/test/java/org/sonarqube/tests/Category5Suite.java2
-rw-r--r--tests/src/test/java/org/sonarqube/tests/qualityProfile/PluginWithoutBuiltinQualityProfile.java58
10 files changed, 214 insertions, 9 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java
index bb8f4d2ac6c..519730c11d3 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImpl.java
@@ -20,15 +20,19 @@
package org.sonar.server.qualityprofile;
import com.google.common.collect.ImmutableList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
@@ -76,6 +80,7 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository
}
Map<String, Map<String, BuiltInQualityProfile>> rulesProfilesByLanguage = validateAndClean(context);
this.qProfiles = toFlatList(rulesProfilesByLanguage);
+ ensureAllLanguagesHaveAtLeastOneBuiltInQP();
profiler.stopDebug();
}
@@ -86,22 +91,29 @@ public class BuiltInQProfileRepositoryImpl implements BuiltInQProfileRepository
return qProfiles;
}
+ private void ensureAllLanguagesHaveAtLeastOneBuiltInQP() {
+ Set<String> languagesWithBuiltInQProfiles = qProfiles.stream().map(BuiltInQProfile::getLanguage).collect(Collectors.toSet());
+ Set<String> languagesWithoutBuiltInQProfiles = Arrays.stream(languages.all())
+ .map(Language::getKey)
+ .filter(key -> !languagesWithBuiltInQProfiles.contains(key))
+ .collect(Collectors.toSet());
+
+ checkState(languagesWithoutBuiltInQProfiles.isEmpty(), "The following languages have no built-in quality profiles: %s",
+ languagesWithoutBuiltInQProfiles.stream().collect(Collectors.joining()));
+ }
+
private Map<String, Map<String, BuiltInQualityProfile>> validateAndClean(BuiltInQualityProfilesDefinition.Context context) {
Map<String, Map<String, BuiltInQualityProfile>> profilesByLanguageAndName = context.profilesByLanguageAndName();
profilesByLanguageAndName.entrySet()
.removeIf(entry -> {
String language = entry.getKey();
if (languages.get(language) == null) {
- LOGGER.info("Language {} is not installed, related Quality profiles are ignored", language);
- return true;
- }
- Collection<BuiltInQualityProfile> profiles = entry.getValue().values();
- if (profiles.isEmpty()) {
- LOGGER.warn("No Quality profiles defined for language: {}", language);
+ LOGGER.info("Language {} is not installed, related quality profiles are ignored", language);
return true;
}
return false;
});
+
return profilesByLanguageAndName;
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java
index 0d1a96835f9..fa6d2b5b636 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/BuiltInQProfileRepositoryImplTest.java
@@ -71,12 +71,13 @@ public class BuiltInQProfileRepositoryImplTest {
}
@Test
- public void initialize_creates_no_BuiltInQProfile_when_there_is_no_definition() {
+ public void initialize_throws_ISE_if_language_has_no_builtin_qp() {
BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages(FOO_LANGUAGE));
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("The following languages have no built-in quality profiles: foo");
+
underTest.initialize();
-
- assertThat(underTest.get()).isEmpty();
}
@Test
diff --git a/settings.gradle b/settings.gradle
index f19d9e246a8..ff20a6df267 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -44,6 +44,7 @@ include 'tests:plugins:fake-governance-plugin'
include 'tests:plugins:foo-plugin-v1'
include 'tests:plugins:foo-plugin-v2'
include 'tests:plugins:foo-plugin-v3'
+include 'tests:plugins:foo-plugin-without-qprofile'
include 'tests:plugins:global-property-change-plugin'
include 'tests:plugins:issue-filter-plugin'
include 'tests:plugins:l10n-fr-pack'
diff --git a/tests/build.gradle b/tests/build.gradle
index 0701f734a2c..3b357654511 100644
--- a/tests/build.gradle
+++ b/tests/build.gradle
@@ -24,6 +24,7 @@ def pluginsForITs = [
':tests:plugins:foo-plugin-v1',
':tests:plugins:foo-plugin-v2',
':tests:plugins:foo-plugin-v3',
+ ':tests:plugins:foo-plugin-without-qprofile',
':tests:plugins:global-property-change-plugin',
':tests:plugins:issue-filter-plugin',
':tests:plugins:l10n-fr-pack',
diff --git a/tests/plugins/foo-plugin-without-qprofile/build.gradle b/tests/plugins/foo-plugin-without-qprofile/build.gradle
new file mode 100644
index 00000000000..a1eed2ef89e
--- /dev/null
+++ b/tests/plugins/foo-plugin-without-qprofile/build.gradle
@@ -0,0 +1,29 @@
+sonarqube {
+ skipProject = true
+}
+
+dependencies {
+ compile 'com.google.guava:guava'
+ compile 'commons-io:commons-io'
+ compile 'commons-lang:commons-lang'
+ compileOnly 'com.google.code.findbugs:jsr305'
+ compileOnly project(path: ':sonar-plugin-api', configuration: 'shadow')
+}
+
+jar {
+ manifest {
+ attributes(
+ 'Plugin-Key': 'foo',
+ 'Plugin-Version': version,
+ 'Plugin-Class': 'org.sonar.foo.FooPlugin',
+ 'Plugin-ChildFirstClassLoader': 'false',
+ 'Sonar-Version': version,
+ 'SonarLint-Supported': 'false',
+ 'Plugin-Name': 'Foo',
+ 'Plugin-License': 'GNU LGPL 3'
+ )
+ }
+ into('META-INF/lib') {
+ from configurations.compile
+ }
+}
diff --git a/tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/Foo.java b/tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/Foo.java
new file mode 100644
index 00000000000..0fe6566e0d6
--- /dev/null
+++ b/tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/Foo.java
@@ -0,0 +1,43 @@
+/*
+ * 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.foo;
+
+import org.sonar.api.resources.Language;
+
+public class Foo implements Language {
+
+ public static final String KEY = "foo";
+ public static final String NAME = "Foo";
+
+ @Override
+ public String getKey() {
+ return KEY;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public String[] getFileSuffixes() {
+ return new String[0];
+ }
+}
diff --git a/tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/FooPlugin.java b/tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/FooPlugin.java
new file mode 100644
index 00000000000..7ee8868d162
--- /dev/null
+++ b/tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/FooPlugin.java
@@ -0,0 +1,35 @@
+/*
+ * 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.foo;
+
+import org.sonar.api.Plugin;
+
+/**
+ * Plugin entry-point, as declared in pom.xml.
+ */
+public class FooPlugin implements Plugin {
+
+ @Override
+ public void define(Context context) {
+ context.addExtension(
+ Foo.class);
+ }
+
+}
diff --git a/tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/package-info.java b/tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/package-info.java
new file mode 100644
index 00000000000..7ebb0e1198d
--- /dev/null
+++ b/tests/plugins/foo-plugin-without-qprofile/src/main/java/org/sonar/foo/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.foo;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java
index b2a635e0703..bf1b19e2517 100644
--- a/tests/src/test/java/org/sonarqube/tests/Category5Suite.java
+++ b/tests/src/test/java/org/sonarqube/tests/Category5Suite.java
@@ -28,6 +28,7 @@ import org.sonarqube.tests.issue.IssueCreationDatePluginChangedTest;
import org.sonarqube.tests.marketplace.UpdateCenterTest;
import org.sonarqube.tests.qualityProfile.ActiveRuleEsResilienceTest;
import org.sonarqube.tests.qualityProfile.BuiltInQualityProfilesNotificationTest;
+import org.sonarqube.tests.qualityProfile.PluginWithoutBuiltinQualityProfile;
import org.sonarqube.tests.rule.RuleEsResilienceTest;
import org.sonarqube.tests.serverSystem.BlueGreenTest;
import org.sonarqube.tests.serverSystem.RestartTest;
@@ -64,6 +65,7 @@ import org.sonarqube.tests.user.UserEsResilienceTest;
HttpHeadersAuthenticationTest.class,
OnboardingTest.class,
BuiltInQualityProfilesNotificationTest.class,
+ PluginWithoutBuiltinQualityProfile.class,
ActiveRuleEsResilienceTest.class,
AnalysisEsResilienceTest.class,
RuleEsResilienceTest.class,
diff --git a/tests/src/test/java/org/sonarqube/tests/qualityProfile/PluginWithoutBuiltinQualityProfile.java b/tests/src/test/java/org/sonarqube/tests/qualityProfile/PluginWithoutBuiltinQualityProfile.java
new file mode 100644
index 00000000000..37fc1767534
--- /dev/null
+++ b/tests/src/test/java/org/sonarqube/tests/qualityProfile/PluginWithoutBuiltinQualityProfile.java
@@ -0,0 +1,58 @@
+/*
+ * 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.sonarqube.tests.qualityProfile;
+
+import com.sonar.orchestrator.Orchestrator;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static util.ItUtils.newOrchestratorBuilder;
+import static util.ItUtils.pluginArtifact;
+
+public class PluginWithoutBuiltinQualityProfile {
+ private static Orchestrator orchestrator;
+
+ @Test
+ public void should_fail_if_plugin_defines_language_and_no_builtin_qprofile() throws IOException {
+ orchestrator = newOrchestratorBuilder()
+ .addPlugin(pluginArtifact("foo-plugin-without-qprofile"))
+ .build();
+
+ try {
+ orchestrator.start();
+ fail("Expected to fail to start");
+ } catch (IllegalStateException e) {
+ String logs = FileUtils.readFileToString(orchestrator.getServer().getWebLogs(), StandardCharsets.UTF_8);
+ assertThat(logs).contains("java.lang.IllegalStateException: The following languages have no built-in quality profiles: foo");
+ }
+ }
+
+ @After
+ public void after() {
+ if (orchestrator != null) {
+ orchestrator.stop();
+ }
+ }
+}