Browse Source

SONAR-7012 Use standard persistence for duplications_data measure

tags/5.3-RC1
Julien Lancelot 8 years ago
parent
commit
11cd65ae85

server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistDuplicationsStep.java → server/sonar-server/src/main/java/org/sonar/server/computation/step/DuplicationDataMeasuresStep.java View File

@@ -22,15 +22,8 @@ package org.sonar.server.computation.step;

import java.util.Set;
import org.apache.commons.lang.StringEscapeUtils;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
import org.sonar.db.measure.MeasureDto;
import org.sonar.db.metric.MetricDto;
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;
@@ -41,67 +34,60 @@ import org.sonar.server.computation.duplication.DuplicationRepository;
import org.sonar.server.computation.duplication.InProjectDuplicate;
import org.sonar.server.computation.duplication.InnerDuplicate;
import org.sonar.server.computation.duplication.TextBlock;
import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepository;
import org.sonar.server.computation.metric.Metric;
import org.sonar.server.computation.metric.MetricRepository;

import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA_KEY;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;

/**
* Persist duplications into
* Compute duplication data measures on files, based on the {@link DuplicationRepository}
*/
public class PersistDuplicationsStep implements ComputationStep {
public class DuplicationDataMeasuresStep implements ComputationStep {

private final DbClient dbClient;
private final DbIdsRepository dbIdsRepository;
private final MeasureRepository measureRepository;
private final TreeRootHolder treeRootHolder;
private final DuplicationRepository duplicationRepository;

public PersistDuplicationsStep(DbClient dbClient, DbIdsRepository dbIdsRepository, TreeRootHolder treeRootHolder,
private final Metric duplicationDataMetric;

public DuplicationDataMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
DuplicationRepository duplicationRepository) {
this.dbClient = dbClient;
this.dbIdsRepository = dbIdsRepository;
this.measureRepository = measureRepository;
this.treeRootHolder = treeRootHolder;
this.duplicationRepository = duplicationRepository;
this.duplicationDataMetric = metricRepository.getByKey(DUPLICATIONS_DATA_KEY);
}

@Override
public void execute() {
DbSession session = dbClient.openSession(true);
try {
MetricDto duplicationMetric = dbClient.metricDao().selectOrFailByKey(session, CoreMetrics.DUPLICATIONS_DATA_KEY);
new DepthTraversalTypeAwareCrawler(new DuplicationVisitor(session, duplicationMetric))
.visit(treeRootHolder.getRoot());
session.commit();
} finally {
MyBatis.closeQuietly(session);
}
new DepthTraversalTypeAwareCrawler(new DuplicationVisitor())
.visit(treeRootHolder.getRoot());
}

private class DuplicationVisitor extends TypeAwareVisitorAdapter {

private final DbSession session;
private final MetricDto duplicationMetric;

private DuplicationVisitor(DbSession session, MetricDto duplicationMetric) {
private DuplicationVisitor() {
super(CrawlerDepthLimit.FILE, PRE_ORDER);
this.session = session;
this.duplicationMetric = duplicationMetric;
}

@Override
public void visitFile(Component file) {
Set<Duplication> duplications = duplicationRepository.getDuplications(file);
if (!duplications.isEmpty()) {
saveDuplications(file, duplications);
computeDuplications(file, duplications);
}
}

private void saveDuplications(Component component, Iterable<Duplication> duplications) {
private void computeDuplications(Component component, Iterable<Duplication> duplications) {
String duplicationXml = createXmlDuplications(component.getKey(), duplications);
MeasureDto measureDto = new MeasureDto()
.setMetricId(duplicationMetric.getId())
.setData(duplicationXml)
.setComponentId(dbIdsRepository.getComponentId(component))
.setSnapshotId(dbIdsRepository.getSnapshotId(component));
dbClient.measureDao().insert(session, measureDto);
measureRepository.add(
component,
duplicationDataMetric,
Measure.newMeasureBuilder().create(duplicationXml)
);
}

private String createXmlDuplications(String componentKey, Iterable<Duplication> duplications) {
@@ -150,7 +136,7 @@ public class PersistDuplicationsStep implements ComputationStep {

@Override
public String getDescription() {
return "Persist duplications";
return "Compute duplication data measures";
}

}

+ 3
- 2
server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportComputationSteps.java View File

@@ -53,6 +53,8 @@ public class ReportComputationSteps implements ComputationSteps {
LoadQualityGateStep.class,
LoadPeriodsStep.class,

// load duplications related stuff
LoadDuplicationsFromReportStep.class,
LoadCrossProjectDuplicationsRepositoryStep.class,

// data computation
@@ -61,8 +63,8 @@ public class ReportComputationSteps implements ComputationSteps {
CoverageMeasuresStep.class,
CommentMeasuresStep.class,
CustomMeasuresCopyStep.class,
LoadDuplicationsFromReportStep.class,
DuplicationMeasuresStep.class,
DuplicationDataMeasuresStep.class,
LanguageDistributionMeasuresStep.class,
UnitTestMeasuresStep.class,
ComplexityMeasuresStep.class,
@@ -89,7 +91,6 @@ public class ReportComputationSteps implements ComputationSteps {
PersistIssuesStep.class,
PersistProjectLinksStep.class,
PersistEventsStep.class,
PersistDuplicationsStep.class,
PersistFileSourcesStep.class,
PersistTestsStep.class,
PersistCrossProjectDuplicationIndexStep.class,

+ 126
- 0
server/sonar-server/src/test/java/org/sonar/server/computation/step/DuplicationDataMeasuresStepTest.java View File

@@ -0,0 +1,126 @@
/*
* 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.Rule;
import org.junit.Test;
import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.duplication.DuplicationRepositoryRule;
import org.sonar.server.computation.duplication.TextBlock;
import org.sonar.server.computation.measure.MeasureRepositoryRule;
import org.sonar.server.computation.metric.MetricRepositoryRule;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.guava.api.Assertions.assertThat;
import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA;
import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA_KEY;
import static org.sonar.server.computation.component.Component.Type.FILE;
import static org.sonar.server.computation.component.Component.Type.PROJECT;
import static org.sonar.server.computation.component.ReportComponent.builder;

public class DuplicationDataMeasuresStepTest extends BaseStepTest {

private static final int ROOT_REF = 1;
private static final String PROJECT_KEY = "PROJECT_KEY";

private static final int FILE_1_REF = 2;
private static final String FILE_1_KEY = "FILE_1_KEY";

private static final int FILE_2_REF = 3;
private static final String FILE_2_KEY = "FILE_2_KEY";

@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
.setRoot(
builder(PROJECT, ROOT_REF).setKey(PROJECT_KEY)
.addChildren(
builder(FILE, FILE_1_REF).setKey(FILE_1_KEY)
.build(),
builder(FILE, FILE_2_REF).setKey(FILE_2_KEY)
.build())
.build());

@Rule
public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);

@Rule
public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
.add(DUPLICATIONS_DATA);

@Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);

DuplicationDataMeasuresStep underTest = new DuplicationDataMeasuresStep(treeRootHolder, metricRepository, measureRepository, duplicationRepository);

@Override
protected ComputationStep step() {
return underTest;
}

@Test
public void nothing_to_do_when_no_duplication() {
underTest.execute();

assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
assertThat(measureRepository.getAddedRawMeasure(FILE_2_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
}

@Test
public void compute_duplications_on_same_file() {
duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), new TextBlock(6, 10));

underTest.execute();

assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY)).isPresent();
assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY).get().getData()).isEqualTo(
"<duplications><g><b s=\"1\" l=\"5\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" r=\"" + FILE_1_KEY + "\"/></g></duplications>"
);
assertThat(measureRepository.getAddedRawMeasure(FILE_2_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
}

@Test
public void compute_duplications_on_different_files() {
duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), FILE_2_REF, new TextBlock(6, 10));

underTest.execute();

assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY)).isPresent();
assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY).get().getData()).isEqualTo(
"<duplications><g><b s=\"1\" l=\"5\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" r=\"" + FILE_2_KEY + "\"/></g></duplications>"
);
assertThat(measureRepository.getAddedRawMeasure(FILE_2_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
}

@Test
public void compute_duplications_on_different_projects() {
String fileKeyFromOtherProject = "PROJECT2_KEY:file2";
duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), fileKeyFromOtherProject, new TextBlock(6, 10));

underTest.execute();

assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY)).isPresent();
assertThat(measureRepository.getAddedRawMeasure(FILE_1_REF, DUPLICATIONS_DATA_KEY).get().getData()).isEqualTo(
"<duplications><g><b s=\"1\" l=\"5\" r=\"" + FILE_1_KEY + "\"/><b s=\"6\" l=\"5\" r=\"" + fileKeyFromOtherProject + "\"/></g></duplications>"
);
assertThat(measureRepository.getAddedRawMeasure(FILE_2_REF, DUPLICATIONS_DATA_KEY)).isAbsent();
}

}

+ 0
- 165
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistDuplicationsStepTest.java View File

@@ -1,165 +0,0 @@
/*
* 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 java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.metric.MetricDto;
import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DbIdsRepositoryImpl;
import org.sonar.server.computation.component.ReportComponent;
import org.sonar.server.computation.duplication.DuplicationRepositoryRule;
import org.sonar.server.computation.duplication.TextBlock;
import org.sonar.test.DbTests;

import static org.assertj.core.api.Assertions.assertThat;

@Category(DbTests.class)
public class PersistDuplicationsStepTest extends BaseStepTest {

private static final String PROJECT_KEY = "PROJECT_KEY";
private static final int FILE_1_REF = 2;
private static final int FILE_2_REF = 3;
private static final int ROOT_REF = 1;

@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@Rule
public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);

DbIdsRepositoryImpl dbIdsRepository = new DbIdsRepositoryImpl();
DbSession session = dbTester.getSession();
DbClient dbClient = dbTester.getDbClient();

PersistDuplicationsStep underTest;

@Before
public void setup() {
dbTester.truncateTables();
underTest = new PersistDuplicationsStep(dbClient, dbIdsRepository, treeRootHolder, duplicationRepository);
}

@Override
protected ComputationStep step() {
return underTest;
}

@After
public void tearDown() {
session.close();
}

@Test
public void nothing_to_do_when_no_duplication() {
saveDuplicationMetric();
initReportWithProjectAndFile();

underTest.execute();

assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(0);
}

@Test
public void persist_duplications_on_same_file() {
MetricDto duplicationMetric = saveDuplicationMetric();
initReportWithProjectAndFile();

duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), new TextBlock(6, 10));

underTest.execute();

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=\"5\" r=\"PROJECT_KEY:file\"/><b s=\"6\" l=\"5\" r=\"PROJECT_KEY:file\"/></g></duplications>");
}

@Test
public void persist_duplications_on_different_files() {
saveDuplicationMetric();
initReportWithProjectAndFile();

duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), 3, new TextBlock(6, 10));

underTest.execute();

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=\"5\" r=\"PROJECT_KEY:file\"/><b s=\"6\" l=\"5\" r=\"PROJECT_KEY:file2\"/></g></duplications>");
}

@Test
public void persist_duplications_on_different_projects() {
saveDuplicationMetric();
initReportWithProjectAndFile();

duplicationRepository.addDuplication(FILE_1_REF, new TextBlock(1, 5), "PROJECT2_KEY:file2", new TextBlock(6, 10));

underTest.execute();

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=\"5\" r=\"PROJECT_KEY:file\"/><b s=\"6\" l=\"5\" r=\"PROJECT2_KEY:file2\"/></g></duplications>");
}

private void initReportWithProjectAndFile() {
Component file1 = ReportComponent.builder(Component.Type.FILE, FILE_1_REF).setUuid("BCDE").setKey("PROJECT_KEY:file").build();
Component file2 = ReportComponent.builder(Component.Type.FILE, FILE_2_REF).setUuid("CDEF").setKey("PROJECT_KEY:file2").build();
Component project = ReportComponent.builder(Component.Type.PROJECT, ROOT_REF).setUuid("ABCD").setKey(PROJECT_KEY).addChildren(file1, file2).build();
treeRootHolder.setRoot(project);

dbIdsRepository.setComponentId(project, 1);
dbIdsRepository.setSnapshotId(project, 10);
dbIdsRepository.setComponentId(file1, 2);
dbIdsRepository.setSnapshotId(file1, 11);
dbIdsRepository.setComponentId(file2, 2);
dbIdsRepository.setSnapshotId(file2, 12);
}

private MetricDto saveDuplicationMetric() {
MetricDto duplicationMetric = new MetricDto().setKey(CoreMetrics.DUPLICATIONS_DATA_KEY)
.setOptimizedBestValue(false)
.setDeleteHistoricalData(false)
.setHidden(false);
dbClient.metricDao().insert(session, duplicationMetric);
session.commit();
return duplicationMetric;
}

}

Loading…
Cancel
Save