3 * Copyright (C) 2009-2017 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.server.computation.task.projectanalysis.step;
22 import java.util.Arrays;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.junit.rules.ExpectedException;
26 import org.sonar.scanner.protocol.output.ScannerReport;
27 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
28 import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
29 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
30 import org.sonar.server.computation.task.projectanalysis.component.Component;
31 import org.sonar.server.computation.task.projectanalysis.component.VisitException;
32 import org.sonar.server.computation.task.projectanalysis.duplication.DetailedTextBlock;
33 import org.sonar.server.computation.task.projectanalysis.duplication.Duplicate;
34 import org.sonar.server.computation.task.projectanalysis.duplication.Duplication;
35 import org.sonar.server.computation.task.projectanalysis.duplication.DuplicationRepositoryRule;
36 import org.sonar.server.computation.task.projectanalysis.duplication.InProjectDuplicate;
37 import org.sonar.server.computation.task.projectanalysis.duplication.InnerDuplicate;
38 import org.sonar.server.computation.task.projectanalysis.duplication.TextBlock;
40 import static org.assertj.core.api.Assertions.assertThat;
41 import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE;
42 import static org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT;
43 import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
44 import static org.sonar.test.ExceptionCauseMatcher.hasType;
46 public class LoadDuplicationsFromReportStepTest {
47 private static final int LINE = 2;
48 private static final int OTHER_LINE = 300;
49 private static final int ROOT_REF = 1;
50 private static final int FILE_1_REF = 11;
51 private static final int FILE_2_REF = 12;
54 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule().setRoot(
55 builder(PROJECT, ROOT_REF)
57 builder(FILE, FILE_1_REF).build(),
58 builder(FILE, FILE_2_REF).build()
63 public BatchReportReaderRule reportReader = new BatchReportReaderRule();
65 public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);
67 public ExpectedException expectedException = ExpectedException.none();
69 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
71 private LoadDuplicationsFromReportStep underTest = new LoadDuplicationsFromReportStep(treeRootHolder, reportReader, duplicationRepository, analysisMetadataHolder);
74 public void verify_description() {
75 assertThat(underTest.getDescription()).isEqualTo("Load inner file and in project duplications");
79 public void skip_if_incremental_analysis() {
80 analysisMetadataHolder.setIncrementalAnalysis(true);
81 reportReader.putDuplications(FILE_2_REF, createDuplication(singleLineTextRange(LINE), createInnerDuplicate(LINE + 1)));
85 assertNoDuplication(FILE_2_REF);
89 public void loads_no_duplications_if_reader_has_no_duplication() {
90 analysisMetadataHolder.setIncrementalAnalysis(false);
93 assertNoDuplication(FILE_1_REF);
97 public void loads_duplication_without_otherFileRef_as_inner_duplication() {
98 analysisMetadataHolder.setIncrementalAnalysis(false);
99 reportReader.putDuplications(FILE_2_REF, createDuplication(singleLineTextRange(LINE), createInnerDuplicate(LINE + 1)));
103 assertNoDuplication(FILE_1_REF);
104 assertDuplications(FILE_2_REF, singleLineDetailedTextBlock(1, LINE), new InnerDuplicate(singleLineTextBlock(LINE + 1)));
108 public void loads_duplication_with_otherFileRef_as_inProject_duplication() {
109 analysisMetadataHolder.setIncrementalAnalysis(false);
110 reportReader.putDuplications(FILE_1_REF, createDuplication(singleLineTextRange(LINE), createInProjectDuplicate(FILE_2_REF, LINE + 1)));
114 assertDuplications(FILE_1_REF, singleLineDetailedTextBlock(1, LINE), new InProjectDuplicate(treeRootHolder.getComponentByRef(FILE_2_REF), singleLineTextBlock(LINE + 1)));
115 assertNoDuplication(FILE_2_REF);
119 public void loads_multiple_duplications_with_multiple_duplicates() {
120 analysisMetadataHolder.setIncrementalAnalysis(false);
121 reportReader.putDuplications(
124 singleLineTextRange(LINE),
125 createInnerDuplicate(LINE + 1), createInnerDuplicate(LINE + 2), createInProjectDuplicate(FILE_1_REF, LINE), createInProjectDuplicate(FILE_1_REF, LINE + 10)),
127 singleLineTextRange(OTHER_LINE),
128 createInProjectDuplicate(FILE_1_REF, OTHER_LINE)),
130 singleLineTextRange(OTHER_LINE + 80),
131 createInnerDuplicate(LINE), createInnerDuplicate(LINE + 10))
136 Component file1Component = treeRootHolder.getComponentByRef(FILE_1_REF);
137 assertThat(duplicationRepository.getDuplications(FILE_2_REF)).containsOnly(
139 singleLineDetailedTextBlock(1, LINE),
140 new InnerDuplicate(singleLineTextBlock(LINE + 1)), new InnerDuplicate(singleLineTextBlock(LINE + 2)), new InProjectDuplicate(file1Component, singleLineTextBlock(LINE)),
141 new InProjectDuplicate(file1Component, singleLineTextBlock(LINE + 10))),
143 singleLineDetailedTextBlock(2, OTHER_LINE),
144 new InProjectDuplicate(file1Component, singleLineTextBlock(OTHER_LINE))
147 singleLineDetailedTextBlock(3, OTHER_LINE + 80),
148 new InnerDuplicate(singleLineTextBlock(LINE)), new InnerDuplicate(singleLineTextBlock(LINE + 10))
154 public void loads_never_consider_originals_from_batch_on_same_lines_as_the_equals() {
155 analysisMetadataHolder.setIncrementalAnalysis(false);
156 reportReader.putDuplications(
159 singleLineTextRange(LINE),
160 createInnerDuplicate(LINE + 1), createInnerDuplicate(LINE + 2), createInProjectDuplicate(FILE_1_REF, LINE + 2)),
162 singleLineTextRange(LINE),
163 createInnerDuplicate(LINE + 2), createInnerDuplicate(LINE + 3), createInProjectDuplicate(FILE_1_REF, LINE + 2))
168 Component file1Component = treeRootHolder.getComponentByRef(FILE_1_REF);
169 assertThat(duplicationRepository.getDuplications(FILE_2_REF)).containsOnly(
171 singleLineDetailedTextBlock(1, LINE),
172 new InnerDuplicate(singleLineTextBlock(LINE + 1)), new InnerDuplicate(singleLineTextBlock(LINE + 2)),
173 new InProjectDuplicate(file1Component, singleLineTextBlock(LINE + 2))
176 singleLineDetailedTextBlock(2, LINE),
177 new InnerDuplicate(singleLineTextBlock(LINE + 2)), new InnerDuplicate(singleLineTextBlock(LINE + 3)),
178 new InProjectDuplicate(file1Component, singleLineTextBlock(LINE + 2))
184 public void loads_duplication_with_otherFileRef_throws_IAE_if_component_does_not_exist() {
185 analysisMetadataHolder.setIncrementalAnalysis(false);
187 reportReader.putDuplications(FILE_1_REF, createDuplication(singleLineTextRange(line), createInProjectDuplicate(666, line + 1)));
189 expectedException.expect(VisitException.class);
190 expectedException.expectCause(hasType(IllegalArgumentException.class).andMessage("Component with ref '666' can't be found"));
196 public void loads_duplication_with_otherFileRef_throws_IAE_if_references_itself() {
197 analysisMetadataHolder.setIncrementalAnalysis(false);
199 reportReader.putDuplications(FILE_1_REF, createDuplication(singleLineTextRange(line), createInProjectDuplicate(FILE_1_REF, line + 1)));
201 expectedException.expect(VisitException.class);
202 expectedException.expectCause(hasType(IllegalArgumentException.class).andMessage("file and otherFile references can not be the same"));
207 private void assertDuplications(int fileRef, TextBlock original, Duplicate... duplicates) {
208 assertThat(duplicationRepository.getDuplications(fileRef)).containsExactly(duplication(original, duplicates));
211 private static Duplication duplication(TextBlock original, Duplicate... duplicates) {
212 return new Duplication(original, Arrays.asList(duplicates));
215 private TextBlock singleLineTextBlock(int line) {
216 return new TextBlock(line, line);
219 private DetailedTextBlock singleLineDetailedTextBlock(int id, int line) {
220 return new DetailedTextBlock(id, line, line);
223 private static ScannerReport.Duplication createDuplication(ScannerReport.TextRange original, ScannerReport.Duplicate... duplicates) {
224 ScannerReport.Duplication.Builder builder = ScannerReport.Duplication.newBuilder()
225 .setOriginPosition(original);
226 for (ScannerReport.Duplicate duplicate : duplicates) {
227 builder.addDuplicate(duplicate);
229 return builder.build();
232 private static ScannerReport.Duplicate createInnerDuplicate(int line) {
233 return ScannerReport.Duplicate.newBuilder()
234 .setRange(singleLineTextRange(line))
238 private static ScannerReport.Duplicate createInProjectDuplicate(int componentRef, int line) {
239 return ScannerReport.Duplicate.newBuilder()
240 .setOtherFileRef(componentRef)
241 .setRange(singleLineTextRange(line))
245 private static ScannerReport.TextRange singleLineTextRange(int line) {
246 return ScannerReport.TextRange.newBuilder()
252 private void assertNoDuplication(int fileRef) {
253 assertThat(duplicationRepository.getDuplications(fileRef)).isEmpty();