]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-21455 Compute high_impact_accepted_issues with impacts query
authorEric Giffon <eric.giffon@sonarsource.com>
Wed, 24 Jan 2024 15:11:02 +0000 (16:11 +0100)
committersonartech <sonartech@sonarsource.com>
Wed, 31 Jan 2024 20:03:36 +0000 (20:03 +0000)
server/sonar-db-dao/src/it/java/org/sonar/db/issue/IssueDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueGroupDto.java
server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueImpactGroupDto.java
server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml
server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueCounter.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/MeasureUpdateFormulaFactoryImplTest.java

index f32cd93dca0fde62829c99a42692eed119c3eb45..4ae47c90d5c8aa07ef75062135193a0a1534ffe6 100644 (file)
@@ -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<IssueGroupDto> 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<IssueGroupDto> 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<IssueImpactGroupDto> 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
index 618a33187ffeb6d2c3a26eb8cab2533b63b61c4e..735711d2983f6f38cdef26284f68d1355330e598 100644 (file)
@@ -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;
index 28e8a8451c6515182b862060992b4722cbf26a93..9455e3a66ec8f2859e1885e901afbac870e08c57 100644 (file)
  */
 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;
   }
index ae88f48bff89207c5a39c69dd7b2dd96440718b8..31f459370f33dcd36c677e94cf341c14e55d2af2 100644 (file)
   </select>
 
   <select id="selectIssueGroupsByComponent" resultType="org.sonar.db.issue.IssueGroupDto" parameterType="map">
-    <include refid="withHighImpactSeverityIssues"/>
     select
       i.issue_type as ruleType,
       i.severity as severity,
-      exists(select 1 from high_impact_severity_issues hisi where hisi.kee = i.kee) as hasHighImpactSeverity,
       i.resolution as resolution,
       i.status as status, sum(i.effort) as effort,
       count(i.issue_type) as "count",
     </if>
     where i.status &lt;&gt; 'CLOSED'
     and i.component_uuid = #{component.uuid,jdbcType=VARCHAR}
-    group by i.issue_type, i.severity, hasHighImpactSeverity, i.resolution, i.status, inLeak
+    group by i.issue_type, i.severity, i.resolution, i.status, inLeak
   </select>
 
-  <sql id="withHighImpactSeverityIssues">
-    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 &lt;&gt; 'CLOSED'
-      and i.component_uuid = #{component.uuid,jdbcType=VARCHAR}
-      and ii.severity = 'HIGH'
-    )
-  </sql>
-
   <select id="selectIssueGroupsByComponent" resultType="org.sonar.db.issue.IssueGroupDto" parameterType="map" databaseId="oracle">
     <include refid="selectIssueGroupsByComponentVendorSpecific"/>
   </select>
   </select>
 
   <sql id="selectIssueGroupsByComponentVendorSpecific">
-    <include refid="withHighImpactSeverityIssues"/>
     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,
       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,
       where i.status &lt;&gt; '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
   </sql>
 
   <select id="selectIssueImpactGroupsByComponent" resultType="org.sonar.db.issue.IssueImpactGroupDto" parameterType="map">
     select
+    i.status as status,
+    i.resolution as resolution,
     ii.software_quality as softwareQuality,
     ii.severity as severity,
     count(i.kee) as "count"
     from issues i
-    left join issues_impacts ii on i.kee = ii.issue_key
-    where 1=1
-    and i.status in ('OPEN', 'REOPENED', 'CONFIRMED')
-    and i.issue_type != 4
+    inner join issues_impacts ii on i.kee = ii.issue_key
+    where i.status &lt;&gt; 'CLOSED'
+    and (i.resolution is null or i.resolution = 'WONTFIX')
     and i.component_uuid = #{component.uuid,jdbcType=VARCHAR}
-    group by ii.software_quality, ii.severity
+    group by i.status, i.resolution, ii.software_quality, ii.severity
   </select>
 
   <select id="selectIssueKeysByComponentUuid" parameterType="string" resultType="string">
index f3343ccacfe9427cd8f243d65fa5d9e8491b7842..34f6f1520aa84fd90fec4b232ace0cfc49313575 100644 (file)
@@ -98,9 +98,6 @@ class IssueCounter {
       byResolution
         .computeIfAbsent(group.getResolution(), k -> new Count())
         .add(group);
-      if (IssueStatus.ACCEPTED.equals(IssueStatus.of(group.getStatus(), group.getResolution())) && group.hasHighImpactSeverity()) {
-        highImpactAccepted.add(group);
-      }
     }
     if (group.getStatus() != null) {
       byStatus
@@ -110,12 +107,18 @@ class IssueCounter {
   }
 
   private void processImpactGroup(IssueImpactGroupDto group) {
-    if (group.getSoftwareQuality() != null && group.getSeverity() != null) {
+    IssueStatus issueStatus = IssueStatus.of(group.getStatus(), group.getResolution());
+
+    if (IssueStatus.OPEN == issueStatus || IssueStatus.CONFIRMED == issueStatus) {
       bySoftwareQualityAndSeverity
         .computeIfAbsent(group.getSoftwareQuality(), k -> new EnumMap<>(Severity.class))
         .computeIfAbsent(group.getSeverity(), k -> new Count())
         .add(group);
     }
+
+    if (Severity.HIGH == group.getSeverity() && IssueStatus.ACCEPTED == issueStatus) {
+      highImpactAccepted.add(group);
+    }
   }
 
   public Optional<String> getHighestSeverityOfUnresolved(RuleType ruleType, boolean onlyInLeak) {
index 7eb37a04a37109754b7e05c6eb30d0a781179cd0..b8e35b8882b970f952d4848a1b458ea75eb89b81 100644 (file)
@@ -332,29 +332,6 @@ public class MeasureUpdateFormulaFactoryImplTest {
       .assertThatValueIs(CoreMetrics.REOPENED_ISSUES, 7);
   }
 
-  @Test
-  public void test_high_impact_accepted_issues() {
-    withNoIssues()
-      .assertThatValueIs(CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES, 0);
-
-    with(
-      newGroup(RuleType.CODE_SMELL).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE)
-        .setHasHighImpactSeverity(true).setCount(3),
-      newGroup(RuleType.CODE_SMELL).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX)
-        .setHasHighImpactSeverity(true).setCount(4),
-      newGroup(RuleType.CODE_SMELL).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX)
-        .setHasHighImpactSeverity(false).setCount(5),
-      newGroup(RuleType.BUG).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE)
-        .setHasHighImpactSeverity(true).setCount(30),
-      newGroup(RuleType.BUG).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX)
-        .setHasHighImpactSeverity(true).setCount(40),
-      newGroup(RuleType.BUG).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX)
-        .setHasHighImpactSeverity(false).setCount(50),
-      // exclude security hotspot
-      newGroup(RuleType.SECURITY_HOTSPOT).setResolution(Issue.RESOLUTION_WONT_FIX).setHasHighImpactSeverity(true).setCount(40))
-      .assertThatValueIs(CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES, 4 + 40);
-  }
-
   @Test
   public void test_technical_debt() {
     withNoIssues().assertThatValueIs(CoreMetrics.TECHNICAL_DEBT, 0);
@@ -931,6 +908,24 @@ public class MeasureUpdateFormulaFactoryImplTest {
       .assertThatLeakValueIs(CoreMetrics.NEW_MAINTAINABILITY_RATING, Rating.A);
   }
 
+  @Test
+  public void compute_shouldComputeHighImpactAcceptedIssues() {
+    withNoIssues()
+      .assertThatValueIs(CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES, 0);
+
+    with(
+      newImpactGroup(RELIABILITY, HIGH, 3),
+      newImpactGroup(RELIABILITY, MEDIUM, 4),
+      newImpactGroup(RELIABILITY, LOW, 1),
+      newImpactGroup(SECURITY, HIGH, 3),
+      newImpactGroup(SECURITY, HIGH, Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX, 4),
+      newImpactGroup(SECURITY, MEDIUM, Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX, 5),
+      newImpactGroup(SECURITY, LOW, Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX, 6),
+      newImpactGroup(SECURITY, HIGH, Issue.STATUS_RESOLVED, Issue.RESOLUTION_FALSE_POSITIVE, 7),
+      newImpactGroup(RELIABILITY, HIGH, Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX, 8))
+      .assertThatValueIs(CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES, 4 + 8);
+  }
+
   @Test
   public void computeHierarchy_shouldComputeImpactMeasures() {
     new HierarchyTester(CoreMetrics.RELIABILITY_ISSUES)
@@ -1086,14 +1081,21 @@ public class MeasureUpdateFormulaFactoryImplTest {
     return dto;
   }
 
-  private static IssueImpactGroupDto newImpactGroup(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity, long count) {
+  private static IssueImpactGroupDto newImpactGroup(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity,
+                                                    String status, @Nullable String resolution, long count) {
     IssueImpactGroupDto dto = new IssueImpactGroupDto();
     dto.setSoftwareQuality(softwareQuality);
     dto.setSeverity(severity);
+    dto.setStatus(status);
+    dto.setResolution(resolution);
     dto.setCount(count);
     return dto;
   }
 
+  private static IssueImpactGroupDto newImpactGroup(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity, long count) {
+    return newImpactGroup(softwareQuality, severity, Issue.STATUS_OPEN, null, count);
+  }
+
   private static IssueGroupDto newResolvedGroup(RuleType ruleType) {
     return newGroup(ruleType).setResolution(Issue.RESOLUTION_FALSE_POSITIVE).setStatus(Issue.STATUS_CLOSED);
   }