diff options
author | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2013-09-13 15:04:41 +0200 |
---|---|---|
committer | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2013-09-13 15:08:55 +0200 |
commit | 3af09034934f3f7b3611fdfed6dd217c73c033e9 (patch) | |
tree | 3a5512cfee6c317cc35efd685b43e6a7191dbe32 /plugins | |
parent | c12be67f1851bc099e6343845d432f7543d0c632 (diff) | |
download | sonarqube-3af09034934f3f7b3611fdfed6dd217c73c033e9.tar.gz sonarqube-3af09034934f3f7b3611fdfed6dd217c73c033e9.zip |
SONAR-766 Add exclusions for coverage
Introduce new API to filter measures before they are saved to context
Implement a measure filter for code coverage measures
Add configuration property for coverage exclusions
Diffstat (limited to 'plugins')
4 files changed, 176 insertions, 1 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index 4b32a973eb3..f72400dd0f7 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -20,7 +20,6 @@ package org.sonar.plugins.core; import org.sonar.api.resources.Qualifiers; - import org.sonar.api.config.PropertyDefinition; import com.google.common.collect.ImmutableList; import org.sonar.api.CoreProperties; @@ -65,6 +64,7 @@ import org.sonar.plugins.core.sensors.BranchCoverageDecorator; import org.sonar.plugins.core.sensors.CheckAlertThresholds; import org.sonar.plugins.core.sensors.CommentDensityDecorator; import org.sonar.plugins.core.sensors.CoverageDecorator; +import org.sonar.plugins.core.sensors.CoverageMeasurementFilter; import org.sonar.plugins.core.sensors.DirectoriesDecorator; import org.sonar.plugins.core.sensors.FilesDecorator; import org.sonar.plugins.core.sensors.GenerateAlertEvents; @@ -463,6 +463,7 @@ public final class CorePlugin extends SonarPlugin { OverallLineCoverageDecorator.class, OverallCoverageDecorator.class, OverallBranchCoverageDecorator.class, + CoverageMeasurementFilter.class, ApplyProjectRolesDecorator.class, CommentDensityDecorator.class, NoSonarFilter.class, @@ -486,6 +487,7 @@ public final class CorePlugin extends SonarPlugin { extensions.addAll(getPropertyDefinitions()); extensions.addAll(IgnoreIssuesPlugin.getExtensions()); + extensions.addAll(CoverageMeasurementFilter.getPropertyDefinitions()); return extensions.build(); } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java new file mode 100644 index 00000000000..99b60f96157 --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java @@ -0,0 +1,93 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.plugins.core.sensors; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import org.sonar.api.CoreProperties; +import org.sonar.api.PropertyType; +import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.config.Settings; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Resource; +import org.sonar.api.utils.WildcardPattern; +import org.sonar.core.measure.MeasurementFilter; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +public class CoverageMeasurementFilter implements MeasurementFilter { + + public static final String PROPERTY_COVERAGE_EXCLUSIONS = "sonar.coverage.exclusions"; + public static final String PROPERTY_COVERAGE_INCLUSIONS = "sonar.coverage.inclusions"; + + private Settings settings; + private CoverageDecorator decorator; + private Collection<WildcardPattern> resourcePatterns; + + public CoverageMeasurementFilter(Settings settings, CoverageDecorator decorator) { + this.settings = settings; + this.decorator = decorator; + + initPatterns(); + } + + @Override + public boolean accept(Resource<?> resource, Measure measure) { + if (this.decorator.usedMetrics().contains(measure.getMetric())) { + return !hasMatchingPattern(resource); + } else { + return true; + } + } + + private boolean hasMatchingPattern(Resource<?> resource) { + boolean found = false; + Iterator<WildcardPattern> iterator = resourcePatterns.iterator(); + while (!found && iterator.hasNext()) { + found = resource.matchFilePattern(iterator.next().toString()); + } + return found; + } + + @VisibleForTesting + void initPatterns() { + Builder<WildcardPattern> builder = ImmutableList.<WildcardPattern>builder(); + for (String pattern : settings.getStringArray(PROPERTY_COVERAGE_EXCLUSIONS)) { + builder.add(WildcardPattern.create(pattern)); + } + resourcePatterns = builder.build(); + } + + public static List<? extends PropertyDefinition> getPropertyDefinitions() { + return ImmutableList.of( + PropertyDefinition.builder("sonar.coverage.exclusions") + .category(CoreProperties.CATEGORY_EXCLUSIONS) + .subCategory(CoreProperties.CATEGORY_CODE_COVERAGE) // TODO Replace with dedicated subcat + .type(PropertyType.STRING) + .multiValues(true) + .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) + .build() + ); + } +} diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties index 616799b7a4b..07b52027cf7 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties @@ -825,6 +825,10 @@ property.category.exclusions.issues=Issues property.category.exclusions.issues.description=Configure which issues should not be reported. property.category.exclusions.duplications=Duplications property.category.exclusions.duplications.description=Configure files which should not be checked for duplicated code. +property.category.exclusions.codeCoverage=Code Coverage +property.category.exclusions.codeCoverage.description=Configure files which should be considered for code coverage. +property.sonar.coverage.exclusions.name=Coverage Exclusions +property.sonar.coverage.exclusions.description=Patterns used to exclude some files from coverage report. property.error.notBoolean=Valid options are "true" and "false" property.error.notInteger=Only digits are allowed property.error.notFloat=Not a floating point number diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java new file mode 100644 index 00000000000..fd4693e1702 --- /dev/null +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java @@ -0,0 +1,76 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.plugins.core.sensors; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.config.PropertyDefinitions; +import org.sonar.api.config.Settings; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.File; +import org.sonar.api.resources.Resource; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class CoverageMeasurementFilterTest { + + private Settings settings; + + private CoverageMeasurementFilter filter; + + @Before + public void createFilter() { + settings = new Settings(new PropertyDefinitions(CoverageMeasurementFilter.getPropertyDefinitions())); + filter = new CoverageMeasurementFilter(settings, new CoverageDecorator()); + } + + @Test + public void shouldNotFilterNonCoverageMetrics() { + Measure otherMeasure = mock(Measure.class); + when(otherMeasure.getMetric()).thenReturn(CoreMetrics.LINES); + assertThat(filter.accept(mock(Resource.class), otherMeasure)).isTrue(); + } + + @Test + public void shouldFilterFileBasedOnPattern() { + Resource<?> resource = new File("org/polop/File.php"); + Measure coverageMeasure = mock(Measure.class); + when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.LINES_TO_COVER); + + settings.setProperty(CoverageMeasurementFilter.PROPERTY_COVERAGE_EXCLUSIONS, "org/polop/*"); + filter.initPatterns(); + assertThat(filter.accept(resource, coverageMeasure)).isFalse(); + } + + @Test + public void shouldNotFilterFileBasedOnPattern() { + Resource<?> resource = new File("org/polop/File.php"); + Measure coverageMeasure = mock(Measure.class); + when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.LINES_TO_COVER); + + settings.setProperty(CoverageMeasurementFilter.PROPERTY_COVERAGE_EXCLUSIONS, "org/other/*"); + filter.initPatterns(); + assertThat(filter.accept(resource, coverageMeasure)).isTrue(); + } +} + |