]> source.dussan.org Git - sonarqube.git/commitdiff
Fix quality flaws
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 12 Nov 2015 14:49:16 +0000 (15:49 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 12 Nov 2015 14:49:25 +0000 (15:49 +0100)
server/sonar-server/src/main/java/org/sonar/server/computation/snapshot/package-info.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadCrossProjectDuplicationsRepositoryStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistCrossProjectDuplicationIndexStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/util/package-info.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadCrossProjectDuplicationsRepositoryStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistCrossProjectDuplicationIndexStepTest.java

diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/snapshot/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/snapshot/package-info.java
new file mode 100644 (file)
index 0000000..b9a86bd
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.computation.snapshot;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
index 689e58b9b7c18c3b77d741e033e2afbc757b0875..03bafb3c30a5632dad4a40b82946009572345761 100644 (file)
 package org.sonar.server.computation.step;
 
 import com.google.common.base.Function;
+
 import java.util.Collection;
 import java.util.List;
 import javax.annotation.Nonnull;
+
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.batch.protocol.output.BatchReport.CpdTextBlock;
@@ -34,11 +36,7 @@ import org.sonar.duplications.block.Block;
 import org.sonar.duplications.block.ByteArray;
 import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
 import org.sonar.server.computation.batch.BatchReportReader;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.CrawlerDepthLimit;
-import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.component.*;
 import org.sonar.server.computation.duplication.CrossProjectDuplicationStatusHolder;
 import org.sonar.server.computation.duplication.IntegrateCrossProjectDuplications;
 import org.sonar.server.computation.snapshot.Snapshot;
@@ -96,27 +94,23 @@ public class LoadCrossProjectDuplicationsRepositoryStep implements ComputationSt
 
     @Override
     public void visitFile(Component file) {
-      visitComponent(file);
-    }
-
-    private void visitComponent(Component component) {
-      List<CpdTextBlock> cpdTextBlocks = newArrayList(reportReader.readCpdTextBlocks(component.getReportAttributes().getRef()));
-      LOGGER.trace("Found {} cpd blocks on file {}", cpdTextBlocks.size(), component.getKey());
+      List<CpdTextBlock> cpdTextBlocks = newArrayList(reportReader.readCpdTextBlocks(file.getReportAttributes().getRef()));
+      LOGGER.trace("Found {} cpd blocks on file {}", cpdTextBlocks.size(), file.getKey());
       if (cpdTextBlocks.isEmpty()) {
         return;
       }
 
       Collection<String> hashes = from(cpdTextBlocks).transform(CpdTextBlockToHash.INSTANCE).toList();
-      List<DuplicationUnitDto> dtos = selectDuplicates(component, hashes);
+      List<DuplicationUnitDto> dtos = selectDuplicates(file, hashes);
       if (dtos.isEmpty()) {
         return;
       }
 
       Collection<Block> duplicatedBlocks = from(dtos).transform(DtoToBlock.INSTANCE).toList();
-      Collection<Block> originBlocks = from(cpdTextBlocks).transform(new CpdTextBlockToBlock(component.getKey())).toList();
-      LOGGER.trace("Found {} duplicated cpd blocks on file {}", duplicatedBlocks.size(), component.getKey());
+      Collection<Block> originBlocks = from(cpdTextBlocks).transform(new CpdTextBlockToBlock(file.getKey())).toList();
+      LOGGER.trace("Found {} duplicated cpd blocks on file {}", duplicatedBlocks.size(), file.getKey());
 
-      integrateCrossProjectDuplications.computeCpd(component, originBlocks, duplicatedBlocks);
+      integrateCrossProjectDuplications.computeCpd(file, originBlocks, duplicatedBlocks);
     }
 
     private List<DuplicationUnitDto> selectDuplicates(Component file, Collection<String> hashes) {
@@ -145,7 +139,7 @@ public class LoadCrossProjectDuplicationsRepositoryStep implements ComputationSt
 
     @Override
     public Block apply(@Nonnull DuplicationUnitDto dto) {
-      // Not that the dto doesn't contains start/end token indexes
+      // Note that the dto doesn't contains start/end token indexes
       return Block.builder()
         .setResourceId(dto.getComponentKey())
         .setBlockHash(new ByteArray(dto.getHash()))
@@ -165,13 +159,15 @@ public class LoadCrossProjectDuplicationsRepositoryStep implements ComputationSt
 
     @Override
     public Block apply(@Nonnull CpdTextBlock duplicationBlock) {
-      return Block.builder()
+      Block block = Block.builder()
         .setResourceId(fileKey)
         .setBlockHash(new ByteArray(duplicationBlock.getHash()))
-        .setIndexInFile(indexInFile++)
+        .setIndexInFile(indexInFile)
         .setLines(duplicationBlock.getStartLine(), duplicationBlock.getEndLine())
         .setUnit(duplicationBlock.getStartTokenIndex(), duplicationBlock.getEndTokenIndex())
         .build();
+      indexInFile++;
+      return block;
     }
   }
 
index b39174003e30cb579dd6488b8b775cfb263c7a7e..04efbf1db78b7ff52830722801560207f865b3ee 100644 (file)
@@ -26,12 +26,7 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.duplication.DuplicationUnitDto;
 import org.sonar.server.computation.batch.BatchReportReader;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.CrawlerDepthLimit;
-import org.sonar.server.computation.component.DbIdsRepository;
-import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.component.*;
 import org.sonar.server.computation.duplication.CrossProjectDuplicationStatusHolder;
 
 import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
@@ -89,7 +84,8 @@ public class PersistCrossProjectDuplicationIndexStep implements ComputationStep
 
     private void visitComponent(Component component) {
       int indexInFile = 0;
-      try (CloseableIterator<BatchReport.CpdTextBlock> blocks = reportReader.readCpdTextBlocks(component.getReportAttributes().getRef())) {
+      CloseableIterator<BatchReport.CpdTextBlock> blocks = reportReader.readCpdTextBlocks(component.getReportAttributes().getRef());
+      try {
         while (blocks.hasNext()) {
           BatchReport.CpdTextBlock block = blocks.next();
           dbClient.duplicationDao().insert(
@@ -98,11 +94,14 @@ public class PersistCrossProjectDuplicationIndexStep implements ComputationStep
               .setHash(block.getHash())
               .setStartLine(block.getStartLine())
               .setEndLine(block.getEndLine())
-              .setIndexInFile(indexInFile++)
+              .setIndexInFile(indexInFile)
               .setSnapshotId(dbIdsRepository.getSnapshotId(component))
               .setProjectSnapshotId(projectSnapshotId)
             );
+          indexInFile++;
         }
+      } finally {
+        blocks.close();
       }
     }
   }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/util/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/util/package-info.java
new file mode 100644 (file)
index 0000000..942873d
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.computation.util;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
index 737c232b6915be539bcc140689a49435563e4c10..ba4d33c5e47a645d1f23bc05e6ec07fb52f16dcc 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.computation.step;
 
 import java.util.Arrays;
 import java.util.Collections;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -49,10 +50,7 @@ import org.sonar.server.computation.duplication.IntegrateCrossProjectDuplication
 import org.sonar.server.computation.snapshot.Snapshot;
 
 import static java.util.Arrays.asList;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 import static org.sonar.server.computation.component.Component.Type.FILE;
 import static org.sonar.server.computation.component.Component.Type.PROJECT;
 
@@ -115,7 +113,7 @@ public class LoadCrossProjectDuplicationsRepositoryStepTest {
   }
 
   @Test
-  public void call_compute_cpd() throws Exception {
+  public void call_compute_cpd_on_one_duplication() throws Exception {
     when(crossProjectDuplicationStatusHolder.isEnabled()).thenReturn(true);
     analysisMetadataHolder.setBaseProjectSnapshot(baseProjectSnapshot);
 
@@ -168,6 +166,88 @@ public class LoadCrossProjectDuplicationsRepositoryStepTest {
       );
   }
 
+  @Test
+  public void call_compute_cpd_on_many_duplication() throws Exception {
+    when(crossProjectDuplicationStatusHolder.isEnabled()).thenReturn(true);
+    analysisMetadataHolder.setBaseProjectSnapshot(baseProjectSnapshot);
+
+    ComponentDto otherProject = createProject("OTHER_PROJECT_KEY");
+    SnapshotDto otherProjectSnapshot = createProjectSnapshot(otherProject);
+
+    ComponentDto otherFIle = createFile("OTHER_FILE_KEY", otherProject);
+    SnapshotDto otherFileSnapshot = createFileSnapshot(otherFIle, otherProjectSnapshot);
+
+    BatchReport.CpdTextBlock originBlock1 = BatchReport.CpdTextBlock.newBuilder()
+      .setHash("a8998353e96320ec")
+      .setStartLine(30)
+      .setEndLine(45)
+      .setStartTokenIndex(0)
+      .setEndTokenIndex(10)
+      .build();
+    BatchReport.CpdTextBlock originBlock2 = BatchReport.CpdTextBlock.newBuilder()
+      .setHash("b1234353e96320ff")
+      .setStartLine(10)
+      .setEndLine(25)
+      .setStartTokenIndex(5)
+      .setEndTokenIndex(15)
+      .build();
+    batchReportReader.putDuplicationBlocks(FILE_REF, asList(originBlock1, originBlock2));
+
+    DuplicationUnitDto duplicate1 = new DuplicationUnitDto()
+      .setHash(originBlock1.getHash())
+      .setStartLine(40)
+      .setEndLine(55)
+      .setIndexInFile(0)
+      .setProjectSnapshotId(otherProjectSnapshot.getId())
+      .setSnapshotId(otherFileSnapshot.getId());
+
+    DuplicationUnitDto duplicate2 = new DuplicationUnitDto()
+      .setHash(originBlock2.getHash())
+      .setStartLine(20)
+      .setEndLine(35)
+      .setIndexInFile(1)
+      .setProjectSnapshotId(otherProjectSnapshot.getId())
+      .setSnapshotId(otherFileSnapshot.getId());
+    dbClient.duplicationDao().insert(dbSession, duplicate1);
+    dbClient.duplicationDao().insert(dbSession, duplicate2);
+    dbSession.commit();
+
+    underTest.execute();
+
+    verify(integrateCrossProjectDuplications).computeCpd(CURRENT_FILE,
+      Arrays.asList(
+        new Block.Builder()
+          .setResourceId(CURRENT_FILE_KEY)
+          .setBlockHash(new ByteArray(originBlock1.getHash()))
+          .setIndexInFile(0)
+          .setLines(originBlock1.getStartLine(), originBlock1.getEndLine())
+          .setUnit(originBlock1.getStartTokenIndex(), originBlock1.getEndTokenIndex())
+          .build(),
+        new Block.Builder()
+          .setResourceId(CURRENT_FILE_KEY)
+          .setBlockHash(new ByteArray(originBlock2.getHash()))
+          .setIndexInFile(1)
+          .setLines(originBlock2.getStartLine(), originBlock2.getEndLine())
+          .setUnit(originBlock2.getStartTokenIndex(), originBlock2.getEndTokenIndex())
+          .build()
+        ),
+      Arrays.asList(
+        new Block.Builder()
+          .setResourceId(otherFIle.getKey())
+          .setBlockHash(new ByteArray(originBlock1.getHash()))
+          .setIndexInFile(duplicate1.getIndexInFile())
+          .setLines(duplicate1.getStartLine(), duplicate1.getEndLine())
+          .build(),
+        new Block.Builder()
+          .setResourceId(otherFIle.getKey())
+          .setBlockHash(new ByteArray(originBlock2.getHash()))
+          .setIndexInFile(duplicate2.getIndexInFile())
+          .setLines(duplicate2.getStartLine(), duplicate2.getEndLine())
+          .build()
+        )
+      );
+  }
+
   @Test
   public void nothing_to_do_when_cross_project_duplication_is_disabled() throws Exception {
     when(crossProjectDuplicationStatusHolder.isEnabled()).thenReturn(false);
@@ -206,10 +286,8 @@ public class LoadCrossProjectDuplicationsRepositoryStepTest {
 
   @Test
   public void nothing_to_do_when_no_cpd_text_blocks_found() throws Exception {
-    analysisMetadataHolder
-      .setCrossProjectDuplicationEnabled(true)
-      .setBranch(null)
-      .setBaseProjectSnapshot(baseProjectSnapshot);
+    when(crossProjectDuplicationStatusHolder.isEnabled()).thenReturn(true);
+    analysisMetadataHolder.setBaseProjectSnapshot(baseProjectSnapshot);
 
     batchReportReader.putDuplicationBlocks(FILE_REF, Collections.<BatchReport.CpdTextBlock>emptyList());
 
@@ -220,10 +298,8 @@ public class LoadCrossProjectDuplicationsRepositoryStepTest {
 
   @Test
   public void nothing_to_do_when_cpd_text_blocks_exists_but_no_duplicated_found() throws Exception {
-    analysisMetadataHolder
-      .setCrossProjectDuplicationEnabled(true)
-      .setBranch(null)
-      .setBaseProjectSnapshot(baseProjectSnapshot);
+    when(crossProjectDuplicationStatusHolder.isEnabled()).thenReturn(true);
+    analysisMetadataHolder.setBaseProjectSnapshot(baseProjectSnapshot);
 
     BatchReport.CpdTextBlock originBlock = BatchReport.CpdTextBlock.newBuilder()
       .setHash("a8998353e96320ec")
index 40d86ac5c2a6275165787cbaf87850e9845ac62f..9e7160eb0e22f76ddcae9e081a207d97397c83b4 100644 (file)
 
 package org.sonar.server.computation.step;
 
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -82,7 +85,7 @@ public class PersistCrossProjectDuplicationIndexStepTest {
   }
 
   @Test
-  public void persist_cpd_text_blocks() throws Exception {
+  public void persist_cpd_text_block() throws Exception {
     when(crossProjectDuplicationStatusHolder.isEnabled()).thenReturn(true);
     reportReader.putDuplicationBlocks(FILE_REF, singletonList(CPD_TEXT_BLOCK));
 
@@ -98,6 +101,29 @@ public class PersistCrossProjectDuplicationIndexStepTest {
     assertThat(dto.get("projectSnapshotId")).isEqualTo(PROJECT_SNAPSHOT_ID);
   }
 
+  @Test
+  public void persist_many_cpd_text_blocks() throws Exception {
+    when(crossProjectDuplicationStatusHolder.isEnabled()).thenReturn(true);
+    reportReader.putDuplicationBlocks(FILE_REF, Arrays.asList(
+      CPD_TEXT_BLOCK,
+      BatchReport.CpdTextBlock.newBuilder()
+        .setHash("b1234353e96320ff")
+        .setStartLine(20)
+        .setEndLine(15)
+        .build()));
+
+    underTest.execute();
+
+    List<Map<String, Object>> dtos = dbTester.select("select hash as \"hash\", start_line as \"startLine\", end_line as \"endLine\", index_in_file as \"indexInFile\", " +
+      "snapshot_id as \"snapshotId\", project_snapshot_id as \"projectSnapshotId\" from duplications_index");
+    assertThat(dtos).extracting("hash").containsOnly(CPD_TEXT_BLOCK.getHash(), "b1234353e96320ff");
+    assertThat(dtos).extracting("startLine").containsOnly(30L, 20L);
+    assertThat(dtos).extracting("endLine").containsOnly(45L, 15L);
+    assertThat(dtos).extracting("indexInFile").containsOnly(0L, 1L);
+    assertThat(dtos).extracting("snapshotId").containsOnly(FILE_SNAPSHOT_ID);
+    assertThat(dtos).extracting("projectSnapshotId").containsOnly(PROJECT_SNAPSHOT_ID);
+  }
+
   @Test
   public void nothing_to_persist_when_no_cpd_text_blocks_in_report() throws Exception {
     when(crossProjectDuplicationStatusHolder.isEnabled()).thenReturn(true);