From: Eric Giffon Date: Wed, 24 Jan 2024 15:11:02 +0000 (+0100) Subject: SONAR-21455 Compute high_impact_accepted_issues with impacts query X-Git-Tag: 10.4.0.87286~60 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ad8e3304ea05510914b268ce24875c59436c46e1;p=sonarqube.git SONAR-21455 Compute high_impact_accepted_issues with impacts query --- diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/issue/IssueDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/issue/IssueDaoIT.java index f32cd93dca0..4ae47c90d5c 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/issue/IssueDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/issue/IssueDaoIT.java @@ -466,22 +466,17 @@ public class IssueDaoIT { ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); RuleDto rule = db.rules().insert(); db.issues().insert(rule, project, file, - i -> i.setStatus("RESOLVED").setResolution("FALSE-POSITIVE").setSeverity("MAJOR").setType(RuleType.BUG).setIssueCreationTime(1_500L) - .replaceAllImpacts(List.of(createImpact(SECURITY, HIGH), createImpact(MAINTAINABILITY, LOW)))); + i -> i.setStatus("RESOLVED").setResolution("FALSE-POSITIVE").setSeverity("MAJOR").setType(RuleType.BUG).setIssueCreationTime(1_500L)); db.issues().insert(rule, project, file, - i -> i.setStatus("OPEN").setResolution(null).setSeverity("CRITICAL").setType(RuleType.BUG).setIssueCreationTime(1_600L) - .replaceAllImpacts(List.of(createImpact(SECURITY, HIGH), createImpact(MAINTAINABILITY, HIGH)))); + i -> i.setStatus("OPEN").setResolution(null).setSeverity("CRITICAL").setType(RuleType.BUG).setIssueCreationTime(1_600L)); IssueDto criticalBug2 = db.issues().insert(rule, project, file, - i -> i.setStatus("OPEN").setResolution(null).setSeverity("CRITICAL").setType(RuleType.BUG).setIssueCreationTime(1_700L) - .replaceAllImpacts(List.of(createImpact(SECURITY, MEDIUM), createImpact(MAINTAINABILITY, LOW)))); + i -> i.setStatus("OPEN").setResolution(null).setSeverity("CRITICAL").setType(RuleType.BUG).setIssueCreationTime(1_700L)); // closed issues are ignored db.issues().insert(rule, project, file, - i -> i.setStatus("CLOSED").setResolution("REMOVED").setSeverity("CRITICAL").setType(RuleType.BUG).setIssueCreationTime(1_700L) - .replaceAllImpacts(List.of(createImpact(SECURITY, HIGH)))); + i -> i.setStatus("CLOSED").setResolution("REMOVED").setSeverity("CRITICAL").setType(RuleType.BUG).setIssueCreationTime(1_700L)); Collection result = underTest.selectIssueGroupsByComponent(db.getSession(), file, 1_000L); - assertThat(result).hasSize(3); assertThat(result.stream().mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(3); assertThat(result.stream().filter(g -> g.getRuleType() == RuleType.BUG.getDbConstant()).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(3); @@ -491,7 +486,6 @@ public class IssueDaoIT { assertThat(result.stream().filter(g -> g.getSeverity().equals("CRITICAL")).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(2); assertThat(result.stream().filter(g -> g.getSeverity().equals("MAJOR")).mapToLong(IssueGroupDto::getCount).sum()).isOne(); assertThat(result.stream().filter(g -> g.getSeverity().equals("MINOR")).mapToLong(IssueGroupDto::getCount).sum()).isZero(); - assertThat(result.stream().filter(IssueGroupDto::hasHighImpactSeverity).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(2); assertThat(result.stream().filter(g -> g.getStatus().equals("OPEN")).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(2); assertThat(result.stream().filter(g -> g.getStatus().equals("RESOLVED")).mapToLong(IssueGroupDto::getCount).sum()).isOne(); @@ -514,11 +508,6 @@ public class IssueDaoIT { assertThat(result.stream().filter(g -> !g.isInLeak()).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(3); } - @NotNull - private static ImpactDto createImpact(SoftwareQuality softwareQuality, Severity high) { - return new ImpactDto().setUuid(UuidFactoryFast.getInstance().create()).setSoftwareQuality(softwareQuality).setSeverity(high); - } - @Test public void selectGroupsOfComponentTreeOnLeak_on_file_new_code_reference_branch() { ComponentDto project = db.components().insertPublicProject().getMainBranchComponent(); @@ -526,8 +515,6 @@ public class IssueDaoIT { RuleDto rule = db.rules().insert(); IssueDto fpBug = db.issues().insert(rule, project, file, i -> i.setStatus("RESOLVED").setResolution("FALSE-POSITIVE").setSeverity("MAJOR").setType(RuleType.BUG)); - IssueDto acceptedBug = db.issues().insert(rule, project, file, - i -> i.setStatus("RESOLVED").setResolution("WONTFIX").setSeverity("MAJOR").setType(RuleType.BUG)); IssueDto criticalBug1 = db.issues().insert(rule, project, file, i -> i.setStatus("OPEN").setResolution(null).setSeverity("CRITICAL").setType(RuleType.BUG)); IssueDto criticalBug2 = db.issues().insert(rule, project, file, @@ -538,31 +525,29 @@ public class IssueDaoIT { // two issues part of new code period on reference branch db.issues().insertNewCodeReferenceIssue(fpBug); - db.issues().insertNewCodeReferenceIssue(acceptedBug); db.issues().insertNewCodeReferenceIssue(criticalBug1); db.issues().insertNewCodeReferenceIssue(criticalBug2); Collection result = underTest.selectIssueGroupsByComponent(db.getSession(), file, -1); - assertThat(result.stream().mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(5); + assertThat(result.stream().mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(4); - assertThat(result.stream().filter(g -> g.getRuleType() == RuleType.BUG.getDbConstant()).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(5); + assertThat(result.stream().filter(g -> g.getRuleType() == RuleType.BUG.getDbConstant()).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(4); assertThat(result.stream().filter(g -> g.getRuleType() == RuleType.CODE_SMELL.getDbConstant()).mapToLong(IssueGroupDto::getCount).sum()).isZero(); assertThat(result.stream().filter(g -> g.getRuleType() == RuleType.VULNERABILITY.getDbConstant()).mapToLong(IssueGroupDto::getCount).sum()).isZero(); assertThat(result.stream().filter(g -> g.getSeverity().equals("CRITICAL")).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(3); - assertThat(result.stream().filter(g -> g.getSeverity().equals("MAJOR")).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(2); + assertThat(result.stream().filter(g -> g.getSeverity().equals("MAJOR")).mapToLong(IssueGroupDto::getCount).sum()).isOne(); assertThat(result.stream().filter(g -> g.getSeverity().equals("MINOR")).mapToLong(IssueGroupDto::getCount).sum()).isZero(); assertThat(result.stream().filter(g -> g.getStatus().equals("OPEN")).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(3); - assertThat(result.stream().filter(g -> g.getStatus().equals("RESOLVED")).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(2); + assertThat(result.stream().filter(g -> g.getStatus().equals("RESOLVED")).mapToLong(IssueGroupDto::getCount).sum()).isOne(); assertThat(result.stream().filter(g -> g.getStatus().equals("CLOSED")).mapToLong(IssueGroupDto::getCount).sum()).isZero(); assertThat(result.stream().filter(g -> "FALSE-POSITIVE".equals(g.getResolution())).mapToLong(IssueGroupDto::getCount).sum()).isOne(); - assertThat(result.stream().filter(g -> "WONTFIX".equals(g.getResolution())).mapToLong(IssueGroupDto::getCount).sum()).isOne(); assertThat(result.stream().filter(g -> g.getResolution() == null).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(3); - assertThat(result.stream().filter(IssueGroupDto::isInLeak).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(4); + assertThat(result.stream().filter(IssueGroupDto::isInLeak).mapToLong(IssueGroupDto::getCount).sum()).isEqualTo(3); assertThat(result.stream().filter(g -> !g.isInLeak()).mapToLong(IssueGroupDto::getCount).sum()).isOne(); } @@ -572,26 +557,46 @@ public class IssueDaoIT { ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); RuleDto rule = db.rules().insert(); db.issues().insert(rule, project, file, - i -> i.replaceAllImpacts(List.of(createImpact(SECURITY, HIGH), createImpact(MAINTAINABILITY, LOW)))); + i -> i.setStatus(STATUS_OPEN).replaceAllImpacts(List.of(createImpact(SECURITY, HIGH), createImpact(MAINTAINABILITY, LOW)))); db.issues().insert(rule, project, file, - i -> i.replaceAllImpacts(List.of(createImpact(SECURITY, HIGH), createImpact(MAINTAINABILITY, HIGH)))); + i -> i.setStatus(STATUS_OPEN).replaceAllImpacts(List.of(createImpact(SECURITY, HIGH), createImpact(MAINTAINABILITY, HIGH)))); db.issues().insert(rule, project, file, - i -> i.replaceAllImpacts(List.of(createImpact(SECURITY, HIGH)))); - // closed issues are ignored + i -> i.setStatus(STATUS_REOPENED).replaceAllImpacts(List.of(createImpact(SECURITY, HIGH)))); + db.issues().insert(rule, project, file, + i -> i.setStatus(STATUS_RESOLVED).setResolution(RESOLUTION_WONT_FIX).replaceAllImpacts(List.of(createImpact(SECURITY, HIGH)))); + // issues in ignored status db.issues().insert(rule, project, file, i -> i.setStatus(Issue.STATUS_CLOSED).replaceAllImpacts(List.of(createImpact(SECURITY, HIGH)))); + db.issues().insert(rule, project, file, + i -> i.setStatus(STATUS_RESOLVED).setResolution(RESOLUTION_FALSE_POSITIVE).replaceAllImpacts(List.of(createImpact(SECURITY, HIGH)))); Collection result = underTest.selectIssueImpactGroupsByComponent(db.getSession(), file); - assertThat(result).hasSize(3); - assertThat(result.stream().mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(5); + assertThat(result).hasSize(5); + assertThat(result.stream().mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(6); + + assertThat(result.stream().filter(g -> g.getSoftwareQuality() == SECURITY).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(4); + assertThat(result.stream().filter(g -> g.getSoftwareQuality() == MAINTAINABILITY).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(2); + + assertThat(result.stream().filter(g -> g.getSeverity() == HIGH).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(5); + assertThat(result.stream().filter(g -> g.getSeverity() == LOW).mapToLong(IssueImpactGroupDto::getCount).sum()).isOne(); + + assertThat(result.stream().filter(g -> STATUS_OPEN.equals(g.getStatus())).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(4); + assertThat(result.stream().filter(g -> STATUS_REOPENED.equals(g.getStatus())).mapToLong(IssueImpactGroupDto::getCount).sum()).isOne(); + assertThat(result.stream().filter(g -> STATUS_RESOLVED.equals(g.getStatus())).mapToLong(IssueImpactGroupDto::getCount).sum()).isOne(); + + assertThat(result.stream().filter(g -> RESOLUTION_WONT_FIX.equals(g.getResolution())).mapToLong(IssueImpactGroupDto::getCount).sum()).isOne(); + assertThat(result.stream().filter(g -> g.getResolution() == null).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(5); - assertThat(result.stream().filter(g -> MAINTAINABILITY == g.getSoftwareQuality()).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(2); - assertThat(result.stream().filter(g -> SECURITY == g.getSoftwareQuality()).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(3); - assertThat(result.stream().filter(g -> SECURITY == g.getSoftwareQuality() && HIGH == g.getSeverity()).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(3); - assertThat(result.stream().filter(g -> HIGH == g.getSeverity()).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(4); - assertThat(result.stream().filter(g -> LOW == g.getSeverity()).mapToLong(IssueImpactGroupDto::getCount).sum()).isEqualTo(1); + assertThat(result.stream().noneMatch(g -> STATUS_CLOSED.equals(g.getResolution()))).isTrue(); + assertThat(result.stream().noneMatch(g -> RESOLUTION_FALSE_POSITIVE.equals(g.getResolution()))).isTrue(); assertThat(result.stream().noneMatch(g -> RELIABILITY == g.getSoftwareQuality())).isTrue(); + assertThat(result.stream().noneMatch(g -> MEDIUM == g.getSeverity())).isTrue(); + } + + @NotNull + private static ImpactDto createImpact(SoftwareQuality softwareQuality, Severity high) { + return new ImpactDto().setUuid(UuidFactoryFast.getInstance().create()).setSoftwareQuality(softwareQuality).setSeverity(high); } @Test diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueGroupDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueGroupDto.java index 618a33187ff..735711d2983 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueGroupDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueGroupDto.java @@ -25,7 +25,6 @@ import javax.annotation.Nullable; public class IssueGroupDto { private int ruleType; private String severity; - private boolean hasHighImpactSeverity; @Nullable private String resolution; private String status; @@ -45,10 +44,6 @@ public class IssueGroupDto { return severity; } - public boolean hasHighImpactSeverity() { - return hasHighImpactSeverity; - } - @CheckForNull public String getResolution() { return resolution; @@ -80,11 +75,6 @@ public class IssueGroupDto { return this; } - public IssueGroupDto setHasHighImpactSeverity(boolean hasHighImpactSeverity) { - this.hasHighImpactSeverity = hasHighImpactSeverity; - return this; - } - public IssueGroupDto setResolution(@Nullable String resolution) { this.resolution = resolution; return this; diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueImpactGroupDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueImpactGroupDto.java index 28e8a8451c6..9455e3a66ec 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueImpactGroupDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueImpactGroupDto.java @@ -19,11 +19,15 @@ */ package org.sonar.db.issue; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import org.sonar.api.issue.impact.Severity; import org.sonar.api.issue.impact.SoftwareQuality; public class IssueImpactGroupDto { + private String status; + private String resolution; private SoftwareQuality softwareQuality; private Severity severity; private long count; @@ -32,6 +36,23 @@ public class IssueImpactGroupDto { // nothing to do } + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + @CheckForNull + public String getResolution() { + return resolution; + } + + public void setResolution(@Nullable String resolution) { + this.resolution = resolution; + } + public SoftwareQuality getSoftwareQuality() { return softwareQuality; } diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml index ae88f48bff8..31f459370f3 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml @@ -458,11 +458,9 @@ - - with high_impact_severity_issues as ( - select distinct kee - from issues i - inner join issues_impacts ii on ii.issue_key = i.kee - where i.status <> 'CLOSED' - and i.component_uuid = #{component.uuid,jdbcType=VARCHAR} - and ii.severity = 'HIGH' - ) - - @@ -501,11 +488,9 @@ - select i2.issue_type as ruleType, i2.severity as severity, - i2.hasHighImpactSeverity as hasHighImpactSeverity, i2.resolution as resolution, i2.status as status, sum(i2.effort) as effort, @@ -515,7 +500,6 @@ select i.issue_type, i.severity, - case when exists(select 1 from high_impact_severity_issues hisi where hisi.kee = i.kee) then 1 else 0 end as hasHighImpactSeverity, i.resolution, i.status, i.effort, @@ -532,21 +516,22 @@ where i.status <> 'CLOSED' and i.component_uuid = #{component.uuid,jdbcType=VARCHAR} ) i2 - group by i2.issue_type, i2.severity, i2.hasHighImpactSeverity, i2.resolution, i2.status, i2.inLeak + group by i2.issue_type, i2.severity, i2.resolution, i2.status, i2.inLeak