Browse Source

SONAR-20546 add inactiveRuleCount to `api/qualityprofiles/inheritance`

tags/10.3.0.82913
Benjamin Campomenosi 7 months ago
parent
commit
2245ffea6e

+ 38
- 9
server/sonar-db-dao/src/it/java/org/sonar/db/rule/RuleDaoIT.java View File

@@ -63,6 +63,8 @@ import static org.assertj.core.api.Assertions.tuple;
import static org.sonar.api.issue.impact.SoftwareQuality.MAINTAINABILITY;
import static org.sonar.api.issue.impact.SoftwareQuality.RELIABILITY;
import static org.sonar.api.issue.impact.SoftwareQuality.SECURITY;
import static org.sonar.api.rule.RuleStatus.*;
import static org.sonar.api.rule.RuleStatus.DEPRECATED;
import static org.sonar.api.rule.RuleStatus.REMOVED;

public class RuleDaoIT {
@@ -478,7 +480,7 @@ public class RuleDaoIT {
.setDescriptionFormat(RuleDto.Format.MARKDOWN)
.addRuleDescriptionSectionDto(sectionDto)
.addDefaultImpact(ruleDefaultImpactDto)
.setStatus(RuleStatus.DEPRECATED)
.setStatus(DEPRECATED)
.setConfigKey("NewConfigKey")
.setSeverity(Severity.INFO)
.setIsTemplate(true)
@@ -503,7 +505,7 @@ public class RuleDaoIT {
RuleDto ruleDto = underTest.selectOrFailByKey(db.getSession(), RuleKey.of("plugin", "NewRuleKey"));
assertThat(ruleDto.getUuid()).isNotNull();
assertThat(ruleDto.getName()).isEqualTo("new name");
assertThat(ruleDto.getStatus()).isEqualTo(RuleStatus.DEPRECATED);
assertThat(ruleDto.getStatus()).isEqualTo(DEPRECATED);
assertThat(ruleDto.getRuleKey()).isEqualTo("NewRuleKey");
assertThat(ruleDto.getRepositoryKey()).isEqualTo("plugin");
assertThat(ruleDto.getConfigKey()).isEqualTo("NewConfigKey");
@@ -526,7 +528,11 @@ public class RuleDaoIT {
assertThat(ruleDto.getDescriptionFormat()).isEqualTo(RuleDto.Format.MARKDOWN);
assertThat(ruleDto.getRuleDescriptionSectionDtos()).usingRecursiveFieldByFieldElementComparator()
.containsOnly(sectionDto);
assertThat(ruleDto.getCleanCodeAttribute()).isEqualTo(CleanCodeAttribute.CLEAR);
assertCleanCodeInformation(ruleDto, CleanCodeAttribute.CLEAR, ruleDefaultImpactDto);
}

private static void assertCleanCodeInformation(RuleDto ruleDto, CleanCodeAttribute attribute, ImpactDto ruleDefaultImpactDto) {
assertThat(ruleDto.getCleanCodeAttribute()).isEqualTo(attribute);
assertThat(ruleDto.getDefaultImpacts()).usingRecursiveFieldByFieldElementComparator()
.containsOnly(ruleDefaultImpactDto);
}
@@ -542,7 +548,7 @@ public class RuleDaoIT {
.setName("new name")
.setDescriptionFormat(RuleDto.Format.MARKDOWN)
.addRuleDescriptionSectionDto(sectionDto)
.setStatus(RuleStatus.DEPRECATED)
.setStatus(DEPRECATED)
.setConfigKey("NewConfigKey")
.setSeverity(Severity.INFO)
.setIsTemplate(true)
@@ -566,7 +572,7 @@ public class RuleDaoIT {

RuleDto ruleDto = underTest.selectOrFailByKey(db.getSession(), RuleKey.of("plugin", "NewRuleKey"));
assertThat(ruleDto.getName()).isEqualTo("new name");
assertThat(ruleDto.getStatus()).isEqualTo(RuleStatus.DEPRECATED);
assertThat(ruleDto.getStatus()).isEqualTo(DEPRECATED);
assertThat(ruleDto.getRuleKey()).isEqualTo("NewRuleKey");
assertThat(ruleDto.getRepositoryKey()).isEqualTo("plugin");
assertThat(ruleDto.getConfigKey()).isEqualTo("NewConfigKey");
@@ -854,9 +860,10 @@ public class RuleDaoIT {
.setDefaultValue("30")
.setDescription("My Parameter");

underTest.insertRuleParam(db.getSession(), ruleDefinitionDto, param);
DbSession session = db.getSession();
underTest.insertRuleParam(session, ruleDefinitionDto, param);

assertThatThrownBy(() -> underTest.insertRuleParam(db.getSession(), ruleDefinitionDto, param))
assertThatThrownBy(() -> underTest.insertRuleParam(session, ruleDefinitionDto, param))
.isInstanceOf(PersistenceException.class);
}

@@ -1171,15 +1178,37 @@ public class RuleDaoIT {
assertThat(deprecatedRuleKeyDto1.getRuleUuid()).isEqualTo(r1.getUuid());
}

@Test
public void countByLanguage_shouldReturnExpectedNumberOfRules() {
insertMultipleRules(10, "js", false, READY);
insertMultipleRules(5, "js", true, READY);
insertMultipleRules(3, "kotlin", false, DEPRECATED);
insertMultipleRules(3, "java", false, REMOVED);

db.getSession().commit();

assertThat(underTest.countByLanguage(db.getSession(), "js")).isEqualTo(10);
assertThat(underTest.countByLanguage(db.getSession(), "kotlin")).isEqualTo(3);
assertThat(underTest.countByLanguage(db.getSession(), "java")).isZero();

}

private void insertMultipleRules(int rulesCount, String language, boolean isExternal, RuleStatus ruleStatus) {
for (int i = 0; i < rulesCount; i++) {
db.rules().insert(rule -> rule.setLanguage(language).setIsExternal(isExternal).setStatus(ruleStatus));
}
}

@Test
public void insertDeprecatedRuleKey_with_same_RuleKey_should_fail() {
String repositoryKey = randomAlphanumeric(50);
String ruleKey = randomAlphanumeric(50);
db.rules().insertDeprecatedKey(d -> d.setOldRepositoryKey(repositoryKey)
RuleDbTester ruleTester = db.rules();
ruleTester.insertDeprecatedKey(d -> d.setOldRepositoryKey(repositoryKey)
.setOldRuleKey(ruleKey));

assertThatThrownBy(() -> {
db.rules().insertDeprecatedKey(d -> d.setOldRepositoryKey(repositoryKey)
ruleTester.insertDeprecatedKey(d -> d.setOldRepositoryKey(repositoryKey)
.setOldRuleKey(ruleKey));
})
.isInstanceOf(PersistenceException.class);

+ 4
- 0
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java View File

@@ -246,4 +246,8 @@ public class RuleDao implements Dao {
public void insert(DbSession dbSession, DeprecatedRuleKeyDto deprecatedRuleKey) {
mapper(dbSession).insertDeprecatedRuleKey(deprecatedRuleKey);
}

public long countByLanguage(DbSession dbSession, String language) {
return mapper(dbSession).countByLanguage(language);
}
}

+ 2
- 0
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java View File

@@ -49,6 +49,8 @@ public interface RuleMapper {

List<RuleDto> selectByLanguage(@Param("language") String language);

Long countByLanguage(@Param("language") String language);

void insertRule(RuleDto ruleDefinitionDto);

void insertRuleDescriptionSection(@Param("ruleUuid") String ruleUuid, @Param("dto") RuleDescriptionSectionDto ruleDescriptionSectionDto);

+ 15
- 3
server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml View File

@@ -244,11 +244,23 @@
from
rules r
where
r.status in ('READY', 'DEPRECATED')
and r.is_external=${_false}
and r.language=#{language, jdbcType=VARCHAR}
<include refid="conditionNotExternalRulesByLanguage" />
</select>

<select id="countByLanguage" resultType="java.lang.Long">
select count(*)
from
rules r
where
<include refid="conditionNotExternalRulesByLanguage" />
</select>

<sql id="conditionNotExternalRulesByLanguage">
r.status in ('READY', 'DEPRECATED', 'BETA')
and r.is_external=${_false}
and r.language=#{language, jdbcType=VARCHAR}
</sql>

<insert id="insertRuleDescriptionSection" parameterType="Map" useGeneratedKeys="false">
insert into rule_desc_sections (
uuid,

+ 9
- 9
server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/InheritanceActionIT.java View File

@@ -137,19 +137,18 @@ public class InheritanceActionIT {

@Test
public void inheritance_parent_child() throws Exception {
RuleDto rule1 = db.rules().insert();
RuleDto rule2 = db.rules().insert();
RuleDto rule3 = db.rules().insert();
String language = "java";
RuleDto rule1 = db.rules().insert(r -> r.setLanguage(language));
RuleDto rule2 = db.rules().insert(r -> r.setLanguage(language));
RuleDto rule3 = db.rules().insert(r -> r.setLanguage(language));
ruleIndexer.commitAndIndex(db.getSession(), asList(rule1.getUuid(), rule2.getUuid(), rule3.getUuid()));

QProfileDto parent = db.qualityProfiles().insert();
QProfileDto parent = db.qualityProfiles().insert(p -> p.setLanguage(language));
db.qualityProfiles().activateRule(parent, rule1);
db.qualityProfiles().activateRule(parent, rule2);
long parentRules = 2;

QProfileDto child = db.qualityProfiles().insert(q -> q.setParentKee(parent.getKee()));
QProfileDto child = db.qualityProfiles().insert(q -> q.setParentKee(parent.getKee()).setLanguage(language));
db.qualityProfiles().activateRule(child, rule3);
long childRules = 1;

activeRuleIndexer.indexAll();

@@ -163,10 +162,11 @@ public class InheritanceActionIT {
InheritanceWsResponse result = InheritanceWsResponse.parseFrom(response);

assertThat(result.getProfile().getKey()).isEqualTo(child.getKee());
assertThat(result.getProfile().getActiveRuleCount()).isEqualTo(childRules);
assertThat(result.getProfile().getActiveRuleCount()).isEqualTo(1);
assertThat(result.getProfile().getInactiveRuleCount()).isEqualTo(2);

assertThat(result.getAncestorsList()).extracting(InheritanceWsResponse.QualityProfile::getKey).containsExactly(parent.getKee());
assertThat(result.getAncestorsList()).extracting(InheritanceWsResponse.QualityProfile::getActiveRuleCount).containsExactly(parentRules);
assertThat(result.getAncestorsList()).extracting(InheritanceWsResponse.QualityProfile::getActiveRuleCount).containsExactly(2L);
}

@Test

+ 11
- 1
server/sonar-webserver-webapi/src/it/resources/org/sonar/server/qualityprofile/ws/InheritanceActionIT/inheritance-buWide.json View File

@@ -5,6 +5,7 @@
"parent": "xoo-my-company-profile-12345",
"activeRuleCount": 2,
"overridingRuleCount": 1,
"inactiveRuleCount": 1,
"isBuiltIn": false
},
"ancestors": [
@@ -13,12 +14,16 @@
"name": "My Company Profile",
"parent": "xoo-sonar-way",
"activeRuleCount": 2,
"overridingRuleCount": 0,
"inactiveRuleCount": 1,
"isBuiltIn": false
},
{
"key": "xoo-sonar-way",
"name": "Sonar way",
"activeRuleCount": 2,
"overridingRuleCount": 0,
"inactiveRuleCount": 1,
"isBuiltIn": true
}
],
@@ -26,15 +31,20 @@
{
"key": "xoo-for-project-one-34567",
"name": "For Project One",
"parent": "xoo-my-bu-profile-23456",
"activeRuleCount": 3,
"overridingRuleCount": 0,
"inactiveRuleCount": 0,
"isBuiltIn": false
},
{
"key": "xoo-for-project-two-45678",
"name": "For Project Two",
"parent": "xoo-my-bu-profile-23456",
"activeRuleCount": 2,
"overridingRuleCount": 1,
"inactiveRuleCount": 1,
"isBuiltIn": false
}
]
}
}

+ 9
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/InheritanceAction.java View File

@@ -20,9 +20,11 @@
package org.sonar.server.qualityprofile.ws;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.sonar.api.resources.Languages;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService.NewAction;
@@ -57,6 +59,7 @@ public class InheritanceAction implements QProfileWsAction {
NewAction inheritance = context.createAction("inheritance")
.setSince("5.2")
.setDescription("Show a quality profile's ancestors and children.")
.setChangelog(new Change("10.3", "Field 'inactiveRuleCount' added to the response"))
.setHandler(this)
.setResponseExample(getClass().getResource("inheritance-example.json"));

@@ -74,7 +77,7 @@ public class InheritanceAction implements QProfileWsAction {
allProfiles.add(profile);
allProfiles.addAll(ancestors);
allProfiles.addAll(children);
Statistics statistics = new Statistics(dbSession, allProfiles);
Statistics statistics = new Statistics(dbSession, allProfiles, profile.getLanguage());

writeProtobuf(buildResponse(profile, ancestors, children, statistics), request, response);
}
@@ -131,6 +134,7 @@ public class InheritanceAction implements QProfileWsAction {
.setName(qualityProfile.getName())
.setActiveRuleCount(statistics.countRulesByProfileKey.getOrDefault(key, 0L))
.setOverridingRuleCount(statistics.countOverridingRulesByProfileKey.getOrDefault(key, 0L))
.setInactiveRuleCount(statistics.countInactiveRuleByProfileKey.getOrDefault(key, 0L))
.setIsBuiltIn(qualityProfile.isBuiltIn());
ofNullable(qualityProfile.getParentKee()).ifPresent(builder::setParent);
return builder.build();
@@ -139,12 +143,15 @@ public class InheritanceAction implements QProfileWsAction {
private class Statistics {
private final Map<String, Long> countRulesByProfileKey;
private final Map<String, Long> countOverridingRulesByProfileKey;
private final Map<String, Long> countInactiveRuleByProfileKey = new HashMap<>();

private Statistics(DbSession dbSession, List<QProfileDto> profiles) {
private Statistics(DbSession dbSession, List<QProfileDto> profiles, String language) {
ActiveRuleDao dao = dbClient.activeRuleDao();
ActiveRuleCountQuery.Builder builder = ActiveRuleCountQuery.builder();
countRulesByProfileKey = dao.countActiveRulesByQuery(dbSession, builder.setProfiles(profiles).build());
countOverridingRulesByProfileKey = dao.countActiveRulesByQuery(dbSession, builder.setProfiles(profiles).setInheritance(OVERRIDES).build());
long totalRuleAvailable = dbClient.ruleDao().countByLanguage(dbSession, language);
countRulesByProfileKey.forEach((profileKey, activeRules) -> countInactiveRuleByProfileKey.put(profileKey, totalRuleAvailable - activeRules));
}
}
}

+ 1
- 0
sonar-ws/src/main/protobuf/ws-qualityprofiles.proto View File

@@ -100,6 +100,7 @@ message InheritanceWsResponse {
optional int64 activeRuleCount = 4;
optional int64 overridingRuleCount = 5;
optional bool isBuiltIn = 6;
optional int64 inactiveRuleCount = 7;
}
}


Loading…
Cancel
Save