package org.sonar.plugins.core.issue;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.*;
+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 org.apache.commons.lang.time.DateUtils;
-import org.sonar.api.batch.*;
+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.component.ResourcePerspectives;
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issue;
-import org.sonar.api.measures.*;
+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.batch.components.TimeMachineConfiguration;
import javax.annotation.Nullable;
-import java.util.*;
+
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* Computes metrics related to number of issues.
CoreMetrics.OPEN_ISSUES,
CoreMetrics.REOPENED_ISSUES,
CoreMetrics.CONFIRMED_ISSUES
- );
+ );
}
public void decorate(Resource resource, DecoratorContext context) {
for (PastSnapshot pastSnapshot : timeMachineConfiguration.getProjectPastSnapshots()) {
int variationIndex = pastSnapshot.getIndex();
Collection<Measure> children = context.getChildrenMeasures(measure.getMetric());
- Date targetDatePlusOneSecond = pastSnapshot.getTargetDate() != null ? DateUtils.addSeconds(pastSnapshot.getTargetDate(), 1) : null;
- int count = countIssuesAfterDate(issues, targetDatePlusOneSecond);
+ // SONAR-3647 Use real snapshot date and not target date in order to stay consistent with other measure variations
+ Date datePlusOneSecond = pastSnapshot.getDate() != null ? DateUtils.addSeconds(pastSnapshot.getDate(), 1) : null;
+ int count = countIssuesAfterDate(issues, datePlusOneSecond);
double sum = MeasureUtils.sumOnVariation(true, variationIndex, children) + count;
measure.setVariation(variationIndex, sum);
}
}
private boolean isAfter(Issue issue, @Nullable Date date) {
- return date == null || (issue.creationDate() != null && DateUtils.truncatedCompareTo(issue.creationDate(), date, Calendar.SECOND)>0);
+ return date == null || (issue.creationDate() != null && DateUtils.truncatedCompareTo(issue.creationDate(), date, Calendar.SECOND) > 0);
}
private boolean shouldSaveNewMetrics(DecoratorContext context) {
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.measures.*;
+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.batch.components.PastSnapshot;
import org.sonar.batch.components.TimeMachineConfiguration;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.*;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyDouble;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.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 {
Rule ruleB1;
Date rightNow;
Date tenDaysAgo;
+ Date afterTenDaysAgo;
Date fiveDaysAgo;
+ Date afterFiveDaysAgo;
Date sameSecond;
@Before
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);
PastSnapshot pastSnapshot = mock(PastSnapshot.class);
when(pastSnapshot.getIndex()).thenReturn(1);
+ when(pastSnapshot.getDate()).thenReturn(afterFiveDaysAgo);
when(pastSnapshot.getTargetDate()).thenReturn(fiveDaysAgo);
PastSnapshot pastSnapshot2 = mock(PastSnapshot.class);
when(pastSnapshot2.getIndex()).thenReturn(2);
+ when(pastSnapshot2.getDate()).thenReturn(afterTenDaysAgo);
when(pastSnapshot2.getTargetDate()).thenReturn(tenDaysAgo);
timeMachineConfiguration = mock(TimeMachineConfiguration.class);
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());
+ when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure> emptyList());
decorator.decorate(resource, context);
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.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));
@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());
+ when(issuable.issues()).thenReturn(Lists.<Issue> newArrayList());
+ when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure> emptyList());
decorator.decorate(resource, context);
@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());
+ when(issuable.issues()).thenReturn(Lists.<Issue> newArrayList());
+ when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure> emptyList());
decorator.decorate(resource, context);
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());
+ when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Collections.<Measure> emptyList());
decorator.decorate(resource, context);