3 * Copyright (C) 2009-2019 SonarSource SA
4 * mailto:info 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.ce.task.projectanalysis.duplication;
22 import org.junit.Rule;
23 import org.junit.Test;
24 import org.sonar.ce.task.projectanalysis.component.FileAttributes;
25 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
26 import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
27 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
29 import static com.google.common.base.Preconditions.checkArgument;
30 import static org.assertj.core.api.Assertions.assertThat;
31 import static org.mockito.Mockito.mock;
32 import static org.mockito.Mockito.when;
33 import static org.sonar.api.measures.CoreMetrics.DUPLICATED_BLOCKS;
34 import static org.sonar.api.measures.CoreMetrics.DUPLICATED_BLOCKS_KEY;
35 import static org.sonar.api.measures.CoreMetrics.DUPLICATED_FILES;
36 import static org.sonar.api.measures.CoreMetrics.DUPLICATED_FILES_KEY;
37 import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES;
38 import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY;
39 import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY_KEY;
40 import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_KEY;
41 import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
42 import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
43 import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT;
44 import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
45 import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
47 public class DuplicationMeasuresTest {
48 private static final int ROOT_REF = 1;
49 private static final int DIRECTORY_REF = 1234;
50 private static final int FILE_1_REF = 12341;
51 private static final int FILE_2_REF = 12342;
52 private static final int FILE_3_REF = 1261;
53 private static final int FILE_4_REF = 1262;
54 private static final FileAttributes FILE_1_ATTRS = mock(FileAttributes.class);
55 private static final FileAttributes FILE_2_ATTRS = mock(FileAttributes.class);
56 private static final FileAttributes FILE_3_ATTRS = mock(FileAttributes.class);
57 private static final FileAttributes FILE_4_ATTRS = mock(FileAttributes.class);
59 private static final String SOME_FILE_KEY = "some file key";
62 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
64 builder(PROJECT, ROOT_REF)
66 builder(DIRECTORY, DIRECTORY_REF)
68 builder(FILE, FILE_1_REF).setFileAttributes(FILE_1_ATTRS).build(),
69 builder(FILE, FILE_2_REF).setFileAttributes(FILE_2_ATTRS).build())
71 builder(FILE, FILE_3_REF).setFileAttributes(FILE_3_ATTRS).build(),
72 builder(FILE, FILE_4_REF).setFileAttributes(FILE_4_ATTRS).build())
75 public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
76 .add(DUPLICATED_BLOCKS)
77 .add(DUPLICATED_FILES)
78 .add(DUPLICATED_LINES)
79 .add(DUPLICATED_LINES_DENSITY);
81 public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
83 public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);
85 private DuplicationMeasures underTest = new DuplicationMeasures(treeRootHolder, metricRepository, measureRepository, duplicationRepository);
88 public void compute_duplicated_blocks_one_for_original_one_for_each_InnerDuplicate() {
89 TextBlock original = new TextBlock(1, 1);
90 duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(2, 2), new TextBlock(3, 3), new TextBlock(2, 3));
94 assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 4);
98 public void compute_duplicated_blocks_does_not_count_blocks_only_once_it_assumes_consistency_from_duplication_data() {
99 duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 1), new TextBlock(3, 3));
100 duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(2, 2), new TextBlock(3, 3));
104 assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 4);
108 public void compute_duplicated_blocks_one_for_original_and_ignores_InProjectDuplicate() {
109 duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 1), FILE_2_REF, new TextBlock(2, 2));
113 assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 1);
117 public void compute_duplicated_blocks_one_for_original_and_ignores_CrossProjectDuplicate() {
118 duplicationRepository.addCrossProjectDuplication(FILE_1_REF, new TextBlock(1, 1), SOME_FILE_KEY, new TextBlock(2, 2));
122 assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 1);
126 public void compute_and_aggregate_duplicated_blocks_from_single_duplication() {
127 addDuplicatedBlock(FILE_1_REF, 10);
128 addDuplicatedBlock(FILE_2_REF, 40);
129 addDuplicatedBlock(FILE_4_REF, 5);
133 assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 10);
134 assertRawMeasureValue(FILE_2_REF, DUPLICATED_BLOCKS_KEY, 40);
135 assertRawMeasureValue(FILE_3_REF, DUPLICATED_BLOCKS_KEY, 0);
136 assertRawMeasureValue(FILE_4_REF, DUPLICATED_BLOCKS_KEY, 5);
137 assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_BLOCKS_KEY, 50);
138 assertRawMeasureValue(ROOT_REF, DUPLICATED_BLOCKS_KEY, 55);
142 public void compute_and_aggregate_duplicated_blocks_to_zero_when_no_duplication() {
145 assertComputedAndAggregatedToZeroInt(DUPLICATED_BLOCKS_KEY);
149 public void compute_duplicated_lines_counts_lines_from_original_and_InnerDuplicate_of_a_single_line() {
150 TextBlock original = new TextBlock(1, 1);
151 duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(2, 2));
155 assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 2);
159 public void compute_duplicated_lines_counts_lines_from_original_and_ignores_InProjectDuplicate() {
160 TextBlock original = new TextBlock(1, 1);
161 duplicationRepository.addDuplication(FILE_1_REF, original, FILE_2_REF, new TextBlock(2, 2));
165 assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 1);
169 public void compute_duplicated_lines_counts_lines_from_original_and_ignores_CrossProjectDuplicate() {
170 TextBlock original = new TextBlock(1, 1);
171 duplicationRepository.addCrossProjectDuplication(FILE_1_REF, original, SOME_FILE_KEY, new TextBlock(2, 2));
175 assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 1);
179 public void compute_duplicated_lines_counts_lines_from_original_and_InnerDuplicate() {
180 TextBlock original = new TextBlock(1, 5);
181 duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(10, 11));
185 assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 7);
189 public void compute_duplicated_lines_counts_lines_from_original_and_InnerDuplicate_only_once() {
190 TextBlock original = new TextBlock(1, 12);
191 duplicationRepository.addDuplication(FILE_1_REF, original, new TextBlock(10, 11), new TextBlock(11, 15));
192 duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(2, 2), new TextBlock(96, 96));
196 assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 16);
200 public void compute_and_aggregate_duplicated_files() {
201 addDuplicatedBlock(FILE_1_REF, 2);
202 addDuplicatedBlock(FILE_3_REF, 10);
203 addDuplicatedBlock(FILE_4_REF, 50);
207 assertRawMeasureValue(FILE_1_REF, DUPLICATED_FILES_KEY, 1);
208 assertRawMeasureValue(FILE_2_REF, DUPLICATED_FILES_KEY, 0);
209 assertRawMeasureValue(FILE_3_REF, DUPLICATED_FILES_KEY, 1);
210 assertRawMeasureValue(FILE_4_REF, DUPLICATED_FILES_KEY, 1);
211 assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_FILES_KEY, 1);
212 assertRawMeasureValue(ROOT_REF, DUPLICATED_FILES_KEY, 3);
216 public void compute_and_aggregate_zero_duplicated_files_when_no_duplication_data() {
219 assertComputedAndAggregatedToZeroInt(DUPLICATED_FILES_KEY);
223 public void compute_and_aggregate_duplicated_lines() {
224 addDuplicatedBlock(FILE_1_REF, 10);
225 addDuplicatedBlock(FILE_2_REF, 9);
226 addDuplicatedBlock(FILE_4_REF, 7);
230 assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_KEY, 10);
231 assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_KEY, 9);
232 assertRawMeasureValue(FILE_3_REF, DUPLICATED_LINES_KEY, 0);
233 assertRawMeasureValue(FILE_4_REF, DUPLICATED_LINES_KEY, 7);
234 assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_KEY, 19);
235 assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_KEY, 26);
239 public void compute_and_aggregate_zero_duplicated_line_when_no_duplication() {
242 assertComputedAndAggregatedToZeroInt(DUPLICATED_LINES_KEY);
246 public void compute_and_aggregate_duplicated_lines_density_using_lines() {
247 addDuplicatedBlock(FILE_1_REF, 2);
248 addDuplicatedBlock(FILE_2_REF, 3);
250 when(FILE_1_ATTRS.getLines()).thenReturn(10);
251 when(FILE_2_ATTRS.getLines()).thenReturn(40);
255 assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 20d);
256 assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_DENSITY_KEY, 7.5d);
257 assertNoRawMeasure(FILE_3_REF, DUPLICATED_LINES_DENSITY_KEY);
258 assertNoRawMeasure(FILE_4_REF, DUPLICATED_LINES_DENSITY_KEY);
259 assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
260 assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_DENSITY_KEY, 10d);
264 public void compute_zero_percent_duplicated_lines_density_when_there_is_no_duplication() {
265 when(FILE_1_ATTRS.getLines()).thenReturn(10);
266 when(FILE_2_ATTRS.getLines()).thenReturn(40);
270 assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
271 assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
272 assertNoRawMeasure(FILE_3_REF, DUPLICATED_LINES_DENSITY_KEY);
273 assertNoRawMeasure(FILE_4_REF, DUPLICATED_LINES_DENSITY_KEY);
274 assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
275 assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_DENSITY_KEY, 0d);
279 public void not_compute_duplicated_lines_density_when_lines_is_zero() {
280 when(FILE_1_ATTRS.getLines()).thenReturn(0);
281 when(FILE_2_ATTRS.getLines()).thenReturn(0);
283 assertNoRawMeasures(DUPLICATED_LINES_DENSITY_KEY);
287 public void compute_100_percent_duplicated_lines_density() {
288 addDuplicatedBlock(FILE_1_REF, 2);
289 addDuplicatedBlock(FILE_2_REF, 3);
291 when(FILE_1_ATTRS.getLines()).thenReturn(2);
292 when(FILE_2_ATTRS.getLines()).thenReturn(3);
296 assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
297 assertRawMeasureValue(FILE_2_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
298 assertNoRawMeasure(FILE_3_REF, DUPLICATED_LINES_DENSITY_KEY);
299 assertNoRawMeasure(FILE_4_REF, DUPLICATED_LINES_DENSITY_KEY);
300 assertRawMeasureValue(DIRECTORY_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
301 assertRawMeasureValue(ROOT_REF, DUPLICATED_LINES_DENSITY_KEY, 100d);
305 * Adds duplication blocks of a single line (each line is specific to its block).
306 * This is a very simple use case, convenient for unit tests but more realistic and complex use cases must be tested separately.
308 private void addDuplicatedBlock(int fileRef, int blockCount) {
309 checkArgument(blockCount > 1, "BlockCount can not be less than 2");
310 TextBlock original = new TextBlock(1, 1);
311 TextBlock[] duplicates = new TextBlock[blockCount - 1];
312 for (int i = 10; i < blockCount + 9; i++) {
313 duplicates[i - 10] = new TextBlock(i, i);
315 duplicationRepository.addDuplication(fileRef, original, duplicates);
318 private void addRawMeasure(int componentRef, String metricKey, int value) {
319 measureRepository.addRawMeasure(componentRef, metricKey, newMeasureBuilder().create(value));
322 private void assertNoRawMeasures(String metricKey) {
323 assertThat(measureRepository.getAddedRawMeasures(FILE_1_REF).get(metricKey)).isEmpty();
324 assertThat(measureRepository.getAddedRawMeasures(FILE_2_REF).get(metricKey)).isEmpty();
325 assertThat(measureRepository.getAddedRawMeasures(DIRECTORY_REF).get(metricKey)).isEmpty();
326 assertThat(measureRepository.getAddedRawMeasures(ROOT_REF).get(metricKey)).isEmpty();
329 private void assertNoRawMeasure(int componentRef, String metricKey) {
330 assertThat(measureRepository.getAddedRawMeasure(componentRef, metricKey)).isNotPresent();
333 private void assertRawMeasureValue(int componentRef, String metricKey, int value) {
334 assertThat(measureRepository.getAddedRawMeasure(componentRef, metricKey).get().getIntValue()).isEqualTo(value);
337 private void assertRawMeasureValue(int componentRef, String metricKey, double value) {
338 assertThat(measureRepository.getAddedRawMeasure(componentRef, metricKey).get().getDoubleValue()).isEqualTo(value);
341 private void assertComputedAndAggregatedToZeroInt(String metricKey) {
342 assertRawMeasureValue(FILE_1_REF, metricKey, 0);
343 assertRawMeasureValue(FILE_2_REF, metricKey, 0);
344 assertRawMeasureValue(FILE_3_REF, metricKey, 0);
345 assertRawMeasureValue(FILE_4_REF, metricKey, 0);
346 assertRawMeasureValue(DIRECTORY_REF, metricKey, 0);
347 assertRawMeasureValue(ROOT_REF, metricKey, 0);