From 89071b4bdb0e13afa58588dbb46b370e01e1f0ad Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 18 Jun 2015 14:44:33 +0200 Subject: [PATCH] SONAR-6646 Remove CountUnresolvedIssuesDecorator from batch --- .../batch/bootstrap/BatchComponents.java | 2 - .../CountUnresolvedIssuesDecorator.java | 304 -------------- .../CountUnresolvedIssuesDecoratorTest.java | 372 ------------------ 3 files changed, 678 deletions(-) delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/compute/CountUnresolvedIssuesDecorator.java delete mode 100644 sonar-batch/src/test/java/org/sonar/batch/compute/CountUnresolvedIssuesDecoratorTest.java diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java index b80e89cdd2b..53041fab9e1 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java @@ -26,7 +26,6 @@ import org.sonar.batch.components.TimeMachineConfiguration; import org.sonar.batch.compute.BranchCoverageDecorator; import org.sonar.batch.compute.CommentDensityDecorator; import org.sonar.batch.compute.CountFalsePositivesDecorator; -import org.sonar.batch.compute.CountUnresolvedIssuesDecorator; import org.sonar.batch.compute.CoverageDecorator; import org.sonar.batch.compute.DirectoriesDecorator; import org.sonar.batch.compute.FilesDecorator; @@ -108,7 +107,6 @@ public class BatchComponents { InitialOpenIssuesSensor.class, // to be moved to compute engine - CountUnresolvedIssuesDecorator.class, CountFalsePositivesDecorator.class, UnitTestDecorator.class, LineCoverageDecorator.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/CountUnresolvedIssuesDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/compute/CountUnresolvedIssuesDecorator.java deleted file mode 100644 index dee397d05d4..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/compute/CountUnresolvedIssuesDecorator.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.batch.compute; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.HashMultiset; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Maps; -import com.google.common.collect.Multiset; -import com.google.common.collect.Sets; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.annotation.Nullable; -import org.apache.commons.lang.time.DateUtils; -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorBarriers; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.batch.RequiresDB; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.MeasuresFilters; -import org.sonar.api.measures.Metric; -import org.sonar.api.measures.RuleMeasure; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.ResourceUtils; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rules.RulePriority; -import org.sonar.batch.components.Period; -import org.sonar.batch.components.TimeMachineConfiguration; - -/** - * Computes metrics related to number of issues. - * - * @since 3.6 - */ -@DependsUpon(DecoratorBarriers.ISSUES_TRACKED) -@RequiresDB -public class CountUnresolvedIssuesDecorator implements Decorator { - - private final ResourcePerspectives perspectives; - private final TimeMachineConfiguration timeMachineConfiguration; - - public CountUnresolvedIssuesDecorator(ResourcePerspectives perspectives, TimeMachineConfiguration timeMachineConfiguration) { - this.perspectives = perspectives; - this.timeMachineConfiguration = timeMachineConfiguration; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependedUpon - public List generatesIssuesMetrics() { - return ImmutableList.of( - CoreMetrics.VIOLATIONS, - CoreMetrics.BLOCKER_VIOLATIONS, - CoreMetrics.CRITICAL_VIOLATIONS, - CoreMetrics.MAJOR_VIOLATIONS, - CoreMetrics.MINOR_VIOLATIONS, - CoreMetrics.INFO_VIOLATIONS, - CoreMetrics.NEW_VIOLATIONS, - CoreMetrics.NEW_BLOCKER_VIOLATIONS, - CoreMetrics.NEW_CRITICAL_VIOLATIONS, - CoreMetrics.NEW_MAJOR_VIOLATIONS, - CoreMetrics.NEW_MINOR_VIOLATIONS, - CoreMetrics.NEW_INFO_VIOLATIONS, - CoreMetrics.OPEN_ISSUES, - CoreMetrics.REOPENED_ISSUES, - CoreMetrics.CONFIRMED_ISSUES - ); - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - Issuable issuable = perspectives.as(Issuable.class, resource); - if (issuable != null) { - Collection issues = issuable.issues(); - boolean shouldSaveNewMetrics = shouldSaveNewMetrics(context); - - Multiset severityBag = HashMultiset.create(); - Map> rulesPerSeverity = Maps.newHashMap(); - ListMultimap issuesPerSeverity = ArrayListMultimap.create(); - int countOpen = 0; - int countReopened = 0; - int countConfirmed = 0; - - for (Issue issue : issues) { - severityBag.add(RulePriority.valueOf(issue.severity())); - Multiset rulesBag = initRules(rulesPerSeverity, RulePriority.valueOf(issue.severity())); - rulesBag.add(issue.ruleKey()); - issuesPerSeverity.put(RulePriority.valueOf(issue.severity()), issue); - - if (Issue.STATUS_OPEN.equals(issue.status())) { - countOpen++; - } else if (Issue.STATUS_REOPENED.equals(issue.status())) { - countReopened++; - } else if (Issue.STATUS_CONFIRMED.equals(issue.status())) { - countConfirmed++; - } - } - - for (RulePriority ruleSeverity : RulePriority.values()) { - saveIssuesForSeverity(context, ruleSeverity, severityBag); - saveIssuesPerRules(context, ruleSeverity, rulesPerSeverity); - saveNewIssuesForSeverity(context, ruleSeverity, issuesPerSeverity, shouldSaveNewMetrics); - saveNewIssuesPerRule(context, ruleSeverity, issues, shouldSaveNewMetrics); - } - - saveTotalIssues(context, issues); - saveNewIssues(context, issues, shouldSaveNewMetrics); - - saveMeasure(context, CoreMetrics.OPEN_ISSUES, countOpen); - saveMeasure(context, CoreMetrics.REOPENED_ISSUES, countReopened); - saveMeasure(context, CoreMetrics.CONFIRMED_ISSUES, countConfirmed); - } - } - - private static void saveTotalIssues(DecoratorContext context, Collection issues) { - if (context.getMeasure(CoreMetrics.VIOLATIONS) == null) { - Collection childrenIssues = context.getChildrenMeasures(CoreMetrics.VIOLATIONS); - Double sum = MeasureUtils.sum(true, childrenIssues); - context.saveMeasure(CoreMetrics.VIOLATIONS, sum + issues.size()); - } - } - - private void saveNewIssues(DecoratorContext context, Collection issues, boolean shouldSaveNewMetrics) { - if (shouldSaveNewMetrics) { - Measure measure = new Measure(CoreMetrics.NEW_VIOLATIONS); - saveNewIssues(context, measure, issues); - } - } - - private static void saveIssuesForSeverity(DecoratorContext context, RulePriority ruleSeverity, Multiset severitiesBag) { - Metric metric = SeverityUtils.severityToIssueMetric(ruleSeverity); - if (context.getMeasure(metric) == null) { - Collection children = context.getChildrenMeasures(MeasuresFilters.metric(metric)); - int sum = MeasureUtils.sum(true, children).intValue() + severitiesBag.count(ruleSeverity); - context.saveMeasure(metric, (double) sum); - } - } - - private void saveNewIssuesForSeverity(DecoratorContext context, RulePriority severity, ListMultimap issuesPerSeverities, boolean shouldSaveNewMetrics) { - if (shouldSaveNewMetrics) { - Metric metric = SeverityUtils.severityToNewMetricIssue(severity); - Measure measure = new Measure(metric); - saveNewIssues(context, measure, issuesPerSeverities.get(severity)); - } - } - - private static void saveIssuesPerRules(DecoratorContext context, RulePriority severity, Map> rulesPerSeverity) { - Metric metric = SeverityUtils.severityToIssueMetric(severity); - - Collection children = context.getChildrenMeasures(MeasuresFilters.rules(metric)); - for (Measure child : children) { - RuleMeasure childRuleMeasure = (RuleMeasure) child; - RuleKey ruleKey = childRuleMeasure.ruleKey(); - if (ruleKey != null && MeasureUtils.hasValue(childRuleMeasure)) { - Multiset rulesBag = initRules(rulesPerSeverity, severity); - rulesBag.add(ruleKey, childRuleMeasure.getIntValue()); - } - } - - Multiset rulesBag = rulesPerSeverity.get(severity); - if (rulesBag != null) { - for (Multiset.Entry entry : rulesBag.entrySet()) { - RuleMeasure measure = RuleMeasure.createForRule(metric, entry.getElement(), (double) entry.getCount()); - measure.setSeverity(severity); - context.saveMeasure(measure); - } - } - } - - private void saveNewIssuesPerRule(DecoratorContext context, RulePriority severity, Collection issues, boolean shouldSaveNewMetrics) { - if (shouldSaveNewMetrics) { - Metric metric = SeverityUtils.severityToNewMetricIssue(severity); - ListMultimap childMeasuresPerRuleKeys = ArrayListMultimap.create(); - ListMultimap issuesPerRuleKeys = ArrayListMultimap.create(); - Set ruleKeys = Sets.newHashSet(); - - Collection children = context.getChildrenMeasures(MeasuresFilters.rules(metric)); - for (Measure child : children) { - RuleMeasure childRuleMeasure = (RuleMeasure) child; - RuleKey ruleKey = childRuleMeasure.ruleKey(); - if (ruleKey != null) { - childMeasuresPerRuleKeys.put(ruleKey, childRuleMeasure); - ruleKeys.add(ruleKey); - } - } - - for (Issue issue : issues) { - if (RulePriority.valueOf(issue.severity()).equals(severity)) { - ruleKeys.add(issue.ruleKey()); - issuesPerRuleKeys.put(issue.ruleKey(), issue); - } - } - - for (RuleKey ruleKey : ruleKeys) { - RuleMeasure measure = RuleMeasure.createForRule(metric, ruleKey, null); - measure.setSeverity(severity); - for (Period period : timeMachineConfiguration.periods()) { - int variationIndex = period.getIndex(); - double sum = MeasureUtils.sumOnVariation(true, variationIndex, childMeasuresPerRuleKeys.get(ruleKey)) + countIssues(issuesPerRuleKeys.get(ruleKey), period); - measure.setVariation(variationIndex, sum); - } - context.saveMeasure(measure); - } - } - } - - private void saveNewIssues(DecoratorContext context, Measure measure, Collection issues) { - for (Period period : timeMachineConfiguration.periods()) { - int variationIndex = period.getIndex(); - Collection children = context.getChildrenMeasures(measure.getMetric()); - double sum = MeasureUtils.sumOnVariation(true, variationIndex, children) + countIssues(issues, period); - measure.setVariation(variationIndex, sum); - } - context.saveMeasure(measure); - } - - private static void saveMeasure(DecoratorContext context, Metric metric, int value) { - context.saveMeasure(metric, (double) (value + sumChildren(context, metric))); - } - - private static int sumChildren(DecoratorContext context, Metric metric) { - int sum = 0; - if (!ResourceUtils.isFile(context.getResource())) { - sum = MeasureUtils.sum(true, context.getChildrenMeasures(metric)).intValue(); - } - return sum; - } - - private static Multiset initRules(Map> rulesPerSeverity, RulePriority severity) { - Multiset rulesBag = rulesPerSeverity.get(severity); - if (rulesBag == null) { - rulesBag = HashMultiset.create(); - rulesPerSeverity.put(severity, rulesBag); - } - return rulesBag; - } - - private int countIssues(Collection issues, Period period) { - // SONAR-3647 Use real snapshot date and not target date in order to stay consistent with other measure variations - Date datePlusOneSecond = period.getDate() != null ? DateUtils.addSeconds(period.getDate(), 1) : null; - return countIssuesAfterDate(issues, datePlusOneSecond); - } - - @VisibleForTesting - int countIssuesAfterDate(Collection issues, @Nullable Date date) { - if (issues == null) { - return 0; - } - int count = 0; - for (Issue issue : issues) { - if (isAfter(issue, date)) { - count++; - } - } - return count; - } - - private static boolean isAfter(Issue issue, @Nullable Date date) { - return date == null || (issue.creationDate() != null && DateUtils.truncatedCompareTo(issue.creationDate(), date, Calendar.SECOND) > 0); - } - - private static boolean shouldSaveNewMetrics(DecoratorContext context) { - return context.getMeasure(CoreMetrics.NEW_VIOLATIONS) == null; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/compute/CountUnresolvedIssuesDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/compute/CountUnresolvedIssuesDecoratorTest.java deleted file mode 100644 index 19637289747..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/compute/CountUnresolvedIssuesDecoratorTest.java +++ /dev/null @@ -1,372 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.batch.compute; - -import com.google.common.collect.Lists; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.time.DateUtils; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentMatcher; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.MeasuresFilter; -import org.sonar.api.measures.Metric; -import org.sonar.api.measures.RuleMeasure; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.Scopes; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.Severity; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.test.IsRuleMeasure; -import org.sonar.batch.components.Period; -import org.sonar.batch.components.TimeMachineConfiguration; - -import static com.google.common.collect.Lists.newArrayList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyDouble; -import static org.mockito.Mockito.argThat; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class CountUnresolvedIssuesDecoratorTest { - - CountUnresolvedIssuesDecorator decorator; - TimeMachineConfiguration timeMachineConfiguration; - Issuable issuable; - DecoratorContext context; - Resource resource; - Project project; - Rule ruleA1; - Rule ruleA2; - Rule ruleB1; - Date rightNow; - Date tenDaysAgo; - Date afterTenDaysAgo; - Date fiveDaysAgo; - Date afterFiveDaysAgo; - Date sameSecond; - - @Before - public void before() { - ruleA1 = Rule.create().setRepositoryKey("ruleA1").setKey("ruleA1").setName("nameA1"); - ruleA2 = Rule.create().setRepositoryKey("ruleA2").setKey("ruleA2").setName("nameA2"); - ruleB1 = Rule.create().setRepositoryKey("ruleB1").setKey("ruleB1").setName("nameB1"); - - rightNow = new Date(); - tenDaysAgo = DateUtils.addDays(rightNow, -10); - afterTenDaysAgo = DateUtils.addDays(tenDaysAgo, 1); - fiveDaysAgo = DateUtils.addDays(rightNow, -5); - afterFiveDaysAgo = DateUtils.addDays(fiveDaysAgo, 1); - sameSecond = DateUtils.truncate(rightNow, Calendar.SECOND); - - timeMachineConfiguration = mock(TimeMachineConfiguration.class); - when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, afterFiveDaysAgo), new Period(2, afterTenDaysAgo))); - - project = mock(Project.class); - resource = mock(Resource.class); - context = mock(DecoratorContext.class); - when(context.getResource()).thenReturn(resource); - when(context.getProject()).thenReturn(project); - when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(null); - - issuable = mock(Issuable.class); - ResourcePerspectives perspectives = mock(ResourcePerspectives.class); - when(perspectives.as(Issuable.class, resource)).thenReturn(issuable); - decorator = new CountUnresolvedIssuesDecorator(perspectives, timeMachineConfiguration); - } - - @Test - public void should_be_depended_upon_metric() { - assertThat(decorator.generatesIssuesMetrics()).hasSize(15); - } - - @Test - public void should_count_issues() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(issuable.issues()).thenReturn(createIssues()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.VIOLATIONS, 4.0); - } - - @Test - public void should_do_nothing_when_issuable_is_null() { - ResourcePerspectives perspectives = mock(ResourcePerspectives.class); - when(perspectives.as(Issuable.class, resource)).thenReturn(null); - CountUnresolvedIssuesDecorator decorator = new CountUnresolvedIssuesDecorator(perspectives, timeMachineConfiguration); - - decorator.decorate(resource, context); - - verifyZeroInteractions(context); - } - - /** - * See http://jira.sonarsource.com/browse/SONAR-1729 - */ - @Test - public void should_not_count_issues_if_measure_already_exists() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(issuable.issues()).thenReturn(createIssues()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - when(context.getMeasure(CoreMetrics.VIOLATIONS)).thenReturn(new Measure(CoreMetrics.VIOLATIONS, 3000.0)); - when(context.getMeasure(CoreMetrics.MAJOR_VIOLATIONS)).thenReturn(new Measure(CoreMetrics.MAJOR_VIOLATIONS, 500.0)); - - decorator.decorate(resource, context); - - verify(context, never()).saveMeasure(eq(CoreMetrics.VIOLATIONS), anyDouble());// not changed - verify(context, never()).saveMeasure(eq(CoreMetrics.MAJOR_VIOLATIONS), anyDouble());// not changed - verify(context, times(1)).saveMeasure(eq(CoreMetrics.CRITICAL_VIOLATIONS), anyDouble());// did not exist - } - - @Test - public void should_save_zero_on_projects() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(issuable.issues()).thenReturn(Lists.newArrayList()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.VIOLATIONS, 0.0); - } - - @Test - public void should_save_zero_on_directories() { - when(resource.getScope()).thenReturn(Scopes.DIRECTORY); - when(issuable.issues()).thenReturn(Lists.newArrayList()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.VIOLATIONS, 0.0); - } - - @Test - public void should_count_issues_by_severity() { - when(resource.getScope()).thenReturn(Scopes.PROJECT); - when(issuable.issues()).thenReturn(createIssues()); - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.emptyList()); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.BLOCKER_VIOLATIONS, 0.0); - verify(context).saveMeasure(CoreMetrics.CRITICAL_VIOLATIONS, 2.0); - verify(context).saveMeasure(CoreMetrics.MAJOR_VIOLATIONS, 1.0); - verify(context).saveMeasure(CoreMetrics.MINOR_VIOLATIONS, 1.0); - verify(context).saveMeasure(CoreMetrics.INFO_VIOLATIONS, 0.0); - } - - @Test - public void should_count_issues_per_rule() { - List issues = newArrayList(); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); - issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name())); - when(issuable.issues()).thenReturn(issues); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0))); - verify(context, never()).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA1, 0.0))); - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA2, 1.0))); - } - - @Test - public void same_rule_should_have_different_severities() { - List issues = newArrayList(); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name())); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.MINOR.name())); - when(issuable.issues()).thenReturn(issues); - - decorator.decorate(resource, context); - - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0))); - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MINOR_VIOLATIONS, ruleA1, 1.0))); - } - - @Test - public void should_count_issues_after_date() { - List issues = createIssuesForNewMetrics(); - - assertThat(decorator.countIssuesAfterDate(null, fiveDaysAgo)).isEqualTo(0); - assertThat(decorator.countIssuesAfterDate(issues, fiveDaysAgo)).isEqualTo(1); // 1 rightNow - assertThat(decorator.countIssuesAfterDate(issues, tenDaysAgo)).isEqualTo(3); // 1 rightNow + 2 fiveDaysAgo - assertThat(decorator.countIssuesAfterDate(issues, sameSecond)).isEqualTo(0); // 0 - } - - @Test - public void should_clear_cache_after_execution() { - Issue issue1 = new DefaultIssue().setRuleKey(RuleKey.of(ruleA1.getRepositoryKey(), ruleA1.getKey())).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(rightNow); - Issue issue2 = new DefaultIssue().setRuleKey(RuleKey.of(ruleA2.getRepositoryKey(), ruleA2.getKey())).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(rightNow); - when(issuable.issues()).thenReturn(newArrayList(issue1)).thenReturn(newArrayList(issue2)); - - decorator.decorate(resource, context); - decorator.decorate(resource, context); - - verify(context, times(2)).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 1.0, 1.0))); - verify(context, never()).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 2.0, 2.0))); - } - - @Test - public void should_save_severity_new_issues() { - when(issuable.issues()).thenReturn(createIssuesForNewMetrics()); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_BLOCKER_VIOLATIONS, 0.0, 0.0))); - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, 1.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, 0.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, 0.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_INFO_VIOLATIONS, 0.0, 0.0))); - } - - @Test - public void should_save_rule_new_issues() { - when(issuable.issues()).thenReturn(createIssuesForNewMetrics()); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, ruleA1, 1.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, ruleA2, 0.0, 1.0))); - verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, ruleB1, 0.0, 1.0))); - } - - @Test - public void should_not_save_new_issues_if_measure_already_computed() { - when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(new Measure()); - when(issuable.issues()).thenReturn(createIssuesForNewMetrics()); - - decorator.decorate(resource, context); - - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_BLOCKER_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_INFO_VIOLATIONS))); - verify(context, never()).saveMeasure(argThat(new IsMetricMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS))); - } - - List createIssues() { - List issues = newArrayList(); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(Severity.CRITICAL).setStatus(Issue.STATUS_OPEN)); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(Severity.CRITICAL).setStatus(Issue.STATUS_REOPENED)); - issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(Severity.MAJOR).setStatus(Issue.STATUS_REOPENED)); - issues.add(new DefaultIssue().setRuleKey(ruleB1.ruleKey()).setSeverity(Severity.MINOR).setStatus(Issue.STATUS_OPEN)); - return issues; - } - - List createIssuesForNewMetrics() { - List issues = newArrayList(); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(rightNow).setStatus(Issue.STATUS_OPEN)); - issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()).setCreationDate(tenDaysAgo).setStatus(Issue.STATUS_OPEN)); - issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name()).setCreationDate(fiveDaysAgo).setStatus(Issue.STATUS_REOPENED)); - issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name()).setCreationDate(tenDaysAgo).setStatus(Issue.STATUS_REOPENED)); - issues.add(new DefaultIssue().setRuleKey(ruleB1.ruleKey()).setSeverity(RulePriority.MINOR.name()).setCreationDate(fiveDaysAgo).setStatus(Issue.STATUS_OPEN)); - issues.add(new DefaultIssue().setRuleKey(ruleB1.ruleKey()).setSeverity(RulePriority.MINOR.name()).setCreationDate(tenDaysAgo).setStatus(Issue.STATUS_OPEN)); - return issues; - } - - class IsVariationRuleMeasure extends ArgumentMatcher { - Metric metric = null; - Rule rule = null; - Double var1 = null; - Double var2 = null; - - public IsVariationRuleMeasure(Metric metric, Rule rule, Double var1, Double var2) { - this.metric = metric; - this.rule = rule; - this.var1 = var1; - this.var2 = var2; - } - - public boolean matches(Object o) { - if (!(o instanceof RuleMeasure)) { - return false; - } - RuleMeasure m = (RuleMeasure) o; - return ObjectUtils.equals(metric, m.getMetric()) && - ObjectUtils.equals(rule.ruleKey(), m.ruleKey()) && - ObjectUtils.equals(var1, m.getVariation1()) && - ObjectUtils.equals(var2, m.getVariation2()); - } - } - - class IsVariationMeasure extends ArgumentMatcher { - Metric metric = null; - Double var1 = null; - Double var2 = null; - - public IsVariationMeasure(Metric metric, Double var1, Double var2) { - this.metric = metric; - this.var1 = var1; - this.var2 = var2; - } - - public boolean matches(Object o) { - if (!(o instanceof Measure)) { - return false; - } - Measure m = (Measure) o; - return ObjectUtils.equals(metric, m.getMetric()) && - ObjectUtils.equals(var1, m.getVariation1()) && - ObjectUtils.equals(var2, m.getVariation2()) && - !(m instanceof RuleMeasure); - } - } - - class IsMetricMeasure extends ArgumentMatcher { - Metric metric = null; - - public IsMetricMeasure(Metric metric) { - this.metric = metric; - } - - public boolean matches(Object o) { - if (!(o instanceof Measure)) { - return false; - } - Measure m = (Measure) o; - return ObjectUtils.equals(metric, m.getMetric()); - } - } -} -- 2.39.5