diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-03-24 16:18:10 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-03-25 15:20:10 +0100 |
commit | ac44823d701c7ae3ea30ea8060c8fe28ca8ee6af (patch) | |
tree | a521202e8caac86d174fbf2675ea129c401ccd74 /server/sonar-server | |
parent | c9ce765d410c8924cb7d11b28e42e85078409622 (diff) | |
download | sonarqube-ac44823d701c7ae3ea30ea8060c8fe28ca8ee6af.tar.gz sonarqube-ac44823d701c7ae3ea30ea8060c8fe28ca8ee6af.zip |
SONAR-6257 Persist duplication measures in compute
Diffstat (limited to 'server/sonar-server')
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="<duplications><g><b s="1" l="5" r="PROJECT_KEY:file"/><b s="6" l="10" r="PROJECT_KEY:file">" + 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="<duplications><g><b s="1" l="5" r="PROJECT_KEY:file"/><b s="6" l="10" r="PROJECT_KEY:file">" + 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> |