From 8bd1b2be54d39c365605d656ec0a67904ba8cd63 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Wed, 26 Aug 2015 11:05:10 +0200 Subject: [PATCH] FillMeasuresWithVariationsStep now support Views Component tree --- .../step/FillMeasuresWithVariationsStep.java | 20 +- .../server/component/SnapshotTesting.java | 7 +- ...rtFillMeasuresWithVariationsStepTest.java} | 2 +- ...ewsFillMeasuresWithVariationsStepTest.java | 241 ++++++++++++++++++ 4 files changed, 259 insertions(+), 11 deletions(-) rename server/sonar-server/src/test/java/org/sonar/server/computation/step/{FillMeasuresWithVariationsStepTest.java => ReportFillMeasuresWithVariationsStepTest.java} (99%) create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java index deef21ce0eb..ff51847f7bd 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStep.java @@ -22,7 +22,6 @@ package org.sonar.server.computation.step; import com.google.common.base.Function; import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -48,6 +47,9 @@ import org.sonar.server.computation.metric.MetricRepository; import org.sonar.server.computation.period.Period; import org.sonar.server.computation.period.PeriodsHolder; +import static com.google.common.collect.FluentIterable.from; +import static org.sonar.server.computation.component.Component.Type.DIRECTORY; +import static org.sonar.server.computation.component.Component.Type.SUBVIEW; import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER; /** @@ -86,11 +88,11 @@ public class FillMeasuresWithVariationsStep implements ComputationStep { public void execute() { DbSession dbSession = dbClient.openSession(false); try { - Iterable metrics = FluentIterable.from(metricRepository.getAll()).filter(NumericMetric.INSTANCE); + List metrics = from(metricRepository.getAll()).filter(NumericMetric.INSTANCE).toList(); new DepthTraversalTypeAwareCrawler(new VariationMeasuresVisitor(dbSession, metrics)) .visit(treeRootHolder.getRoot()); } finally { - dbSession.close(); + dbClient.closeSession(dbSession); } } @@ -102,10 +104,10 @@ public class FillMeasuresWithVariationsStep implements ComputationStep { public VariationMeasuresVisitor(DbSession session, Iterable metrics) { // measures on files are currently purged, so past measures are not available on files - super(CrawlerDepthLimit.DIRECTORY, PRE_ORDER); + super(CrawlerDepthLimit.reportMaxDepth(DIRECTORY).withViewsMaxDepth(SUBVIEW), PRE_ORDER); this.session = session; - this.metricIds = FluentIterable.from(metrics).transform(MetricDtoToMetricId.INSTANCE).toSet(); - this.metricByKeys = FluentIterable.from(metrics).uniqueIndex(MetricToKey.INSTANCE); + this.metricIds = from(metrics).transform(MetricDtoToMetricId.INSTANCE).toSet(); + this.metricByKeys = from(metrics).uniqueIndex(MetricToKey.INSTANCE); } @Override @@ -117,8 +119,8 @@ public class FillMeasuresWithVariationsStep implements ComputationStep { private MeasuresWithVariationRepository computeMeasuresWithVariations(Component component) { MeasuresWithVariationRepository measuresWithVariationRepository = new MeasuresWithVariationRepository(); for (Period period : periodsHolder.getPeriods()) { - List pastMeasures = dbClient.measureDao().selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, component.getUuid(), period.getSnapshotId(), - metricIds); + List pastMeasures = dbClient.measureDao() + .selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, component.getUuid(), period.getSnapshotId(), metricIds); setVariationMeasures(component, pastMeasures, period.getIndex(), measuresWithVariationRepository); } return measuresWithVariationRepository; @@ -140,7 +142,7 @@ public class FillMeasuresWithVariationsStep implements ComputationStep { } private void setVariationMeasures(Component component, List pastMeasures, int period, MeasuresWithVariationRepository measuresWithVariationRepository) { - Map pastMeasuresByMeasureKey = FluentIterable.from(pastMeasures).uniqueIndex(pastMeasureToMeasureKey); + Map pastMeasuresByMeasureKey = from(pastMeasures).uniqueIndex(pastMeasureToMeasureKey); for (Map.Entry entry : measureRepository.getRawMeasures(component).entries()) { String metricKey = entry.getKey(); Measure measure = entry.getValue(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/SnapshotTesting.java b/server/sonar-server/src/test/java/org/sonar/server/component/SnapshotTesting.java index 738c7b5924d..e37007386a3 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/SnapshotTesting.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/SnapshotTesting.java @@ -41,7 +41,12 @@ public class SnapshotTesting { public static SnapshotDto createForProject(ComponentDto project) { return createBasicSnapshot(project, project.getId()) - .setPath(""); + .setPath(""); + } + + public static SnapshotDto createForView(ComponentDto view) { + return createBasicSnapshot(view, view.getId()) + .setPath(""); } private static SnapshotDto createBasicSnapshot(ComponentDto component, Long rootProjectId) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportFillMeasuresWithVariationsStepTest.java similarity index 99% rename from server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java rename to server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportFillMeasuresWithVariationsStepTest.java index e90819a3eb6..6b28ebfe291 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportFillMeasuresWithVariationsStepTest.java @@ -50,7 +50,7 @@ import static org.sonar.server.component.SnapshotTesting.createForComponent; import static org.sonar.server.component.SnapshotTesting.createForProject; @Category(DbTests.class) -public class FillMeasuresWithVariationsStepTest { +public class ReportFillMeasuresWithVariationsStepTest { static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT); static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java new file mode 100644 index 00000000000..e1b21956cf6 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsFillMeasuresWithVariationsStepTest.java @@ -0,0 +1,241 @@ +/* + * 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.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +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.component.ComponentDto; +import org.sonar.db.component.ComponentTesting; +import org.sonar.db.component.SnapshotDto; +import org.sonar.db.measure.MeasureDto; +import org.sonar.server.computation.batch.BatchReportReaderRule; +import org.sonar.server.computation.batch.TreeRootHolderRule; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.ViewsComponent; +import org.sonar.server.computation.measure.Measure; +import org.sonar.server.computation.measure.MeasureRepositoryRule; +import org.sonar.server.computation.metric.Metric; +import org.sonar.server.computation.metric.MetricImpl; +import org.sonar.server.computation.metric.MetricRepositoryRule; +import org.sonar.server.computation.period.Period; +import org.sonar.server.computation.period.PeriodsHolderRule; +import org.sonar.test.DbTests; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.server.component.SnapshotTesting.createForComponent; +import static org.sonar.server.component.SnapshotTesting.createForProject; +import static org.sonar.server.component.SnapshotTesting.createForView; + +@Category(DbTests.class) +public class ViewsFillMeasuresWithVariationsStepTest { + + static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT); + static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR); + static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT); + static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL); + + static final ComponentDto VIEW_DTO = ComponentTesting.newView(); + + static final Component VIEW = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build(); + + @Rule + public DbTester dbTester = DbTester.create(System2.INSTANCE); + + @Rule + public BatchReportReaderRule reportReader = new BatchReportReaderRule(); + + @Rule + public PeriodsHolderRule periodsHolder = new PeriodsHolderRule(); + + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); + + @Rule + public MetricRepositoryRule metricRepository = new MetricRepositoryRule() + .add(ISSUES_METRIC) + .add(DEBT_METRIC) + .add(FILE_COMPLEXITY_METRIC) + .add(BUILD_BREAKER_METRIC); + + @Rule + public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); + + DbSession session = dbTester.getSession(); + + DbClient dbClient = dbTester.getDbClient(); + + FillMeasuresWithVariationsStep underTest; + + @Before + public void setUp() { + dbTester.truncateTables(); + dbClient.componentDao().insert(session, VIEW_DTO); + session.commit(); + + underTest = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository); + } + + @Test + public void do_nothing_when_no_raw_measure() { + SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO); + dbClient.snapshotDao().insert(session, period1ViewSnapshot); + dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d)); + session.commit(); + + periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot)); + + treeRootHolder.setRoot(VIEW); + + underTest.execute(); + + assertThat(measureRepository.getRawMeasures(VIEW).keys()).isEmpty(); + } + + @Test + public void do_nothing_when_no_period() { + Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build(); + treeRootHolder.setRoot(view); + periodsHolder.setPeriods(); + + underTest.execute(); + + assertThat(measureRepository.getRawMeasures(view).keys()).isEmpty(); + } + + @Test + public void set_variation() { + // View + SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO); + dbClient.snapshotDao().insert(session, period1ViewSnapshot); + dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d)); + + // SubView + ComponentDto subviewDto = ComponentTesting.newSubView(VIEW_DTO, "dir", "who cares?"); + dbClient.componentDao().insert(session, subviewDto); + SnapshotDto period1SubviewSnapshot = createForComponent(subviewDto, period1ViewSnapshot); + dbClient.snapshotDao().insert(session, period1SubviewSnapshot); + dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), subviewDto.getId(), period1SubviewSnapshot.getId(), 10d)); + session.commit(); + + periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot)); + + Component subview = ViewsComponent.builder(Component.Type.SUBVIEW, 2).setUuid(subviewDto.uuid()).build(); + Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).addChildren(subview).build(); + treeRootHolder.setRoot(view); + + addRawMeasure(view, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null)); + addRawMeasure(subview, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null)); + + underTest.execute(); + + assertThat(measureRepository.getRawMeasure(view, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d); + assertThat(measureRepository.getRawMeasure(subview, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d); + } + + @Test + public void set_variations_on_all_periods() { + SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO).setLast(false); + SnapshotDto period2ViewSnapshot = createForProject(VIEW_DTO).setLast(false); + SnapshotDto period3ViewSnapshot = createForProject(VIEW_DTO).setLast(false); + SnapshotDto period4ViewSnapshot = createForProject(VIEW_DTO).setLast(false); + SnapshotDto period5ViewSnapshot = createForProject(VIEW_DTO).setLast(false); + dbClient.snapshotDao().insert(session, period1ViewSnapshot, period2ViewSnapshot, period3ViewSnapshot, period4ViewSnapshot, period5ViewSnapshot); + + dbClient.measureDao().insert(session, + newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 0d), + newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period2ViewSnapshot.getId(), 20d), + newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period3ViewSnapshot.getId(), 40d), + newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period4ViewSnapshot.getId(), 80d), + newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period5ViewSnapshot.getId(), 100d)); + session.commit(); + + periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot), + newPeriod(2, period2ViewSnapshot), + newPeriod(3, period3ViewSnapshot), + newPeriod(4, period4ViewSnapshot), + newPeriod(5, period5ViewSnapshot)); + + treeRootHolder.setRoot(VIEW); + + addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null)); + + underTest.execute(); + + assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(1); + + Measure measure = measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get(); + assertThat(measure.hasVariations()).isTrue(); + assertThat(measure.getVariations().getVariation1()).isEqualTo(80d); + assertThat(measure.getVariations().getVariation2()).isEqualTo(60d); + assertThat(measure.getVariations().getVariation3()).isEqualTo(40d); + assertThat(measure.getVariations().getVariation4()).isEqualTo(0d); + assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d); + } + + @Test + public void set_variation_on_all_numeric_metrics() { + SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO); + dbClient.snapshotDao().insert(session, period1ViewSnapshot); + dbClient.measureDao().insert(session, + newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d), + newMeasureDto(DEBT_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 10d), + newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 2d), + newMeasureDto(BUILD_BREAKER_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 1d) + ); + session.commit(); + + periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot)); + + treeRootHolder.setRoot(VIEW); + + addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null)); + addRawMeasure(VIEW, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null)); + addRawMeasure(VIEW, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null)); + addRawMeasure(VIEW, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null)); + + underTest.execute(); + + assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(4); + + assertThat(measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d); + assertThat(measureRepository.getRawMeasure(VIEW, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d); + assertThat(measureRepository.getRawMeasure(VIEW, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d); + assertThat(measureRepository.getRawMeasure(VIEW, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d); + } + + private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) { + return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value); + } + + private static Period newPeriod(int index, SnapshotDto snapshotDto) { + return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId()); + } + + private void addRawMeasure(Component component, Metric metric, Measure measure) { + measureRepository.add(component, metric, measure); + } +} -- 2.39.5