From 54af62e34d4b586251f58d861ca8e7dd8660667d Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Fri, 12 Jun 2015 11:44:17 +0200 Subject: [PATCH] SONAR-6620 persist metrics based on MetricRepository --- .../computation/measure/MeasureImpl.java | 2 +- .../measure/MeasureToMeasureDto.java | 104 +++++++ .../computation/step/PersistMeasuresStep.java | 109 ++------ .../measure/MeasureToMeasureDtoTest.java | 210 ++++++++++++++ .../step/PersistMeasuresStepTest.java | 263 ++---------------- 5 files changed, 371 insertions(+), 317 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureToMeasureDto.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureToMeasureDtoTest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureImpl.java index 8d08c9bc574..673a8bf58a2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureImpl.java @@ -46,7 +46,7 @@ public final class MeasureImpl implements Measure { @Nullable private String description; - protected MeasureImpl(ValueType valueType, @Nullable Integer ruleId, @Nullable Integer characteristicId, @Nullable Double value, @Nullable String data, @Nullable Level dataLevel) { + private MeasureImpl(ValueType valueType, @Nullable Integer ruleId, @Nullable Integer characteristicId, @Nullable Double value, @Nullable String data, @Nullable Level dataLevel) { this.valueType = valueType; this.ruleId = ruleId; this.characteristicId = characteristicId; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureToMeasureDto.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureToMeasureDto.java new file mode 100644 index 00000000000..c758805e7da --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureToMeasureDto.java @@ -0,0 +1,104 @@ +/* + * 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.measure; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import org.sonar.core.measure.db.MeasureDto; +import org.sonar.server.computation.metric.Metric; + +public enum MeasureToMeasureDto { + INSTANCE; + + @Nonnull + public MeasureDto toMeasureDto(Measure measure, Metric metric, long componentId, long snapshotId) { + MeasureDto out = new MeasureDto(); + out.setMetricId(metric.getId()); + out.setComponentId(componentId); + out.setSnapshotId(snapshotId); + out.setCharacteristicId(measure.getCharacteristicId()); + out.setRuleId(measure.getRuleId()); + if (measure.hasVariations()) { + setVariations(out, measure.getVariations()); + } + if (measure.hasQualityGateStatus()) { + setAlert(out, measure.getQualityGateStatus()); + } + // TODO persist personId if DevCockpit is reactivated +// out.setPersonId(measure.hasPersonId() ? measure.getPersonId() : null); + out.setDescription(measure.getDescription()); + out.setValue(valueAsDouble(measure)); + out.setData(data(measure)); + return out; + } + + private static void setVariations(MeasureDto measureDto, MeasureVariations variations) { + measureDto.setVariation(1, variations.hasVariation1() ? variations.getVariation1() : null); + measureDto.setVariation(2, variations.hasVariation2() ? variations.getVariation2() : null); + measureDto.setVariation(3, variations.hasVariation3() ? variations.getVariation3() : null); + measureDto.setVariation(4, variations.hasVariation4() ? variations.getVariation4() : null); + measureDto.setVariation(5, variations.hasVariation5() ? variations.getVariation5() : null); + } + + private static void setAlert(MeasureDto measureDto, QualityGateStatus qualityGateStatus) { + measureDto.setAlertStatus(qualityGateStatus.getStatus().name()); + measureDto.setAlertText(qualityGateStatus.getText()); + } + + private static String data(Measure in) { + switch (in.getValueType()) { + case NO_VALUE: + case BOOLEAN: + case INT: + case LONG: + case DOUBLE: + return in.getData(); + case STRING: + return in.getStringValue(); + case LEVEL: + return in.getLevelValue().name(); + default: + return null; + } + } + + /** + * return the numerical value as a double. It's the type used in db. + * Returns null if no numerical value found + */ + @CheckForNull + private static Double valueAsDouble(Measure measure) { + switch (measure.getValueType()) { + case BOOLEAN: + return measure.getBooleanValue() ? 1.0d : 0.0d; + case INT: + return (double) measure.getIntValue(); + case LONG: + return (double) measure.getLongValue(); + case DOUBLE: + return measure.getDoubleValue(); + case NO_VALUE: + case STRING: + case LEVEL: + default: + return null; + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java index 4f40bcb46f6..aff9c970462 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistMeasuresStep.java @@ -20,24 +20,23 @@ package org.sonar.server.computation.step; -import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; import java.util.List; -import javax.annotation.CheckForNull; +import java.util.Map; import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.rule.RuleKey; -import org.sonar.batch.protocol.output.BatchReport; import org.sonar.core.measure.db.MeasureDto; import org.sonar.core.persistence.DbSession; -import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.DbIdsRepository; import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor; import org.sonar.server.computation.component.TreeRootHolder; -import org.sonar.server.computation.issue.RuleCache; -import org.sonar.server.computation.measure.MetricCache; +import org.sonar.server.computation.measure.Measure; +import org.sonar.server.computation.measure.MeasureRepository; +import org.sonar.server.computation.measure.MeasureToMeasureDto; +import org.sonar.server.computation.metric.Metric; +import org.sonar.server.computation.metric.MetricRepository; import org.sonar.server.db.DbClient; -import static com.google.common.collect.Lists.newArrayList; import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.PRE_ORDER; public class PersistMeasuresStep implements ComputationStep { @@ -45,23 +44,21 @@ public class PersistMeasuresStep implements ComputationStep { /** * List of metrics that should not be received from the report, as they should only by fed by the compute engine */ - private static final List FORBIDDEN_METRIC_KEYS = newArrayList(CoreMetrics.DUPLICATIONS_DATA_KEY); + private static final List FORBIDDEN_METRIC_KEYS = ImmutableList.of(CoreMetrics.DUPLICATIONS_DATA_KEY); private final DbClient dbClient; - private final RuleCache ruleCache; - private final MetricCache metricCache; + private final MetricRepository metricRepository; private final DbIdsRepository dbIdsRepository; private final TreeRootHolder treeRootHolder; - private final BatchReportReader reportReader; + private final MeasureRepository measureRepository; - public PersistMeasuresStep(DbClient dbClient, RuleCache ruleCache, MetricCache metricCache, DbIdsRepository dbIdsRepository, TreeRootHolder treeRootHolder, - BatchReportReader reportReader) { + public PersistMeasuresStep(DbClient dbClient, MetricRepository metricRepository, DbIdsRepository dbIdsRepository, + TreeRootHolder treeRootHolder, MeasureRepository measureRepository) { this.dbClient = dbClient; - this.ruleCache = ruleCache; - this.metricCache = metricCache; + this.metricRepository = metricRepository; this.dbIdsRepository = dbIdsRepository; this.treeRootHolder = treeRootHolder; - this.reportReader = reportReader; + this.measureRepository = measureRepository; } @Override @@ -81,7 +78,6 @@ public class PersistMeasuresStep implements ComputationStep { } private class MeasureVisitor extends DepthTraversalTypeAwareVisitor { - private final DbSession session; private MeasureVisitor(DbSession session) { @@ -91,74 +87,25 @@ public class PersistMeasuresStep implements ComputationStep { @Override public void visitAny(Component component) { - int componentRef = component.getRef(); - List measures = reportReader.readComponentMeasures(componentRef); - persistMeasures(measures, dbIdsRepository.getComponentId(component), dbIdsRepository.getSnapshotId(component)); - } - - private void persistMeasures(List batchReportMeasures, long componentId, long snapshotId) { - for (BatchReport.Measure measure : batchReportMeasures) { - if (FORBIDDEN_METRIC_KEYS.contains(measure.getMetricKey())) { - throw new IllegalStateException(String.format("Measures on metric '%s' cannot be send in the report", measure.getMetricKey())); - } - dbClient.measureDao().insert(session, toMeasureDto(measure, componentId, snapshotId)); - } - } - } + Map measures = measureRepository.getRawMeasures(component); + long componentId = dbIdsRepository.getComponentId(component); + long snapshotId = dbIdsRepository.getSnapshotId(component); - @VisibleForTesting - MeasureDto toMeasureDto(BatchReport.Measure in, long componentId, long snapshotId) { - if (!in.hasValueType()) { - throw new IllegalStateException(String.format("Measure %s does not have value type", in)); - } - if (!in.hasMetricKey()) { - throw new IllegalStateException(String.format("Measure %s does not have metric key", in)); + persistMeasures(measures, componentId, snapshotId); } - MeasureDto out = new MeasureDto(); - out.setVariation(1, in.hasVariationValue1() ? in.getVariationValue1() : null); - out.setVariation(2, in.hasVariationValue2() ? in.getVariationValue2() : null); - out.setVariation(3, in.hasVariationValue3() ? in.getVariationValue3() : null); - out.setVariation(4, in.hasVariationValue4() ? in.getVariationValue4() : null); - out.setVariation(5, in.hasVariationValue5() ? in.getVariationValue5() : null); - out.setAlertStatus(in.hasAlertStatus() ? in.getAlertStatus() : null); - out.setAlertText(in.hasAlertText() ? in.getAlertText() : null); - out.setDescription(in.hasDescription() ? in.getDescription() : null); - out.setComponentId(componentId); - out.setSnapshotId(snapshotId); - out.setMetricId(metricCache.get(in.getMetricKey()).getId()); - out.setRuleId(in.hasRuleKey() ? ruleCache.get(RuleKey.parse(in.getRuleKey())).getId() : null); - out.setCharacteristicId(in.hasCharactericId() ? in.getCharactericId() : null); - out.setPersonId(in.hasPersonId() ? in.getPersonId() : null); - out.setValue(valueAsDouble(in)); - setData(in, out); - return out; - } + private void persistMeasures(Map batchReportMeasures, long componentId, long snapshotId) { + for (Map.Entry measure : batchReportMeasures.entrySet()) { + String metricKey = measure.getKey(); + if (FORBIDDEN_METRIC_KEYS.contains(metricKey)) { + throw new IllegalStateException(String.format("Measures on metric '%s' cannot be send in the report", metricKey)); + } - private static MeasureDto setData(BatchReport.Measure in, MeasureDto out) { - if (in.hasStringValue()) { - out.setData(in.getStringValue()); + Metric metric = metricRepository.getByKey(metricKey); + MeasureDto measureDto = MeasureToMeasureDto.INSTANCE.toMeasureDto(measure.getValue(), metric, componentId, snapshotId); + dbClient.measureDao().insert(session, measureDto); + } } - return out; } - /** - * return the numerical value as a double. It's the type used in db. - * Returns null if no numerical value found - */ - @CheckForNull - private static Double valueAsDouble(BatchReport.Measure measure) { - switch (measure.getValueType()) { - case BOOLEAN: - return measure.hasBooleanValue() ? (measure.getBooleanValue() ? 1.0d : 0.0d) : null; - case INT: - return measure.hasIntValue() ? (double) measure.getIntValue() : null; - case LONG: - return measure.hasLongValue() ? (double) measure.getLongValue() : null; - case DOUBLE: - return measure.hasDoubleValue() ? measure.getDoubleValue() : null; - default: - return null; - } - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureToMeasureDtoTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureToMeasureDtoTest.java new file mode 100644 index 00000000000..777cae00802 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureToMeasureDtoTest.java @@ -0,0 +1,210 @@ +/* + * 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.measure; + +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.sonar.core.measure.db.MeasureDto; +import org.sonar.server.computation.metric.Metric; +import org.sonar.server.computation.metric.MetricImpl; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(DataProviderRunner.class) +public class MeasureToMeasureDtoTest { + private static final MetricImpl SOME_METRIC = new MetricImpl(42, "metric_key", "metric_name", Metric.MetricType.STRING); + private static final int SOME_COMPONENT_ID = 951; + private static final int SOME_SNAPSHOT_ID = 753; + private static final String SOME_DATA = "some_data"; + private static final String SOME_STRING = "some_string"; + private static final MeasureVariations SOME_VARIATIONS = new MeasureVariations(1d, 2d, 3d, 4d, 5d); + private static final MetricImpl SOME_BOOLEAN_METRIC = new MetricImpl(1, "1", "1", Metric.MetricType.BOOL); + private static final MetricImpl SOME_INT_METRIC = new MetricImpl(2, "2", "2", Metric.MetricType.INT); + private static final MetricImpl SOME_LONG_METRIC = new MetricImpl(3, "3", "3", Metric.MetricType.DISTRIB); + private static final MetricImpl SOME_DOUBLE_METRIC = new MetricImpl(4, "4", "4", Metric.MetricType.FLOAT); + private static final MetricImpl SOME_STRING_METRIC = new MetricImpl(5, "5", "5", Metric.MetricType.STRING); + private static final MetricImpl SOME_LEVEL_METRIC = new MetricImpl(6, "6", "6", Metric.MetricType.LEVEL); + + private final MeasureToMeasureDto underTest = MeasureToMeasureDto.INSTANCE; + + @Test(expected = NullPointerException.class) + public void toMeasureDto_throws_NPE_if_Measure_arg_is_null() { + underTest.toMeasureDto(null, SOME_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + } + + @Test(expected = NullPointerException.class) + public void toMeasureDto_throws_NPE_if_Metric_arg_is_null() { + underTest.toMeasureDto(MeasureImpl.builder().createNoValue(), null, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + } + + @DataProvider + public static Object[][] all_types_MeasureImpls() { + return new Object[][] { + { MeasureImpl.builder().create(true, SOME_DATA), SOME_BOOLEAN_METRIC}, + { MeasureImpl.builder().create(1, SOME_DATA), SOME_INT_METRIC}, + { MeasureImpl.builder().create((long) 1, SOME_DATA), SOME_LONG_METRIC}, + { MeasureImpl.builder().create((double) 2, SOME_DATA), SOME_DOUBLE_METRIC}, + { MeasureImpl.builder().create(SOME_STRING), SOME_STRING_METRIC}, + { MeasureImpl.builder().create(Measure.Level.OK), SOME_LEVEL_METRIC} + }; + } + + @Test + @UseDataProvider("all_types_MeasureImpls") + public void toMeasureDto_returns_Dto_without_any_variation_if_Measure_has_no_MeasureVariations(MeasureImpl measure, Metric metric) { + MeasureDto measureDto = underTest.toMeasureDto(measure, metric, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(measureDto.getVariation(1)).isNull(); + assertThat(measureDto.getVariation(2)).isNull(); + assertThat(measureDto.getVariation(3)).isNull(); + assertThat(measureDto.getVariation(4)).isNull(); + assertThat(measureDto.getVariation(5)).isNull(); + } + + @Test + @UseDataProvider("all_types_MeasureImpls") + public void toMeasureDto_returns_Dto_with_variation_if_Measure_has_MeasureVariations(MeasureImpl measure, Metric metric) { + MeasureDto measureDto = underTest.toMeasureDto(measure.setVariations(SOME_VARIATIONS), metric, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(measureDto.getVariation(1)).isEqualTo(1d); + assertThat(measureDto.getVariation(2)).isEqualTo(2d); + assertThat(measureDto.getVariation(3)).isEqualTo(3d); + assertThat(measureDto.getVariation(4)).isEqualTo(4d); + assertThat(measureDto.getVariation(5)).isEqualTo(5d); + } + + @Test + @UseDataProvider("all_types_MeasureImpls") + public void toMeasureDto_returns_Dto_without_alertStatus_nor_alertText_if_Measure_has_no_QualityGateStatus(MeasureImpl measure, Metric metric) { + MeasureDto measureDto = underTest.toMeasureDto(measure, metric, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(measureDto.getAlertStatus()).isNull(); + assertThat(measureDto.getAlertText()).isNull(); + } + + @Test + @UseDataProvider("all_types_MeasureImpls") + public void toMeasureDto_returns_Dto_with_alertStatus_and_alertText_if_Measure_has_QualityGateStatus(MeasureImpl measure, Metric metric) { + String alertText = "some error"; + MeasureDto measureDto = underTest.toMeasureDto(measure.setQualityGateStatus(new QualityGateStatus(Measure.Level.ERROR, alertText)), metric, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(measureDto.getAlertStatus()).isEqualTo(Measure.Level.ERROR.name()); + assertThat(measureDto.getAlertText()).isEqualTo(alertText); + } + + @Test + @UseDataProvider("all_types_MeasureImpls") + public void toMeasureDto_does_no_set_ruleId_if_not_set_in_Measure(MeasureImpl measure, Metric metric) { + assertThat(underTest.toMeasureDto(measure, metric, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID).getRuleId()).isNull(); + } + + @Test + public void toMeasureDto_sets_ruleId_if_set_in_Measure() { + MeasureImpl measure = MeasureImpl.builder().forRule(42).createNoValue(); + + assertThat(underTest.toMeasureDto(measure, SOME_BOOLEAN_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID).getRuleId()).isEqualTo(42); + } + + @Test + @UseDataProvider("all_types_MeasureImpls") + public void toMeasureDto_does_no_set_characteristicId_if_not_set_in_Measure(MeasureImpl measure, Metric metric) { + assertThat(underTest.toMeasureDto(measure, metric, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID).getCharacteristicId()).isNull(); + } + + @Test + public void toMeasureDto_sets_characteristicId_if_set_in_Measure() { + MeasureImpl measure = MeasureImpl.builder().forCharacteristic(42).createNoValue(); + + assertThat(underTest.toMeasureDto(measure, SOME_BOOLEAN_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID).getCharacteristicId()).isEqualTo(42); + } + + @Test + @UseDataProvider("all_types_MeasureImpls") + public void toMeasureDto_set_componentId_and_snapshotId_from_method_arguments(MeasureImpl measure, Metric metric) { + MeasureDto measureDto = underTest.toMeasureDto(measure, metric, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(measureDto.getComponentId()).isEqualTo(SOME_COMPONENT_ID); + assertThat(measureDto.getSnapshotId()).isEqualTo(SOME_SNAPSHOT_ID); + } + + @Test + @UseDataProvider("all_types_MeasureImpls") + public void toMeasureDto_does_not_set_personId_until_DevCockpit_is_enabled_again(MeasureImpl measure, Metric metric) { + MeasureDto measureDto = underTest.toMeasureDto(measure, metric, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(measureDto.getPersonId()).isNull(); + } + + @Test + public void toMeasureDto_maps_value_to_1_or_0_and_data_from_data_field_for_BOOLEAN_metric() { + MeasureDto trueMeasureDto = underTest.toMeasureDto(MeasureImpl.builder().create(true, SOME_DATA), SOME_BOOLEAN_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(trueMeasureDto.getValue()).isEqualTo(1d); + assertThat(trueMeasureDto.getData()).isEqualTo(SOME_DATA); + + MeasureDto falseMeasureDto = underTest.toMeasureDto(MeasureImpl.builder().create(false, SOME_DATA), SOME_BOOLEAN_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(falseMeasureDto.getValue()).isEqualTo(0d); + assertThat(falseMeasureDto.getData()).isEqualTo(SOME_DATA); + } + + @Test + public void toMeasureDto_maps_value_and_data_from_data_field_for_INT_metric() { + MeasureDto trueMeasureDto = underTest.toMeasureDto(MeasureImpl.builder().create(123, SOME_DATA), SOME_INT_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(trueMeasureDto.getValue()).isEqualTo(123); + assertThat(trueMeasureDto.getData()).isEqualTo(SOME_DATA); + } + + @Test + public void toMeasureDto_maps_value_and_data_from_data_field_for_LONG_metric() { + MeasureDto trueMeasureDto = underTest.toMeasureDto(MeasureImpl.builder().create((long) 456, SOME_DATA), SOME_LONG_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(trueMeasureDto.getValue()).isEqualTo(456); + assertThat(trueMeasureDto.getData()).isEqualTo(SOME_DATA); + } + + @Test + public void toMeasureDto_maps_value_and_data_from_data_field_for_DOUBLE_metric() { + MeasureDto trueMeasureDto = underTest.toMeasureDto(MeasureImpl.builder().create((double) 789, SOME_DATA), SOME_DOUBLE_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(trueMeasureDto.getValue()).isEqualTo(789); + assertThat(trueMeasureDto.getData()).isEqualTo(SOME_DATA); + } + + @Test + public void toMeasureDto_maps_to_only_data_for_STRING_metric() { + MeasureDto trueMeasureDto = underTest.toMeasureDto(MeasureImpl.builder().create(SOME_STRING), SOME_STRING_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(trueMeasureDto.getValue()).isNull(); + assertThat(trueMeasureDto.getData()).isEqualTo(SOME_STRING); + } + + @Test + public void toMeasureDto_maps_name_of_Level_to_data_and_has_no_value_for_LEVEL_metric() { + MeasureDto trueMeasureDto = underTest.toMeasureDto(MeasureImpl.builder().create(Measure.Level.OK), SOME_LEVEL_METRIC, SOME_COMPONENT_ID, SOME_SNAPSHOT_ID); + + assertThat(trueMeasureDto.getValue()).isNull(); + assertThat(trueMeasureDto.getData()).isEqualTo(Measure.Level.OK.name()); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java index 9252828d997..5f2921ae468 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java @@ -30,13 +30,11 @@ import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.Severity; import org.sonar.api.utils.System2; import org.sonar.api.utils.internal.Uuids; import org.sonar.batch.protocol.Constants.MeasureValueType; import org.sonar.batch.protocol.output.BatchReport; import org.sonar.core.component.ComponentDto; -import org.sonar.core.measure.db.MeasureDto; import org.sonar.core.metric.db.MetricDto; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.DbTester; @@ -49,7 +47,9 @@ import org.sonar.server.computation.component.DbIdsRepository; import org.sonar.server.computation.component.DumbComponent; import org.sonar.server.computation.issue.RuleCache; import org.sonar.server.computation.issue.RuleCacheLoader; -import org.sonar.server.computation.measure.MetricCache; +import org.sonar.server.computation.measure.MeasureRepository; +import org.sonar.server.computation.measure.MeasureRepositoryImpl; +import org.sonar.server.computation.metric.MetricRepositoryImpl; import org.sonar.server.db.DbClient; import org.sonar.server.measure.persistence.MeasureDao; import org.sonar.server.metric.persistence.MetricDao; @@ -63,25 +63,22 @@ import static org.assertj.core.api.Assertions.assertThat; public class PersistMeasuresStepTest extends BaseStepTest { private static final String PROJECT_KEY = "PROJECT_KEY"; - private static final String METRIC_KEY = "metric-key"; + private static final String STRING_METRIC_KEY = "string-metric-key"; + private static final String DOUBLE_METRIC_KEY = "double-metric-key"; private static final RuleKey RULE_KEY = RuleKey.of("repo", "rule-key"); - private static final long FILE_COMPONENT_ID = 3L; - private static final long FILE_SNAPSHOT_ID = 3L; - @ClassRule public static DbTester dbTester = new DbTester(); - @Rule public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); - @Rule public BatchReportReaderRule reportReader = new BatchReportReaderRule(); DbClient dbClient; DbSession session; DbIdsRepository dbIdsRepository = new DbIdsRepository(); - MetricDto metric; + MetricDto stringMetric; + MetricDto doubleMetric; RuleDto rule; PersistMeasuresStep sut; @@ -93,17 +90,21 @@ public class PersistMeasuresStepTest extends BaseStepTest { dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new MeasureDao(), new ComponentDao(), new MetricDao(), new RuleDao(System2.INSTANCE)); session = dbClient.openSession(false); - metric = new MetricDto().setKey(METRIC_KEY).setEnabled(true).setOptimizedBestValue(false).setHidden(false).setDeleteHistoricalData(false); - dbClient.metricDao().insert(session, metric); + stringMetric = new MetricDto().setValueType("STRING").setShortName("String metric").setKey(STRING_METRIC_KEY).setEnabled(true); + dbClient.metricDao().insert(session, stringMetric); + doubleMetric = new MetricDto().setValueType("FLOAT").setShortName("Double metric").setKey(DOUBLE_METRIC_KEY).setEnabled(true); + dbClient.metricDao().insert(session, doubleMetric); rule = RuleTesting.newDto(RULE_KEY); dbClient.ruleDao().insert(session, rule); session.commit(); RuleCache ruleCache = new RuleCache(new RuleCacheLoader(dbClient)); - MetricCache metricCache = new MetricCache(dbClient); + MetricRepositoryImpl metricRepository = new MetricRepositoryImpl(dbClient); + metricRepository.start(); + MeasureRepository measureRepository = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository, ruleCache); session.commit(); - sut = new PersistMeasuresStep(dbClient, ruleCache, metricCache, dbIdsRepository, treeRootHolder, reportReader); + sut = new PersistMeasuresStep(dbClient, metricRepository, dbIdsRepository, treeRootHolder, measureRepository); } @After @@ -113,8 +114,8 @@ public class PersistMeasuresStepTest extends BaseStepTest { @Test public void insert_measures_from_report() throws Exception { - ComponentDto projectDto = addComponent(1, "project-key"); - ComponentDto fileDto = addComponent(2, "file-key"); + ComponentDto projectDto = addComponent("project-key"); + ComponentDto fileDto = addComponent("file-key"); Component file = DumbComponent.builder(Component.Type.FILE, 2).setUuid("CDEF").setKey("MODULE_KEY:file").build(); Component project = DumbComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).addChildren(file).build(); @@ -137,8 +138,7 @@ public class PersistMeasuresStepTest extends BaseStepTest { .setAlertStatus("WARN") .setAlertText("Open issues > 0") .setDescription("measure-description") - .setMetricKey(METRIC_KEY) - .setRuleKey(RULE_KEY.toString()) + .setMetricKey(STRING_METRIC_KEY) .setCharactericId(123456) .build())); @@ -154,9 +154,8 @@ public class PersistMeasuresStepTest extends BaseStepTest { .setAlertStatus("ERROR") .setAlertText("Blocker issues variation > 0") .setDescription("measure-description") - .setMetricKey(METRIC_KEY) + .setMetricKey(DOUBLE_METRIC_KEY) .setRuleKey(RULE_KEY.toString()) - .setCharactericId(123456) .build())); sut.execute(); @@ -165,234 +164,28 @@ public class PersistMeasuresStepTest extends BaseStepTest { assertThat(dbTester.countRowsOfTable("project_measures")).isEqualTo(2); List> dtos = dbTester.select( - "select snapshot_id as \"snapshotId\", project_id as \"componentId\", metric_id as \"metricId\", rule_id as \"ruleId\", value as \"value\", text_value as \"textValue\" " + - " from project_measures"); + "select snapshot_id as \"snapshotId\", project_id as \"componentId\", metric_id as \"metricId\", rule_id as \"ruleId\", value as \"value\", text_value as \"textValue\", " + + "rule_priority as \"severity\" from project_measures"); Map dto = dtos.get(0); assertThat(dto.get("snapshotId")).isEqualTo(3L); assertThat(dto.get("componentId")).isEqualTo(projectDto.getId()); - assertThat(dto.get("metricId")).isEqualTo(metric.getId().longValue()); - assertThat(dto.get("ruleId")).isEqualTo(rule.getId().longValue()); + assertThat(dto.get("metricId")).isEqualTo(stringMetric.getId().longValue()); + assertThat(dto.get("ruleId")).isNull(); assertThat(dto.get("textValue")).isEqualTo("measure-data"); + assertThat(dto.get("severity")).isNull(); dto = dtos.get(1); assertThat(dto.get("snapshotId")).isEqualTo(4L); assertThat(dto.get("componentId")).isEqualTo(fileDto.getId()); - assertThat(dto.get("metricId")).isEqualTo(metric.getId().longValue()); + assertThat(dto.get("metricId")).isEqualTo(doubleMetric.getId().longValue()); assertThat(dto.get("ruleId")).isEqualTo(rule.getId().longValue()); + assertThat(dto.get("characteristicId")).isNull(); assertThat(dto.get("value")).isEqualTo(123.123d); + assertThat(dto.get("severity")).isNull(); } - @Test - public void map_full_batch_measure() { - BatchReport.Component component = defaultComponent().build(); - ComponentDto componentDto = addComponent(component.getRef(), "component-key"); - - BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.DOUBLE) - .setDoubleValue(123.123d) - .setVariationValue1(1.1d) - .setVariationValue2(2.2d) - .setVariationValue3(3.3d) - .setVariationValue4(4.4d) - .setVariationValue5(5.5d) - .setAlertStatus("WARN") - .setAlertText("Open issues > 0") - .setDescription("measure-description") - .setMetricKey(METRIC_KEY) - .setRuleKey(RULE_KEY.toString()) - .setCharactericId(123456) - .setPersonId(5432) - .build(); - - MeasureDto measure = sut.toMeasureDto(batchMeasure, componentDto.getId(), FILE_SNAPSHOT_ID); - - assertThat(measure).isEqualToComparingFieldByField(new MeasureDto() - .setComponentId(componentDto.getId()) - .setSnapshotId(3L) - .setCharacteristicId(123456) - .setPersonId(5432) - .setValue(123.123d) - .setVariation(1, 1.1d) - .setVariation(2, 2.2d) - .setVariation(3, 3.3d) - .setVariation(4, 4.4d) - .setVariation(5, 5.5d) - .setAlertStatus("WARN") - .setAlertText("Open issues > 0") - .setDescription("measure-description") - .setMetricId(metric.getId()) - .setRuleId(rule.getId())); - } - - @Test - public void map_minimal_batch_measure() { - BatchReport.Component component = defaultComponent().build(); - ComponentDto componentDto = addComponent(component.getRef(), "component-key"); - - BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.INT) - .setMetricKey(METRIC_KEY) - .build(); - - MeasureDto measure = sut.toMeasureDto(batchMeasure, componentDto.getId(), FILE_SNAPSHOT_ID); - - assertThat(measure).isEqualToComparingFieldByField(new MeasureDto() - .setComponentId(componentDto.getId()) - .setSnapshotId(FILE_SNAPSHOT_ID) - .setMetricId(metric.getId())); - } - - @Test - public void map_boolean_batch_measure() { - BatchReport.Component component = defaultComponent().build(); - addComponent(component.getRef(), "component-key"); - - BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.BOOLEAN) - .setBooleanValue(true) - .setMetricKey(METRIC_KEY) - .build(); - - MeasureDto measure = sut.toMeasureDto(batchMeasure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - - assertThat(measure.getValue()).isEqualTo(1.0); - - batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.BOOLEAN) - .setBooleanValue(false) - .setMetricKey(METRIC_KEY) - .build(); - - measure = sut.toMeasureDto(batchMeasure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - - assertThat(measure.getValue()).isEqualTo(0.0); - - batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.BOOLEAN) - .setMetricKey(METRIC_KEY) - .build(); - - measure = sut.toMeasureDto(batchMeasure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - - assertThat(measure.getValue()).isNull(); - } - - @Test - public void map_double_batch_measure() { - BatchReport.Component component = defaultComponent().build(); - addComponent(component.getRef(), "component-key"); - - BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.DOUBLE) - .setDoubleValue(3.2) - .setMetricKey(METRIC_KEY) - .build(); - - MeasureDto measure = sut.toMeasureDto(batchMeasure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - - assertThat(measure.getValue()).isEqualTo(3.2); - - batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.DOUBLE) - .setMetricKey(METRIC_KEY) - .build(); - - measure = sut.toMeasureDto(batchMeasure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - - assertThat(measure.getValue()).isNull(); - } - - @Test - public void map_int_batch_measure() { - BatchReport.Component component = defaultComponent().build(); - addComponent(component.getRef(), "component-key"); - - BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.INT) - .setIntValue(3) - .setMetricKey(METRIC_KEY) - .build(); - - MeasureDto measure = sut.toMeasureDto(batchMeasure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - - assertThat(measure.getValue()).isEqualTo(3.0); - - batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.INT) - .setMetricKey(METRIC_KEY) - .build(); - - measure = sut.toMeasureDto(batchMeasure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - - assertThat(measure.getValue()).isNull(); - } - - @Test - public void map_long_batch_measure() { - BatchReport.Component component = defaultComponent().build(); - addComponent(component.getRef(), "component-key"); - - BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.LONG) - .setLongValue(3L) - .setMetricKey(METRIC_KEY) - .build(); - - MeasureDto measure = sut.toMeasureDto(batchMeasure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - - assertThat(measure.getValue()).isEqualTo(3.0); - - batchMeasure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.LONG) - .setMetricKey(METRIC_KEY) - .build(); - - measure = sut.toMeasureDto(batchMeasure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - - assertThat(measure.getValue()).isNull(); - } - - @Test(expected = IllegalStateException.class) - public void fail_when_no_metric_key() { - BatchReport.Measure measure = BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.STRING) - .setStringValue("string-value") - .build(); - BatchReport.Component component = defaultComponent() - .build(); - addComponent(component.getRef(), "component-key"); - sut.toMeasureDto(measure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - } - - @Test(expected = IllegalStateException.class) - public void fail_when_no_value() { - BatchReport.Measure measure = BatchReport.Measure.newBuilder() - .setMetricKey("repo:metric-key") - .build(); - BatchReport.Component component = defaultComponent() - .build(); - addComponent(component.getRef(), "component-key"); - sut.toMeasureDto(measure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - } - - @Test(expected = IllegalStateException.class) - public void fail_when_forbid_metric() { - BatchReport.Measure measure = BatchReport.Measure.newBuilder() - .setMetricKey("duplications_data") - .build(); - BatchReport.Component component = defaultComponent() - .build(); - addComponent(component.getRef(), "component-key"); - sut.toMeasureDto(measure, FILE_COMPONENT_ID, FILE_SNAPSHOT_ID); - } - - private BatchReport.Component.Builder defaultComponent() { - return BatchReport.Component.newBuilder() - .setRef(1); - } - - private ComponentDto addComponent(int ref, String key) { + private ComponentDto addComponent(String key) { ComponentDto componentDto = new ComponentDto().setKey(key).setUuid(Uuids.create()); dbClient.componentDao().insert(session, componentDto); session.commit(); -- 2.39.5