]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-12188 Density of duplications is calculated with number of lines of test files
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Thu, 13 Jun 2019 14:59:21 +0000 (09:59 -0500)
committerSonarTech <sonartech@sonarsource.com>
Thu, 13 Jun 2019 18:21:14 +0000 (20:21 +0200)
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationMeasures.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/duplication/DuplicationMeasuresTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokensTest.java

index f29477995f37a10c1c380f388f6c5f532626631f..c2fd3bd4db59dc7941ef255f8a78b7d636c9a28b 100644 (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);
         }
index 0b698b616021a2f93fa7659cbd95090d020d8100..86c8fdfa23982b5830dde28a25cf4797ce0333db 100644 (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();
index a30a4accc76735512767dcc60f934255a97ed6bd..f6907ba68ba58f18dca155fcad870aeab0178feb 100644 (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() {
index 44827ebcebb85963344fcc55428c6ed064ca2265..8320cea7544fc47ddfb900a53ff7b6546744ceb7 100644 (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")