3 * Copyright (C) 2009-2016 SonarSource SA
4 * mailto:contact AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.computation.task.projectanalysis.step;
22 import org.junit.Before;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.sonar.api.utils.System2;
26 import org.sonar.db.DbClient;
27 import org.sonar.db.DbSession;
28 import org.sonar.db.DbTester;
29 import org.sonar.db.component.ComponentDto;
30 import org.sonar.db.component.ComponentTesting;
31 import org.sonar.db.component.SnapshotDto;
32 import org.sonar.db.measure.MeasureDto;
33 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
34 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
35 import org.sonar.server.computation.task.projectanalysis.component.Component;
36 import org.sonar.server.computation.task.projectanalysis.component.DumbDeveloper;
37 import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
38 import org.sonar.server.computation.task.projectanalysis.measure.Measure;
39 import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
40 import org.sonar.server.computation.task.projectanalysis.measure.MeasureVariations;
41 import org.sonar.server.computation.task.projectanalysis.metric.Metric;
42 import org.sonar.server.computation.task.projectanalysis.metric.MetricImpl;
43 import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
44 import org.sonar.server.computation.task.projectanalysis.period.Period;
45 import org.sonar.server.computation.task.projectanalysis.period.PeriodsHolderRule;
47 import static org.assertj.core.api.Assertions.assertThat;
48 import static org.sonar.db.component.SnapshotTesting.newAnalysis;
49 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
51 public class ReportComputeMeasureVariationsStepTest {
53 private static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
54 private static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
55 private static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
56 private static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
57 private static final Metric NEW_DEBT = new MetricImpl(5, "new_debt", "new_debt", Metric.MetricType.WORK_DUR);
58 private static final String PROJECT_UUID = "prj uuid";
59 private static final int PROJECT_REF = 1;
60 private static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, PROJECT_REF).setUuid(PROJECT_UUID).build();
64 public DbTester dbTester = DbTester.create(System2.INSTANCE);
66 public BatchReportReaderRule reportReader = new BatchReportReaderRule();
68 public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
70 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
72 public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
75 .add(FILE_COMPLEXITY_METRIC)
76 .add(BUILD_BREAKER_METRIC)
79 public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
81 private ComponentDto project;
83 DbSession session = dbTester.getSession();
85 DbClient dbClient = dbTester.getDbClient();
87 ComputeMeasureVariationsStep underTest;
91 project = dbTester.components().insertProject(dbTester.organizations().insert(), PROJECT_UUID);
93 underTest = new ComputeMeasureVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
97 public void do_nothing_when_no_raw_measure() {
98 SnapshotDto period1ProjectSnapshot = newAnalysis(project);
99 dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
100 dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period1ProjectSnapshot.getUuid(), 60d));
103 periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
105 treeRootHolder.setRoot(PROJECT);
109 assertThat(measureRepository.getRawMeasures(PROJECT).keys()).isEmpty();
113 public void do_nothing_when_no_period() {
114 Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).build();
115 treeRootHolder.setRoot(project);
116 periodsHolder.setPeriods();
120 assertThat(measureRepository.getRawMeasures(project).keys()).isEmpty();
124 public void set_variation() {
126 SnapshotDto period1Snapshot = newAnalysis(project);
127 dbClient.snapshotDao().insert(session, period1Snapshot);
128 dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period1Snapshot.getUuid(), 60d));
131 ComponentDto directoryDto = ComponentTesting.newDirectory(project, "dir");
132 dbClient.componentDao().insert(session, directoryDto);
133 dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.uuid(), period1Snapshot.getUuid(), 10d));
136 periodsHolder.setPeriods(newPeriod(1, period1Snapshot));
138 Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid(directoryDto.uuid()).build();
139 Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).addChildren(directory).build();
140 treeRootHolder.setRoot(project);
142 addRawMeasure(project, ISSUES_METRIC, newMeasureBuilder().create(80, null));
143 addRawMeasure(directory, ISSUES_METRIC, newMeasureBuilder().create(20, null));
147 assertThat(measureRepository.getRawMeasure(project, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
148 assertThat(measureRepository.getRawMeasure(directory, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
152 public void set_zero_variation_when_no_change() {
154 SnapshotDto period1Snapshot = newAnalysis(project);
155 dbClient.snapshotDao().insert(session, period1Snapshot);
156 dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period1Snapshot.getUuid(), 60d));
159 ComponentDto directoryDto = ComponentTesting.newDirectory(project, "dir");
160 dbClient.componentDao().insert(session, directoryDto);
161 dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.uuid(), period1Snapshot.getUuid(), 10d));
164 periodsHolder.setPeriods(newPeriod(1, period1Snapshot));
166 Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid(directoryDto.uuid()).build();
167 Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).addChildren(directory).build();
168 treeRootHolder.setRoot(project);
170 addRawMeasure(project, ISSUES_METRIC, newMeasureBuilder().create(60, null));
171 addRawMeasure(directory, ISSUES_METRIC, newMeasureBuilder().create(10, null));
175 assertThat(measureRepository.getRawMeasure(project, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(0d);
176 assertThat(measureRepository.getRawMeasure(directory, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(0d);
180 public void set_variation_to_raw_value_on_new_component() throws Exception {
182 SnapshotDto past1ProjectSnapshot = newAnalysis(project).setCreatedAt(1000_000_000L);
183 SnapshotDto currentProjectSnapshot = newAnalysis(project).setCreatedAt(2000_000_000L);
184 dbClient.snapshotDao().insert(session, past1ProjectSnapshot);
185 dbClient.snapshotDao().insert(session, currentProjectSnapshot);
186 dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, past1ProjectSnapshot.getUuid(), 60d));
187 dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, currentProjectSnapshot.getUuid(), 60d));
190 periodsHolder.setPeriods(newPeriod(1, past1ProjectSnapshot));
192 // Directory has just been added => no snapshot
193 Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid("DIRECTORY").build();
194 Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).addChildren(directory).build();
195 treeRootHolder.setRoot(project);
197 addRawMeasure(project, ISSUES_METRIC, newMeasureBuilder().create(90, null));
198 addRawMeasure(directory, ISSUES_METRIC, newMeasureBuilder().create(10, null));
202 assertThat(measureRepository.getRawMeasure(project, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(30d);
203 // Variation should be the raw value
204 assertThat(measureRepository.getRawMeasure(directory, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
208 public void set_variations_on_all_periods() {
209 SnapshotDto period1ProjectSnapshot = newAnalysis(project).setLast(false);
210 SnapshotDto period2ProjectSnapshot = newAnalysis(project).setLast(false);
211 SnapshotDto period3ProjectSnapshot = newAnalysis(project).setLast(false);
212 SnapshotDto period4ProjectSnapshot = newAnalysis(project).setLast(false);
213 SnapshotDto period5ProjectSnapshot = newAnalysis(project).setLast(false);
214 dbClient.snapshotDao().insert(session, period1ProjectSnapshot, period2ProjectSnapshot, period3ProjectSnapshot, period4ProjectSnapshot, period5ProjectSnapshot);
216 dbClient.measureDao().insert(session,
217 newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period1ProjectSnapshot.getUuid(), 0d),
218 newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period2ProjectSnapshot.getUuid(), 20d),
219 newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period3ProjectSnapshot.getUuid(), 40d),
220 newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period4ProjectSnapshot.getUuid(), 80d),
221 newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period5ProjectSnapshot.getUuid(), 100d));
224 periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot),
225 newPeriod(2, period2ProjectSnapshot),
226 newPeriod(3, period3ProjectSnapshot),
227 newPeriod(4, period4ProjectSnapshot),
228 newPeriod(5, period5ProjectSnapshot));
230 treeRootHolder.setRoot(PROJECT);
232 addRawMeasure(PROJECT, ISSUES_METRIC, newMeasureBuilder().create(80, null));
236 assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(1);
238 Measure measure = measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get();
239 assertThat(measure.hasVariations()).isTrue();
240 assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
241 assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
242 assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
243 assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
244 assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
248 public void set_variation_on_all_numeric_metrics() {
249 SnapshotDto period1ProjectSnapshot = newAnalysis(project);
250 dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
251 dbClient.measureDao().insert(session,
252 newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period1ProjectSnapshot.getUuid(), 60d),
253 newMeasureDto(DEBT_METRIC.getId(), PROJECT_UUID, period1ProjectSnapshot.getUuid(), 10d),
254 newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), PROJECT_UUID, period1ProjectSnapshot.getUuid(), 2d),
255 newMeasureDto(BUILD_BREAKER_METRIC.getId(), PROJECT_UUID, period1ProjectSnapshot.getUuid(), 1d));
258 periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
260 treeRootHolder.setRoot(PROJECT);
262 addRawMeasure(PROJECT, ISSUES_METRIC, newMeasureBuilder().create(80, null));
263 addRawMeasure(PROJECT, DEBT_METRIC, newMeasureBuilder().create(5L, null));
264 addRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC, newMeasureBuilder().create(3d, 1, null));
265 addRawMeasure(PROJECT, BUILD_BREAKER_METRIC, newMeasureBuilder().create(false, null));
269 assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(4);
271 assertThat(measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
272 assertThat(measureRepository.getRawMeasure(PROJECT, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
273 assertThat(measureRepository.getRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
274 assertThat(measureRepository.getRawMeasure(PROJECT, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
278 public void do_not_set_variations_on_numeric_metric_for_developer() {
279 SnapshotDto period1ProjectSnapshot = newAnalysis(project);
280 dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
281 dbClient.measureDao().insert(session,
282 newMeasureDto(ISSUES_METRIC.getId(), PROJECT_UUID, period1ProjectSnapshot.getUuid(), 60d));
285 periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
287 treeRootHolder.setRoot(PROJECT);
289 DumbDeveloper developer = new DumbDeveloper("a");
290 measureRepository.addRawMeasure(PROJECT_REF, ISSUES_METRIC.getKey(), newMeasureBuilder().forDeveloper(developer).create(80, null));
294 assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(1);
296 assertThat(measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC, developer).get().hasVariations()).isFalse();
300 public void does_not_update_existing_variations() throws Exception {
301 SnapshotDto period1ProjectSnapshot = newAnalysis(project);
302 dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
303 dbClient.measureDao().insert(session, newMeasureDto(NEW_DEBT.getId(), PROJECT_UUID, period1ProjectSnapshot.getUuid(), 60d));
305 periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
306 treeRootHolder.setRoot(PROJECT);
308 addRawMeasure(PROJECT, NEW_DEBT, newMeasureBuilder().setVariations(new MeasureVariations(10d)).createNoValue());
312 // As the measure has already variations it has been ignored, then variations will be the same
313 assertThat(measureRepository.getRawMeasure(PROJECT, NEW_DEBT).get().getVariations().getVariation1()).isEqualTo(10d);
316 private static MeasureDto newMeasureDto(int metricId, String componentUuid, String analysisUuid, double value) {
317 return new MeasureDto()
318 .setMetricId(metricId)
319 .setComponentUuid(componentUuid)
320 .setAnalysisUuid(analysisUuid)
324 private static Period newPeriod(int index, SnapshotDto snapshotDto) {
325 return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getUuid());
328 private void addRawMeasure(Component component, Metric metric, Measure measure) {
329 measureRepository.addRawMeasure(component.getReportAttributes().getRef(), metric.getKey(), measure);