]> source.dussan.org Git - sonarqube.git/blob
3fe2036216c85687d4cb227ef6e7de7aac47c5a2
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.ce.task.projectanalysis.step;
21
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.Optional;
26 import java.util.Set;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.sonar.api.measures.CoreMetrics;
30 import org.sonar.ce.task.projectanalysis.component.Component;
31 import org.sonar.ce.task.projectanalysis.component.FileAttributes;
32 import org.sonar.ce.task.projectanalysis.component.ReportComponent;
33 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
34 import org.sonar.ce.task.projectanalysis.formula.coverage.LinesAndConditionsWithUncoveredMetricKeys;
35 import org.sonar.ce.task.projectanalysis.measure.Measure;
36 import org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry;
37 import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
38 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
39 import org.sonar.ce.task.projectanalysis.source.NewLinesRepository;
40 import org.sonar.ce.task.step.TestComputationStepContext;
41
42 import static org.assertj.core.api.Assertions.assertThat;
43 import static org.assertj.guava.api.Assertions.assertThat;
44 import static org.mockito.Mockito.mock;
45 import static org.mockito.Mockito.when;
46 import static org.sonar.api.measures.CoreMetrics.CONDITIONS_BY_LINE_KEY;
47 import static org.sonar.api.measures.CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY;
48 import static org.sonar.api.measures.CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY;
49 import static org.sonar.api.measures.CoreMetrics.NEW_CONDITIONS_TO_COVER_KEY;
50 import static org.sonar.api.measures.CoreMetrics.NEW_LINES_TO_COVER_KEY;
51 import static org.sonar.api.measures.CoreMetrics.NEW_UNCOVERED_CONDITIONS_KEY;
52 import static org.sonar.api.measures.CoreMetrics.NEW_UNCOVERED_LINES_KEY;
53 import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
54 import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
55 import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT;
56 import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
57 import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
58 import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.entryOf;
59 import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
60
61 public class ReportNewCoverageMeasuresStepTest {
62
63   private static final int ROOT_REF = 1;
64   private static final int DIRECTORY_1_REF = 1111;
65   private static final int FILE_1_REF = 11111;
66   private static final int DIRECTORY_2_REF = 1112;
67   private static final int FILE_2_REF = 11121;
68   private static final int FILE_3_REF = 11122;
69   private static final Component FILE_1 = builder(FILE, FILE_1_REF).build();
70   private static final Component FILE_2 = builder(FILE, FILE_2_REF).build();
71   private static final Component FILE_3 = builder(FILE, FILE_3_REF).build();
72
73   private static final ReportComponent MULTIPLE_FILES_TREE = builder(PROJECT, ROOT_REF)
74     .addChildren(
75       builder(DIRECTORY, DIRECTORY_1_REF)
76         .addChildren(FILE_1)
77         .build(),
78       builder(DIRECTORY, DIRECTORY_2_REF)
79         .addChildren(FILE_2, FILE_3)
80         .build())
81     .build();
82
83   @Rule
84   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
85   @Rule
86   public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
87     .add(CoreMetrics.COVERAGE_LINE_HITS_DATA)
88     .add(CoreMetrics.CONDITIONS_BY_LINE)
89     .add(CoreMetrics.COVERED_CONDITIONS_BY_LINE)
90     .add(CoreMetrics.NEW_LINES_TO_COVER)
91     .add(CoreMetrics.NEW_UNCOVERED_LINES)
92     .add(CoreMetrics.NEW_CONDITIONS_TO_COVER)
93     .add(CoreMetrics.NEW_UNCOVERED_CONDITIONS)
94     .add(CoreMetrics.NEW_COVERAGE)
95     .add(CoreMetrics.NEW_BRANCH_COVERAGE)
96     .add(CoreMetrics.NEW_LINE_COVERAGE);
97
98   @Rule
99   public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
100   private NewLinesRepository newLinesRepository = mock(NewLinesRepository.class);
101   private NewCoverageMeasuresStep underTest = new NewCoverageMeasuresStep(treeRootHolder, measureRepository, metricRepository, newLinesRepository);
102   public static final ReportComponent FILE_COMPONENT = ReportComponent.builder(Component.Type.FILE, FILE_1_REF)
103     .setFileAttributes(new FileAttributes(false, null, 1)).build();
104
105   @Test
106   public void no_measure_for_PROJECT_component() {
107     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, ROOT_REF).build());
108
109     underTest.execute(new TestComputationStepContext());
110
111     assertThat(measureRepository.isEmpty()).isTrue();
112   }
113
114   @Test
115   public void no_measure_for_DIRECTORY_component() {
116     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.DIRECTORY, DIRECTORY_1_REF).build());
117
118     underTest.execute(new TestComputationStepContext());
119
120     assertThat(measureRepository.isEmpty()).isTrue();
121   }
122
123   @Test
124   public void no_measure_for_unit_test_FILE_component() {
125     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.FILE, FILE_1_REF).setFileAttributes(new FileAttributes(true, null, 1)).build());
126
127     underTest.execute(new TestComputationStepContext());
128
129     assertThat(measureRepository.isEmpty()).isTrue();
130   }
131
132   @Test
133   public void no_measures_for_FILE_component_without_code() {
134     treeRootHolder.setRoot(ReportComponent.builder(Component.Type.FILE, FILE_1_REF).setFileAttributes(new FileAttributes(false, null, 1)).build());
135
136     underTest.execute(new TestComputationStepContext());
137
138     assertThat(measureRepository.isEmpty()).isTrue();
139   }
140
141   @Test
142   public void zero_measures_when_nothing_has_changed() {
143     treeRootHolder.setRoot(FILE_COMPONENT);
144     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
145     when(newLinesRepository.getNewLines(FILE_COMPONENT)).thenReturn(Optional.of(Collections.emptySet()));
146     measureRepository.addRawMeasure(FILE_COMPONENT.getReportAttributes().getRef(), COVERAGE_LINE_HITS_DATA_KEY, newMeasureBuilder().create("2=1;3=1"));
147     measureRepository.addRawMeasure(FILE_COMPONENT.getReportAttributes().getRef(), CONDITIONS_BY_LINE_KEY, newMeasureBuilder().create("2=1"));
148     measureRepository.addRawMeasure(FILE_COMPONENT.getReportAttributes().getRef(), COVERED_CONDITIONS_BY_LINE_KEY, newMeasureBuilder().create("2=1"));
149
150     underTest.execute(new TestComputationStepContext());
151
152     verify_only_zero_measures_on_new_lines_and_conditions_measures(FILE_COMPONENT);
153   }
154
155   @Test
156   public void zero_measures_for_FILE_component_without_CoverageData() {
157     treeRootHolder.setRoot(FILE_1);
158     setNewLines(FILE_1);
159
160     underTest.execute(new TestComputationStepContext());
161
162     verify_only_zero_measures_on_new_lines_and_conditions_measures(FILE_1);
163   }
164
165   @Test
166   public void verify_computation_of_measures_for_new_lines_for_FILE() {
167     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
168
169     String coverageLineHitsData = COVERAGE_LINE_HITS_DATA_KEY;
170     String newLinesToCover = NEW_LINES_TO_COVER_KEY;
171     String newUncoveredLines = NEW_UNCOVERED_LINES_KEY;
172     String newConditionsToCover = NEW_CONDITIONS_TO_COVER_KEY;
173     String newUncoveredConditions = NEW_UNCOVERED_CONDITIONS_KEY;
174
175     verify_computation_of_measures_for_new_lines(coverageLineHitsData,
176       newLinesToCover, newUncoveredLines, newConditionsToCover, newUncoveredConditions);
177   }
178
179   private void verify_computation_of_measures_for_new_lines(String coverageLineHitsData,
180     String newLinesToCover, String newUncoveredLines, String newConditionsToCover, String newUncoveredConditions) {
181     treeRootHolder.setRoot(FILE_COMPONENT);
182     setNewLines(FILE_1, 1, 2, 4);
183
184     measureRepository.addRawMeasure(FILE_COMPONENT.getReportAttributes().getRef(), coverageLineHitsData, newMeasureBuilder().create("2=0;3=2;4=3"));
185
186     underTest.execute(new TestComputationStepContext());
187
188     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_COMPONENT.getReportAttributes().getRef()))).contains(
189       entryOf(newLinesToCover, createMeasure(2d)),
190       entryOf(newUncoveredLines, createMeasure(1d)),
191       entryOf(newConditionsToCover, createMeasure(0d)),
192       entryOf(newUncoveredConditions, createMeasure(0d)));
193   }
194
195   @Test
196   public void verify_computation_of_measures_for_new_conditions_for_FILE() {
197     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
198
199     String coverageLineHitsData = COVERAGE_LINE_HITS_DATA_KEY;
200     String conditionsByLine = CONDITIONS_BY_LINE_KEY;
201     String coveredConditionsByLine = COVERED_CONDITIONS_BY_LINE_KEY;
202     String newLinesToCover = NEW_LINES_TO_COVER_KEY;
203     String newUncoveredLines = NEW_UNCOVERED_LINES_KEY;
204     String newConditionsToCover = NEW_CONDITIONS_TO_COVER_KEY;
205     String newUncoveredConditions = NEW_UNCOVERED_CONDITIONS_KEY;
206
207     verify_computation_of_measures_for_new_conditions(new MetricKeys(coverageLineHitsData, conditionsByLine, coveredConditionsByLine,
208       newLinesToCover, newUncoveredLines, newConditionsToCover, newUncoveredConditions));
209   }
210
211   @Test
212   public void verify_aggregation_of_measures_for_new_conditions() {
213     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
214
215     String coverageLineHitsData = CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY;
216     String conditionsByLine = CoreMetrics.CONDITIONS_BY_LINE_KEY;
217     String coveredConditionsByLine = CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY;
218     String newLinesToCover = NEW_LINES_TO_COVER_KEY;
219     String newUncoveredLines = NEW_UNCOVERED_LINES_KEY;
220     String newConditionsToCover = NEW_CONDITIONS_TO_COVER_KEY;
221     String newUncoveredConditions = NEW_UNCOVERED_CONDITIONS_KEY;
222
223     MetricKeys metricKeys = new MetricKeys(coverageLineHitsData, conditionsByLine, coveredConditionsByLine,
224       newLinesToCover, newUncoveredLines, newConditionsToCover, newUncoveredConditions);
225
226     treeRootHolder.setRoot(MULTIPLE_FILES_TREE);
227     defineNewLinesAndMeasures(FILE_1, metricKeys, new MeasureValues(3, 4, 1), new MeasureValues(0, 3, 2));
228     defineNewLinesAndMeasures(FILE_2, metricKeys, new MeasureValues(0, 14, 6), new MeasureValues(0, 13, 7));
229     defineNewLinesAndMeasures(FILE_3, metricKeys, new MeasureValues(3, 4, 1), new MeasureValues(1, 13, 7));
230
231     underTest.execute(new TestComputationStepContext());
232
233     // files
234     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).contains(
235       entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
236       entryOf(metricKeys.newUncoveredLines, createMeasure(3d)),
237       entryOf(metricKeys.newConditionsToCover, createMeasure(7d)),
238       entryOf(metricKeys.newUncoveredConditions, createMeasure(4d)));
239     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).contains(
240       entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
241       entryOf(metricKeys.newUncoveredLines, createMeasure(4d)),
242       entryOf(metricKeys.newConditionsToCover, createMeasure(27d)),
243       entryOf(metricKeys.newUncoveredConditions, createMeasure(14d)));
244     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_3_REF))).contains(
245       entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
246       entryOf(metricKeys.newUncoveredLines, createMeasure(2d)),
247       entryOf(metricKeys.newConditionsToCover, createMeasure(17d)),
248       entryOf(metricKeys.newUncoveredConditions, createMeasure(9d)));
249     // directories
250     assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_1_REF))).contains(
251       entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
252       entryOf(metricKeys.newUncoveredLines, createMeasure(3d)),
253       entryOf(metricKeys.newConditionsToCover, createMeasure(7d)),
254       entryOf(metricKeys.newUncoveredConditions, createMeasure(4d)));
255     assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_2_REF))).contains(
256       entryOf(metricKeys.newLinesToCover, createMeasure(10d)),
257       entryOf(metricKeys.newUncoveredLines, createMeasure(6d)),
258       entryOf(metricKeys.newConditionsToCover, createMeasure(44d)),
259       entryOf(metricKeys.newUncoveredConditions, createMeasure(23d)));
260     // submodule
261     MeasureRepoEntry[] repoEntriesFromProject = {entryOf(metricKeys.newLinesToCover, createMeasure(15d)),
262       entryOf(metricKeys.newUncoveredLines, createMeasure(9d)),
263       entryOf(metricKeys.newConditionsToCover, createMeasure(51d)),
264       entryOf(metricKeys.newUncoveredConditions, createMeasure(27d))};
265     // project
266     assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).contains(repoEntriesFromProject);
267   }
268
269   @Test
270   public void verify_aggregates_variations_for_new_code_line_and_branch_Coverage() {
271     LinesAndConditionsWithUncoveredMetricKeys metricKeys = new LinesAndConditionsWithUncoveredMetricKeys(
272       CoreMetrics.NEW_LINES_TO_COVER_KEY, CoreMetrics.NEW_CONDITIONS_TO_COVER_KEY,
273       CoreMetrics.NEW_UNCOVERED_LINES_KEY, CoreMetrics.NEW_UNCOVERED_CONDITIONS_KEY);
274     String codeCoverageKey = CoreMetrics.NEW_COVERAGE_KEY;
275     String lineCoverageKey = CoreMetrics.NEW_LINE_COVERAGE_KEY;
276     String branchCoverageKey = CoreMetrics.NEW_BRANCH_COVERAGE_KEY;
277
278     verify_aggregates_variations(metricKeys, codeCoverageKey, lineCoverageKey, branchCoverageKey);
279   }
280
281   private void verify_aggregates_variations(LinesAndConditionsWithUncoveredMetricKeys metricKeys, String codeCoverageKey, String lineCoverageKey, String branchCoverageKey) {
282     treeRootHolder.setRoot(MULTIPLE_FILES_TREE);
283     measureRepository
284       .addRawMeasure(FILE_1_REF, metricKeys.getLines(), createMeasure(3000d))
285       .addRawMeasure(FILE_1_REF, metricKeys.getConditions(), createMeasure(300d))
286       .addRawMeasure(FILE_1_REF, metricKeys.getUncoveredLines(), createMeasure(30d))
287       .addRawMeasure(FILE_1_REF, metricKeys.getUncoveredConditions(), createMeasure(9d))
288
289       .addRawMeasure(FILE_2_REF, metricKeys.getLines(), createMeasure(2000d))
290       .addRawMeasure(FILE_2_REF, metricKeys.getConditions(), createMeasure(400d))
291       .addRawMeasure(FILE_2_REF, metricKeys.getUncoveredLines(), createMeasure(200d))
292       .addRawMeasure(FILE_2_REF, metricKeys.getUncoveredConditions(), createMeasure(16d));
293
294     underTest.execute(new TestComputationStepContext());
295
296     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).containsOnly(
297       entryOf(codeCoverageKey, createMeasure(98.8d)),
298       entryOf(lineCoverageKey, createMeasure(99d)),
299       entryOf(branchCoverageKey, createMeasure(97d)));
300     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).containsOnly(
301       entryOf(codeCoverageKey, createMeasure(91d)),
302       entryOf(lineCoverageKey, createMeasure(90d)),
303       entryOf(branchCoverageKey, createMeasure(96d)));
304     assertThat(measureRepository.getAddedRawMeasures(FILE_3_REF)).isEmpty();
305
306     assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_1_REF))).containsOnly(
307       entryOf(codeCoverageKey, createMeasure(98.8d)),
308       entryOf(lineCoverageKey, createMeasure(99d)),
309       entryOf(branchCoverageKey, createMeasure(97d)));
310
311     assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_2_REF))).containsOnly(
312       entryOf(codeCoverageKey, createMeasure(91d)),
313       entryOf(lineCoverageKey, createMeasure(90d)),
314       entryOf(branchCoverageKey, createMeasure(96d)));
315
316     MeasureRepoEntry[] modulesAndProjectEntries = {
317       entryOf(codeCoverageKey, createMeasure(95.5d)),
318       entryOf(lineCoverageKey, createMeasure(95.4d)),
319       entryOf(branchCoverageKey, createMeasure(96.4d))
320     };
321
322     assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).containsOnly(modulesAndProjectEntries);
323   }
324
325   private void verify_only_zero_measures_on_new_lines_and_conditions_measures(Component component) {
326     assertThat(toEntries(measureRepository.getAddedRawMeasures(component.getReportAttributes().getRef()))).containsOnly(
327       entryOf(NEW_LINES_TO_COVER_KEY, createMeasure(0d)),
328       entryOf(NEW_UNCOVERED_LINES_KEY, createMeasure(0d)),
329       entryOf(NEW_CONDITIONS_TO_COVER_KEY, createMeasure(0d)),
330       entryOf(NEW_UNCOVERED_CONDITIONS_KEY, createMeasure(0d)));
331   }
332
333   private void defineNewLinesAndMeasures(Component c, MetricKeys metricKeys, MeasureValues line4, MeasureValues line6) {
334     setNewLines(c, 1, 2, 4, 5, 6, 7);
335     measureRepository.addRawMeasure(c.getReportAttributes().getRef(), metricKeys.coverageLineHitsData,
336       newMeasureBuilder().create("2=0;3=2;4=" + line4.lineHits + ";5=1;6=" + line6.lineHits + ";7=0"));
337     measureRepository
338       .addRawMeasure(c.getReportAttributes().getRef(), metricKeys.conditionsByLine, newMeasureBuilder().create("4=" + line4.coveredConditions + ";6=" + line6.coveredConditions));
339     measureRepository.addRawMeasure(c.getReportAttributes().getRef(), metricKeys.coveredConditionsByLine,
340       newMeasureBuilder().create("4=" + line4.uncoveredConditions + ";6=" + line6.uncoveredConditions));
341   }
342
343   private static final class MetricKeys {
344     private final String coverageLineHitsData;
345     private final String conditionsByLine;
346     private final String coveredConditionsByLine;
347     private final String newLinesToCover;
348     private final String newUncoveredLines;
349     private final String newConditionsToCover;
350     private final String newUncoveredConditions;
351
352     public MetricKeys(String coverageLineHitsData, String conditionsByLine, String coveredConditionsByLine,
353       String newLinesToCover, String newUncoveredLines, String newConditionsToCover, String newUncoveredConditions) {
354       this.coverageLineHitsData = coverageLineHitsData;
355       this.conditionsByLine = conditionsByLine;
356       this.coveredConditionsByLine = coveredConditionsByLine;
357       this.newLinesToCover = newLinesToCover;
358       this.newUncoveredLines = newUncoveredLines;
359       this.newConditionsToCover = newConditionsToCover;
360       this.newUncoveredConditions = newUncoveredConditions;
361     }
362   }
363
364   private static final class MeasureValues {
365     private final int lineHits;
366     private final int coveredConditions;
367     private final int uncoveredConditions;
368
369     public MeasureValues(int lineHits, int coveredConditions, int uncoveredConditions) {
370       this.lineHits = lineHits;
371       this.coveredConditions = coveredConditions;
372       this.uncoveredConditions = uncoveredConditions;
373     }
374   }
375
376   private void verify_computation_of_measures_for_new_conditions(MetricKeys metricKeys) {
377     treeRootHolder.setRoot(FILE_COMPONENT);
378     defineNewLinesAndMeasures(FILE_COMPONENT, metricKeys, new MeasureValues(3, 4, 1), new MeasureValues(0, 3, 2));
379
380     underTest.execute(new TestComputationStepContext());
381
382     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_COMPONENT.getReportAttributes().getRef()))).contains(
383       entryOf(metricKeys.newLinesToCover, createMeasure(5d)),
384       entryOf(metricKeys.newUncoveredLines, createMeasure(3d)),
385       entryOf(metricKeys.newConditionsToCover, createMeasure(7d)),
386       entryOf(metricKeys.newUncoveredConditions, createMeasure(4d)));
387   }
388
389   private static Measure createMeasure(Double expectedVariation) {
390     return newMeasureBuilder()
391       .setVariation(expectedVariation)
392       .createNoValue();
393   }
394
395   private void setNewLines(Component c, Integer... lines) {
396     when(newLinesRepository.newLinesAvailable()).thenReturn(true);
397     Set<Integer> newLines = new HashSet<>(Arrays.asList(lines));
398     when(newLinesRepository.getNewLines(c)).thenReturn(Optional.of(newLines));
399   }
400 }