From 6381e5a67c6363e66d1ef7b4d6d5ed6919894d87 Mon Sep 17 00:00:00 2001 From: Eric Giffon Date: Wed, 24 Jan 2024 14:01:34 +0100 Subject: [PATCH] SONAR-21455 Live update of impact measures --- .../java/org/sonar/db/issue/IssueDaoIT.java | 39 ++++++ .../java/org/sonar/db/issue/IssueDao.java | 4 + .../sonar/db/issue/IssueImpactGroupDto.java | 58 +++++++++ .../java/org/sonar/db/issue/IssueMapper.java | 2 + .../org/sonar/db/issue/IssueMapper.xml | 14 ++ .../server/measure/live/IssueCounter.java | 50 ++++++- .../live/LiveMeasureTreeUpdaterImpl.java | 18 ++- .../measure/live/MeasureUpdateFormula.java | 4 + .../live/MeasureUpdateFormulaFactoryImpl.java | 42 ++++++ .../MeasureUpdateFormulaFactoryImplTest.java | 123 ++++++++++++++++-- 10 files changed, 340 insertions(+), 14 deletions(-) create mode 100644 server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueImpactGroupDto.java 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 7ae2f4eb5fa..f32cd93dca0 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 @@ -34,6 +34,7 @@ import org.jetbrains.annotations.NotNull; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.sonar.api.issue.Issue; import org.sonar.api.issue.impact.Severity; import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.api.rule.RuleKey; @@ -565,6 +566,44 @@ public class IssueDaoIT { assertThat(result.stream().filter(g -> !g.isInLeak()).mapToLong(IssueGroupDto::getCount).sum()).isOne(); } + @Test + public void selectIssueImpactGroupsByComponent_shouldReturnImpactGroups() { + ComponentDto project = db.components().insertPublicProject().getMainBranchComponent(); + 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)))); + db.issues().insert(rule, project, file, + i -> i.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 + db.issues().insert(rule, project, file, + i -> i.setStatus(Issue.STATUS_CLOSED).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.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 -> RELIABILITY == g.getSoftwareQuality())).isTrue(); + } + + @Test + public void selectIssueImpactGroupsByComponent_whenComponentWithNoIssues_shouldReturnEmpty() { + ComponentDto project = db.components().insertPublicProject().getMainBranchComponent(); + ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); + + Collection groups = underTest.selectIssueImpactGroupsByComponent(db.getSession(), file); + + assertThat(groups).isEmpty(); + } + @Test public void selectByKey_givenOneIssueNewOnReferenceBranch_selectOneIssueWithNewOnReferenceBranch() { underTest.insert(db.getSession(), newIssueDto(ISSUE_KEY1) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDao.java index 8d3a9454bbd..d4708ab2fbd 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDao.java @@ -90,6 +90,10 @@ public class IssueDao implements Dao { return mapper(dbSession).selectIssueGroupsByComponent(component, leakPeriodBeginningDate); } + public Collection selectIssueImpactGroupsByComponent(DbSession dbSession, ComponentDto component) { + return mapper(dbSession).selectIssueImpactGroupsByComponent(component); + } + public Cursor scrollIssuesForIndexation(DbSession dbSession, @Nullable @Param("branchUuid") String branchUuid, @Nullable @Param("issueKeys") Collection issueKeys) { return mapper(dbSession).scrollIssuesForIndexation(branchUuid, issueKeys); 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 new file mode 100644 index 00000000000..28e8a8451c6 --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueImpactGroupDto.java @@ -0,0 +1,58 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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.db.issue; + +import org.sonar.api.issue.impact.Severity; +import org.sonar.api.issue.impact.SoftwareQuality; + +public class IssueImpactGroupDto { + + private SoftwareQuality softwareQuality; + private Severity severity; + private long count; + + public IssueImpactGroupDto() { + // nothing to do + } + + public SoftwareQuality getSoftwareQuality() { + return softwareQuality; + } + + public void setSoftwareQuality(SoftwareQuality softwareQuality) { + this.softwareQuality = softwareQuality; + } + + public Severity getSeverity() { + return severity; + } + + public void setSeverity(Severity severity) { + this.severity = severity; + } + + public long getCount() { + return count; + } + + public void setCount(long count) { + this.count = count; + } +} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java index c2cec03fd74..21f43b1773f 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueMapper.java @@ -74,6 +74,8 @@ public interface IssueMapper { Collection selectIssueGroupsByComponent(@Param("component") ComponentDto component, @Param("leakPeriodBeginningDate") long leakPeriodBeginningDate); + Collection selectIssueImpactGroupsByComponent(@Param("component") ComponentDto component); + List selectByBranch(@Param("keys") Set keys, @Nullable @Param("changedSince") Long changedSince); List selectRecentlyClosedIssues(@Param("queryParams") IssueQueryParams issueQueryParams); 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 7a1773cb4d3..ae88f48bff8 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 @@ -535,6 +535,20 @@ group by i2.issue_type, i2.severity, i2.hasHighImpactSeverity, i2.resolution, i2.status, i2.inLeak + +