From 4e19fe7ccd4c5ff5ca29fb0bdb831ed03942f441 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 10 May 2016 11:15:16 +0200 Subject: [PATCH] SONAR-7555 Add measures on number of won't fix issues --- .../src/test/java/it/dbCleaner/PurgeTest.java | 10 ++-- .../test/java/it/issue/IssueMeasureTest.java | 15 +++--- .../computation/issue/IssueCounter.java | 15 ++++-- .../computation/issue/IssueCounterTest.java | 46 +++++++++++++++++-- .../resources/org/sonar/l10n/core.properties | 3 ++ .../org/sonar/api/measures/CoreMetrics.java | 16 +++++++ 6 files changed, 85 insertions(+), 20 deletions(-) diff --git a/it/it-tests/src/test/java/it/dbCleaner/PurgeTest.java b/it/it-tests/src/test/java/it/dbCleaner/PurgeTest.java index 38b7c016c2fb..417344cd14fd 100644 --- a/it/it-tests/src/test/java/it/dbCleaner/PurgeTest.java +++ b/it/it-tests/src/test/java/it/dbCleaner/PurgeTest.java @@ -76,9 +76,9 @@ public void test_evolution_of_number_of_rows_when_scanning_two_times_the_same_pr collector.checkThat("Wrong number of files", count("projects where qualifier in ('FIL')"), equalTo(4)); collector.checkThat("Wrong number of unit test files", count("projects where qualifier in ('UTS')"), equalTo(0)); - int measuresOnTrk = 44; - int measuresOnBrc = 216; - int measuresOnDir = 137; + int measuresOnTrk = 45; + int measuresOnBrc = 222; + int measuresOnDir = 141; int measuresOnFil = 69; // count measures  @@ -105,8 +105,8 @@ public void test_evolution_of_number_of_rows_when_scanning_two_times_the_same_pr // must be a different date, else a single snapshot is kept per day scan(PROJECT_SAMPLE_PATH, DateFormatUtils.ISO_DATE_FORMAT.format(today)); - int newMeasuresOnTrk = 54; - int newMeasuresOnBrc = 280; + int newMeasuresOnTrk = 55; + int newMeasuresOnBrc = 286; int newMeasuresOnDir = 44; int newMeasuresOnFil = 0; diff --git a/it/it-tests/src/test/java/it/issue/IssueMeasureTest.java b/it/it-tests/src/test/java/it/issue/IssueMeasureTest.java index 016e2da5c455..507d88cc3493 100644 --- a/it/it-tests/src/test/java/it/issue/IssueMeasureTest.java +++ b/it/it-tests/src/test/java/it/issue/IssueMeasureTest.java @@ -64,6 +64,7 @@ public void issues_by_severity_measures() { /** * SONAR-4330 + * SONAR-7555 */ @Test public void issues_by_resolution_and_status_measures() { @@ -75,19 +76,21 @@ public void issues_by_resolution_and_status_measures() { List issues = searchIssuesByProject(SAMPLE_PROJECT_KEY); assertThat(issues).hasSize(17); - // 1 is a false-positive, 1 is confirmed, 1 is reopened, and the remaining ones stays open + // 1 is a false-positive, 1 is a won't fix, 1 is confirmed, 1 is reopened, and the remaining ones stays open adminIssueClient().doTransition(issues.get(0).key(), "falsepositive"); - adminIssueClient().doTransition(issues.get(1).key(), "confirm"); - adminIssueClient().doTransition(issues.get(2).key(), "resolve"); - adminIssueClient().doTransition(issues.get(2).key(), "reopen"); + adminIssueClient().doTransition(issues.get(1).key(), "wontfix"); + adminIssueClient().doTransition(issues.get(2).key(), "confirm"); + adminIssueClient().doTransition(issues.get(3).key(), "resolve"); + adminIssueClient().doTransition(issues.get(3).key(), "reopen"); // Re analyze the project to compute measures runProjectAnalysis(ORCHESTRATOR, "shared/xoo-sample"); Resource project = ORCHESTRATOR.getServer().getWsClient().find( - ResourceQuery.createForMetrics(SAMPLE_PROJECT_KEY, "false_positive_issues", "open_issues", "reopened_issues", "confirmed_issues")); + ResourceQuery.createForMetrics(SAMPLE_PROJECT_KEY, "false_positive_issues", "wont_fix_issues", "open_issues", "reopened_issues", "confirmed_issues")); assertThat(project.getMeasureIntValue("false_positive_issues")).isEqualTo(1); - assertThat(project.getMeasureIntValue("open_issues")).isEqualTo(14); + assertThat(project.getMeasureIntValue("wont_fix_issues")).isEqualTo(1); + assertThat(project.getMeasureIntValue("open_issues")).isEqualTo(13); assertThat(project.getMeasureIntValue("reopened_issues")).isEqualTo(1); assertThat(project.getMeasureIntValue("confirmed_issues")).isEqualTo(1); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java index 779dce7fcd26..fa95b9efc83c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java @@ -26,7 +26,6 @@ import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; -import org.sonar.api.issue.Issue; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.rules.RuleType; import org.sonar.core.issue.DefaultIssue; @@ -39,6 +38,8 @@ import org.sonar.server.computation.period.Period; import org.sonar.server.computation.period.PeriodsHolder; +import static org.sonar.api.issue.Issue.RESOLUTION_FALSE_POSITIVE; +import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX; import static org.sonar.api.issue.Issue.STATUS_CONFIRMED; import static org.sonar.api.issue.Issue.STATUS_OPEN; import static org.sonar.api.issue.Issue.STATUS_REOPENED; @@ -58,6 +59,7 @@ import static org.sonar.api.measures.CoreMetrics.OPEN_ISSUES_KEY; import static org.sonar.api.measures.CoreMetrics.REOPENED_ISSUES_KEY; import static org.sonar.api.measures.CoreMetrics.VIOLATIONS_KEY; +import static org.sonar.api.measures.CoreMetrics.WONT_FIX_ISSUES_KEY; import static org.sonar.api.rule.Severity.BLOCKER; import static org.sonar.api.rule.Severity.CRITICAL; import static org.sonar.api.rule.Severity.INFO; @@ -67,10 +69,8 @@ /** * For each component, computes the measures related to number of issues: * @@ -167,6 +167,7 @@ private void addMeasuresByStatus(Component component) { addMeasure(component, REOPENED_ISSUES_KEY, currentCounters.counter().reopened); addMeasure(component, CONFIRMED_ISSUES_KEY, currentCounters.counter().confirmed); addMeasure(component, FALSE_POSITIVE_ISSUES_KEY, currentCounters.counter().falsePositives); + addMeasure(component, WONT_FIX_ISSUES_KEY, currentCounters.counter().wontFix); } private void addMeasuresByType(Component component) { @@ -231,6 +232,7 @@ private static class Counter { private int reopened = 0; private int confirmed = 0; private int falsePositives = 0; + private int wontFix = 0; private final Multiset severityBag = HashMultiset.create(); private final EnumMultiset typeBag = EnumMultiset.create(RuleType.class); @@ -240,6 +242,7 @@ void add(Counter counter) { reopened += counter.reopened; confirmed += counter.confirmed; falsePositives += counter.falsePositives; + wontFix += counter.wontFix; severityBag.addAll(counter.severityBag); typeBag.addAll(counter.typeBag); } @@ -249,8 +252,10 @@ void add(DefaultIssue issue) { unresolved++; typeBag.add(issue.type()); severityBag.add(issue.severity()); - } else if (Issue.RESOLUTION_FALSE_POSITIVE.equals(issue.resolution())) { + } else if (RESOLUTION_FALSE_POSITIVE.equals(issue.resolution())) { falsePositives++; + } else if (RESOLUTION_WONT_FIX.equals(issue.resolution())) { + wontFix++; } switch (issue.status()) { case STATUS_OPEN: diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueCounterTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueCounterTest.java index a55dafba40a2..c23c67a60eee 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueCounterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueCounterTest.java @@ -43,6 +43,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.api.issue.Issue.RESOLUTION_FALSE_POSITIVE; import static org.sonar.api.issue.Issue.RESOLUTION_FIXED; +import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX; import static org.sonar.api.issue.Issue.STATUS_CLOSED; import static org.sonar.api.issue.Issue.STATUS_CONFIRMED; import static org.sonar.api.issue.Issue.STATUS_OPEN; @@ -63,6 +64,7 @@ import static org.sonar.api.measures.CoreMetrics.OPEN_ISSUES_KEY; import static org.sonar.api.measures.CoreMetrics.REOPENED_ISSUES_KEY; import static org.sonar.api.measures.CoreMetrics.VIOLATIONS_KEY; +import static org.sonar.api.measures.CoreMetrics.WONT_FIX_ISSUES_KEY; import static org.sonar.api.rule.Severity.BLOCKER; import static org.sonar.api.rule.Severity.CRITICAL; import static org.sonar.api.rule.Severity.MAJOR; @@ -92,6 +94,7 @@ public class IssueCounterTest { static final Metric NEW_MINOR_ISSUES_METRIC = new MetricImpl(14, NEW_MINOR_VIOLATIONS_KEY, NEW_MINOR_VIOLATIONS_KEY, INT); static final Metric NEW_INFO_ISSUES_METRIC = new MetricImpl(15, NEW_INFO_VIOLATIONS_KEY, NEW_INFO_VIOLATIONS_KEY, INT); static final Metric FALSE_POSITIVE_ISSUES_METRIC = new MetricImpl(16, FALSE_POSITIVE_ISSUES_KEY, FALSE_POSITIVE_ISSUES_KEY, INT); + static final Metric WONT_FIX_ISSUES_METRIC = new MetricImpl(23, WONT_FIX_ISSUES_KEY, WONT_FIX_ISSUES_KEY, INT); static final Metric CODE_SMELLS_METRIC = new MetricImpl(17, CoreMetrics.CODE_SMELLS_KEY, CoreMetrics.CODE_SMELLS_KEY, INT); static final Metric BUGS_METRIC = new MetricImpl(18, CoreMetrics.BUGS_KEY, CoreMetrics.BUGS_KEY, INT); static final Metric VULNERABILITIES_METRIC = new MetricImpl(19, CoreMetrics.VULNERABILITIES_KEY, CoreMetrics.VULNERABILITIES_KEY, INT); @@ -126,6 +129,7 @@ public class IssueCounterTest { .add(NEW_MINOR_ISSUES_METRIC) .add(NEW_INFO_ISSUES_METRIC) .add(FALSE_POSITIVE_ISSUES_METRIC) + .add(WONT_FIX_ISSUES_METRIC) .add(CODE_SMELLS_METRIC) .add(BUGS_METRIC) .add(VULNERABILITIES_METRIC) @@ -165,25 +169,59 @@ public void count_issues_by_status() { underTest.beforeComponent(PROJECT); underTest.afterComponent(PROJECT); - // count by status assertThat(measureRepository.getRawMeasure(FILE1, ISSUES_METRIC).get().getIntValue()).isEqualTo(1); assertThat(measureRepository.getRawMeasure(FILE1, OPEN_ISSUES_METRIC).get().getIntValue()).isEqualTo(1); - assertThat(measureRepository.getRawMeasure(FILE1, FALSE_POSITIVE_ISSUES_METRIC).get().getIntValue()).isEqualTo(1); assertThat(measureRepository.getRawMeasure(FILE1, CONFIRMED_ISSUES_METRIC).get().getIntValue()).isEqualTo(0); assertThat(measureRepository.getRawMeasure(FILE2, ISSUES_METRIC).get().getIntValue()).isEqualTo(2); assertThat(measureRepository.getRawMeasure(FILE2, OPEN_ISSUES_METRIC).get().getIntValue()).isEqualTo(0); - assertThat(measureRepository.getRawMeasure(FILE2, FALSE_POSITIVE_ISSUES_METRIC).get().getIntValue()).isEqualTo(0); assertThat(measureRepository.getRawMeasure(FILE2, CONFIRMED_ISSUES_METRIC).get().getIntValue()).isEqualTo(2); assertThat(measureRepository.getRawMeasure(FILE3, ISSUES_METRIC).get().getIntValue()).isEqualTo(0); assertThat(measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get().getIntValue()).isEqualTo(3); assertThat(measureRepository.getRawMeasure(PROJECT, OPEN_ISSUES_METRIC).get().getIntValue()).isEqualTo(1); - assertThat(measureRepository.getRawMeasure(PROJECT, FALSE_POSITIVE_ISSUES_METRIC).get().getIntValue()).isEqualTo(1); assertThat(measureRepository.getRawMeasure(PROJECT, CONFIRMED_ISSUES_METRIC).get().getIntValue()).isEqualTo(2); } + @Test + public void count_issues_by_resolution() { + periodsHolder.setPeriods(); + + // bottom-up traversal -> from files to project + underTest.beforeComponent(FILE1); + underTest.onIssue(FILE1, createIssue(null, STATUS_OPEN, BLOCKER)); + underTest.onIssue(FILE1, createIssue(RESOLUTION_FIXED, STATUS_CLOSED, MAJOR)); + underTest.onIssue(FILE1, createIssue(RESOLUTION_FALSE_POSITIVE, STATUS_RESOLVED, MAJOR)); + underTest.onIssue(FILE1, createIssue(RESOLUTION_WONT_FIX, STATUS_CLOSED, MAJOR)); + underTest.afterComponent(FILE1); + + underTest.beforeComponent(FILE2); + underTest.onIssue(FILE2, createIssue(null, STATUS_CONFIRMED, BLOCKER)); + underTest.onIssue(FILE2, createIssue(null, STATUS_CONFIRMED, MAJOR)); + underTest.onIssue(FILE2, createIssue(RESOLUTION_WONT_FIX, STATUS_CLOSED, MAJOR)); + underTest.afterComponent(FILE2); + + underTest.beforeComponent(FILE3); + underTest.afterComponent(FILE3); + + underTest.beforeComponent(PROJECT); + underTest.afterComponent(PROJECT); + + assertThat(measureRepository.getRawMeasure(FILE1, ISSUES_METRIC).get().getIntValue()).isEqualTo(1); + assertThat(measureRepository.getRawMeasure(FILE1, FALSE_POSITIVE_ISSUES_METRIC).get().getIntValue()).isEqualTo(1); + assertThat(measureRepository.getRawMeasure(FILE1, WONT_FIX_ISSUES_METRIC).get().getIntValue()).isEqualTo(1); + + assertThat(measureRepository.getRawMeasure(FILE2, ISSUES_METRIC).get().getIntValue()).isEqualTo(2); + assertThat(measureRepository.getRawMeasure(FILE2, FALSE_POSITIVE_ISSUES_METRIC).get().getIntValue()).isEqualTo(0); + assertThat(measureRepository.getRawMeasure(FILE2, WONT_FIX_ISSUES_METRIC).get().getIntValue()).isEqualTo(1); + + assertThat(measureRepository.getRawMeasure(FILE3, ISSUES_METRIC).get().getIntValue()).isEqualTo(0); + + assertThat(measureRepository.getRawMeasure(PROJECT, FALSE_POSITIVE_ISSUES_METRIC).get().getIntValue()).isEqualTo(1); + assertThat(measureRepository.getRawMeasure(PROJECT, WONT_FIX_ISSUES_METRIC).get().getIntValue()).isEqualTo(2); + } + @Test public void count_unresolved_issues_by_severity() { periodsHolder.setPeriods(); diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 45484d7f87ad..10a2e7214f0b 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2731,6 +2731,9 @@ metric.profile_version.description=Selected quality profile version metric.false_positive_issues.name=False Positive Issues metric.false_positive_issues.description=False positive issues +metric.wont_fix_issues.name=Won't Fix Issues +metric.wont_fix_issues.description=Won't fix issues + metric.open_issues.name=Open Issues metric.open_issues.description=Open issues diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java index e20b47360fbd..cd3b57d20f54 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java @@ -1538,6 +1538,22 @@ public final class CoreMetrics { .setOptimizedBestValue(true) .create(); + /** + * @since 5.6 + */ + public static final String WONT_FIX_ISSUES_KEY = "wont_fix_issues"; + + /** + * @since 5.6 + */ + public static final Metric WONT_FIX_ISSUES = new Metric.Builder(WONT_FIX_ISSUES_KEY, "Won't Fix Issues", Metric.ValueType.INT) + .setDescription("Won't fix issues") + .setDirection(Metric.DIRECTION_WORST) + .setDomain(DOMAIN_ISSUES) + .setBestValue(0.0) + .setOptimizedBestValue(true) + .create(); + /** * @since 3.6 */