]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6646 Remove CountUnresolvedIssuesDecorator from batch
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 18 Jun 2015 12:44:33 +0000 (14:44 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 22 Jun 2015 10:45:26 +0000 (12:45 +0200)
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
sonar-batch/src/main/java/org/sonar/batch/compute/CountUnresolvedIssuesDecorator.java [deleted file]
sonar-batch/src/test/java/org/sonar/batch/compute/CountUnresolvedIssuesDecoratorTest.java [deleted file]

index b80e89cdd2bdbefc7a8db1706533452732aa7ec9..53041fab9e1ff793416b65aa51caefdd7880b7a2 100644 (file)
@@ -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 (file)
index dee397d..0000000
+++ /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<Metric> generatesIssuesMetrics() {
-    return ImmutableList.<Metric>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<Issue> issues = issuable.issues();
-      boolean shouldSaveNewMetrics = shouldSaveNewMetrics(context);
-
-      Multiset<RulePriority> severityBag = HashMultiset.create();
-      Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity = Maps.newHashMap();
-      ListMultimap<RulePriority, Issue> issuesPerSeverity = ArrayListMultimap.create();
-      int countOpen = 0;
-      int countReopened = 0;
-      int countConfirmed = 0;
-
-      for (Issue issue : issues) {
-        severityBag.add(RulePriority.valueOf(issue.severity()));
-        Multiset<RuleKey> 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<Issue> issues) {
-    if (context.getMeasure(CoreMetrics.VIOLATIONS) == null) {
-      Collection<Measure> childrenIssues = context.getChildrenMeasures(CoreMetrics.VIOLATIONS);
-      Double sum = MeasureUtils.sum(true, childrenIssues);
-      context.saveMeasure(CoreMetrics.VIOLATIONS, sum + issues.size());
-    }
-  }
-
-  private void saveNewIssues(DecoratorContext context, Collection<Issue> 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<RulePriority> severitiesBag) {
-    Metric metric = SeverityUtils.severityToIssueMetric(ruleSeverity);
-    if (context.getMeasure(metric) == null) {
-      Collection<Measure> 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<RulePriority, Issue> 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<RulePriority, Multiset<RuleKey>> rulesPerSeverity) {
-    Metric metric = SeverityUtils.severityToIssueMetric(severity);
-
-    Collection<Measure> 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<RuleKey> rulesBag = initRules(rulesPerSeverity, severity);
-        rulesBag.add(ruleKey, childRuleMeasure.getIntValue());
-      }
-    }
-
-    Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
-    if (rulesBag != null) {
-      for (Multiset.Entry<RuleKey> 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<Issue> issues, boolean shouldSaveNewMetrics) {
-    if (shouldSaveNewMetrics) {
-      Metric metric = SeverityUtils.severityToNewMetricIssue(severity);
-      ListMultimap<RuleKey, Measure> childMeasuresPerRuleKeys = ArrayListMultimap.create();
-      ListMultimap<RuleKey, Issue> issuesPerRuleKeys = ArrayListMultimap.create();
-      Set<RuleKey> ruleKeys = Sets.newHashSet();
-
-      Collection<Measure> 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<Issue> issues) {
-    for (Period period : timeMachineConfiguration.periods()) {
-      int variationIndex = period.getIndex();
-      Collection<Measure> 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<RuleKey> initRules(Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity, RulePriority severity) {
-    Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
-    if (rulesBag == null) {
-      rulesBag = HashMultiset.create();
-      rulesPerSeverity.put(severity, rulesBag);
-    }
-    return rulesBag;
-  }
-
-  private int countIssues(Collection<Issue> 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<Issue> 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 (file)
index 1963728..0000000
+++ /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.<Measure>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.<Measure>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.<Issue>newArrayList());
-    when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure>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.<Issue>newArrayList());
-    when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure>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.<Measure>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<Issue> 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<Issue> 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<Issue> 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<Issue> createIssues() {
-    List<Issue> 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<Issue> createIssuesForNewMetrics() {
-    List<Issue> 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<Measure> {
-    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<Measure> {
-    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<Measure> {
-    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());
-    }
-  }
-}