import javax.annotation.Nullable;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.rules.RuleType;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
.build();
private final PeriodHolder periodHolder;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
private final MetricRepository metricRepository;
private final MeasureRepository measureRepository;
private final Map<String, Counters> countersByComponentUuid = new HashMap<>();
private Counters currentCounters;
- public IssueCounter(PeriodHolder periodHolder,
+ public IssueCounter(PeriodHolder periodHolder, AnalysisMetadataHolder analysisMetadataHolder,
MetricRepository metricRepository, MeasureRepository measureRepository) {
this.periodHolder = periodHolder;
+ this.analysisMetadataHolder = analysisMetadataHolder;
this.metricRepository = metricRepository;
this.measureRepository = measureRepository;
}
}
currentCounters.add(issue);
- if (!periodHolder.hasPeriod()) {
- return;
- }
- Period period = periodHolder.getPeriod();
- // Add one second to not take into account issues created during current analysis
- if (issue.creationDate().getTime() > truncateToSeconds(period.getSnapshotDate())) {
+ if (analysisMetadataHolder.isSLBorPR()) {
currentCounters.addOnPeriod(issue);
+ } else if (periodHolder.hasPeriod()) {
+ Period period = periodHolder.getPeriod();
+ if (issue.creationDate().getTime() > truncateToSeconds(period.getSnapshotDate())) {
+ currentCounters.addOnPeriod(issue);
+ }
}
}
addMeasuresBySeverity(component);
addMeasuresByStatus(component);
addMeasuresByType(component);
- addMeasuresByPeriod(component);
+ addNewMeasures(component);
currentCounters = null;
}
measureRepository.add(component, metric, Measure.newMeasureBuilder().create(value));
}
- private void addMeasuresByPeriod(Component component) {
- if (!periodHolder.hasPeriod()) {
+ private void addNewMeasures(Component component) {
+ if (!periodHolder.hasPeriod() && !analysisMetadataHolder.isSLBorPR()) {
return;
}
double unresolvedVariations = (double) currentCounters.counterForPeriod().unresolved;
import java.util.HashMap;
import java.util.Map;
import org.sonar.api.measures.CoreMetrics;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
import org.sonar.ce.task.projectanalysis.metric.Metric;
import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
-import org.sonar.ce.task.projectanalysis.period.Period;
import org.sonar.ce.task.projectanalysis.period.PeriodHolder;
import org.sonar.core.issue.DefaultIssue;
public class NewEffortAggregator extends IssueVisitor {
private final Map<String, NewEffortCounter> counterByComponentUuid = new HashMap<>();
private final PeriodHolder periodHolder;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
private final MeasureRepository measureRepository;
private final Metric newMaintainabilityEffortMetric;
private NewEffortCounter counter = null;
- public NewEffortAggregator(PeriodHolder periodHolder, MetricRepository metricRepository, MeasureRepository measureRepository) {
+ public NewEffortAggregator(PeriodHolder periodHolder, AnalysisMetadataHolder analysisMetadataHolder, MetricRepository metricRepository,
+ MeasureRepository measureRepository) {
this.periodHolder = periodHolder;
+ this.analysisMetadataHolder = analysisMetadataHolder;
this.measureRepository = measureRepository;
this.newMaintainabilityEffortMetric = metricRepository.getByKey(NEW_TECHNICAL_DEBT_KEY);
@Override
public void onIssue(Component component, DefaultIssue issue) {
- if (issue.resolution() == null && issue.effortInMinutes() != null && periodHolder.hasPeriod()) {
- counter.add(issue, periodHolder.getPeriod());
+ if (issue.resolution() == null && issue.effortInMinutes() != null) {
+ if (analysisMetadataHolder.isSLBorPR()) {
+ counter.add(issue, 0L);
+ } else if (periodHolder.hasPeriod()) {
+ counter.add(issue, periodHolder.getPeriod().getSnapshotDate());
+ }
}
}
@Override
public void afterComponent(Component component) {
- if (periodHolder.hasPeriod()) {
+ if (periodHolder.hasPeriod() || analysisMetadataHolder.isSLBorPR()) {
computeMeasure(component, newMaintainabilityEffortMetric, counter.maintainabilitySum);
computeMeasure(component, newReliabilityEffortMetric, counter.reliabilitySum);
computeMeasure(component, newSecurityEffortMetric, counter.securitySum);
securitySum.add(otherCounter.securitySum);
}
- void add(DefaultIssue issue, Period period) {
- long newEffort = calculate(issue, period);
+ void add(DefaultIssue issue, long startDate) {
+ long newEffort = calculate(issue, startDate);
switch (issue.type()) {
case CODE_SMELL:
maintainabilitySum.add(newEffort);
}
}
- long calculate(DefaultIssue issue, Period period) {
- if (issue.creationDate().getTime() > truncateToSeconds(period.getSnapshotDate())) {
+ long calculate(DefaultIssue issue, long startDate) {
+ if (issue.creationDate().getTime() > truncateToSeconds(startDate)) {
return MoreObjects.firstNonNull(issue.effortInMinutes(), 0L);
}
return 0L;
import java.util.Map;
import org.sonar.api.ce.measure.Issue;
import org.sonar.api.measures.CoreMetrics;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.PathAwareVisitorAdapter;
import org.sonar.ce.task.projectanalysis.formula.counter.RatingValue;
private final PeriodHolder periodHolder;
private final Map<String, Metric> metricsByKey;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
- public NewReliabilityAndSecurityRatingMeasuresVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, ComponentIssuesRepository componentIssuesRepository,
- PeriodHolder periodHolder) {
+ public NewReliabilityAndSecurityRatingMeasuresVisitor(MetricRepository metricRepository, MeasureRepository measureRepository,
+ ComponentIssuesRepository componentIssuesRepository, PeriodHolder periodHolder, AnalysisMetadataHolder analysisMetadataHolder) {
super(LEAVES, POST_ORDER, CounterFactory.INSTANCE);
this.measureRepository = measureRepository;
this.componentIssuesRepository = componentIssuesRepository;
this.metricsByKey = ImmutableMap.of(
NEW_RELIABILITY_RATING_KEY, metricRepository.getByKey(NEW_RELIABILITY_RATING_KEY),
NEW_SECURITY_RATING_KEY, metricRepository.getByKey(NEW_SECURITY_RATING_KEY));
+ this.analysisMetadataHolder = analysisMetadataHolder;
}
@Override
}
private void computeAndSaveMeasures(Component component, Path<Counter> path) {
- if (!periodHolder.hasPeriod()) {
+ if (!periodHolder.hasPeriod() && !analysisMetadataHolder.isSLBorPR()) {
return;
}
initRatingsToA(path);
.stream()
.filter(issue -> issue.resolution() == null)
.filter(issue -> issue.type().equals(BUG) || issue.type().equals(VULNERABILITY))
- .forEach(issue -> path.current().processIssue(issue, periodHolder.getPeriod()));
+ .forEach(issue -> path.current().processIssue(issue, analysisMetadataHolder.isSLBorPR(), periodHolder));
}
private static void addToParent(Path<Counter> path) {
}
void add(Counter otherCounter) {
- newRatingValueByMetric.entrySet().forEach(e -> e.getValue().increment(otherCounter.newRatingValueByMetric.get(e.getKey())));
+ newRatingValueByMetric.forEach((metric, rating) -> rating.increment(otherCounter.newRatingValueByMetric.get(metric)));
}
- void processIssue(Issue issue, Period period) {
- if (isOnPeriod((DefaultIssue) issue, period)) {
+ void processIssue(Issue issue, boolean isSLBorPR, PeriodHolder periodHolder) {
+ if (isSLBorPR || isOnPeriod((DefaultIssue) issue, periodHolder.getPeriod())) {
Rating rating = RATING_BY_SEVERITY.get(issue.severity());
if (issue.type().equals(BUG)) {
newRatingValueByMetric.get(NEW_RELIABILITY_RATING_KEY).increment(rating);
assertThat(underTest.isShortLivingBranch()).isTrue();
}
+ @Test
+ public void getIsSLBorPR_returns_true() {
+ Branch branch = mock(Branch.class);
+ when(branch.getType()).thenReturn(BranchType.SHORT);
+
+ AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl();
+ underTest.setBranch(branch);
+
+ assertThat(underTest.isSLBorPR()).isTrue();
+ }
+
+ @Test
+ public void getIsSLBorPR_returns_false() {
+ Branch branch = mock(Branch.class);
+ when(branch.getType()).thenReturn(BranchType.LONG);
+
+ AnalysisMetadataHolderImpl underTest = new AnalysisMetadataHolderImpl();
+ underTest.setBranch(branch);
+
+ assertThat(underTest.isSLBorPR()).isFalse();
+ }
+
@Test
public void getPullRequestBranch_returns_true() {
Branch branch = mock(Branch.class);
import org.junit.Test;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.rules.RuleType;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.ce.task.projectanalysis.analysis.Branch;
import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.ce.task.projectanalysis.period.Period;
import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule;
import org.sonar.core.issue.DefaultIssue;
+import org.sonar.db.component.BranchType;
import org.sonar.db.rule.RuleTesting;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
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;
@Rule
public PeriodHolderRule periodsHolder = new PeriodHolderRule();
+ @Rule
+ public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
+
@Rule
public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
.add(ISSUES_METRIC)
@Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
- private IssueCounter underTest = new IssueCounter(periodsHolder, metricRepository, measureRepository);
+ private IssueCounter underTest = new IssueCounter(periodsHolder, analysisMetadataHolder, metricRepository, measureRepository);
@Test
public void count_issues_by_status() {
}
@Test
- public void count_new_issues() {
+ public void count_new_issues_if_period_exists() {
Period period = newPeriod(1500000000000L);
periodsHolder.setPeriod(period);
assertVariation(PROJECT, NEW_VULNERABILITIES_METRIC, 0);
}
+ @Test
+ public void count_all_issues_as_new_issues_if_pr_or_slb() {
+ periodsHolder.setPeriod(null);
+ Branch branch = mock(Branch.class);
+ when(branch.getType()).thenReturn(BranchType.SHORT);
+ analysisMetadataHolder.setBranch(branch);
+
+ underTest.beforeComponent(FILE1);
+ underTest.onIssue(FILE1, createIssue(null, STATUS_OPEN, BLOCKER, 1000000L).setType(RuleType.CODE_SMELL));
+ underTest.onIssue(FILE1, createIssue(null, STATUS_OPEN, BLOCKER, 0L).setType(RuleType.BUG));
+ underTest.onIssue(FILE1, createIssue(null, STATUS_OPEN, CRITICAL, 100000L).setType(RuleType.CODE_SMELL));
+ underTest.onIssue(FILE1, createIssue(null, STATUS_OPEN, CRITICAL, 100000L).setType(RuleType.BUG));
+ underTest.onIssue(FILE1, createIssue(RESOLUTION_FIXED, STATUS_CLOSED, MAJOR, 200000L).setType(RuleType.BUG));
+ underTest.afterComponent(FILE1);
+
+ underTest.beforeComponent(FILE2);
+ underTest.afterComponent(FILE2);
+
+ underTest.beforeComponent(PROJECT);
+ underTest.afterComponent(PROJECT);
+
+ assertVariation(FILE1, NEW_ISSUES_METRIC, 4);
+ assertVariation(FILE1, NEW_CRITICAL_ISSUES_METRIC, 2);
+ assertVariation(FILE1, NEW_BLOCKER_ISSUES_METRIC, 2);
+ assertVariation(FILE1, NEW_MAJOR_ISSUES_METRIC, 0);
+ assertVariation(FILE1, NEW_CODE_SMELLS_METRIC, 2);
+ assertVariation(FILE1, NEW_BUGS_METRIC, 2);
+ assertVariation(FILE1, NEW_VULNERABILITIES_METRIC, 0);
+
+ assertVariation(PROJECT, NEW_ISSUES_METRIC, 4);
+ assertVariation(PROJECT, NEW_CRITICAL_ISSUES_METRIC, 2);
+ assertVariation(PROJECT, NEW_BLOCKER_ISSUES_METRIC, 2);
+ assertVariation(PROJECT, NEW_MAJOR_ISSUES_METRIC, 0);
+ assertVariation(PROJECT, NEW_CODE_SMELLS_METRIC, 2);
+ assertVariation(PROJECT, NEW_BUGS_METRIC, 2);
+ assertVariation(PROJECT, NEW_VULNERABILITIES_METRIC, 0);
+ }
+
@Test
public void exclude_hotspots_from_issue_counts() {
periodsHolder.setPeriod(null);
import org.junit.Test;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.Duration;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.ce.task.projectanalysis.analysis.Branch;
import org.sonar.ce.task.projectanalysis.component.Component;
+import org.sonar.ce.task.projectanalysis.component.DefaultBranchImpl;
import org.sonar.ce.task.projectanalysis.component.ReportComponent;
import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
import org.sonar.ce.task.projectanalysis.period.Period;
import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule;
import org.sonar.core.issue.DefaultIssue;
+import org.sonar.db.component.BranchType;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.guava.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT;
import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT_KEY;
.add(NEW_SECURITY_REMEDIATION_EFFORT);
@org.junit.Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create();
+ @org.junit.Rule
+ public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
private final Random random = new Random();
- private NewEffortAggregator underTest = new NewEffortAggregator(periodsHolder, metricRepository, measureRepository);
+ private NewEffortAggregator underTest = new NewEffortAggregator(periodsHolder, analysisMetadataHolder, metricRepository, measureRepository);
@Test
public void sum_new_maintainability_effort_of_issues() {
@Test
public void no_measures_if_no_periods() {
+ Branch branch = mock(Branch.class);
+ when(branch.getType()).thenReturn(BranchType.LONG);
+ analysisMetadataHolder.setBranch(branch);
periodsHolder.setPeriod(null);
DefaultIssue unresolved = newCodeSmellIssue(10);
import org.junit.Test;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.Duration;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.ce.task.projectanalysis.analysis.Branch;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.FileAttributes;
import org.sonar.ce.task.projectanalysis.component.ReportComponent;
import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.util.Uuids;
+import org.sonar.db.component.BranchType;
import org.sonar.server.measure.Rating;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING;
import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING_KEY;
@Rule
public PeriodHolderRule periodsHolder = new PeriodHolderRule().setPeriod(new Period("mode", null, LEAK_PERIOD_SNAPSHOT_IN_MILLISEC, "UUID"));
+ @Rule
+ public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
@Rule
public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
private VisitorsCrawler underTest = new VisitorsCrawler(Arrays.asList(fillComponentIssuesVisitorRule,
- new NewReliabilityAndSecurityRatingMeasuresVisitor(metricRepository, measureRepository, componentIssuesRepositoryRule, periodsHolder)));
+ new NewReliabilityAndSecurityRatingMeasuresVisitor(metricRepository, measureRepository, componentIssuesRepositoryRule,
+ periodsHolder, analysisMetadataHolder)));
@Test
public void measures_created_for_project_are_all_A_when_they_have_no_FILE_child() {
@Test
public void compute_C_reliability_and_security_rating_on_major_issue() {
+ // Calculate metric not because a period is set, but because it is a PR
+ periodsHolder.setPeriod(null);
+ Branch b = mock(Branch.class);
+ when(b.getType()).thenReturn(BranchType.PULL_REQUEST);
+ analysisMetadataHolder.setBranch(b);
+
treeRootHolder.setRoot(ROOT_PROJECT);
fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
newBugIssue(10L, MAJOR).setCreationDate(AFTER_LEAK_PERIOD_DATE),
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.measure.LiveMeasureComparator;
if (!lastAnalysis.isPresent()) {
return Optional.empty();
}
- Optional<Long> beginningOfLeakPeriod = lastAnalysis.map(SnapshotDto::getPeriodDate);
QualityGate qualityGate = qGateComputer.loadQualityGate(dbSession, organization, project, branch);
Collection<String> metricKeys = getKeysOfAllInvolvedMetrics(qualityGate);
MeasureMatrix matrix = new MeasureMatrix(components, metricsPerId.values(), dbMeasures);
FormulaContextImpl context = new FormulaContextImpl(matrix, debtRatingGrid);
+ long beginningOfLeak = getBeginningOfLeakPeriod(lastAnalysis, branch);
+
components.forEach(c -> {
- IssueCounter issueCounter = new IssueCounter(dbClient.issueDao().selectIssueGroupsByBaseComponent(dbSession, c, beginningOfLeakPeriod.orElse(Long.MAX_VALUE)));
+ IssueCounter issueCounter = new IssueCounter(dbClient.issueDao().selectIssueGroupsByBaseComponent(dbSession, c, beginningOfLeak));
for (IssueMetricFormula formula : formulaFactory.getFormulas()) {
- // exclude leak formulas when leak period is not defined
- if (beginningOfLeakPeriod.isPresent() || !formula.isOnLeak()) {
+ // use formulas when the leak period is defined, it's a PR/SLB, or the formula is not about the leak period
+ if (shouldUseLeakFormulas(lastAnalysis.get(), branch) || !formula.isOnLeak()) {
context.change(c, formula);
try {
formula.compute(context, issueCounter);
new QGChangeEvent(project, branch, lastAnalysis.get(), config, previousStatus, () -> Optional.of(evaluatedQualityGate)));
}
+ private static long getBeginningOfLeakPeriod(Optional<SnapshotDto> lastAnalysis, BranchDto branch) {
+ if (isSLBorPR(branch)) {
+ return 0L;
+ } else {
+ Optional<Long> beginningOfLeakPeriod = lastAnalysis.map(SnapshotDto::getPeriodDate);
+ return beginningOfLeakPeriod.orElse(Long.MAX_VALUE);
+ }
+ }
+
+ private static boolean isSLBorPR(BranchDto branch) {
+ return branch.getBranchType() == BranchType.SHORT || branch.getBranchType() == BranchType.PULL_REQUEST;
+ }
+
+ private static boolean shouldUseLeakFormulas(SnapshotDto lastAnalysis, BranchDto branch) {
+ return lastAnalysis.getPeriodDate() != null || isSLBorPR(branch);
+ }
+
@CheckForNull
private static Metric.Level loadPreviousStatus(List<MetricDto> metrics, List<LiveMeasureDto> dbMeasures) {
MetricDto alertStatusMetric = metrics.stream()
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
+import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.organization.OrganizationDto;
-import org.sonar.server.measure.Rating;
import org.sonar.server.es.ProjectIndexer;
import org.sonar.server.es.TestProjectIndexers;
+import org.sonar.server.measure.Rating;
import org.sonar.server.qualitygate.EvaluatedQualityGate;
import org.sonar.server.qualitygate.QualityGate;
import org.sonar.server.qualitygate.changeevent.QGChangeEvent;
private ComponentDto dir;
private ComponentDto file1;
private ComponentDto file2;
+ private ComponentDto branch;
+ private ComponentDto branchFile;
private LiveQualityGateComputer qGateComputer = mock(LiveQualityGateComputer.class);
private QualityGate qualityGate = mock(QualityGate.class);
private EvaluatedQualityGate newQualityGate = mock(EvaluatedQualityGate.class);
dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java"));
file1 = db.components().insertComponent(ComponentTesting.newFileDto(project, dir));
file2 = db.components().insertComponent(ComponentTesting.newFileDto(project, dir));
+ branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST));
+ branchFile = db.components().insertComponent(ComponentTesting.newFileDto(branch));
}
@Test
assertThatProjectChanged(result, project);
}
+ @Test
+ public void calculate_new_metrics_if_it_is_pr_or_branch() {
+ markProjectAsAnalyzed(branch, null);
+ db.measures().insertLiveMeasure(branch, intMetric, m -> m.setVariation(42.0).setValue(null));
+ db.measures().insertLiveMeasure(branchFile, intMetric, m -> m.setVariation(42.0).setValue(null));
+
+ // generates values 1, 2, 3 on leak measures
+ List<QGChangeEvent> result = run(branchFile, newQualifierBasedIntLeakFormula(), newRatingLeakFormula(Rating.B));
+
+ assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(4);
+
+ // Numeric value depends on qualifier (see newQualifierBasedIntLeakFormula())
+ assertThatIntMeasureHasLeakValue(branchFile, ORDERED_BOTTOM_UP.indexOf(Qualifiers.FILE));
+ assertThatRatingMeasureHasLeakValue(branchFile, Rating.B);
+ assertThatIntMeasureHasLeakValue(branch, ORDERED_BOTTOM_UP.indexOf(Qualifiers.PROJECT));
+ assertThatRatingMeasureHasLeakValue(branch, Rating.B);
+ assertThatProjectChanged(result, branch);
+ }
+
@Test
public void do_nothing_if_project_has_not_been_analyzed() {
// project has no snapshots
List<QGChangeEvent> result = run(file1, newIncrementalFormula());
-
assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(0);
assertThatProjectNotChanged(result, project);
}
}
private void markProjectAsAnalyzed(ComponentDto p) {
+ markProjectAsAnalyzed(p, 1_490_000_000L);
+ }
+
+ private void markProjectAsAnalyzed(ComponentDto p, @Nullable Long periodDate) {
assertThat(p.qualifier()).isEqualTo(Qualifiers.PROJECT);
- db.components().insertSnapshot(p, s -> s.setPeriodDate(1_490_000_000L));
+ db.components().insertSnapshot(p, s -> s.setPeriodDate(periodDate));
}
private LiveMeasureDto assertThatIntMeasureHasValue(ComponentDto component, double expectedValue) {