aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java79
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/example-inheritance.json35
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest.java136
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest.java96
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-buWide.json14
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest/inheritance-buWide.json10
6 files changed, 251 insertions, 119 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java
index 131215733b5..2212384869c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceAction.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.qualityprofile.ws;
+import com.google.common.collect.Multimap;
import org.sonar.api.resources.Languages;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
@@ -31,9 +32,12 @@ import org.sonar.server.db.DbClient;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.qualityprofile.QProfile;
import org.sonar.server.qualityprofile.QProfileFactory;
+import org.sonar.server.qualityprofile.QProfileLoader;
import org.sonar.server.qualityprofile.QProfileLookup;
+import org.sonar.server.search.FacetValue;
import java.util.List;
+import java.util.Map;
public class QProfileInheritanceAction implements BaseQProfileWsAction {
@@ -41,13 +45,16 @@ public class QProfileInheritanceAction implements BaseQProfileWsAction {
private final QProfileLookup profileLookup;
+ private final QProfileLoader profileLoader;
+
private final QProfileFactory profileFactory;
private final Languages languages;
- public QProfileInheritanceAction(DbClient dbClient, QProfileLookup profileLookup, QProfileFactory profileFactory, Languages languages) {
+ public QProfileInheritanceAction(DbClient dbClient, QProfileLookup profileLookup, QProfileLoader profileLoader, QProfileFactory profileFactory, Languages languages) {
this.dbClient = dbClient;
this.profileLookup = profileLookup;
+ this.profileLoader = profileLoader;
this.profileFactory = profileFactory;
this.languages = languages;
}
@@ -75,40 +82,86 @@ public class QProfileInheritanceAction implements BaseQProfileWsAction {
List<QProfile> ancestors = profileLookup.ancestors(profile, session);
List<QualityProfileDto> children = dbClient.qualityProfileDao().findChildren(session, profileKey);
+ Map<String, Multimap<String, FacetValue>> profileStats = profileLoader.getAllProfileStats();
- writeResponse(response.newJsonWriter(), ancestors, children);
+ writeResponse(response.newJsonWriter(), profile, ancestors, children, profileStats);
} finally {
session.close();
}
}
- private void writeResponse(JsonWriter json, List<QProfile> ancestors, List<QualityProfileDto> children) {
+ private void writeResponse(JsonWriter json, QualityProfileDto profile, List<QProfile> ancestors, List<QualityProfileDto> children,
+ Map<String, Multimap<String, FacetValue>> profileStats) {
json.beginObject();
- writeAncestors(json, ancestors);
- writeChildren(json, children);
+ writeProfile(json, profile, profileStats);
+ writeAncestors(json, ancestors, profileStats);
+ writeChildren(json, children, profileStats);
json.endObject().close();
}
- private void writeAncestors(JsonWriter json, List<QProfile> ancestors) {
+ private void writeProfile(JsonWriter json, QualityProfileDto profile, Map<String, Multimap<String, FacetValue>> profileStats) {
+ String profileKey = profile.getKey();
+ json.name("profile").beginObject()
+ .prop("key", profileKey)
+ .prop("name", profile.getName())
+ .prop("parent", profile.getParentKee());
+ writeStats(json, profileKey, profileStats);
+ json.endObject();
+ }
+
+ private void writeAncestors(JsonWriter json, List<QProfile> ancestors, Map<String, Multimap<String, FacetValue>> profileStats) {
json.name("ancestors").beginArray();
for (QProfile ancestor : ancestors) {
+ String ancestorKey = ancestor.key();
json.beginObject()
- .prop("key", ancestor.key())
+ .prop("key", ancestorKey)
.prop("name", ancestor.name())
- .prop("parent", ancestor.parent())
- .endObject();
+ .prop("parent", ancestor.parent());
+ writeStats(json, ancestorKey, profileStats);
+ json.endObject();
}
json.endArray();
}
- private void writeChildren(JsonWriter json, List<QualityProfileDto> children) {
+ private void writeChildren(JsonWriter json, List<QualityProfileDto> children, Map<String, Multimap<String, FacetValue>> profileStats) {
json.name("children").beginArray();
for (QualityProfileDto child : children) {
+ String childKey = child.getKey();
json.beginObject()
- .prop("key", child.getKey())
- .prop("name", child.getName())
- .endObject();
+ .prop("key", childKey)
+ .prop("name", child.getName());
+ writeStats(json, childKey, profileStats);
+ json.endObject();
}
json.endArray();
}
+
+ private void writeStats(JsonWriter json, String profileKey, Map<String, Multimap<String, FacetValue>> profileStats) {
+ if (profileStats.containsKey(profileKey)) {
+ Multimap<String, FacetValue> ancestorStats = profileStats.get(profileKey);
+ json.prop("activeRuleCount", getActiveRuleCount(ancestorStats));
+ json.prop("overridingRuleCount", getOverridingRuleCount(ancestorStats));
+ }
+ }
+
+ private Long getActiveRuleCount(Multimap<String, FacetValue> profileStats) {
+ Long result = null;
+ if (profileStats.containsKey("countActiveRules")) {
+ result = profileStats.get("countActiveRules").iterator().next().getValue();
+ }
+ return result;
+ }
+
+ private Long getOverridingRuleCount(Multimap<String, FacetValue> profileStats) {
+ Long result = null;
+ if (profileStats.containsKey("inheritance")) {
+ for (FacetValue value : profileStats.get("inheritance")) {
+ if ("OVERRIDES".equals(value.getKey())) {
+ result = value.getValue();
+ }
+ }
+ }
+ return result;
+ }
+
}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/example-inheritance.json b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/example-inheritance.json
new file mode 100644
index 00000000000..743a4b7a18b
--- /dev/null
+++ b/server/sonar-server/src/main/resources/org/sonar/server/qualityprofile/ws/example-inheritance.json
@@ -0,0 +1,35 @@
+{
+ "profile": {
+ "key": "xoo-my-bu-profile-23456",
+ "name": "My BU Profile",
+ "parent": "xoo-my-company-profile-12345",
+ "activeRuleCount": 3,
+ "overridingRuleCount": 1
+ },
+ "ancestors": [
+ {
+ "key": "xoo-my-company-profile-12345",
+ "name": "My Company Profile",
+ "parent": "xoo-my-group-profile-01234",
+ "activeRuleCount": 3
+ },
+ {
+ "key": "xoo-my-group-profile-01234",
+ "name": "My Group Profile",
+ "activeRuleCount": 2
+ }
+ ],
+ "children": [
+ {
+ "key": "xoo-for-project-one-34567",
+ "name": "For Project One",
+ "activeRuleCount": 5
+ },
+ {
+ "key": "xoo-for-project-two-45678",
+ "name": "For Project Two",
+ "activeRuleCount": 4,
+ "overridingRuleCount": 1
+ }
+ ]
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest.java
new file mode 100644
index 00000000000..0a6d0c823a7
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest.java
@@ -0,0 +1,136 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.server.qualityprofile.ws;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualityprofile.QProfileName;
+import org.sonar.server.qualityprofile.QProfileTesting;
+import org.sonar.server.qualityprofile.RuleActivation;
+import org.sonar.server.qualityprofile.RuleActivator;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.ws.WsTester;
+
+public class QProfileInheritanceActionMediumTest {
+
+ @ClassRule
+ public static final ServerTester tester = new ServerTester();
+
+ private WsTester wsTester;
+
+ private DbClient db;
+
+ private DbSession session;
+
+ @Before
+ public void setUp() throws Exception {
+ tester.clearDbAndIndexes();
+ db = tester.get(DbClient.class);
+ session = db.openSession(false);
+
+ wsTester = new WsTester(tester.get(QProfilesWs.class));
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void inheritance_nominal() throws Exception {
+ RuleDto rule1 = createRule("xoo", "rule1");
+ RuleDto rule2 = createRule("xoo", "rule2");
+ RuleDto rule3 = createRule("xoo", "rule3");
+
+ /*
+ * groupWide (2) <- companyWide (2) <- buWide (2, 1 overriding) <- (forProject1 (2), forProject2 (2))
+ */
+ QualityProfileDto groupWide = createProfile("xoo", "My Group Profile", "xoo-my-group-profile-01234");
+ createActiveRule(rule1, groupWide);
+ createActiveRule(rule2, groupWide);
+ session.commit();
+
+ QualityProfileDto companyWide = createProfile("xoo", "My Company Profile", "xoo-my-company-profile-12345");
+ setParent(groupWide, companyWide);
+
+ QualityProfileDto buWide = createProfile("xoo", "My BU Profile", "xoo-my-bu-profile-23456");
+ setParent(companyWide, buWide);
+ overrideActiveRuleSeverity(rule1, buWide, Severity.CRITICAL);
+
+ QualityProfileDto forProject1 = createProfile("xoo", "For Project One", "xoo-for-project-one-34567");
+ setParent(buWide, forProject1);
+ createActiveRule(rule3, forProject1);
+ session.commit();
+
+ QualityProfileDto forProject2 = createProfile("xoo", "For Project Two", "xoo-for-project-two-45678");
+ setParent(buWide, forProject2);
+ overrideActiveRuleSeverity(rule2, forProject2, Severity.CRITICAL);
+
+ wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", buWide.getKee()).execute().assertJson(getClass(), "inheritance-buWide.json");
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void fail_if_not_found() throws Exception {
+ wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", "polop").execute();
+ }
+
+ private QualityProfileDto createProfile(String lang, String name, String key) {
+ QualityProfileDto profile = QProfileTesting.newDto(new QProfileName(lang, name), key);
+ db.qualityProfileDao().insert(session, profile);
+ session.commit();
+ return profile;
+ }
+
+ private void setParent(QualityProfileDto profile, QualityProfileDto parent) {
+ tester.get(RuleActivator.class).setParent(parent.getKey(), profile.getKey());
+ }
+
+ private RuleDto createRule(String lang, String id) {
+ RuleDto rule = RuleDto.createFor(RuleKey.of("blah", id))
+ .setLanguage(lang)
+ .setSeverity(Severity.BLOCKER)
+ .setStatus(RuleStatus.READY);
+ db.ruleDao().insert(session, rule);
+ return rule;
+ }
+
+ private ActiveRuleDto createActiveRule(RuleDto rule, QualityProfileDto profile) {
+ ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
+ .setSeverity(rule.getSeverityString());
+ db.activeRuleDao().insert(session, activeRule);
+ return activeRule;
+ }
+
+ private void overrideActiveRuleSeverity(RuleDto rule, QualityProfileDto profile, String severity) {
+ tester.get(RuleActivator.class).activate(session, new RuleActivation(rule.getKey()).setSeverity(severity), profile.getKey());
+ session.commit();
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest.java
deleted file mode 100644
index 4231d26966b..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.server.qualityprofile.ws;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.utils.System2;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.qualityprofile.db.QualityProfileDao;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.language.LanguageTesting;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.qualityprofile.QProfileTesting;
-import org.sonar.server.ws.WsTester;
-import org.sonar.test.DbTests;
-
-import static org.mockito.Mockito.mock;
-
-@Category(DbTests.class)
-public class QProfileInheritanceActionTest {
-
- @ClassRule
- public static final DbTester dbTester = new DbTester();
-
- private WsTester wsTester;
-
- private DbClient dbClient;
-
- private DbSession session;
-
- @Before
- public void setUp() throws Exception {
- dbTester.truncateTables();
- dbClient = new DbClient(dbTester.database(), dbTester.myBatis(),
- new QualityProfileDao(dbTester.myBatis(), mock(System2.class)));
- session = dbClient.openSession(false);
-
- wsTester = new WsTester(new QProfilesWs(
- mock(RuleActivationActions.class),
- mock(BulkRuleActivationActions.class),
- mock(ProjectAssociationActions.class),
- new QProfileInheritanceAction(dbClient, new QProfileLookup(dbClient), new QProfileFactory(dbClient), LanguageTesting.newLanguages("xoo"))));
- }
-
- @After
- public void tearDown() {
- session.close();
- }
-
- @Test
- public void inheritance_nominal() throws Exception {
- /*
- * groupWide <- companyWide <- buWide <- (forProject1, forProject2)
- */
- QualityProfileDto groupWide = QProfileTesting.newDto(QProfileName.createFor("xoo", "My Group Profile"), "xoo-my-group-profile-01234");
- QualityProfileDto companyWide = QProfileTesting.newDto(QProfileName.createFor("xoo", "My Company Profile"), "xoo-my-company-profile-12345").setParentKee(groupWide.getKee());
- QualityProfileDto buWide = QProfileTesting.newDto(QProfileName.createFor("xoo", "My BU Profile"), "xoo-my-by-profile-23456").setParentKee(companyWide.getKee());
- QualityProfileDto forProject1 = QProfileTesting.newDto(QProfileName.createFor("xoo", "For Project One"), "xoo-for-project-one-34567").setParentKee(buWide.getKee());
- QualityProfileDto forProject2 = QProfileTesting.newDto(QProfileName.createFor("xoo", "For Project Two"), "xoo-for-project-two-45678").setParentKee(buWide.getKee());
-
- dbClient.qualityProfileDao().insert(session, groupWide, companyWide, buWide, forProject1, forProject2);
- session.commit();
-
- wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", buWide.getKee()).execute().assertJson(getClass(), "inheritance-buWide.json");
- }
-
- @Test(expected = NotFoundException.class)
- public void fail_if_not_found() throws Exception {
- wsTester.newGetRequest("api/qualityprofiles", "inheritance").setParam("profileKey", "polop").execute();
- }
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-buWide.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-buWide.json
new file mode 100644
index 00000000000..9e3707e5d3f
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionMediumTest/inheritance-buWide.json
@@ -0,0 +1,14 @@
+{
+ "profile": {
+ "key": "xoo-my-bu-profile-23456", "name": "My BU Profile", "parent": "xoo-my-company-profile-12345",
+ "activeRuleCount": 2, "overridingRuleCount": 1
+ },
+ "ancestors": [
+ {"key": "xoo-my-company-profile-12345", "name": "My Company Profile", "parent": "xoo-my-group-profile-01234", "activeRuleCount": 2},
+ {"key": "xoo-my-group-profile-01234", "name": "My Group Profile", "activeRuleCount": 2}
+ ],
+ "children": [
+ {"key": "xoo-for-project-one-34567", "name": "For Project One", "activeRuleCount": 3},
+ {"key": "xoo-for-project-two-45678", "name": "For Project Two", "activeRuleCount": 2, "overridingRuleCount": 1}
+ ]
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest/inheritance-buWide.json b/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest/inheritance-buWide.json
deleted file mode 100644
index 154c25e3f13..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/qualityprofile/ws/QProfileInheritanceActionTest/inheritance-buWide.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "ancestors": [
- {"key": "xoo-my-company-profile-12345", "name": "My Company Profile", "parent": "xoo-my-group-profile-01234"},
- {"key": "xoo-my-group-profile-01234", "name": "My Group Profile"}
- ],
- "children": [
- {"key": "xoo-for-project-one-34567", "name": "For Project One"},
- {"key": "xoo-for-project-two-45678", "name": "For Project Two"}
- ]
-} \ No newline at end of file