Only plugin metrics and some defined core metrics are allowed to be read from the batchtags/5.2-RC1
@@ -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, |
@@ -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()); | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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(); | |||
} | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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); | |||
@@ -366,11 +371,26 @@ public class MeasureRepositoryImplTest { | |||
assertThat(underTest.getRawMeasure(OTHER_COMPONENT, metric1)).isAbsent(); | |||
} | |||
@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)); |
@@ -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); | |||
} | |||
} |
@@ -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); |
@@ -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(); | |||
} | |||
} | |||
} |
@@ -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() | |||
); | |||
} | |||
} | |||
} |