diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-07-10 12:33:09 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-07-15 10:44:32 +0200 |
commit | cc6e6c4ba3e48371736d5b3bfffbed39e43fef9b (patch) | |
tree | 1178a3a3748b347632ec506b22361781a7763414 | |
parent | 698e9952c6d633a49c7f1611ea978f811fdab12b (diff) | |
download | sonarqube-cc6e6c4ba3e48371736d5b3bfffbed39e43fef9b.tar.gz sonarqube-cc6e6c4ba3e48371736d5b3bfffbed39e43fef9b.zip |
Filter metrics that can be read from the batch
Only plugin metrics and some defined core metrics are allowed to be read from the batch
11 files changed, 499 insertions, 41 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java index bf03be56377..ebd3a564caf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java @@ -29,10 +29,9 @@ import org.picocontainer.lifecycle.ReflectionLifecycleStrategy; import org.picocontainer.monitors.NullComponentMonitor; import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Profiler; -import org.sonar.core.platform.Module; -import org.sonar.server.computation.issue.UpdateConflictResolver; import org.sonar.core.issue.tracking.Tracker; import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.Module; import org.sonar.server.computation.ComputationService; import org.sonar.server.computation.ReportQueue; import org.sonar.server.computation.activity.ActivityManager; @@ -63,10 +62,11 @@ import org.sonar.server.computation.issue.ScmAccountToUserLoader; import org.sonar.server.computation.issue.TrackerBaseInputFactory; import org.sonar.server.computation.issue.TrackerExecution; import org.sonar.server.computation.issue.TrackerRawInputFactory; +import org.sonar.server.computation.issue.UpdateConflictResolver; import org.sonar.server.computation.language.LanguageRepositoryImpl; import org.sonar.server.computation.measure.MeasureRepositoryImpl; import org.sonar.server.computation.measure.newcoverage.NewCoverageMetricKeysModule; -import org.sonar.server.computation.metric.MetricRepositoryImpl; +import org.sonar.server.computation.metric.MetricModule; import org.sonar.server.computation.period.PeriodsHolderImpl; import org.sonar.server.computation.qualitygate.EvaluationResultTextConverterImpl; import org.sonar.server.computation.qualitygate.QualityGateHolderImpl; @@ -143,6 +143,8 @@ public class ComputeEngineContainerImpl extends ComponentContainer implements Co return Arrays.asList( ActivityManager.class, + MetricModule.class, + // holders BatchReportDirectoryHolderImpl.class, TreeRootHolderImpl.class, @@ -155,7 +157,6 @@ public class ComputeEngineContainerImpl extends ComponentContainer implements Co // repositories LanguageRepositoryImpl.class, - MetricRepositoryImpl.class, MeasureRepositoryImpl.class, EventRepositoryImpl.class, ProjectSettingsRepository.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java index 4a180c4655b..04b5fa46cb2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java @@ -37,6 +37,7 @@ import org.sonar.server.computation.component.Component; import org.sonar.server.computation.debt.Characteristic; import org.sonar.server.computation.metric.Metric; import org.sonar.server.computation.metric.MetricRepository; +import org.sonar.server.computation.metric.ReportMetricValidator; import static com.google.common.base.Preconditions.checkArgument; import static java.lang.String.format; @@ -47,13 +48,16 @@ public class MeasureRepositoryImpl implements MeasureRepository { private final BatchReportReader reportReader; private final BatchMeasureToMeasure batchMeasureToMeasure; private final MetricRepository metricRepository; + private final ReportMetricValidator reportMetricValidator; + private final MeasureDtoToMeasure measureDtoToMeasure = new MeasureDtoToMeasure(); private final Set<Integer> loadedComponents = new HashSet<>(); private final Map<Integer, Map<MeasureKey, Measure>> measures = new HashMap<>(); - public MeasureRepositoryImpl(DbClient dbClient, BatchReportReader reportReader, MetricRepository metricRepository) { + public MeasureRepositoryImpl(DbClient dbClient, BatchReportReader reportReader, MetricRepository metricRepository, ReportMetricValidator reportMetricValidator) { this.dbClient = dbClient; this.reportReader = reportReader; + this.reportMetricValidator = reportMetricValidator; this.batchMeasureToMeasure = new BatchMeasureToMeasure(); this.metricRepository = metricRepository; } @@ -181,8 +185,11 @@ public class MeasureRepositoryImpl implements MeasureRepository { } for (BatchReport.Measure batchMeasure : reportReader.readComponentMeasures(component.getRef())) { - Metric metric = metricRepository.getByKey(batchMeasure.getMetricKey()); - addLocal(component, metric, batchMeasureToMeasure.toMeasure(batchMeasure, metric).get(), OverridePolicy.DO_NOT_OVERRIDE); + String metricKey = batchMeasure.getMetricKey(); + if (reportMetricValidator.validate(metricKey)) { + Metric metric = metricRepository.getByKey(metricKey); + addLocal(component, metric, batchMeasureToMeasure.toMeasure(batchMeasure, metric).get(), OverridePolicy.DO_NOT_OVERRIDE); + } } loadedComponents.add(component.getRef()); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/metric/MetricModule.java b/server/sonar-server/src/main/java/org/sonar/server/computation/metric/MetricModule.java new file mode 100644 index 00000000000..becdb49bff3 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/metric/MetricModule.java @@ -0,0 +1,34 @@ +/* + * 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.metric; + +import org.sonar.core.metric.SensorMetrics; +import org.sonar.core.platform.Module; + +public class MetricModule extends Module { + @Override + protected void configureModule() { + add( + SensorMetrics.class, + ReportMetricValidatorImpl.class, + MetricRepositoryImpl.class); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/metric/ReportMetricValidator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/metric/ReportMetricValidator.java new file mode 100644 index 00000000000..e5c66fee0d3 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/metric/ReportMetricValidator.java @@ -0,0 +1,30 @@ +/* + * 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.metric; + +/** + * Validate metric to know if it can be read from the batch + */ +public interface ReportMetricValidator { + + boolean validate(String metricKey); + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/metric/ReportMetricValidatorImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/metric/ReportMetricValidatorImpl.java new file mode 100644 index 00000000000..851dc8ae93f --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/metric/ReportMetricValidatorImpl.java @@ -0,0 +1,67 @@ +/* + * 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.metric; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.metric.SensorMetrics; + +public class ReportMetricValidatorImpl implements ReportMetricValidator { + + private static final Logger LOG = Loggers.get(ReportMetricValidatorImpl.class); + + private Map<String, org.sonar.api.measures.Metric> metricByKey; + private Set<String> alreadyLoggedMetricKeys = new HashSet<>(); + + public ReportMetricValidatorImpl(SensorMetrics sensorMetrics) { + this.metricByKey = FluentIterable.from(sensorMetrics.getMetrics()).uniqueIndex(MetricToKey.INSTANCE); + } + + @Override + public boolean validate(String metricKey) { + org.sonar.api.measures.Metric metric = metricByKey.get(metricKey); + if (metric == null) { + if (!alreadyLoggedMetricKeys.contains(metricKey)) { + LOG.warn("The metric '{}' is ignored and should not be send in the batch report", metricKey); + alreadyLoggedMetricKeys.add(metricKey); + } + return false; + } + return true; + } + + private enum MetricToKey implements Function<org.sonar.api.measures.Metric, String> { + INSTANCE; + + @Nullable + @Override + public String apply(@Nonnull org.sonar.api.measures.Metric input) { + return input.key(); + } + } +} 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 263517c5349..a6f6c47e552 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 @@ -29,8 +29,9 @@ import java.util.List; import java.util.Map; import javax.annotation.Nonnull; import org.sonar.api.measures.CoreMetrics; -import org.sonar.db.measure.MeasureDto; +import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.measure.MeasureDto; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.DbIdsRepository; import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor; @@ -41,7 +42,6 @@ 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.db.DbClient; import static com.google.common.collect.FluentIterable.from; import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER; @@ -49,12 +49,7 @@ import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ public class PersistMeasuresStep implements ComputationStep { /** - * List of metrics that should not be received from the report, as they should only be fed by the compute engine - */ - private static final List<String> FORBIDDEN_METRIC_KEYS = ImmutableList.of(CoreMetrics.DUPLICATIONS_DATA_KEY); - - /** - * List of metrics that should be persisted on file measure (Waiting for SONAR-6688 to be implemented) + * List of metrics that should not be persisted on file measure (Waiting for SONAR-6688 to be implemented) */ private static final List<String> NOT_TO_PERSIST_ON_FILE_METRIC_KEYS = ImmutableList.of( CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION_KEY, @@ -112,9 +107,6 @@ public class PersistMeasuresStep implements ComputationStep { private void persistMeasures(Component component, Multimap<String, Measure> batchReportMeasures, long componentId, long snapshotId) { for (Map.Entry<String, Collection<Measure>> measures : batchReportMeasures.asMap().entrySet()) { String metricKey = measures.getKey(); - if (FORBIDDEN_METRIC_KEYS.contains(metricKey)) { - throw new IllegalStateException(String.format("Measures on metric '%s' cannot be send in the report", metricKey)); - } if (NOT_TO_PERSIST_ON_FILE_METRIC_KEYS.contains(metricKey) && component.getType() == Component.Type.FILE) { continue; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java index 114c1305c84..d5d704afd3a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java @@ -53,6 +53,7 @@ import org.sonar.server.computation.debt.Characteristic; import org.sonar.server.computation.metric.Metric; import org.sonar.server.computation.metric.MetricImpl; import org.sonar.server.computation.metric.MetricRepository; +import org.sonar.server.computation.metric.ReportMetricValidator; import org.sonar.server.db.DbClient; import org.sonar.server.metric.persistence.MetricDao; @@ -90,13 +91,15 @@ public class MeasureRepositoryImplTest { private static final RuleDto SOME_RULE = RuleDto.createFor(RuleKey.of("A", "1")).setId(963); private static final Characteristic SOME_CHARACTERISTIC = new Characteristic(741, "key", null); + private ReportMetricValidator reportMetricValidator = mock(ReportMetricValidator.class); + private DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new MeasureDao(), new SnapshotDao(), new MetricDao(), new ComponentDao()); private MetricRepository metricRepository = mock(MetricRepository.class); - private MeasureRepositoryImpl underTest = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository); + private MeasureRepositoryImpl underTest = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository, reportMetricValidator); private DbClient mockedDbClient = mock(DbClient.class); private BatchReportReader mockBatchReportReader = mock(BatchReportReader.class); - private MeasureRepositoryImpl underTestWithMock = new MeasureRepositoryImpl(mockedDbClient, mockBatchReportReader, metricRepository); + private MeasureRepositoryImpl underTestWithMock = new MeasureRepositoryImpl(mockedDbClient, mockBatchReportReader, metricRepository, reportMetricValidator); @CheckForNull private DbSession dbSession; @@ -217,7 +220,7 @@ public class MeasureRepositoryImplTest { Measure.newMeasureBuilder().create("sds"), Measure.newMeasureBuilder().create(Measure.Level.OK), Measure.newMeasureBuilder().createNoValue() - ); + ); @DataProvider public static Object[][] measures() { @@ -225,7 +228,7 @@ public class MeasureRepositoryImplTest { @Nullable @Override public Object[] apply(Measure input) { - return new Measure[]{input}; + return new Measure[] {input}; } }).toArray(Object[].class); } @@ -352,9 +355,11 @@ public class MeasureRepositoryImplTest { public void getRawMeasure_returns_measure_from_batch_if_not_added_through_add_method() { String value = "trololo"; + when(reportMetricValidator.validate(METRIC_KEY_1)).thenReturn(true); + reportReader.putMeasures(FILE_COMPONENT.getRef(), ImmutableList.of( BatchReport.Measure.newBuilder().setMetricKey(METRIC_KEY_1).setStringValue(value).build() - )); + )); Optional<Measure> res = underTest.getRawMeasure(FILE_COMPONENT, metric1); @@ -367,10 +372,25 @@ public class MeasureRepositoryImplTest { } @Test + public void getRawMeasure_returns_only_validate_measure_from_batch_if_not_added_through_add_method() { + when(reportMetricValidator.validate(METRIC_KEY_1)).thenReturn(true); + when(reportMetricValidator.validate(METRIC_KEY_2)).thenReturn(false); + + reportReader.putMeasures(FILE_COMPONENT.getRef(), ImmutableList.of( + BatchReport.Measure.newBuilder().setMetricKey(METRIC_KEY_1).setStringValue("value1").build(), + BatchReport.Measure.newBuilder().setMetricKey(METRIC_KEY_2).setStringValue("value2").build() + )); + + assertThat(underTest.getRawMeasure(FILE_COMPONENT, metric1)).isPresent(); + assertThat(underTest.getRawMeasure(FILE_COMPONENT, metric2)).isAbsent(); + } + + @Test public void getRawMeasure_retrieves_added_measure_over_batch_measure() { + when(reportMetricValidator.validate(METRIC_KEY_1)).thenReturn(true); reportReader.putMeasures(FILE_COMPONENT.getRef(), ImmutableList.of( BatchReport.Measure.newBuilder().setMetricKey(METRIC_KEY_1).setStringValue("some value").build() - )); + )); Measure addedMeasure = SOME_MEASURE; underTest.add(FILE_COMPONENT, metric1, addedMeasure); @@ -383,9 +403,10 @@ public class MeasureRepositoryImplTest { @Test public void getRawMeasure_retrieves_measure_from_batch_and_caches_it_locally_so_that_it_can_be_updated() { + when(reportMetricValidator.validate(METRIC_KEY_1)).thenReturn(true); reportReader.putMeasures(FILE_COMPONENT.getRef(), ImmutableList.of( BatchReport.Measure.newBuilder().setMetricKey(METRIC_KEY_1).setStringValue("some value").build() - )); + )); Optional<Measure> measure = underTest.getRawMeasure(FILE_COMPONENT, metric1); @@ -444,6 +465,7 @@ public class MeasureRepositoryImplTest { @Test public void getRawMeasure_for_characteristic_returns_measure_for_specified_rule() { + when(reportMetricValidator.validate(metric1.getKey())).thenReturn(true); Measure measure = Measure.newMeasureBuilder().forCharacteristic(SOME_CHARACTERISTIC.getId()).createNoValue(); underTest.add(FILE_COMPONENT, metric1, measure); @@ -454,6 +476,8 @@ public class MeasureRepositoryImplTest { @Test public void getRawMeasures_returns_added_measures_over_batch_measures() { + when(reportMetricValidator.validate(METRIC_KEY_1)).thenReturn(true); + when(reportMetricValidator.validate(METRIC_KEY_2)).thenReturn(true); BatchReport.Measure batchMeasure1 = BatchReport.Measure.newBuilder().setMetricKey(METRIC_KEY_1).setStringValue("some value").build(); BatchReport.Measure batchMeasure2 = BatchReport.Measure.newBuilder().setMetricKey(METRIC_KEY_2).setStringValue("some value").build(); reportReader.putMeasures(FILE_COMPONENT.getRef(), ImmutableList.of(batchMeasure1, batchMeasure2)); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/metric/ReportMetricValidatorImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/metric/ReportMetricValidatorImplTest.java new file mode 100644 index 00000000000..5c98e9b31e8 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/metric/ReportMetricValidatorImplTest.java @@ -0,0 +1,74 @@ +/* + * 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.metric; + +import com.google.common.collect.ImmutableSet; +import java.util.Collections; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.measures.Metric; +import org.sonar.api.utils.log.LogTester; +import org.sonar.core.metric.SensorMetrics; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.api.measures.Metric.Builder; +import static org.sonar.api.measures.Metric.ValueType; + +public class ReportMetricValidatorImplTest { + + @Rule + public LogTester logTester = new LogTester(); + + static final String METRIC_KEY = "metric_key"; + + SensorMetrics sensorMetrics = mock(SensorMetrics.class); + + @Test + public void validate_metric() throws Exception { + when(sensorMetrics.getMetrics()).thenReturn(ImmutableSet.<Metric>of(new Builder(METRIC_KEY, "name", ValueType.INT).create())); + ReportMetricValidator validator = new ReportMetricValidatorImpl(sensorMetrics); + + assertThat(validator.validate(METRIC_KEY)).isTrue(); + assertThat(logTester.logs()).isEmpty(); + } + + @Test + public void not_validate_metric() throws Exception { + when(sensorMetrics.getMetrics()).thenReturn(Collections.<Metric>emptySet()); + ReportMetricValidator validator = new ReportMetricValidatorImpl(sensorMetrics); + + assertThat(validator.validate(METRIC_KEY)).isFalse(); + assertThat(logTester.logs()).containsOnly("The metric 'metric_key' is ignored and should not be send in the batch report"); + } + + @Test + public void not_generate_new_log_when_validating_twice_the_same_metric() throws Exception { + when(sensorMetrics.getMetrics()).thenReturn(Collections.<Metric>emptySet()); + ReportMetricValidator validator = new ReportMetricValidatorImpl(sensorMetrics); + + assertThat(validator.validate(METRIC_KEY)).isFalse(); + assertThat(logTester.logs()).hasSize(1); + assertThat(validator.validate(METRIC_KEY)).isFalse(); + assertThat(logTester.logs()).hasSize(1); + } +} 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 b15f3172f69..665ea3c43c7 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 @@ -49,8 +49,6 @@ import org.sonar.server.rule.db.RuleDao; import org.sonar.test.DbTests; import static org.assertj.core.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.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION; import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION_KEY; import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION; @@ -202,20 +200,6 @@ public class PersistMeasuresStepTest extends BaseStepTest { assertThat(retrieveDtos()).isEmpty(); } - @Test(expected = IllegalStateException.class) - public void fail_with_ISE_when_trying_to_insert_forbidden_measures() { - metricRepository.add(1, DUPLICATIONS_DATA); - - reportReader.putMeasures(FILE_REF, Arrays.asList( - BatchReport.Measure.newBuilder() - .setValueType(MeasureValueType.STRING) - .setStringValue("{duplications}") - .setMetricKey(DUPLICATIONS_DATA_KEY) - .build())); - - sut.execute(); - } - @Test public void do_not_insert_file_complexity_distribution_metric_on_files() { metricRepository.add(1, FILE_COMPLEXITY_DISTRIBUTION); diff --git a/sonar-core/src/main/java/org/sonar/core/metric/SensorMetrics.java b/sonar-core/src/main/java/org/sonar/core/metric/SensorMetrics.java new file mode 100644 index 00000000000..52f17def834 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/metric/SensorMetrics.java @@ -0,0 +1,185 @@ +/* + * 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.core.metric; + +import com.google.common.base.Function; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import javax.annotation.Nullable; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.Metrics; + +import static org.sonar.api.measures.CoreMetrics.ACCESSORS; +import static org.sonar.api.measures.CoreMetrics.CLASSES; +import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES; +import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_DATA; +import static org.sonar.api.measures.CoreMetrics.COMPLEXITY; +import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_CLASSES; +import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_FUNCTIONS; +import static org.sonar.api.measures.CoreMetrics.CONDITIONS_BY_LINE; +import static org.sonar.api.measures.CoreMetrics.CONDITIONS_TO_COVER; +import static org.sonar.api.measures.CoreMetrics.COVERAGE_LINE_HITS_DATA; +import static org.sonar.api.measures.CoreMetrics.COVERED_CONDITIONS_BY_LINE; +import static org.sonar.api.measures.CoreMetrics.DIRECTORIES; +import static org.sonar.api.measures.CoreMetrics.DUPLICATED_BLOCKS; +import static org.sonar.api.measures.CoreMetrics.DUPLICATED_FILES; +import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES; +import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY; +import static org.sonar.api.measures.CoreMetrics.FILES; +import static org.sonar.api.measures.CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION; +import static org.sonar.api.measures.CoreMetrics.FUNCTIONS; +import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION; +import static org.sonar.api.measures.CoreMetrics.GENERATED_LINES; +import static org.sonar.api.measures.CoreMetrics.GENERATED_NCLOC; +import static org.sonar.api.measures.CoreMetrics.IT_CONDITIONS_BY_LINE; +import static org.sonar.api.measures.CoreMetrics.IT_CONDITIONS_TO_COVER; +import static org.sonar.api.measures.CoreMetrics.IT_COVERAGE_LINE_HITS_DATA; +import static org.sonar.api.measures.CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE; +import static org.sonar.api.measures.CoreMetrics.IT_LINES_TO_COVER; +import static org.sonar.api.measures.CoreMetrics.IT_UNCOVERED_CONDITIONS; +import static org.sonar.api.measures.CoreMetrics.IT_UNCOVERED_LINES; +import static org.sonar.api.measures.CoreMetrics.LINES; +import static org.sonar.api.measures.CoreMetrics.LINES_TO_COVER; +import static org.sonar.api.measures.CoreMetrics.NCLOC; +import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA; +import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION; +import static org.sonar.api.measures.CoreMetrics.OVERALL_CONDITIONS_BY_LINE; +import static org.sonar.api.measures.CoreMetrics.OVERALL_CONDITIONS_TO_COVER; +import static org.sonar.api.measures.CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA; +import static org.sonar.api.measures.CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE; +import static org.sonar.api.measures.CoreMetrics.OVERALL_LINES_TO_COVER; +import static org.sonar.api.measures.CoreMetrics.OVERALL_UNCOVERED_CONDITIONS; +import static org.sonar.api.measures.CoreMetrics.OVERALL_UNCOVERED_LINES; +import static org.sonar.api.measures.CoreMetrics.PUBLIC_API; +import static org.sonar.api.measures.CoreMetrics.PUBLIC_UNDOCUMENTED_API; +import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES; +import static org.sonar.api.measures.CoreMetrics.SKIPPED_TESTS; +import static org.sonar.api.measures.CoreMetrics.STATEMENTS; +import static org.sonar.api.measures.CoreMetrics.TESTS; +import static org.sonar.api.measures.CoreMetrics.TEST_ERRORS; +import static org.sonar.api.measures.CoreMetrics.TEST_EXECUTION_TIME; +import static org.sonar.api.measures.CoreMetrics.TEST_FAILURES; +import static org.sonar.api.measures.CoreMetrics.TEST_SUCCESS_DENSITY; +import static org.sonar.api.measures.CoreMetrics.UNCOVERED_CONDITIONS; +import static org.sonar.api.measures.CoreMetrics.UNCOVERED_LINES; + +/** + * This class is used to know the list of metrics that can be send by sensor. + * <p/> + * The batch should not send other metrics, and the Compute Engine should not allow other metrics from the batch report. + */ +public class SensorMetrics { + + private static final Set<Metric> ALLOWED_CORE_METRICS = ImmutableSet.<Metric>of( + LINES, + GENERATED_LINES, + NCLOC, + NCLOC_DATA, + GENERATED_NCLOC, + NCLOC_LANGUAGE_DISTRIBUTION, + + COMMENT_LINES, + COMMENT_LINES_DATA, + + PUBLIC_API, + PUBLIC_UNDOCUMENTED_API, + + FILES, + DIRECTORIES, + CLASSES, + FUNCTIONS, + STATEMENTS, + ACCESSORS, + + DUPLICATED_LINES, + DUPLICATED_BLOCKS, + DUPLICATED_FILES, + DUPLICATED_LINES_DENSITY, + + COMPLEXITY, + COMPLEXITY_IN_CLASSES, + COMPLEXITY_IN_FUNCTIONS, + FILE_COMPLEXITY_DISTRIBUTION, + FUNCTION_COMPLEXITY_DISTRIBUTION, + + TESTS, + SKIPPED_TESTS, + TEST_ERRORS, + TEST_FAILURES, + TEST_EXECUTION_TIME, + TEST_SUCCESS_DENSITY, + + LINES_TO_COVER, + UNCOVERED_LINES, + COVERAGE_LINE_HITS_DATA, + CONDITIONS_TO_COVER, + UNCOVERED_CONDITIONS, + COVERED_CONDITIONS_BY_LINE, + CONDITIONS_BY_LINE, + + IT_LINES_TO_COVER, + IT_UNCOVERED_LINES, + IT_COVERAGE_LINE_HITS_DATA, + IT_CONDITIONS_TO_COVER, + IT_UNCOVERED_CONDITIONS, + IT_COVERED_CONDITIONS_BY_LINE, + IT_CONDITIONS_BY_LINE, + + OVERALL_LINES_TO_COVER, + OVERALL_UNCOVERED_LINES, + OVERALL_COVERAGE_LINE_HITS_DATA, + OVERALL_CONDITIONS_TO_COVER, + OVERALL_UNCOVERED_CONDITIONS, + OVERALL_COVERED_CONDITIONS_BY_LINE, + OVERALL_CONDITIONS_BY_LINE, + + QUALITY_PROFILES + ); + + private final Set<Metric> metrics; + + public SensorMetrics(Metrics[] metricsRepositories) { + this.metrics = ImmutableSet.copyOf(Iterables.concat(getPluginMetrics(metricsRepositories), ALLOWED_CORE_METRICS)); + } + + public Set<Metric> getMetrics() { + return metrics; + } + + private static Iterable<Metric> getPluginMetrics(Metrics[] metricsRepositories) { + return FluentIterable.from(Arrays.asList(metricsRepositories)) + .transformAndConcat(FlattenMetrics.INSTANCE); + } + + private enum FlattenMetrics implements Function<Metrics, List<Metric>> { + INSTANCE; + + @Nullable + @Override + public List<Metric> apply(Metrics input) { + return input.getMetrics(); + } + } +} diff --git a/sonar-core/src/test/java/org/sonar/core/metric/SensorMetricsTest.java b/sonar-core/src/test/java/org/sonar/core/metric/SensorMetricsTest.java new file mode 100644 index 00000000000..332e5eff7f8 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/metric/SensorMetricsTest.java @@ -0,0 +1,60 @@ +/* + * 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.core.metric; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import java.util.List; +import org.junit.Test; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.Metrics; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; + +public class SensorMetricsTest { + + static final SensorMetrics SENSOR_METRICS_WITHOUT_METRIC_PLUGIN = new SensorMetrics(new Metrics[]{}); + static final SensorMetrics SENSOR_METRICS_WITH_PLUGIN = new SensorMetrics(new Metrics[]{new FakeMetrics()}); + + @Test + public void check_number_of_allowed_core_metrics() throws Exception { + assertThat(SENSOR_METRICS_WITHOUT_METRIC_PLUGIN.getMetrics()).hasSize(53); + } + + @Test + public void check_metrics_from_plugin() throws Exception { + List<Metric> metrics = newArrayList(SENSOR_METRICS_WITH_PLUGIN.getMetrics()); + Iterables.removeAll(metrics, SENSOR_METRICS_WITHOUT_METRIC_PLUGIN.getMetrics()); + assertThat(metrics).hasSize(2); + } + + private static class FakeMetrics implements Metrics { + + @Override + public List<Metric> getMetrics() { + return ImmutableList.<Metric>of( + new Metric.Builder("key1", "name1", Metric.ValueType.INT).create(), + new Metric.Builder("key2", "name2", Metric.ValueType.FLOAT).create() + ); + } + } +} |