Browse Source

SONAR-12188 Density of duplications is calculated with number of lines of test files

tags/7.8
Duarte Meneses 5 years ago
parent
commit
9155f18ee4

+ 7
- 7
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationMeasures.java View File

@@ -37,7 +37,6 @@ import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
import org.sonar.ce.task.projectanalysis.metric.MetricRepository;

import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Iterables.isEmpty;
import static java.util.Objects.requireNonNull;
import static org.sonar.api.measures.CoreMetrics.DUPLICATED_BLOCKS_KEY;
@@ -88,10 +87,6 @@ public class DuplicationMeasures {
protected int dupLineCount = 0;
protected int lineCount = 0;

protected DuplicationCounter() {
this(null);
}

private DuplicationCounter(@Nullable DuplicationRepository duplicationRepository) {
this.duplicationRepository = duplicationRepository;
}
@@ -107,7 +102,7 @@ public class DuplicationMeasures {
@Override
public void initialize(CounterInitializationContext context) {
Component leaf = context.getLeaf();
if (leaf.getType() == Component.Type.FILE) {
if (leaf.getType() == Component.Type.FILE && !leaf.getFileAttributes().isUnitTest()) {
initializeForFile(leaf);
} else if (leaf.getType() == Component.Type.PROJECT_VIEW) {
initializeForProjectView(context);
@@ -129,7 +124,12 @@ public class DuplicationMeasures {
for (Duplication duplication : duplications) {
blocks++;
addLines(duplication.getOriginal(), duplicatedLineNumbers);
for (InnerDuplicate innerDuplicate : from(duplication.getDuplicates()).filter(InnerDuplicate.class)) {
InnerDuplicate[] innerDuplicates = duplication.getDuplicates().stream()
.filter(x -> x instanceof InnerDuplicate)
.map(d -> (InnerDuplicate) d)
.toArray(InnerDuplicate[]::new);

for (InnerDuplicate innerDuplicate : innerDuplicates) {
blocks++;
addLines(innerDuplicate.getTextBlock(), duplicatedLineNumbers);
}

+ 27
- 2
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationMeasuresTest.java View File

@@ -19,6 +19,7 @@
*/
package org.sonar.ce.task.projectanalysis.duplication;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.ce.task.projectanalysis.component.FileAttributes;
@@ -51,10 +52,13 @@ public class DuplicationMeasuresTest {
private static final int FILE_2_REF = 12342;
private static final int FILE_3_REF = 1261;
private static final int FILE_4_REF = 1262;
private static final int FILE_5_REF = 1263;

private static final FileAttributes FILE_1_ATTRS = mock(FileAttributes.class);
private static final FileAttributes FILE_2_ATTRS = mock(FileAttributes.class);
private static final FileAttributes FILE_3_ATTRS = mock(FileAttributes.class);
private static final FileAttributes FILE_4_ATTRS = mock(FileAttributes.class);
private static final FileAttributes FILE_5_ATTRS = mock(FileAttributes.class);

private static final String SOME_FILE_KEY = "some file key";

@@ -69,7 +73,8 @@ public class DuplicationMeasuresTest {
builder(FILE, FILE_2_REF).setFileAttributes(FILE_2_ATTRS).build())
.build(),
builder(FILE, FILE_3_REF).setFileAttributes(FILE_3_ATTRS).build(),
builder(FILE, FILE_4_REF).setFileAttributes(FILE_4_ATTRS).build())
builder(FILE, FILE_4_REF).setFileAttributes(FILE_4_ATTRS).build(),
builder(FILE, FILE_5_REF).setFileAttributes(FILE_5_ATTRS).build())
.build());
@Rule
public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
@@ -84,6 +89,11 @@ public class DuplicationMeasuresTest {

private DuplicationMeasures underTest = new DuplicationMeasures(treeRootHolder, metricRepository, measureRepository, duplicationRepository);

@Before
public void before() {
when(FILE_5_ATTRS.isUnitTest()).thenReturn(true);
}

@Test
public void compute_duplicated_blocks_one_for_original_one_for_each_InnerDuplicate() {
TextBlock original = new TextBlock(1, 1);
@@ -94,6 +104,18 @@ public class DuplicationMeasuresTest {
assertRawMeasureValue(FILE_1_REF, DUPLICATED_BLOCKS_KEY, 4);
}

@Test
public void dont_compute_duplicated_blocks_for_test_files() {
duplicationRepository.addDuplication(FILE_5_REF, new TextBlock(1, 1), new TextBlock(3, 3));
duplicationRepository.addDuplication(FILE_5_REF, new TextBlock(2, 2), new TextBlock(3, 3));

underTest.execute();

assertRawMeasureValue(FILE_5_REF, DUPLICATED_BLOCKS_KEY, 0);
assertRawMeasureValue(FILE_5_REF, DUPLICATED_FILES_KEY, 0);

}

@Test
public void compute_duplicated_blocks_does_not_count_blocks_only_once_it_assumes_consistency_from_duplication_data() {
duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 1), new TextBlock(3, 3));
@@ -250,6 +272,9 @@ public class DuplicationMeasuresTest {
when(FILE_1_ATTRS.getLines()).thenReturn(10);
when(FILE_2_ATTRS.getLines()).thenReturn(40);

// this should have no effect as it's a test file
when(FILE_5_ATTRS.getLines()).thenReturn(1_000_000);

underTest.execute();

assertRawMeasureValue(FILE_1_REF, DUPLICATED_LINES_DENSITY_KEY, 20d);
@@ -276,7 +301,7 @@ public class DuplicationMeasuresTest {
}

@Test
public void not_compute_duplicated_lines_density_when_lines_is_zero() {
public void dont_compute_duplicated_lines_density_when_lines_is_zero() {
when(FILE_1_ATTRS.getLines()).thenReturn(0);
when(FILE_2_ATTRS.getLines()).thenReturn(0);
underTest.execute();

+ 18
- 7
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java View File

@@ -27,20 +27,23 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.cpd.NewCpdTokens;
import org.sonar.api.batch.sensor.internal.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;

public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens {
private static final Logger LOG = Loggers.get(DefaultCpdTokens.class);
private final List<TokensLine> result = new ArrayList<>();
private InputFile inputFile;
private DefaultInputFile inputFile;
private int startLine = Integer.MIN_VALUE;
private int startIndex = 0;
private int currentIndex = 0;
private StringBuilder sb = new StringBuilder();
private TextRange lastRange;
private boolean loggedTestCpdWarning = false;

public DefaultCpdTokens(SensorStorage storage) {
super(storage);
@@ -48,7 +51,7 @@ public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens {

@Override
public DefaultCpdTokens onFile(InputFile inputFile) {
this.inputFile = requireNonNull(inputFile, "file can't be null");
this.inputFile = (DefaultInputFile) requireNonNull(inputFile, "file can't be null");
return this;
}

@@ -79,8 +82,6 @@ public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens {
checkState(lastRange == null || lastRange.end().compareTo(range.start()) <= 0,
"Tokens of file %s should be provided in order.\nPrevious token: %s\nLast token: %s", inputFile, lastRange, range);

String value = image;

int line = range.start().line();
if (line != startLine) {
addNewTokensLine(result, startIndex, currentIndex, startLine, sb);
@@ -88,14 +89,24 @@ public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens {
startLine = line;
}
currentIndex++;
sb.append(value);
sb.append(image);
lastRange = range;

return this;
}

private boolean isExcludedForDuplication() {
return ((DefaultInputFile) inputFile).isExcludedForDuplication();
if (inputFile.isExcludedForDuplication()) {
return true;
}
if (inputFile.type() == InputFile.Type.TEST) {
if (!loggedTestCpdWarning) {
LOG.warn("Duplication reported for '{}' will be ignored because it's a test file.", inputFile);
loggedTestCpdWarning = true;
}
return true;
}
return false;
}

public List<TokensLine> getTokenLines() {

+ 21
- 4
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokensTest.java View File

@@ -20,6 +20,7 @@
package org.sonar.api.batch.sensor.cpd.internal;

import org.junit.Test;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.sensor.internal.SensorStorage;
@@ -32,6 +33,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;

public class DefaultCpdTokensTest {
private final SensorStorage sensorStorage = mock(SensorStorage.class);

private final DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.java")
.setLines(2)
@@ -42,7 +44,6 @@ public class DefaultCpdTokensTest {

@Test
public void save_no_tokens() {
SensorStorage sensorStorage = mock(SensorStorage.class);
DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
.onFile(inputFile);

@@ -55,7 +56,6 @@ public class DefaultCpdTokensTest {

@Test
public void save_one_token() {
SensorStorage sensorStorage = mock(SensorStorage.class);
DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
.onFile(inputFile)
.addToken(inputFile.newRange(1, 2, 1, 5), "foo");
@@ -69,7 +69,6 @@ public class DefaultCpdTokensTest {

@Test
public void handle_exclusions() {
SensorStorage sensorStorage = mock(SensorStorage.class);
inputFile.setExcludedForDuplication(true);
DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
.onFile(inputFile)
@@ -82,9 +81,27 @@ public class DefaultCpdTokensTest {
assertThat(tokens.getTokenLines()).isEmpty();
}

@Test
public void dont_save_for_test_files() {
DefaultInputFile testInputFile = new TestInputFileBuilder("foo", "src/Foo.java")
.setLines(2)
.setOriginalLineStartOffsets(new int[] {0, 50})
.setOriginalLineEndOffsets(new int[] {49, 100})
.setLastValidOffset(101)
.setType(InputFile.Type.TEST)
.build();

DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
.onFile(testInputFile)
.addToken(testInputFile.newRange(1, 2, 1, 5), "foo");

tokens.save();
verifyZeroInteractions(sensorStorage);
assertThat(tokens.getTokenLines()).isEmpty();
}

@Test
public void save_many_tokens() {
SensorStorage sensorStorage = mock(SensorStorage.class);
DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
.onFile(inputFile)
.addToken(inputFile.newRange(1, 2, 1, 5), "foo")

Loading…
Cancel
Save