aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-server
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2015-03-24 16:18:10 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2015-03-25 15:20:10 +0100
commitac44823d701c7ae3ea30ea8060c8fe28ca8ee6af (patch)
treea521202e8caac86d174fbf2675ea129c401ccd74 /server/sonar-server
parentc9ce765d410c8924cb7d11b28e42e85078409622 (diff)
downloadsonarqube-ac44823d701c7ae3ea30ea8060c8fe28ca8ee6af.tar.gz
sonarqube-ac44823d701c7ae3ea30ea8060c8fe28ca8ee6af.zip
SONAR-6257 Persist duplication measures in compute
Diffstat (limited to 'server/sonar-server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/batch/GlobalRepositoryAction.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/measure/MetricCache.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStep.java167
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/persistence/MetricDao.java26
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/batch/GlobalRepositoryActionTest.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java7
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest.java335
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java7
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MetricDaoTest.java71
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_referentials.json2
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest/persist_duplication_on_same_file-result.xml11
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest/persist_duplication_on_same_file.xml6
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/measure/persistence/MetricDaoTest/shared.xml29
14 files changed, 611 insertions, 61 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalRepositoryAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalRepositoryAction.java
index ab9c5abe752..ae6a9a06d16 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalRepositoryAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalRepositoryAction.java
@@ -78,14 +78,14 @@ public class GlobalRepositoryAction implements RequestHandler {
}
private void addMetrics(GlobalRepositories ref, DbSession session) {
- for (MetricDto metric : dbClient.metricDao().findEnabled(session)) {
+ for (MetricDto metric : dbClient.metricDao().selectEnabled(session)) {
Boolean optimizedBestValue = metric.isOptimizedBestValue();
ref.addMetric(
new org.sonar.batch.protocol.input.Metric(metric.getId(), metric.getKey(),
metric.getValueType(),
metric.getDescription(),
metric.getDirection(),
- metric.getName(),
+ metric.getKey(),
metric.isQualitative(),
metric.isUserManaged(),
metric.getWorstValue(),
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MetricCache.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MetricCache.java
index a910415c1e0..febaaf9e6a3 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MetricCache.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MetricCache.java
@@ -37,7 +37,7 @@ public class MetricCache {
public MetricCache(DbClient dbClient) {
DbSession dbSession = dbClient.openSession(false);
try {
- List<MetricDto> metricList = dbClient.metricDao().findEnabled(dbSession);
+ List<MetricDto> metricList = dbClient.metricDao().selectEnabled(dbSession);
this.metrics = Maps.uniqueIndex(metricList, new Function<MetricDto, String>() {
@Override
public String apply(MetricDto metric) {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java
index 530fcaad11b..bfba1b718d0 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java
@@ -45,6 +45,7 @@ public class ComputationSteps {
PersistIssuesStep.class,
PersistComponentLinksStep.class,
PersistEventsStep.class,
+ PersistDuplicationMeasuresStep.class,
// Switch snapshot and purge
SwitchSnapshotStep.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStep.java
new file mode 100644
index 00000000000..76bad984a1b
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStep.java
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+package org.sonar.server.computation.step;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.core.component.ComponentKeys;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.core.measure.db.MetricDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.db.DbClient;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+public class PersistDuplicationMeasuresStep implements ComputationStep {
+
+ private final DbClient dbClient;
+
+ public PersistDuplicationMeasuresStep(DbClient dbClient) {
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public String[] supportedProjectQualifiers() {
+ return new String[] {Qualifiers.PROJECT};
+ }
+
+ @Override
+ public void execute(ComputationContext context) {
+ DbSession session = dbClient.openSession(true);
+ try {
+ MetricDto duplicationMetric = dbClient.metricDao().selectByKey(session, CoreMetrics.DUPLICATIONS_DATA_KEY);
+ DuplicationContext duplicationContext = new DuplicationContext(context, duplicationMetric, session);
+ int rootComponentRef = context.getReportMetadata().getRootComponentRef();
+ recursivelyProcessComponent(duplicationContext, null, rootComponentRef);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ private void recursivelyProcessComponent(DuplicationContext duplicationContext, @Nullable Integer parentComponentRef, int componentRef) {
+ BatchReportReader reportReader = duplicationContext.context().getReportReader();
+ BatchReport.Component component = reportReader.readComponent(componentRef);
+ List<BatchReport.Duplication> duplications = reportReader.readComponentDuplications(componentRef);
+ if (!duplications.isEmpty() && parentComponentRef != null) {
+ saveDuplications(duplicationContext, reportReader.readComponent(parentComponentRef), component, duplications);
+ }
+
+ for (Integer childRef : component.getChildRefList()) {
+ recursivelyProcessComponent(duplicationContext, componentRef, childRef);
+ }
+ }
+
+ private void saveDuplications(DuplicationContext duplicationContext, BatchReport.Component parentComponent, BatchReport.Component component,
+ List<BatchReport.Duplication> duplications) {
+
+ String duplicationXml = createXmlDuplications(duplicationContext, parentComponent, component.getPath(), duplications);
+ MeasureDto measureDto = new MeasureDto()
+ .setMetricId(duplicationContext.metric().getId())
+ .setData(duplicationXml)
+ .setComponentId(component.getId())
+ .setSnapshotId(component.getSnapshotId());
+ dbClient.measureDao().insert(duplicationContext.session(), measureDto);
+ }
+
+ private String createXmlDuplications(DuplicationContext duplicationContext, BatchReport.Component parentComponent, String componentPath,
+ Iterable<BatchReport.Duplication> duplications) {
+
+ StringBuilder xml = new StringBuilder();
+ xml.append("<duplications>");
+ for (BatchReport.Duplication duplication : duplications) {
+ xml.append("<g>");
+ appendDuplication(xml, ComponentKeys.createKey(parentComponent.getKey(), componentPath, duplicationContext.context().getReportMetadata().getBranch()),
+ duplication.getOriginBlock());
+ for (BatchReport.DuplicationBlock duplicationBlock : duplication.getDuplicatedByList()) {
+ processDuplicationBlock(duplicationContext, xml, duplicationBlock, parentComponent.getKey(), componentPath);
+ }
+ xml.append("</g>");
+ }
+ xml.append("</duplications>");
+ return xml.toString();
+ }
+
+ private void processDuplicationBlock(DuplicationContext duplicationContext, StringBuilder xml, BatchReport.DuplicationBlock duplicationBlock, String parentComponentKey,
+ String componentPath) {
+
+ if (duplicationBlock.hasComponentKey()) {
+ // componentKey is only set for cross project duplications
+ String crossProjectComponentKey = duplicationBlock.getComponentKey();
+ appendDuplication(xml, crossProjectComponentKey, duplicationBlock);
+ } else {
+ String branch = duplicationContext.context().getReportMetadata().getBranch();
+ if (duplicationBlock.hasOtherComponentRef()) {
+ // Duplication is on a different file
+ BatchReport.Component duplicationComponent = duplicationContext.context().getReportReader().readComponent(duplicationBlock.getOtherComponentRef());
+ appendDuplication(xml, ComponentKeys.createKey(parentComponentKey, duplicationComponent.getPath(), branch), duplicationBlock);
+ } else {
+ // Duplication is on a the same file
+ appendDuplication(xml, ComponentKeys.createKey(parentComponentKey, componentPath, branch), duplicationBlock);
+ }
+ }
+ }
+
+ private static void appendDuplication(StringBuilder xml, String componentKey, BatchReport.DuplicationBlock duplicationBlock) {
+ int length = duplicationBlock.getEndLine() - duplicationBlock.getStartLine();
+ xml.append("<b s=\"").append(duplicationBlock.getStartLine())
+ .append("\" l=\"").append(length)
+ .append("\" r=\"").append(StringEscapeUtils.escapeXml(componentKey))
+ .append("\"/>");
+ }
+
+ private static class DuplicationContext {
+ private DbSession session;
+ private ComputationContext context;
+ private MetricDto duplicationMetric;
+
+ DuplicationContext(ComputationContext context, MetricDto duplicationMetric, DbSession session) {
+ this.context = context;
+ this.duplicationMetric = duplicationMetric;
+ this.session = session;
+ }
+
+ public ComputationContext context() {
+ return context;
+ }
+
+ public MetricDto metric() {
+ return duplicationMetric;
+ }
+
+ public DbSession session() {
+ return session;
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Persist duplications";
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/persistence/MetricDao.java b/server/sonar-server/src/main/java/org/sonar/server/measure/persistence/MetricDao.java
index d561ead931e..ed345eec80d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/persistence/MetricDao.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/persistence/MetricDao.java
@@ -20,34 +20,28 @@
package org.sonar.server.measure.persistence;
-import com.google.common.annotations.VisibleForTesting;
import org.sonar.api.ServerComponent;
-import org.sonar.api.utils.System2;
import org.sonar.core.measure.db.MetricDto;
import org.sonar.core.measure.db.MetricMapper;
import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.BaseDao;
-import java.util.List;
+import javax.annotation.CheckForNull;
-public class MetricDao extends BaseDao<MetricMapper, MetricDto, String> implements ServerComponent, DaoComponent {
+import java.util.List;
- public MetricDao() {
- this(System2.INSTANCE);
- }
+public class MetricDao implements ServerComponent, DaoComponent {
- @VisibleForTesting
- public MetricDao(System2 system) {
- super(MetricMapper.class, system);
+ @CheckForNull
+ public MetricDto selectByKey(DbSession session, String key) {
+ return session.getMapper(MetricMapper.class).selectByKey(key);
}
- @Override
- protected MetricDto doGetNullableByKey(DbSession session, String key) {
- return mapper(session).selectByKey(key);
+ public List<MetricDto> selectEnabled(DbSession session) {
+ return session.getMapper(MetricMapper.class).selectAllEnabled();
}
- public List<MetricDto> findEnabled(DbSession session) {
- return mapper(session).selectAllEnabled();
+ public void insert(DbSession session, MetricDto dto){
+ session.getMapper(MetricMapper.class).insert(dto);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalRepositoryActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalRepositoryActionTest.java
index 30a9ce8eba1..5afe8f54be7 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalRepositoryActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalRepositoryActionTest.java
@@ -70,8 +70,8 @@ public class GlobalRepositoryActionTest {
@Test
public void return_metrics() throws Exception {
- when(metricDao.findEnabled(session)).thenReturn(newArrayList(
- MetricDto.createFor("coverage").setDescription("Coverage by unit tests").setValueType("PERCENT").setQualitative(true)
+ when(metricDao.selectEnabled(session)).thenReturn(newArrayList(
+ new MetricDto().setId(1).setKey("coverage").setDescription("Coverage by unit tests").setValueType("PERCENT").setQualitative(true)
.setWorstValue(0d).setBestValue(100d).setOptimizedBestValue(false).setDirection(1).setEnabled(true)
));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java
index 06f7580a42c..a795572cf34 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java
@@ -45,12 +45,13 @@ public class ComputationStepsTest {
mock(IndexComponentsStep.class),
mock(PersistComponentLinksStep.class),
mock(PersistMeasuresStep.class),
- mock(PersistEventsStep.class)
+ mock(PersistEventsStep.class),
+ mock(PersistDuplicationMeasuresStep.class)
);
- assertThat(registry.orderedSteps()).hasSize(14);
+ assertThat(registry.orderedSteps()).hasSize(15);
assertThat(registry.orderedSteps().get(0)).isInstanceOf(ParseReportStep.class);
- assertThat(registry.orderedSteps().get(13)).isInstanceOf(SendIssueNotificationsStep.class);
+ assertThat(registry.orderedSteps().get(14)).isInstanceOf(SendIssueNotificationsStep.class);
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest.java
new file mode 100644
index 00000000000..5699b186c49
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest.java
@@ -0,0 +1,335 @@
+/*
+ * 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.
+ */
+
+package org.sonar.server.computation.step;
+
+import org.junit.*;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.core.measure.db.MetricDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.measure.persistence.MeasureDao;
+import org.sonar.server.measure.persistence.MetricDao;
+import org.sonar.test.DbTests;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class PersistDuplicationMeasuresStepTest extends BaseStepTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ File reportDir;
+
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
+
+ DbSession session;
+
+ DbClient dbClient;
+
+ PersistDuplicationMeasuresStep sut;
+
+ @Before
+ public void setup() throws Exception {
+ dbTester.truncateTables();
+ session = dbTester.myBatis().openSession(false);
+ dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new MeasureDao(), new MetricDao());
+
+ reportDir = temp.newFolder();
+
+ sut = new PersistDuplicationMeasuresStep(dbClient);
+ }
+
+ @Override
+ protected ComputationStep step() throws IOException {
+ return sut;
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ session.close();
+ }
+
+ @Test
+ public void nothing_to_do_when_no_duplication() throws Exception {
+ saveDuplicationMetric();
+ initReportWithProjectAndFile();
+
+ sut.execute(new ComputationContext(new BatchReportReader(reportDir), ComponentTesting.newProjectDto("PROJECT")));
+
+ assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(0);
+ }
+
+ @Test
+ public void persist_duplications_on_same_file() throws Exception {
+ MetricDto duplicationMetric = saveDuplicationMetric();
+
+ BatchReportWriter writer = initReportWithProjectAndFile();
+
+ BatchReport.Duplication duplication = BatchReport.Duplication.newBuilder()
+ .setOriginBlock(BatchReport.DuplicationBlock.newBuilder()
+ .setOtherComponentRef(2)
+ .setStartLine(1)
+ .setEndLine(5)
+ .build())
+ .addDuplicatedBy(BatchReport.DuplicationBlock.newBuilder()
+ .setOtherComponentRef(2)
+ .setStartLine(6)
+ .setEndLine(10)
+ .build())
+ .build();
+ writer.writeComponentDuplications(2, newArrayList(duplication));
+
+ sut.execute(new ComputationContext(new BatchReportReader(reportDir), ComponentTesting.newProjectDto("PROJECT")));
+
+ assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
+
+ Map<String, Object> dto = dbTester.selectFirst("select snapshot_id as \"snapshotId\", metric_id as \"metricId\", text_value as \"textValue\" from project_measures");
+ assertThat(dto.get("snapshotId")).isEqualTo(11L);
+ assertThat(dto.get("metricId")).isEqualTo(duplicationMetric.getId().longValue());
+ assertThat(dto.get("textValue")).isEqualTo("<duplications><g><b s=\"1\" l=\"4\" r=\"PROJECT_KEY:file\"/><b s=\"6\" l=\"4\" r=\"PROJECT_KEY:file\"/></g></duplications>");
+ }
+
+ @Test
+ public void persist_duplications_on_same_file_linked_on_a_module() throws Exception {
+ saveDuplicationMetric();
+
+ File reportDir = temp.newFolder();
+ BatchReportWriter writer = new BatchReportWriter(reportDir);
+ writer.writeMetadata(BatchReport.Metadata.newBuilder()
+ .setRootComponentRef(1)
+ .setProjectKey("PROJECT_KEY")
+ .setAnalysisDate(150000000L)
+ .build());
+
+ writer.writeComponent(BatchReport.Component.newBuilder()
+ .setRef(1)
+ .setType(Constants.ComponentType.PROJECT)
+ .setUuid("UUID_A")
+ .setKey("PROJECT_KEY")
+ .setSnapshotId(10L)
+ .addChildRef(2)
+ .build());
+ writer.writeComponent(BatchReport.Component.newBuilder()
+ .setRef(2)
+ .setType(Constants.ComponentType.PROJECT)
+ .setUuid("UUID_B")
+ .setKey("MODULE_KEY")
+ .setSnapshotId(11L)
+ .addChildRef(3)
+ .build());
+ writer.writeComponent(BatchReport.Component.newBuilder()
+ .setRef(3)
+ .setType(Constants.ComponentType.FILE)
+ .setUuid("UUID_C")
+ .setSnapshotId(12L)
+ .setPath("file")
+ .build());
+
+ BatchReport.Duplication duplication = BatchReport.Duplication.newBuilder()
+ .setOriginBlock(BatchReport.DuplicationBlock.newBuilder()
+ .setOtherComponentRef(3)
+ .setStartLine(1)
+ .setEndLine(5)
+ .build())
+ .addDuplicatedBy(BatchReport.DuplicationBlock.newBuilder()
+ .setOtherComponentRef(3)
+ .setStartLine(6)
+ .setEndLine(10)
+ .build())
+ .build();
+ writer.writeComponentDuplications(3, newArrayList(duplication));
+
+ sut.execute(new ComputationContext(new BatchReportReader(reportDir), ComponentTesting.newProjectDto("PROJECT")));
+
+ assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
+
+ Map<String, Object> dto = dbTester.selectFirst("select snapshot_id as \"snapshotId\", text_value as \"textValue\" from project_measures");
+ assertThat(dto.get("snapshotId")).isEqualTo(12L);
+ assertThat(dto.get("textValue")).isEqualTo("<duplications><g><b s=\"1\" l=\"4\" r=\"MODULE_KEY:file\"/><b s=\"6\" l=\"4\" r=\"MODULE_KEY:file\"/></g></duplications>");
+ }
+
+ @Test
+ public void persist_duplications_on_same_file_when_a_branch_is_used() throws Exception {
+ saveDuplicationMetric();
+
+ File reportDir = temp.newFolder();
+ BatchReportWriter writer = new BatchReportWriter(reportDir);
+ writer.writeMetadata(BatchReport.Metadata.newBuilder()
+ .setRootComponentRef(1)
+ .setProjectKey("PROJECT_KEY")
+ .setBranch("origin/master")
+ .setAnalysisDate(150000000L)
+ .build());
+
+ writer.writeComponent(BatchReport.Component.newBuilder()
+ .setRef(1)
+ .setType(Constants.ComponentType.PROJECT)
+ .setUuid("UUID_A")
+ .setKey("PROJECT_KEY")
+ .setSnapshotId(10L)
+ .addChildRef(2)
+ .build());
+ writer.writeComponent(BatchReport.Component.newBuilder()
+ .setRef(2)
+ .setType(Constants.ComponentType.FILE)
+ .setUuid("UUID_B")
+ .setSnapshotId(11L)
+ .setPath("file")
+ .build());
+
+ BatchReport.Duplication duplication = BatchReport.Duplication.newBuilder()
+ .setOriginBlock(BatchReport.DuplicationBlock.newBuilder()
+ .setOtherComponentRef(2)
+ .setStartLine(1)
+ .setEndLine(5)
+ .build())
+ .addDuplicatedBy(BatchReport.DuplicationBlock.newBuilder()
+ .setOtherComponentRef(2)
+ .setStartLine(6)
+ .setEndLine(10)
+ .build())
+ .build();
+ writer.writeComponentDuplications(2, newArrayList(duplication));
+
+ sut.execute(new ComputationContext(new BatchReportReader(reportDir), ComponentTesting.newProjectDto("PROJECT")));
+
+ assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
+
+ Map<String, Object> dto = dbTester.selectFirst("select snapshot_id as \"snapshotId\", text_value as \"textValue\" from project_measures");
+ assertThat(dto.get("snapshotId")).isEqualTo(11L);
+ assertThat(dto.get("textValue")).isEqualTo("<duplications><g><b s=\"1\" l=\"4\" r=\"PROJECT_KEY:file:origin/master\"/><b s=\"6\" l=\"4\" r=\"PROJECT_KEY:file:origin/master\"/></g></duplications>");
+ }
+
+ @Test
+ public void persist_duplications_on_different_files() throws Exception {
+ saveDuplicationMetric();
+ BatchReportWriter writer = initReportWithProjectAndFile();
+
+ writer.writeComponent(BatchReport.Component.newBuilder()
+ .setRef(3)
+ .setType(Constants.ComponentType.FILE)
+ .setUuid("UUID_C")
+ .setSnapshotId(12L)
+ .setPath("file2")
+ .build());
+
+ BatchReport.Duplication duplication = BatchReport.Duplication.newBuilder()
+ .setOriginBlock(BatchReport.DuplicationBlock.newBuilder()
+ .setOtherComponentRef(2)
+ .setStartLine(1)
+ .setEndLine(5)
+ .build())
+ .addDuplicatedBy(BatchReport.DuplicationBlock.newBuilder()
+ .setOtherComponentRef(3)
+ .setStartLine(6)
+ .setEndLine(10)
+ .build())
+ .build();
+ writer.writeComponentDuplications(2, newArrayList(duplication));
+
+ sut.execute(new ComputationContext(new BatchReportReader(reportDir), ComponentTesting.newProjectDto("PROJECT")));
+
+ assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
+
+ Map<String, Object> dto = dbTester.selectFirst("select snapshot_id as \"snapshotId\", text_value as \"textValue\" from project_measures");
+ assertThat(dto.get("snapshotId")).isEqualTo(11L);
+ assertThat(dto.get("textValue")).isEqualTo("<duplications><g><b s=\"1\" l=\"4\" r=\"PROJECT_KEY:file\"/><b s=\"6\" l=\"4\" r=\"PROJECT_KEY:file2\"/></g></duplications>");
+ }
+
+ @Test
+ public void persist_duplications_on_different_projects() throws Exception {
+ saveDuplicationMetric();
+ BatchReportWriter writer = initReportWithProjectAndFile();
+
+ BatchReport.Duplication duplication = BatchReport.Duplication.newBuilder()
+ .setOriginBlock(BatchReport.DuplicationBlock.newBuilder()
+ .setOtherComponentRef(2)
+ .setStartLine(1)
+ .setEndLine(5)
+ .build())
+ .addDuplicatedBy(BatchReport.DuplicationBlock.newBuilder()
+ .setComponentKey("PROJECT2_KEY:file2")
+ .setStartLine(6)
+ .setEndLine(10)
+ .build())
+ .build();
+ writer.writeComponentDuplications(2, newArrayList(duplication));
+
+ sut.execute(new ComputationContext(new BatchReportReader(reportDir), ComponentTesting.newProjectDto("PROJECT")));
+
+ assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(1);
+
+ Map<String, Object> dto = dbTester.selectFirst("select snapshot_id as \"snapshotId\", text_value as \"textValue\" from project_measures");
+ assertThat(dto.get("snapshotId")).isEqualTo(11L);
+ assertThat(dto.get("textValue")).isEqualTo("<duplications><g><b s=\"1\" l=\"4\" r=\"PROJECT_KEY:file\"/><b s=\"6\" l=\"4\" r=\"PROJECT2_KEY:file2\"/></g></duplications>");
+ }
+
+ private BatchReportWriter initReportWithProjectAndFile() throws IOException {
+ BatchReportWriter writer = new BatchReportWriter(reportDir);
+ writer.writeMetadata(BatchReport.Metadata.newBuilder()
+ .setRootComponentRef(1)
+ .setProjectKey("PROJECT_KEY")
+ .setAnalysisDate(150000000L)
+ .build());
+
+ writer.writeComponent(BatchReport.Component.newBuilder()
+ .setRef(1)
+ .setType(Constants.ComponentType.PROJECT)
+ .setUuid("UUID_A")
+ .setKey("PROJECT_KEY")
+ .setSnapshotId(10L)
+ .addChildRef(2)
+ .build());
+ writer.writeComponent(BatchReport.Component.newBuilder()
+ .setRef(2)
+ .setType(Constants.ComponentType.FILE)
+ .setUuid("UUID_B")
+ .setSnapshotId(11L)
+ .setPath("file")
+ .build());
+
+ return writer;
+ }
+
+ private MetricDto saveDuplicationMetric(){
+ MetricDto duplicationMetric = new MetricDto().setKey(CoreMetrics.DUPLICATIONS_DATA_KEY);
+ dbClient.metricDao().insert(session, duplicationMetric);
+ session.commit();
+ return duplicationMetric;
+ }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java
index 910f0b6ff26..c83c7c258bd 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MeasureDaoTest.java
@@ -22,7 +22,7 @@ package org.sonar.server.measure.persistence;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
+import org.junit.ClassRule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.sonar.api.rule.Severity;
@@ -39,14 +39,15 @@ import static org.assertj.core.api.Assertions.assertThat;
@Category(DbTests.class)
public class MeasureDaoTest {
- @Rule
- public DbTester db = new DbTester();
+ @ClassRule
+ public static DbTester db = new DbTester();
DbSession session;
MeasureDao sut;
@Before
public void setUp() {
+ db.truncateTables();
session = db.myBatis().openSession(false);
sut = new MeasureDao();
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MetricDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MetricDaoTest.java
index 81bbd179c4c..52750ec126c 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MetricDaoTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/persistence/MetricDaoTest.java
@@ -22,14 +22,21 @@ package org.sonar.server.measure.persistence;
import org.junit.After;
import org.junit.Before;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.experimental.categories.Category;
import org.sonar.core.measure.db.MetricDto;
-import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.test.DbTests;
import static org.assertj.core.api.Assertions.assertThat;
-public class MetricDaoTest extends AbstractDaoTestCase {
+@Category(DbTests.class)
+public class MetricDaoTest {
+
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
DbSession session;
@@ -37,7 +44,8 @@ public class MetricDaoTest extends AbstractDaoTestCase {
@Before
public void createDao() {
- session = getMyBatis().openSession(false);
+ dbTester.truncateTables();
+ session = dbTester.myBatis().openSession(false);
dao = new MetricDao();
}
@@ -48,32 +56,75 @@ public class MetricDaoTest extends AbstractDaoTestCase {
@Test
public void get_by_key() throws Exception {
- setupData("shared");
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
- MetricDto result = dao.getNullableByKey(session, "coverage");
+ MetricDto result = dao.selectByKey(session, "coverage");
assertThat(result.getId()).isEqualTo(2);
- assertThat(result.getName()).isEqualTo("coverage");
- assertThat(result.getValueType()).isEqualTo("PERCENT");
+ assertThat(result.getKey()).isEqualTo("coverage");
+ assertThat(result.getShortName()).isEqualTo("Coverage");
assertThat(result.getDescription()).isEqualTo("Coverage by unit tests");
+ assertThat(result.getDomain()).isEqualTo("Tests");
+ assertThat(result.getValueType()).isEqualTo("PERCENT");
+ assertThat(result.getOrigin()).isEqualTo("JAV");
assertThat(result.getDirection()).isEqualTo(1);
assertThat(result.isQualitative()).isTrue();
assertThat(result.isUserManaged()).isFalse();
assertThat(result.getWorstValue()).isEqualTo(0d);
assertThat(result.getBestValue()).isEqualTo(100d);
assertThat(result.isOptimizedBestValue()).isFalse();
+ assertThat(result.isDeleteHistoricalData()).isFalse();
+ assertThat(result.isHidden()).isFalse();
assertThat(result.isEnabled()).isTrue();
// Disabled metrics are returned
- result = dao.getNullableByKey(session, "disabled");
+ result = dao.selectByKey(session, "disabled");
assertThat(result.getId()).isEqualTo(3);
assertThat(result.isEnabled()).isFalse();
}
@Test
public void find_all_enabled() throws Exception {
- setupData("shared");
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
- assertThat(dao.findEnabled(session)).hasSize(2);
+ assertThat(dao.selectEnabled(session)).hasSize(2);
}
+ @Test
+ public void insert() throws Exception {
+ dao.insert(session, new MetricDto()
+ .setId(1)
+ .setKey("coverage")
+ .setShortName("Coverage")
+ .setDescription("Coverage by unit tests")
+ .setDomain("Tests")
+ .setValueType("PERCENT")
+ .setQualitative(true)
+ .setUserManaged(true)
+ .setWorstValue(0d)
+ .setBestValue(100d)
+ .setOptimizedBestValue(true)
+ .setDirection(1)
+ .setOrigin("JAV")
+ .setHidden(true)
+ .setDeleteHistoricalData(true)
+ .setEnabled(true));
+
+ MetricDto result = dao.selectByKey(session, "coverage");
+ assertThat(result.getId()).isNotNull();
+ assertThat(result.getKey()).isEqualTo("coverage");
+ assertThat(result.getShortName()).isEqualTo("Coverage");
+ assertThat(result.getDescription()).isEqualTo("Coverage by unit tests");
+ assertThat(result.getDomain()).isEqualTo("Tests");
+ assertThat(result.getValueType()).isEqualTo("PERCENT");
+ assertThat(result.getOrigin()).isEqualTo("JAV");
+ assertThat(result.getDirection()).isEqualTo(1);
+ assertThat(result.isQualitative()).isTrue();
+ assertThat(result.isUserManaged()).isTrue();
+ assertThat(result.getWorstValue()).isEqualTo(0d);
+ assertThat(result.getBestValue()).isEqualTo(100d);
+ assertThat(result.isOptimizedBestValue()).isTrue();
+ assertThat(result.isDeleteHistoricalData()).isTrue();
+ assertThat(result.isHidden()).isTrue();
+ assertThat(result.isEnabled()).isTrue();
+ }
}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_referentials.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_referentials.json
index ec34825d8c3..2e558edbbf6 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_referentials.json
+++ b/server/sonar-server/src/test/resources/org/sonar/server/batch/GlobalRepositoryActionTest/return_global_referentials.json
@@ -2,7 +2,7 @@
"timestamp": 0,
"metrics": [
{
- "id": 0,
+ "id": 1,
"key": "coverage",
"valueType": "PERCENT",
"description": "Coverage by unit tests",
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest/persist_duplication_on_same_file-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest/persist_duplication_on_same_file-result.xml
new file mode 100644
index 00000000000..68809ddb260
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest/persist_duplication_on_same_file-result.xml
@@ -0,0 +1,11 @@
+<dataset>
+
+ <project_measures id="1" snapshot_id="1000" metric_id="10" value="[null]"
+ text_value="&lt;duplications&gt;&lt;g&gt;&lt;b s=&quot;1&quot; l=&quot;5&quot; r=&quot;PROJECT_KEY:file&quot;/&gt;&lt;b s=&quot;6&quot; l=&quot;10&quot; r=&quot;PROJECT_KEY:file&quot;&gt;"
+ measure_data="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]" />
+
+ <project_measures id="2" snapshot_id="1000" metric_id="10" value="[null]"
+ text_value="&lt;duplications&gt;&lt;g&gt;&lt;b s=&quot;1&quot; l=&quot;5&quot; r=&quot;PROJECT_KEY:file&quot;/&gt;&lt;b s=&quot;6&quot; l=&quot;10&quot; r=&quot;PROJECT_KEY:file&quot;&gt;"
+ measure_data="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]" />
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest/persist_duplication_on_same_file.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest/persist_duplication_on_same_file.xml
new file mode 100644
index 00000000000..53ff5efd294
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistDuplicationMeasuresStepTest/persist_duplication_on_same_file.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <metrics id="1" name="duplications_data" val_type="DATA" description="Duplications details" short_name="Duplications details" domain="Duplication"
+ qualitative="[false]" enabled="[true]" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="[false]"/>
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/measure/persistence/MetricDaoTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/measure/persistence/MetricDaoTest/shared.xml
index 50f05bf1946..82b23eead28 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/measure/persistence/MetricDaoTest/shared.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/measure/persistence/MetricDaoTest/shared.xml
@@ -1,32 +1,15 @@
-<!--
- ~ 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.
- -->
-
<dataset>
<metrics id="1" name="ncloc" val_type="INT" description="Non Commenting Lines of Code" domain="Size" short_name="Lines of code"
- qualitative="[false]" enabled="[true]" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="-1" hidden="[false]"/>
+ qualitative="[false]" enabled="[true]" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="-1" hidden="[false]"
+ origin="JAV" delete_historical_data="[false]" user_managed="[false]"/>
<metrics id="2" name="coverage" val_type="PERCENT" description="Coverage by unit tests" domain="Tests" short_name="Coverage"
- qualitative="[true]" enabled="[true]" worst_value="0" optimized_best_value="[false]" best_value="100" direction="1" hidden="[false]"/>
+ qualitative="[true]" enabled="[true]" worst_value="0" optimized_best_value="[false]" best_value="100" direction="1" hidden="[false]"
+ origin="JAV" delete_historical_data="[false]" user_managed="[false]"/>
<metrics id="3" name="disabled" val_type="INT" description="[null]" domain="[null]" short_name="disabled"
- qualitative="[false]" enabled="[false]" worst_value="0" optimized_best_value="[true]" best_value="100" direction="1" hidden="[false]"/>
+ qualitative="[false]" enabled="[false]" worst_value="0" optimized_best_value="[true]" best_value="100" direction="1" hidden="[false]"
+ origin="JAV" delete_historical_data="[false]" user_managed="[false]"/>
</dataset>